2011-04-21 143 views
5

我有一個Python float,我想要float這是1 ULP s越來越小。Python是否具有與java.lang.Math.nextUp等效的功能?

在Java中,我會用Math.nextUp(x)Math.nextAfter(x, Double.NEGATIVE_INFINITY)來做到這一點。

有沒有辦法在Python中做到這一點?我想用math.frexp and math.ldexp自己來實現它,但據我所知Python沒有指定浮點類型的大小。

+1

同樣的問題在這裏問:http://bytes.com/topic/python/answers/739926-next-float,具有很好的答案... – Benjamin 2011-04-21 20:05:35

回答

1

我不確定這是不是你想要的,但是sys.float_info.epsilon是「1和大於1的最小值之間的差值」,你可以做x * (1 + sys.float_info.epsilon)

http://docs.python.org/library/sys.html#sys.float_info

+1

這是一個相關的想法,但不正是我想要的。從本質上說,0的指數是正確的,但對於較小的指數它太大,對於較大的指數太小。感謝您指出'sys.float_info'。至少在這種結構下,我可以可靠地確定底層浮點類型的大小,即使我仍然必須猜測它是IEEE-754。有了這個,我可以根據@Benjamin的建議,特別是結構模塊,制定解決方案。 – rlibby 2011-04-22 02:38:50

+0

'x + epsilon'?那不就是'x *(1 + epsilon)'嗎? – vartec 2011-04-22 14:34:54

+0

@vartec我不知道,但我在答案中糾正了它。 – 2011-04-23 23:37:16

2

你可以看看如何Decimal.next_plus()/Decimal.next_minus()實現:

>>> from decimal import Decimal as D 
>>> d = D.from_float(123456.789) 
>>> d 
Decimal('123456.789') 
>>> d.next_plus() 
Decimal('123456.789') 
>>> d.next_minus() 
Decimal('123456.789') 
>>> d.next_toward(D('-inf')) 
Decimal('123456.789') 

確保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]) 

的替代品:

  • 呼叫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

    >>> 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,考慮到邊緣情況。結果在這種情況下是相同的。

+0

它看起來不錯,需要一些波蘭語 - 因爲在python中的float有53位的尾數http://docs.python。組織/ 2 /教程/ floatingpoint.html。我認爲更好的是使用frexp ldexp - 可以更快。 – Chameleon 2013-11-27 15:10:07

+0

@Chameleon:是的。你可以使用'frexp()'''ldexpr()'找到「next after」。 – jfs 2017-01-14 14:58:31

相關問題