الجولة() في بيثون لا يبدو أن التقريب بشكل صحيح
-
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