我必须为我大学的一个项目计算11^16.不知何故,Math.pow(11,16)计算出的解比WolframAlpha或我的其他计算方法精确1.

Result from WolframAlpha

我的代码是:

public class Test {
    public static void main(String args[]) {
        long a = 11;
        long b = 16;
        System.out.println("" + (long)Math.pow(a, b));
        System.out.println("" + squareAndMultiply(a, b));
    }

    public static long squareAndMultiply(long b, long e){
        long result = 1;
        long sq = b;
        while(e>0){
            if(e%2==1){
                result *= sq;
            }
            sq = sq * sq;
            e /= 2;
        }
        return result;
    }
}

代码的结果是:

数学pow(11,16):

45949729863572160

平方和倍数(11,16):

45949729863572161

推荐答案

使用浮点运算,您将处于一个灰色区域,其中double的精度小于long(即使doublerange要大得多).

double具有53位精度,而long可以将所有64位用于精度.当您处理高达11的值时,一个double的值与下一个double以上的值之间的差异变得很明显.

Java有一个built-in method Math.ulp("最后一位的单位"),它有效地给出了连续可表示值之间的值差.(有double版和float版.)

System.out.println(Math.ulp(Math.pow(11, 16)));

8.0

这意味着大于45949729863572160的最小可能double值是45949729863572168.

长值45949729863572161是正确的,但鉴于其有限(但仍然很大)的精度,使用Math.pow45949729863572160得到的值与double得到的真实答案非常接近.

将结果转换为long没有任何区别,因为Math.pow已经将结果计算为double,所以答案已经被1关闭.您的long计算值的方法是正确的.

如果计算的值会溢出long,那么可以使用BigDecimal, which has its own pow method来保持1.0的精度,而不是使用double.

Java相关问答推荐

如果给定层次 struct 级别,如何从其预序穿越构造n元树

SQlite for Android无法使用json_group_array/json_object

Select 按位运算序列

AssertJ Java:多条件断言

由于我在Main方法中关闭了 scanner ,但在该方法中创建了一个新的 scanner ,因此出现了错误

使用GridBagLayout正确渲染

@Rollback @ Transmission在验收测试中不工作

如何在Application.yaml中连接字符串?

try 将JSON字符串响应从API转换为映射字符串、对象>;时出错

JOLT根据值删除并保留其余的json键

Oracle中从JSON中提取和插入数据

Android无法在Java代码中调用Kotlin代码,原因是在Companion中使用Kotlin枚举时

为什么创建Java动态代理需要接口参数

如何使用Java对随机生成的字母数字优惠券代码进行过期设置

如何在右击时 Select 新行?

如何在Struts2中使用操作类中的结果注释重定向到不同的命名空间

原始和参数化之间的差异调用orElseGet时可选(供应商)

在不带instanceof或switch的java中记录模式

如何在 Java 函数式代码中使用泛型

在Java中,在Object#equals()调用期间,两个对象是否必须具有相同的hashCode?我们是否需要在 equals() 中比较 hashCode?