Форум сайта python.su
купил Лутца (3-е издание)…. Почитал про ООП, функции, сборки мусора и т.д. Все было прекрасно и понятно пока не стукнуло в голову почитать элементарное - мат. операции над числами…
Пример из книги:
>>> 5/2
2
(не 2.5 !) поверг в шок. Но такая “фича” Питона вроде лечится: “from __future__ import division”.
А вот сложение/вычитание вещественных чисел повергло в шок, от которого пока отойти не могу:
>>> 0.15 + 0.15 - 0.3
0.0
но
>>> 0.1 + 0.2 - 0.3
5.5511151231257827e-017
Как избавится от такой фичи/бага Питона, Лутц не написал….
Господа, а как же писать программы, если вместо нуля программа может вернуть такую дрянь? Прошу ответить, ибо вопрос достаточно серьезный.
Офлайн
Как видно 5 на 10 в минус 17 степени… то есть точность до тысячных просто не может страдать.
Функция format, при выводе результата на экран всё это дело лечит.
А вообще есть отдельная библиотека решающая эту проблему. Поиск по форуму даст ответы.
Офлайн
Для начала почитайте о том как хранятся вещественные числа в памяти: http://www.delphikingdom.ru/asp/viewitem.asp?catalogid=934
Лутц не написал о таком нюансе, т.к. это характерно для всех языков и изучается еще в школе на уроках информатики. Он и мыслях не мог представить, что вы этого не знаете! :)
Обычно, для научных вычислений используются вещественные числа.
Для операций, например, с деньгами следует использовать специальные типы данных: currency, money и т.п.
В Питоне, как в других языках, существуют специальные библиотеки для работы с такими числами.
http://www.google.com.ua/search?hl=ru&rls=ru&q=python+currency+money
Отредактировано (Март 10, 2009 23:06:27)
Офлайн
Format это конечно хорошо, но числа можно не только выводить. Условия if (a+b-c) == 0 будут давать неверный результат.
Если отдельная библиотека - это Decimal, то…. посудите сами:
получаю данные от веб-сервиса в виде дерева объектов. Теперь нужно пробежаться по дереву, все вещественные числа переписать “obj.attr = decimal.Decimal(obj.attr)” и только потом подставлять данные в формулы… Блин, ну это просто костыль какой-то…
Офлайн
Lexander
Я писал программы на PHP, JavaScript и C#. В этих языках -17 степени программиста не беспокоят.
Офлайн
dimabest
>>> 5/2
2
(не 2.5 !) поверг в шок.
>>> 5.0 / 2
2.5
Офлайн
dimabest
>>> 0.1 + 0.2 - 0.3
5.5511151231257827e-017
Как избавится от такой фичи/бага Питона, Лутц не написал….
[crchemist@localhost ~]$ lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> = 0.1 + 0.2 - 0.3
5.5511151231258e-17
http://tryruby.hobix.com/ Interactive ruby ready.
>> 1 + 2
=> 3
>> 0.1 + 0.2 - 0.3
=> 5.55111512312578e-17
>>
[crchemist@localhost ~]$ python
Python 2.5.2 (r252:60911, Sep 30 2008, 15:41:38)
[GCC 4.3.2 20080917 (Red Hat 4.3.2-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 0.1 + 0.2 - 0.3
5.5511151231257827e-17
>>>
Офлайн
Lexanderбггг, искал-искал и не нашел ничего кроме decimal из стандартной библиотеки Питона (которая, впрочем, мне вполне подходит) :). В php тоже возможны такие приколы с вещественными числами, но после набора операций с делениями, округлениями и т.п. А Питон, похоже, рубит на корню “неправильное” использование вещественных чисел, когда выдает такие результаты на тривиальных примерах.
Для операций, например, с деньгами следует использовать специальные типы данных: currency, money и т.п.
В Питоне, как в других языках, существуют специальные библиотеки для работы с такими числами.
http://www.google.com.ua/search?hl=ru&rls=ru&q=python+currency+money
Офлайн
Это не есть специфическая проблема Питона.
Так ведут себя флоаты вообще. На сопроцессоре.
Дело в том, что в любой системе счисления есть иррациональные числа
- в десятичной системе счисления это, например, 1/3. Невозможно записать его конечным количестом знаков.
- в двоичной - например, 1/5
print умеет маскировать этот случай, делая округление. repr - не делает. Но число в любом случае в душе - иррациональное.
>>> repr(1./5)
'0.20000000000000001'
>>> print 1./5
0.2
Офлайн
Четыре диалекта scheme - Ypsilon 0.9.6, Bigloo (3.1b), DrScheme 4.1.2, Gambit-C v4.3.2,
а также “J” 602a, REBOL, Factor, newlisp 10.0.2 - все выдали ответ 5.551115123125783e-17
CLISP 2.45 (- (+ 0.1 0.2) 0.3) = 0, но при этом (- (+ 0.1 0.4) 0.3) = 0.19999999
Отличился OpenLisp = -5.96046e-008
То есть многие языки, если не большинство - считают по умолчанию так же, как и Python.
Отредактировано (Март 11, 2009 09:25:24)
Офлайн