Java 铸造Math.pow()时的精度损失
我试图计算int的最大值,但是我不明白为什么转换为int的计算值低于转换为long时的值。我在计算器上提出了Java 铸造Math.pow()时的精度损失,java,casting,int,Java,Casting,Int,我试图计算int的最大值,但是我不明白为什么转换为int的计算值低于转换为long时的值。我在计算器上提出了(2^31)-1,值为 2_147_483_647 在Java中,当我上升2^31并扣除1时,它应该计算int2147483647的最大值,但它没有 System.out.println(((long) Math.pow(2, 31)) - 1); System.out.println((int) Math.pow(2, 31) - 1); 第一次计算得出:2\u 147\u 48
(2^31)-1
,值为
2_147_483_647
在Java中,当我上升2^31
并扣除1
时,它应该计算int2147483647
的最大值,但它没有
System.out.println(((long) Math.pow(2, 31)) - 1);
System.out.println((int) Math.pow(2, 31) - 1);
第一次计算得出:2\u 147\u 483\u 647
第二次计算给出:
2\u 147\u 483\u 646
键入整个Math.pow(2,31)-1)
。像这样
System.out.println((int) (Math.pow(2, 31) - 1));
你把括号放错地方了。应该是:
System.out.println((int) (Math.pow(2, 31) - 1));
强制转换优先于减法。你应该先做减法:
System.out.println((int) (Math.pow(2, 31) - 1));
是Math.pow(2,31)
的类型为2_147_483_648
(因为Math.pow()返回一个double),这个数字不适合整数double
- 当您将双精度
转换为整数时,它将被截断为整数所能容纳的最大值(请参阅)2_147_483_648
- 强制转换将双精度
截断为int2_147_483_648
2_147_483_647
- 然后代码减去1,最后得到
2\u 147\u 483\u 646
((long) Math.pow(2, 31)) - 1;
这意味着您首先计算Math.pow(2,31)
,这将产生
2.147_483_648 E9
之后,您将强制转换为long
。请注意,long
对于该值有足够的位置,因此它表示为
2_147_483_648
然后减去1
,得到
2_147_483_647
2_147_483_646
第二个例子 现在,让我们看看第二个示例的作用。你写的
(int) Math.pow(2, 31) - 1
这被解释为
((int) Math.pow(2, 31)) - 1
因此,与之前相同,但强制转换为int
,而不是long
。现在请注意,int
没有足够的位置来放置该值。可以表示的最大int
2_147_483_647 // MAX_INTEGER
所以你也会得到这个值。然后减去1
,得到
2_147_483_647
2_147_483_646
校正 我想你是这么想的
(int) Math.pow(2, 31) - 1
评估为
(int) (Math.pow(2, 31) - 1)
但事实并非如此。如果你把这一点说得很清楚,你就会明白
2_147_483_647
正如所料
运算符优先级 您可以在Java语言规范中了解这一点,请参阅。强制转换的优先级高于减法等运算符 这是因为强制转换是一个一元运算符,而减法是二元运算符。一元优先于二元。因此,下表概述如下:
+----------------------------------------------------------------+
| Operators | Precedence (top is high, bottom low) |
|-----------------------|----------------------------------------|
| postfix | expr++ expr-- |
| unary | ++expr --expr +expr -expr ~ ! |
| multiplicative | * / % |
| additive | + - |
| shift | << >> >>> |
| relational | < > <= >= instanceof |
| equality | == != |
| bitwise AND | & |
| bitwise exclusive OR | ^ |
| bitwise inclusive OR | | |
| logical AND | && |
| logical OR | || |
| ternary | ? : |
| assignment | = += -= *= /= %= &= ^= |= <<= >>= >>>= |
+----------------------------------------------------------------+
+----------------------------------------------------------------+
|运算符|优先级(顶部为高,底部为低)|
|-----------------------|----------------------------------------|
|后缀| expr++expr--|
|一元|++expr--expr+expr-expr~|
|乘法|*/%|
|加法|+-|
|班次|>>>>|
|关系|<>=实例|
|相等|==!=|
|按位与|&|
|位异或|^|
|按位包含或| ||
|逻辑与&&|
|逻辑或| | ||
|三元|?:|
|分配|=+=-=*=/=%=&=^=|===>>=|
+----------------------------------------------------------------+
Casting当然是unitary类别的一部分。像这样编写代码
(int)Math.pow(2,31)-1
使Java将Math.pow(2,31)
转换为int。因为这超过了int的最大值,结果是2_147_483_647
。因为之后减去1,所以得到的值低于实际解。
您应该将整个计算转换为int,而不仅仅是Math.pow(2,31)
,因此它看起来是这样的:
(int)(Math.pow(2,31)-1)
Java在释放double->int时不会溢出,这就是为什么数学没有检查的原因