क्यों 1 // 0.01 == 99 पायथन में?


31

मुझे लगता है कि यह एक क्लासिक फ़्लोटिंग पॉइंट सटीक प्रश्न है, लेकिन मैं इस परिणाम के चारों ओर अपना सिर लपेटने की कोशिश कर रहा हूं, 1//0.01पायथन 3.7.5 पैदावार में चल रहा है 99।

मुझे लगता है कि यह एक अपेक्षित परिणाम है, लेकिन क्या यह तय करने का कोई तरीका है कि इसके int(1/f)बजाय इसका उपयोग करना अधिक सुरक्षित है 1//f?


4
हां, यह हमेशा सुरक्षित रहता है int (1 / f)। केवल इसलिए कि // FLOOR डिवीजन है, और आप इसे गलत तरीके से ROUND मानते हैं।
— पेर्डी एस्टाकेल


2
नकल नहीं है। यह हमेशा का उपयोग करके अपेक्षित रूप से 99.99% काम कर सकते हैं round()और कभी नहीं //या int()। जुड़ा हुआ प्रश्न फ्लोट तुलना के बारे में है जिसका ट्रंकेशन से कोई लेना-देना नहीं है और ऐसा कोई आसान निर्धारण नहीं है।
— अधिकतम

जवाबों:


23

यदि यह वास्तविक संख्याओं के साथ विभाजन 1//0.01होता है , तो ठीक 100 होगा। चूंकि वे फ्लोटिंग-पॉइंट सन्निकटन हैं, हालांकि, 0.011/100 से थोड़ा बड़ा है, जिसका अर्थ है कि भागफल 100 से थोड़ा छोटा है। यह 99 है। मूल्य मान जो तब तैरता है 99 तक।


3
यह "जब यह सुरक्षित है, तो तय करने का एक तरीका नहीं है"।
— स्कॉट हंटर

10
"सुरक्षित" अच्छी तरह से परिभाषित नहीं है।
— शेपनर

1
पूरी तरह से इसे अनदेखा करने के लिए, esp। जब ओपी फ़्लोटिंग पॉइंट मुद्दों से अवगत होता है?
— स्कॉट हंटर

3
@chepner यदि "सुरक्षित" अच्छी तरह से परिभाषित नहीं है, तो शायद स्पष्टीकरण के लिए पूछना बेहतर है: /

2
यह बहुत मेरे लिए स्पष्ट है कि "सुरक्षित" का अर्थ है "त्रुटि नहीं बदतर एक सस्ते जेब कैलकुलेटर की तुलना में"
— maxy

9

इस परिणाम के कारण आप की तरह हैं, और बताया गया है कि फ्लोटिंग पॉइंट गणित टूट गया है? और कई अन्य समान प्रश्नोत्तर।

जब आप अंश और हर के दशमलव की संख्या जानते हैं, तो एक अधिक विश्वसनीय तरीका यह है कि उन संख्याओं को पहले गुणा किया जाए ताकि वे पूर्णांकों के रूप में माने जा सकें, और फिर उन पर पूर्णांक विभाजन करें:

तो आपके मामले में 1//0.01पहले परिवर्तित किया जाना चाहिए 1*100//(0.01*100)जो कि 100 है।

अधिक चरम मामलों में आप अभी भी "अप्रत्याशित" परिणाम प्राप्त कर सकते हैं। roundपूर्णांक विभाजन करने से पहले अंश और हर में कॉल जोड़ना आवश्यक हो सकता है :

1 * 100000000000 // round(0.00000000001 * 100000000000)

लेकिन, यदि यह निश्चित दशमलव (पैसा, सेंट) के साथ काम करने के बारे में है, तो सेंट के साथ काम करने को इकाई मानें , ताकि सभी अंकगणित को पूर्णांक अंकगणित के रूप में किया जा सके, और केवल करते समय / मुख्य मौद्रिक इकाई (डॉलर) से परिवर्तित करें। मैं / हे।

या वैकल्पिक रूप से, दशमलव के लिए एक पुस्तकालय, की तरह का उपयोग दशमलव है, जो:

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

from decimal import Decimal
cent = Decimal(1) / Decimal(100) # Contrary to floating point, this is exactly 0.01
print (Decimal(1) // cent) # 100

3
"जो स्पष्ट रूप से 100 है।" जरूरी नहीं: यदि .01 सटीक नहीं है, तो .01 * 100 भी नहीं है। इसे मैन्युअल रूप से "ट्यून" किया जाना चाहिए।
— glglgl

8

आपको जो ध्यान में रखना है, वह //यह है कि floorऑपरेटर है और इस तरह से आपको पहले सोचना चाहिए जैसे कि आपके पास 100 में गिरने की समान संभावना है जैसे कि 99 (*) में (क्योंकि ऑपरेशन के 100 ± epsilonसाथ होगा epsilon>0बशर्ते कि वास्तव में 100.00 प्राप्त करने की संभावना .. 0 बेहद कम हैं।)

आप वास्तव में इसे माइनस साइन के साथ देख सकते हैं,

>>> 1//.01
99.0
>>> -1//.01
-100.0

और आपको (अन) आश्चर्यचकित होना चाहिए।

दूसरी ओर, int(-1/.01)पहले विभाजन करता है और फिर int()संख्या में लागू होता है , जो कि मंजिल नहीं है, लेकिन 0 की ओर एक झुकाव है ! उस मामले में अर्थ

>>> 1/.01
100.0
>>> -1/.01
-100.0

इसलिये,

>>> int(1/.01)
100
>>> int(-1/.01)
-100

हालांकि, राउंडिंग आपको इस ऑपरेटर के लिए आपका अपेक्षित परिणाम देगा क्योंकि फिर से, उन आंकड़ों के लिए त्रुटि छोटी है।

(*) मैं यह नहीं कह रहा हूं कि संभावना समान है, मैं सिर्फ यह कह रहा हूं कि एक प्राथमिकता जब आप अस्थायी अंकगणित के साथ इस तरह की गणना करते हैं जो कि आपको मिल रहा है, इसका एक अनुमान है।


7

फ़्लोटिंग पॉइंट नंबर अधिकांश दशमलव संख्याओं का सही प्रतिनिधित्व नहीं कर सकते हैं, इसलिए जब आप एक फ़्लोटिंग पॉइंट शाब्दिक टाइप करते हैं तो आपको वास्तव में उस शाब्दिक का एक अनुमान मिलता है। आपके द्वारा लिखी गई संख्या से अनुमान बड़ा या छोटा हो सकता है।

आप इसे तैरते हुए दशमलव संख्या के सटीक मान को दशमलव या अंश में देख सकते हैं।

>>> from decimal import Decimal
>>> Decimal(0.01)
Decimal('0.01000000000000000020816681711721685132943093776702880859375')
>>> from fractions import Fractio
>>> Fraction(0.01)
Fraction(5764607523034235, 576460752303423488) 

हम अपने अयोग्य शाब्दिक के कारण त्रुटि को खोजने के लिए Fraction type का उपयोग कर सकते हैं।

>>> float((Fraction(1)/Fraction(0.01)) - 100)
-2.0816681711721685e-15

हम यह भी पता लगा सकते हैं कि 100 के आसपास दानेदार डबल सटीक फ़्लोटिंग पॉइंट संख्याएं अगली बार सुन्न से उपयोग करके कैसे होती हैं।

>>> from numpy import nextafter
>>> nextafter(100,0)-100
-1.4210854715202004e-14

इससे हम यह अनुमान लगा सकते हैं कि निकटतम फ्लोटिंग पॉइंट संख्या 1/0.01000000000000000020816681711721685132943093776702880859375वास्तव में 100 है।

के बीच का अंतर 1//0.01और int(1/0.01)गोलाई है। 1 // 0.01 एक ही चरण में अगले पूरी संख्या के लिए सटीक परिणाम नीचे राउंड करता है। तो हमें 99 का परिणाम मिलता है।

int (1 / 0.01) दूसरी ओर दो चरणों में गोल होता है, पहले यह परिणाम को निकटतम दोहरी परिशुद्धता फ्लोटिंग पॉइंट संख्या (जो कि ठीक 100 है) पर राउंड करता है, फिर यह राउंडिंग पॉइंट नंबर को अगले पूर्णांक (जो है) पर राउंड करता है फिर से ठीक 100)।


इसे सिर्फ चक्कर लगाना भ्रामक है। यह या तो बुलाया जाना चाहिए काट-छांट या शून्य की ओर गोलाई : int(0.9) == 0औरint(-0.9) == 0
— maxy

यह द्विआधारी फ्लोटिंग बिंदु प्रकार है जिसके बारे में आप यहां बात कर रहे हैं। (इसमें दशमलव फ़्लोटिंग पॉइंट प्रकार भी हैं।)
— स्टीफन C

3

यदि आप निम्नलिखित पर अमल करते हैं

from decimal import *

num = Decimal(1) / Decimal(0.01)
print(num)

उत्पादन होगा:

99.99999999999999791833182883

यह इस तरह से आंतरिक रूप से प्रस्तुत किया गया है, इसलिए इसे नीचे गोल करना //होगा99


2
इस मामले में त्रुटि दिखाने के लिए यह सटीक है, लेकिन ध्यान रखें कि "दशमलव" अंकगणित भी सटीक नहीं है।
— प्लगवॉश करें

साथ Decimal(0.01)आप बहुत देर हो चुकी है, त्रुटि पहले से ही में इससे पहले कि आप फोन crept Decimal। मुझे यकीन नहीं है कि यह सवाल का जवाब कैसे है ... आपको पहले एक सटीक 0.01 की गणना करनी चाहिए Decimal(1) / Decimal(100), जैसे मैंने अपने उत्तर में दिखाया था।
— त्रिशूल

@trincot मेरा उत्तर "क्यों 1 // 0.01 == 99" शीर्षक में प्रश्न है, मैंने ओपी को यह दिखाने की कोशिश की कि फ्लोटिंग संख्याओं को आंतरिक रूप से कैसे व्यवहार किया जाता है।
— 21
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.