3

The question is not aswered in Increment a python floating point value by the smallest possible amount difference:

 1. **[Increment a python floating point value by the smallest possible amount][1] just not works try this code**:

import math
epsilon  = math.ldexp(1.0, -53) # smallest double that 0.5+epsilon != 0.5
maxDouble = float(2**1024 - 2**971)  # From the IEEE 754 standard
minDouble  = math.ldexp(1.0, -1022) # min positive normalized double
smallEpsilon  = math.ldexp(1.0, -1074) # smallest increment for doubles < minFloat
infinity = math.ldexp(1.0, 1023) * 2

def nextafter(x,y):    
    """returns the next IEEE double after x in the direction of y if possible"""
    if y==x:
       return y         #if x==y, no increment

    # handle NaN
    if x!=x or y!=y:
        return x + y       

    if x >= infinity:
        return infinity

    if x <= -infinity:
        return -infinity

    if -minDouble < x < minDouble:
        if y > x:
            return x + smallEpsilon
        else:
            return x - smallEpsilon  

    m, e = math.frexp(x)        
    if y > x:
        m += epsilon
    else:
        m -= epsilon

    return math.ldexp(m,e)

print nextafter(1e307, 1e308), 'nextafter(1e307, 1e308)'
print nextafter(1e308, 1e307), 'nextafter(1e308, 1e307)'

Results is invalid:

1e+307 nextafter(1e307, 1e308) # invalid 2e307 possible!!!
1e+308 nextafter(1e308, 1e307) # invalid 9e307 possible!!!

it was not asked how to add/substract the smallest value but was asked how to add/substract value in specific direction - propose solution is need to know x and y. Here is required to know only x. 2. propose solution in Increment a python floating point value by the smallest possible amount will not work on border conditions.


I want to add/substract for any float some smallest values which will change this float value about one bit of mantissa/significant part. How to calculate such small number efficiently.

For example I have such array of x:

xs = [1e300, 1e0, 1e-300]

What will be function for it to generate the smallest value? All assertion should be valid.

for x in xs:
  assert x < x + smallestChange(x)
  assert x > x - smallestChange(x)

Consider that 1e308 + 1 == 1e308 since 1 does means 0 for mantissa so `smallestChange' should be dynamic.

Community
  • 1
  • 1
Chameleon
  • 9,722
  • 16
  • 65
  • 127
  • @JohnY Checked http://stackoverflow.com/questions/6063755/increment-a-python-floating-point-value-by-the-smallest-possible-amount 1e308 will not work with epsilon since to small to increment. Want use pure python without *dirty tricks*. – Chameleon Nov 27 '13 at 14:28
  • @JohnY Example is good `math.frexp` and `math.ldexp` should used. – Chameleon Nov 27 '13 at 14:52
  • @JohnY You marked it wrong as duplicate - see your suggested code not works try 1e308, 1e307 it will fail tests. – Chameleon Nov 27 '13 at 16:10

1 Answers1

0

Try using hex:

>>> float.hex(3740.0)
'0x1.d380000000000p+11'

Edit the hex string and:

>>> float.fromhex('0x1.d380000000001p+11')
3740.0000000000005

This uses the reverse of the example in the docs.

A longer answer:

n = 1e+300
h = float.hex(n)
print h
i = h.find('.')
if i < 0:
    print h, 'is not a float'
else:
    j = h.find('p')
    n1 = int(h[i+1:j], base=16)
    a = n
    while a == n:
        n1 += 1
        a = float.fromhex(h[:i+1] + hex(n1)[2:j-i+1] + h[j:])
    print a-n
f p
  • 3,165
  • 1
  • 27
  • 35