Jest sobie Edit, do którego wpisuję dziesiętnie liczbę w zakresie 0..2^128-1 (128 bitową).
Jak przekonwertować tak dużą liczbę do postaci binarnej, tzn. zapisać w 16-bajtowym buforze?
Jak zrobić konwersję odwrotną?
Jest sobie Edit, do którego wpisuję dziesiętnie liczbę w zakresie 0..2^128-1 (128 bitową).
Jak przekonwertować tak dużą liczbę do postaci binarnej, tzn. zapisać w 16-bajtowym buforze?
Jak zrobić konwersję odwrotną?
Wykorzystaj np. GMP (powinno się udać bez problemu dokonać konwersji z x10 do x2).
Dzięki! Wykorzystałem tą bibliotekę GMP, oczywiście wspomagając się wrapperem dla Delphi (https://code.google.com/archive/p/gmp-wrapper-for-delphi/downloads).
uses gmp_lib, gmp_obj;
var
s: AnsiString;
i: mpz_t;
buf: array [0..15] of byte;
count: mp_size_t;
begin
//s:='340282366920938463463374607431760000000';
s := '4584946418820579326'; //łańcuch do konwersji (niezbyt długi, żeby można było zweryfikować wynik w kalkulatorze)
mpz_init_set_str(i, PAnsiChar(s), 10); //konwersja stringa do typu mpz_t
mpz_export(@buf, @count, -1, 1, 0, 0, i); //konwersja (little endian) typu mpz_t do bufora "buf" (istotne tylko początkowych "count" bajtów!)
if count < 16 then
FillChar(buf[count], 16 - count, 0); //wyzerowanie nieistotnych bajtów
end;
I jeszcze uzupełniam o konwersję odwrotną z bufora (128b) do stringa, tak więc po ubraniu w procedurę i funkcję wygląda to tak (dla potomnych):
uses gmp_lib, gmp_obj;
type
TBuf128Bit = array [0..15] of Byte; //bufor 128-bitowy
procedure StringToBuf128Bit(s: AnsiString; var buf: TBuf128Bit); //konwersja liczby dziesiętnej w stringu do bufora 128-bitowego (little endian)
var
i: mpz_t;
count: mp_size_t;
begin
mpz_init_set_str(i, PAnsiChar(s), 10); //konwersja liczby dziesiętnej w stringu do zmiennej "i" typu "mpz_t"
mpz_export(@buf, @count, -1, 1, 0, 0, i); //konwersja (little endian) zmiennej "i" typu "mpz_t" do bufora "buf" (istotne tylko początkowych "count" bajtów!)
if count < 16 then
FillChar(buf[count], 16 - count, 0); //!!! wyzerowanie nieistotnych bajtów
mpz_clear(i); //zwolnienie "i"
end;
function Buf128BitToString(buf: TBuf128Bit): AnsiString; //konwersja bufora 128-bitowego (little endian) do liczby w stringu (zapis dziesiętny)
Var
i: mpz_t;
begin
mpz_init(i); //inicjalizacja zmiennej
mpz_import(i, 16, -1, 1, 0, 0, @buf); //konwersja bufora "buf" (little endian) do zmiennej "i" typu "mpz_t"
result := mpz_get_str(nil, 10, i); //konwersja zmiennej "i" typu "mpz_t" do liczby w stringu (zapis dziesiętny)
mpz_clear(i); //zwolnienie "i"
end;
procedure TForm1.Button1Click(Sender: TObject); //test konwersji w obie strony
Var
buf: TBuf128Bit;
s_in, s_out: AnsiString;
begin
//s_in:= '340282366920938463463374607431768211455'; //max na 128 bitach (2^128-1)
s_in := '4584946418820579326';
StringToBuf128Bit(s_in, buf);
s_out := Buf128BitToString(buf);
ShowMessage(String(s_out)); //s_out = s_in
end;
Dodam jeszcze, że można też sprawdzić, czy konwertowany łańcuch nie przekracza maksymalnej wartości 2^128-1, czyli po zamianie procedury "StringToBuf128Bit" na funkcję:
function TryStringToBuf128Bit(s: AnsiString; var buf: TBuf128Bit): boolean; //konwersja liczby dziesiętnej w stringu do bufora 128-bitowego (little endian)
var
i: mpz_t;
count: mp_size_t;
begin
mpz_init_set_str(i, PAnsiChar(s), 10); //konwersja liczby dziesiętnej w stringu do zmiennej "i" typu "mpz_t"
mpz_export(@buf, @count, -1, 1, 0, 0, i); //konwersja (little endian) zmiennej "i" typu "mpz_t" do bufora "buf" (istotne tylko początkowych "count" bajtów!)
if count <= 16 then //jeśli ilość bajtów potrzebna do zapisu binarnego liczby nie jest większa od 16 (liczba w zakresie 128-bitów)
begin
if count < 16 then
FillChar(buf[count], 16 - count, 0); //!!! wyzerowanie nieistotnych bajtów
result := true; //liczba w stringu w zakresie do 128-bitów (2^128-1)
end
else
result := false; //liczba w stringu ponad zakres 128-bitów
mpz_clear(i); //zwolnienie "i"
end;
są jeszcze takie biblioteki:
TBigNum https://sourceforge.net/projects/bigint/?source=directory
oraz http://www.delphiforfun.org/Programs/Library/big_integers.htm