Ограничение числа с плавающей запятой до двух десятичных знаков

Я хочу, чтобы a был округлен до 13,95.

>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999

Функция round работает не так, как я ожидал.

stackoverflow.com/questions/249467/…
user3850 18.01.2009 22:42

Важно, чтобы валюта не была плавающей. Поплавки неточные. Но суммы в пенни или центах - целые числа. Следовательно, целые числа - это правильный способ представления валюты.

Davoud Taghawi-Nejad 16.07.2012 02:44

@ DavoudTaghawi-Nejad или более точно ... Десятичный тип

Basic 08.04.2013 15:01

Хм ... Вы пытаетесь представлять валюту? Если это так, вам не следует использовать поплавки для долларов. Вероятно, вы могли бы использовать числа с плавающей запятой для пенни или любой другой наименьшей общей денежной единицы, которую вы пытаетесь смоделировать, но лучше всего использовать десятичное представление, как предложил ХУАГАГУА в своем ответе.

SingleNegationElimination 13.04.2009 07:39

@Basic, это зависит (в основном нет). Использование целых чисел в центах или пенни - это доказательство глупости. Это отраслевой стандарт представления денег. Если вы знаете, что делаете, хорошо разбираетесь в арифметике с плавающей запятой и десятичном классе Python, вы можете использовать decimal. Но это во многом зависит от вашей проблемы. Вам нужны десятичные дроби произвольной точности? Или всего две цифры? Если две цифры: целое. Это убережет вас от неприятностей. Источник Я работал в консалтинговой компании по программному обеспечению для банковского дела.

Davoud Taghawi-Nejad 17.04.2014 21:56

Я, наверное, приду сюда слишком поздно, но я хотел спросить, решили ли разработчики Python эту проблему? Потому что, когда я округляю (13,949999999999999, 2), я просто получаю 13,95. Я пробовал это в Python 2.7.6, а также в 3.4. Оно работает. Не уверен, что 2.7 вообще было там в 2009 году. Может быть, это вещь Python 2.5?

bad_keypoints 22.09.2015 08:51

@bad_keypoints: Да, проблема округления решена с помощью Python 2.7.0+. Подробнее в мой ответ здесь

hynekcer 29.07.2016 20:55

@ DavoudTaghawi-Nejad суммы пенни или цента являются целыми числами, не по ценам на бензин ...

gerrit 13.03.2017 17:19

Они по-прежнему целые, но с более низким базовым значением. Например, 0,5 цента будет 500 номиналом 1/1000 цента.

Davoud Taghawi-Nejad 14.03.2017 18:38

Он работает для меня на Python 2.7. Должно быть обновлено

Palak Bansal 10.09.2020 19:43
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1 876
11
3 836 927
29

Ответы 29

Вы сталкиваетесь с старая проблема с числами с плавающей запятой, которые не все числа могут быть представлены точно. Командная строка просто показывает вам полную форму с плавающей запятой из памяти.

С представлением с плавающей запятой ваша округленная версия - это то же самое число. Поскольку компьютеры являются двоичными, они хранят числа с плавающей запятой как целое число, а затем делят его на степень двойки, так что 13,95 будет представлено аналогично 125650429603636838 / (2 ** 53).

Числа с двойной точностью имеют точность 53 бита (16 цифр), а обычные числа с плавающей запятой имеют точность 24 бита (8 цифр). тип с плавающей запятой в Python использует двойную точность для хранения значений.

Например,

>>> 125650429603636838/(2**53)
13.949999999999999

>>> 234042163/(2**24)
13.949999988079071

>>> a = 13.946
>>> print(a)
13.946
>>> print("%.2f" % a)
13.95
>>> round(a,2)
13.949999999999999
>>> print("%.2f" % round(a, 2))
13.95
>>> print("{:.2f}".format(a))
13.95
>>> print("{:.2f}".format(round(a, 2)))
13.95
>>> print("{:.15f}".format(round(a, 2)))
13.949999999999999

Если у вас есть только два десятичных знака (например, для отображения значения валюты), у вас есть несколько лучших вариантов:

  1. Используйте целые числа и сохраняйте значения в центах, а не в долларах, а затем разделите на 100, чтобы преобразовать их в доллары.
  2. Или используйте число с фиксированной запятой, например десятичный.

Но как насчет того, чтобы число увеличилось с 13,95 до, скажем, 13,90? Тогда мой результат будет 13,9. Я бы хотел, чтобы он показывал ноль.

Christian 11.09.2012 19:25

@Christian Существует фундаментальная разница между сохраненным значением и тем, как вы отображать это значение. Форматирование вывода должно позволить вам добавлять отступы по мере необходимости, а также добавлять разделители запятых и т. д.

Basic 08.04.2013 15:03

Стоит отметить, что "%.2f" % round(a,2) можно вставлять не только в printf, но и в такие вещи, как str()

andilabs 01.11.2013 05:15

почему люди всегда предполагают, что валюта округляется с плавающей запятой? иногда просто хочется работать с меньшей точностью.

worc 12.01.2014 03:56

Следует отметить, что "%.2f" %0.245 будет выводить '0.24', т.е. он округляет только 6 или больше

user2426679 07.06.2014 02:23

@ user2426679: Кажется, вы не поняли этого ответа. Попробуйте округлить 0,225 до двух десятичных знаков.

John Y 18.06.2014 02:43

Примечание. В формате 0 позиционный аргумент не нужен в python 2.7 или 3.1, я думал, что это часть формата и получил странные результаты :) ("{: .2f}". Format (a)

Alex Punnen 11.12.2015 10:16

@JohnY, почему тогда 0,245 раунда до 0,24, а 0,225 раунда правильно? Хотелось бы 0,245 округлить до 0,25

radtek 14.06.2016 20:41

@radtek: Вы должны понимать, что двоичное значение (типа float) - это всего лишь ближайшая доступная аппроксимация десятичного числа (с которым вы знакомы как человек). Не существует такого (конечно представимого) двоичного значения, как 0,245. Его просто не существует, а математически не могу существует. Двоичное значение, которое ближе всего к 0,245, немного меньше, чем 0,245, поэтому, естественно, оно округляется в меньшую сторону. Точно так же в двоичном формате нет такой вещи, как 0,225, но двоичное значение, которое ближе всего к 0,225, немного больше чем 0,225, поэтому, естественно, оно округляется в большую сторону.

John Y 14.06.2016 22:06

@JohnY Я не просил объяснений, просто решение. Я думаю, что единственное решение - использовать десятичный тип, если только кто-то не может назвать лучший.

radtek 15.06.2016 22:13

@radtek: Вы буквально просили объяснений. Самым простым решением действительно является использование Decimal, и это было одно из решений, представленных в этом ответе. Другой заключался в преобразовании ваших количеств в целые числа и использовании целочисленной арифметики. Оба этих подхода также упоминались в других ответах и ​​комментариях.

John Y 15.06.2016 22:45

Кстати, начиная с Python 3.6 мы можем использовать f-строки: f"Result is {result:.2f}"

Andrey Semakin 20.02.2019 15:53

как это работает, если я хочу добавить строку вперед, например: print ('blabla floatnumber function (x))

PV8 27.06.2019 17:00

Я не мог правильно понять, почему питон хранит число, а затем делит его на другое число вместо хранения реального значения числа? Почему у нас этого нет в C++, C# или ...? Почему мы не можем сохранить 0,0001_0000_0000_0000 ... для 0,1?

Mahdi Amrollahi 02.12.2019 12:48

@MahdiAmrollahi: У компьютеров есть биты. Они не могут хранить «реальные числа». Они просто складывают кусочки и интерпретируют их обычным образом. Для целых чисел это довольно просто (многие биты - это число с основанием 2). Но только с 0 и 1 вы не можете сохранить «реальное значение», особенно если реальное значение является иррациональным значением (например, пи). Арифметика IEEE-754 (float в Python, float / double в C / C++ / C#) эффективна и «достаточно близка». Существуют более точные варианты (fractions.Fraction, decimal.Decimal; последний использует формат хранения, аналогичный тому, который вы просите), но они медленнее и больше.

ShadowRanger 12.12.2020 09:48

Вы можете изменить формат вывода:

>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95

Он делает именно то, что вы ему сказали, и работает правильно. Узнайте больше о путаница с плавающей запятой и, возможно, попробуйте вместо этого объекты десятичный.

Большинство чисел не могут быть точно представлены в числах с плавающей запятой. Если вы хотите округлить число, потому что это то, что требует ваша математическая формула или алгоритм, тогда вам нужно использовать round. Если вы просто хотите ограничить отображение определенной точностью, даже не используйте round и просто отформатируйте его как эту строку. (Если вы хотите отобразить его с помощью какого-либо альтернативного метода округления, а их много, вам нужно смешать два подхода.)

>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'

И, наконец, что, пожалуй, наиболее важно, если вам нужна математика точный, вам вообще не нужны числа с плавающей запятой. Обычный пример имеет дело с деньгами и хранением «центов» как целого числа.

Учебник Python имеет приложение под названием Арифметика с плавающей запятой: проблемы и ограничения. Прочтите это. Он объясняет, что происходит и почему Python делает все возможное. Есть даже пример, соответствующий вашему. Позвольте мне немного процитировать:

>>> 0.1
0.10000000000000001

you may be tempted to use the round() function to chop it back to the single digit you expect. But that makes no difference:

>>> round(0.1, 1)
0.10000000000000001

The problem is that the binary floating-point value stored for “0.1” was already the best possible binary approximation to 1/10, so trying to round it again can’t make it better: it was already as good as it gets.

Another consequence is that since 0.1 is not exactly 1/10, summing ten values of 0.1 may not yield exactly 1.0, either:

>>> sum = 0.0
>>> for i in range(10):
...     sum += 0.1
...
>>> sum
0.99999999999999989

Альтернативой и решением ваших проблем было бы использование модуля decimal.

Появились новые спецификации формата Спецификация строкового формата Мини-язык:

Вы можете сделать то же самое, что и:

"{:.2f}".format(13.949999999999999)

Примечание 1: выше возвращает строку. Чтобы получить float, просто оберните float(...):

float("{:.2f}".format(13.949999999999999))

Обертывание Заметка 2: с float() ничего не меняет:

>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True

Чтобы добавить запятые, вы также можете '{0:,.2f}'.format(1333.949999999), который печатает '1,333.95'.

Stephen Blum 20.06.2014 06:41

@ OnurYıldırım: да, но вы можете обернуть это float(); float("{0:.2f}".format(13.9499999))

Jossef Harush 17.08.2014 17:22

@JossefHarush, вы можете обернуть его с помощью float (), но вы ничего не получили. Теперь у вас снова есть поплавок с той же неточностью. 13.9499999999999 и 13.95 - это одно и то же число с плавающей запятой.

Ned Batchelder 17.08.2014 17:52

@NedBatchelder: я согласен, что они равны, но это ограничивает число с плавающей запятой двумя десятичными точками :)

Jossef Harush 17.08.2014 18:09

Нет возможности «округлить» число. Форматирование просто для красивой печати. Если вам действительно нужно хранить цифры (например, отслеживать деньги), используйте целые числа.

Neil 08.10.2017 00:41

@NeilChowdhury Верно, я спросил меня то же самое после того, как написал ответ. Предположение вопроса состоит в том, чтобы отобразить число с плавающей запятой с точностью до двух десятичных знаков.

Xolve 08.10.2017 06:43

Обратите внимание, что если вы хотите отформатировать более одного числа, вам нужно увеличить целое число перед двоеточием: >>> print ("{0: .2f} - {0: .2f}". Format (.1234, .5678 )) 0,12 - 0,12 >>> print ("{0: .2f} - {1: .2f}". Format (.1234, .5678)) 0,12 - 0,57

AlejandroVD 15.11.2017 21:33

Кстати, начиная с Python 3.6 мы можем использовать f-строки: f"Result is {result:.2f}"

Andrey Semakin 20.02.2019 15:54

Попробуйте следующий код:

>>> a = 0.99334
>>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
>>> print a
0.99

Но будьте осторожны, значение a по-прежнему является неточным. Взгляните сюда - repl.it/LJs (нажмите «Запустить сеанс» в верхней части правого раздела).

lifebalance 02.10.2013 23:23

Если вы придерживаетесь этого подхода, вам следует добавить 0,5 для более точного представления. интервал (а * 100 + 0,5) / 100,0; Другой вариант - использовать math.ceil.

arhuaco 08.11.2013 04:11

Если участник собирается проголосовать против этого ответа, пожалуйста, предоставьте объяснение, чтобы мы могли понять, что не так в этом подходе. По причине, упомянутой OriolJ, я считаю, что это лучший ответ.

Shashank Sawant 08.06.2014 08:55

@ShashankSawant: Ну, во-первых, ответ в представленном виде не округляется, а обрезается. Предложение добавить половину в конце будет округлено, но тогда в этом нет никакой пользы, чем просто использовать функцию round в первую очередь. Во-вторых, поскольку это решение все еще использует плавающую точку, исходная проблема OP остается даже для «исправленной» версии этого «решения».

John Y 18.06.2014 02:54

-1, это просто ненужная повторная реализация функции round (которая использовалась в вопросе).

interjay 13.09.2014 02:55

@interjay, который необходим, если round() не работает, как указано в OP.

Pithikos 18.02.2015 16:28

Это отлично работает в Python 3, вам просто нужно убедиться, что вы включили .0 в знаменатель.

duhaime 05.03.2018 03:08

@Pithikos round() работает нормально, и этот код не работает лучше. Проблема в том, что Python использует двоичные числа с плавающей запятой, и наиболее близким к 13.95 является 13.949999999999999. Если вы видите код, который генерирует любое другое число, это потому, что при преобразовании в строку применяется большее округление. См. Математика с плавающей запятой не работает?.

Mark Ransom 19.12.2019 02:00

Для Python <3 (например, 2.6 или 2.7) это можно сделать двумя способами.

# Option one 
older_method_string = "%.9f" % numvar

# Option two (note ':' before the '.9f')
newer_method_string = "{:.9f}".format(numvar)

Но обратите внимание, что для версий Python выше 3 (например, 3.2 или 3.3) второй вариант - предпочтительный.

Для получения дополнительной информации о втором варианте я предлагаю эту ссылку на форматирование строк из документации Python.

И для получения дополнительной информации о первом варианте этой ссылки будет достаточно, и она содержит информацию о различных флагах.

Ссылка: Преобразуйте число с плавающей запятой до определенной точности, а затем скопируйте в строку

Как вы представляете целое число? Если я использую "{i3}". Format (numvar), я получаю сообщение об ошибке.

skytux 12.12.2013 19:29

Вот что я имею в виду: если numvar=12.456, то "{:.2f}".format(numvar) дает 12.46, но "{:2i}".format(numvar) выдает ошибку, и я ожидаю 12.

skytux 12.12.2013 19:47

Для исправления плавающей запятой в языках с динамическим типом, таких как Python и JavaScript, я использую эту технику.

# For example:
a = 70000
b = 0.14
c = a * b

print C# Prints 980.0000000002
# Try to fix
c = int(c * 10000)/100000
print C# Prints 980

Вы также можете использовать Decimal следующим образом:

from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
# Results in 6 precision -> Decimal('0.142857')

getcontext().prec = 28
Decimal(1) / Decimal(7)
# Results in 28 precision -> Decimal('0.1428571428571428571428571429')
getcontext().prec = 6 работает только в рамках функции или во всех местах?
Julio Marins 04.10.2017 23:12

Контексты - это среда для арифметических операций. Они регулируют точность, устанавливают правила округления, определяют, какие сигналы обрабатываются как исключения, и ограничивают диапазон показателей. У каждого потока есть свой текущий контекст @JulioMarins

Siamand 04.10.2017 23:32

Я считаю, что самый простой подход - использовать функцию format().

Например:

a = 13.949999999999999
format(a, '.2f')

13.95

В результате получается число с плавающей запятой в виде строки, округленной до двух десятичных знаков.

Чтобы округлить число до разрешения, лучше всего использовать следующий способ, который может работать с любым разрешением (0,01 для двух знаков после запятой или даже с другими шагами):

>>> import numpy as np
>>> value = 13.949999999999999
>>> resolution = 0.01
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
13.95

>>> resolution = 0.5
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
14.0

у меня не работает на python 3.4.3 и numpy 1.9.1? >>> import numpy as np >>> res = 0.01 >>> value = 0.184 >>> np.round (value / res) * res 0.17999999999999999

szeitlin 11.04.2016 19:34

Ищу документацию, я вижу, что проблема связана с точностью / точностью numpy.round. Поэтому перед умножением с разрешением необходимо определить его как int. Я обновил код. Спасибо тебе за это!

iblasi 13.04.2016 19:28

Единственное, что необходимо - это преобразовать результат numpy.float64 из np.round в float или просто использовать round(value, 2). Не существует действительного номера IEEE 754 между 13.949999999999999 (= 1395 / 100.) и 3.950000000000001 (= 1395 * .01). Как вы думаете, почему ваш метод самый лучший? Исходное значение 13.949999999999999289 (= value = round (value, 2)) даже более точное, чем ваше 13.95000000000000178 (напечатанное np.float96). Дополнительная информация также для numpy теперь добавлена ​​в мой ответ, который вы, вероятно, проголосовали против по ошибке. Изначально речь не шла о numpy.

hynekcer 15.04.2016 16:04

@hynekcer Не думаю, что мой ответ лучший. Просто хотел добавить пример предельного числа с плавающей запятой до n десятичных знаков, но ближайшего к определенному разрешению. Как вы сказали, я проверил, что вместо int вы также можете использовать float для примера @szeitlin. Спасибо за дополнительный комментарий. (Извините, но я не голосовал против вас)

iblasi 15.04.2016 23:49

Добавление совершенно новой зависимости для числовой обработки (панд) - это «лучший способ»?

Hejazzman 18.04.2019 17:13

Я использую метод нарезки строк. Это относительно быстро и просто.

Сначала преобразуйте float в строку, выберите желаемую длину.

float = str(float)[:5]

В единственной строке выше мы преобразовали значение в строку, а затем сохранили строку только с ее первыми четырьмя цифрами или символами (включительно).

Надеюсь, это поможет!

Пожалуйста, не публикуйте одинаковые ответы на несколько вопросов.

vaultah 31.12.2015 11:18

Ничего себе ... tdh ... Пожалуйста, никогда не создавайте никаких бухгалтерских программ ... Что произойдет, если число окажется 113.94 ?? это приведет к 113.9 ... оставив 0,04 пропущенным .... Также на это уже есть ответы более 5 лет назад ....

Angry 84 08.01.2016 06:33

TL; DR;)

Проблема округления ввода / вывода была окончательно решен Python 2.7.0 и 3.1.

Правильно округленное число может быть обратимо преобразовано туда и обратно:
str -> float() -> repr() -> float() ... или Decimal -> float -> str -> Decimal
Тип Decimal больше не нужен для хранения.


(Естественно, может возникнуть необходимость округлить результат сложения или вычитания округленных чисел, чтобы исключить накопленные последние битовые ошибки. Явная десятичная арифметика может быть удобна, но преобразование в строку с помощью str() (то есть с округлением до 12 допустимо цифр) обычно бывает достаточно, если не требуется предельной точности или чрезмерного количества последовательных арифметических операций.)

Бесконечный тест:

import random
from decimal import Decimal
for x in iter(random.random, None):           # Verify FOREVER that rounding is fixed :-)
    assert float(repr(x)) == x                # Reversible repr() conversion.
    assert float(Decimal(repr(x))) == x
    assert len(repr(round(x, 10))) <= 12      # Smart decimal places in repr() after round.
    if x >= 0.1:                              # Implicit rounding to 12 significant digits
        assert str(x) == repr(round(x, 12))   # by str() is good enough for small errors.
        y = 1000 * x                             # Decimal type is excessive for shopping
        assert str(y) == repr(round(y, 12 - 3))  # in a supermaket with Python 2.7+ :-)

Документация

См. Четвертый абзац Примечания к выпуску Python 2.7 - другие языковые изменения:

Conversions between floating-point numbers and strings are now correctly rounded on most platforms. These conversions occur in many different places: str() on floats and complex numbers; the float and complex constructors; numeric formatting; serializing and de-serializing floats and complex numbers using the marshal, pickle and json modules; parsing of float and imaginary literals in Python code; and Decimal-to-float conversion.

Related to this, the repr() of a floating-point number x now returns a result based on the shortest decimal string that’s guaranteed to round back to x under correct rounding (with round-half-to-even rounding mode). Previously it gave a string based on rounding x to 17 decimal digits.

Связанная проблема


Больше информации: Форматирование float до Python 2.7 было аналогично текущему numpy.float64. Оба типа используют одинаковую 64-битную двойную точность IEEE 754 с 52-битной мантиссой. Большое различие состоит в том, что np.float64.__repr__ часто форматируется с чрезмерным десятичным числом, чтобы ни один бит не мог быть потерян, но действительного числа IEEE 754 между 13.949999999999999 и 13.950000000000001 не существует. Результат нехороший, и преобразование repr(float(number_as_string)) необратимо с помощью numpy. С другой стороны: float.__repr__ отформатирован так, что важна каждая цифра; последовательность без пропусков и преобразование обратимое. Проще говоря: если у вас, возможно, есть число numpy.float64, преобразуйте его в обычное число с плавающей запятой, чтобы он был отформатирован для людей, а не для числовых процессоров, иначе с Python 2.7+ больше ничего не потребуется.

Почему проголосовали против? Речь шла о Python float (с двойной точностью) и обычном round, а не о numpy.double и его преобразовании в строку. Обычное округление в Python действительно невозможно сделать лучше, чем в Python 2.7. Большинство ответов было написано до 2.7, но они устарели, хотя изначально были очень хорошими. Это причина моего ответа.

hynekcer 15.04.2016 14:02

53 бита, когда вы включаете «скрытый бит», который неявно является 1, за исключением «постепенного потери значимости».

Rick James 17.05.2017 07:16

Это не ошибка раунда, это ошибка дисплея.

Rick James 17.05.2017 07:22

Да, это хорошо известно. Однако мне не хватает контекста, если вы возражаете против чего-либо в примечаниях к выпуску Python 2.7 или в моем тексте или против чего-либо вообще. Сложнее, чем было необходимо, цель этого вопроса. Следует добавить, что преобразование из строки в число с плавающей запятой также было исправлено в Python 2.7 из-за ошибка округления на некоторых 32-битных чипах Intel и что «Функция round () также правильно округлена сейчас». (Примечания к выпуску - функции 3.1 перенесены в 2.7). Вы согласны?

hynekcer 17.05.2017 12:26

Ой, это был a*b против b*a. Спасибо за ссылки - Ностальгия.

Rick James 17.05.2017 23:11

Образец кода не работает как для Python 2.7.13, так и для Python 3.5.3.

Jérôme 16.04.2018 11:50

@ Жером. Спасибо. Исправлено сейчас. У меня была опечатка x вместо y, когда я объединил два теста в этот пример для разного порядка величины.

hynekcer 16.04.2018 21:46

Встроенный round() отлично работает с Python 2.7 или новее.

Пример:

>>> round(14.22222223, 2)
14.22

Проверьте документация.

Итак, я должен понимать, что это ошибка Python 2.7? Почему такая фундаментальная функция дает разные результаты в версиях 2.7 и 3?

StartupGuy 03.09.2017 02:50

но round(2.16, 1) дает 2.2, почему python просто предлагает функцию truncate

jiamo 08.01.2018 06:31

Например, если вы попытаетесь округлить значение 2,675 до двух десятичных знаков, вы получите >>> round(2.675, 2) 2.67docs.python.org/2/tutorial/floatingpoint.html

danger89 06.11.2018 20:41

Со страницы документации Python 3: Note 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.

Richard Dally 19.05.2019 01:14

Обратите внимание, что если вы попытаетесь использовать этот метод для печати числа, такого как 1.00000, он распечатает только 1.0, независимо от того, сколько десятичных знаков вы укажете.

Josh Correia 03.08.2019 19:36

@RichardDally Спасибо за столь необходимую информацию. Не могли бы вы объяснить, почему "большинство десятичных дробей не могут быть представлены в точности как число с плавающей запятой"?

Md. Sabbir Ahmed 12.12.2020 09:57

Использовать

print"{:.2f}".format(a)

вместо

print"{0:.2f}".format(a)

Потому что последнее может привести к ошибкам вывода при попытке вывода нескольких переменных (см. Комментарии).

Это нонсенс. Два приведенных оператора ведут себя идентично в Python 2.7, и только второй оператор действителен в Python 2.6. (Ни один из операторов не действителен в Python 3 или Python <2.6.) У первой формы нет никаких преимуществ, кроме краткости.

Mark Dickinson 28.01.2018 20:56

Я имею в виду, что печать "{0: .2f} {0: .2f}". Format (a, b) приведет к ошибке при выводе - он будет выводить значение 'a' дважды. При печати "{:. 2f} {: .2f}". Format (a, b) будет выводить значения 'a' и 'b'.

Alexey Antonenko 01.02.2018 20:30

Для Python 3 вам просто нужно добавить скобки print (...). И в них все, что я написал, правильно.

Alexey Antonenko 01.02.2018 20:31

"Я имею в виду, напечатайте" {0: .2f} {0: .2f} ". Format (a, b) приведет к ошибке при выводе". Ах. Что ж, это совсем другое заявление! Может стоит отредактировать свой ответ? (Что, например, означает «вызвать ошибку» в текущем ответе? Можете ли вы привести пример случая, когда второй оператор вызывает исключение, а первый - нет?)

Mark Dickinson 01.02.2018 21:34

Вы будете после print ("{0: .2f} {1: .2f}". Format (a, b)), если у вас есть две переменные

Hovo 11.02.2018 02:12
orig_float = 232569 / 16000.0

14.5355625

short_float = float("{:.2f}".format(orig_float)) 

14.54

Кажется, здесь никто еще не упомянул об этом, поэтому позвольте мне привести пример в формате f-string / template-string Python 3.6, который, на мой взгляд, очень аккуратен:

>>> f'{a:.2f}'

Он также хорошо работает с более длинными примерами, с операторами и не нуждающимися в скобках:

>>> print(f'Completed in {time.time() - start:.2f}s')

это конец 2020 года, а это все еще намного ниже

galactica 20.11.2020 10:17

Как отметил @Matt, Python 3.6 предоставляет f-строки, и они также могут использовать вложенные параметры:

value = 2.34558
precision = 2
width = 4

print(f'result: {value:{width}.{precision}f}')

который отобразит result: 2.35

В Python 2.7:

a = 13.949999999999999
output = float("%0.2f"%a)
print output

Это совсем не помогает. output имеет значение точно так же как a, поэтому вы могли бы написать print a вместо print output в последней строке.

Mark Dickinson 26.05.2018 09:12

@MarkDickinson Не могли бы вы попробовать еще раз. Потому что он работает в моем компиляторе, как и ожидалось.

Shashank Singh 23.09.2018 11:07

Вы упускаете мою точку зрения. Да, ваш код печатает 13.95. Но то же самое делает print a для этого конкретного значения a в Python 2.7, поэтому не совсем понятно, в чем заключалась цель этапа форматирования.

Mark Dickinson 23.09.2018 14:13

@MarkDickinson Я отредактировал код. Я согласен с тем, что «print a» выводит то же значение, что и «print output». Но если вы сравните «a == output», результатом будет «False», потому что на этапе форматирования плавающее значение «a» округляется до двух десятичных знаков.

Shashank Singh 23.09.2018 14:45

Вы действительно пробовали a == output для кода, который вы показываете? Он дает мне True, и я подозреваю, что это дает и вам.

Mark Dickinson 23.09.2018 14:46

@MarkDickinson Для a=13.949999999999999 я получаю Правда. Для a=13.9499999 я получаю Ложь. Я немного запутался !!!

Shashank Singh 23.09.2018 14:58
from decimal import Decimal


def round_float(v, ndigits=2, rt_str=False):
    d = Decimal(v)
    v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
    if rt_str:
        return v_str
    return Decimal(v_str)

Полученные результаты:

Python 3.6.1 (default, Dec 11 2018, 17:41:10)
>>> round_float(3.1415926)
Decimal('3.14')
>>> round_float(3.1445926)
Decimal('3.14')
>>> round_float(3.1455926)
Decimal('3.15')
>>> round_float(3.1455926, rt_str=True)
'3.15'
>>> str(round_float(3.1455926))
'3.15'

Это просто как 1,2,3:

  1. используйте модуль десятичный для быстрой арифметики правильно округленных десятичных чисел с плавающей запятой:

    d = десятичный (10000000.0000009)

для достижения округления:

   d.quantize(Decimal('0.01'))

будет результат с Decimal('10000000.00')

  1. сделать выше СУХОЙ:
    def round_decimal(number, exponent='0.01'):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(exponent))

ИЛИ ЖЕ

    def round_decimal(number, decimal_places=2):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(10) ** -decimal_places)
  1. проголосуйте за этот ответ :)

PS: критика других: форматирование не округление.

Вы можете использовать оператор формат для округления значения до 2 десятичных знаков в python:

print(format(14.4499923, '.2f')) // output is 14.45

Это возвращает строку

Jemshit Iskenderov 22.03.2019 22:15

А как насчет такой лямбда-функции:

arred = lambda x,n : x*(10**n)//1/(10**n)

Таким образом, вы могли просто сделать:

arred(3.141591657,2)

и получить

3.14

Используйте комбинацию объекта Decimal и метода round ().

Python 3.7.3
>>> from decimal import Decimal
>>> d1 = Decimal (13.949999999999999) # define a Decimal
>>> d1 
Decimal('13.949999999999999289457264239899814128875732421875')
>>> d2 = round(d1, 2) # round to 2 decimals
>>> d2
Decimal('13.95')

lambda x, n: int (x * 10п + 0,5) / 10n работал у меня многие лет на многих языках.

Ответы, которые я видел, не работали со случаем float (52.15). После некоторых тестов я нашел решение, которое я использую:

import decimal
        
def value_to_decimal(value, decimal_places):
    decimal.getcontext().rounding = decimal.ROUND_HALF_UP  # define rounding method
    return decimal.Decimal(str(float(value))).quantize(decimal.Decimal('1e-{}'.format(decimal_places)))

(Преобразование «значения» в число с плавающей запятой, а затем в строку очень важно, таким образом, «значение» может иметь тип с плавающей запятой, десятичное, целое или строковое!)

Надеюсь, это кому-нибудь поможет.

У нас есть несколько вариантов для этого: Опция 1:

x = 1.090675765757
g = float("{:.2f}".format(x))
print(g)

Вариант 2: Встроенный round () поддерживает Python 2.7 или новее.

x = 1.090675765757
g =  round(x, 2)
print(g)

В вопросе конкретно сказано, что круглый метод не делает то, что хочет. Проверьте этот ответ для получения дополнительной информации о том, почему это

Gustavo Kawamoto 05.10.2020 04:43
float_number = 12.234325335563
round(float_number, 2)

Это вернется;

12.23

функция round принимает два аргумента; Число для округления и количество возвращаемых десятичных знаков. Здесь я вернул 2 десятичных знака.

Но как вы получили дополнительный 0, если у нас есть, скажем, 0,093? Это дает мне 0,1 в качестве ответа

Naman Jain 25.11.2020 03:40

Если вы вернете 2 десятичных разряда или вообще на 1 место больше, чем количество нулей, присутствующих в десятичной части с левой стороны, тогда вы получите правильный результат, как хотите. Например, если вы примените просто мой ответ к числу 0,093, он вернет 0,09, но если вы хотите получить только 1 десятичный знак, тогда, конечно, он вернет 0,1, поскольку 0,0 полностью неверен. (и мой код работает таким же образом. Возможно, вы хотите получить только 1 десятичный разряд. Если если вы хотите получить более точные результаты, необходимо увеличить количество десятичных знаков.)

Irfan wani 25.11.2020 12:53

Неправда, что он вернет десятичное число, согласно документации `Возвращаемое значение является целым числом, если ndigits опущено или None. В противном случае возвращаемое значение имеет тот же тип, что и число. ndigits может быть отрицательным.

Saif Masadeh 09.03.2021 04:53

Если вы хотите обрабатывать деньги, используйте модуль python десятичный

from decimal import Decimal, ROUND_HALF_UP

# amount can be integer, string, tuple, float, or another Decimal object
def to_money(amount) -> Decimal:
    money = Decimal(amount).quantize(Decimal('.00'), rounding=ROUND_HALF_UP)
    return money

Другие вопросы по теме