5

考虑以下:

#include <iostream>
#include <cmath>
int main()
{
  using std::cout;
  using std::endl;

  const long double be2 = std::log(2);
  cout << std::log(8.0) / be2 << ", " << std::floor(std::log(8.0) / be2)
      << endl;

  cout << std::log(8.0L) / be2 << ", " << std::floor(std::log(8.0L) / be2)
      << endl;
}

输出

  3, 2
  3, 3

为什么输出不同?我在这里想念什么?

这里也是键盘的链接:http: //codepad.org/baLtYrmy

如果这很重要,我在 linux 上使用 gcc 4.5。

4

3 回答 3

4

当我添加这个:

cout.precision(40);

我得到这个输出:

2.999999999999999839754918906642444653698, 2
3.00000000000000010039712117215771058909, 3

您正在打印两个非常接近但不完全等于 3.0 的值。std::floor对于非常接近的值,其结果可能会有所不同(从数学上讲,它是一个不连续的函数)。

于 2011-08-11T19:39:45.487 回答
2
#include <iostream>
#include <cmath>
#include <iomanip>

int main()
{
  using std::cout;
  using std::endl;

  const long double be2 = std::log(2);

  cout << setprecision (50)<<std::log(8.0)<<"\n";
  cout << setprecision (50)<<std::log(8.0L)<<"\n";
  cout << setprecision (50)<<std::log(8.0) / be2 << ", " << std::floor(std::log(8.0) / be2)
       << endl;
  cout << setprecision (50)<< std::log(8.0L) / be2 << ", " << std::floor(std::log(8.0L) / be2)
       << endl;

  return 0;
}

输出是:

2.0794415416798357476579894864698871970176696777344
2.0794415416798359282860714225549259026593063026667
2.9999999999999998397549189066424446536984760314226, 2
3.0000000000000001003971211721577105890901293605566, 3

如果您在这里查看输出,您会注意到两个输出的精度略有不同。这些舍入错误通常会在执行时触发 float 和 double 的操作,floor()并且出现的结果不是人们认为应该的结果。

当您使用浮点数或双精度数时,记住两个属性PrecisionRounding很重要。

您可能想在我的回答中阅读更多关于它的信息,同样的推理也适用于这里

于 2011-08-11T19:32:14.007 回答
2

为了扩展Als所说的-

在第一种情况下,您将 8 字节双精度值除以 16 字节长双精度值。在第二种情况下,您将 16 字节长双精度数除以 16 字节长双精度数。这会导致一个非常小的舍入误差,可以在此处看到:

cout << std::setprecision(20) << (std::log(8.0) / be2) << std::endl;
cout << std::setprecision(20) << (std::log(8.0L) / be2) << std::endl;

产生:

2.9999999999999998398
3.0000000000000001004

编辑说:在这种情况下, sizeof 是您的朋友(查看精度差异):

sizeof(std::log(8.0));  // 8
sizeof(std::log(8.0L)); // 16
sizeof(be2);            // 16
于 2011-08-11T19:38:30.867 回答