评估和截断
Evaluation and Truncation
先发生什么,截断还是求值?如果我这样做:
int a = (2+3)*10.5;
a 得到 52,但如果我这样做:
int a = 30 / 4 * 5;
a 得到 35。
所以一个表达式先求值然后截断。然后截断的值用于其他计算?因为在第二条语句中,“30/4”首先被评估,然后被截断为 7。具体规则是什么?文档中的任何内容...我不是在谈论类型转换,在这种情况下只是截断,比如表达式一个接一个地被截断?
发生什么情况取决于所涉及的值的类型。
2
、3
、30
、4
和 5
都是 int
.
类型
10.5
具有类型 double
.
因此(2+3)*10.5
执行2
和3
的整数加法,得到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;
2
和 3
都是 int
类型,所以它们只是相加——结果 (5
) 的类型是 int
再次。
但是 10.5
的类型是 double
。所以,5
也被转换为double
,结果是52.5
。仅因为您将其分配给 int
,它会转换回 int
,因此必须进行截断。
在你的第二个例子中:
int a = 30 / 4 * 5;
30
和 4
的类型都是 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
类型,因为 5
从 int
转换为 double
。此表达式的值为 52.5
,在分配给 int
.
时被截断为 52
30 / 4 * 5
从左到右分组(乘法和除法具有相同的优先级所以associativity 运算符开始发挥作用),所以它等同于 (30 / 4) * 5
。 30 / 4
是 7
(整数除法),然后乘以 5
得到结果。
一个更有趣的例子是30 / 4 * 5.0
。也就是还是35
不过是double
类型。分组仍为 (30 / 4) * 5.0
.
先发生什么,截断还是求值?如果我这样做:
int a = (2+3)*10.5;
a 得到 52,但如果我这样做:
int a = 30 / 4 * 5;
a 得到 35。
所以一个表达式先求值然后截断。然后截断的值用于其他计算?因为在第二条语句中,“30/4”首先被评估,然后被截断为 7。具体规则是什么?文档中的任何内容...我不是在谈论类型转换,在这种情况下只是截断,比如表达式一个接一个地被截断?
发生什么情况取决于所涉及的值的类型。
2
、3
、30
、4
和 5
都是 int
.
10.5
具有类型 double
.
因此(2+3)*10.5
执行2
和3
的整数加法,得到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;
2
和 3
都是 int
类型,所以它们只是相加——结果 (5
) 的类型是 int
再次。
但是 10.5
的类型是 double
。所以,5
也被转换为double
,结果是52.5
。仅因为您将其分配给 int
,它会转换回 int
,因此必须进行截断。
在你的第二个例子中:
int a = 30 / 4 * 5;
30
和 4
的类型都是 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
类型,因为 5
从 int
转换为 double
。此表达式的值为 52.5
,在分配给 int
.
52
30 / 4 * 5
从左到右分组(乘法和除法具有相同的优先级所以associativity 运算符开始发挥作用),所以它等同于 (30 / 4) * 5
。 30 / 4
是 7
(整数除法),然后乘以 5
得到结果。
一个更有趣的例子是30 / 4 * 5.0
。也就是还是35
不过是double
类型。分组仍为 (30 / 4) * 5.0
.