पायथन 3.x गोलाई व्यवहार


176

मैं सिर्फ पाइथन 3.0 में नया क्या पढ़ रहा था और यह बताता है:

राउंड () फ़ंक्शन राउंडिंग रणनीति और रिटर्न प्रकार बदल गए हैं। सटीक आधे मामले अब शून्य से दूर होने के बजाय निकटतम परिणाम तक पहुंच गए हैं। (उदाहरण के लिए, राउंड (2.5) अब 3 के बजाय 2 रिटर्न।)

और दौर के लिए प्रलेखन :

अंतर्निहित प्रकारों के लिए समर्थन दौर () में, मानों को शक्ति माइनस n के 10 के निकटतम कई पर गोल किया जाता है; यदि दो गुणक समान रूप से पास हैं, तो गोलाई भी पसंद के अनुसार की जाती है

तो, v2.7.3 के तहत :

In [85]: round(2.5)
Out[85]: 3.0

In [86]: round(3.5)
Out[86]: 4.0

जैसा कि मुझे उम्मीद थी। हालाँकि, अब v3.2.3 के तहत :

In [32]: round(2.5)
Out[32]: 2

In [33]: round(3.5)
Out[33]: 4

यह काउंटर-सहज ज्ञान युक्त लगता है और इसके विपरीत जो मैं गोलाई के बारे में समझता हूं (और लोगों को यात्रा करने के लिए बाध्य करता हूं)। अंग्रेजी मेरी मूल भाषा नहीं है, लेकिन जब तक मैंने इसे पढ़ा, मुझे लगा कि मुझे पता है कि गोलाई का क्या मतलब है: - / मुझे यकीन है कि उस समय v3 पेश किया गया था, इस बारे में कुछ चर्चा हुई होगी, लेकिन मैं एक अच्छा कारण खोजने में असमर्थ था मेरी खोज।

  1. क्या किसी को इस बात की जानकारी है कि इसे क्यों बदला गया?
  2. क्या कोई अन्य मुख्यधारा की प्रोग्रामिंग भाषाएं हैं (उदाहरण के लिए, C, C ++, Java, पर्ल, ..) जो इस तरह की (मेरे लिए असंगत) गोलाई में हैं?

मुझे यहां क्या समझ नहीं आ रहा है?

अद्यतन करें: @ Li-aungYip की टिप्पणी "बैंकर की गोलाई" ने मुझे खोज करने के लिए सही खोज शब्द / कीवर्ड दिए और मुझे यह SO प्रश्न मिला: .NET डिफ़ॉल्ट रूप में बैंकर की गोलाई का उपयोग क्यों करता है? , इसलिए मैं इसे ध्यान से पढ़ूंगा।


27
मेरे पास इसे देखने का समय नहीं है, लेकिन मेरा मानना ​​है कि इसे "बैंकर की गोलाई" कहा जाता है। मेरा मानना ​​है कि यह वित्त उद्योग में आम है।
ली-आंग यिप

2
@ शहतूत अच्छी तरह से, हां, इसका व्यवहार अपने स्वयं के विवरण के अनुरूप है। तो अगर यह कहेंगे कि "गोलाई" इसके मूल्य को दोगुना कर रही है और उसने किया है, तो यह भी सुसंगत होगा :) .. लेकिन यह आम तौर पर गोलाई के विपरीत लगता है । इसलिए मैं एक बेहतर समझ की तलाश में हूं।
लेवोन

1
@ Li-aungYip लीड "बैंकर की गोलाई" के लिए धन्यवाद .. मैं इसे देखूंगा।
लेवोन


3
बस एक ध्यान दें: बैंकर्स गोलाई सिर्फ वित्त में आम नहीं है। इस तरह से मुझे प्राथमिक विद्यालय में पहले से ही 70 के दशक में राउंड करने के लिए सिखाया गया था :-)
लेन्नर्ट रेगेब्रो

जवाबों:


160

पाइथन 3.0 का तरीका इन दिनों मानक गोलाई पद्धति माना जाता है, हालांकि कुछ भाषा कार्यान्वयन बस में नहीं हैं।

सरल "हमेशा राउंड 0.5 अप" तकनीक का परिणाम उच्च संख्या की ओर थोड़ा पूर्वाग्रह होता है। बड़ी संख्या में गणना के साथ, यह महत्वपूर्ण हो सकता है। पायथन 3.0 दृष्टिकोण इस मुद्दे को समाप्त करता है।

आम उपयोग में गोलाई का एक से अधिक तरीका है। आईईईई 754, फ्लोटिंग-पॉइंट गणित के लिए अंतरराष्ट्रीय मानक, पांच अलग-अलग गोलाई विधियों को परिभाषित करता है (पायथन 3.0 द्वारा उपयोग किया जाने वाला डिफ़ॉल्ट है)। और अन्य हैं।

यह व्यवहार उतना व्यापक रूप से ज्ञात नहीं है जितना इसे होना चाहिए। AppleScript था, अगर मुझे सही ढंग से याद है, तो इस राउंडिंग विधि का शुरुआती अपनाने वाला। roundAppleScript में आदेश वास्तव में प्रस्ताव पास कई विकल्प है, लेकिन राउंड की ओर-यहां तक कि जाहिरा तौर पर इंजीनियर कार्यान्वित के रूप में यह आईईईई 754 में है डिफ़ॉल्ट है roundआदेश इतना करने के लिए सभी अनुरोधों से तंग आ चुके हो गया "यह काम है कि मैं में सीखा बनाने स्कूल "कि उसने अभी-अभी लागू किया है: round 2.5 rounding as taught in schoolएक मान्य AppleScript कमांड है। :-)


4
मुझे इस "डिफ़ॉल्ट मानक गोलाई पद्धति का इन दिनों बहुत अधिक सार्वभौमिक रूप से पता नहीं था", क्या आप (या कोई और) यह जान पाएंगे कि क्या C / C ++ / Java / Perl या कोई अन्य "मुख्य-धारा" भाषाएँ उसी तरह से लागू होती हैं?
लेवोन

3
रूबी करती है। Microsoft की .NET भाषाएँ इसे करती हैं। हालांकि जावा प्रकट नहीं होता है। मैं इसे हर संभव भाषा के लिए ट्रैक नहीं कर सकता, लेकिन मुझे लगता है कि यह हाल ही में डिज़ाइन की गई भाषाओं में सबसे आम है। मुझे लगता है कि C और C ++ पर्याप्त पुराने हैं जो वे नहीं करते हैं।
टाइप करें

5
माणिक रिटर्न के 3लिए2.5.round
jfs

14
मैंने AppleScript के इस से निपटने के बारे में थोड़ा जोड़ा क्योंकि मुझे व्यंग्यात्मक तरीके से "पुराने" व्यवहार को लागू करना पसंद है।
टाइप करें

2
@kindall यह विधि 1985 से IEEE डिफ़ॉल्ट राउंडिंग मोड है (जब IEEE 754-1985 प्रकाशित हुआ था)। यह C में कम से कम C89 (और इस तरह C ++ में) के बाद से डिफ़ॉल्ट राउंडिंग मोड भी रहा है, हालाँकि , C99 (और C ++ 11 से पहले छिटपुट समर्थन के साथ) "राउंड ()" फ़ंक्शन उपलब्ध है जो उपयोग करता है इसके बजाय शून्य से दूर दौर। आंतरिक फ़्लोटिंग पॉइंट राउंडिंग और फ़ंक्शंस का परिवार () फ़ैमिली अभी भी राउंडिंग मोड सेटिंग का पालन करता है, जो राउंड टाईल्स के लिए भी चूक करता है।
वॉलरिन

41

आप दशमलव मॉड्यूल का उपयोग करके Py3000 में प्राप्त होने वाली गोलाई को नियंत्रित कर सकते हैं :

>>> decimal.Decimal('3.5').quantize(decimal.Decimal('1'), 
    rounding=decimal.ROUND_HALF_UP)
>>> Decimal('4')

>>> decimal.Decimal('2.5').quantize(decimal.Decimal('1'),    
    rounding=decimal.ROUND_HALF_EVEN)
>>> Decimal('2')

>>> decimal.Decimal('3.5').quantize(decimal.Decimal('1'), 
    rounding=decimal.ROUND_HALF_DOWN)
>>> Decimal('3')

धन्यवाद .. मैं इस मॉड्यूल से परिचित नहीं था। किसी भी विचार मैं पायथन v 2.x का व्यवहार कैसे प्राप्त करूंगा? आपके द्वारा दिखाए गए उदाहरण ऐसा नहीं करते हैं। बस अगर यह संभव हो जाएगा उत्सुक है।
लेवोन

1
@ लेवोन: निरंतर ROUND_HALF_UPपाइथन 2.X के पुराने व्यवहार के समान है।
dawg

2
आप दशमलव मॉड्यूल के लिए एक संदर्भ भी निर्धारित कर सकते हैं जो आपके लिए निहित है। setcontext()समारोह देखें ।
kindall

यह वही है जो मैं आज ढूंढ रहा था। पायथन 3.4.3 में अपेक्षित रूप से कार्य करना। इसके अलावा ध्यान देने योग्य है, तो आप नियंत्रित कर सकते हैं कि कितना यह बदलकर दौर quantize(decimal.Decimal('1')के लिए quantize(decimal.Decimal('0.00')करता है, तो आप इस तरह के पैसे के लिए के रूप में निकटतम 100s के दौर करना चाहते हैं।
इगोर

यह सॉल्यूशन उतनी round(number, ndigits)ही देर के लिए रिप्लेसमेंट का काम करता ndigitsहै, जितना कि पॉजिटिव हो, लेकिन झुंझलाहट से आप इसका इस्तेमाल किसी चीज को बदलने में नहीं कर सकते round(5, -1)
पेक्का क्लर्क

15

बस यहाँ प्रलेखन से एक महत्वपूर्ण नोट जोड़ने के लिए:

https://docs.python.org/dev/library/functions.html#round

ध्यान दें

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

तो पायथन 3.2 में निम्नलिखित परिणाम प्राप्त करने के लिए आश्चर्यचकित न हों:

>>> round(0.25,1), round(0.35,1), round(0.45,1), round(0.55,1)
(0.2, 0.3, 0.5, 0.6)

>>> round(0.025,2), round(0.035,2), round(0.045,2), round(0.055,2)
(0.03, 0.04, 0.04, 0.06)

मैंने देखा। और मेरी पहली प्रतिक्रिया: 16-बिट सीपीयू का उपयोग कौन कर रहा है जो "2.67x" के सभी क्रमपरिवर्तन का प्रतिनिधित्व करने में असमर्थ है? यह कहते हुए कि फ्लोट में अंशों को व्यक्त नहीं किया जा सकता है, यहाँ एक बलि का बकरा लगता है: कोई भी आधुनिक सीपीयू गलत नहीं है, किसी भी लंगोटी में (अजगर को छोड़कर?)
एडम

9
@ एडम: मुझे लगता है कि आप गलत समझ रहे हैं। बोट्स को स्टोर करने के लिए उपयोग किए जाने वाले बाइनरी प्रारूप (IEEE 754 बाइनरी 64) 2.675बिल्कुल प्रतिनिधित्व नहीं कर सकता है: कंप्यूटर निकटतम हो सकता है 2.67499999999999982236431605997495353221893310546875। यह बहुत करीब है, लेकिन यह बिल्कुल बराबर नहीं है2.675 : यह करने के लिए की तुलना में बहुत करीब 2.67है 2.68। तो roundफ़ंक्शन सही काम करता है, और इसे लगभग 2-अंक-के-बाद-बिंदु के मूल्य पर गोल करता है, अर्थात् 2.67। इसका पायथन से कोई लेना-देना नहीं है, और बाइनरी फ्लोटिंग-पॉइंट के साथ सब कुछ करना है।
मार्क डिकिन्सन

3
यह "सही बात" नहीं है क्योंकि इसे एक स्रोत-कोड स्थिर दिया गया था :), लेकिन मैं आपकी बात देखता हूं।
एडम

@ एडम: मैं जेएस में इसी विचित्रता में भाग गया, इससे पहले कि यह भाषा विशिष्ट नहीं है।
इगोर

5

मुझे हाल ही में इसके साथ भी समस्याएं थीं। इसलिए, मैंने एक पायथन 3 मॉड्यूल विकसित किया है जिसमें 2 फ़ंक्शंस trueround () और trueround_preaches () हैं जो इसे संबोधित करते हैं और समान गोलाई व्यवहार देते हैं जिनका उपयोग प्राथमिक विद्यालय (बैंकर के राउंडिंग) से किया जाता है। यहाँ मॉड्यूल है। बस कोड को सहेजें और इसे कॉपी करें या आयात करें। नोट: trueround_preaches मॉड्यूल ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_UP, और ROUND_05 फ़्लैग फ़्लैग के अनुसार आवश्यकताओं के आधार पर गोलाई व्यवहार को बदल सकता है। नीचे दिए गए फ़ंक्शंस के लिए, डॉकस्ट्रिंग देखें या मदद (ट्रुअराउंड) और मदद (trueround_preaches) को आगे के दस्तावेज़ के लिए दुभाषिया में कॉपी करें।

#! /usr/bin/env python3
# -*- coding: utf-8 -*-

def trueround(number, places=0):
    '''
    trueround(number, places)

    example:

        >>> trueround(2.55, 1) == 2.6
        True

    uses standard functions with no import to give "normal" behavior to 
    rounding so that trueround(2.5) == 3, trueround(3.5) == 4, 
    trueround(4.5) == 5, etc. Use with caution, however. This still has 
    the same problem with floating point math. The return object will 
    be type int if places=0 or a float if places=>1.

    number is the floating point number needed rounding

    places is the number of decimal places to round to with '0' as the
        default which will actually return our interger. Otherwise, a
        floating point will be returned to the given decimal place.

    Note:   Use trueround_precision() if true precision with
            floats is needed

    GPL 2.0
    copywrite by Narnie Harshoe <signupnarnie@gmail.com>
    '''
    place = 10**(places)
    rounded = (int(number*place + 0.5if number>=0 else -0.5))/place
    if rounded == int(rounded):
        rounded = int(rounded)
    return rounded

def trueround_precision(number, places=0, rounding=None):
    '''
    trueround_precision(number, places, rounding=ROUND_HALF_UP)

    Uses true precision for floating numbers using the 'decimal' module in
    python and assumes the module has already been imported before calling
    this function. The return object is of type Decimal.

    All rounding options are available from the decimal module including 
    ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, 
    ROUND_HALF_UP, ROUND_UP, and ROUND_05UP.

    examples:

        >>> trueround(2.5, 0) == Decimal('3')
        True
        >>> trueround(2.5, 0, ROUND_DOWN) == Decimal('2')
        True

    number is a floating point number or a string type containing a number on 
        on which to be acted.

    places is the number of decimal places to round to with '0' as the default.

    Note:   if type float is passed as the first argument to the function, it
            will first be converted to a str type for correct rounding.

    GPL 2.0
    copywrite by Narnie Harshoe <signupnarnie@gmail.com>
    '''
    from decimal import Decimal as dec
    from decimal import ROUND_HALF_UP
    from decimal import ROUND_CEILING
    from decimal import ROUND_DOWN
    from decimal import ROUND_FLOOR
    from decimal import ROUND_HALF_DOWN
    from decimal import ROUND_HALF_EVEN
    from decimal import ROUND_UP
    from decimal import ROUND_05UP

    if type(number) == type(float()):
        number = str(number)
    if rounding == None:
        rounding = ROUND_HALF_UP
    place = '1.'
    for i in range(places):
        place = ''.join([place, '0'])
    return dec(number).quantize(dec(place), rounding=rounding)

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

Narnie


5

पायथन 3.x राउंड .5 एक पड़ोसी के लिए मान जो भी है

assert round(0.5) == 0
assert round(1.5) == 2
assert round(2.5) == 2

import decimal

assert decimal.Decimal('0.5').to_integral_value() == 0
assert decimal.Decimal('1.5').to_integral_value() == 2
assert decimal.Decimal('2.5').to_integral_value() == 2

हालाँकि, कोई दशमलव राउंडिंग को "बैक" में हमेशा राउंड में बदल सकता है। यदि आवश्यक हो तो:

decimal.getcontext().rounding = decimal.ROUND_HALF_UP

assert decimal.Decimal('0.5').to_integral_value() == 1
assert decimal.Decimal('1.5').to_integral_value() == 2
assert decimal.Decimal('2.5').to_integral_value() == 3

i = int(decimal.Decimal('2.5').to_integral_value()) # to get an int
assert i == 3
assert type(i) is int

1

अजगर 3 में पायथन 2 राउंडिंग व्यवहार।

15 वें दशमलव स्थानों पर 1 जोड़ना। 15 अंकों तक सटीकता।

round2=lambda x,y=None: round(x+1e-15,y)

3
क्या आप इस सूत्र के पीछे के अंतर्ज्ञान की व्याख्या कर सकते हैं?
हादि

2
मैं जो समझता हूं, वह अंश जो सही ढंग से प्रस्तुत नहीं किया जा सकता है, वह 15 9 तक होगा, फिर अपव्यय। उदाहरण के लिए, 2.675है 2.67499999999999982236431605997495353221893310546875। 1e-15 को जोड़ने से यह 2.675 से अधिक हो जाएगा और इसे सही तरीके से गोल कर देगा। यदि अंश पहले से ही कोड स्थिर है, तो 1e-15 को जोड़ने से गोलाई में कुछ भी नहीं बदलेगा।
बेनोइट डुफ्रेसने

1

कुछ मामले:

in: Decimal(75.29 / 2).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
in: round(75.29 / 2, 2)
out: 37.65 GOOD

in: Decimal(85.55 / 2).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)
in: round(85.55 / 2, 2)
out: 42.77 BAD

फिक्स के लिए:

in: round(75.29 / 2 + 0.00001, 2)
out: 37.65 GOOD
in: round(85.55 / 2 + 0.00001, 2)
out: 42.78 GOOD

यदि आप अधिक दशमलव चाहते हैं, उदाहरण के लिए 4, आपको (+ 0.0000001) जोड़ना चाहिए।

मेरे लिए काम।


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

-1

नमूना प्रजनन:

['{} => {}'.format(x+0.5, round(x+0.5)) for x in range(10)]

['0.5 => 0', '1.5 => 2', '2.5 => 2', '3.5 => 4', '4.5 => 4', '5.5 => 6', '6.5 => 6', '7.5 => 8', '8.5 => 8', '9.5 => 10']

एपीआई: https://docs.python.org/3/library/functions.html#round

राज्य अमेरिका:

दशमलव बिंदु के बाद ndigits के चक्कर में वापसी संख्या। यदि ndigits को छोड़ दिया गया है या कोई भी नहीं है, तो वह अपने इनपुट में निकटतम पूर्णांक लौटाता है।

अंतर्निहित समर्थन दौर () के लिए, मानों को शक्ति माइनस ndigits के 10 के निकटतम कई पर गोल किया जाता है; यदि दो गुणक समान रूप से पास हैं, तो गोलाई भी पसंद के अनुसार की जाती है (इसलिए, उदाहरण के लिए, दोनों गोल (0.5) और गोल (-0.5) 0 हैं, और गोल) (1.5) 2 है। कोई भी पूर्णांक मान ndigits (सकारात्मक, शून्य या नकारात्मक) के लिए मान्य है। रिटर्न मान एक पूर्णांक है यदि ndigits को छोड़ दिया गया है या कोई भी नहीं है। अन्यथा वापसी मूल्य में नंबर के समान प्रकार है।

एक सामान्य पायथन ऑब्जेक्ट संख्या के लिए, गोल प्रतिनिधियों को संख्या के लिए। दौर

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

इस अंतर्दृष्टि को देखते हुए आप इसे हल करने के लिए कुछ गणित का उपयोग कर सकते हैं

import math
def my_round(i):
  f = math.floor(i)
  return f if i - f < 0.5 else f+1

अब आप राउंड के बजाय my_round के साथ एक ही टेस्ट चला सकते हैं।

['{} => {}'.format(x + 0.5, my_round(x+0.5)) for x in range(10)]
['0.5 => 1', '1.5 => 2', '2.5 => 3', '3.5 => 4', '4.5 => 5', '5.5 => 6', '6.5 => 7', '7.5 => 8', '8.5 => 9', '9.5 => 10']

-2

पायथन 3.x में गोल करने का सबसे आसान तरीका, जैसा कि स्कूल में सिखाया जाता है, एक सहायक चर का उपयोग कर रहा है:

n = 0.1 
round(2.5 + n)

और ये श्रृंखला के परिणाम 2.0 से 3.0 (0.1 चरणों में) होंगे:

>>> round(2 + n)
>>> 2

>>> round(2.1 + n)
>>> 2

>>> round(2.2 + n)
>>> 2

>>> round(2.3 + n)
>>> 2

>>> round(2.4 + n)
>>> 2

>>> round(2.5 + n)
>>> 3

>>> round(2.6 + n)
>>> 3

>>> round(2.7 + n)
>>> 3

>>> round(2.8 + n)
>>> 3

>>> round(2.9 + n)
>>> 3

>>> round(3 + n)
>>> 3

-2

आप math.ceil मॉड्यूल का उपयोग करके अपनी गोलाई को नियंत्रित कर सकते हैं:

import math
print(math.ceil(2.5))
> 3

वह हमेशा अपने दशमलव भाग के बिना नंबर लौटाएगा, यह गोलाई नहीं है। Ceil (2.5) = 2, Ceil (2.99) = 2
krafter

1
python3 + में, यदि संख्या तर्क एक धनात्मक या ऋणात्मक संख्या है, तो छत फ़ंक्शन सीलिंग मान लौटाता है।
Eds_k

[१४] में: math.ceil (२.९९) आउट [१४]: ३
१k

हां, मुझे माफ करना मैं गलत था। छत () छत के मूल्य को लौटाता है, जबकि मंजिल () मैं जिस बारे में बात कर रहा था, उसे वापस करता है। लेकिन फिर भी, मेरी राय में यह काफी नहीं गोलाई व्यवहार है (इन दोनों कार्यों)
krafter

-4

इस कोड को आज़माएं:

def roundup(input):   
   demo = input  if str(input)[-1] != "5" else str(input).replace("5","6")
   place = len(demo.split(".")[1])-1
   return(round(float(demo),place))

परिणाम होगा:

>>> x = roundup(2.5)
>>> x
3.0  
>>> x = roundup(2.05)
>>> x
2.1 
>>> x = roundup(2.005)
>>> x
2.01 

आप यहां देख सकते हैं: https://i.stack.imgur.com/QQUkS.png

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.