4

When I try to store large number into a float like float varr = 123456789; the variable varr has value of 123456792.0 not 123456789.0 as I expected. Why?

Is there any solution for this?

I cannot use double or decimal since I'm restricted to 4 bytes in memory.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Almir
  • 1,158
  • 8
  • 9

4 Answers4

1

This is because of the limited precision of a float variable. Use double instead.

As you can see here, float has only a precision of 7 digits, whereas double has 13: http://msdn.microsoft.com/en-us/library/b1e65aza%28v=vs.80%29.aspx

With four bytes of memory you can express approx. 4 Billion different values, i.e. a decimal number with 9 digits. You must ask yourself whether the numbers you want to display fit into that range. E.g. if you have number from 0 to 999 999 999 to store, four bytes are enough. If you have number from 1 000 000 000 to 1 999 999 999 then it is also enough. In this case you need to convert the input number (a double) to an integer by subtracting 1 000 000 000. When reading the value you can perform the inverse.

This principle can be extended to display other ranges of number or larger ranges with less precision. But you have to code the conversion by yourself.

Kit Fisto
  • 4,385
  • 5
  • 26
  • 43
1

If you need more precision you could use double or decimal.
Anyway remember that a floating point number is always approximated.

Marco
  • 56,740
  • 14
  • 129
  • 152
0

The precision of float type implies this limitation. You can use double type instead.

float type in C# conforms to the IEEE 754-2008 binary32 format (Single-precision floating-point format)

From Wikipedia:

The IEEE 754 standard specifies a binary32 as having:

  • Sign bit: 1 bit
  • Exponent width: 8 bits
  • Significand precision: 24 (23 explicitly stored)

This gives from 6 to 9 significant decimal digits precision (if a decimal string with at most 6 significant decimal is converted to IEEE 754 single precision and then converted back to the same number of significant decimal, then the final string should match the original; and if an IEEE 754 single precision is converted to a decimal string with at least 9 significant decimal and then converted back to single, then the final number must match the original).

Sign bit determines the sign of the number, which is the sign of the significand as well. Exponent is either an 8 bit signed integer from −128 to 127 (2's Complement) or an 8 bit unsigned integer from 0 to 255 which is the accepted biased form in IEEE 754 binary32 definition. For this case an exponent value of 127 represents the actual zero. The true significand includes 23 fraction bits to the right of the binary point and an implicit leading bit (to the left of the binary point) with value 1 unless the exponent is stored with all zeros. Thus only 23 fraction bits of the significand appear in the memory format but the total precision is 24 bits (equivalent to log10(224) ≈ 7.225 decimal digits).

BTW, I don't get your result. I run this code:

float varr = 123456789;
Console.WriteLine(varr.ToString("#"));

and my output is 123456800.

Mohammad Dehghan
  • 17,853
  • 3
  • 55
  • 72
0

If you can use integers (int), with 32-bit integers (4 bytes), you can store that number, and you won't get any precision problems.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Thomas Padron-McCarthy
  • 27,232
  • 8
  • 51
  • 75