为何C++中1.0/3.0不属于未定义操作?(无法用float表示)
为什么
1.0 / 3.0不是未定义行为? 你引用的C++标准条款容易让人产生误解,核心要搞清楚“可被结果类型表示”的真实含义:
若表达式求值期间,结果在数学上无定义或超出其类型的可表示值范围,则行为未定义。
二元/运算符产生第一个表达式除以第二个表达式的商。若商a/b可被结果类型表示[略];否则,a/b的行为未定义。
这里的“商可被结果类型表示”,不是要求数学上的精确值能被类型精准存储——要是按这个逻辑,绝大多数浮点数运算都成未定义行为了。实际标准的意思是:经过浮点数标准规定的舍入处理后,最终结果要落在该类型的可表示范围内。
以常见的IEEE754双精度double为例,它从设计上就不保证能精确存储所有实数,而是通过舍入规则(默认是“向最近值舍入,遇中间值则选末尾为偶数的那个”),把无法精确表示的实数映射到最近的合法double值。1.0 / 3.0的数学结果是无限循环的二进制小数,确实没法精确存在double里,但经过舍入后得到的是一个完全合法的double值,完全在该类型的可表示范围内。
标准里说的“未定义行为”,针对的是两种情况:
- 数学上本身无定义的操作(比如整数除以0,或者实数域里负数开平方)
- 数学结果超出类型的可表示范围(比如计算一个远超
double最大上限的数导致溢出)
而1.0 / 3.0既不属于数学无定义,舍入后的结果也没超出double的范围,所以它是完全定义良好的行为,编译器会按照浮点数规则生成正确的舍入结果。
内容的提问来源于stack exchange,提问作者Andrew Tomazos
相关产品推荐
相关产品推荐

