开发者

How to reproduce C++ double rounding issue

Floating point precision is limited in C++ and for novice programmers that often causes trouble when rounding values.

When teaching students it is often useful to demonstrate the floating point precision number roun开发者_如何学Goding issue. What possible ways do you know to demonstrate such rounding issue consistently on all C++ compilers?


You can use this example:

#include <iostream>
using namespace std;

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

The program will never terminate as d never equals 1.


First, we should note that, in IEEE754 floating point, 1.5, 0.5, and 2.0 are all exactly represented. So, in this specific example, 1.5 will never be 1.499999999999.

Having said that, I think the thing to do is to expose your students to numbers are not exactly representable. Say, 1.1.

Here is a sample program:

#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";
}

Perhaps you can walk them through this program, being careful to say that d1 and d2 are both approximately equal to 1.1.

For advanced students, you can go through factional binary arithmetic and see why 1/2 is representable, but 1/10 is not.

EDIT: I think the way to bring the point home is to compare repeating decimal fractions with repeating binary fractions. Show your students 1/7 in decimal. Do the long division on the board. Point out that you cannot write 1/7 down exactly using finite resources. Then, either show them how to write 1/10 as a binary fraction, or just tell them that you can't write down it either using finite resources.

Point out that floats are finite (32 bits) and doubles are finite (64 bits). Maybe introduce pigeonhole principal and say that you can't represent an infinite set (like all rationals) in a finite word length.

Whatever you try, please report back here and let us know how it works.


I like the following example:

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;

The output follows:

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

The cause of contradiction is floating point calculations.


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

or

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

:)


Try this example:

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

which prints

0.07499999999999999722 rounded to two decimal places is 0.07

note that 0.075 rounded to two decimal places should be 0.08, not 0.07 as we see in the output. This example clearly demonstrates double rounding issue

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜