В документации для функции круглый() указано, что вы передаете ей число, а позиции после десятичной дроби нужно округлять. Таким образом, должен делает это:
n = 5.59
round(n, 1) # 5.6
Но, на самом деле, вкрадывается старая добрая странность с плавающей запятой, и вы получаете:
5.5999999999999996
Для пользовательского интерфейса мне нужно отобразить 5.6. Я покопался в Интернете и нашел документация, который зависит от моей реализации Python. К сожалению, это происходит как на моей машине разработчика Windows, так и на каждом сервере Linux, который я пробовал. Смотрите также здесь.
Есть ли способ обойти это без создания собственной круглой библиотеки?
На самом деле он не работает правильно, так это round(5.55, 1) = 5.5.
Отвечает ли это на ваш вопрос? Ограничение числа с плавающей запятой до двух десятичных знаков






Как насчет:
round(n,1)+epsilon
Это будет работать только в том случае, если округление будет постоянно отличаться от круглого числа на эпсилон. Если epsilon = .000001, то round(1.0/5.0, 1) + epsilon возьмет точное представление 0,2 и сделает его 0,00001. Не менее серьезные проблемы возникли бы, если бы эпсилон находился внутри круглой функции.
Ничего не могу поделать с тем, как он хранится, но, по крайней мере, форматирование работает правильно:
'%.1f' % round(n, 1) # Gives you '5.6'
Я пробовал print '%.2f' % 655.665, но он возвращает 655.66, он должен быть 655.67
@Kyrie см. stackoverflow.com/questions/9301690/…. Здесь виновата неточность с плавающей точкой - «5,665 -> 5,67», но «15,665 -> 15,66». Используйте десятичные дроби, если вам нужна точная точность.
это работает после поиска :) from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_DOWN # использовать для округления чисел с плавающей запятой Decimal(str(655.665)).quantize(Decimal('1.11'), rounding=ROUND_HALF_UP) # Проблемы и ограничения при использовании чисел с плавающей запятой
Вы можете переключить тип данных на целое число:
>>> n = 5.59
>>> int(n * 10) / 10.0
5.5
>>> int(n * 10 + 0.5)
56
А затем отобразите число, вставив десятичный разделитель языкового стандарта.
Однако Ответ Джимми лучше.
Вы можете использовать оператор формата строки %, аналогичный sprintf.
mystring = "%.2f" % 5.5999
Вы получите «5.6», если сделаете str(round(n, 1)) вместо round(n, 1).
Математика с плавающей запятой уязвима для небольших, но раздражающих погрешностей точности. Если вы можете работать с целым числом или фиксированной точкой, вам будет гарантирована точность.
printf присоска.
print '%.1f' % 5.59 # returns 5.6
Форматирование работает правильно даже без округления:
"%.1f" % n
Согласно документы, этот стиль форматирования строк со временем исчезнет. Формат нового стиля - "{:.1f}".format(n).
Не округляется правильно: '%.5f' % 0.988625 дает 0.98862
@schlamar: Это тоже поведение round (): round (0.988625,5) также дает 0.98862. round (0,988626,5), а также "% .5f"% 0,988626 дают 0,98863
к сожалению, "% .2f"% 2.675 вернет 2,67 - что может быть неожиданным ответом для тех, кто использует этот метод и ожидает 2,68
round(5.59, 1) работает нормально. Проблема в том, что 5.6 нельзя точно представить в двоичной системе с плавающей запятой.
>>> 5.6
5.5999999999999996
>>>
Как говорит Винко, вы можете использовать форматирование строк для округления при отображении.
У Python есть модуль для десятичной арифметики, если вам это нужно.
Это больше не проблема ни с Python 2.7, ни с Python 3.5.
Взгляните на Десятичный модуль
Decimal “is based on a floating-point model which was designed with people in mind, and necessarily has a paramount guiding principle – computers must provide an arithmetic that works in the same way as the arithmetic that people learn at school.” – excerpt from the decimal arithmetic specification.
и
Decimal numbers can be represented exactly. In contrast, numbers like 1.1 and 2.2 do not have an exact representations in binary floating point. End users typically would not expect 1.1 + 2.2 to display as 3.3000000000000003 as it does with binary floating point.
Decimal предоставляет такие операции, которые упрощают написание приложений, требующих операций с плавающей запятой, а также должен представлять эти результаты в удобочитаемом формате, например в бухгалтерском учете.
Если вы используете модуль Decimal, вы можете выполнить аппроксимацию без использования функции «округления». Вот что я использовал для округления, особенно при написании денежных приложений:
Decimal(str(16.2)).quantize(Decimal('.01'), rounding=ROUND_UP)
Это вернет десятичное число, равное 16,20.
rounding='ROUND_UP'
Если вы получаете эту ошибку NameError: global name 'ROUND_UP' is not defined, вам необходимо импортировать функцию округления: from decimal import Decimal, ROUND_UP. Другие функции округления
Ваш пример все еще кажется опасным: вы полагаетесь на округление, предоставляемое str ().
Это действительно большая проблема. Попробуйте этот код:
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),)
вы можете видеть истину: точка с плавающей запятой хранится как ближайшая конечная сумма дробей, знаменатели которой являются степенями двойки.
Отлично работает
format(5.59, '.1f') # to display
float(format(5.59, '.1f')) #to round
Я делаю:
int(round( x , 0))
В этом случае мы сначала правильно округляем на уровне единиц, а затем конвертируем в целое число, чтобы избежать печати числа с плавающей запятой.
так
>>> int(round(5.59,0))
6
Я думаю, что этот ответ работает лучше, чем формирование строки, и мне также удобнее использовать круглую функцию.
Вот где я вижу неудачу раунда. Что, если вы захотите округлить эти 2 числа до одного десятичного знака? 23,45 23,55 Мое образование заключалось в том, что округляя их, вы должны получить: 23,4 23,6 "правило" состоит в том, что вы должны округлять в большую сторону, если предыдущее число было нечетным, а не в большую, если предыдущее число было четным. Функция round в Python просто усекает 5.
То, о чем вы говорите, - это "банковское округление", один из множества различных способов выполнения округления.
Код:
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
Проблема только в том, что последняя цифра равна 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() в этом случае. Учитывать
print(round(61.295, 2))
print(round(1.295, 2))
выведет
61.3
1.29
что не является желаемым результатом, если вам нужно твердое округление до ближайшего целого числа. Чтобы обойти это поведение, используйте math.ceil() (или math.floor(), если хотите округлить в меньшую сторону):
from math import ceil
decimal_count = 2
print(ceil(61.295 * 10 ** decimal_count) / 10 ** decimal_count)
print(ceil(1.295 * 10 ** decimal_count) / 10 ** decimal_count)
выходы
61.3
1.3
Надеюсь, это поможет.
Другой возможный вариант:
def hard_round(number, decimal_places=0):
"""
Function:
- Rounds a float value to a specified number of decimal places
- Fixes issues with floating point binary approximation rounding in python
Requires:
- `number`:
- Type: int|float
- What: The number to round
Optional:
- `decimal_places`:
- Type: int
- What: The number of decimal places to round to
- Default: 0
Example:
```
hard_round(5.6,1)
```
"""
return int(number*(10**decimal_places)+0.5)/(10**decimal_places)
Вот простой способ округлить число с плавающей запятой до любого количества десятичных знаков, и он по-прежнему будет работать в 2021 году!
float_number = 12.234325335563
rounded = round(float_number, 3) # 3 is the number of decimal places to be returned.You can pass any number in place of 3 depending on how many decimal places you want to return.
print(rounded)
И это напечатает;
12.234
Я пробовал это с раундом python 2.7.11 (5.59), и он дает результат как 5.6 как в Windows, так и в 64-битной машине Linux x86, Cython? (Указанная ссылка на документацию теперь, я думаю, изменена)