Уведомления

Группа в Telegram: @pythonsu

#1 Фев. 5, 2011 00:23:25

Subideal Ox
От:
Зарегистрирован: 2010-11-23
Сообщения: 65
Репутация: +  0  -
Профиль   Отправить e-mail  

round() в python 2.6

М-да… гений - парадоксов друг.

То есть Вы с самого начала знали, что round в 2.6 и 2.7 работают абсолютно одинаково и все дело только в том, как число из внутреннего (абсолютно идентичного) представления преобразуется в строку в разных версиях?

Но зачем тогда нужно было предлагать свой round? И почему Вы спорили с Андреем, который говорил то же самое?
И к чему тогда фраза:

Isem
Потому что sql сам умеет округлять на выходе
?

Или под Вашим ником еще кто-то пишет?



Офлайн

#2 Фев. 5, 2011 00:32:21

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

round() в python 2.6

Я кроме питона 3.1 (и других языков) больше ни чем никогда не пользовался. Ну кроме метода дедукции. Да, и методом pickle я тоже никогда не пользовался, потому что это бессмысленно. Зачем мне неизвестный мне формат (это не ошибка), когда я и так знаю, что он записывает (в принципе) ? А моя цитируемая Вами фраза к тому, что мне выдали число, но объяснили это совершенно не так, как это на самом деле происходит, после чего я, естественно, не смог промолчать.
И под моим ником сижу только я.
p.s. А с Андреем я спорил потому, что он меня приравнял, извините, не туда (его первый пост со мной через запятую). Да и сказал он, что я не смог понять что (ну со мной бывает такое иногда) (надеюсь, Андрей на меня зла держать за это не будет).
p.s.s И случай – бог-изобретатель.



Отредактировано (Фев. 5, 2011 01:09:02)

Офлайн

#3 Фев. 5, 2011 00:33:12

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

round() в python 2.6

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

Имеем дробь 4.31. В float она хранится в виде <знак>1.<мантисса> * pow(2, <экспонента>)
Знак и экспонента сейчас не важны. Мантисса - дробная часть числа, записанная по основанию два.
Оригинальная запись была “4.31”, дробная часть пишется по основанию 10.
Когда переводим из десятичного основания в двоичное - получаем бесконечную дробь. Примерно как 1/3 в переводе на десятичное основание - тоже бесконечная.

В float мантисса записывается “пока хватает места”, а (бесконечный) остаток выбрасывается.
Если записывать 1/3 с точностью до 3 знаков, получим 0.333. В float 53 (считая со старшей неявной единицей) двоичных разряда. Я не хочу приводить эту длинную простыню ноликов и единичек, достаточно представить что она есть.

Теперь нужно обратно перевести float в строку в десятичном представлении.
Двоичное число стало конечным. Но из-за отсечения не поместившихся бит оно не точно соответствует десятичному числу, из которого конструировалось.

Python 2.6- (и Python 3.0) делали это так: преобразовываем “как есть” и получаем длинный “хвост” - 4.3099999999999996
В Python 3.1 (а после и в Python 2.7) алгоритм поменяли.
Это длинная простыня format_float_short в ./Python/pystrtod.c

Работает она так:
У нас есть мантисса <b1 b2 b3 b4 b5> - на самом деле 52 бита.
Переводим ее в десятичную форму: <d1 d2>. Перевод остановился на b3, например - потому что b4 и b5 не дают десятичного числа.
Последняя десятичная цифра d3 - неполная, потому что входной поток бит закончился раньше, чем мы получили их достаточное количество.
Добавляем в этот поток все возможные комбинации, необходимые для завершения построения d3.
Выбираем из всех возможных d3 такую цифру, чтобы результирующее число имело минимальную запись (чем больше выходит ноликов в конце, тем лучше).

Вуаля, получили минимальное десятичное представление денормализованного двоичного числа.
Внимание, это - не округление в математическом смысле.
Алгоритм подбирает такой остаток, не поместившийся в мантиссу из-за конечного ее размера, чтобы результат можно было записать минимальным количеством цифр.
Точность при этом не теряется - десятичное число “длиннее” в двоичном виде, чем мантисса в float и при этом совпадает с ней на первых 52 битах.

Получилось всё еще довольно длинно и запутанно - но этот вопрос вообще нелегко объясняется “на пальцах”.
Вот документ, с которого всё начиналось: http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
Довольно много математики.



Офлайн

#4 Фев. 5, 2011 00:38:59

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

round() в python 2.6

Isem
Да, и методом pickle я тоже никогда не пользовался, потому что это бессмысленно.
Например, СУБД ZODB построена на базе pickle.
Isem
Зачем мне неизвестный мне формат (это не ошибка), когда я и так знаю, что он записывает (в принципе)?
Действительно, зачем вообще такие форматы, лучше такой формат, в котором никто не знает, что он записывает =)



Офлайн

#5 Фев. 5, 2011 00:45:47

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

round() в python 2.6

Андрей Светлов
Довольно много математики.
Как правило.



Офлайн

#6 Фев. 5, 2011 00:47:21

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

round() в python 2.6

regall
Действительно, зачем вообще такие форматы, лучше такой формат, в котором никто не знает, что он записывает
Ну это передергивание. Пусть даже и со смайликом. :)



Офлайн

#7 Фев. 8, 2011 14:48:02

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

round() в python 2.6

Эм… Может тему из новичков в профессионалы перенесём? :)))))



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version