Oberon space

General Category => Общий раздел => Тема начата: ilovb от Октябрь 09, 2012, 04:02:39 am

Название: Умный калькулятор
Отправлено: ilovb от Октябрь 09, 2012, 04:02:39 am
Всегда удивлялся виндозному калькулятору.

вычислим:
10 / 3 = 3,333333333333333

Что будет если умножить на 3 результат?
Каждый кодер знает что 9,999999999999999

Но этот засранец запоминает рациональные числа и выдает 10

К тому же он помнит не только последнее рациональное число, а на всю глубину вычислений.
Т.е. к числу 10 всегда можно вернуться выполняя обратные действия.
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 04:29:53 am
Всегда удивлялся виндозному калькулятору.

вычислим:
10 / 3 = 3,333333333333333

Что будет если умножить на 3 результат?
Каждый кодер знает что 9,999999999999999

Угу. А каждый программист знает что это не так :-) (и этим отличается программист от кодера)
$ cat float.cpp
#include <stdio.h>

int main() {
float foo;
float boo;
scanf("%f %f", &foo, &boo);
foo = foo/boo;
scanf("%f", &boo);
foo = foo*boo;
printf ("%f\n", foo);
return 0;
}
$ g++ float.cpp
$ ./a.out
10 3 3
10.000000
Название: Re: Умный калькулятор
Отправлено: ilovb от Октябрь 09, 2012, 04:47:32 am
Фу ты чорт я уже и подзабыл как тип Real устроен  :)
Название: Re: Умный калькулятор
Отправлено: ilovb от Октябрь 09, 2012, 05:33:14 am
Н да... В Real точность только на иррациональных числах теряется (в калькуляторе аналогично)
Мне почему-то казалось что в бесконечных дробях тоже...
Давно я на нормальных языках не кодил однако  :)
Название: Re: Умный калькулятор
Отправлено: Geniepro от Октябрь 09, 2012, 05:37:11 am
Hugs> 10/3
3.33333333333333
Hugs> 3.33333333333333*3
9.99999999999999

о_О

Однако

Hugs> let x=10/3 in 3*x
10.0
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 05:38:05 am
Н да... В Real точность только на иррациональных числах теряется (в калькуляторе аналогично)
Мне почему-то казалось что в бесконечных дробях тоже...
Давно я на нормальных языках не кодил однако  :)
Ключ к пониманию механизма лежит в ответе на вопрос: "что такое бесконечные дроби для IEEE 754?"
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 05:38:36 am
Hugs> 10/3
3.33333333333333
Hugs> 3.33333333333333*3
9.99999999999999

о_О
Выкинь свой haskell.
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 05:40:58 am
Однако

Hugs> let x=10/3 in 3*x
10.0
Работать с литералами не интересно - оно их может оптимизировать на лету. Работать надо с тем, о чем компилятор не знает, то есть с вводимыми числами пользователем.
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 05:45:05 am
Hugs> 10/3
3.33333333333333
Hugs> 3.33333333333333*3
9.99999999999999
Ой, сори. Выкинуть тебе следует не haskell, а мозг: ты же потерял точность ручками скопировав текстовое обрезанное представление. 3.33333333333333 не равно тому числу что находится в памяти компьютера когда он делит 10/3.

> 3.33333333333333 == 10/3
=> False
Название: Re: Умный калькулятор
Отправлено: ilovb от Октябрь 09, 2012, 05:58:18 am
Однако в виндозном калькуляторе:
1/3 + 4/3 - 5/3 = 0
а в черной каропке:
1/3 + 4/3 - 5/3 = -2.220446049250313E-160.0000000000  ???
Название: Re: Умный калькулятор
Отправлено: ilovb от Октябрь 09, 2012, 06:04:04 am
Пардон, лишнее скопировал. Там так:
1/3 + 4/3 - 5/3 = -2.220446049250313E-16

Похоже что точность 10/3 - это просто неудачный пример
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 06:19:18 am
Однако в виндозном калькуляторе:
1/3 + 4/3 - 5/3 = 0
а в черной каропке:
1/3 + 4/3 - 5/3 = -2.220446049250313E-160.0000000000  ???
У виндовозного калькулятора точность выше (то есть там не 64битные числа).
Название: Re: Умный калькулятор
Отправлено: Geniepro от Октябрь 09, 2012, 06:21:13 am
Пардон, лишнее скопировал. Там так:
1/3 + 4/3 - 5/3 = -2.220446049250313E-16

Похоже что точность 10/3 - это просто неудачный пример

Hugs> 1/3 + 4/3 - 5/3
-2.22044604925031e-016
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 06:28:58 am
Пардон, лишнее скопировал. Там так:
1/3 + 4/3 - 5/3 = -2.220446049250313E-16

Похоже что точность 10/3 - это просто неудачный пример

Hugs> 1/3 + 4/3 - 5/3
-2.22044604925031e-016
Сколько знаков после запятой в маздайном калькуляторе? Если 15ть, то:
$ cat float.cpp
#include <stdio.h>

int main() {
double a,b,c;
scanf("%lf %lf %lf",&a,&b,&c);
a = a/3;
b = b/3;
c = c/3;
printf ("%1.15lf\n", a+b-c);
return 0;
}

$ ./a.out
1 4 5
-0.000000000000000
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 06:29:50 am
Пардон, лишнее скопировал. Там так:
1/3 + 4/3 - 5/3 = -2.220446049250313E-16

Похоже что точность 10/3 - это просто неудачный пример
Ключевой вопрос - почему это неудачный пример? ;-)
Название: Re: Умный калькулятор
Отправлено: Geniepro от Октябрь 09, 2012, 06:34:25 am
main = do
    putStr "x: "; x<-readLn
    putStr "y: "; y<-readLn
    let xy=x/y
    putStr "z: "; z<-readLn
    putStrLn $ show x  ++ "/" ++ show y ++ " = " ++ show xy
    putStrLn $ show xy ++ "*" ++ show z ++ " = " ++ show (xy * z)

Main> :main
x: 10
y: 3
z: 3
10.0/3.0 = 3.33333333333333
3.33333333333333*3.0 = 10.0
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 06:35:41 am
main = do
    putStr "x: "; x<-readLn
    putStr "y: "; y<-readLn
    let xy=x/y
    putStr "z: "; z<-readLn
    putStrLn $ show x  ++ "/" ++ show y ++ " = " ++ show xy
    putStrLn $ show xy ++ "*" ++ show z ++ " = " ++ show (xy * z)

Main> :main
x: 10
y: 3
z: 3
10.0/3.0 = 3.33333333333333
3.33333333333333*3.0 = 10.0
Именно.
Название: Re: Умный калькулятор
Отправлено: Geniepro от Октябрь 09, 2012, 06:38:27 am
import Data.Ratio

r = 1%3 + 4%3 - 5%3

Main> r
0 % 1

Работайте, господа, с рациональными дробями! )))
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 06:50:03 am
Н да... В Real точность только на иррациональных числах теряется (в калькуляторе аналогично)
Мне почему-то казалось что в бесконечных дробях тоже...

Про "бесконечные" дроби есть пример интересней:
printf ("%1.70lf\n", 0.3);выдает:
0.2999999999999999888977697537484345957636833190917968750000000000000000Как думаешь, почему? ;-)

А вот такое:
printf ("%1.70lf\n", 0.3f);выдает такое:
0.3000000119209289550781250000000000000000000000000000000000000000000000
Жить страшно, не правда ли?

Что выбираешь, тайд или кипячение? ;-)
Название: Re: Умный калькулятор
Отправлено: ilovb от Октябрь 09, 2012, 06:55:30 am
Если бы я еще шарил в кракозябрах этих "printf ("%1.70lf\n", 0.3);"  ;D
Это типа вывод числа 0.3 с большим числом знаков после запятой?
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 06:57:36 am
Если бы я еще шарил в кракозябрах этих "printf ("%1.70lf\n", 0.3);"  ;D
Это типа вывод числа 0.3 с большим числом знаков после запятой?
Да. Это ("%1.70lf\n") называется - форматный вывод. И это то самое место, которое в Си сделано удобней чем в стандартной плюсовой либе. Да и во многих других языках тоже (если они не копируют это у Сей).
Название: Re: Умный калькулятор
Отправлено: ilovb от Октябрь 09, 2012, 07:03:06 am
То что не все числа представимы в формате IEEE754 для меня не новость.
Смущает больше что точность не теряется при вычислении 10/3.

Я предпочитаю ожидать погрешность в этом случае. И считаю что это правильно.

виндозный калькулятор же всегда сохраняет точность на рациональных числах (по крайней мере не замечал обратного)

Соответственно я предположил что он хранит таки рациональные числа.
Но скорее всего ты прав. В нем наверно просто формат IEEE754 128 бит.
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 07:25:14 am
То что не все числа представимы в формате IEEE754 для меня не новость.
Смущает больше что точность не теряется при вычислении 10/3.

Я предпочитаю ожидать погрешность в этом случае. И считаю что это правильно.
Окэй, не хочешь подумать/повикипедить, скажу ответ: представление чисел у компьютера не десятичное, а таки двоичное. Следовательно конечные десятичные дроби могут быть бесконечными двоичными (замечу, что конечная двоичная дробь это всегда конечная же десятичная). Поэтому 0.3 - это бесконечная периодическая дробь в двоичном представлении.

А "точность" того, что выводит мелкомягкий калькулятор скорее всего связана с тем, что на экранчике мало циферек и он просто округляет (форматный вывод, ага). Ну и длинные числа. Скорее всего там даже не 128 бит, а именно реально длинные числа (по крайней мере для целочисленнки там точно они, советую поэкспериментировать с факториалом, оценить время работы на больших числах). Длинные числа - это значит, что такое число легко может занимать например килобайт. В общем, ограничены лишь своп-файлом.
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 07:37:56 am
А "точность" того, что выводит мелкомягкий калькулятор скорее всего связана с тем, что на экранчике мало циферек и он просто округляет (форматный вывод, ага). Ну и длинные числа. Скорее всего там даже не 128 бит, а именно реально длинные числа (по крайней мере для целочисленнки там точно они, советую поэкспериментировать с факториалом, оценить время работы на больших числах). Длинные числа - это значит, что такое число легко может занимать например килобайт. В общем, ограничены лишь своп-файлом.
Да, либо, что вероятно, там просто фиксированная точка. Эксперименты показали, что больше чем 10^10000 и меньше чем 10^-10000 оно не обрабатывает. Так что разумнее всего сделать было именно фиксированную точку.
Название: Re: Умный калькулятор
Отправлено: ilovb от Октябрь 09, 2012, 07:45:48 am
Окэй, не хочешь подумать/повикипедить, скажу ответ: представление чисел у компьютера не десятичное, а таки двоичное. Следовательно конечные десятичные дроби могут быть бесконечными двоичными (замечу, что конечная двоичная дробь это всегда конечная же десятичная). Поэтому 0.3 - это бесконечная периодическая дробь в двоичном представлении.

Ну так это и означает что:
Цитата: ilovb
... не все числа представимы в формате IEEE754

Т.е. конечную десятичную дробь 0.3 в этом формате представить нельзя

А "точность" того, что выводит мелкомягкий калькулятор скорее всего связана с тем, что на экранчике мало циферек и он просто округляет (форматный вывод, ага). Ну и длинные числа.

Там вообще странно...
Вот результат вычисления в калькуляторе:
sqrt(2) * sqrt(2) - 2 = -1,588200079154339e-19

однако
sqrt(2) * sqrt(2) = 2

Скорее всего там даже не 128 бит, а именно реально длинные числа (по крайней мере для целочисленнки там точно они, советую поэкспериментировать с факториалом, оценить время работы на больших числах). Длинные числа - это значит, что такое число легко может занимать например килобайт. В общем, ограничены лишь своп-файлом.

Ну в 1С длинные числа. И ведут они себя не так.
Собственно они себя предсказуемо ведут в противоположность IEEE754.
Погрешность всегда ровно там, где ее ожидаешь.
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 07:51:38 am
Ну так это и означает что:
Цитата: ilovb
... не все числа представимы в формате IEEE754

Т.е. конечную десятичную дробь 0.3 в этом формате представить нельзя
Можно, при условии что пользователь будет смотреть на нее через узкую амбразуру форматного вывода :-)

Там вообще странно...
Вот результат вычисления в калькуляторе:
sqrt(2) * sqrt(2) - 2 = -1,588200079154339e-19

однако
sqrt(2) * sqrt(2) = 2
Либо очередные выкрутасы форматного вывода (формат может зависить от целой части числа - по сравнению с двойкой остаток неточный ничтожен, а вот по сравнению с нулем - значим), либо оно таки умеет полусимвольно вычислять.

Я полагаю, что калькуляторы у разных версий винды разные. Потому как добравшись до калькулятора Win7 я увидел поведение которого раньше там не было.
Название: Re: Умный калькулятор
Отправлено: Geniepro от Октябрь 09, 2012, 09:39:06 am
... именно реально длинные числа (по крайней мере для целочисленнки там точно они, советую поэкспериментировать с факториалом, оценить время работы на больших числах). ...

Win7 64-bit, calc.exe
1000! = 4,02387260077093773543702433923e+2567

ну и де тут длинные целые? о_О
Название: Re: Умный калькулятор
Отправлено: Geniepro от Октябрь 09, 2012, 09:44:41 am
... именно реально длинные числа (по крайней мере для целочисленнки там точно они, советую поэкспериментировать с факториалом, оценить время работы на больших числах). ...

Win7 64-bit, calc.exe
1000! = 4,02387260077093773543702433923e+2567

ну и де тут длинные целые? о_О

Хотя, похоже, там есть длинные числа: 1000! - (1000! - 1) = 1 (делал вычисления через его память по кнопкам M+ M- MR)
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 09:47:23 am
... именно реально длинные числа (по крайней мере для целочисленнки там точно они, советую поэкспериментировать с факториалом, оценить время работы на больших числах). ...

Win7 64-bit, calc.exe
1000! = 4,02387260077093773543702433923e+2567

ну и де тут длинные целые? о_О
Дык это ж афигенно длинное целое! Или тебя предствление этого числа смучает (форматный вывод то есть)? ;-)
Название: Re: Умный калькулятор
Отправлено: ilovb от Октябрь 09, 2012, 10:34:54 am
Это как раз укладывается в 128 бит формат

Число четверной точности (http://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%BE_%D1%87%D0%B5%D1%82%D0%B2%D0%B5%D1%80%D0%BD%D0%BE%D0%B9_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D0%B8)
Цитата:
0x 7ffe ffff ffff ffff ffff ffff ffff ffff  ≈  1.189731495357231765085759326628007 × 10^4932 (Максимальное число четверной точности)
Название: Re: Умный калькулятор
Отправлено: valexey_u от Октябрь 09, 2012, 11:11:25 am
Это как раз укладывается в 128 бит формат

Число четверной точности (http://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%BE_%D1%87%D0%B5%D1%82%D0%B2%D0%B5%D1%80%D0%BD%D0%BE%D0%B9_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D0%B8)
Цитата:
0x 7ffe ffff ffff ffff ffff ffff ffff ffff  ≈  1.189731495357231765085759326628007 × 10^4932 (Максимальное число четверной точности)
Только это целочи число ты посчитал. А пределы для плавающей точки четверной точности будут другими.
Название: Re: Умный калькулятор
Отправлено: ilovb от Октябрь 09, 2012, 01:06:52 pm
Вот где длинная арифметика  :)  http://www.wolframalpha.com/input/?i=10000000000%21
Название: Re: Умный калькулятор
Отправлено: Geniepro от Октябрь 09, 2012, 10:35:08 pm
Это как раз укладывается в 128 бит формат

Число четверной точности (http://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%BE_%D1%87%D0%B5%D1%82%D0%B2%D0%B5%D1%80%D0%BD%D0%BE%D0%B9_%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D0%B8)
Цитата:
0x 7ffe ffff ffff ffff ffff ffff ffff ffff  ≈  1.189731495357231765085759326628007 × 10^4932 (Максимальное число четверной точности)
ну аналогично для (10000! - 1) - 10000! = -1
при том что 10000! = 2,8462596809170545189064132121199e+35659 (calc.exe из WinXP sp3)