0

I know when converting some numbers from binary to floating point there can be problems.

For example: 1.4 results in 1.39999. 6.2 is 6.1999999, 6.6 is 6.599999, etc.

Is there a way to calculate which numbers will cause these problems? Like create some sort of spreadsheet or database with numbers from 1-50,000 which don't convert exactly?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user2039871
  • 153
  • 1
  • 1
  • 9
  • What do you mean by converting from binary to floating point? At the end of the day, everything is stored in binary. FLoating point is just one example of a binary format. – paul Feb 04 '13 at 14:25
  • I mean on a calculator like this: http://www.h-schmidt.net/FloatConverter/IEEE754.html When you enter decimal 6.2 you get 6.1999 – user2039871 Feb 04 '13 at 14:27
  • Even if you were to have such a list, you can hardly _avoid_ these numbers forever. In a context where you're calculating with increasingly error-prone calculations and conversions, you should use the `decimal` data type and stay clear of `float`. – Wim Ombelets Feb 04 '13 at 15:12
  • The reason I want a list is because this is for a CNC machine where we may manual enter a feed rate or something. A list of numbers 1-1000 would even be helpful. Is it possible to create such a thing? – user2039871 Feb 04 '13 at 16:04

2 Answers2

1

The errors in floating point calculations are rooted in the way that floating point numbers are stored. Depending on which precision you are using (usually either single (float) or double-precision). Double-precision floats take more space, but are roughly twice as precise.

Floating point numbers are typically stored in an IEEE format and thus only the most significant bits are included.

In a string of bits stored in this way to represent a floating point number, there are different parts that comprise the number. First, there is a sign bit indicating whether the number is positive or negative. Next, the exponent portion of the number is stored (in single-precision floats, this takes 8 bits). After the exponent, all remaining bits represent the significant digits of the number. Thus, the bits 1 10000000 01000000000000000000000 represent -0.5 The sign bit (first one) signifies that the number is negative. The next eight bits are the exponent. Usually, the exponent is stored with a bias so that small numbers may be stored precisely in addition to large ones. To do this, the exponent used for calculations is -127 (if an 8 bit exponent) + the exponent bits interpreted as an integer (in our case 128). All remaining bits signify the significant digits of the number starting with the ones place and moving rightward from there we cut the value in half each time (1 is 1, but 01 is 1/2 and 001 is 1/4) in our case the total number is -0.5 (-1 for the sign bit * 2^1 for the exponent * 0.5 for the remaining bits)

For further example, here is a converter that uses checkboxes to indicate the bits. At worst, you could write a bot to test all of the combinations you care about.

In general, if it cannot be described with a fraction that is not directly made of combinations of powers of two, it will be rounded. (If you can't get it with 1/2 + 1/4 + 1/8 etc. it will probably be rounded)

Psetmaj
  • 437
  • 4
  • 6
  • Yes I am familiar with this page. I just want to find a way to document all of the numbers that have an issue for a certain range. I am using this for CNC programming, and when we enter 6.2, the machine won't actually run. So I want to document the problem #'s in a database/spreadsheet – user2039871 Feb 04 '13 at 16:21
  • It might be easier to find the numbers you can use rather than the ones you cannot. In that direction, you could automate this by trying each bit pattern for the numbers in the range you desire and storing the result as a number you can use. Otherwise, you could probably choose a scale at which you want to know which numbers will round (e.g. 1.1, 1.2, 1.3, 1.4, ... or 1.01, 1.02, 1.03, ...) and try them entering the ones that when converted to a String are not the same as the ones you entered as bad numbers. – Psetmaj Feb 05 '13 at 02:25
0

Almost all numbers are troublesome. The minor exception are those, that when repeatedly multiplied by 2 get rid of the fractional part and end up being less than 2^24.

e.g.

0.125 -> 0.25 -> 0.5 -> 1.0 !  OK
6.4 --> 12.8 --> 25.6 -> 51.2 -> 102.4 : we got a cycle! (.4 .8 .6 .2 ... )

EDIT

Given the purpose/context of the issue, the inexactness seems to cause trouble when the floating point is rounded towards zero.

e.g.

10.2 == 10.199999809, when the next floating point would be  
next == 10.200000763  <-- the difference to the wanted value is ~4 times higher
vs.
10.3 == 10.300000197, when the previous (rounded down fp would be)
prev == 10.299992370, <-- this would have been also ~4x further from away

Perhaps it's time to talk to the programmer of the CNC driver...

Aki Suihkonen
  • 19,144
  • 1
  • 36
  • 57
  • So its basically any decimal. .1, .2, .3, etc. They all are not exact – user2039871 Feb 04 '13 at 16:28
  • except for .5. All others have infinite binary digit expansion, but then again many of them have enough zeroes after the point of truncation so they end up to be printed correctly enough. – Aki Suihkonen Feb 04 '13 at 20:14