Уведомления

Группа в Telegram: @pythonsu

#1 Фев. 4, 2011 13:12:03

Dr.Ziko
От:
Зарегистрирован: 2011-01-28
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

round() в python 2.6

Здравствуйте. С коллегой скиптик пишем и возникла такая интересная ситуация. У меня python 2.7.1, а у коллеги 2.6.5.
Ставим такой эксперимент:

Python 2.7.1 (r271:86832, Jan  6 2011, 11:45:30) 
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> round (4.3111111, 2)
4.31
И оно же у коллеги.

Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> round (4.3111111, 2)
4.3099999999999996
Кто-то может это объяснить? И как-то можно питона заставить округлять число корректно?



Офлайн

#2 Фев. 4, 2011 13:16:28

regall
От: Киев
Зарегистрирован: 2008-07-17
Сообщения: 1583
Репутация: +  3  -
Профиль   Отправить e-mail  

round() в python 2.6

>>> 4.3099999999999996 == 4.31
True
Для вывода пользуйтесь форматированием строк



Офлайн

#3 Фев. 4, 2011 13:20:41

Dr.Ziko
От:
Зарегистрирован: 2011-01-28
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

round() в python 2.6

regall
>>> 4.3099999999999996 == 4.31
True
Для вывода пользуйтесь форматированием строк
Вывод мне не нужен в принципе, я лишь проверяю корректность данных в списке. Т.е. если я запишу это число в БД, например, то там будет 4.31 вместо 4.30999999999996?



Офлайн

#4 Фев. 4, 2011 13:27:48

regall
От: Киев
Зарегистрирован: 2008-07-17
Сообщения: 1583
Репутация: +  3  -
Профиль   Отправить e-mail  

round() в python 2.6

Dr.Ziko
Т.е. если я запишу это число в БД, например, то там будет 4.31 вместо 4.30999999999996?
А попробовать? =)



Офлайн

#5 Фев. 4, 2011 13:28:40

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

round() в python 2.6

Это относится только к repr у float, а не к самому числу:

Python now uses David Gay’s algorithm for finding the shortest floating point representation that doesn’t change its value. This should help mitigate some of the confusion surrounding binary floating point numbers.

The significance is easily seen with a number like 1.1 which does not have an exact equivalent in binary floating point. Since there is no exact equivalent, an expression like float('1.1') evaluates to the nearest representable value which is 0x1.199999999999ap+0 in hex or 1.100000000000000088817841970012523233890533447265625 in decimal. That nearest value was and still is used in subsequent floating point calculations.

What is new is how the number gets displayed. Formerly, Python used a simple approach. The value of repr(1.1) was computed as format(1.1, ‘.17g’) which evaluated to ‘1.1000000000000001’. The advantage of using 17 digits was that it relied on IEEE-754 guarantees to assure that eval(repr(1.1)) would round-trip exactly to its original value. The disadvantage is that many people found the output to be confusing (mistaking intrinsic limitations of binary floating point representation as being a problem with Python itself).

The new algorithm for repr(1.1) is smarter and returns ‘1.1’. Effectively, it searches all equivalent string representations (ones that get stored with the same underlying float value) and returns the shortest representation.

The new algorithm tends to emit cleaner representations when possible, but it does not change the underlying values. So, it is still the case that 1.1 + 2.2 != 3.3 even though the representations may suggest otherwise.

The new algorithm depends on certain features in the underlying floating point implementation. If the required features are not found, the old algorithm will continue to be used. Also, the text pickle protocols assure cross-platform portability by using the old algorithm.

(Contributed by Eric Smith and Mark Dickinson; issue 1580)



Офлайн

#6 Фев. 4, 2011 13:32:33

Dr.Ziko
От:
Зарегистрирован: 2011-01-28
Сообщения: 13
Репутация: +  0  -
Профиль   Отправить e-mail  

round() в python 2.6

regall
Dr.Ziko
Т.е. если я запишу это число в БД, например, то там будет 4.31 вместо 4.30999999999996?
А попробовать? =)
Не, ну это ж надо написать недостающую часть скрипта по записи в БД))) Ладно, обещаюсь попробовать и отписаться о результатах)



Офлайн

#7 Фев. 4, 2011 16:07:28

Isem
От:
Зарегистрирован: 2010-08-27
Сообщения: 447
Репутация: +  7  -
Профиль   Отправить e-mail  

round() в python 2.6

Dr.Ziko
Вывод мне не нужен в принципе, я лишь проверяю корректность данных в списке. Т.е. если я запишу это число в БД, например, то там будет 4.31 вместо 4.30999999999996?
Там будет именно то, что вы запишете, то есть 4.30999999999996.
Если вы туда будете писать ‘A’, то с чего там будет ‘B’?



Отредактировано (Фев. 4, 2011 16:09:07)

Офлайн

#8 Фев. 4, 2011 16:58:39

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

round() в python 2.6

Dr.Ziko, Isem.
Вы различаете двоичную запись и текстовое представление для float?
И то, что многие дроби можно записать двумя способами, 4.31 одна из них?



Офлайн

#9 Фев. 4, 2011 17:37:53

Isem
От:
Зарегистрирован: 2010-08-27
Сообщения: 447
Репутация: +  7  -
Профиль   Отправить e-mail  

round() в python 2.6

Андрей Светлов
Вы различаете двоичную запись и текстовое представление для float?
И то, что многие дроби можно записать двумя способами, 4.31 одна из них?
Вы сами то поняли, что сказали? Вы путаете три вещи: это точное значение числа, его двоичное представление с конечным количеством битов и его десятичное представление с конечным количеством десятичных знаков.
Вы же сами процитировали, прочитайте внимательнее. На всякий случай отсылаю желающих к стандарту представления вещественных чисел, используемых в современных процессорах на аппаратном уровне.

p.s. http://en.wikipedia.org/wiki/IEEE_754-2008



Отредактировано (Фев. 4, 2011 17:38:46)

Офлайн

#10 Фев. 4, 2011 21:36:25

Eliont
От:
Зарегистрирован: 2010-05-30
Сообщения: 77
Репутация: +  0  -
Профиль   Отправить e-mail  

round() в python 2.6

Вариант - использовать свой round:

    def round(num):
num = float(num)
x = num - math.floor(num)
if x == 0: return int(num)
elif x < 0.5: return int(math.floor(num))
else: return int(math.ceil(num))



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version