参见英文答案 > Increment a python floating point value by the smallest possible amount 14个
我有一个Python浮点数,我希望浮点数大于和小于1 ULP.
在Java中,我将使用Math.nextUp(x)
和Math.nextAfter(x,Double.NEGATIVE_INFINITY)
执行此操作.
有没有办法在Python中执行此操作?我想过用math.frexp
and math.ldexp
自己实现它,但据我所知Python并没有指定浮点类型的大小.
最佳答案
你可以看一下
Decimal.next_plus()
/Decimal.next_minus()
是如何实现的:
@H_301_14@>>> from decimal import Decimal as D
>>> d = D.from_float(123456.78901234567890)
>>> d
Decimal('123456.789012345674564130604267120361328125')
>>> d.next_plus()
Decimal('123456.7890123456745641306043')
>>> d.next_minus()
Decimal('123456.7890123456745641306042')
>>> d.next_toward(D('-inf'))
Decimal('123456.7890123456745641306042')
确保decimal context具有您需要的值:
@H_301_14@>>> from decimal import getcontext
>>> getcontext()
Context(prec=28,rounding=ROUND_HALF_EVEN,Emin=-999999999,Emax=999999999,capitals=1,flags=[],traps=[InvalidOperation,DivisionByZero,Overflow])
备择方案:
>使用ctypes调用C99 nextafter()
:
>>> import ctypes
>>> nextafter = ctypes.CDLL(None).nextafter
>>> nextafter.argtypes = ctypes.c_double,ctypes.c_double
>>> nextafter.restype = ctypes.c_double
>>> nextafter(4,float('+inf'))
4.000000000000001
>>> _.as_integer_ratio()
(4503599627370497,1125899906842624)
使用numpy:
@H_301_14@>>> import numpy
>>> numpy.nextafter(4,float('+inf'))
4.0000000000000009
>>> _.as_integer_ratio()
(4503599627370497,1125899906842624)
尽管repr()不同,但结果是一样的.
>如果我们忽略边缘情况,那么@S.Lott answer的简单frexp / ldexp解决方案可以工作:
>>> import math,sys
>>> m,e = math.frexp(4.0)
>>> math.ldexp(2 * m + sys.float_info.epsilon,e - 1)
4.000000000000001
>>> _.as_integer_ratio()
(4503599627370497,1125899906842624)
> pure Python next_after(x,y)
implementation by @Mark Dickinson考虑边缘情况.在这种情况下结果是相同的.