Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If I copy a float to another variable, will they be equal?

People also ask

Can we compare float values?

To compare two floating point or double values, we have to consider the precision in to the comparison. For example, if two numbers are 3.1428 and 3.1415, then they are same up to the precision 0.01, but after that, like 0.001 they are not same.

Is floating the same as variable?

Floating rates are carried by credit card companies and commonly seen with mortgages. Floating rates follow the market or track an index or another benchmark interest rate. Floating rates are also called variable rates.

Is it better to use double or float?

double has higher precision, whereas floats take up less memory and are faster. In general you should use float unless you have a case where it isn't accurate enough. On typical modern computers, double is just as fast as float.


Besides the assert(NaN==NaN); case pointed out by kmdreko, you can have situations with x87-math, when 80bit floats are temporarily stored to memory and later compared to values which are still stored inside a register.

Possible minimal example, which fails with gcc9.2 when compiled with -O2 -m32:

#include <cassert>

int main(int argc, char**){
    float x = 1.f/(argc+2);
    volatile float y = x;
    assert(x==y);
}

Godbolt Demo: https://godbolt.org/z/X-Xt4R

The volatile can probably be omitted, if you manage to create sufficient register-pressure to have y stored and reloaded from memory (but confuse the compiler enough, not to omit the comparison all-together).

See GCC FAQ reference:

  • Why floating-point results change with optimization levels or different compiler versions or different target architectures?

It won't be true if x is NaN, since comparisons on NaN are always false (yes, even NaN == NaN). For all other cases (normal values, subnormal values, infinities, zeros) this assertion will be true.

The advice for avoiding == for floats applies to calculations due to floating point numbers being unable to express many results exactly when used in arithmetic expressions. Assignment is not a calculation and there's no reason that assignment would yield a different value than the original.


Extended-precision evaluation should be a non-issue if the standard is followed. From <cfloat> inherited from C [5.2.4.2.2.8] (emphasis mine):

Except for assignment and cast (which remove all extra range and precision), the values of operations with floating operands and values subject to the usual arithmetic conversions and of floating constants are evaluated to a format whose range and precision may be greater than required by the type.

However, as the comments have pointed out, some cases with certain compilers, build-options, and targets could make this paradoxically false.


Yes, y will assuredly take on the value of x:

[expr.ass]/2: In simple assignment (=), the object referred to by the left operand is modified ([defns.access]) by replacing its value with the result of the right operand.

There is no leeway for other values to be assigned.

(Others have already pointed out that an equivalence comparison == will nonetheless evaluate to false for NaN values.)

The usual issue with floating-point == is that it's easy to not have quite the value you think you do. Here, we know that the two values, whatever they are, are the same.


Yes, in all cases (disregarding NaNs and x87 issues), this will be true.

If you do a memcmp on them you will be able test for equality while being able to compare NaNs and sNaNs. This will also require the compiler to take the address of the variable which will coerce the value into a 32-bit float instead of an 80-bit one. This will eliminate the x87 issues. The second assertion here is intended to fail to show that == will not compare NaNs as true:

#include <cmath>
#include <cassert>
#include <cstring>

int main(void)
{
    float x = std::nan("");
    float y = x;
    assert(!std::memcmp(&y, &x, sizeof(float)));
    assert(y == x);
    return 0;
}

Note that if the NaNs have a different internal representation (i.e. differing mantissa), the memcmp will not compare true.


In usual cases, it would evaluate to true. (or the assert statement won't do anything)

Edit:

By 'usual cases' I mean am excluding the aforementioned scenarios (such as NaN values and 80x87 floating point units) as pointed by other users.

Given the obsolesence of 8087 chips in today's context, the issue is rather isolated and for the question to be applicable in current state of floating-point architecture used, its true for all cases except for NaNs.

(reference about 8087 - https://home.deec.uc.pt/~jlobo/tc/artofasm/ch14/ch143.htm)

Kudos to @chtz for reproducing a good example and @kmdreko for mentioning NaNs - didn't knew about them before!