Mnożenie dwóch ogromnych liczb daje wynik ujemny – potrzebuję innego rozwiązania

0

Potrzebuję kodu, który obsłużył by jeszcze większą liczbę niż jest w stanie przechować boost/multiprecision/cpp_int. Czy jest na to jakiś sposób? Wymnożenie dwóch ogromnych liczb daje mi wynik ujemny.

#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
#include "boost/mpl/modulus.hpp"
using namespace std;
namespace mp = boost::multiprecision;

int main(int argc, char** argv) {
	
	mp::cpp_int euler = 26194632753873340482602470600187899982402756268656161642115088222204269931601629690910523738797032987144744428087470047611436579725572063118045346350639 * 2894666295091607599607776089080441405972487981119197947170667488057939157985640323643757150025183870400839347786750350201269178064721047552528631553695706;
	
	cout << euler;
		return 0;
}
-5414206902746483450
--------------------------------
Process exited after 0.06991 seconds with return value 0
Press any key to continue . . .


2

Nie używasz do mnożenia Boost.Multiprecision w tym przykładzie. Mnożysz inty. Zdecydowanie poza ich zakresem.

#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
#include "boost/mpl/modulus.hpp"
using namespace std;

using big_int = boost::multiprecision::cpp_int;

int main(int argc, char** argv)
{

    big_int a{ "2619463275387334048260247060018789998240275626865616164211508822"
               "2204269931601629690910523738797032987144744428087470047611436579"
               "725572063118045346350639" };

    big_int b{ "2894666295091607599607776089080441405972487981119197947170667488"
               "0579391579856403236437571500251838704008393477867503502012691780"
               "64721047552528631553695706" };

    auto euler = a * b;

    cout << euler;
    return 0;
}

https://wandbox.org/permlink/0nAuI9Rn6JCCITV0

0

Chyba też nie do końca. Mały ten wynik coś wychodzi, jakby zakres cpp_int się przekręcał.

int main(int argc, char** argv) {
	
	mp::cpp_int p = 26194632753873340482602470600187899982402756268656161642115088222204269931601629690910523738797032987144744428087470047611436579725572063118045346350639;
	mp::cpp_int q = 2894666295091607599607776089080441405972487981119197947170667488057939157985640323643757150025183870400839347786750350201269178064721047552528631553695706;
	mp::cpp_int euler = p * q;
	
	cout << euler;
		return 0;
}
21076087456280930068618841074290652422
--------------------------------
Process exited after 0.03726 seconds with return value 0
Press any key to continue . . .
2

Może dlatego, że znów używasz wbudowanych typów liczbowych, zamiast inicjalizować stringami? Przecież dostałeś przykład...

1

Swoją drogą dziwne, że ci się to zbudowało. Kompilator powinien krzyczeć, że nie może poprawnie zinterpretować tych literałów.
Przykładowo clang generuje błąd:

prog.cc:9:25: error: integer literal is too large to be represented in any integer type
    mp::cpp_int euler = 26194632753873340482602470600187899982402756268656161642115088222204269931601629690910523738797032987144744428087470047611436579725572063118045346350639 * 2894666295091607599607776089080441405972487981119197947170667488057939157985640323643757150025183870400839347786750350201269178064721047552528631553695706;
                        ^

gcc tylko warning:

prog.cc:9:25: warning: integer constant is too large for its type
     mp::cpp_int euler = 26194632753873340482602470600187899982402756268656161642115088222204269931601629690910523738797032987144744428087470047611436579725572063118045346350639 * 2894666295091607599607776089080441405972487981119197947170667488057939157985640323643757150025183870400839347786750350201269178064721047552528631553695706;
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Dodaj do kompilatora flagę -Wall.

0

Jeszcze lepiej jak nie będziesz wprowadzał tych liczb bezpośrednio do kodu. Po co kombinować jak można zrobić tak:

int main(int, char**) {

    mp::cpp_int a, b, c;

    while (cin >> a >> b) {
        c = a * b;
        cout << c << '\n';
    }
    return 0;
}

https://wandbox.org/permlink/FNaYIxC2PfQ3Bkis

0

Spoko, dzięki :) Nie używałem inicjalizacji stringami, bo mi kompilator coś krzyczy, że nie wie co to big_int. Wygląda na to, że to problem kompilatora. Ale dzięki ;)

7	7	66	[Error] expected nested-name-specifier before 'big_int'
66	In function 'int main(int, char**)':
12	5	66	[Error] 'big_int' was not declared in this scope
0

big_int to mp::cpp_int w twoim kodzie, użyłem innego aliasu tylko.

0
MarekR22 napisał(a):

Jeszcze lepiej jak nie będziesz wprowadzał tych liczb bezpośrednio do kodu. Po co kombinować jak można zrobić tak:

int main(int, char**) {

    mp::cpp_int a, b, c;

    while (cin >> a >> b) {
        c = a * b;
        cout << c << '\n';
    }
    return 0;
}

https://wandbox.org/permlink/FNaYIxC2PfQ3Bkis

Bo tak na serio korzystam z winapi i mi się program wiesza. Szukam problemu.

//Przeliczanie HEX na DEC
	DWORD len = GetWindowTextLength( Hex1 );
	if(len > 0)
	{
		LPSTR Bufor =( LPSTR ) GlobalAlloc( GPTR, len + 1 );
		GetWindowText( Hex1, Bufor, len + 1 );
	
		mp::cpp_int tmp = convertHexToDec(Bufor);
		std::ostringstream * ptr = new std::ostringstream;
		 *ptr << tmp;
		SetWindowText(Dec1, ptr->str().c_str());
		mp::cpp_int dec1 = tmp;
	
		GlobalFree( Bufor );
		clearString(ptr);
		len = GetWindowTextLength( Hex2 );
		Bufor =( LPSTR ) GlobalAlloc( GPTR, len + 1 );
		GetWindowText( Hex2, Bufor, len + 1 );
		
		
		
		if(len > 0)
		{
			
			tmp = convertHexToDec(Bufor);
			*ptr << tmp;
			SetWindowText(Dec2, ptr->str().c_str());
			mp::cpp_int dec2 = tmp;	
			
			GlobalFree( Bufor );
			clearString(ptr);
			len = GetWindowTextLength( ExInHex );						
			
			if(len > 0)
			{
		
				Bufor =( LPSTR ) GlobalAlloc( GPTR, len + 1 );
				GetWindowText( ExInHex, Bufor, len + 1 );
				tmp = convertHexToDec(Bufor);
				*ptr << tmp;
				SetWindowText(ExInDec, ptr->str().c_str());
				mp::cpp_int e = tmp;											
					
			//Liczenie n
				mp::cpp_int n = dec1 * dec2;
				
				clearString(ptr);
				*ptr << n;
				SetWindowText(rRSAN, ptr->str().c_str());
1

new std::ostringstream; na litość boską po co? Żeby sobie zapewnić wyciek pamięci?
Nie pisz takich wielkich kolosów.
Izoluj sobie różne części kodu np: UI od logiki programu.
W tym czymś za dużo się dzieje na raz, więc ciężko się czyta.

0

Jak ci się wiesza program, to w IDE, kliknij pauzę (nie wiem jak się to nazywa w Visual Studio, program ma się zatrzymać do debugowania w bieżącym miejscu).
Odszukaj okienko o nazwie "Call Stack" i przeanalizuj fragmenty kodu, które wskażą ci pozycje w "Call Stack". Jeśli robisz wiele wątków, to dla każdego powinieneś sprawdzić "Call stack" (w VS jest to zrobione beznadziejnie).

0

Już się nie wiesza ;) znalazłem błąd.

1 użytkowników online, w tym zalogowanych: 0, gości: 1