Reputation: 31
I am trying to convert 20 digit decimal value to hexadecimal using Delphi code. Although I find the code below in C#.
BigInteger bi = new BigInteger("12345678901234567890");
string s = bi.ToHexString();
Can anyone help with equivalent delphi code to achieve this objective?
Please note that using kstools code, I was able to convert 17 digit hexadecimal value to 20 digit decimal but I cannot reverse it to get back the hexadecimal value.
The kstool code is as follows:
var
I: TksInteger;
....
I.FromString('$ABDCF123456789FE');
Result = I.AsString;
Upvotes: 3
Views: 4398
Reputation: 11
The following Delphi function converts a decimal number and returns a right-justified hexadecimal number. It is not elegant, but it works.
//Uses STRUTILS Delphi module
function IHEX(x:Double): string; //Returns hex number as right-justified string
var i,k,a,mx:Integer;
y,Z,a1:currency;
s:string;
hxs: array[0..15] of string;
const hx='0123456789ABCDEF';
begin
Y:=abs(X); //Make sure target decimal is not a negative number
mx:=0; //Count number of hex digits derived from conversion
repeat
z:= y / 16; // Divide the decimal number by base 16
a:=Trunc(z); // Get integer part of dividend
if z>=16 then begin //If integer dividend greater than 16
a1:=16 * Frac(z);//Get the dividend carry-over
k:=Trunc(a1); // Base 16 left-to-right placement digit
If k<=9 then hxs[mx]:=IntToStr(k) //if hex digit greater than 9,
else
hxs[mx]:=hx[k+1]; //get hex alpha digit
mx:=mx+1; //increment hex digit placement
y:=a; //Replace decimal with current dividend result
end;
if z<16 then begin //When dividend less than 16,
a1:=16 * Frac(z); //get dividend carry-over
k:=Trunc(a1); //Base 16 left-to-right placement digit
If k<=9 then hxs[mx]:=IntToStr(k) //If hex digit greater than 9,
else
hxs[mx]:=hx[k+1]; //get hex alpha digit
mx:=mx+1; //increment hex digit placement
y:=a; //Replace decimal with current dividend result
end;
until y<16; //When loop ends, last hex digit derived from division
If a<=9 then hxs[mx]:=IntToStr(a) //If last hex digit greater than 9,
else
hxs[mx]:=hx[a+1]; //get hex alpha digit
//Pull HEX digits from placement array in reverse order to create HEX number
s:='';
i:=mx;
repeat
s:=s + hxs[i];
i:=i-1;
until i<0;
s:=s+'H';
//Format HEX number as seven characters RIGHT-JUSTIFIED
repeat
k:=Length(s);
if k<7 then s:='0'+s;
until Length(s)>=7;
Result:=s;
end;
Upvotes: 1
Reputation: 10937
The same as David Heffernan translation but optimized and compatible with older Delphi versions...
function DecimalToHex(const Dec: AnsiString): AnsiString;
var
ResultArray: array of byte;
n, i: Integer;
val, digit: Byte;
c: AnsiChar;
begin
SetLength(ResultArray, Trunc(Length(Dec) * Ln(10) / Ln(16)) + 1);
n := 0;
for c in Dec do
begin
Assert(CharInSet(c, ['0'..'9']));
val := ord(c) - ord('0');
for i := 0 to n do
begin
digit := ResultArray[i] * 10 + val;
ResultArray[i] := digit and $0F;
val := digit shr 4;
end;
if val <> 0 then
begin
inc(n);
ResultArray[n] := val;
end;
end;
Result := '';
for digit in ResultArray do
Result := AnsiString('0123456789ABCDEF')[digit + 1] + Result;
end;
Upvotes: 1
Reputation: 612884
Here's a Delphi translation of a C# answer to an identical question:
program DecToHex;
{$APPTYPE CONSOLE}
uses
SysUtils, Generics.Collections;
function DecimalToHex(const Dec: string): string;
var
bytes: Generics.Collections.TList<Byte>;
i, digit, val: Integer;
b: Byte;
c: Char;
begin
bytes := Generics.Collections.TList<Byte>.Create;
try
bytes.Add(0);
for c in Dec do
begin
Assert(CharInSet(c, ['0'..'9']));
val := ord(c)-ord('0');
for i := 0 to bytes.Count-1 do
begin
digit := bytes[i]*10 + val;
bytes[i] := digit and $0F;
val := digit shr 4;
end;
if (val<>0) then
bytes.Add(val);
end;
Result := '';
for b in bytes do
Result := '0123456789ABCDEF'[b+1] + Result;
finally
bytes.Free;
end;
end;
const
test = '56493153725735501823';
begin
WriteLn(test + ' = $' + DecimalToHex(test));
end.
Output:
56493153725735501823 = $30FFFFFFFFFFFFFFF
Upvotes: 7
Reputation: 24086
What's the problem exactly?
Using the example that you've given, it just works here.
Proof
This code converts 12345678901234567890 to a string, and then back to a number.
program Project122; {$APPTYPE CONSOLE}
uses SysUtils;
const SomeBigNumber=12345678901234567890;
var S:String; SomeBigNumber2:UInt64;
begin
WriteLn(SomeBigNumber);
S := '$'+IntToHex(SomeBigNumber, 40);
Writeln('As Hex: ',S);
Writeln;
Writeln('Now let''s convert it back...');
SomeBigNumber2 := StrToInt64(S);
Writeln(SomeBigNumber2);
ReadLn;
end.
output:
12345678901234567890 As Hex:
$AB54A98CEB1F0AD2
Now let's convert it back...
12345678901234567890
If you want to convert any 20-digit number, this won't work, because the largest ones don't fit in a UINT64.
18446744073709551615 is the largest number that you can fit in a UIN64.
12345678901234567890
Upvotes: 3