Python是否与java.lang.Math.nextUp等价? [英] Does Python have an equivalent to java.lang.Math.nextUp?

查看:143
本文介绍了Python是否与java.lang.Math.nextUp等价?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Python float ,我想要 float s,它们是1 ULP 越大越小。

在bc中,我会使用 Math.nextUp(x) Math.nextAfter(x,Double.NEGATIVE_INFINITY)



有没有办法在Python中做到这一点?我以为自己用 math.frexp math.ldexp ,但据我所知Python没有指定浮点类型的大小。

解决方案

你可以看看 Decimal.next_plus() / Decimal.next_minus() 被执行:

 >>>从十进制输入十进制为D 
>>> d = D.from_float(123456.78901234567890)
>>> d
十进制('123456.789012345674564130604267120361328125')
>>> d.next_plus()
十进制('123456.7890123456745641306043')
>>> d.next_minus()
十进制('123456.7890123456745641306042')
>>> d.next_toward(D(' - inf'))
十进制('123456.7890123456745641306042')

确保十进制上下文具有您需要的值:

 >>> from decimal import getcontext 
>>> getcontext()
Context(prec = 28,rounding = ROUND_HALF_EVEN,Emin = -999999999,Emax = 999999999,
capitals = 1,flags = [],陷阱= [InvalidOperation,DivisionByZero,Overflow])






替代方案:


I have a Python float, and I want to have the floats which are 1 ULP greater and lesser.

In Java, I would do this with Math.nextUp(x) and Math.nextAfter(x, Double.NEGATIVE_INFINITY).

Is there a way to do this in Python? I thought about implementing it myself with math.frexp and math.ldexp but as far as I know Python doesn't specify the size of floating point types.

解决方案

You could look at how Decimal.next_plus()/Decimal.next_minus() are implemented:

>>> 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')

Make sure that decimal context has values that you need:

>>> from decimal import getcontext
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999,
capitals=1, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])


Alternatives:

  • Call C99 nextafter() 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)
    

    Despite different repr(), the result is the same.

  • If we ignore edge cases then a simple frexp/ldexp solution from @S.Lott answer 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)
    

  • pure Python next_after(x, y) implementation by @Mark Dickinson that takes into account edge cases. The result is the same in this case.

这篇关于Python是否与java.lang.Math.nextUp等价?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆