Подтвердить что ты не робот

Почему языки программирования округляются до 0,6?

Если вы поместите десятичное число в формате, где округление должно быть округлено до ближайшего 10-го, а это: 1.55, оно будет округлено до 1.5. 1.56 округляется до 1.6. В школе я вспоминаю, что вы собрались, когда достигли пяти, и вниз, если это 4 или ниже. Почему это отличается в Python и др.

Вот пример кода для Python 2.6x (независимо от последней версии)

'{0:01.2f}'.format(5.555)  # This will return '5.55'

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

'{0:01.1f}'.format(5.55)  # This will return '5.5'
# But then
'{0:01.1f}'.format(1.55)  # This will return '1.6'

Почему разница при использовании 1.55 против 5.55. Оба набираются как литералы (так плавает)

4b9b3361

Ответ 1

Во-первых, в большинстве языков некорректированная константа типа "1.55" рассматривается как значение двойной точности. Тем не менее, 1.55 не является точно представленным как значение двойной точности, потому что он не имеет завершающего представления в двоичном формате. Это вызывает много любопытных поведений, но один эффект заключается в том, что при вводе 1.55 вы фактически не получаете значение, равное половине от 1,5 до 1,6.

В двоичном выражении десятичное число 1.55:

1.10001100110011001100110011001100110011001100110011001100110011001100...

Когда вы набираете "1.55", это значение фактически округляется до ближайшего представляемого значения двойной точности (во многих системах... но есть исключения, которые я получу). Это значение:

1.1000110011001100110011001100110011001100110011001101

который немного больше 1,55; в десятичной форме это точно:

1.5500000000000000444089209850062616169452667236328125

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

Но подождите, в вашей системе, "1.55" округлено, а не вверх. Что происходит?

Это может быть несколько разных вещей, но, скорее всего, вы находитесь на платформе (возможно, в Windows), которая по умолчанию выполняет арифметику с плавающей запятой, используя инструкции x87, которые используют другую (80-битную) внутреннюю формат. В 80-битном формате значение 1.55 имеет значение:

1.100011001100110011001100110011001100110011001100110011001100110

который немного меньше 1,55; в десятичном значении это число:

1.54999999999999999995663191310057982263970188796520233154296875

Поскольку он меньше 1,55, он округляется, когда округляется до одной цифры после десятичной точки, давая результат "1,5", который вы наблюдаете.

FWIW: в большинстве языков программирования, режим округления по умолчанию на самом деле "округляется до ближайшего, привязывается к четному". Просто, когда вы укажете дробные значения в десятичном значении, вы почти никогда не столкнетесь с точным случаем на полпути, так что непрофессионалу может быть трудно это наблюдать. Однако вы можете это увидеть, если посмотреть, как "1,5" округляется до нулевых цифр:

>>> "%.0f" % 0.5
'0'
>>> "%.0f" % 1.5
'2'

Обратите внимание, что оба значения округляются до четных чисел; ни раундов до "1".

Изменить: в вашем пересмотренном вопросе, вы, похоже, переключились на другой интерпретатор python, на котором с плавающей запятой выполняется в двойном типе IEEE754, а не на 80-х типа x87. Таким образом, "1.55" округляется, как в моем первом примере, но "5.55" преобразуется в следующее двоичное значение с плавающей запятой:

101.10001100110011001100110011001100110011001100110011

что точно:

5.54999999999999982236431605997495353221893310546875

в десятичной системе; так как он меньше 5.55, он округляется вниз.

Ответ 2

Существует множество способов округления чисел. Подробнее о округлении можно прочитать в Википедии. Метод округления, используемый в Python, Раунд половины от нуля, а метод округления, который вы описываете, более или менее одинаковый (по крайней мере, для положительных чисел).

Ответ 3

Можете ли вы привести примерный код, потому что это не то поведение, которое я вижу в Python:

>>> "%.1f" % 1.54
'1.5'
>>> "%.1f" % 1.55
'1.6'
>>> "%.1f" % 1.56
'1.6'

Ответ 4

Это, похоже, не так. Вы используете форматирование строки "float", верно?

>>> "%0.2f" % 1.55
'1.55'
>>> "%0.1f" % 1.55
'1.6'
>>> "%0.0f" % 1.55
'2'

Ответ 5

Округление и усечение разные для каждого языка программирования, поэтому ваш вопрос, вероятно, напрямую связан с Python.

Однако rounding, поскольку практика зависит от вашей методологии.

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

Изменить: На некоторых других плагинах кажется, что Python не показывает описанное вами поведение округления:

>>> "%0.2f" % 1.55 
'1.55' 
>>> "%0.1f" % 1.55 
'1.6' 
>>> "%0.0f" % 1.55 
'2' 

Ответ 6

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

1.5 rounds to 2
2.5 rounds to 2
3.5 rounds to 4
4.5 rounds to 4

т.е. значение .5 будет округлено до ближайшего целого числа. Причиной этого является то, что округление большого количества чисел будет даже в конечном итоге. Если банк, например, должен оплатить интеррест, чтобы миллион клиентов, а 10% из них заканчиваются стоимостью 0,5 центов, банк будет выплачивать еще 500 долларов, если бы значения были округлены.

Другой причиной неожиданного округления является точность чисел с плавающей запятой. Большинство чисел не могут быть представлены точно, поэтому они представлены максимально приближенным приближением. Когда вы думаете, что у вас есть число, равное 1,55, вы действительно можете получить число, подобное 1,54999. Разумеется, округление этого числа до одного десятичного знака приведет к 1,5, а не к 1,6.

Ответ 7

Одним из способов устранения хотя бы одного аспекта проблем округления (по крайней мере, некоторое время) является некоторая предварительная обработка. Форматы с одиночной и двойной точностью могут представлять все целые числа точно от -2 ^ 24-1 до 2 ^ 24-1 и -2 ^ 53-1 до 2 ^ 53-1 соответственно. Что может быть сделано с реальным числом (с ненулевой частью доли), это

  • отмените знак и сохраните его позже
  • умножить оставшееся положительное число на 10 ^ (требуется число десятичных знаков)
  • добавьте 0.5, если режим округления окружения настроен на отбивание (округление до нуля)
  • округлите число до ближайшего
  • sprintf число в строку с 0 десятичными знаками в формате
  • "вручную" форматирует строку в соответствии с ее длиной, следующей за sprintf, количеством десятичных знаков, десятичной точкой и знаком
  • строка должна содержать точное число

Имейте в виду, что если результат после шага 3 превышает диапазон конкретного формата (см. выше), ваш ответ будет неправильным.