【问题标题】:Java number precision in JavascriptJavascript 中的 Java 数字精度
【发布时间】:2017-05-18 16:00:45
【问题描述】:

我在 Java 中有以下代码将十六进制值转换为长数字,在示例中我使用了值:'B4EEB49B04C0'

public static long HexStr2Long(String value)
{
    value = value.toUpperCase();
    long result = 0;
    for (int i = 0; i < value.length(); i++)
    {
        int x = value.length() - i - 1;
        char ch = value.charAt(i);
        result += keys.indexOf(ch) * Pow(exponent, x);
    }
    return result;
}

public static long Pow(long baseNo, long x)
{
    long value = 1;
    while (x > 0)
    {
        value = value * baseNo;
        x--;
    }
    return value;
}

public static void main(String[] args) {
    long result = HexStr2Long("B4EEB49B04C0");
    System.out.print("resultado: "+result+"\n");
}

结果是:1463925582232863984

现在,我在 Javascript 中创建了等效代码:

pow = function(baseNo, x){
  var value = 1;
  while(x > 0){
    value = value * baseNo;
    x--;
  }

  return value;
}

hexStr2Long = function(val){
 var keys = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 var exponent = keys.length;

 val = val.toUpperCase();
 var result = 0;
 for (var i = 0; i < val.length; i++) {
    var x = val.length - i - 1;
    var ch = val.charAt(i);
    result +=  keys.indexOf(ch) * Math.pow(exponent, x);
 }

 return result;
}
var r = hexStr2Long(wifimac);
console.log('Result: '+r);

结果是:1463925582232864000,这个错了,必须和Java代码一样。

我怎样才能做到这一点?我已经尝试使用该库 (BigNumber) 但没有成功。

【问题讨论】:

  • 这不会解决你的问题,但你没有调用你定义的 pow 函数,而是调用 Math.pow
  • 是的,我知道。结果还是一样的。
  • @Andreas 我在下面的(错误)答案中遇到了同样的错误。如果您将十六进制数解释为 IEEE-754 FP 数,则它会准确生成 1463925582232863984。

标签: javascript java node.js math numbers


【解决方案1】:

1463925582232864000 是最接近 1463925582232863984 的 64 位 IEEE-754 浮点数。Javascript 中的数字(目前 - 我相信这正在发生变化)始终是 64 位 IEEE-754 浮点数。

基本上,为了做到这一点,您需要一个支持数字类型其他的 Javascript 库,而不是内置的。(我希望 BigNumber 可以工作,但您没有向我们展示你用它做了什么,所以很难知道你做错了什么。)

【讨论】:

    【解决方案2】:

    以下是有关原因的一些信息: https://modernweb.com/what-every-javascript-developer-should-know-about-floating-points/

    问题在于 Javascript 的浮点精度。

    您总是可以尝试其他库,例如 Math.js

    【讨论】:

    • 当然,您必须配置 math.js 以使用 BigNumbers 或 Fractions,默认情况下它仍然使用常规 JS 数字。
    【解决方案3】:

    经过一些实验,我看到 0xB4EEB49B04C0 是 IEEE-754 FP 十六进制表示。所以这个答案根本不合适。

    1463925582232863984 是输入的正确十进制表示!

    因此,您应该使用支持 IEEE-754 输入的 bignumber 库。

    忽略旧答案

    使用 BigNumber 按预期工作:

    var r2 = new BigNumber("B4EEB49B04C0", 16);
    console.log(r2.toString());
    

    它输出 198937325274304。在线大数转换器也给出了这个结果。 这让我怀疑你的 Java 代码的输出也是错误的。你能验证“1463925582232863984”是正确的结果吗?

    输入是一个 48 位数字,因此它不能大于支持的最大 64 位数字。您发布的结果应等于“1450e88f9298c4f0”作为输入。

    【讨论】:

    • 感谢您的回答,弗兰克。结果“1463925582232863984”是正确的。 Java 代码来自 GPS 公司,他们给了我将 Mac 地址转换为数字的代码,因为我使用的是 NodeJS,所以我想在 Javascript 中转换 Java 代码。
    • 支持的最大整数为 9007199254740991,这显然小于您的结果值。但是您的输入适合 48 位,因此结果不能大于 MAX_INT imo。
    • @FrankSchmid:不,支持的整数值比这大得多。 9007199254740991 (Number.MAX_SAFE_INTEGER) 只是您可以加 1 并获得下一个连续整数的最大整数。
    猜你喜欢
    • 1970-01-01
    • 2023-03-04
    • 2011-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-12
    相关资源
    最近更新 更多