繁体   English   中英

将“大”十六进制数(字符串格式)转换为不带 BigInteger 的十进制数(字符串格式) Class

[英]Convert a "big" Hex number (string format) to a decimal number (string format) without BigInteger Class

如何转换“大”十六进制数(字符串格式):

EC851A69B8ACD843164E10CFF70CF9E86DC2FEE3CF6F374B43C854E3342A2F1AC3E30C741CC41E679DF6D07CE6FA3A66083EC9B8C8BF3AF05D8BDBB0AA6CB3EF8C5BAA2A5E531BA9E28592F99E0FE4F95169A6C63F635D0197E325C5EC76219B907E4EBDCD401FB1986E4E3CA661FF73E7E2B8FD9988E753B7042B2BBCA76679

到十进制数(字符串格式):

166089946137986168535368849184301740204613753693156360462575217560130904921953976324839782808018277000296027060873747803291797869684516494894741699267674246881622658654267131250470956587908385447044319923040838072975636163137212887824248575510341104029461758594855159174329892125993844566497176102668262139513

不使用BigInteger Class(因为我的应用程序应该支持没有 .NET Framework 4 的机器)?

这是一个快速而肮脏的实现,可以处理任意大的数字。 这种实现的目的是简单,而不是性能; 因此,如果要在生产场景中使用它,应该大大优化它。

编辑 :根据DanByström实施的反十进制到十六进制转换进一步简化:

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);
}

我刚刚将道格拉斯的代码翻译成了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

也是statman.info十六进制转换的基准

一种简单的方法是使用支持您的.NET版本的大数据库。 我推荐GnuMpDotNet ,它使用优秀的GMP库 默认情况下,它以.NET 3.5为目标,但您可以将其更改为.NET 2.0而不会破坏任何内容(只需删除引用和using引用新内容的语句),因为它不使用.NET 3.5中的任何内容。 以下是使用GnuMpDotNet的示例:

BigInt e = new BigInt(hexString, 16);
string decimalStr = e.ToString();

您可以使用IntX库,因为它应该与.Net 2.0及更高版本一起使用。 从关于BigInteger的页面描述:

所以内部System.Numerics.BigInteger似乎使用标准的任意算术算法,我不担心IntX库,因为由于它使用FHT,它对于真正的大整数来说可能快一些。

许可证非常自由,但值得一读,只是为了确保它没问题。

我没有使用过这个库,但是粗略地看一下源代码,这应该就是你需要做的

string dec = new IntX(myHex, 16).ToString();

如果您不想自己编译代码,可以通过Nuget安装它。

请看我的答案: https//stackoverflow.com/a/18231860/2521214

值得一看

  • 基于字符串的转换(仅限可用内存)
  • dec-> hex和hex <-dec包括在内
  • 没有使用bigint / bigreal lib
  • 支持定点字符串格式(无指数)

我刚刚将道格拉斯代码翻译成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));
}

我刚刚将道格拉斯代码翻译成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;
}

我刚刚将 Douglas 代码翻译成 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;

将道格拉斯代码翻译成 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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM