2012-05-02 18 views
9

क्या पाइथन फ्लोटिंग-पॉइंट मान प्राप्त करने के लिए एक फ़ंक्शन प्रदान करता है जो मौजूदा फ़्लोटिंग-पॉइंट मान के कम से कम महत्वपूर्ण बिट को बढ़ाने से होता है?फ़्लोटिंग-पॉइंट अनुक्रम में आपको अगला मान कैसे मिलता है?

मैं std::nextafter फ़ंक्शन जैसा कुछ भी ढूंढ रहा हूं जो C++ 11 में जोड़ा गया था।

+0

मुझे विश्वास नहीं है, लेकिन यह देखने का प्रयास कर रहा है कि 'std :: nextafter' कैसे लागू किया गया है और हो सकता है कि हम कुछ समकक्ष के साथ आ सकें। – Abhijit

+0

मेरा साइथन आधारित समाधान विंडोज़ पर काम करना चाहिए (देखा कि आप अपनी प्रोफ़ाइल में एक विंडोज़ लड़के हैं)। आप पाइप से साइथन स्थापित कर सकते हैं। जीसीसी/जी ++ की आवश्यकता है। आपको setup.py में लाइब्रेरी, library_dirs और include_dirs पथ सेट करना पड़ सकता है, वे मानक फ़ाइल पथ हैं जिन्हें आप अपने कंपाइलर को cmath का उपयोग करने वाले कुछ बनाने के लिए पास करेंगे। सुनिश्चित नहीं है कि वे पथ विंडोज़ पर क्या दिखेंगे या भले ही उन्हें आवश्यकता होगी (शायद नहीं), लेकिन कोई कारण नहीं है कि यह काम नहीं करना चाहिए। – Endophage

+0

नहीं, यह नहीं है। नकली का सबसे आसान तरीका यह है कि संरचना मॉड्यूल का उपयोग 8-बाइट int में परिवर्तित करने के लिए, int में एक जोड़ें, और वापस कनवर्ट करें। यह सकारात्मक संख्याओं के लिए ठीक काम करता है, और नकारात्मक संख्याओं के लिए कुछ tweaking की जरूरत है। –

उत्तर

1

चेक बाहर http://docs.python.org/library/stdtypes.html#float.hex

के इस एक कार्यान्वयन है कि ज्यादा के बारे में अगले के बाद पता नहीं है कोशिश करते हैं।

सबसे पहले, हम हेक्स स्ट्रिंग से हेक्स हिस्सा है और प्रतिपादक निकालने के लिए की जरूरत है:

def extract_parts(hex_val): 
    if not hex_val.startswith('0x1.'): 
     return None 
    relevant_chars = hex_val[4:] 
    if not len(relevant_chars) > 14 and relevant_chars[13] == 'p': 
     return None 
    hex_portion = int(relevant_chars[:13], 16) 
    if relevant_chars[14] == '+': 
     p_val = int(relevant_chars[15:]) 
    elif relevant_chars[14] == '-': 
     p_val = -int(relevant_chars[15:]) 
    else: 
     return None 
    return (hex_portion, p_val) 

तो हम सकारात्मक या नकारात्मक दिशा में बढ़ाने के लिए कोई तरीका होना चाहिए (हम हेक्स स्ट्रिंग पहले से ही मान लेंगे

:

def increment_hex(hex_portion, p_val, direction): 
    if hex_portion == 0 and direction == -1: 
     new_hex = 'f' * 13 
     p_val -= 1 
    elif hex_portion == int('f' * 13, 16) and direction == 1: 
     new_hex = '0' * 13 
     p_val += 1 
    else: 
     new_hex = hex(hex_portion + direction)[2:].rstrip('L').zfill(13) 

    if len(new_hex) != 13: 
     return None 
    return format_hex(new_hex, p_val) 

हम एक स्वीकार्य हेक्स स्ट्रिंग और प्रतिपादक है, जो मैं ऊपर उपयोग पुन: प्रारूपित करना एक सहायक समारोह की जरूरत है: एक पूर्णांक hex_portion) में बदल दिया गया

अंत में, nextafter लागू करने के लिए:

def nextafter(float_val): 
    hex_equivalent = float_val.hex() 
    hex_portion, p_val = extract_parts(hex_equivalent) 

    direction = 1 
    new_hex_equiv = increment_hex(hex_portion, p_val, direction) 
    return float.fromhex(new_hex_equiv) 
+1

हू? यह 'std :: अगले के बाद' के बराबर कैसा है? – phihag

+1

@ फिहाग, यह बिल्कुल समान नहीं है लेकिन यह स्वयं लिखने का आधार हो सकता है। –

2

अद्यतन:

बाहर कर देता है तो उसे एक डुप्लीकेट प्रश्न (जो खोज के लिए परिणाम # 2 के रूप में गूगल में आता है कि "C++ nextafter अजगर"): Increment a python floating point value by the smallest possible amount

स्वीकृत उत्तर कुछ ठोस समाधान प्रदान करता है।

मूल जवाब:

निश्चित रूप से यह सही समाधान नहीं है लेकिन कुछ ही लाइनों cython का उपयोग कर आप मौजूदा सी ++ समारोह लपेटो और अजगर में इसका इस्तेमाल करने की अनुमति देगा। मैंने नीचे दिए गए कोड को संकलित किया है और यह मेरे उबंटू 11.10 बॉक्स पर काम करता है।

सबसे पहले, एक .pyx फ़ाइल (मैं मेरा nextafter.pyx कहा जाता है) सी ++ करने के लिए अपने इंटरफेस को परिभाषित करता:

cdef extern from "cmath": 
    float nextafter(float start, float to) 

def pynextafter(start, to): 
    cdef float float_start = float(start) 
    cdef float float_to = float(to) 
    result = nextafter(start, to) 
    return result 

फिर एक setup.py को परिभाषित करता है विस्तार का निर्माण करने के लिए कैसे:

from distutils.core import setup 
from distutils.extension import Extension 
from Cython.Distutils import build_ext 

ext_modules=[ 
    Extension("nextafter", 
     ["nextafter.pyx"], 
     libraries=[], 
     library_dirs=[], 
     include_dirs=[], 
     language="c++", 
    ) 
] 

setup(
    name = "nextafter", 
    cmdclass = {"build_ext": build_ext}, 
    ext_modules = ext_modules 
) 

सुनिश्चित करें कि वे एक ही निर्देशिका में हैं तो python setup.py build_ext --inplace के साथ बनाएं। मुझे आशा है कि आप देख सकते हैं कि आप विस्तार के बाद के बाद के अन्य बदलावों को कैसे जोड़ेंगे (युगल, आदि ...)। एक बार बनाया गया, तो आप के बाद एक होना चाहिए। तो। उसी निर्देशिका में पाइथन को फायर करें (या उसके बाद कहीं भी अपने रास्ते पर रखें) और आपको from nextafter import pynextafter पर कॉल करने में सक्षम होना चाहिए।

का आनंद लें!

+0

आश्चर्यजनक रूप से पर्याप्त है कि मेरे पास उस प्रश्न का उत्तर है। –

+0

@MarkRansom umm ... lol? – Endophage

+0

मुझे लगता है कि आपको अपनी '.pyx' फ़ाइल में' float' को हर जगह 'डबल'' से प्रतिस्थापित करने की आवश्यकता है। (या यदि आप वास्तव में फ्लोट्स का उपयोग करना चाहते हैं, तो 'nextafterf' का उपयोग करें, लेकिन चूंकि पाइथन फ्लोट सी ++ युगल के अनुरूप होता है, इसलिए डबल संस्करण अधिक समझ में आता है।) –

13

अपने प्रश्न के पहले भाग का जवाब देने के लिए: नहीं, पायथन इस कार्यक्षमता को सीधे प्रदान नहीं करता है। लेकिन यह एक पायथन समारोह लिखना काफी आसान है जो यह करता है, आईईईई 754 फ्लोटिंग पॉइंट मानता है।

आईईईई 754 बाइनरी फ्लोटिंग-पॉइंट प्रारूपों को चालाकी से डिजाइन किया गया है ताकि एक फ्लोटिंग-पॉइंट नंबर से 'अगले' तक जाने से थोड़ा सा प्रतिनिधित्व बढ़ सके। यह [0, infinity) श्रेणी में किसी भी संख्या के लिए काम करता है, दाएं सीमाओं और उपनामों में। nextUp का एक संस्करण तैयार करने के लिए जो पूर्ण फ़्लोटिंग-पॉइंट रेंज को कवर करता है, आपको ऋणात्मक संख्या, infinities, नैन, और नकारात्मक शून्य से जुड़े एक विशेष मामले से निपटने की भी आवश्यकता है। नीचे पायथन में आईईईई 754 के nextUp फ़ंक्शन का मानकों का अनुपालन संस्करण है। इसमें सभी कोने के मामलों को शामिल किया गया है।

import math 
import struct 

def next_up(x): 
    # NaNs and positive infinity map to themselves. 
    if math.isnan(x) or (math.isinf(x) and x > 0): 
     return x 

    # 0.0 and -0.0 both map to the smallest +ve float. 
    if x == 0.0: 
     x = 0.0 

    n = struct.unpack('<q', struct.pack('<d', x))[0] 
    if n >= 0: 
     n += 1 
    else: 
     n -= 1 
    return struct.unpack('<d', struct.pack('<q', n))[0] 

nextDown और nextAfter के कार्यान्वयन तो इस तरह दिखेगा। (ध्यान दें कि nextAfter आईईईई 754 द्वारा निर्दिष्ट एक फ़ंक्शन नहीं है, इसलिए आईईईई विशेष मूल्यों के साथ क्या होना चाहिए, इसके बारे में अनुमान लगाया गया है। यहां मैं आईबीएम डेसिमल अंकगणितीय मानक का पालन कर रहा हूं कि पायथन की decimal.Decimal कक्षा आधारित है।)

def next_down(x): 
    return -next_up(-x) 

def next_after(x, y): 
    # If either argument is a NaN, return that argument. 
    # This matches the implementation in decimal.Decimal 
    if math.isnan(x): 
     return x 
    if math.isnan(y): 
     return y 

    if y == x: 
     return y 
    elif y > x: 
     return next_up(x) 
    else: 
     return next_down(x) 
संबंधित मुद्दे