Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a float variable stop incrementing at 16777216 in C#?

float a = 0; while (true) {     a++;     if (a > 16777216)         break; // Will never break... a stops at 16777216 } 

Can anyone explain this to me why a float value stops incrementing at 16777216 in this code?

Edit:

Or even more simple:

float a = 16777217; // a becomes 16777216 
like image 645
Jan Avatar asked Sep 26 '12 07:09

Jan


People also ask

Why is floating point not exact?

Floating-point decimal values generally do not have an exact binary representation due to how the CPU represents floating point data. For this reason, you may experience a loss of precision, and some floating-point operations may produce unexpected results.

How do you store floating numbers?

Scalars of type float are stored using four bytes (32-bits). The format used follows the IEEE-754 standard. The mantissa represents the actual binary digits of the floating-point number.

What is float variable in C?

A float variable can contain whole numbers and fractions Float is a shortened term for "floating point." By definition, it's a fundamental data type built into the compiler that's used to define numeric values with floating decimal points. C, C++, C# and many other programming languages recognize float as a data type.

How do you assign a float to a variable?

To initialize a variable with float value, use assign operator and assign the floating point value to the variable. Variable name has to be on the left hand side and the float value has to be on the right side. In the following Python program, we have initialized variables x and y with float values.


2 Answers

Short roundup of IEEE-754 floating point numbers (32-bit) off the top of my head:

  • 1 bit sign (0 means positive number, 1 means negative number)
  • 8 bit exponent (with -127 bias, not important here)
  • 23 bits "mantissa"
  • With exceptions for the exponent values 0 and 255, you can calculate the value as: (sign ? -1 : +1) * 2^exponent * (1.0 + mantissa)
    • The mantissa bits represent binary digits after the decimal separator, e.g. 1001 0000 0000 0000 0000 000 = 2^-1 + 2^-4 = .5 + .0625 = .5625 and the value in front of the decimal separator is not stored but implicitly assumed as 1 (if exponent is 255, 0 is assumed but that's not important here), so for an exponent of 30, for instance, this mantissa example represents the value 1.5625

Now to your example:

16777216 is exactly 224, and would be represented as 32-bit float like so:

  • sign = 0 (positive number)
  • exponent = 24 (stored as 24+127=151=10010111)
  • mantissa = .0
  • As 32 bits floating-point representation: 0 10010111 00000000000000000000000
  • Therefore: Value = (+1) * 2^24 * (1.0 + .0) = 2^24 = 16777216

Now let's look at the number 16777217, or exactly 224+1:

  • sign and exponent are the same
  • mantissa would have to be exactly 2-24 so that (+1) * 2^24 * (1.0 + 2^-24) = 2^24 + 1 = 16777217
  • And here's the problem. The mantissa cannot have the value 2-24 because it only has 23 bits, so the number 16777217 just cannot be represented with the accuracy of 32-bit floating points numbers!
like image 158
AndiDog Avatar answered Oct 05 '22 08:10

AndiDog


16777217 cannot be represented exactly with a float. The next highest number that a float can represent exactly is 16777218.

So, you try to increment the float value 16777216 to 16777217, which cannot be represented in a float.

like image 38
Eric J. Avatar answered Oct 05 '22 09:10

Eric J.