Я хочу a
округляться до 13,95 .
>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999
round
Функция не работает так , как я ожидал.
python
floating-point
rounding
precision
ShadowRanger
источник
источник
Ответы:
Вы сталкиваетесь со старой проблемой с числами с плавающей запятой, что не все числа могут быть представлены точно. Командная строка просто показывает вам полную форму с плавающей запятой из памяти.
С представлением с плавающей точкой ваша округленная версия - это то же число. Поскольку компьютеры являются двоичными, они хранят числа с плавающей запятой в виде целого числа, а затем делят его на степень двойки, поэтому 13,95 будет представлено аналогично 125650429603636838 / (2 ** 53).
Числа двойной точности имеют точность 53 бита (16 цифр), а обычные числа с плавающей точкой имеют точность 24 бита (8 цифр). Тип с плавающей точкой в Python использует двойную точность для хранения значений.
Например,
Если вам нужно только два десятичных знака (например, для отображения значения валюты), у вас есть пара лучших вариантов:
источник
"%.2f" % round(a,2)
вы можете вставить не только в printf, но и в такие вещи, какstr()
float
) является лишь ближайшим доступным приближением десятичного числа (с которым вы знакомы как человек). Не существует такого (конечно представимого) двоичного значения, как 0,245. Он просто не существует и математически не может существовать. Двоичное значение, которое ближе всего к 0,245, немного меньше, чем 0,245, поэтому, естественно, оно округляется вниз. Аналогично, в двоичном коде нет такой вещи, как 0,225, но двоичное значение, которое ближе всего к 0,225, немного больше, чем 0,225, поэтому, естественно, оно округляется.Decimal
, и это было одно из решений, представленных в этом ответе. Другой - преобразовать ваши величины в целое и использовать целочисленную арифметику. Оба этих подхода также появились в других ответах и комментариях.Появились новые спецификации формата, спецификация формата строки мини-язык :
Вы можете сделать так же, как:
Примечание 1: выше возвращает строку. Для того, чтобы получить как поплавок, просто оберните
float(...)
:Примечание 2: упаковка с помощью
float()
ничего не меняет:источник
'{0:,.2f}'.format(1333.949999999)
распечатать'1,333.95'
.float()
;float("{0:.2f}".format(13.9499999))
f"Result is {result:.2f}"
Встроенный
round()
прекрасно работает в Python 2.7 или более поздней версии.Пример:
Ознакомьтесь с документацией .
источник
round(2.16, 1)
дать2.2
почему питон просто предлагаютtruncate
FUNC>>> round(2.675, 2) 2.67
docs.python.org/2/tutorial/floatingpoint.htmlNote The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.
Я чувствую, что самый простой подход - это использовать
format()
функцию.Например:
Это создает число с плавающей точкой в виде строки, округленной до двух десятичных знаков.
источник
использование
вместо
Поскольку последнее может привести к ошибкам вывода при попытке вывести несколько переменных (см. Комментарии).
источник
Большинство чисел не могут быть точно представлены в числах с плавающей точкой. Если вы хотите округлить число, потому что это то, чего требует ваша математическая формула или алгоритм, тогда вы хотите использовать округление. Если вы просто хотите ограничить отображение с определенной точностью, то даже не используйте округление и просто отформатируйте его как эту строку. (Если вы хотите отобразить его каким-либо альтернативным методом округления, и есть тонны, то вам нужно смешать два подхода.)
И, наконец, хотя, возможно, самое главное, если вы хотите точную математику, то вы вообще не хотите плавать. Обычный пример - работа с деньгами и хранение центов в виде целого числа.
источник
Попробуйте код ниже:
источник
round
функции в первую очередь. Во-вторых, поскольку в этом решении все еще используется число с плавающей запятой, исходная проблема ОП сохраняется даже для «исправленной» версии этого «решения».round
функции (которая использовалась в вопросе).round()
не работает, как упомянуто OP.TLDR;)
Проблема округления ввода / вывода была окончательно решена в Python 2.7.0 и 3.1 .
Правильно округленное число может быть преобразовано обратимо назад и вперед:
str -> float() -> repr() -> float() ...
илиDecimal -> float -> str -> Decimal
Десятичный тип больше не нужен для хранения.
(Естественно, может потребоваться округлить результат сложения или вычитания округленных чисел, чтобы исключить накопленные ошибки последних битов. Явная десятичная арифметика может быть еще удобной, но преобразование в строковое значение
str()
(то есть с округлением до 12 действительных цифр ) обычно достаточно хорош, если не требуется чрезвычайной точности или большого числа последовательных арифметических операций.)Бесконечный тест :
Документация
Смотрите примечания к выпуску Python 2.7 - Изменения в других языках в четвертом абзаце:
Связанная проблема
Дополнительная информация: форматирование
float
до Python 2.7 было похоже на текущийnumpy.float64
. Оба типа используют одинаковую 64-битную IEEE 754 двойную точность с 52-битной мантиссой. Большая разница состоит в том, чтоnp.float64.__repr__
часто форматируется с чрезмерным десятичным числом, чтобы ни один бит не мог быть потерян, но между 13.949999999999999 и 13.950000000000001 не существует действительного числа IEEE 754. Результат не хороший, и преобразованиеrepr(float(number_as_string))
не обратимо с NumPy. С другой стороны:float.__repr__
отформатирован так, что важна каждая цифра; последовательность без пробелов и преобразование является обратимым. Проще говоря: если у вас, возможно, есть номер numpy.float64, преобразуйте его в обычное число с плавающей точкой, чтобы его можно было отформатировать для людей, а не для числовых процессоров, иначе в Python 2.7+ больше ничего не нужно.источник
float
(двойной точности) и обычномround
, а не о numpy.double и его преобразовании в строку. Простое округление Python действительно не может быть сделано лучше, чем в Python 2.7. Большинство ответов было написано до 2.7, но они устарели, хотя изначально они были очень хорошими. Это причина моего ответа.1
, кроме как во время «постепенного снижения уровня».a*b
противb*a
. Спасибо за ссылки - Ностальгия.С Python <3 (например, 2.6 или 2.7), есть два способа сделать это.
Но обратите внимание, что для версий Python выше 3 (например, 3.2 или 3.3) предпочтительнее второй вариант .
Для получения дополнительной информации о втором варианте я предлагаю эту ссылку на форматирование строки из документации Python .
И для получения дополнительной информации по первому варианту, эта ссылка будет достаточной и содержит информацию о различных флагах .
Ссылка: Преобразовать число с плавающей запятой с определенной точностью, а затем скопировать в строку
источник
numvar=12.456
, то"{:.2f}".format(numvar)
дает,12.46
но"{:2i}".format(numvar)
дает ошибку, и я ожидаю12
.Вы можете изменить формат вывода:
источник
Никто здесь, кажется, еще не упомянул об этом, поэтому позвольте мне привести пример в формате f-string / template-string в Python 3.6, который, на мой взгляд, прекрасно выглядит:
Это хорошо работает и с более длинными примерами, с операторами и не нуждающимися в скобках:
источник
Вы можете использовать оператор формата для округления значения до 2 десятичных знаков в python:
источник
В Python 2.7:
источник
output
имеет точно такое же значение, какa
, так что вы могли бы написатьprint a
вместоprint output
последней строки.13.95
. Но так жеprint a
, для этого конкретного значенияa
, в Python 2.7, так что не очень понятно, какой смысл был в шаге форматирования.a == output
код, который вы показываете? Это даетTrue
мне, и я подозреваю, что это делает и для вас.В руководстве по Python есть приложение под названием « Арифметика с плавающей точкой: проблемы и ограничения» . Прочитайте это. Это объясняет, что происходит и почему Python делает все возможное. У него есть даже пример, который соответствует вашему. Позвольте мне процитировать немного:
Альтернативой и решением ваших проблем будет использование
decimal
модуля.источник
Как указал @Matt, Python 3.6 предоставляет f-строки , и они также могут использовать вложенные параметры :
который будет отображать
result: 2.35
источник
Он делает именно то, что вы сказали, и работает правильно. Узнайте больше о путанице с плавающей точкой и, возможно, вместо этого попробуйте использовать десятичные объекты.
источник
Используйте комбинацию десятичного объекта и метода round ().
источник
Для исправления плавающей запятой в динамических типах языков, таких как Python и JavaScript, я использую эту технику
Вы также можете использовать десятичное число следующим образом:
источник
getcontext().prec = 6
работает только для объема функции или всех местах?Результаты:
источник
источник
Как насчет лямбда-функции, как это:
Таким образом, вы можете просто сделать:
и получить
источник
Это просто как 1,2,3:
используйте десятичный модуль для быстрой правильно округленной десятичной арифметики с плавающей точкой:
д = Десятичный (10000000.0000009)
добиться округления:
будут результаты с
Decimal('10000000.00')
ИЛИ
PS: критика других: форматирование не округляет.
источник
Для округления числа до разрешения лучше всего подходит следующий способ, который может работать с любым разрешением (0,01 для двух десятичных знаков или даже для других шагов):
источник
numpy.round
точности / точности. Таким образом, он требует определить его как int перед умножением с разрешением. Я обновил код. Спасибо за это!numpy.float64
результат np.round вfloat
или просто использоватьround(value, 2)
. Действительный номер IEEE 754 не существует между 13,949999999999999 (= 1395/100) и 3,950000000000001 (= 1395 * .01). Почему вы думаете, что ваш метод является лучшим? Исходное значение 13,949999999999999289 (= значение = округлое (значение, 2)) еще точнее, чем ваше 13,95000000000000178 (напечатано np.float96). Теперь к моему ответу добавлена дополнительная информация о numpy, по которой вы, вероятно, ошибочно проголосовали. Первоначально это не было о numpy.int
вас также можно использоватьfloat
пример @szeitlin. Спасибо за ваш дополнительный комментарий. (Извините, но я вас не понизил)лямбда x, n: int (x * 10 n + .5) / 10 n работал для меня много лет на многих языках.
источник
Я использую метод нарезки строк. Это относительно быстро и просто.
Во-первых, преобразуйте число с плавающей точкой в строку и выберите желаемую длину.
В приведенной выше строке мы преобразовали значение в строку, а затем сохранили строку только до первых четырех цифр или символов (включительно).
Надеюсь, это поможет!
источник