循环中的 C++ 浮点错误与单个表达式中的浮点错误

hal*_*ley 3 c++ floating-point compiler-optimization

(免责声明:我知道浮点数不能精确表示十分之一。)

我在 C++ 中使用单精度浮点数(以测试舍入错误),我遇到了这种奇怪的行为。

#include <iostream>
#include <iomanip>
using namespace std;

int main(){
  // set number of sigdigs in output
  cout << setprecision(9);

  float singleA = 0.1 * 7.;
  float singleB = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1;
  float singleC = 0.0;
  for (int i = 0; i < 7; i++){
    singleC += 0.1;
  }
  // ^ i expected that to be the same as
  // 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1

  cout << "multiplied:      " << singleA << endl;
  cout << "added in one go: " << singleB << endl;
  cout << "added in a loop: " << singleC << endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

multiplied:      0.699999988
added in one go: 0.699999988
added in a loop: 0.700000048
Run Code Online (Sandbox Code Playgroud)

我想知道为什么在表达式中添加 0.1 7 次会产生与在循环中添加 0.1 7 次不同的结果。我都加了 0.1 7 次,为什么会发生这种情况?是否singleB使用浮点十进制算法进行优化

Sne*_*tel 5

0.1double,不是float。因此,当您在表达式中添加其中的七个时,将使用双精度算术进行运算,然后将最终结果转换为单精度。在循环中,您在每次添加后丢弃额外的精度。试试看0.1f,你会得到相同的结果。

  • 回复“用‘0.1f’尝试一下,你会得到相同的结果。”:不一定。C++ 标准允许实现以比标称类型更高的精度计算浮点表达式,直到执行赋值或强制转换。因此,编译器可以使用“double”算术添加“float”值,并获得与每个结果单独存储在“float”中不同的舍入结果。 (2认同)