0

I'm learning c++ from a tutorial and there, I was told that comparing floats in c++ can be very comfusing. For example, in the below code:

#include <iostream>

using namespace std;

int main()
{
    float decimalNumber = 1.2;
    
    if (decimalNumber == 1.2){
        cout << "Equal" << endl;
    }else{
        cout << "Not equal" << endl;
    }

    return 0;
}

I would get "not equal". I agree on this point. The tutor told that If we need to compare floats, we can use > to the nearest number. (that would not be very precise). I searched for different ways to compare floats in google and I got many complex ways of doing that.

Then I created a program myself:

#include <iostream>

using namespace std;

int main()
{
    float decimalNumber = 1.2;
    
    if (decimalNumber == (float)1.2){
        cout << "Equal" << endl;
    }else{
        cout << "Not equal" << endl;
    }

    return 0;
}

After type-casting like above, I got "Equal".

The thing I want to know is that should I use the above way to compare floats in all of my programs? Does this have some cons?

Note : I know how a number is represented exactly in the memory and how 0.1 + 0.2 !- 0.3 as described in another SO Question. I just want to know that can I check the equality of two floats in the above way?

Praneet Dixit
  • 1,393
  • 9
  • 25
  • 2
    Does this answer your question? [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – G.M. Jul 31 '20 at 10:17
  • @G.M. I have viewed the question you have suggested and found it very useful, but in this question I want to know that is using the method as described in my question, should be used to compare floats as I have described. – Praneet Dixit Jul 31 '20 at 10:26
  • 1
    there is no universal answer. Your way of comparing breaks down as soon as you compare eg `0.6 + 0.6` with `1.2`. The best is to not compare floats for equality, if you still need it then it completely depends on your requirements how to best realize it – 463035818_is_not_an_ai Jul 31 '20 at 10:31

2 Answers2

2

The thing I want to know is that should I use the above way to compare floats in all of my programs?

Depends on context. Equality comparison is very rarely useful with floats.

However yes, whether you compare with equality or relationality, you should compare floating point objects of same type, instead of mixing float and double.

Does this have some cons?

Floating point calculations potentially have error. Result might not be what you expect. When there is error, then equality comparison is meaningless.

eerorika
  • 232,697
  • 12
  • 197
  • 326
1

The reason that second example works is, in a way, pure chance.

Some factors to consider:

  1. When both sides of the comparison are of type float, the compiler is probably more likely to "optimise out" the comparison so that it just happens during the compilation process. It can look at the literals and realise that the two numbers are logically the same, even though at runtime they may differ at lower levels of precision.

  2. When both sides of the comparison are of type float, they have the same precision, so if you've created the values in the same way (here, by a literal), any error in the lower levels of precision could be identical. When one of them is a double, you have additional erroring bits at the end that throw off the comparison. And if you'd created one via 0.6 + 0.6 then the result could also be different as the errors propagate differently.

In general, do not rely on this. You can't really predict how "accurate" your floats will be when they contain numbers not representable exactly in binary. You should stick to epsilon-range compares (where appropriate) if you need loose value comparison, even if direct comparison appears to "work" occasionally without it.

A good approach to take, if you don't actually need floating point, is to use fixed point instead. There are no built-in fixed-point types in the language, but that's okay because you can simulate them trivially with a little arithmetic. It's hard to know what your use case is here, but if you only need one decimal place, instead you can store int decimalNumber = 12 (i.e. shift the decimal point by one) and just divide by ten whenever you need to display it. Two ints of value 12 always compare nicely.

Money is a great example of this: count in pennies (or tenths of pennies), not in pounds, to avoid errors creeping in that scam your customers out of their cash.

Asteroids With Wings
  • 17,071
  • 2
  • 21
  • 35