Update:在Python 3.9+中有math.nextafter() https://docs.python.org/3/library/math.html#math.nextafter:
>>> import math
>>> x = 4
>>> math.nextafter(x, math.inf)
4.000000000000001
Old answer:
你可以看看如何Decimal.next_plus()/Decimal.next_minus() http://hg.python.org/cpython/file/fecf9e6d7630/Lib/decimal.py#l3448已实施:
>>> 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')
确保十进制上下文 http://docs.python.org/library/decimal.html#decimal.Context有您需要的值:
>>> from decimal import getcontext
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999,
capitals=1, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
备择方案:
-
Call C99 nextafter() https://stackoverflow.com/a/6163157/4279 using 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)
Using numpy
:
>>> import numpy
>>> numpy.nextafter(4, float('+inf'))
4.0000000000000009
>>> _.as_integer_ratio()
(4503599627370497, 1125899906842624)
尽管不同repr()
, 结果是一样的。
-
如果我们忽略边缘情况,那么一个简单的 frexp/ldexp 解决方案来自@S.Lott 回答 https://stackoverflow.com/a/6064066/4279 works:
>>> 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)
-
纯Pythonnext_after(x, y)由 @Mark Dickinson 实施 https://stackoverflow.com/a/10426033/4279考虑到边缘情况。在本例中结果是相同的。