Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Python
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > Программирование
_Pasha
Привет!
Долго мне питон не нравился, потом таки постепенно начал вникать, дух противоречия спадает.
Решил отбросить разное лишнее, калькулятор в частности, и пользоваться питоноконсолью.
Но сегодня с утра я в шоке:
Код
Python 2.7.3 (default, Sep 26 2012, 21:53:58)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 40.0-37.96
2.039999999999999
>>>

Что бы это значило? crying.gif
--
Граница глюка
>>> 40-31.2
8.8
>>> 40-32.2
7.799999999999997
Причем, в выражениях - то же самое. Это чтож оно насчитает в итоге?!

Вести с полей.
Если пишешь print 40-37.96 то выводит 2.04
Нет никакого желания продолжать дальше. На использование в кач-ве калькулятора можно забить. И хорошо, что из книжек 80-х годов осталась масса макулатуры по бейсику, там всегда были контрольные примеры. Проверим, что эта гадость в компании с numPy насчитает, хотя бы с матрицами. Ух, как я зол!
demidrol
это уже прочитал? Вообще-то питон честно следует ieee-шному стандарту на числа с плавающей точкой и показывает их так, как видит машина.

И бейсик и фортран (даже матлаб) вам посчитают точно то же самое, только вывод на экран там -- как бы это поточнее сказать -- более "умный".
_Pasha
Цитата(demidrol @ Feb 25 2013, 10:17) *
И бейсик и фортран (даже матлаб) вам посчитают точно то же самое, только вывод на экран там -- как бы это поточнее сказать -- более "умный".

Где-то должно что-то задаваться для подобного представления, чует мое сердце.
Но это все цветочки. Берем онлайн конвертер ieee754 в зубы и курим
Код
исходное        после преобр. к double
40.0                40.0
30.2                30.200000762939453
31.2                31.200000762939453
32.2                32.20000076293945

Я перестаю понимать. При вычитании чушь начинается как только экспоненты стали равны.
А у 40 и 32.2 экспонента == 5
До того, по законам жанра, должны выравниваться порядки и только после вычитаться мантиссы. И в этом случае все нормально, хотя "мусор" в вычитаемом тот же. А представления меняются. Чушь? Чушь собачья!
Виктория
То есть исходный вопрос заключается все-таки "Как правильно вывести на печать?"
Сегодня праздник "чистых" программистов?
MrYuran
Код
Python 2.7.2 (default, Jun 12 2011, 15:08:59) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> 30.2+31.3
61.5
>>> 32.2+31.25
63.45
>>>

Венда, версия пытона на 1 младше, чем

Код
>>> 40-37.96
2.039999999999999
>>> 40-32.2
7.799999999999997
>>>


smile3046.gif

А вот так:
Код
>>> a = 40-32.2
>>> print a
7.8
>>>
Виктория
Ага, непонятно почему print с его стандартными модификаторами e, f, g и т.п. игнорируется?

Вообще то, если уж задумываться о точности и возможностях Питона с его динамическими типами, то наверно стоит познакомиться также с такими пакетами Python library for arbitrary-precision floating-point arithmetic

Цитата
Mpmath is a pure-Python library for multiprecision floating-point
arithmetic. It provides an extensive set of transcendental functions,
unlimited exponent sizes, complex numbers, interval arithmetic,
numerical integration and differentiation, root-finding, linear algebra,
and much more. Almost any calculation can be performed just as well at
10-digit or 1000-digit precision, and in many cases mpmath implements
asymptotically fast algorithms that scale well for extremely high
precision work. Mpmath internally uses Python's builtin long integers by
default, but automatically switches to GMP/MPIR for much faster
high-precision arithmetic if gmpy is installed
thermit
Цитата
_Pasha:
Что бы это значило?


Это означает, что множество чисел типа double не содержит числа 2.04

Цитата
Если пишешь print 40-37.96 то выводит 2.04


print выполняет округление.

Цитата
Ух, как я зол!


Пользуйтесь прогами позволяющими оперировать с числами произвольной точности.
Например, pari/gp, J...
Хотя, для подавляющего большинства вычислений точности даблов хватает. Не очень понимаю, что именно вас не устраивает.
_Pasha
Цитата(Виктория @ Feb 25 2013, 12:43) *
То есть исходный вопрос заключается все-таки "Как правильно вывести на печать?"

Все-таки ™ вопрос такой, точнее, я бы сделал так, чтобы для операндов в выражении, состоящем исключительно из операций сложения/вычитания, учитывалась точность входных операндов и результат округлялся до той точности, которая максимальная. Насчет тотальной применимости - сомневаюсь, можно сломать арифметику, но в консольном режиме это просто должно быть.

Цитата(Виктория @ Feb 25 2013, 13:50) *
Вообще то, если уж задумываться о точности и возможностях Питона с его динамическими типами, то наверно стоит познакомиться также с такими пакетами

Ага. Спасибо, у меня его еще нет.

Цитата(MrYuran @ Feb 25 2013, 13:19) *
Венда, версия пытона на 1 младше, чем

Невероятно, но
Код
Python 2.7.3 (default, Sep 26 2012, 21:53:58)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 32.2+31.25
63.45
>>> 30.2+31.3
61.5
>>> 37.96+2.04
40.0
>>>


Цитата(thermit @ Feb 25 2013, 14:14) *
Это означает, что множество чисел типа double не содержит числа 2.04

Судя по листингу выше, это ничего не означает sm.gif
thermit
Цитата
Судя по листингу выше, это ничего не означает


Означает. Даже не сомневайтесь.
А вот листинг действительно ничего не означает, ибо

Код
>> 37.96+2.039999999999999

ans =

    40
>> 37.96+2.039999999999998

ans =

    40
>> 37.96+2.039999999999997

ans =

    40
>> 37.96+2.04

ans =

    40


Успехов в поиске несуществующих глюков.
_Pasha
Цитата(thermit @ Feb 25 2013, 15:00) *
Успехов в поиске несуществующих глюков.

Спасибо, ужЕ нашел biggrin.gif
Еще раз, механика скорбного дела.
37.96+2.04 Выровняли порядки и сложили. Ошибка представления ушла от сдвигов мантиссы 2.04 вправо.
--
Вычли из 40 37.96 появилась ошибка представления. Вопросов нет.
--
Вычли из 40 31.2 после приведения порядков ошибка представления ушла? А нормализация с непременным сдвигом влево?
--
Вопрос: почему нельзя сразу округлить результат до числа, представленного наибольшей точностью? Если эти точности заданы явно? Кому это полезно?
thermit
Цитата
_Pasha:
Вычли из 40 31.2 после приведения порядков ошибка представления ушла?


Куда кто ушел? 31.2 уже не представимо. Мантисса не позволяет. Ближайшее 31.199999999999999.
haker_fox
Гм, ради интереса у себя все проверил... Тоже самое) Как быть-то?
CODE
Python 3.2.3 (default, Apr 11 2012, 07:15:24) [MSC v.1500 32 bit (Intel)] on
32
Type "help", "copyright", "credits" or "license" for more information.
>>> 40.0-37.96
2.039999999999999

>>> print (40.0 - 37.96)
2.039999999999999
>>>
_Pasha
Цитата(thermit @ Feb 25 2013, 16:25) *
Куда кто ушел? 31.2 уже не представимо. Мантисса не позволяет. Ближайшее 31.199999999999999.

Вот и именно.
40.0 = 1.25*2^5
31.2 = 1.9500000476837158 * 2^4=0.975000023841858*2^5 (казалось бы, здесь она уменьшается, эта ошибка)
40.0-31.2 = 0.274999976158142*2^5=8.79999923706054
--
А пишет 8.8 cranky.gif
Т.е. в зависимости от того, как там дела на Марсе, он то "хочет" округлить то "не хочет"
--
Для более придирчивого взгляда, обобщу: если мы из представимого множеством double числа вычтем непредставимое, то в результате обязательно получим непредставимое, а в консоли это не так.
Виктория
Цитата(_Pasha @ Feb 25 2013, 18:02) *
Т.е. в зависимости от того, как там дела на Марсе, он то "хочет" округлить то "не хочет"


Может сервис локализации тут мельтешит?( Параметры категории LC_NUMERIC, какое правильное значение grouping для Ваших примеров - никак не соображу, в Excel всё это выглядит как-то прозрачнее).
_Pasha
Цитата(Виктория @ Feb 25 2013, 20:12) *
Может сервис локализации тут мельтешит?( Параметры категории LC_NUMERIC, какое правильное значение grouping для Ваших примеров - никак не соображу, в Excel всё это выглядит как-то прозрачнее).

OK. Смотрим, ессно, дефолтный локаль, какой эст
Код
>>> import locale
>>> locale.localeconv()
{'mon_decimal_point': '', 'int_frac_digits': 127, 'p_sep_by_space': 127, 'frac_digits': 127, 'thousands_sep': '', 'n_sign_posn': 127, 'decimal_point': '.', 'int_curr_symbol': '', 'n_cs_precedes': 127, 'p_sign_posn': 127, 'mon_thousands_sep': '', 'negative_sign': '', 'currency_symbol': '', 'n_sep_by_space': 127, 'mon_grouping': [], 'p_cs_precedes': 127, 'positive_sign': '', 'grouping': []}
>>>

Врядли оно тутта при чём. Это чистая проблема конверсии double -> string
До системы уравнений пока сегодня не добрался sm.gif на предмет чреватости ошибки, но это тоже врядли. Не может же весь мир дураками быть, в конце концов!
--
Покурю-ка я исходники 2.7.3
Себе полезно, - людЯм интересно sm.gif
Тем более, документировано - ну просто красота!
Виктория
Не забудьте рассказать результаты. Как я поняла по этим страницам "усовершенствование IEEE-754" началось как раз с версии 2.7
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.