c++ - 如果存储在中间 "double"变量中,浮点计算会发生变化

标签 c++ floating-point double floating-accuracy

我正在尝试编写一个简单的 log base 2 方法。我知道在计算机上表示 std::log(8.0) 和 std::log(2.0) 之类的东西很困难。我也明白 std::log(8.0)/std::log(2.0) 可能导致值略低于 3.0。我不明白的是为什么将下面的计算结果放入 double 并使其成为左值然后将其转换为 unsigned int 与直接转换公式相比会改变结果。以下代码显示了我的测试用例,它在我的 32 位 debian wheezy 机器上反复失败,但在我的 64 位 debian wheezy 机器上反复通过。

#include <cmath>
#include "assert.h"

int main () {
  int n = 8;
  unsigned int i =
    static_cast<unsigned int>(std::log(static_cast<double>(n)) /
                              std::log(static_cast<double>(2)));
  double d =
    std::log(static_cast<double>(n)) / std::log(static_cast<double>(2));
  unsigned int j = static_cast<unsigned int> (d);
  assert (i == j);
}

我也知道我可以使用位移以更可预测的方式得出我的结果。我很好奇为什么将结果转换为 int 操作与将该值粘贴到堆栈上的 double 并将 double 转换到堆栈有什么不同。

最佳答案

在 C++ 中, float 可以做这种事情。

一个可能的解释是,除法的结果在内部以比double 更高的精度计算,并存储在比double 更高精度的寄存器中。

将其直接转换为 unsigned int 与首先将其转换为 double 然后再转换为 unsigned int 的结果不同。

要准确了解发生了什么,查看编译器针对 32 位情况生成的汇编输出可能会有所帮助。

不用说,您不应该编写依赖于浮点运算准确性的代码。

关于c++ - 如果存储在中间 "double"变量中,浮点计算会发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29335982/

相关文章:

c - 除法结果始终为零

c++ - 多个网格到单个波前 OBJ 文件

c++ - C++(MFC,而非 .NET)应用程序的程序集重定向

c++ - C++ 中的静态对象与单例类对象?

java - double 或 float 数据类型在循环中不能正确相加?

haskell - 非整数的模/余数函数

c++ - 为什么在 win32 计时器回调中抛出的未处理异常未被调试器视为未处理异常?

gwt - JavaScript 上的任意精度 float

使用变量选择在点后打印多少个数字

c++ - C++中的最佳 double 值限制