الجولة() في بيثون لا يبدو أن التقريب بشكل صحيح

StackOverflow https://stackoverflow.com/questions/56820

  •  09-06-2019
  •  | 
  •  

سؤال

وثائق الجولة() وظيفة الدول التي تمر عليه عدد وظائف الماضي عشري إلى الجولة.وبالتالي فإنه يجب أن هل هذا:

n = 5.59
round(n, 1) # 5.6

ولكن في الواقع جيدة القديمة النقطة العائمة غرابة تزحف يمكنك الحصول على:

5.5999999999999996

لأغراض واجهة المستخدم, أنا بحاجة إلى عرض 5.6.أنا مطعون حول الإنترنت وجدت بعض الوثائق هذا يعتمد على تنفيذ بيثون.للأسف يحدث هذا على كل من ويندوز ديف الجهاز و كل خادم لينكس لقد حاولت. انظر هنا أيضا.

قصيرة خلق بلدي جولة المكتبة, هل هناك أي طريقة للتغلب على هذا ؟

هل كانت مفيدة؟

المحلول

أنا لا يمكن أن تساعد الطريقة التي يتم تخزينها ، ولكن على الأقل التنسيق يعمل بشكل صحيح:

'%.1f' % round(n, 1) # Gives you '5.6'

نصائح أخرى

التنسيق يعمل بشكل صحيح حتى دون الحاجة إلى جولة:

"%.1f" % n

إذا كنت تستخدم عشري الوحدة يمكنك التقريبي دون استخدام 'جولة' وظيفة.هنا هو ما كنت تستخدم التقريب خصوصا عند الكتابة النقدية التطبيقات:

Decimal(str(16.2)).quantize(Decimal('.01'), rounding=ROUND_UP)

هذا سيعود رقم عشري الذي هو 16.20.

round(5.59, 1) تعمل بشكل جيد.المشكلة هي أن 5.6 لا يمكن أن تكون ممثلة بالضبط في ثنائي النقطة العائمة.

>>> 5.6
5.5999999999999996
>>> 

كما فينكو يقول ، يمكنك استخدام سلسلة التنسيق للقيام التقريب للعرض.

الثعبان لديه وحدة الحساب العشري إذا كنت بحاجة إلى ذلك.

يمكنك الحصول على '5.6' إذا كنت لا str(round(n, 1)) بدلا من مجرد round(n, 1).

يمكنك التبديل إلى نوع بيانات عدد صحيح:

>>> n = 5.59
>>> int(n * 10) / 10.0
5.5
>>> int(n * 10 + 0.5)
56

ثم عرض عدد من إدخال الإعدادات المحلية هو الفاصل العشري.

ومع ذلك ، جيمي الإجابة هو أفضل.

النقطة العائمة الرياضيات هي عرضة طفيفة ، ولكن مزعج الدقة الدقة.إذا كان يمكنك العمل مع عدد صحيح أو نقطة ثابتة ، سوف تكون مضمونة الدقة.

نلقي نظرة على عشري وحدة

عشري "يستند إلى النقطة العائمة النموذج الذي تم تصميمه مع الناس في الاعتبار بالضرورة لديه قصوى المبدأ التوجيهي – أجهزة الكمبيوتر يجب أن يقدم الحساب الذي يعمل في نفس الطريقة كما في الحساب أن يتعلم الناس في المدرسة". – مقتطفات من عشري الحساب المواصفات.

و

الأرقام العشرية يمكن أن تكون ممثلة بالضبط.في المقابل, أرقام مثل 1.1 و 2.2 يكن لديك بالضبط تمثيل ثنائي العائمة نقطة.المستخدمين عادة لا نتوقع 1.1 + 2.2 لعرض كما 3.3000000000000003 كما يفعل مع ثنائي النقطة العائمة.

عشري يوفر هذا النوع من العمليات التي تجعل من السهل لكتابة التطبيقات التي تتطلب عمليات النقطة العائمة ، أيضا تحتاج إلى تقديم هذه النتائج في شكل مقروء الإنسان ، مثل المحاسبة.

إنها مشكلة كبيرة في الواقع.جرب هذا الكود:

print "%.2f" % (round((2*4.4+3*5.6+3*4.4)/8,2),)

فإنه يعرض 4.85.ثم يمكنك القيام به:

print "Media = %.1f" % (round((2*4.4+3*5.6+3*4.4)/8,1),)

ويظهر 4.8.هل الحسابات باليد الجواب الدقيق هو 4.85, ولكن إذا كنت في محاولة:

print "Media = %.20f" % (round((2*4.4+3*5.6+3*4.4)/8,20),)

يمكنك أن ترى الحقيقة:تعويم نقطة تخزين أقرب مبلغ محدود من الكسور التي القواسم القوى اثنين.

يمكنك استخدام سلسلة شكل المشغل %, ، على غرار sprintf.

mystring = "%.2f" % 5.5999

printf مصاصة.

print '%.1f' % 5.59  # returns 5.6

يعمل الكمال

format(5.59, '.1f') # to display
float(format(5.59, '.1f')) #to round

أنا أفعل:

int(round( x , 0))

في هذه الحالة, نحن الجولة الأولى بشكل صحيح على مستوى الوحدة ، ثم نتحول صحيح لتجنب الطباعة تعويم.

لذلك

>>> int(round(5.59,0))
6

أعتقد أن هذا الجواب يعمل بشكل أفضل من صيغة السلسلة ، كما أنه يجعل أكثر سنس لي أن استخدم الدالة round.

كود:

x1 = 5.63
x2 = 5.65
print(float('%.2f' % round(x1,1)))  # gives you '5.6'
print(float('%.2f' % round(x2,1)))  # gives you '5.7'

الإخراج:

5.6
5.7

هنا حيث أرى جولة الفشل.ما إذا كنت تريد هذه الجولة 2 أرقام إلى رقم عشري واحد?23.45 23.55 دراستي كانت من التقريب هذه يجب أن تحصل على:23.4 23.6 "القاعدة" يجري ذلك يجب أن جولة حتى لو السابق كان رقم غريب لا جولة حتى لو السابق عدد حتى.الجولة وظيفة في بيثون ببساطة باقتطاع 5.

المشكلة فقط عندما يكون الرقم الأخير هو 5.على سبيل المثال.0.045 داخليا تخزين 0.044999999999999...ببساطة يمكن أن الزيادة الأخيرة رقم 6 و جولة قبالة.هذا وسوف تعطيك النتائج المرجوة.

import re


def custom_round(num, precision=0):
    # Get the type of given number
    type_num = type(num)
    # If the given type is not a valid number type, raise TypeError
    if type_num not in [int, float, Decimal]:
        raise TypeError("type {} doesn't define __round__ method".format(type_num.__name__))
    # If passed number is int, there is no rounding off.
    if type_num == int:
        return num
    # Convert number to string.
    str_num = str(num).lower()
    # We will remove negative context from the number and add it back in the end
    negative_number = False
    if num < 0:
        negative_number = True
        str_num = str_num[1:]
    # If number is in format 1e-12 or 2e+13, we have to convert it to
    # to a string in standard decimal notation.
    if 'e-' in str_num:
        # For 1.23e-7, e_power = 7
        e_power = int(re.findall('e-[0-9]+', str_num)[0][2:])
        # For 1.23e-7, number = 123
        number = ''.join(str_num.split('e-')[0].split('.'))
        zeros = ''
        # Number of zeros = e_power - 1 = 6
        for i in range(e_power - 1):
            zeros = zeros + '0'
        # Scientific notation 1.23e-7 in regular decimal = 0.000000123
        str_num = '0.' + zeros + number
    if 'e+' in str_num:
        # For 1.23e+7, e_power = 7
        e_power = int(re.findall('e\+[0-9]+', str_num)[0][2:])
        # For 1.23e+7, number_characteristic = 1
        # characteristic is number left of decimal point.
        number_characteristic = str_num.split('e+')[0].split('.')[0]
        # For 1.23e+7, number_mantissa = 23
        # mantissa is number right of decimal point.
        number_mantissa = str_num.split('e+')[0].split('.')[1]
        # For 1.23e+7, number = 123
        number = number_characteristic + number_mantissa
        zeros = ''
        # Eg: for this condition = 1.23e+7
        if e_power >= len(number_mantissa):
            # Number of zeros = e_power - mantissa length = 5
            for i in range(e_power - len(number_mantissa)):
                zeros = zeros + '0'
            # Scientific notation 1.23e+7 in regular decimal = 12300000.0
            str_num = number + zeros + '.0'
        # Eg: for this condition = 1.23e+1
        if e_power < len(number_mantissa):
            # In this case, we only need to shift the decimal e_power digits to the right
            # So we just copy the digits from mantissa to characteristic and then remove
            # them from mantissa.
            for i in range(e_power):
                number_characteristic = number_characteristic + number_mantissa[i]
            number_mantissa = number_mantissa[i:]
            # Scientific notation 1.23e+1 in regular decimal = 12.3
            str_num = number_characteristic + '.' + number_mantissa
    # characteristic is number left of decimal point.
    characteristic_part = str_num.split('.')[0]
    # mantissa is number right of decimal point.
    mantissa_part = str_num.split('.')[1]
    # If number is supposed to be rounded to whole number,
    # check first decimal digit. If more than 5, return
    # characteristic + 1 else return characteristic
    if precision == 0:
        if mantissa_part and int(mantissa_part[0]) >= 5:
            return type_num(int(characteristic_part) + 1)
        return type_num(characteristic_part)
    # Get the precision of the given number.
    num_precision = len(mantissa_part)
    # Rounding off is done only if number precision is
    # greater than requested precision
    if num_precision <= precision:
        return num
    # Replace the last '5' with 6 so that rounding off returns desired results
    if str_num[-1] == '5':
        str_num = re.sub('5$', '6', str_num)
    result = round(type_num(str_num), precision)
    # If the number was negative, add negative context back
    if negative_number:
        result = result * -1
    return result

ماذا عن:

round(n,1)+epsilon
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top