2011-05-13 16 views
17

के साथ पाइथन राउंडिंग त्रुटि मुझे नहीं पता कि यह एक स्पष्ट बग है, लेकिन सिमुलेशन के पैरामीटर को बदलने के लिए पाइथन स्क्रिप्ट चलाने के दौरान, मुझे एहसास हुआ कि डेल्टा = 0.2 9 और डेल्टा = 0.58 के साथ परिणाम गायब थे। जांच पर, मैंने देखा है कि निम्नलिखित पायथन कोड:फ्लोट नंबर

for i_delta in range(0, 101, 1): 
    delta = float(i_delta)/100 

    (...) 

filename = 'foo' + str(int(delta * 100)) + '.dat' 

डेल्टा = 0.28 और 0.29, एक ही .57 के साथ और .58, कारण के लिए समान फ़ाइलों उत्पन्न किया जा रहा है कि अजगर रिटर्न (29)/100 .28999999999999998 के रूप में तैरने लगते हैं । लेकिन यह एक व्यवस्थित त्रुटि नहीं है, इस अर्थ में यह हर पूर्णांक के साथ नहीं होता है। तो मैं निम्नलिखित पायथन स्क्रिप्ट बनाया:

import sys 

n = int(sys.argv[1]) 

for i in range(0, n + 1): 
    a = int(100 * (float(i)/100)) 
    if i != a: print i, a 

और मैं संख्या जिसके लिए इस गोलाई त्रुटि होता है में किसी भी पैटर्न नहीं देख सकता। यह उन विशेष संख्याओं के साथ क्यों होता है?

+4

यह ठीक है कि आईईईई 754 फ्लोटिंग-पॉइंट नंबर कैसे काम करते हैं। मैं सुझाव देता हूं कि आप आसानी से छंटनी के बजाए फ्लोट को एक पूर्णांक में बदलने के लिए गोल करें। –

+1

यह कोई त्रुटि नहीं है - यह कई अलग-अलग भाषाओं में आम है। कुछ walkarounds हैं, लेकिन इस मामले में सबसे सरल समाधान सिर्फ फ़ाइल नाम में idelta का उपयोग कर सकता है। बस ध्यान रखें कि idelta डिफ़ॉल्ट रूप से लूप के बाहर पारित नहीं किया गया है। – Tadeck

+2

# StdSOAnswer_1। इस तरह फ्लोटिंग पॉइंट काम करता है। –

उत्तर

27

कोई भी संख्या जिसे दो की सटीक शक्तियों से नहीं बनाया जा सकता है, को फ़्लोटिंग पॉइंट नंबर के रूप में बिल्कुल प्रदर्शित नहीं किया जा सकता है; इसे अनुमानित करने की जरूरत है। कभी-कभी निकटतम अनुमान वास्तविक संख्या से कम होगा।

What Every Computer Scientist Should Know About Floating-Point Arithmetic पढ़ें।

+0

मैं वही लिंक पोस्ट करने से पहले ईमानदारी से उसी दस्तावेज़ पर आपका लिंक नहीं देख पाया। बस इतना अच्छा संदर्भ दिखाता है। –

+0

@ जिंबोब, मैंने मूल पोस्ट के एक मिनट बाद लिंक जोड़ा। यह एक क्लासिक है, लेकिन मेरे पास यह तुरंत आसान नहीं था। –

+5

पायथनिस्टस के लिए, [पायथन ट्यूटोरियल] (http://docs.python.org/tutorial/floatingpoint.html) में एक छोटा (और पढ़ने में आसान) अध्याय भी है जो इस समस्या से संबंधित है। –

16

floating point numbers की प्रकृति के कारण यह बहुत प्रसिद्ध है।

यदि आप दशमलव अंकगणित नहीं करना चाहते हैं तो फ्लोटिंग पॉइंट अंकगणित नहीं है libraries ऐसा करने के लिए।

जैसे,

>>> from decimal import Decimal 
>>> Decimal(29)/Decimal(100) 
Decimal('0.29') 
>>> Decimal('0.29')*100 
Decimal('29') 
>>> int(Decimal('29')) 
29 

सामान्य दशमलव में शायद पानी में गिर रहा है और अभी भी दुर्लभ मामलों में राउंडिंग त्रुटियों होगा नंबर एक परिमित दशमलव प्रतिनिधित्व (उदाहरण के लिए किसी भी अंश नहीं है जब जहां हर 1 नहीं है या 2 या 5 द्वारा विभाजित - दशमलव आधार के कारक (10))। उदाहरण के लिए:

>>> s = Decimal(7) 
>>> Decimal(1)/s/s/s/s/s/s/s*s*s*s*s*s*s*s 
Decimal('0.9999999999999999999999999996') 
>>> int(Decimal('0.9999999999999999999999999996')) 
0 

तो जब तक आप फर्श फ़ंक्शन नहीं चाहते हैं, तब तक इन्हें फ़्लोटिंग पॉइंट्स को काटने से पहले हमेशा गोल करना सबसे अच्छा होता है।

>>> int(1.9999) 
1 
>>> int(round(1.999)) 
2 

एक अन्य विकल्प fractions पुस्तकालय जो अनुमानित नहीं करता है से भिन्न वर्ग का प्रयोग है। (यह केवल आवश्यकतानुसार पूर्णांक संख्याओं और denominators जोड़ने/घटाना और गुणा करता रहता है)।

+0

हम्म, वास्तव में एक बेहतर उदाहरण दशमलव (1)/दशमलव (3) * दशमलव (3) है, जो 1.0 को अधिक परिशुद्धता के साथ उत्पन्न नहीं करता है। "जब आधार 10 नहीं है" तब होना चाहिए जब अंश को आधार 10 में बिल्कुल प्रदर्शित नहीं किया जा सकता है। संख्या निश्चित रूप से आधार 10 है। –

+0

@ डेरेकलिट्ज - सहमत, मेरा जवाब मैला था।आपका उदाहरण अधिक संक्षेप में है (हालांकि दोनों समान रूप से वैध हैं)। जब लिखा जाना चाहिए कि संख्या -10 में सीमित दशमलव प्रतिनिधित्व नहीं है, तो किसी भी अंश के साथ ऐसा होगा जब denominator 2 या 5 द्वारा विभाजित नहीं किया जा सकता है (माना जाता है कि अंश को आधार 10 में बिल्कुल प्रदर्शित नहीं किया जा सकता है। संख्या निश्चित रूप से, आधार 10 में है। "बिल्कुल सही नहीं है। संख्याओं में आधार नहीं हैं। एक-तिहाई = 1/(1 + 1 + 1) बिल्कुल आधार के बावजूद। एक अंश के रूप में लिखा गया है जिसमें यह हो सकता है आधार 10--1/3 में दर्शाया गया है।) –

+0

@dr_jimbob मुझे ऊपर सुधार पसंद है, हालांकि, मुझे बयान पसंद नहीं है 'संख्याओं के आधार नहीं हैं'। शायद अंतर अर्थपूर्ण है, लेकिन शब्दों का अर्थ महत्वपूर्ण है। एक संख्या को एक मान (या यदि आप पसंद करते हैं तो मात्रा) का प्रतिनिधित्व करना चाहिए। एक संख्या प्रणाली बनाने के लिए आधार को चुनने की आवश्यकता है, प्रतीकों को चुना जाना चाहिए, और दीवार हम अधिक प्रभावी ढंग से संवाद कर सकते हैं तो सरल टैलींग, लेकिन मुझे यकीन है कि आपका मतलब यही है :) –

संबंधित मुद्दे