评估和截断

Evaluation and Truncation

先发生什么,截断还是求值?如果我这样做:

int a = (2+3)*10.5;

a 得到 52,但如果我这样做:

int a = 30 / 4 * 5; 

a 得到 35。

所以一个表达式先求值然后截断。然后截断的值用于其他计算?因为在第二条语句中,“30/4”首先被评估,然后被截断为 7。具体规则是什么?文档中的任何内容...我不是在谈论类型转换,在这种情况下只是截断,比如表达式一个接一个地被截断?

发生什么情况取决于所涉及的值的类型。

233045 都是 int.

类型

10.5 具有类型 double.

因此(2+3)*10.5执行23的整数加法,得到5(另一个int),然后[=的浮点乘法23=](从 5 隐式转换)和 10.5,产生 52.5。此数字分配给 int,它隐式地将其截断为 52

另一方面,在 30 / 4 * 5 中,所有操作数都是 int,没有任何内容被转换为 double。因此 30 / 4 执行整数除法,得到 7,然后乘以 5,得到 35.

没有单独的评估和截断。截断可以作为类型转换的一部分发生,但在 30 / 4 中,您不是在查看单独的截断和评估步骤,而是在查看单个操作(整数除法)。当然,由于这个结果的类型是int,它不能有任何小数位。

你有点问错了问题,没有单独的评估和截断步骤这样的东西。截断是类型转换的副作用,如果转换后的值不能在目标类型中准确表示,例如

double d = 2.5;
int i = d;       // 2.5 is truncated as a side effect of converting to int

所以你必须知道的是在计算表达式时操作数是如何转换的。确切的规则有点复杂,我将在这里重点介绍基础知识。通常,对于算术运算符,如果操作数的类型不相同,则会以某种方式转换其中一个,以便可以表示两个值。在你的第一个例子中:

int a = (2+3)*10.5;

23 都是 int 类型,所以它们只是相加——结果 (5) 的类型是 int再次。

但是 10.5 的类型是 double。所以,5也被转换为double,结果是52.5。仅因为您将其分配给 int,它会转换回 int,因此必须进行截断。

在你的第二个例子中:

int a = 30 / 4 * 5;

304 的类型都是 int。因此,不进行转换,直接进行除法。

这里有一个要点: 两个整数相除是 整数除法 ,它再次导致 int(此处:7).那不是截断,而是整数除法的定义方式。事实上,您可能在学校早期就使用一种名为 long division with remainder 的算法学习过该操作。 C 中有一个 "opposite" 运算模 (%),它会给你该除法的 余数

所以,这里你有 int 类型的结果 7,然后乘以 5,另一个 int,因此,同样,没有转换 - - 最后的结果是 35.

检查如果你写

会发生什么
int a = 30.0 / 4 * 5;

代替。现在,/ 的第一个操作数是双精度数,因此 4 也被转换为 double,结果是 7.5 —— 又是 double,导致 5 转换为 double 并产生 37.5.

的最终结果

这再次转换为 int 因为您将其分配给 int 并且截断产生 37.


请注意运算符 / 在这里有两种不同的含义(实数除法与整数除法),具体取决于其操作数的类型。

不要考虑截断求值。相反,请考虑 分组 整数除法 。还有一些其他术语需要引入以进行充分分析:我已经注意 斜体 那些。

表达式 (2 + 3) * 10.5 因括号而明确分组。所以 5 * 10.5 是一个中间步骤;这是一个 double 类型,因为 5int 转换为 double。此表达式的值为 52.5,在分配给 int.

时被截断为 52

30 / 4 * 5从左到右分组(乘法和除法具有相同的优先级所以associativity 运算符开始发挥作用),所以它等同于 (30 / 4) * 530 / 47(整数除法),然后乘以 5 得到结果。

一个更有趣的例子是30 / 4 * 5.0。也就是还是35不过是double类型。分组仍为 (30 / 4) * 5.0.