Найти - Пользователи
Полная версия: Ошибочный ответ в математических операциях.
Начало » Python для новичков » Ошибочный ответ в математических операциях.
1
Ankx
Я не так давно начал изучать 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
hellslade
>>> 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 Еще были темы похожие – поищите.
Ankx
Хм, замечательно… Я думал о чем-то в этом роде, но меня ввело в заблуждение, что print выводил нормальные 0.2
Но самый главный вопрос тогда как с этим бороться? Полазил по ссылкам, да вопрос поднимался явно часто, и объяснений почему так происходит много, но в основном везде пишут, мол это не ошибка и “небольшие проблемы с округлением” вроде как не проблема. Может быть, конечно но на мой взгляд это уже не “небольшие проблемы”, небольшие проблемы когда ошибка в седьмом знаке после запятой, а не не правильный ответ в арифметике “на пальцах”. Такое с числами пожалуй еще только php творит.
Но ведь пишут же на питоне сложные программы физико-математического плана, значит можно с этим бороться, правильно?
P.S. Пока сижу читаю ман по decimal, надеюсь поможет.
Ed
Ankx
Может быть, конечно но на мой взгляд это уже не “небольшие проблемы”, небольшие проблемы когда ошибка в седьмом знаке после запятой, а не не правильный ответ в арифметике “на пальцах”.
Для арифметики “на пальцах” вам math без надобности:
>>> y = 1268
>>> print y/10, y%10
126 8
Ankx
2 Ed, спасибо.
ZZZ
__builtins__.round
igor.kaist
Ankx, а зачем в каждой строке ставишь ; в конце?! Это же не паскаль…
Dimka665
лол же
>>> divmod(1268, 10)
(126, 8)
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