Python是否有类似java.lang.Math.nextUp的方法?
我有一个Python中的float
(浮点数),我想得到比这个浮点数大1个ULP(单位在最后一位)和小1个ULP的浮点数。
在Java中,我可以用Math.nextUp(x)
来获取比x大的下一个浮点数,使用Math.nextAfter(x, Double.NEGATIVE_INFINITY)
来获取比x小的下一个浮点数。
那么在Python中有没有类似的方法呢?我考虑过用math.frexp
和math.ldexp
自己实现,但我知道Python并没有规定浮点数的大小。
2 个回答
1
我不确定这是不是你想要的,但 sys.float_info.epsilon
是“1和能表示为浮点数的比1稍大的最小值之间的差”,你可以这样做 x * (1 + sys.float_info.epsilon)
。
5
更新: 在 Python 3.9 及以上版本中,有一个新的功能 math.nextafter()
:
>>> import math
>>> x = 4
>>> math.nextafter(x, math.inf)
4.000000000000001
旧答案:
你可以看看 Decimal.next_plus()
/Decimal.next_minus()
是怎么实现的:
>>> 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')
确保 小数上下文 中有你需要的值:
>>> from decimal import getcontext
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999,
capitals=1, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
其他选择:
使用 C99 的
nextafter()
,通过ctypes
调用:>>> 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
:>>> import numpy >>> numpy.nextafter(4, float('+inf')) 4.0000000000000009 >>> _.as_integer_ratio() (4503599627370497, 1125899906842624)
尽管
repr()
的表现不同,但结果是一样的。如果忽略一些特殊情况,那么来自 @S.Lott 的答案 中的简单 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)
@Mark Dickinson 提供的纯 Python
next_after(x, y)
实现,考虑了特殊情况。在这种情况下,结果是一样的。