4

Имеет ли встроенная функция round() в Python между 2.4 и 2.7?Изменение в Python, построенное в функции round() между 2.4 и 2.7

Python 2.4:

Python 2.4.6 (#1, Feb 12 2009, 14:52:44) 
[GCC 3.4.6 20060404 (Red Hat 3.4.6-8)] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> f = 1480.39499999999998181010596454143524169921875 
>>> round(f,2) 
1480.4000000000001 
>>> 

Python 2.7:

Python 2.7.1 (r271:86832, May 13 2011, 08:14:41) 
[GCC 3.4.6 20060404 (Red Hat 3.4.6-11)] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> f = 1480.39499999999998181010596454143524169921875 
>>> round(f, 2) 
1480.39 
>>> 

Есть в любом случае, чтобы получить поведение Python 2.4 обратно?

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

Update

Для контекста я сравниваю значение в двух системах, одна из которых использует десятичное представление, а другая с плавающей точкой одной. Это может (или не обязательно) быть законным различием между системами, которые необходимо проверить дальше, поэтому я буду консультироваться с пользователями и заниматься им на уровне «отчетности», а не в точке, где я получаю данные из систем ,

Благодарим за помощь!

+0

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

+3

P.S. Ответ Python 2.7 кажется мне более правильным, я бы не ожидал найти вариант для доставки неверных результатов. –

+1

«К сожалению, этот [десятичный модуль], вероятно, на данный момент не является опцией с учетом временных ограничений.« Я сомневаюсь, что это действительно так, по крайней мере, вы не должны ожидать, что поплавок даст точный результат или точное округление поскольку поплавок неточно по определению. Спасите себя от хлопот и конвертируйте свою программу в десятичную. –

ответ

3

Наверное, нет, поскольку Python 2.4 фактически вернул неверный результат. Поскольку вы округливаете сумму, которая строго меньше 5, правильный результат следует округлить.

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

6

Ответ на ваш первый вопрос: да, round был исправлен в Python 2.7.

Ответ на ваш второй вопрос: я не уверен, если не использовать более ранний Python (2.6 должно по-прежнему демонстрировать поведение 2.4). В этом конкретном случае ваша ценность неотличима от 1480.395 и 1480.395 (для нас, основанных на 10 человек) раундов до 1480.40. Поэтому я предполагаю, что вы можете попробовать сначала округлить до одного места, кроме того, что вы действительно на самом деле, превратите это в строку, а затем получите десятичное число от этого ... но, к сожалению, я не могу придумать ничего, что не включает Decimal. Если я что-то придумаю (прежде чем кто-то еще напишет что-то лучше), я вернусь и отредактирую.

(Но на самом деле, это десятичный все, что трудно использовать?)

Edit: Вот пример того, как использовать Decimal:

>>> from decimal import Decimal 
>>> f = Decimal('1480.395') 
>>> f.quantize(Decimal('0.00')) 
Decimal('1480.40') 
>>> float(Decimal('1480.40')) 
1480.4 

Некоторые примечания:

Python 2.7 позволяет использовать поплавки для ввода в десятичный. Не делайте этого, так как вы вернетесь туда, где вы начали. Кроме того, не используйте встроенную функцию round в десятичной системе, потому что эта функция преобразует ваше десятичное правое обратно в float и, таким образом, вы вернетесь туда, где вы начали. В своей простейшей форме Decimal quantize принимает еще одно десятичное число, которое имеет число десятичных знаков, которые вы действительно хотите (подумайте об этом как о шаблоне для округления). Если ваши данные обязательно должны быть плавающими, то конвертировать их обратно в float после завершения всех ваших вычислений Decimal.

И наконец: я не уверен, что это покрывает все возможные странные угловые случаи в поведении поплавка Python 2.4. Если вы полагаетесь на точно Поведение Python 2.4, на Python 2.4 не может быть замены. То, что я описал выше, просто на один шаг ближе к округлению человека.

+0

Поскольку ближайшее бинарное представление 1480.395 - это всего лишь волосы, округленные до любого количества цифр 3 или больше, просто покидает вас, где вы начали - двойное округление не помогает. –

+1

@Mark: Нет, я не предлагаю крутить на поплавке; Я говорю вокруг * Десятичный * (используя 'quantize'). Я поясню в ответе ... –

1

В what's new in python 2.6 странице я вижу следующее (со ссылкой на PEP 3141):

Python 3.0 добавляет несколько абстрактных базовых классов для числовых типов, вдохновленных цифровой башни схемы. Эти классы были обращены к 2.6 в качестве модуля чисел.

...

В Python 3.0, PEP слегка переопределяет существующие внутренние команды круглые(), Math.floor(), Math.ceil(), и добавляет новую, математике. trunc(), который был передан в Python 2.6. math.trunc() округляется к нулю, возвращая ближайший Интеграл, который находится между аргументом функции и нулем.

И, благодаря @ наценка Дикинсон комментарий, в what's new in python 2.7 странице, следующий текст найден: функция

Круглое() также теперь правильно округлены.

Так что да, изменение произошло в python 2.7. Это можно проверить, убедившись, что в Python 2.6 поведение по-прежнему старый:

Python 2.6.7 (r267:88850, Aug 11 2011, 12:18:09) 
[GCC 4.6.1] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> f = 1480.39499999999998181010596454143524169921875 
>>> round(f, 2) 
1480.4000000000001 

В моем дистрибутиве Linux я до сих пор доступ к обоим Python 2.6 и Python 2.7 и, вероятно, у вас есть также в вашем; поэтому, если вам нужно старое поведение, возможно, вы можете попробовать запустить код в python 2.6.

+0

Соответствующее изменение было на самом деле в Python 2.7, а не в Python 2.6, хотя в документе 2.7 «что нового» есть только краткое упоминание: «Теперь функция round() корректна округлый «. –

+0

@MarkDickinson Спасибо, я обдумал ответ с информацией, которую вы предоставили. – jcollado