Why is 1.1 + 2.2 not equal to 3.3 !!!

Please explain this. I also faced this type of problems before:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  #include <iostream>
#include <cmath>
using namespace std;

int main()
{
    double a = 1.1, b = 2.2, c = 3.3;

    cout << "a + b = " << a + b << endl;
    cout << "c = " << c << endl;

    if(a + b == c) cout << "Okay!\n"; 
    else cout << "Surprise!\n"; // this is executed

    return 0;
}


The output is quite surprising:
a + b = 3
c = 3
Surprise!
Last edited on
1.1 + 2.2 Is equal to 3.3. But From what I understand, and someone will correct me if Im wrong. You can't compare two floats/doubles in c++, because there is rounding problems. I debugged your program (Something you should learn to do) and these are the a b and c values.

https://gyazo.com/9c1b4cb8441bcf5a4da0313127a03fbd

As you can see, they're not exactly 1.1,2.2, and 3.3.

You can find lots of info on how to compare floats and doubles on the net.
Last edited on
Because 1.1, 2.2 and 3.3 in base 10 can't be represented exactly in the base 2 floating point format used by your computer. For this reason, it's never a good idea to compare floating point numbers with ==. Instead of doing a == b, do fabs(a-b) < epsilon where epsilon is some very small number.
ah b/c in computer doing operation on real numbers always cause some rounding.
You may not notice the rounding but computer is in base 2 so 0.1 cannot really be represented perfectly nor 0.2 and 0.3 but 0.25 can be that's because 0.25 is 2^-2. If you want to know more I may explain more just ask.

So comparision is usually done this way

1
2
3
4
 
#define epsilon 0.0000001

if( fabs( a + b - c ) < epsilon )


Hell yeah 2 people is way quicker than me lolololol this forum is quite crowded today.
Last edited on
Yes, tell me all you know about this, please.
If you just want the conclusion skip to the last sentence of this post

so here is how real num is represented in computer according to IEEE754 standard (if you are a cs student you will learn this eventually)
there are 3 parts

sign bit
exponent bit
fraction bit

here is how they are stored perhaps you want to store 0.8 in 8 bit float
1 sign bit
3 exponent bit
4 fraction bit

first transform the decimal to binary decimal like these
0.8 * 2 = 1.6
0.6 * 2 = 1.2
0.2 * 2 = 0.4
0.4 * 2 = 0.8
0.8

take your decimal time it by 2 then see the number before dot what ever it is remove it and then replace it with 0

the resulting binary decimal is
0.11001100....

the you have to transform it to a sort of scientific form
something like the way you write number in physic
0.0000444 is 4.44 * 10^-5

0.11001100 become
1.1001100... * 2^-1

so
the sign is 0 (positive)
the exponent is -1
the fraction is 0.1001100 << i didn't miss the 1 before the dot

0.100110011000 is an infinite loop so some round would be done
become
0.1010

And the bit representation become
0 010 1010
s exp frac

which if translated back become
1.1010 * 2^-1 =
0.11010 = 1*1/2 + 1*1/4 + 0 * 1/8+ 1*1/16 = 13/16 = 0.8125

that's way it's not perfect
there must be part where it seem strange to you but I not explaining them because it would be too long.

My point is you the way computer store real number is the same as how you store scientific number in physic. There will be rounding because memory is limited.

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

int main()
{
    double a = 1.1, b = 2.2, c = 3.3;
    double sum = a + b;

    cout << setprecision(18);
    cout << "a   =   " << a   << endl;
    cout << "b   =   " << b   << endl;    
    cout << "sum =   " << sum << endl;
    cout << "c   =   " << c   << endl;
    cout << "sum - c      = " << sum - c      << endl;
    cout << "c - sum      = " << c - sum      << endl;
    cout << "abs(c - sum) = " << abs(c - sum) << endl;
    
    const double epsilon = 0.0000001;
    if (abs(c - sum) < epsilon)
        cout << "Equal\n";
    else
        cout << "Not equal\n";
    return 0;
}
a   =   1.10000000000000009
b   =   2.20000000000000018
sum =   3.30000000000000027
c   =   3.29999999999999982
sum - c      = 4.44089209850062616e-016
c - sum      = -4.44089209850062616e-016
abs(c - sum) = 4.44089209850062616e-016
Equal



In C++ the <cmath> function abs() will work. A const is preferred over #define.

Edit:
line 21 should read if (abs(c - sum) < epsilon)
Last edited on
We are used to the idea that some numbers cannot be expressed precisely in decimal notation, e.g.
1/7 = 0.142857142857142857142857142857... or
1/3 = 0.333333333333333333333333333333...

In binary a similar thing happens, but it may take us by surprise because it means decimal values such as 1.1 cannot be represented precisely, but instead have recurring sequence of digits.

You can try this out using the online converter here:
https://www.mathsisfun.com/binary-decimal-hexadecimal-converter.html
Type some decimal value into the decimal box to see its binary equivalent.
I learned that doubles can store values with ten digits of precision after decimal point. So, how did you store so precise values into double:
a = 1.10000000000000009
b = 2.20000000000000018
sum = 3.30000000000000027
c = 3.29999999999999982
I learned that doubles can store values with ten digits of precision after decimal point.

Maybe you were told they can store at least ten significant digits?
This is roughly how I understand the different floating point types:

float - about 7 decimal digits precision
double - about 15 decimal digits precision
long double - about 17 decimal digits precision


These figures are approximate because the values are stored in binary, not decimal and the behaviour will depend upon the actual value being stored.

Note also, if there are digits before the decimal point, there will be correspondingly fewer after it.
Last edited on
In C++ the <cmath> function abs() will work.

No it won't. Not even close. abs() takes an integer and returns an integer. You need to use fabs()
Topic archived. No new replies allowed.