如何重现C ++双舍入问题

时间:2011-03-19 22:24:50

标签: c++ floating-point rounding

浮点精度在C++中受到限制,对于新手程序员来说,在舍入值时经常会遇到麻烦。

在教学生时,通常有助于演示浮点精确数舍入问题。您知道在所有C++编译器上一致地证明这样的舍入问题有哪些可能的方法?

5 个答案:

答案 0 :(得分:5)

您可以使用此示例:

#include <iostream>
using namespace std;

int main() {
  for (double d = 0.0; d != 1.0; d += 0.1)
    cout << d << "\n";
}

程序永远不会终止,因为d永远不会等于1。

答案 1 :(得分:4)

首先,我们应该注意,在IEEE754浮点中,1.50.52.0都是完全代表的。因此,在此具体示例中,1.5永远不会是1.499999999999

话虽如此,我认为要做的是让学生接触的数字。说,1.1

以下是一个示例程序:

#include <iostream>
#include <iomanip>

int main() {
   std::cout << std::setprecision(30);
   double d1(1.1);
   std::cout << d1 << "\n";
   double d2(11);
   double eps = d2/10 - d1;
   std::cout << d2 << "\n";
   std::cout << eps << "\n";
   bool equal = (d1 == d2);
   std::cout << equal << "\n";
}

也许你可以通过这个程序,小心地说d1d2 大约等于1.1。

对于高年级学生,您可以通过派系二进制算术查看为什么1/2可以表示,但1/10不是。

编辑:我认为将点回归的方法是将重复的小数部分与重复的二进制分数进行比较。以小数显示您的学生1/7。在董事会做长期分工。指出你不能使用有限资源写下1/7。然后,要么向他们展示如何将1/10写成二进制分数,要么告诉他们你不能用有限的资源写下它。

指出浮点数是有限的(32位),双精度数是有限的(64位)。也许引入鸽派校长并说你不能用有限的单词长度表示无限集合(如所有有理数)。

无论您尝试什么,请在此处报告,并告诉我们它是如何运作的。

答案 2 :(得分:2)

我喜欢以下示例:

double sum = 0;
for (int i = 0; i < 10; i++, sum += 0.1);
cout << "sum = " << sum << endl;
cout << "(sum == 1.) is " << boolalpha << (sum == 1.)  << endl;

输出如下:

sum = 1
(sum == 1.) is false

矛盾的原因是浮点计算。

答案 3 :(得分:1)

printf("%.20f\n",0.1f);

cout << fixed << setprecision(20) << 0.1f << endl;

:)

答案 4 :(得分:1)

试试这个例子:

#include <cstdio>
int main() {
    printf("%.20lf rounded to two decimal places is %.2lf\n", 0.075, 0.075);
    return 0;
}

打印

0.07499999999999999722 rounded to two decimal places is 0.07

请注意,0.075舍入到两位小数应该是0.08,而不是我们在输出中看到的0.07。此示例清楚地演示了双舍入问题