0

Is it true that the last non-zero digit to the right of the decimal point in a non whole number float is always 5? Can/has someone prove[ed] this formally? Also, how many 0s in a row to the right of the decimal point are needed to conclude that there are no more non-zero digits farther to the right--I have seen #s such as 1.23450678500000 (an example, probably not a real float), so I know it is at least two.

Andrew
  • 1
  • 4
  • 19

2 Answers2

2

Is it true that the last non-zero digit to the right of the decimal point in a non whole number float is always 5?

In a binary floating-point format, if a number is not an integer, the last non-zero digit of its decimal numeral is 5.

Generally, a floating-point format represents numbers as some integer M multiplied by power e of a fixed-base b: Mbe, with various limits on M and e. If b is two, we call this a binary format. Binary floating-point formats are currently the most common. Some platforms provide decimal formats, where b is 10. Other bases are mathematically possible but rarely used, although 16 was somewhat used in the past.

To see the last digit is 5, consider the form Mbe. The only way this can be a non-integer is for e to be negative. If M is even, we can reduce the form to (M/2)•be−1, and, if M/2 is also even, we can reduce further and continue reducing until we have an odd integer multiplied by a negative power of 2. This is equivalent to dividing by a positive power of 2. Then we can see that the last digit is 5:

  • If we are dividing by 21, the number is .5, 1.5, 2.5, 3.5, and so on.
  • If we are dividing by 22, the number is half of one of those, so it is .25, .75, 1.25, 1.75, and so on.
  • If we are dividing by any greater power of 2, we are always dividing some number that ends in 5 by 2, and that means we carry the ½ fraction from the position where the 5 is to the next position, producing half of 10 there, and half of 10 is 5.

Alternately, we can see that multiplying a numeral by 2, even repeatedly, can never make a digit position 0 unless it is 0 or 5. Multiplying 1, 2, 3, 4, 6, 7, 8, or 9, will produce 2, 4, 6, 8, 2, 4, 6, and 8, respectively, and multiplying those by 2 produces a digit from the same set. So, if a non-integer multiplied by a power of 2 produces an integer, its last non-zero digit must be 5.

Also, how many 0s in a row to the right of the decimal point are needed to conclude that there are no more non-zero digits farther to the right…

This depends on the specific floating-point format. A high-precision format can represent numbers that are very close to some number .xxxx500 but not equal to it. For any given floating-point format, there must be some limit to the number of zeros there can be before a non-zero digit, but it may require some work to figure it out. If you have concerns about finding the number of digits required to represent a floating-point number accurately, there are other ways to approach it.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • regarding the second Q: v1=0.0625000000000000277555756156289135105907917022705078125, v2=0.06250000000000001387778780781445675529539585113525390625, both are exact (maybe this second question should be an independent Q~how can a mere mortal conclude from inspection (vs actual conversion) that a non whole number float is displayed exactly? ) – Andrew Aug 09 '21 at 08:30
0

Regarding the 2nd question (narrated): >>> v 1.5000005 # OK

>>> print("%f") % (v)
1.500001
**# Maybe not...**

>>> print("%.15f") % (v)
1.500000500000000
**# Ends in 5, so OK now, right?  No! It should've rounded to even.  Huh?**

>>> print("%.16f") % (v)
1.5000005000000001
**# "16 decimal digits is accuracy", I learned in school** 

>>> print("%.31f") % (v)
1.5000005000000000698889834893635
**#NOT SO FAST; but now I found the real value since it ends in 5--see, "I'm smart, and I want respect" (Fraedo)**

>>> print("%.2000f") % (v)
1.50000050000000006988898348936345428228378295898437500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
**# I should have listened to mom, and been a Mail Man! (are there yet more lurking non-zero digits???)**
Andrew
  • 1
  • 4
  • 19
  • A value `x` representable in IEEE 754 binary64 format and satisfying `2**(e-1) <= x < 2**e` needs at most `max(53 - e, 0)` digits after the point to represent exactly in decimal. So for example for `x` in `[0.5, 1.0)` you need at most 53 digits after the point; for `x` in `[0.25, 0.5)` at most 54 digits; for `x` in `[1.0, 2.0)` at most 52 digits, and so on. You may also be interested to know that for IEEE 754 binary64 format, the maximum number of consecutive zeros (bracketed by nonzero digits at both ends) in any decimal expansion is 20. See https://stackoverflow.com/q/20273877/270986. – Mark Dickinson Aug 09 '21 at 18:31