• 0

[C++] Confusing bug with setprecision()


Question

Hello, I'm new to the forums and would really appreciate your help. I seem to be missing something with the setprecision() function. I want to round a floating point with 3 decimal places up to 2 decimal places.

#include <iostream>
#include <iomanip>

using namespace std;

int main() {
   double x = 5.555;
   cout <<  "x is " << fixed << setprecision(2) << x << endl;

   return 0;	
}

If I compile this (using g++), the output is

x is 5.55

However, if I change x to 5.556 it rounds up correctly to 5.56. What am I doing wrong?

Link to comment
Share on other sites

4 answers to this question

Recommended Posts

  • 0

setprecision() is not meant to be used as a means to round a number, but to enforce decimal places.

if you want to round properly, you need to do the following:

1. Get the multiple desired by raising the base of 10.0 to the precision needed

2. Multiply the original number by the multiple obtained in step 1 (shifts the decimal) and then add 0.5

3. Since we added 0.5 we need to find the floor of the temp

4. return the decimal by dividing by the multiple

multiple = pow(10.0, precision);
value = floor(num * multiple +0.5) / multiple;

Link to comment
Share on other sites

  • 0

I think setprecision does round properly, though. That's not the main problem.

The real problem is that computers cannot represent floating points perfectly. Try this small modification to your code:

(This produces the right answer on my compiler)

#include <iostream>
#include <iomanip>

using namespace std;

int main() {
   double x = 5.555;
   x += 0.000000001;
   cout <<  "x is " << fixed << setprecision(2) << x << endl;
   return 0;	
}

The computer stores 5.555 as something like 5.55499999999876, which rounds down to 5.55.

You can fix such cases by always adding something small, like 10^-9.

Unfortunately this can be extremely unpredictable - for example HeartsOfWar's manual rounding code works anyway.

(It might not work for some other case though, I dunno)

For more information you can check the wikipedia article:

http://en.wikipedia.org/wiki/Floating_poin...curacy_problems

Link to comment
Share on other sites

  • 0

Ok, thanks for the help guys. I was misled by my university notes; they were a bit vague on this sort of thing. Anyway, both of your methods work for me but I will use HeartsOfWar's code because I know it won't produce any inconsistencies. Thanks for the extra information .v3. I was completely stumped as to why it would round up some numbers but not others.

Link to comment
Share on other sites

  • 0

Actually, after some extra fiddling it seems setprecision IS messed up :| (it actually doesn't round up things that end in .5)

But the stuff about imprecision still holds (Most of the time it doesn't matter though :))

Beware:

#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;

int main()
{
	double num = 1.255;
	double multiple = pow(10.0, 2);
	double value = floor(num * multiple + 0.5) / multiple;
	cout << value << endl;
}

This outputs 1.25 in my version of g++ :p

Edited by .v3
Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.