Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems casting NAN floats to int

Tags:

Ignoring why I would want to do this, the 754 IEEE fp standard doesn't define the behavior for the following:

float h = NAN;
printf("%x %d\n", (int)h, (int)h);

Gives: 80000000 -2147483648

Basically, regardless of what value of NAN I give, it outputs 80000000 (hex) or -2147483648 (dec). Is there a reason for this and/or is this correct behavior? If so, how come?

The way I'm giving it different values of NaN are here: How can I manually set the bit value of a float that equates to NaN?

So basically, are there cases where the payload of the NaN affects the output of the cast?

Thanks!

like image 583
Chris Avatar asked Apr 28 '12 18:04

Chris


People also ask

Can a float can be cast into an int?

A float value can be converted to an int value no larger than the input by using the math. floor() function, whereas it can also be converted to an int value which is the smallest integer greater than the input using math.

What will happen if you cast a float to an integer?

Casting a float to an integer truncates the value, so if you have 3.999998 , and you cast it to an integer , you get 3 . The way to prevent this is to round the result.

Can NaN be an integer?

No, NaN is a floating point value. Every possible value of an int is a number.

How do I fix NaN error in Python?

We can replace NaN values with 0 to get rid of NaN values. This is done by using fillna() function. This function will check the NaN values in the dataframe columns and fill the given value.


2 Answers

The result of a cast of a floating point number to an integer is undefined/unspecified for values not in the range of the integer variable (±1 for truncation).

Clause 6.3.1.4:

When a finite value of real floating type is converted to an integer type other than _Bool, the fractional part is discarded (i.e., the value is truncated toward zero). If the value of the integral part cannot be represented by the integer type, the behavior is undefined.

If the implementation defines __STDC_IEC_559__, then for conversions from a floating-point type to an integer type other than _BOOL:

if the floating value is infinite or NaN or if the integral part of the floating value exceeds the range of the integer type, then the "invalid" floating- point exception is raised and the resulting value is unspecified.

(Annex F [normative], point 4.)

If the implementation doesn't define __STDC_IEC_559__, then all bets are off.

like image 166
Daniel Fischer Avatar answered Sep 23 '22 02:09

Daniel Fischer


There is a reason for this behavior, but it is not something you should usually rely on.

As you note, IEEE-754 does not specify what happens when you convert a floating-point NaN to an integer, except that it should raise an invalid operation exception, which your compiler probably ignores. The C standard says the behavior is undefined, which means not only do you not know what integer result you will get, you do not know what your program will do at all; the standard allows the program to abort or get crazy results or do anything. You probably executed this program on an Intel processor, and your compiler probably did the conversion using one of the built-in instructions. Intel specifies instruction behavior very carefully, and the behavior for converting a floating-point NaN to a 32-bit integer is to return 0x80000000, regardless of the payload of the NaN, which is what you observed.

Because Intel specifies the instruction behavior, you can rely on it if you know the instruction used. However, since the compiler does not provide such guarantees to you, you cannot rely on this instruction being used.

like image 21
Eric Postpischil Avatar answered Sep 24 '22 02:09

Eric Postpischil