长过int除法

Long over int division

之前有人问过这个问题。我不同意这个答案。为什么除法会这样?请看 long aslong=n/(a*b)

这一行

仅供参考。几年前的类似问题。 Unexpected result in long/int division

long n=8589934592l; // =2^33 
int nasint=(int)n;  // it can't fit into int so it's zero.          
int a=2097152; int b=1024;
int asint=(int) n/(a*b); // n is cast into zero. so answer is zero.
long aslong=n/(a*b); // don't the int get cast into long?
long aslong2=n/((long)a*(long)b); // as expected

System.out.println("long n=" + n + " as int=" + nasint); // long n=8589934592 as int=0
System.out.println("asint=" + asint); // asint=0
System.out.println("aslong=" + aslong); // aslong=-4
System.out.println("aslong2=" + aslong2); // aslong2=4

Java 语言规范说明如下。

15.7.3.“计算尊重括号和优先级”:

The Java programming language respects the order of evaluation indicated explicitly by parentheses and implicitly by operator precedence.

15.7.2.“在操作前评估操作数”:

The Java programming language guarantees that every operand of an operator (except the conditional operators &&, ||, and ? :) appears to be fully evaluated before any part of the operation itself is performed.

这意味着 (a*b)n/(a*b) 中的除法运算符 之前计算 ,因为 abint 个变量,乘法是 int。然后将结果进行“Widening Primitive Conversion”到long的除法。


既然我引用了 JLS,那我也引用一下这个吧(特别感谢 David Wallace 的关注):

3.10.1.“整数文字”:

An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int (§4.2.1).

The suffix L is preferred, because the letter l (ell) is often hard to distinguish from the digit 1 (one).