【问题标题】:Java always give me wrong result with huge numbers [duplicate]Java总是给我巨大的数字错误的结果[重复]
【发布时间】:2017-09-20 13:23:55
【问题描述】:

我写了这行代码:

System.out.println(Math.pow(7, 23) % 143);   // 7^23 mod 143

我预计输出为2,但输出为93.0。有人知道我在做什么错吗?

【问题讨论】:

标签: java numbers


【解决方案1】:

数字“溢出”double,这是 Math.pow() 期望和返回的。请改用BigInteger

BigInteger.valueOf(7)
        .pow(23)
        .mod(BigInteger.valueOf(143))

或者像@Felk 所建议的那样一步一步:

BigInteger.valueOf(7)
        .modPow(BigInteger.valueOf(23), BigInteger.valueOf(143))

【讨论】:

  • BigInteger 甚至可以让modPow() 一步完成这项工作
  • @Felk 编辑了答案,谢谢!
  • 您的回答中有一个不正确的说法:“数字溢出双倍”。在 2.7e19 左右,它在 double 范围内,但无法以必要的精度表示。所以 BigInteger 解决方案是最直接的方法。
  • @RalfKleberhoff 是的,你是对的。我只是把它放在引号里,因为安迪·特纳已经把它钉牢了。谢谢!
【解决方案2】:

Math.pow的结果是double,有64位;其中 53 个是尾数位。这意味着任何大于2^53-1 = 9007199254740991 的整数都不能精确地表示为双精度数。

7^23 比 2^53-1 大(实际上只是比 2^64 大一点),所以不能精确表示。因此,% 的结果不是您所期望的。

改用BigInteger,正如@Costi 已经建议的那样。

【讨论】:

    【解决方案3】:

    如果中间求幂结果太大而无法保存在变量中,请使用 Modular exponentiation algorithm

    System.out.println(powMod(7, 23, 143)); // = 2
    
    // Example from Wikipedia with minor changes
    private static int powMod(int base, int exponent, int modulus) {
        if (modulus == 1)
            return 0;
    
        base %= modulus;
        int result = 1;
        while (exponent > 0) {
            if ((exponent & 1) == 1)
                result = (result * base) % modulus;
            exponent >>= 1;
            base = (base * base) % modulus;
        }
        return result;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-19
      • 1970-01-01
      • 2015-05-27
      • 1970-01-01
      • 2019-03-24
      相关资源
      最近更新 更多