python - दो दशमलव बिंदुओं पर तैरना सीमित है




floating-point rounding (13)

मैं 13.9 5 तक गोल करना चाहता हूं।

>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999

round समारोह जिस तरह से मैं उम्मीद करता हूं काम नहीं करता है।


tldr;)

इनपुट / आउटपुट पर गोल करने की समस्या को पायथन 2.7.0 और 3.1 निश्चित रूप से हल किया गया है

अनंत परीक्षण:

import random
for x in iter(random.random, None):           # verify FOREVER that rounding is fixed :-)
    assert float(repr(x)) == x                # Reversible repr() conversion
    assert len(repr(round(x, 10))) <= 12      # Smart decimal places in repr() after round
    if x >= 0.1:                              # Implicit rounding to 12 significant digits 
        assert str(x) == repr(round(x, 12))   # by str() is good enough for small errors
        y = 1000 * x                             # Decimal type is excessive for shopping 
        assert str(y) == repr(round(y, 12 - 3))  # in the supermaket with Python 2.7+ :-)

डॉक्स

रिलीज नोट्स पाइथन 2.7 देखें - अन्य भाषा चौथा पैराग्राफ बदलती है:

फ्लोटिंग-पॉइंट नंबर और तारों के बीच रूपांतरण अब अधिकांश प्लेटफॉर्म पर सही ढंग से गोल किए गए हैं। ये रूपांतरण कई अलग-अलग स्थानों में होते हैं: str () फ्लोट्स और जटिल संख्याओं पर; फ्लोट और जटिल रचनाकार; संख्यात्मक स्वरूपण; मार्शल, अचार और जेसन मॉड्यूल का उपयोग करके फ्लोट और जटिल संख्याओं को क्रमबद्ध करना और डी-सीरियलाइज करना; पायथन कोड में फ्लोट और काल्पनिक अक्षर की पार्सिंग; और दशमलव-से-फ्लोट रूपांतरण।

इससे संबंधित, फ्लोटिंग-पॉइंट नंबर x का repr () अब सबसे कम दशमलव स्ट्रिंग के आधार पर परिणाम देता है जो कि सही गोल करने के दौरान x पर वापस जाने की गारंटी देता है (राउंड-आधा-टू-राउंडिंग मोड के साथ)। पहले यह गोल करने के लिए x से 17 दशमलव अंकों के आधार पर एक स्ट्रिंग दिया।

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

संपादित करें - अधिक जानकारी:: पायथन 2.7 से पहले float का स्वरूपण वर्तमान numpy.float64 समान था। दोनों प्रकार 52 बिट मैंटिसा के साथ 64 बिट आईईईई 754 डबल परिशुद्धता का उपयोग करते हैं। एक बड़ा अंतर यह है कि np.float64.__repr__ को अत्यधिक दशमलव संख्या के साथ अक्सर स्वरूपित किया जाता है ताकि कोई भी खोया जा सके, लेकिन 13.949 99 99 99 99 99 99 और 13.950000000000001 के बीच कोई वैध आईईईई 754 संख्या मौजूद नहीं है, नतीजा अच्छा नहीं है और रूपांतरण repr(float(number_as_string)) उलटा नहीं है। दूसरी तरफ: float.__repr__ स्वरूपित है ताकि प्रत्येक अंक महत्वपूर्ण हो, अनुक्रम अंतराल के बिना है और रूपांतरण उलटा है। बस: यदि आपके पास शायद numpy.float64 संख्या है, तो इसे मनुष्यों के लिए संख्यात्मक प्रोसेसर के लिए प्रारूपित करने के लिए सामान्य फ्लोट में परिवर्तित करें, अन्यथा पायथन 2.7+ के साथ और कुछ भी आवश्यक नहीं है।


अधिकांश संख्याओं को फ्लोट्स में बिल्कुल प्रतिनिधित्व नहीं किया जा सकता है। यदि आप संख्या को गोल करना चाहते हैं क्योंकि आपका गणितीय सूत्र या एल्गोरिदम आवश्यक है, तो आप गोल का उपयोग करना चाहते हैं। यदि आप डिस्प्ले को एक निश्चित परिशुद्धता तक सीमित करना चाहते हैं, तो राउंड का उपयोग न करें और केवल उस स्ट्रिंग के रूप में प्रारूपित करें। (यदि आप इसे कुछ वैकल्पिक गोलाकार विधि के साथ प्रदर्शित करना चाहते हैं, और वहां बहुत सारे हैं, तो आपको दो दृष्टिकोणों को मिश्रण करने की आवश्यकता है।)

>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'

और आखिरकार, हालांकि शायद सबसे महत्वपूर्ण बात यह है कि यदि आप सटीक गणित चाहते हैं तो आप बिल्कुल तैरना नहीं चाहते हैं। सामान्य उदाहरण पैसे से निपट रहा है और 'सेंट' को एक पूर्णांक के रूप में स्टोर करने के लिए है।


आप पुरानी समस्या में फ्लोटिंग पॉइंट नंबरों के साथ चल रहे हैं कि सभी संख्याओं का प्रतिनिधित्व नहीं किया जा सकता है। कमांड लाइन आपको सिर्फ स्मृति से पूर्ण फ़्लोटिंग पॉइंट फॉर्म दिखा रही है। फ़्लोटिंग पॉइंट में आपका गोलाकार संस्करण एक ही नंबर है। चूंकि कंप्यूटर द्विआधारी हैं, इसलिए वे फ़्लोटिंग पॉइंट नंबर को एक पूर्णांक के रूप में संग्रहीत करते हैं और फिर इसे दो की शक्ति से विभाजित करते हैं, इसलिए 13.9 5 को 125650429603636838 / (2 ** 53) के समान रूप में प्रदर्शित किया जाएगा। डबल परिशुद्धता संख्या में सटीक के 53 बिट्स (16 अंक) होते हैं और नियमित फ्लोट में 24 बिट्स (8 अंक) सटीक होते हैं। पायथन में फ़्लोटिंग पॉइंट मूल्यों को स्टोर करने के लिए डबल परिशुद्धता का उपयोग करता है

उदाहरण के लिए

  >>> 125650429603636838/(2**53)
  13.949999999999999

  >>> 234042163/(2**24)
  13.949999988079071

  >>> a=13.946
  >>> print(a)
  13.946
  >>> print("%.2f" % a)
  13.95
  >>> round(a,2)
  13.949999999999999
  >>> print("%.2f" % round(a,2))
  13.95
  >>> print("{0:.2f}".format(a))
  13.95
  >>> print("{0:.2f}".format(round(a,2)))
  13.95
  >>> print("{0:.15f}".format(round(a,2)))
  13.949999999999999

यदि आप मुद्रा में केवल दो दशमलव स्थानों के बाद हैं तो आपके पास कुछ बेहतर विकल्प हैं जो सेंट्स में पूर्णांक और स्टोर मानों का उपयोग नहीं करते हैं और फिर डॉलर में परिवर्तित करने के लिए 100 से विभाजित करते हैं। या decimal तरह एक निश्चित बिंदु संख्या का उपयोग करें


उपयोग

print"{:.2f}".format(a)

के बजाय

print"{0:.2f}".format(a)

चूंकि उत्तरार्द्ध एकाधिक चर आउटपुट करने का प्रयास करते समय आउटपुट त्रुटि का कारण बन सकता है (टिप्पणियां देखें)


ऐसा लगता है कि यहां तक ​​कि किसी ने अभी तक इसका उल्लेख नहीं किया है, इसलिए मुझे पायथन 3.6 के एफ-स्ट्रिंग / टेम्पलेट-स्ट्रिंग प्रारूप में एक उदाहरण दें, जो मुझे लगता है कि खूबसूरती से साफ है:

>>> f'{a:.2f}'

यह ऑपरेटरों के साथ और माता-पिता की आवश्यकता नहीं होने के साथ भी लंबे उदाहरणों के साथ अच्छी तरह से काम करता है:

>>> print(f'Completed in {time.time() - start:.2f}s')

जैसा कि @ मैट ने बताया, पायथन 3.6 एफ-स्ट्रिंग प्रदान करता है , और वे नेस्टेड पैरामीटर का भी उपयोग कर सकते हैं:

value = 2.34558
precision = 2
width = 4

print(f'result: {value:{width}.{precision}f}')

जो result: 2.35 प्रदर्शित करेगा result: 2.35


नीचे दिए गए कोड आज़माएं:

>>> a = 0.99334
>>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
>>> print a
0.99

पाइथन और जावास्क्रिप्ट जैसे गतिशील भाषाओं में फ़्लोटिंग पॉइंट को ठीक करने के लिए मैं इस तकनीक का उपयोग करता हूं

# for example:
a=70000
b=0.14
c=a*b

print c # prints 980.0000000002
#try to fix 
c=int(c * 10000)/100000
print c # prints 980

आप दशमलव को follwoing के रूप में भी उपयोग कर सकते हैं:

from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
#result in 6 precision -> Decimal('0.142857')
getcontext().prec = 28
Decimal(1) / Decimal(7)
#result in 28 precision -> Decimal('0.1428571428571428571428571429')

पायथन 2.7,

उम्मीद है कि यह मदद करेगा

a = 13.949999999999999
output = float(("%0.2f"%a))
print output

पायथन ट्यूटोरियल में एक परिशिष्ट कहा जाता है: फ़्लोटिंग प्वाइंट अंकगणितीय: मुद्दे और सीमाएं । इसे पढ़ें। यह बताता है कि क्या हो रहा है और क्यों पाइथन अपना सर्वश्रेष्ठ प्रदर्शन कर रहा है। इसमें एक उदाहरण भी है जो आपके साथ मेल खाता है। मुझे थोड़ा उद्धरण दें:

>>> 0.1
0.10000000000000001

आप round() फ़ंक्शन का उपयोग करने के लिए लुभाने के लिए प्रेरित हो सकते हैं ताकि आप इसे एक ही अंक पर वापस कर सकें। लेकिन इससे कोई फर्क नहीं पड़ता:

>>> round(0.1, 1)
0.10000000000000001

समस्या यह है कि “0.1” लिए संग्रहीत बाइनरी फ़्लोटिंग-पॉइंट मान पहले से ही 1/10 तक सबसे अच्छा बाइनरी अनुमान था, इसलिए इसे फिर से गोल करने की कोशिश करना बेहतर नहीं हो सकता है: यह पहले से ही उतना ही अच्छा था जितना इसे प्राप्त होता है।

एक और परिणाम यह है कि चूंकि 0.1 बिल्कुल 1/10 नहीं है, 0.1 दस मानों को जोड़कर बिल्कुल 1.0 नहीं मिल सकता है, या तो:

>>> sum = 0.0
>>> for i in range(10):
...     sum += 0.1
...
>>> sum
0.99999999999999989

आपकी समस्याओं का एक विकल्प और समाधान decimal मॉड्यूल का उपयोग करेगा।


मैं जिस विधि का उपयोग करता हूं वह स्ट्रिंग स्लाइसिंग का है। यह अपेक्षाकृत तेज़ और सरल है।

सबसे पहले, फ्लोट को एक स्ट्रिंग में कनवर्ट करें, उस लम्बाई को चुनें जिसे आप चाहते हैं।

float = str(float)[:5]

उपरोक्त एकल पंक्ति में, हमने मान को एक स्ट्रिंग में परिवर्तित कर दिया है, फिर स्ट्रिंग को केवल अपने पहले चार अंकों या वर्णों (समावेशी) में रखा है।

उम्मीद है की वो मदद करदे!


यह वही कर रहा है जो आपने इसे करने के लिए कहा था, और सही तरीके से काम कर रहा था। फ़्लोटिंग पॉइंट भ्रम के बारे में और पढ़ें और इसके बजाय decimal आजमाएं।


orig_float = 232569 / 16000.0

14.5355625

short_float = float("{:.2f}".format(orig_float)) 

14.54





precision