Convert a “big” Hex number (string format) to a de

2020-02-08 08:37发布

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)?

7条回答
何必那么认真
2楼-- · 2020-02-08 09:07

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();
查看更多
老娘就宠你
3楼-- · 2020-02-08 09:09

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);
}
查看更多
▲ chillily
4楼-- · 2020-02-08 09:09

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

查看更多
地球回转人心会变
5楼-- · 2020-02-08 09:10

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)
查看更多
爷、活的狠高调
6楼-- · 2020-02-08 09:14

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.

查看更多
7楼-- · 2020-02-08 09:17

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;
}
查看更多
登录 后发表回答