LINUX.ORG.RU

[haskell] Покритикуйте программу численного интегрирования

 


0

0

Метод (правых) прямоугольников:

equidistantPoints a b n = [a, a + h .. b]
    where h = (b - a) / n

squareIntegrateR f a b n =
    (sum (map f (tail (equidistantPoints a b n)))) * h
    where h = (b - a) / n

main = do
    print ( squareIntegrateR (\x -> cos x) 0 (pi/2) 100000 )
    print ( squareIntegrateR (\x -> x) 0 (pi/2) 10000 )
    print ( x*x/2 ) where x = pi/2

Проверка:

# ghc -o int int.hs && ./int
0.999992145996432
1.2338239201912735
1.2337005501361697

☆☆

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

Финал

Прямоугольники, трапеции, Симпсон.

-- Правые прямоугольники
squareIntegrateR f a b n =
    (sum (map f [a + h, a + 2*h .. b])) * h
    where h = (b - a) / n

-- Левые прямоугольники
squareIntegrateL f a b n =
    (sum (map f [a, a + h .. b - h])) * h
    where h = (b - a) / n

-- Средние прямоугольники
squareIntegrate f a b n =
    (sum (map f [a + h/2, a + h/2 + h .. b - h/2])) * h
    where h = (b - a) / n

-- Трапеции
trapezeIntegrate f a b n =
    ((sum (map f [a + h, a + 2*h .. b - h])) + t) * h
    where
        t = (f a + f b)/2
        h = (b - a) / n

-- Симпсон
simpsonIntegrate f a b n =
    (s + s4 + s2) * h / 6
    where
        s  = f a + f b
        s4 = 4 * (sum . map f $ [a + h/2, a + h/2 + h .. b - h/2])
        s2 = 2 * (sum . map f $ [a + h,   a + 2*h     .. b - h])
        h  = (b - a) / n

-- Функции для проверки
testcases = [
--             функция      a   b      n    ответ
    ("x",     \x -> x,      0, 1,    100,   1/2),
    ("x^2",   \x -> x^2,    1, 2,    100,   7/3),
    ("cos x", \x -> cos(x), 0, pi/2, 100,   1.0),
    ("sin x", \x -> sin(x), 0, pi/2, 100,   1.0),
    ("exp x", \x -> exp(x), 0, 1,    100,   exp(1) - 1),
    ("x*sin x", \x -> x*sin(x), 0, 2*pi, 100, -6.283185306023805)
          ]

-- Процедура проверки
maketest [] = do return ()
maketest ((name, f, a, b, n, r):ts) = do
    putStrLn ""
    putStrLn $ "-- " ++ name ++ " от " ++ show a ++ " до "
            ++ show b ++ ", n = " ++ show n ++ ", равно " ++ show r
    putStrLn $ "Правые  прямоугольники: " ++ show (squareIntegrateR f a b n)
    putStrLn $ "Левые   прямоугольники: " ++ show (squareIntegrateL f a b n)
    putStrLn $ "Средние прямоугольники: " ++ show (squareIntegrate  f a b n)
    putStrLn $ "Формула трапеций:       " ++ show (squareIntegrateR f a b n)
    putStrLn $ "Формула Симпсона:       " ++ show (simpsonIntegrate f a b n)
    maketest ts


main = do
    maketest testcases

Вывод:

# ghc -o int int.hs && ./int

-- x от 0.0 до 1.0, n = 100.0, равно 0.5
Правые  прямоугольники: 0.5050000000000003
Левые   прямоугольники: 0.4950000000000003
Средние прямоугольники: 0.5000000000000003
Формула трапеций:       0.5050000000000003
Формула Симпсона:       0.5000000000000003

-- x^2 от 1.0 до 2.0, n = 100.0, равно 2.3333333333333335
Правые  прямоугольники: 2.348350000000002
Левые   прямоугольники: 2.318350000000002
Средние прямоугольники: 2.3333250000000008
Формула трапеций:       2.348350000000002
Формула Симпсона:       2.3333333333333344

-- cos x от 0.0 до 1.5707963267948966, n = 100.0, равно 1.0
Правые  прямоугольники: 0.9921254566056366
Левые   прямоугольники: 1.0078334198735852
Средние прямоугольники: 1.0000102809119091
Формула трапеций:       0.9921254566056366
Формула Симпсона:       1.000000000021143

-- sin x от 0.0 до 1.5707963267948966, n = 100.0, равно 1.0
Правые  прямоугольники: 1.0078334198735803
Левые   прямоугольники: 0.9921254566056313
Средние прямоугольники: 1.0000102809119036
Формула трапеций:       1.0078334198735803
Формула Симпсона:       1.0000000000211375

-- exp x от 0.0 до 1.0, n = 100.0, равно 1.718281828459045
Правые  прямоугольники: 1.7268875565927133
Левые   прямоугольники: 1.7097047383081228
Средние прямоугольники: 1.718274668972309
Формула трапеций:       1.7268875565927133
Формула Симпсона:       1.7182818284650117

-- x*sin x от 0.0 до 6.283185307179586, n = 100.0, равно -6.283185306023805
Правые  прямоугольники: -6.281118086046078
Левые   прямоугольники: -6.281118086046067
Средние прямоугольники: -6.284218968755679
Формула трапеций:       -6.281118086046078
Формула Симпсона:       -6.283185341185809

ip1981 ☆☆
() автор топика
Ответ на: комментарий от qnikst

> Что значит допустим? В приведённых ссылках есть результат и вывод того, что априорное значение погрешности вычисления методом ср. прямоугольников в 2 раза меньше, чем трапеции (на равномерном разбиении). Если есть пренетзии к доказательтву можете писать их и что-либо выводить.

«допустим» в данном случае эквивалент «напрмер»

f(x)=x*x показывает, что оценка неулучшаема, и при должном знании предмета ты бы привел именно ее и закончил бы спор сразу

при любом n там будет погрешность у трапеций в два раза хуже средних прямоугольников

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

бррр, у меня не было желания приводить функцию пример. я больше доверяю выводу оценок, что и привёл.

в общем уже об одном и том же говорим.

qnikst ★★★★★
()

А может, не изобретать велосипеды и использовать математические библиотеки? Например, GSL???

Eddy_Em ☆☆☆☆☆
()
Ответ на: Финал от ip1981
-- Симпсон 
simpsonIntegrate f a b n = 
    (s + s4 + s2) * h / 6 
    where 
        s  = f a + f b 
        s4 = 4 * (sum . map f $ [a + h/2, a + h/2 + h .. b - h/2]) 
        s2 = 2 * (sum . map f $ [a + h,   a + 2*h     .. b - h]) 
        h  = (b - a) / n 

Ну вот, ты Симпсону сетку в два раза более плотную сделал. Хотя он и так уделал бы всех думаю.

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

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

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