views:

88

answers:

3

Possible Duplicate:
Why don't operations on double-precision values give expected results?

I am experiencing a peculiar problem in C++. I created a variable of type Double. Then I did some calculations with some values assigned to other variables and assigned the result to the double variable I declared. It gave me a result with a long decimal part. I want it to round to only 2 decimal places. and store it into the variable. But even after several attempt rounding, I couldnt round it to 2 decimal places.

Then I tried another way to check what the real problem is. I created a Double variable and assigned it the value 1.11. But when I debugged it by putting a break point and added a watch for that variable, I could find that the value now stored in the variable is 1.109999999999.

My question is, why is it showing like that? Isnt there any way in which we can round the variable into two decimal places? Why is it showing a long decimal part even if we assign a number with just two decimal places?

Please suggest a way to store numbers - whether it is calculated or directly assigned - as it is, in a double variable rather than a number with a long decimal part.

+6  A: 

In the set of double values, there is no such thing as the number 1.11 because internally, double uses a binary representation (as opposed to humans who are used to a decimal representation). Most finite decimal numbers (such as 1.11) have an infinite representation in binary, but since memory is limited, you lose some precision because of rounding.

The closest you can get to 1.11 with the double data type is 1.1100000000000000976996261670137755572795867919921875, which is internally represented as 0x3ff1c28f5c28f5c3.

Your requirement of two decimal places sounds like you are working with money. A simple solution is to store the cents in an integer (as opposed to the dollars in a double):

int cents = 111;

This way, you don't lose any precision. Another solution is to use a dedicated decimal data type.

FredOverflow
+2  A: 

Not every decimal number has an exact, finite, binary floating-point representation. You've already found one example, but another one is 0.1 (decimal) = 0.0001100110011... (binary).

You either need to live with that, or use a decimal floating-point library (which will be less efficient).

My recommendation would be to store numbers to full precision, and only round when you need to display them to humans.

Oli Charlesworth
That depends on usage. Financial institutions take a dim view on any rounding errors (especially if it benefits the customer). Thus if you are doing anything with money you need a decimal type.
Martin York
+1  A: 

the floating-point types like float and double are not 100% precise. They may store 14.3 as 14.299999... and there is nothing wrong about that. That is why you should NEVER compare two floats or doubles with == operator, instread you should check if the absolute value of their difference is smaller than a certain epsilon, like 0.000000001

Now, if you want to output the number in a pleasant way, you can use setprecision from <iomanip>

E.g.

#include <iostream>
#include <iomanip>

int main()
{
   double d = 1.389040598345;
   std::cout << setprecision(2) << d; //outputs 1.39
}

If you want to obtain the value of d rounded 2 decimal places after the point, then you can use this formula

d = floor((d*100)+0.5)/100.0; //d is now 1.39
Armen Tsirunyan
Casting to `int` is a very bad idea, because most double values are too large to fit in the set of integers. I suggest calling `floor` instead.
FredOverflow
@FredOverflow: Ok, agree, changing
Armen Tsirunyan