Вопрос

Документация для круглый() функция указывает, что вы передаете ей число, а позиции после запятой округляете.Таким образом, это следует сделай это:

n = 5.59
round(n, 1) # 5.6

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

5.5999999999999996

Для целей пользовательского интерфейса мне нужно отобразить 5.6.Я порылся в Интернете и нашел кое-что Документация что это зависит от моей реализации Python.К сожалению, это происходит как на моем компьютере для разработки Windows, так и на каждом сервере Linux, который я пробовал. Смотрите также здесь.

Если не считать создания моей собственной библиотеки раундов, есть ли какой-нибудь способ обойти это?

Это было полезно?

Решение

Я ничего не могу поделать с тем, как это хранится, но, по крайней мере, форматирование работает правильно:

'%.1f' % round(n, 1) # Gives you '5.6'

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

Форматирование работает корректно даже без округления:

"%.1f" % n

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

Decimal(str(16.2)).quantize(Decimal('.01'), rounding=ROUND_UP)

Это вернет десятичное число, равное 16.20.

round(5.59, 1) работает нормально.Проблема в том, что 5.6 не может быть точно представлена в двоичном формате с плавающей запятой.

>>> 5.6
5.5999999999999996
>>> 

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

Python имеет модуль для десятичной арифметики если тебе это нужно.

Вы получите "5.6", если вы это сделаете str(round(n, 1)) вместо того, чтобы просто round(n, 1).

Вы можете изменить тип данных на целое число:

>>> n = 5.59
>>> int(n * 10) / 10.0
5.5
>>> int(n * 10 + 0.5)
56

А затем отобразите число, вставив десятичный разделитель языкового стандарта.

Однако, Ответ Джимми это лучше.

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

Взгляните на Десятичный модуль

Decimal “ основан на модели с плавающей запятой которая была разработана с учетом потребностей людей и обязательно имеет первостепенный руководящий принцип – компьютеры должны обеспечивать арифметику , которая работает так же, как арифметика, которую люди изучают в школе ”. – выдержка из спецификации десятичной арифметики.

и

Десятичные числа могут быть представлены точно.Напротив, такие числа, как 1.1 и 2.2, не имеют точного представления в двоичной системе с плавающей запятой.Конечные пользователи, как правило, не ожидать 1.1 + 2.2 для отображения как 3.3000000000000003 как это происходит с двоичной плавающей запятой.

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

Это действительно большая проблема.Попробуйте этот код:

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),)

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

Вы можете использовать оператор string format ( строковый формат) %, аналогично sprintf.

mystring = "%.2f" % 5.5999

printf молокосос.

print '%.1f' % 5.59  # returns 5.6

Работает Идеально

format(5.59, '.1f') # to display
float(format(5.59, '.1f')) #to round

Я делаю:

int(round( x , 0))

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

итак

>>> int(round(5.59,0))
6

Я думаю, что этот ответ работает лучше, чем форматирование строки, и мне также более разумно использовать функцию round.

Код:

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

Вот тут-то я и вижу, что раунд терпит неудачу.Что, если бы вы захотели округлить эти 2 числа до одного знака после запятой?23.45 23.55 Мое образование состояло в том, что, округляя их, вы должны получить:23.4 23.6 "правило" заключается в том, что вы должны округлять в большую сторону, если предыдущее число было нечетным, а не в большую, если предыдущее число было четным.Функция round в python просто усекает 5.

Проблема возникает только тогда, когда последняя цифра равна 5.Например.0,045 хранится внутри как 0,04499999999999999...Вы могли бы просто увеличить последнюю цифру до 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(n,1)+epsilon
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top