[ad_1]
Asked
Viewed
7k times
How to convert a “big” Hex number (in string format):
EC851A69B8ACD843164E10CFF70CF9E86DC2FEE3CF6F374B43C854E3342A2F1AC3E30C741CC41E679DF6D07CE6FA3A66083EC9B8C8BF3AF05D8BDBB0AA6CB3EF8C5BAA2A5E531BA9E28592F99E0FE4F95169A6C63F635D0197E325C5EC76219B907E4EBDCD401FB1986E4E3CA661FF73E7E2B8FD9988E753B7042B2BBCA76679
to a decimal number (in string format):
166089946137986168535368849184301740204613753693156360462575217560130904921953976324839782808018277000296027060873747803291797869684516494894741699267674246881622658654267131250470956587908385447044319923040838072975636163137212887824248575510341104029461758594855159174329892125993844566497176102668262139513
without using BigInteger
Class (as my application should support machines without .NET Framework 4)?
13
Here’s a quick-and-dirty implementation that can work with arbitrarily-large numbers. The aim of this implementation is simplicity, not performance; thus, it should be optimized drastically if it’s to be used in a production scenario.
Edit: Simplified further per Dan Byström’s implementation of the inverse decimal-to-hex conversion:
static string HexToDecimal(string hex)
{
List<int> dec = new List<int> { 0 }; // decimal result
foreach (char c in hex)
{
int carry = Convert.ToInt32(c.ToString(), 16);
// initially holds decimal value of current hex digit;
// subsequently holds carry-over for multiplication
for (int i = 0; i < dec.Count; ++i)
{
int val = dec[i] * 16 + carry;
dec[i] = val % 10;
carry = val / 10;
}
while (carry > 0)
{
dec.Add(carry % 10);
carry /= 10;
}
}
var chars = dec.Select(d => (char)('0' + d));
var cArr = chars.Reverse().ToArray();
return new string(cArr);
}
7
I just translated Douglas’ code into VBA
Function HexToDecimal(ByVal sHex As String) As String
Dim dec() As Long
ReDim dec(0 To 0) As Long
Dim lCharLoop As Long
For lCharLoop = 1 To Len(sHex)
Dim char As String * 1
char = Mid$(sHex, lCharLoop, 1)
Dim carry As Long
carry = Val("&h" & char)
Dim i As Long
For i = 0 To UBound(dec)
Dim lVal As Long
lVal = dec(i) * 16 + carry
dec(i) = lVal Mod 10
carry = lVal \ 10
Next i
While (carry > 0)
ReDim Preserve dec(0 To UBound(dec) + 1) As Long
dec(UBound(dec)) = carry Mod 10
carry = carry \ 10
Wend
Next
For lCharLoop = UBound(dec) To LBound(dec) Step -1
Dim sDecimal As String
sDecimal = sDecimal & Chr$(48 + dec(lCharLoop))
Next
HexToDecimal = sDecimal
End Function
Private Sub TestHexToDecimal()
Debug.Assert HexToDecimal("F") = "15"
Debug.Assert HexToDecimal("4") = CStr(Val("&H4"))
Debug.Assert HexToDecimal("10") = CStr(Val("&H10"))
Debug.Assert HexToDecimal("20") = CStr(Val("&H20"))
Debug.Assert HexToDecimal("30") = CStr(Val("&H30"))
Debug.Assert HexToDecimal("40") = CStr(Val("&H40"))
Debug.Assert HexToDecimal("44") = CStr(Val("&H44"))
Debug.Assert HexToDecimal("FF") = "255"
Debug.Assert HexToDecimal("FFF") = "4095"
Debug.Assert HexToDecimal("443") = CStr(Val("&H443"))
Debug.Assert HexToDecimal("443C1") = "279489"
Debug.Assert HexToDecimal("443C1CE20DFD592FB374D829B894BBE5") = "90699627342249584016268008583970733029"
Debug.Assert HexToDecimal("EC851A69B8ACD843164E10CFF70CF9E86DC2FEE3CF6F374B43C854E3342A2F1AC3E30" & _
"C741CC41E679DF6D07CE6FA3A66083EC9B8C8BF3AF05D8BDBB0AA6CB3EF8C5BAA2A5" & _
"E531BA9E28592F99E0FE4F95169A6C63F635D0197E325C5EC76219B907E4EBDCD401FB1" & _
"986E4E3CA661FF73E7E2B8FD9988E753B7042B2BBCA76679") = _
"1660899461379861685353688491843017402046137536931563604625752175601309049219" & _
"5397632483978280801827700029602706087374780329179786968451649489474169926767" & _
"4246881622658654267131250470956587908385447044319923040838072975636163137212" & _
"8878242485755103411040294617585948551591743298921259938445664971761026682621" & _
"39513"
End Sub
Also a benchmark at statman.info Hexadecimal Conversion for large numbers
You can use the IntX library as it should work with .Net 2.0 and up. From the description on the page in regards to BigInteger
:
So internally System.Numerics.BigInteger seems to use standard
arbitrary arithmetic algorithms and I am not worrying about IntX
library since, due to its use of FHT, it can be times faster for
really big integers.
The license is pretty liberal but worth reading first just to make sure it’s okay.
I’ve not used this library but from a cursory glance at the source code this should be all you need to do
string dec = new IntX(myHex, 16).ToString();
If you don’t want to compile the code yourself, you can install it via Nuget.
An easy way would be to use a big number library that supports your version of .NET. I’d recommend GnuMpDotNet, which uses the excellent GMP library. By default it targets .NET 3.5, but you can change that to .NET 2.0 without breaking anything (just remove the references and using
statement that refer to new things), as it doesn’t use anything from .NET 3.5. Here is an example using GnuMpDotNet:
BigInt e = new BigInt(hexString, 16);
string decimalStr = e.ToString();
0
Look at my answer here: https://stackoverflow.com/a/18231860/2521214
worth looking
- string based conversions (limited by free memory only)
- dec->hex and hex<-dec included
- no bigint/bigreal lib used
- supporting fixed point string formats (no exponents)
I just translated Douglas code to PHP:
function BigNumberHexToDecimal($hex)
{
$dec = array(0);
$hexLen = strlen($hex);
for($h=0;$h<$hexLen;++$h)
{
$carry = hexdec($hex[$h]);
for ($i = 0; $i < count($dec); ++$i)
{
$val = $dec[$i] * 16 + $carry;
$dec[$i] = $val % 10;
$carry = (int)($val / 10);
}
while ($carry > 0)
{
$dec[] = $carry % 10;
$carry = (int)($carry / 10);
}
}
return join("", array_reverse($dec));
}
I just translated Douglas code to JAVA:
public static String HexToDec(String hex) {
List<Integer> dec = new ArrayList<Integer>();
for (int k = 0; k < hex.length(); k++) {
String c = hex.charAt(k) + "";
int carry = Integer.parseInt(c, 16);
for (int i = 0; i < dec.size(); ++i) {
int val = dec.get(i) * 16 + carry;
dec.set(i, val % 10);
carry = val / 10;
}
while (carry > 0) {
dec.add(carry % 10);
carry /= 10;
}
}
int[] out = new int[dec.size()];
for (int i = 0; i < dec.size(); i++) {
out[i] = dec.get(i).intValue();
}
return arrayToDecString(reverseArray(out));
}
public static String arrayToDecString(int[] data) {
String str = "";
for (int i = 0; i < data.length; i++) {
str += data[i] + "";
}
return str;
}
public static int[] reverseArray(int[] data) {
for (int i = 0; i < data.length / 2; i++) {
int temp = data[i];
data[i] = data[data.length - i - 1];
data[data.length - i - 1] = temp;
}
return data;
}
I just translated Douglas code to Delphi/Pascal:
function HexToDecimal(const Hex: string): string;
var
dec: TList;
I: Integer;
carry: Cardinal;
c: Char;
val: Integer;
begin
Result := '';
dec := TList.Create;
try
dec.Add(Pointer(0)); // decimal result
for c in Hex do begin
carry := StrToInt('$' + c); // initially holds decimal value of current hex digit;
// subsequently holds carry-over for multiplication
for I := 0 to dec.Count -1 do begin
val := Integer(dec[I]) * 16 + carry;
dec[I] := Pointer(Integer(val mod 10));
carry := val div 10;
end;
while carry > 0 do begin
dec.Add(Pointer(Integer(carry mod 10)));
carry := carry div 10;
end;
end;
for I := 0 to dec.Count -1 do begin
val := Integer(dec[I]);
Result := IntToStr(val) + Result;
end;
finally
dec.Free;
end;
end;
procedure Test;
var
S: string;
begin
S := HexToDecimal('FF'); // 255
S := HexToDecimal('FFF'); // 4095
S := HexToDecimal('443C1'); // 279489
S := HexToDecimal('443C1CE20DFD592FB374D829B894BBE5'); // "90699627342249584016268008583970733029"
S := 'EC851A69B8ACD843164E10CFF70CF9E86DC2FEE3CF6F374B43C854E3342A2F1AC3E30' +
'C741CC41E679DF6D07CE6FA3A66083EC9B8C8BF3AF05D8BDBB0AA6CB3EF8C5BAA2A5' +
'E531BA9E28592F99E0FE4F95169A6C63F635D0197E325C5EC76219B907E4EBDCD401FB1' +
'986E4E3CA661FF73E7E2B8FD9988E753B7042B2BBCA76679';
S := HexToDecimal(S); // "166089946137986168535368849184301740204613753693156360462575217560130904921953976324839782808018277000296027060873747803291797869684516494894741699267674246881622658654267131250470956587908385447044319923040838072975636163137212887824248575510341104029461758594855159174329892125993844566497176102668262139513"
end;
Translated Douglas code to Qt:
QByteArray convertHexToDecimal(const QByteArray &hex)
{
QList<int> dec;
for (int i = 0; i < hex.count(); i++) {
int carry = hex.mid(i, 1).toInt(nullptr, 16);
for (int j = 0; j < dec.count(); ++j) {
int val = dec[j] * 16 + carry;
dec[j] = val % 10;
carry = val / 10;
}
while (carry > 0) {
dec.append(carry % 10);
carry /= 10;
}
}
QByteArray chars;
foreach (int d, dec) {
chars.prepend((char)('0' + d));
}
return chars;
}
lang-cs
[ad_2]