Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is float.MaxValue 0xFF 0xFF 0x7F 0x7F and not 0x7F, 0xFF, 0xFF, 0xFF like ints?

I guess this needs little extra information. But, why is it that way?

(This assumes the 23 bit float type is base on IEEE 754 32 bit binary floating point, and Little Endianness.)

In 32bit ints it's pretty straightforward, since:

int.MaxValue = 0x7FFFFFFF = 01111111 11111111 11111111 11111111 = 2147483647

In floats:

0x7FFFFFFF = 01111111 11111111 11111111 11111111 = 2.14748365E+9

I get the E+9 notation. But why is it that:

float.MaxValue = 0xFFFF7F7F = 11111111 11111111 01111111 01111111 = 3.40282347E+38

like image 901
AStackOverflowUser Avatar asked Nov 11 '13 07:11

AStackOverflowUser


2 Answers

You said:

int.MaxValue = 0x7F, 0xFF, 0xFF, 0xFF = 01111111 11111111 11111111 11111111 = 2147483647

int.MaxValue is indeed 2147483647 because this is a 32-bit value, signed and encoded in two’s complement, which is valued this way in your case:

value = -231b31 + b30•230 + b29•229 + … + b0•20 = 2147483647 (as all bits b0 to b30 are 1 and b31 is 0).

You said:

In floats: 0x7F, 0xFF, 0xFF, 0xFF = 01111111 11111111 11111111 11111111 = 2.14748365E+9

That’s slightly incorrect. What you've done is convert int.MaxValue to float (you’ve not interpreted the encoding of the max int value as float — you’ve changed representations) which is:

2.14748365E+9 ≈ 2147483647 = 2147483647.0 — all the same stuff for humans, but floating-point values and integers are encoded in memory differently

but

2147483647.0’s hex representation (when rounded to a float) is 0x4f000000 not 0x7F, 0xFF, 0xFF, 0xFF.

Here is why (single precision floating point format):

enter image description here

0x4f000000 is valued as (-1)0•(1+0)•2158-127 = 1•1•231 = 231 = 2147483648.0

You may check yourself here online IEE754 converter.

You also said:

float.MaxValue = 0xFF 0xFF 0x7F 0x7F = 11111111 11111111 01111111 01111111 = 3.40282347E+38

The 3.40282347E+38 value is correct, but its hex representation is not 0xFF 0xFF 0x7F 0x7F but 0x7f7fffff.

You may decode 0x7f7fffff this way:

(-1)0•(1+2-1+2-2+2-3+…+2-23)•2254-127 = 1•(1+1)•2127, which is approximately 2•2127 = 2128 ≈ 3.40282347E+38.

You may wonder why the exponent is 254 and not 255. Exponent value 255 is a special case, and values with the exponent set to 255 are treated as +infinity or -infinity (depending on sign bit) if the significand (fraction) field is zero and as NaNs if the significand field is not zero.

like image 112
Artur Avatar answered Nov 15 '22 01:11

Artur


It looks like your endianness is confused. The maximum single precision (32-bit) IEEE-754 float value is composed of:

  • one sign bit, which is zero for positive numbers
  • eight bits of exponent, which cannot be all ones (since that would mean the value was NaN), so the maximum value is 11111110 = 254 (biased) = 127 (actual exponent)
  • 23 bits of mantissa, of which the maximum value would be all ones

So I would expect the maximum single-precision float value to look like 0x7F7FFFFF.

like image 43
Daniel Pryden Avatar answered Nov 15 '22 01:11

Daniel Pryden