LINUX.ORG.RU

Представление иррациональных чисел без потери точности

 ,


2

1

Привет. Задумал совместить важное и нужное с полезным, а именно решил начать изучать haskell, а заодно и написать на нём очередную имэджбоарду набор сценариев/или какой-то проектик (пока не сформировал мысль, что именно это должно быть, возможно, некоторое моделирование каких-нибудь процессов)

Нужны комплексные числа. Действительная и мнимая часть их может быть иррациональной. Числа pi там скорее всего не будет, но будет (sqrt 2), насчёт остальных корней пока не знаю, актуально ли. Ну в идеале чтобы можно было представить числа в любой рациональной степени (2 в степени 1/2, например, что и есть sqrt 2).

Хотелось, чтобы эти степени и корни не вычислялись, а представлялись в памяти как есть (haskell ведь ленивый язык?), и в случае необходимости сами себя упрощали (если я умножаю sqrt 2 на самого себя, я получаю же 2?)

Может быть и не любое иррациональное число можно так представить... но мне и не все нужны, а только простые случаи.

Понятно, почему я не хочу real/float - неизбежные потери точности. Можно постоянно применять округления, но, думаю, тут я могу получить неожиданности. Потери в производительности меня не смущают, не думаю, что они пока актуальны.

Так вот, мой вопрос в том - есть ли что-то уже готовое может быть? Я ничего не нашёл... похоже, придётся делать самому. Стандартный тип Complex вроде как работает с Float/Double либо Int, либо Rational, что немного не то... если я не ошибся?

P.S. Знаю, что, возможно, всё это есть в Maple, и, может быть, даже в mathematica или maxima, но это как-то «не спортивно» что ли. :) Да и не хочется зависеть от математических пакетов.

Сделай, в чём проблема-то.

Можешь просто положиться на ленивость, а можешь намутить свой упращатор (по аналогии с символьным вычислением производной из SICP).

Посмотри, кстати, раздельчик «Extended example: Numeric Types» из 13й главы RWH, думаю, будет интересно.

yoghurt ★★★★★ ()
Ответ на: комментарий от yoghurt

Спасибо. Почитаю. Да, я и думал, что придётся делать, оно и к лучшему, лучше разберусь в вопросе.

BattleCoder ★★★★★ ()

Хотелось, чтобы эти степени и корни не вычислялись, а представлялись в памяти как есть (haskell ведь ленивый язык?), и в случае необходимости сами себя упрощали (если я умножаю sqrt 2 на самого себя, я получаю же 2?)

data Expr 
  = NF  Int
  | Com (Complex Expr) 
  | Add Expr Expr
  | Sub Expr Expr
  | Mul Expr Expr
  | Sqrt Expr 
  | Exp Expr Expr

instance Num Expr where
  (+) = Add
  ...

simplify :: Expr -> Expr
simplify (Exp (Sqrt e) (Lit 2)) = e
simplify ...
 
eval   :: Expr -> Double
pprint :: Expr -> String

instance Show Expr where
  show = pprint . simplify
...
fmap ()

Числа pi там скорее всего не будет, но будет (sqrt 2), насчёт остальных корней пока не знаю, актуально ли

Если только корни, это называется «алгебраические» числа. Если же только sqrt(2), то это еще проще. как называется, не подскажу, но реализовать элементарно - аналогично комплексным, только не i^2 = -1, а i^2 = 2

MyTrooName ★★★★★ ()
Ответ на: комментарий от provaton

я не говорю, что это плохо. Я говорю, что полноценное решение проблемы ТС - это CAS.

И да я хочу CAS для haskell, или байндинги к maple хотя бы, т.к. самому времени писать нет, а делать расчеты для диссера на haskell приятнее, чем в чистом maple :)

Или хотя бы crack для reduce переписать, вроде автор хотел, но не знаю как у него с этим дела (и вообще жив ли он).

qnikst ★★★★★ ()
Ответ на: комментарий от BattleCoder

либо это будет смешная штука как писал душкин для курса по квантам для курсеры, либо покрывать только мелкий интересующий юзкейс.

Если это цель и это устравивает, то можно читать тред дальше и смотреть варианты :)

qnikst ★★★★★ ()
Последнее исправление: qnikst (всего исправлений: 1)

Стандартный тип Complex вроде как работает с Float/Double либо Int, либо Rational, что немного не то... если я не ошибся?

Complex работает с любым RealFloat

Представление иррациональных чисел без потери точности

http://hackage.haskell.org/package/numbers-2009.8.9

anonymous ()
Ответ на: комментарий от MyTrooName

i^2 = 1 это двойные числа

Но того что хочет ТС сделать не выйдет. Пишет он какую-то фигню. Если дело только за корнями, то тут можно, конечно.

anonymous ()
Ответ на: комментарий от anonymous

Хотя выйдет, конечно, если сделать CAS

Какой нафиг CAS, я так понял, что ТС хочет арифметику для комплексных чисел с ленивыми корнями и упрощалкой. Не знаю как на хаскеле, а на крестах это можно за вечер сделать.

no-such-file ★★★★★ ()
Ответ на: комментарий от no-such-file

В терминологии любителей SICP это как раз CAS, так как там автор, объясняя, как реализовать рациональные числа, говорил-таки что-то про CAS :)

BattleCoder ★★★★★ ()
Ответ на: комментарий от no-such-file

Какой нафиг CAS, я так понял, что ТС хочет арифметику для комплексных чисел с ленивыми корнями и упрощалкой

Правда что ли? Ну это не очень интересно. Пусть делает что-то вроде atensor, будет больше толку.

Интересно, а как делаются такие упрощалки? Я на CL пытался делать с наскоку простым pattern matching'ом. Язык был такой:

aX - атом, lX - лист, nX - число, rX - остаток выражения. И такое правило: '(- a1 (- a1)) срабатывает на (- x (- x)), например, но не на '(- x (- y)).

Но интересно было бы описать алгебру с помощью подобного языка, а упрощалка сама бы делала что от неё требуется.

anonymous ()

Почитай, как представляются алгебраические числа в Mathematica. Они там представляются как пронумерованные корни соотв. уравнения.

anonymous ()

Нужны комплексные числа. Действительная и мнимая часть их может быть иррациональной.

если я умножаю sqrt 2 на самого себя, я получаю же 2?

не угадал

зы. поэтому сначала общие решения делают одни спецы в мат.пакетах, а потом другие спецы хардкодят частные решения на somelang.

MKuznetsov ★★★★★ ()
Ответ на: комментарий от qnikst

Crack написан на reduce, сейчас им рулит prof. Thomas Wolf и насколько я знаю его, он переписывать на haskell его не собирается, тем более это выглядело бы странным, в начале нужно было бы написать cas на haskell, а потом уже переписывать crack. Но при случае попробую у него уточнить.

cool_hedin ()
Ответ на: комментарий от cool_hedin

ну может он просто в неформальном разговоре высказался, т.к. как мне говорили, он хотел попробовать языки типа haskell. Прикольно увидеть на лоре людей знакомых с Томасом, я не знаком, но его студенты нам интегрируемые системы считали, которые, чем-нить типа maple не брались. =)

qnikst ★★★★★ ()
Последнее исправление: qnikst (всего исправлений: 1)
Ответ на: комментарий от qnikst

Я его знаю только по email, но мой научрук с ним работал в Броку, а потом и я с ними, но уже удалённо. crack, кстати, очень хорошая решалка (там хорошо продуманы ветвления, с которыми в maple очень плохо), лучше я пока не видел, жаль только падает иногда и не очень стабильна в параллельном режиме (и Томас, похоже на него забыл, а жаль, может быть в связи с этим про haskell и думал). Прикольно видеть людей на лоре, которые про reduce и crack слышали :)

cool_hedin ()
Ответ на: комментарий от BattleCoder

так мистер там имел именно «алгебраическое» умножение, насколько я понял.

да и вообще - не парься и юзай уже существующие CAS.

dikiy ★★☆☆☆ ()
Ответ на: комментарий от dikiy

неужели?

если ТС хочет возвращать (sqrt 2) как решение x^2-2=0 (а видимо он этого хочет) - то будет возвращать пару значений, при само-перемножении которых будет |2,2i|. Где-то так - он же хочет комплексную арифметику ;-)

MKuznetsov ★★★★★ ()
Ответ на: комментарий от MKuznetsov

неужели?

если ТС хочет возвращать (sqrt 2) как решение x^2-2=0 (а видимо он этого хочет) - то будет возвращать пару значений, при само-перемножении которых будет |2,2i|. Где-то так - он же хочет комплексную арифметику ;-)

насколько я понял он просто хочет возвращать корень из двух как корень из двух. представлять его в памяти можно просто как 2 в степени 1/2 :)

а два - комплексных корней у уравнения x^2=2 нет.

dikiy ★★☆☆☆ ()
Ответ на: комментарий от dikiy

а два - комплексных корней у уравнения x^2=2 нет.

Похоже что ему после приема визина начинают мерещиться.

anonymous ()
Ответ на: комментарий от dikiy

насколько я понял он просто хочет возвращать корень из двух как корень из двух. представлять его в памяти можно просто как 2 в степени 1/2 :)

а как он будет синусы и экспоненты представлять? без них с комплексными числами тяжко..

а сумма sqrt(2) sqrt(3) у него так и останется тюплом ??

а как представить root(7,pow(3,3))? показатель тоже дробный..а не дай бог он получится иррациональным

получается что не теряя точности - это почти полноценный CAS или приближать иррациональные числа рациональными дробями, совсем слегка (и в принципе контроллируемо) потеряв точность; но это переизобретение велосипеда, да и не стоит оно того..

а два - комплексных корней у уравнения x^2=2 нет.

ну ты понял..пятницо :) но всё равно их там два, и дальнейшие построения должны учитывать оба варианта.

MKuznetsov ★★★★★ ()
Ответ на: комментарий от MKuznetsov

а как он будет синусы и экспоненты представлять? без них с комплексными числами тяжко..

никак. они же не являются иррациональными числами.

а сумма sqrt(2) sqrt(3) у него так и останется тюплом ??

да.

а как представить root(7,pow(3,3))? показатель тоже дробный..а не дай бог он получится иррациональным

ну так надо следить, чтобы не получился... Ведь постановка задачи-то - работать в кольце иррациональных чисел, так?

получается что не теряя точности - это почти полноценный CAS или приближать

есессно.

dikiy ★★☆☆☆ ()

Да и не хочется зависеть от математических пакетов.

правильно. давайте делать свой велосипед.

dikiy ★★☆☆☆ ()

Вот это я понимаю, уровень ЛОРа, столько-то ответов и ни слова об алгебраических vs. трансцендентных числах. Все какие-то косинусы, экспоненты, квадратные корни. Неосиляторы, хуле.

anonymous ()
Ответ на: комментарий от anonymous

Не компилится.

Data/Number/Dif.hs:97:8:
    Could not deduce (Eq a) arising from the literal `0'
    from the context (Num a)
      bound by the instance declaration at Data/Number/Dif.hs:86:10-31
    Possible fix: add (Eq a) to the context of the instance declaration
    In the pattern: 0
    In the pattern: C 0
    In an equation for `*': (C 0) * _ = C 0
BattleCoder ★★★★★ ()

То, о чём вы говорите — это алгебраические числа. Они же — корни многочленов. Многочлен определяется набором своих коеффициентов. Поэтому можно довольно много иррациональных чисел представить как наборы рациональных коеффициентов многочленов.

dnoskov ()
Ответ на: комментарий от dnoskov

Ага. :) Я уже понял. Читайте выше. Но всё равно спасибо.

BattleCoder ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.