Я хочу, чтобы a
было округлено до 13.95.
>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999
Функция round
работает не так, как я ожидал.
Вы столкнулись со старой проблемой с числами с плавающей запятой: не все числа могут быть представлены точно. Командная строка просто показывает вам полную форму с плавающей точкой из памяти.
При представлении с плавающей точкой ваша округленная версия - это то же самое число. Поскольку компьютеры двоичные, они хранят числа с плавающей точкой как целое число, а затем делят его на степень двойки, поэтому 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("{0:.2f}".format(a))
13.95
>>> print("{0:.2f}".format(round(a,2)))
13.95
>>> print("{0:.15f}".format(round(a,2)))
13.949999999999999
Если вам нужны только два знака после запятой (например, для отображения валютного значения), то у вас есть несколько лучших вариантов:
Существуют новые спецификации формата, String Format Specification Mini-Language:
Вы можете сделать то же самое, что:
"{0:.2f}".format(13.949999999999999)
Примечание, что вышеприведенное возвращает строку. Для того, чтобы получить число в виде float, просто оберните его с помощью float(...)
:
float("{0:.2f}".format(13.949999999999999))
Примечание, что обертывание с float()
ничего не меняет:
>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{0:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True
Встроенная функция round()
отлично работает в Python 2.7 или более поздней версии.
Пример:
>>> round(14.22222223, 2)
14.22
Посмотрите документацию.
Я чувствую, что самый простой подход-использовать формат ()
функция.
Например:
a = 13.949999999999999
format(a, '.2f')
13.95
Это создает число с плавающей запятой в строку с точностью до двух знаков после запятой.
Большинство чисел не может быть точно представлено в поплавки. Если вы хотите, чтобы округлить число, потому что's что ваши математические формулы или алгоритма необходимо, то необходимо использовать круглый. Если вы просто хотите ограничить просмотр определенной точностью, а затем Дон'т даже использовать круглые и просто отформатировать его как строку. (Если вы хотите, чтобы отобразить его с какой-то другой способ округления, а есть т, то вам нужно смешать два подхода.)
>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'
И наконец, хотя, возможно, самое главное, если вы хотите точное математика тогда вы не'т хотим, чтобы поплавки на всех. Обычным примером является дело с деньгами и в магазине 'копеек' как целое.
Использовать
print"{:.2f}".format(a)
вместо
print"{0:.2f}".format(a)
Потому что последнее может привести к ошибкам на выходе при попытке вывода нескольких переменных (см. комментарии).
С помощью 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.
И для получения дополнительной информации о варианте, по этой ссылке будет достаточно и информации на различные флаги.
Проблема округления ввода / вывода была решена окончательно с помощью Python 2.7.0 и 3.1.
Правильно округленное число может быть обратимо преобразуется и обратно:
стр -> поплавка() -> предст() -> поплавка (из) ... " или " десятичное -> плавающая> стр -> десятичное
Тип decimal не нужно для хранения.
(Естественно, это может быть в результате сложения или вычитания из округленных цифр, чтобы устранить накопленные в прошлом ошибок. Явной десятичной арифметики может быть еще пригодится, но преобразование в строку (ул.)
(то есть с округлением до 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 - другие изменения четвертый пункт:
преобразования между числами с плавающей точкой и строки Теперь правильно округленная на большинстве платформ. Эти преобразования происходят в самых разных местах: STR() на поплавки и комплексных чисел; поплавок и сложные конструкторы; форматирование; сериализации и де-сериализации плавает и комплексных чисел с помощью
маршал
,рассол
иJSON с
модулей; разбора поплавка и мнимой литералы в Python код; и десятичной плавающей преобразования.в связи с этим, в предст - () с плавающей точкой числа X возвращает результат, основанный на короткий десятичную строку, которая гарантированно сзади на х под правильной округления (с круглым половина-даже режим округления). Ранее он дал строку на основе округления х до 17 десятичных цифр.
*Дополнительная информация: форматирование "плывет" перед питоном 2.7 был похож на пакете numpy в настоящее время.float64. Оба типа используют тот же 64-битный [стандарт IEEE 754](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) двойной точности с 52 бита мантиссы. Большая разница заключается в том, что
НП.float64.предстчасто отформатирован с чрезмерным количеством десятичных так что не может быть потеряно, но не действует по стандарту IEEE 754 число существует между 13.949999999999999 и 13.950000000000001. Результат не хороший и преобразование
предст(поплавка(number_as_string)) не обратимых операций с numpy. С другой стороны: поплавок.__предст__
форматируется так, что каждая цифра важна; последовательность без пробелов и преобразование является обратимым. Просто: если вы, возможно, есть и NumPy.float64 число, преобразовать его в обычный поплавок для того, чтобы быть отформатирован для людей, а не для числовых процессоров, в противном случае больше ничего и не надо с Python 2.7+.
Вы можете изменить формат вывода:
>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95
Вы можете использовать формат оператор округления значения до 2 знаков после запятой в Python:
print(format(14.4499923, '.2f')) // output is 14.45
Здесь, кажется, никто не упоминал об этом, поэтому позвольте мне привести пример в Python 3.6'С Ф-строку/шаблон-строка форматирования, я думаю, красиво аккуратно:
>>> f'{a:.2f}'
Он хорошо работает с уже слишком примерами, с операторами и не нуждающихся в скобки:
>>> print(f'Completed in {time.time() - start:.2f}s')
В Python 2.7:
a = 13.949999999999999
output = float("%0.2f"%a)
print output
Питон учебник имеет приложение под названием арифметика с плавающей точкой: проблемы и ограничения. Прочитать его. Это объясняет то, что происходит и почему Python делает все возможное. Это был даже пример, который соответствует вашей. Позволю себе процитировать немного:
0.1 0.10000000000000001
У вас может возникнуть соблазн использовать круглые()` функция порубить его обратно в один цифры вы ожидаете. Но это не делает никакой разница:
круглая(0.1, 1) 0.10000000000000001
проблема в том, что бинарные значение с плавающей точкой хранятся на
“0.1”
уже был самый лучший бинарный приближение к1/10
, таким образом пытаясь вокруг него снова не может сделать это лучше: Это было уже так хорошо, как он получает.другим следствием является то, что с
0.1
> есть не совсем1/10
, подводя десять значения0.1
может точно не выход1.0
, либо:сумма = 0.0 Для я в диапазоне(10): ... сумма += 0.1 ... сумма 0.99999999999999989
Одним из альтернативных и решение ваших проблем будет использовать десятичное число
модуль.
Как @Мэтт указал, питон 3.6 обеспечивает Ф-строк, и они могут также использовать вложенный параметров:
value = 2.34558
precision = 2
width = 4
print(f'result: {value:{width}.{precision}f}')
который будет отображать результат: 2.35`
Он делает именно то, что вы ему сказали, и работает правильно. Прочитайте больше о floating point confusion и, возможно, попробуйте вместо этого использовать decimal объекты.
Для фиксации плавающей точкой в тип-динамических языков, таких как 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
Вы также можете использовать десятичные следующим образом:
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')
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'
Используйте комбинацию десятичных предмет и круглым() метод.
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')