java如何定义算术表达式的结果

how does java define the result of an arithmetic expression

我正在为 Java 编写解析器,但是,当涉及到基本类型的操作时,我有点迷茫。

例如我有这些表达式:

int i;
long l;
float f;
short s;
byte b;
//this is being cast from a float to an int? should this be a cast from byte?
int var1 = (int) (l * i * f * s * b);
//this is being cast from a float to an int? should this be a cast from long?
int var2 = (int) (l * (i * f * s * b));
//again casting from float to int? should this be a cast from short?
int var3 = (int) ((f) * (l) * (s));
//this seems to be a float but i expected this to be a long
int var4 = (int) ((f) * (l));

我认为最后要完成的操作将是结果类型,但是,这似乎不是上述示例中的情况。 (我没有列出任何双精度运算,但是,似乎双精度像浮点数一样优先。)

我的另一个想法是,因为它必须进行浮点运算,所以它正在将其转换为最大的 (32/64) 位类型,这样就不会丢失任何信息,除非有一个特定的强制转换隐藏了这一事实它 一个 float/double,例如以下表达式的计算结果为 long。

int var1 = (l * i * (int) d * s * b);

这种想法确实不尽如人意,但是,就好像在同一个表达式中有一个 long/float 如果 long 的值太大而无法放入 float,您可能会丢失信息.

您可以找到 in the language spec 的两个最相关的详细信息是:

  • 乘法(以及加法、减法、除法等)是左结合。所以:

    l * i * f * s * b
    

    被评估为

    (((l * i) * f) * s) * b
    
  • 乘法(以及加法、减法、除法等)的操作数经过binary numeric promotion。松散地,这意味着操作数被扩大以相互兼容。

    更准确地说:

    • 如果一个操作数是双精度,则另一个加宽为双精度
    • 否则,如果一个操作数是浮点数,则另一个被加宽为浮点数
    • 否则,如果一个操作数是long,则另一个被加宽为long
    • 否则,两个操作数都被扩展为 int

    最后一点告诉你,即使相乘类似的类型,比如 short 和 short,操作数仍然扩大到 int

有了这两点:

  • l * i 是一个长
  • (l * i) * f 是一个浮点数
  • ((l * i) * f) * s 是一个浮点数
  • (((l * i) * f) * s) * b 是一个浮点数。

因此,您正在从 float 转换为 int。