2

有人可以向我解释为什么下面代码的结果不同吗?提前致谢。所有变量都是双倍的。

第一的:

volume=(4/3)*(Math.PI*Math.pow(raio,3))

如果我声明 raio=5,结果将是=392,xxx

如果出现以下情况,结果也将是 392:

volume=(Math.PI*Math.pow(raio,3))*(4/3);

第二:

volume=(Math.PI*Math.pow(raio,3))*4/3;

如果我声明 raio=5,那么结果现在是正确的:523,xxx

4

6 回答 6

4

这是因为当你使用:

volume=(Math.PI*Math.pow(raio,3))*(4/3);

发生的情况是 (4/3) 被评估为整数除法,因此 (4/3) = 1。

因此,

volume=(Math.PI*Math.pow(raio,3))*4/3;

会起作用,因为它是一个 double * 4,它是一个 double,然后除以 3,这也是一个 double。

如果你试试这个:

volume=(Math.PI*Math.pow(raio,3))*(4.0/3.0);

你应该看到它起作用了。

请注意,您可能只需 4.0/3 或 4/3.0 就可以逃脱。

于 2013-11-06T21:52:12.027 回答
1
(pi * raio^3)*(4/3) != (pi * raio^3)*4 / 3.

在第二个中,它乘以 4,然后除以 3。在第一个中,它乘以 (4/3)

更不用说 4 和 3 不是双打

于 2013-11-06T21:51:53.507 回答
1

在第一次计算中,您有效地运行 1*(Math.PI*Math.pow(raio,3)),因为 4/3 以整数完成并计算为 1。在第二次计算中,第一个参数被计算为加倍,导致表达式的其余部分被评估为双精度。尝试运行 (4.0/3.0)*(Math.PI*Math.pow(raio,3))

于 2013-11-06T21:53:03.030 回答
1

在你的第一种情况下,(4/3) returns an int which is 1;

利用MathExpression*(4.0/3.0);

于 2013-11-06T21:53:03.250 回答
1

Math.PIS 定义为 double PI = 3.141592653589793;

当您执行任何一个变量为 double 的操作时,另一个变量会自动提升为 double。由于第 4/3 段,您的两个示例中的差异即将到来。

在大括号中使用时,它被视为 int 并得到 1,而在另一个示例中,4 乘以 double 值得到 double,然后再除以 3,得到 1.333333。

总结:volume=(Math.PI*Math.pow(raio,3))*(4/3);评估为

        volume = (392.6990816987241)*(4/3)
        volume = (392.6990816987241) * (1)  //<--int division
        volume = 392.6990816987241

volume=(Math.PI*Math.pow(raio,3))*4/3;被评估为

        volume = (392.6990816987241) *4/3
        volume = 1570.7963267948965/3   //division of double by int
        volume = 523.5987755982989

如果您注意到,第二个结果是1.33333第一个结果的倍数。

如果在第一个示例中,如果您将一个参数更改为双精度,例如 4.0 或 3.0 或两者,即

        volume=(Math.PI*Math.pow(raio,3))*(4.0/3)
   or   volume=(Math.PI*Math.pow(raio,3))*(4/3.0)
   or   volume=(Math.PI*Math.pow(raio,3))*(4.0/3.0)

您将得到与示例 2 相同的结果。

希望这可以帮助。

于 2013-11-06T21:54:39.257 回答
1

首先,看这个优先表:http ://www.seas.upenn.edu/~palsetia/java/precedenceTable.html

优先级决定哪个表达式将在其他表达式之前解析为一个值。在您给出的第一个和第二个示例中:

  • 包含 pi 的大括号将自行解析
  • 带有表达式的大括号4/3将自行解析

后面的除法产生1,因为两个integer 文字的除法会产生一个int不能表示小数的 eger 类型。这些小数在第一个和第二个示例的计算中都丢失了。

与此相反,最后一个表达式从左到右解析。大括号不会影响计算的顺序,因为它们包含了无论如何都会首先解析的第一个表达式。第一个大括号产生一个double类型,然后与int 4. 这里发生的事情称为隐式转换

这实际上是一种特殊形式的隐式转换,称为类型提升。为了结合 anint和 a double,Java首先将 a升级intadouble以使类型兼容。double在某种程度上可以被视为比 . 更通用的类型int。当前一个计算的结果除以int 3.

因为隐式转换发生在任何integer 值被除之前,所以4/3保留了小数点,这会导致与前两个示例不同的结果。在这些示例中,您可以使用显式转换来获得所需的结果:

(double) 4/3

请注意,显式转换 - 看起来像类型转换的语句 - 具有比除法更高的优先级,即在此双精度除以另一个将此数字隐式转换为4类型之前的优先级。当然,您也可以使用双重文字而不是显式转换并观察相同的结果。double3double4d

PS:第二个和第一个示例还包含4/3当它与另一个包含 pi 的大括号的结果相乘时的结果的隐式转换。然而,此时小数已经丢失。

于 2013-11-06T22:14:37.217 回答