施放Math.pow()时精度损失

时间:2017-12-07 14:29:14

标签: java casting int

我试图计算int的最大值,但是我无法弄清楚为什么转换为int的计算值低于转换为long时的计算值。我在计算器上提出(2^31) - 1,值为

2_147_483_647

我希望在Java 2^31上升1并在Java中扣除2147483647时,它应该计算int System.out.println(((long) Math.pow(2, 31)) - 1); System.out.println((int) Math.pow(2, 31) - 1); 的最大数量,但事实并非如此。

2_147_483_647

第一个计算给出:2_147_483_646

第二次计算得出:public class GridStudent { [Key] public int IdStudent { get; set; } public string Name { get; set; } public string LastName { get; set; } }

5 个答案:

答案 0 :(得分:5)

演员阵容优先于减法。你应该先做减法:

$httpProvider.interceptors.
push('httpRedirectInterceptor');
  • System.out.println((int) (Math.pow(2, 31) - 1)); Math.pow(2, 31),类型为2_147_483_648(因为Math.pow()返回一个double),此数字不适合int。

  • 当您将双double强制转换为int时,它会被截断为int可以容纳的最大值(请参阅How does double to int cast work in Java)。

  • 强制转换将双2_147_483_648截断为int 2_147_483_648

  • 然后你的代码减去1,最后得到2_147_483_647

答案 1 :(得分:2)

第一个例子

让我们分析一下你做了什么。第一个例子是

((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

第二个例子

现在让我们看看第二个例子的作用。你写的

(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_646

校正

我认为你认为

(int) Math.pow(2, 31) - 1

评估为

(int) (Math.pow(2, 31) - 1)

但事实并非如此。如果你明确这一点,你确实会得到

2_147_483_647

正如所料。

运算符优先级

您可以在 Java语言规范中了解相关内容,请参阅JLS§15.15 Unary Operators。投射具有优先于运算符,例如减法。

这是因为施放一元运算符,而减法是二进制。一元优先于二元。因此official documentation给出了下表作为概述:

+----------------------------------------------------------------+
| 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            | = += -= *= /= %= &= ^= |= <<= >>= >>>= |
+----------------------------------------------------------------+

投射当然是一元类别的一部分。

答案 2 :(得分:1)

Typecast整个Math.pow(2, 31) - 1)。喜欢这个

System.out.println((int) (Math.pow(2, 31) - 1));

答案 3 :(得分:1)

您将括号放在错误的位置。它应该是:

System.out.println((int) (Math.pow(2, 31) - 1));

答案 4 :(得分:0)

编写像(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)