Как округлить число с плавающей запятой до определенного десятичного знака?

84

Предположим, у меня есть 8.8333333333333339, и я хочу преобразовать его в 8.84. Как я могу сделать это на Python?

round(8.8333333333333339, 2)дает 8.83и нет 8.84. Я новичок в Python или программировании в целом.

Я не хочу печатать это как строку, и результат будет использован в дальнейшем. Для получения дополнительной информации о проблеме, пожалуйста, ознакомьтесь с советами Тима Уилсона по программированию на Python: ссуды и калькулятор платежей .

hsinxh
источник
4
round (8,8333333333333339, 2) даст 8,83 никогда не 8,84 кажется.
VGE
42
Почему 8,84? 8,8333333 ... следует округлить до 8,83 при наведении на два десятичных знака.
Тим Пицкер
дубликат: stackoverflow.com/questions/56820/…
mouad
1
если вы хотите распечатать значение, используйте такой формат, как print "% .2f"% 8.8333333333333339. это напечатает значение с двумя цифрами
VGE
Я отредактировал заголовок, потому что это ранний результат для "python round float", и, вероятно, это не то, что ищет большинство людей. Надеюсь, новое название проясняет ситуацию.
jpmc26 04

Ответы:

101

8.833333333339(или 8.833333333333334результат 106.00/12) правильно округленный до двух знаков после запятой 8.83. Математически это звучит так, будто вам нужна функция потолка . Тот, что находится в mathмодуле Python, называется ceil:

import math

v = 8.8333333333333339
print(math.ceil(v*100)/100)  # -> 8.84

Соответственно, функции пола и потолка обычно сопоставляют действительное число с наибольшим предыдущим или наименьшим последующим целым числом, которое имеет нулевые десятичные разряды, поэтому, чтобы использовать их для двух десятичных разрядов, число сначала умножается на 10 2 (или 100) для сдвига десятичной дроби. точка, а затем делится на нее для компенсации.

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

def ceiling(x):
    n = int(x)
    return n if n-1 < x <= n else n+1

Как все это связано с связанной проблемой калькулятора кредита и платежей :

скриншот вывода кредитного калькулятора

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

В равной степени было бы справедливо использовать обычное округление с получением ежемесячного платежа в размере 8.83и немного большего окончательного платежа в размере 8.87. Однако в реальном мире люди, как правило, не любят, когда их платежи увеличиваются, поэтому округление каждого платежа является обычной практикой - оно также быстрее возвращает деньги кредитору.

Мартино
источник
67

Это нормально (и не имеет ничего общего с Python), потому что 8.83 не может быть представлен точно как двоичное число с плавающей запятой, так же как 1/3 не может быть представлен точно в десятичном (0.333333 ... до бесконечности).

Если вы хотите обеспечить абсолютную точность, вам понадобится decimalмодуль:

>>> import decimal
>>> a = decimal.Decimal("8.833333333339")
>>> print(round(a,2))
8.83
Тим Пицкер
источник
Нет, если вы используете printфункцию / оператор (в зависимости от вашей версии Python).
Тим Пицкер
>>> 106.00/12 => 8.833333333333334
Мартино
22

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

>>> import decimal
>>> decimal.Decimal('8.333333').quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_UP)
Decimal('8.34')
>>> decimal.Decimal('8.333333').quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_DOWN)
Decimal('8.33')
>>> 
casevh
источник
13

Более простой способ - просто использовать функцию round (). Вот пример.

total_price = float()
price_1 = 2.99
price_2 = 0.99
total_price = price_1 + price_2

Если бы вы прямо сейчас распечатали total_price, вы бы получили

3.9800000000000004

Но если вы заключите его в функцию round (), например,

print(round(total_price,2))

Выход равен

3.98

Функция round () работает, принимая два параметра. Первое - это число, которое нужно округлить. Второй - это количество десятичных знаков, до которых нужно округлить.

user2252471
источник
7

Если округлить 8,8333333333339 до 2 десятичных знаков, правильный ответ - 8,83, а не 8,84. Причина, по которой вы получили 8.83000000001, заключается в том, что 8.83 - это число, которое не может быть правильно представлено в двоичном формате, и оно дает вам ближайший. Если вы хотите распечатать его без всех нулей, сделайте, как говорит VGE:

print "%.2f" % 8.833333333339   #(Replace number with the variable?)
Андреас Лёв Селвик
источник
6

Самый простой способ сделать это - использовать встроенную функцию ниже:

format()

Например:

format(1.242563,".2f")

Результатом будет:

1.24

Так же:

format(9.165654,".1f")

даст:

9.2
сай сурья мадхав
источник
Формат ответа был дан в 2010 году здесь . Вместо этого вы могли бы обновить этот ответ.
ZF007
5

Если вы хотите округлить, 8,84 - неправильный ответ. 8,833333333333 округлено - это 8,83, а не 8,84. Если вы хотите всегда округлять вверх, вы можете использовать math.ceil. Используйте оба варианта в сочетании с форматированием строк, потому что округление числа с плавающей запятой само по себе не имеет смысла.

"%.2f" % (math.ceil(x * 100) / 100)
Рош Оксюморон
источник
4

Только для записи. Вы можете сделать это так:

def roundno(no):
    return int(no//1 + ((no%1)/0.5)//1)

Нет необходимости во включениях / импорте

двухгорячий
источник
2

Вот мое решение проблемы округления вверх / вниз

< .5  round down

> = .5  round up

import math

def _should_round_down(val: float):
    if val < 0:
        return ((val * -1) % 1) < 0.5
    return (val % 1) < 0.5

def _round(val: float, ndigits=0):
    if ndigits > 0:
        val *= 10 ** (ndigits - 1)
    is_positive = val > 0
    tmp_val = val
    if not is_positive:
        tmp_val *= -1
    rounded_value = math.floor(tmp_val) if _should_round_down(val) else math.ceil(tmp_val)
    if not is_positive:
        rounded_value *= -1
    if ndigits > 0:
        rounded_value /= 10 ** (ndigits - 1)
    return rounded_value

# test
# nr = 12.2548
# for digit in range(0, 4):
#     print("{} decimals : {} -> {}".format(digit, nr, _round(nr, digit)))

# output
# 0 decimals : 12.2548 -> 12
# 1 decimals : 12.2548 -> 12.0
# 2 decimals : 12.2548 -> 12.3
# 3 decimals : 12.2548 -> 12.25
Опра
источник
1

У меня есть такой код:

tax = (tax / 100) * price

а затем этот код:

tax = round((tax / 100) * price, 2)

раунд сработал для меня

Nic56
источник
Вы решили мою проблему. Я мог только с этим справиться. Больше ничего не работало. renewal_percentage=round(df_x_renewal_count/df_all_count*100)
Kierk
0

Вот простая функция, которая сделает это за вас:

def precision(num,x):
    return "{0:.xf}".format(round(num))

Здесь num - десятичное число. x - это десятичная дробь до того места, где вы хотите округлить плавающее число.

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

Пример 1:

precision(10.2, 9)

вернется

10.200000000 (до 9 десятичных знаков)

Пример 2:

precision(10.2231, 2)

вернется

10,22 (до двух десятичных знаков)

Акаш Кандпал
источник