我有一个非常有趣的错误,其中.498 * 2000产生995而不是996 - 但仅当2000存储在整数变量而不是简单的文字中时。我运行以下代码以确保我不会发疯,变量的结果显示在注释中。 dequeue和peek是我正在使用的函数,它们返回int16_t,虽然这似乎不重要因为c仍然是值为2000的int。所有值都通过print语句和在gdb中运行来确认。
int a = buffer.dequeue(); // a = 0
int b = buffer.peek(); // b = 2000
int c = a + b; // c = 2000
float d = .498*2000; // d = 996
int e = static_cast<int>(d); // e = 996
int f = .498*2000; // f = 996
int g = .498*c; // g = 995 WHY??????
我真的不明白这里发生了什么,并且非常欣赏这个主题的一些亮点。谢谢!
编辑:
澄清究竟发生了什么,简化: 我在主文件中运行以下代码:
int a = 2000;
int b = .498*2000;
int c = .498*a;
std::cout << a << " " << b << " " << c << std::endl;
得到以下输出:
2000 996 995
我不明白为什么c和b是基于2000是文字变量还是整数变量的不同值。在我看来,在任何一种情况下都应该应用相同的舍入或截断。 谢谢。
我正在编译以下内容:
g++ -o main.o -g -std=c++0x
答案 0 :(得分:1)
我认为差异来自于编译时评估与浮点表达式的运行时评估。
编译器能够在编译时评估d
。它仅在运行时评估g
。但是,它们不需要产生完全相同的值。
来自5.19 Constant expressions /4:
虽然在某些情况下,必须在程序转换期间评估常量表达式,但在程序执行期间可以评估其他表达式。由于本国际标准对浮点运算的准确性没有任何限制,因此未指定在转换期间对浮点表达式的求值是否与对同一表达式的求值产生相同的结果(或对相同值的相同操作)在程序执行期间。
最好避免使用此类代码。该标准不保证这些数字的准确性。结果可能因编译器而异。它们可能会因相同的编译器而异,但优化标志也不同。