Уведомления

Группа в Telegram: @pythonsu

#1 Июль 4, 2009 17:08:20

Ankx
От:
Зарегистрирован: 2009-07-04
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Ошибочный ответ в математических операциях.

Я не так давно начал изучать Python, и вобщем-то применил свою всегдашнюю методику:
читаем документацию, ищем для себя N десятков маленьких, но интересных полупрактических задачек для тренировки (в этом лично мне очень помогает diofant.ru).
И во время решения одной такой задачки натолкнулся на необъяснимую для меня странность, в написанном алгоритме отделения от числа единиц. То есть число, например, 56 должен представить как 5 и 6; 1268 как 126 и 8 и т.д и т.п.:
Однако оказалось если двухзначное число записано из двух цифр n и n+1 в ответ выдается n, причем во всех остальных случаях все работает без накладок.
Собственно код дающий ошибку:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import math;
y = 12;
z, Buffer = math.modf(y / 10.0);
print z;
z = z * 10;
print z;
z = int(z);
print(z);
В выводе будет 0.2 2.0 и… 1!
Для y = 34 - 3.
В случае же если число не указанного вида (n и n+1) ответ будет соответствовать действительности.

Видно что ошибка возникает после z = int(z). Использование math.trunc проблем не решает.
Что удивительно такой код работает правильно:
x = 2.0;
x = int(2.0);
print x;
Хотя не совсем понятно чем один случай отличается от второго.
То же самое в run time^\:
lexa@linux-lexa:~> python
Python 2.6 (r26:66714, Dec 3 2008, 10:55:18)
[GCC 4.3.2 [gcc-4_3-branch revision 141291]] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> y=12
>>> z, Buffer = math.modf(y / 10.0)
>>> print z
0.2
>>> z = z * 10
>>> print z
2.0
>>> z = int(z)
>>> print z
1
Для интереса сваял аналогичную программку на том что валялоь ближе, т.е. на Pascal:
program buben ;

uses crt;
var y : integer;
z : real;

BEGIN
y := 12;
z := frac(y / 10);
writeln(z);
z := z * 10;
writeln(z);
y:=trunc(z);
writeln(y);
END.
Ошибка не повторилась, вывел следующее:
2.00000000000000E-001
2.00000000000000E+000
2

Уже весь мозг над проблемой сломал, может кто нибудь объяснить в чем дело?

Как оказалось все сложнее, и ошибка приходится не на все и не только на числа приведенного мной вида, написал для проверки:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import math;
print "Введено Получено Должно.0";
for y in range(11, 100):
z, Buffer = math.modf(y / 10.0);
z = z * 10;
a = z;
z = int(z);
print str(y) + " ...... " + str(z) + " ...... " + str(a);
Привожу теперь только список ошибок для краткости:
Введено Получено Должно.0
12 …… 1 …… 2.0
14 …… 3 …… 4.0
23 …… 2 …… 3.0
24 …… 3 …… 4.0
28 …… 7 …… 8.0
33 …… 2 …… 3.0
34 …… 3 …… 4.0
38 …… 7 …… 8.0
41 …… 0 …… 1.0
43 …… 2 …… 3.0
46 …… 5 …… 6.0
48 …… 7 …… 8.0
51 …… 0 …… 1.0
53 …… 2 …… 3.0
56 …… 5 …… 6.0
58 …… 7 …… 8.0
61 …… 0 …… 1.0
63 …… 2 …… 3.0
66 …… 5 …… 6.0
68 …… 7 …… 8.0
71 …… 0 …… 1.0
73 …… 2 …… 3.0
76 …… 5 …… 6.0
78 …… 7 …… 8.0
81 …… 0 …… 1.0
82 …… 1 …… 2.0
86 …… 5 …… 6.0
87 …… 6 …… 7.0
91 …… 0 …… 1.0
92 …… 1 …… 2.0
96 …… 5 …… 6.0
97 …… 6 …… 7.0



Отредактировано (Июль 4, 2009 17:23:25)

Офлайн

#2 Июль 4, 2009 17:46:19

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

Ошибочный ответ в математических операциях.

>>> import math
>>> y = 12
>>> z, Buffer = math.modf(y / 10.0)
>>> z
0.19999999999999996
>>> z
1.9999999999999996
int() отбрасывает всю дробную часть и остается “1” :)
вот здесь почитайте (первое, что попалось на глаза)
http://python.su/forum/viewtopic.php?id=4648 Еще были темы похожие – поищите.



Офлайн

#3 Июль 4, 2009 18:29:28

Ankx
От:
Зарегистрирован: 2009-07-04
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Ошибочный ответ в математических операциях.

Хм, замечательно… Я думал о чем-то в этом роде, но меня ввело в заблуждение, что print выводил нормальные 0.2
Но самый главный вопрос тогда как с этим бороться? Полазил по ссылкам, да вопрос поднимался явно часто, и объяснений почему так происходит много, но в основном везде пишут, мол это не ошибка и “небольшие проблемы с округлением” вроде как не проблема. Может быть, конечно но на мой взгляд это уже не “небольшие проблемы”, небольшие проблемы когда ошибка в седьмом знаке после запятой, а не не правильный ответ в арифметике “на пальцах”. Такое с числами пожалуй еще только php творит.
Но ведь пишут же на питоне сложные программы физико-математического плана, значит можно с этим бороться, правильно?
P.S. Пока сижу читаю ман по decimal, надеюсь поможет.



Отредактировано (Июль 4, 2009 18:37:24)

Офлайн

#4 Июль 4, 2009 18:47:25

Ed
От:
Зарегистрирован: 2008-12-13
Сообщения: 1032
Репутация: +  13  -
Профиль   Отправить e-mail  

Ошибочный ответ в математических операциях.

Ankx
Может быть, конечно но на мой взгляд это уже не “небольшие проблемы”, небольшие проблемы когда ошибка в седьмом знаке после запятой, а не не правильный ответ в арифметике “на пальцах”.
Для арифметики “на пальцах” вам math без надобности:
>>> y = 1268
>>> print y/10, y%10
126 8



Офлайн

#5 Июль 4, 2009 18:54:54

Ankx
От:
Зарегистрирован: 2009-07-04
Сообщения: 4
Репутация: +  0  -
Профиль   Отправить e-mail  

Ошибочный ответ в математических операциях.

2 Ed, спасибо.



Отредактировано (Июль 4, 2009 19:09:58)

Офлайн

#6 Июль 4, 2009 19:07:27

ZZZ
От: Москва
Зарегистрирован: 2008-04-03
Сообщения: 2161
Репутация: +  26  -
Профиль   Адрес электронной почты  

Ошибочный ответ в математических операциях.

__builtins__.round



Офлайн

#7 Июль 5, 2009 12:29:31

igor.kaist
От:
Зарегистрирован: 2007-11-12
Сообщения: 1879
Репутация: +  3  -
Профиль   Отправить e-mail  

Ошибочный ответ в математических операциях.

Ankx, а зачем в каждой строке ставишь ; в конце?! Это же не паскаль…



Офлайн

#8 Июль 6, 2009 07:30:43

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

Ошибочный ответ в математических операциях.

лол же

>>> divmod(1268, 10)
(126, 8)



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version