为何Java计算2^61 - 1结果错误?
为什么用Math.pow计算2^61-1会得到错误结果?
问题出在Math.pow()的返回类型和精度限制上:
- double类型的精度不足:
Math.pow(2,61)返回的是double类型值,而double是64位浮点数,其中只有52位用来存储尾数(有效数字部分)。它能精确表示的整数范围是-2^53到2^53,而2^61远超出这个范围,所以Math.pow(2,61)无法精确存储真实的2^61值,实际存储的是一个比真实值略大的近似值。 - 减法操作无法体现精度:当你对这个近似值执行
-1操作时,由于1相对于2^61来说太小了,超出了double能分辨的最小精度单位,所以这个减法操作实际上不会改变原有的近似值——也就是说,Math.pow(2,61)-1的结果和Math.pow(2,61)的近似值在double中是同一个数。 - 强转long时保留错误值:最后把这个错误的
double值强转为long,就得到了比正确结果大1的数值。
正确的写法
要精确计算这个值,直接用整数运算即可,比如用位操作:
class Main { public static void main(String[] args) { long x = (1L << 61) - 1; System.out.println(x); } }
这里1L是长整型的1,左移61位就是精确的2^61,再减1就能得到正确的2305843009213693951。
内容的提问来源于stack exchange,提问作者jack klompus
相关产品推荐
相关产品推荐

