SORU
19 Mayıs 2011, PERŞEMBE


Artım mümkün olan en küçük miktarda python kayan nokta değeri

Sözlük anahtarları olarak kayan nokta değerleri kullanıyorum.

Bazençokzaman zaman (belki de asla, ama asla değil), çarpışma olacak. Mümkün olduğunca küçük bir miktar tarafından kayan nokta değeri artan bu gidermek istiyorum. Bunu nasıl yapabilirim?

C, mantis bit bunu başarmak için çevireceğimi, ama python ile mümkün değil sanırım.

CEVAP
28 Mayıs 2011, CUMARTESİ


Artım python kayan nokta mümkün olan en küçük miktarda değer

Sen deli değilsin ve bunu yapmak gerekir. Python matematik kitaplığı geçerli bir eksiklik, ne yazık ki, hem Python 2'de.X ve Python3000. Python math.nextafter(x,y) olmalı ama yok. En C derleyicileri fonksiyonları beri eklemek için önemsiz olacaktır.

nextafter(x,y) fonksiyonları y yönünde x aşağıdaki şekilde farklı gösterilebilir kayan noktalı bir sonraki değeri döndürür. Bu nextafter() işlevleri platformu üzerinde çalışmak için ya da bir sonraki değeri mümkün olduğunu göstermek için mantıklı bir değer iade garantisi vardır.

nextafter() fonksiyonları POSIX C99 ISO standartlarına parçası ve _nextafter() in Visual C. Standart matematik kütüphaneleri, C, C , ve tüm IEEE önerilen nextafter uygulamak Artırmak Java() C99 uyumlu Görsel işlevler veya yöntemler. (Dürüst olmak gerekirse bilmiyorum .NET nextafter vardır(). Microsoft çok C99 veya POSIX umurunda bile değil.)

Python C99 matematik fonksiyonları ve davranışları matematik modülü için en destekleyici yönde ilerliyor gibi görünüyor beri, nextafter() hariç merak ediliyor. Neyse ki, orada kolay çözümler.

Yokbit öldürmek fonksiyonları burada tam olarak ya doğru ya da underflows, vb kenar durumlarda, değerleri 0.0, 0.0, subnormals, sonsuz, negatif değerler negatif olsa gidiyor gibi, başa. Doğru bit eğer bu yönde ise öldürmek nasıl bir fikir vermek için Here is a reference implementation of nextafter() in C.

Python nextafter() ya da diğer hariç POSIX matematik fonksiyonları elde etmek için iki katı çalışma alternatif yollarını şunlardır:

Kullanım Numpy:

>>> import numpy
>>> numpy.nextafter(0,1)
4.9406564584124654e-324
>>> numpy.nextafter(.1, 1)
0.10000000000000002
>>> numpy.nextafter(1e6, -1)
999999.99999999988
>>> numpy.nextafter(-.1, 1)
-0.099999999999999992

Doğrudan sistem matematik için DLL Link:

import ctypes
import sys
from sys import platform as _platform

if _platform == "linux" or _platform == "linux2":
    _libm = ctypes.cdll.LoadLibrary('libm.so.6')
    _funcname = 'nextafter'
elif _platform == "darwin":
    _libm = ctypes.cdll.LoadLibrary('libSystem.dylib')
    _funcname = 'nextafter'
elif _platform == "win32":
    _libm = ctypes.cdll.LoadLibrary('msvcrt.dll')
    _funcname = '_nextafter'
else:
    # these are the ones I have access to...
    # fill in library and function name for your system math dll
    print "Platform", repr(_platform), "is not supported"
    sys.exit(0)

_nextafter = getattr(_libm, _funcname)
_nextafter.restype = ctypes.c_double
_nextafter.argtypes = [ctypes.c_double, ctypes.c_double]

def nextafter(x, y):
    "Returns the next floating-point number after x in the direction of y."
    return _nextafter(x, y)

assert nextafter(0, 1) - nextafter(0, 1) == 0
assert 0.0   nextafter(0, 1) > 0.0

Ve eğer gerçekten saf Python bir çözüm istiyorsanız:

# handles edge cases correctly on MY computer 
# not extensively QA'd...
import math
# 'double' means IEEE 754 double precision -- c 'double'
epsilon  = math.ldexp(1.0, -53) # smallest double that 0.5 epsilon != 0.5
maxDouble = float(2**1024 - 2**971)  # From the IEEE 754 standard
minDouble  = math.ldexp(1.0, -1022) # min positive normalized double
smallEpsilon  = math.ldexp(1.0, -1074) # smallest increment for doubles < minFloat
infinity = math.ldexp(1.0, 1023) * 2

def nextafter(x,y):    
    """returns the next IEEE double after x in the direction of y if possible"""
    if y==x:
       return y         #if x==y, no increment

    # handle NaN
    if x!=x or y!=y:
        return x   y       

    if x >= infinity:
        return infinity

    if x <= -infinity:
        return -infinity

    if -minDouble < x < minDouble:
        if y > x:
            return x   smallEpsilon
        else:
            return x - smallEpsilon  

    m, e = math.frexp(x)        
    if y > x:
        m  = epsilon
    else:
        m -= epsilon

    return math.ldexp(m,e)

Ya da, kullanmak Mark Dickinson's mükemmel solution

Belli ki Numpy çözüm kolay olur.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • GenTechPC

    GenTechPC

    1 Temmuz 2007
  • Michael Zhang

    Michael Zhan

    8 EYLÜL 2012
  • SRI International

    SRI Internat

    30 NİSAN 2008