为什么输出不同,公式为何相同?

时间:2020-02-27 22:25:45

标签: c++ floating-point

size

上面的代码旨在获取整数y的最后一位,奇怪的是foo是shapes而bar是int y = 89; int foo = (y / 10.0 - y / 10) * 10; int bar = (89 / 10.0 - 89 / 10) * 10; cout << foo << ' ' << bar << '\n'; ,为什么会这样?两种版本的表达式有什么区别?

1 个答案:

答案 0 :(得分:5)

C ++标准允许实现比标称格式要求的精度更高的精度来评估浮点表达式。例如,可以将float表达式视为double或更高,而将double表达式视为long double。这种额外的精度可能会导致评估上的差异,尤其是在使用不连续函数(例如转换为int)的情况下。

例如,给定y = 89y / 10.0 - y / 10的实数运算将为.9,而double(IEEE-754 binary64)算术则为0.9000000000000003552713678800500929355621337890625和{{{ 1}}(Intel的80位格式)算法,然后乘以10并转换为long double会分别产生9或8。

在禁用优化的情况下,编译器可能会在运行时使用int评估表达式,而在编译过程中使用y评估表达式,并且它们可能使用不同的精度。通过优化,编译器很可能会在第一个表达式中认识到89实际上是常量y,并在编译过程中对两个表达式进行求值,并对两者使用相同的方法。

C ++标准要求将强制类型转换和赋值操作转换为名义类型,因此一项测试是否会发生这种情况是插入强制类型转换:

89

如果这导致int foo = (double) ((double) (y / 10.0) - y / 10) * 10; int bar = (double) ((double) (89 / 10.0) - 89 / 10) * 10; foo相同,则支持该假设。您的编译器可能具有控制如何计算浮点表达式的开关。

另一项测试是包括bar并打印<cfloat>的值。如果为0,则该实现要求以其名义类型评估浮点运算,并且不应发生此行为。如果它是1或2,则该实现声明分别使用FLT_EVAL_METHODdouble来评估long double表达式,并且不应再次发生此行为,因为两个表达式将被评估为相同道路。如果为-1,则表示实现未声明这些声明,因此可能会发生该行为。

要获取非负整数的最后一位,请使用double

相关问题