1

I need to convert a hexadecimal value to a decimal integer. Is there some unit that can do this?

On the web I have found something about it but it is not helping me much. I understood that using inline asm it is possible to represent it as a packed array of four 32 bit Integer. I have found as convert a int32 or int64 to int128 and viceversa, but not found nothing for take for example two int64 and to do a int128 and too i have found issue searching in asm inline something that emule div operator, mul operator and sum operator.

So I ask if someone can help me to solve this problem. My objective is to take a string in hexadecimal and convert it in decimal and after that calculate the equivalent value in base 35 (0..9, A..Z). Thanks very much.

Lieven Keersmaekers
  • 57,207
  • 13
  • 112
  • 146
Marcello Impastato
  • 2,263
  • 5
  • 30
  • 52
  • 1
    what data structure holds your 128 bit int? – David Heffernan Sep 10 '11 at 18:39
  • 1
    99% certainty that he means Base36. – Chris Thornton Sep 10 '11 at 19:43
  • (a) about data structure i found something as: type Int128 = packed array [0..3] of Int32. (b) For base 35 i mean number from 0 to 9 and letter from A to Z. in exadecimal for example we heve number from 0 to 9 and letter from A to F. In general i mean number x mod 35 and rest from 0 to 34 where 34 for example represent Z. (c) no, not base36, i mean base35 but too with base36 not change much; in mine case need work in base35. – Marcello Impastato Sep 10 '11 at 20:00
  • 1
    Maybe try a library that supports arbitrary sized integer maths, such as [link](http://code.google.com/p/fundamentals/downloads/detail?name=FundamentalsHugeInt415.zip&can=2&q=). – David Butler Sep 10 '11 at 20:10
  • 7
    0..9, a..z is 36 digits – David Heffernan Sep 10 '11 at 20:17
  • Hello, thanks for answer. I have looked about library that you have linked me, from code i check that it work only with 32 and 64 bits. Reading, about date (year 2001), i suppose that it was wrote when yet not was present 64bit integer. So not solved :( – Marcello Impastato Sep 10 '11 at 20:38
  • Then take one of the other ones http://www.efg2.com/Lab/Library/Delphi/MathFunctions/Cryptography.htm#MultiplePrecision – Marco van de Voort Sep 10 '11 at 20:42

1 Answers1

5

If you convert the hexadecimal string into an array of bytes (see SysUtils for that) you can use the follewing code to convert it into 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;

Then transform the base 35 bytes into characters:

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;

I don't think you need 128 bit math..

Good luck!

Ritsaert Hornstra
  • 5,013
  • 1
  • 33
  • 51