Уведомления

Группа в Telegram: @pythonsu

#1 Март 10, 2009 22:34:11

dimabest
От:
Зарегистрирован: 2009-02-12
Сообщения: 253
Репутация: +  0  -
Профиль   Отправить e-mail  

сложение/вычитание вещественных чисел

купил Лутца (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

Как избавится от такой фичи/бага Питона, Лутц не написал….

Господа, а как же писать программы, если вместо нуля программа может вернуть такую дрянь? Прошу ответить, ибо вопрос достаточно серьезный.



Офлайн

#2 Март 10, 2009 22:54:59

Griffon
От: Ukrain, Zaporozhie
Зарегистрирован: 2009-03-04
Сообщения: 324
Репутация: +  11  -
Профиль   Отправить e-mail  

сложение/вычитание вещественных чисел

Как видно 5 на 10 в минус 17 степени… то есть точность до тысячных просто не может страдать.
Функция format, при выводе результата на экран всё это дело лечит.

А вообще есть отдельная библиотека решающая эту проблему. Поиск по форуму даст ответы.



Офлайн

#3 Март 10, 2009 23:05:31

Lexander
От:
Зарегистрирован: 2008-09-19
Сообщения: 1139
Репутация: +  33  -
Профиль   Отправить e-mail  

сложение/вычитание вещественных чисел

Для начала почитайте о том как хранятся вещественные числа в памяти: 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)

Офлайн

#4 Март 10, 2009 23:08:57

dimabest
От:
Зарегистрирован: 2009-02-12
Сообщения: 253
Репутация: +  0  -
Профиль   Отправить e-mail  

сложение/вычитание вещественных чисел

Format это конечно хорошо, но числа можно не только выводить. Условия if (a+b-c) == 0 будут давать неверный результат.

Если отдельная библиотека - это Decimal, то…. посудите сами:

получаю данные от веб-сервиса в виде дерева объектов. Теперь нужно пробежаться по дереву, все вещественные числа переписать “obj.attr = decimal.Decimal(obj.attr)” и только потом подставлять данные в формулы… Блин, ну это просто костыль какой-то…



Офлайн

#5 Март 10, 2009 23:14:23

dimabest
От:
Зарегистрирован: 2009-02-12
Сообщения: 253
Репутация: +  0  -
Профиль   Отправить e-mail  

сложение/вычитание вещественных чисел

Lexander

Я писал программы на PHP, JavaScript и C#. В этих языках -17 степени программиста не беспокоят.



Офлайн

#6 Март 10, 2009 23:26:49

crchemist
От:
Зарегистрирован: 2008-07-09
Сообщения: 379
Репутация: +  0  -
Профиль   Отправить e-mail  

сложение/вычитание вещественных чисел

dimabest
>>> 5/2
2

(не 2.5 !) поверг в шок.
>>> 5.0 / 2
2.5



Офлайн

#7 Март 10, 2009 23:32:00

crchemist
От:
Зарегистрирован: 2008-07-09
Сообщения: 379
Репутация: +  0  -
Профиль   Отправить e-mail  

сложение/вычитание вещественных чисел

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
>>>



Офлайн

#8 Март 11, 2009 01:14:01

dimabest
От:
Зарегистрирован: 2009-02-12
Сообщения: 253
Репутация: +  0  -
Профиль   Отправить e-mail  

сложение/вычитание вещественных чисел

Lexander
Для операций, например, с деньгами следует использовать специальные типы данных: currency, money и т.п.
В Питоне, как в других языках, существуют специальные библиотеки для работы с такими числами.
http://www.google.com.ua/search?hl=ru&rls=ru&q=python+currency+money
бггг, искал-искал и не нашел ничего кроме decimal из стандартной библиотеки Питона (которая, впрочем, мне вполне подходит) :). В php тоже возможны такие приколы с вещественными числами, но после набора операций с делениями, округлениями и т.п. А Питон, похоже, рубит на корню “неправильное” использование вещественных чисел, когда выдает такие результаты на тривиальных примерах.



Офлайн

#9 Март 11, 2009 03:52:29

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

сложение/вычитание вещественных чисел

Это не есть специфическая проблема Питона.
Так ведут себя флоаты вообще. На сопроцессоре.
Дело в том, что в любой системе счисления есть иррациональные числа
- в десятичной системе счисления это, например, 1/3. Невозможно записать его конечным количестом знаков.
- в двоичной - например, 1/5

print умеет маскировать этот случай, делая округление. repr - не делает. Но число в любом случае в душе - иррациональное.

>>> repr(1./5)
'0.20000000000000001'
>>> print 1./5
0.2
decimal - хороша, но медленная.
В песочнице репозитария питона лежит cdecimal.
Она не вполне совместимая.
Других не знаю.
Думал как-то завернуть что-нибудь более приличное, реализацию IEEE-754, но так руки и не дошли. Используем стандартный decimal.



Офлайн

#10 Март 11, 2009 09:00:16

asv13
От:
Зарегистрирован: 2007-01-22
Сообщения: 130
Репутация: +  0  -
Профиль   Отправить e-mail  

сложение/вычитание вещественных чисел

Четыре диалекта 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)

Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version