128-битная операция с Delphi - PullRequest
1 голос
/ 10 сентября 2011

Мне нужно преобразовать шестнадцатеричное значение в десятичное целое. Есть какой-то блок, который может это сделать?

В сети я нашел кое-что об этом, но это мне мало помогает. Я понял, что, используя inline asm, можно представить его как упакованный массив из четырех 32-битных Integer. Я нашел, как преобразовать int32 или int64 в int128 и наоборот, но не нашел ничего, чтобы взять, например, два int64 и сделать int128, и я также нашел проблему поиска в asm inline что-то, что emule div operator, mul оператор и sum оператор.

Поэтому я спрашиваю, может ли кто-нибудь помочь мне решить эту проблему. Моя цель - взять строку в шестнадцатеричной форме и преобразовать ее в десятичную, а после этого вычислить эквивалентное значение в base 35 (0..9, A..Z). Большое спасибо.

1 Ответ

5 голосов
/ 11 сентября 2011

Если вы преобразуете шестнадцатеричную строку в массив байтов (см. SysUtils для этого), вы можете использовать следующий код для преобразования его в base 35:

function EncodeBaseX( const Values: array of Byte; var Dest: array of Byte; Radix: Integer ): Boolean;
var
  i,j,Carry: Integer;
begin
  // We're unsuccesful up to now
  Result := False;

  // Check if we have an output buffer and clear it
  if Length( Dest ) = 0 then Exit;
  System.FillChar( Dest[ 0 ], Length( Dest ), 0 );

  // fill in the details
  for i := 0 to High( Values ) do begin
    Carry := Values[ i ];
    for j := 0 to High( Dest ) do begin
      Inc( Carry, Radix * Dest[ j ] );
      Dest[ j ] := Carry and $ff;
      Carry := Carry shr 8;
    end;
    if Carry <> 0 then Exit; // overflow
  end;

  // We're succesful
  Result := True;
end;

{Bytes: array of byte (0..255); Dest: array of Byte(0..Radix-1)}
function DecodeBaseX( const Bytes: array of Byte; var Dest: array of Byte; Radix: Integer ): Boolean;
var
  i,j,Carry: Integer;
  B: array of Byte;
begin
  // We're unsuccesful up to now
  Result := False;

  // Copy data
  if Length( Bytes ) = 0 then Exit;
  SetLength( B, Length( Bytes ) );
  System.Move( Bytes[ 0 ], B[ 0 ], Length( B ) );

  // fill in the details
  for i := High( Dest ) downto 0 do begin
    Carry := 0;
    for j := High( Bytes ) downto 0 do begin
      Carry := Carry shl 8 + B[ j ];
      B[ j ] := Carry div Radix; Carry := Carry mod Radix;
    end;
    Dest[ i ] := Carry;
  end;

  // Check if we collected all the bits
  Carry := 0;
  for i := 0 to High( B ) do Carry := Carry or B[ i ];

  // We're succesful if no bits stayed pending.
  Result := ( Carry = 0 );
end;

Затем преобразуйте базовые 35 байтов в символы:

function EncodeKeyToString( const Num128Bits: array of Byte ): Ansistring;
var
  Src:   array [0..15] of Byte; // your 128 bits
  Dest:  array [0..24] of Byte;
  i:     Integer;
const
  EncodeTable: AnsiString = '0123456789ABCDEFGHIJKLMNPQRSTUVWXYZ'; 
  // O is not present to make base 35. If you want a different code, be my guest.
begin
  // Convert to an array of 25 values between 0-35
  System.Move( Num128Bits[ 0 ], Src[ 0 ], Length( Src ) ); // Copy data in our private placeholder
  DecodeBaseX( Src, Dest, 35 );    

  // Convert to a representable string
  SetLength( Result, Length( Dest ) );
  for i := 0 to High( Dest ) do begin
    Assert( Dest[ i ] < Length( EncodeTable ) );
    Result[ i + 1 ] := EncodeTable[ 1 + Dest[ i ] ];
  end;
end;

Не думаю, что вам нужна 128-битная математика ..

Удачи!

...