Найти - Пользователи
Полная версия: сложение/вычитание вещественных чисел
Начало » Python для новичков » сложение/вычитание вещественных чисел
1 2 3
dimabest
купил Лутца (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

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

Господа, а как же писать программы, если вместо нуля программа может вернуть такую дрянь? Прошу ответить, ибо вопрос достаточно серьезный.
Griffon
Как видно 5 на 10 в минус 17 степени… то есть точность до тысячных просто не может страдать.
Функция format, при выводе результата на экран всё это дело лечит.

А вообще есть отдельная библиотека решающая эту проблему. Поиск по форуму даст ответы.
Lexander
Для начала почитайте о том как хранятся вещественные числа в памяти: 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
dimabest
Format это конечно хорошо, но числа можно не только выводить. Условия if (a+b-c) == 0 будут давать неверный результат.

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

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

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

(не 2.5 !) поверг в шок.
>>> 5.0 / 2
2.5
crchemist
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
>>>
dimabest
Lexander
Для операций, например, с деньгами следует использовать специальные типы данных: currency, money и т.п.
В Питоне, как в других языках, существуют специальные библиотеки для работы с такими числами.
http://www.google.com.ua/search?hl=ru&rls=ru&q=python+currency+money
бггг, искал-искал и не нашел ничего кроме decimal из стандартной библиотеки Питона (которая, впрочем, мне вполне подходит) :). В php тоже возможны такие приколы с вещественными числами, но после набора операций с делениями, округлениями и т.п. А Питон, похоже, рубит на корню “неправильное” использование вещественных чисел, когда выдает такие результаты на тривиальных примерах.
Андрей Светлов
Это не есть специфическая проблема Питона.
Так ведут себя флоаты вообще. На сопроцессоре.
Дело в том, что в любой системе счисления есть иррациональные числа
- в десятичной системе счисления это, например, 1/3. Невозможно записать его конечным количестом знаков.
- в двоичной - например, 1/5

print умеет маскировать этот случай, делая округление. repr - не делает. Но число в любом случае в душе - иррациональное.
>>> repr(1./5)
'0.20000000000000001'
>>> print 1./5
0.2
decimal - хороша, но медленная.
В песочнице репозитария питона лежит cdecimal.
Она не вполне совместимая.
Других не знаю.
Думал как-то завернуть что-нибудь более приличное, реализацию IEEE-754, но так руки и не дошли. Используем стандартный decimal.
asv13
Четыре диалекта 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.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB