- Practice
- Functional Programming
- Introduction
- Area Under Curves and Volume of Revolving a Curve
- Discussions

# Area Under Curves and Volume of Revolving a Curve

# Area Under Curves and Volume of Revolving a Curve

mattklein999 + 1 comment I'm pretty sure the sample data is wrong.

For the first given sample, the only way to get the "correct" value of

`2435300.3`

is if you sum up all of the slices between 1.0 and 4.0, inclusive.However, that would be incorrect. It should be all of the slices between 1.0 and 3.999, inclusive, which sums to

`2428775.4`

. By including the last slice**STARTING**at 4.0, you're actually including the slice representing 4.0 to 4.001, which is clearly outside the target bounds.I'm somewhat disappointed with this "Introduction" to "Functional Programming" example, since its mostly just an exercise in calculus (but there is already a Mathematics domain here for that). This should have given us the motivation

*and*the formulas, and then we pratice implementing them in our given language.naderghanbari + 0 comments I think this is not true.

If you sum slices between

`1.0`

and`4.0`

excluding the`first`

slice you get`2435300.3`

.The problem I have with this exercise is that it doesn't precisely specify which numerical method and which convention to use but the given article (link) uses a summation from

`1`

to`n`

which means we have to exclude the first slice and include the last slice.

anandrajj + 2 comments This link has simple tutorial. This could help you to understand the problem well. http://www.intmath.com/applications-integration/4-volume-solid-revolution.php

giaym + 0 comments wouldnt have bothered otherwise, thanks!

naderghanbari + 0 comments Multiplying the

`π`

at the end makes perfect sense but for languages with a predefined template we can't do that here as the predefined function has to return the area of each slice (disk).Multiplying all terms (slices) or mutlplying at the end affects the double precision so probably better not to bother with that here, i.e. just multiply all slices by

`π`

if you are solving this with a language which doesn't come with a template (Erlang for instance).

hungryfrog + 1 comment There is something wrong with the sample output , it is not 2435300.3 but 2432036.5

naderghanbari + 0 comments Wolfram Alpha probably calcuates the exact value because this is a polynomial. It might use analytical methods or even numerical methods which are exact for polynomials (up to a certain degree). What we're asked to do here is specifically using the limit definition of integral.

The precision also matters, here we have to sum slices between 1.0 and 4.0 excluding the first slice (as in the link, i.e. summation from

`1`

to`n`

), then we get`2435300.3`

.By the way there seems to be a problem with the relative error. My Scala code passed all the tests but I couldn't make my Erlang code work after spending 1h, the results are definitely within the

`0.01`

relative margin but tests are failing.

FlavioFernandes4 + 0 comments Scala:

def f(coefficients:List[Int],powers:List[Int], x:Double):Double = coefficients.zip(powers) .foldLeft(0.0){case (acc,(c,p))=> acc + c * math.pow(x,p)} def area(coefficients:List[Int],powers:List[Int],x:Double):Double = math.Pi * math.pow(f(coefficients,powers,x),2) def summation(func:(List[Int],List[Int],Double)=>Double, upperLimit:Int, lowerLimit:Int, coefficients:List[Int], powers:List[Int]):Double = { val step = 0.001 val subIntervals= lowerLimit.toDouble to upperLimit by step subIntervals .foldLeft(0.0){case (acc,x)=> acc + func(coefficients,powers,x)*step} }

freckletonj + 2 comments Is there a cleaner way to do this in Haskell?

step = 0.001 f :: Floating a => [a] -> [a] -> a -> a f as bs x = sum [a * (x ** b) | (a, b) <- zip as bs] integral g l r as bs = sum integrals where ln = fromIntegral l rn = fromIntegral r asn = map fromIntegral as bsn = map fromIntegral bs ys = map (f asn bsn) [ln, ln + step .. rn] integrals = map g ys area = integral ((*) step) vol = integral (\x -> pi * x ** 2 * step) solve :: Int -> Int -> [Int] -> [Int] -> [Double] solve l r a b = [area l r a b, vol l r a b]

anfelor + 0 comments solve :: Int -> Int -> [Int] -> [Int] -> [Double] solve l r as bs = [integral (* step), integral (\x -> pi * x ^ 2 * step)] where step = 0.001 :: Double f :: Double -> Double f x = sum [(fromIntegral a) * (x ^^ b) | (a, b) <- zip as bs] integral :: (Double -> Double) -> Double integral g = sum $ map (g . f) [fromIntegral l, fromIntegral l + step .. fromIntegral r]

`(^^) :: (Fractional a, Integral b) => a -> b -> a`

- Use where blocks to group functions
- You pass a lot of arguments around without changing them, in a where clause you can avoid that.

Nonetheless I would consider your code to be quite good.

paulpach + 2 comments A better way would be if the integral function received the function that it is supposed to integrate. Then the integral function would work with any function.

This is my integral function:

-- integral of any arbitrary function integral f l r = sum [ (f x) * dx | x <- [l, l+dx .. r] ] where dx = 0.001

The order of the parameters is meant to support currying. For example, lets say I want a function that is the integral of x^2:

-- this creates a function that is the integral of x ** 2, f = integral (**2) -- evaluate it like this: test = f 1.0 4.0

Then you can use it to solve the problem like this:

-- Evaluates a polynomy. The parameters are ordered for currying poly :: [Double] -> [Double] -> Double -> Double poly a b x = sum [ ac * (x ** bc) | (ac, bc) <- zip a b] -- creates a function that is the rotation of an arbitrary -- function around the x axis. rotate f x = y * y * pi where y = f x area a b l r= integral (poly a b) l r volume a b l r= integral (rotate (poly a b)) l r

GeneralGrievous + 1 comment This is AMAZING. I have almost no Calculus background, therefore I wasn't able to understand this challenge. Thank you really much for helping me with this.

Let me share my translation to F#. It is correctly working.

let integral f left right = let dx = 0.001 Seq.sum [ for x in left .. dx .. right -> (f x) * dx ] let polynomialExpr aSeq bSeq x = Seq.zip aSeq bSeq |> Seq.map (fun (a, b) -> a * (x ** b)) |> Seq.sum let rotate f x = let y = f x y * y * Math.PI let area aSeq bSeq left right = integral (polynomialExpr aSeq bSeq) left right let volume aSeq bSeq left right = integral (rotate <| polynomialExpr aSeq bSeq) left right

paulpach + 0 comments I don't know F#, but it looks like very straight forward.

Your code looks nice. I am glad my explanation helped.

naderghanbari + 0 comments Oh man, I love Haskell. Wonderland of mathematics, logics, combinatory logics, and lambda calculus!

phi_ba + 0 comments Interesting example, but I spendt most of my time finding a minor error in my formula. Would have been nice if they provided the concrete formulas to use, since the links aren't that helpful if you didn't do math in some time like me.

ckutlu + 0 comments The lambda pattern

`(\[a, b, [l, r]] -> solve l r a b)`

in the given IO code segment fails for test cases [2,3,4] due to them having extra unnecessary newline characters. Either the test cases need to be fixed or the pattern in the default IO code needs to be changed as the problem gives no hint at this kind of corner case and a perfectly working code fails at submission.A simple fix for the lambda pattern is :

(\(a:b:[l, r]:_) -> solve l r a b)

imvladikon + 3 comments O_o, I misunderstood and... calculated the integral by analytical integration of the polynomial.

rablanken13 + 1 comment Awesome =D. You should share your code for the shiggles.

Seamas + 0 comments {-# LANGUAGE ConstraintKinds, DeriveFunctor #-} import Text.Printf (printf) import Data.Foldable (fold) import Data.Bifunctor (bimap) import Data.Monoid ((<>)) type PolynomialAble pow num = (Integral pow, Floating num) data Monomial pow = Ln | ToThe pow deriving (Functor, Eq, Show) newtype Polynomial pow num = P { getTerms :: [(Monomial pow, num)] } deriving (Eq, Show) sqrPoly :: PolynomialAble pow num => Polynomial pow num -> Polynomial pow num sqrPoly (P p) = P $ concatMap (\(ToThe k, v) -> bimap (fmap (+ k)) (* v) `map` p) p toFn :: PolynomialAble pow num => Polynomial pow num -> (num -> num) toFn = foldr (\(n, c) fn -> \y -> let f = case n of { ToThe n' -> (^^ n'); Ln -> log } in fn y + c * f y) (const 0) . getTerms solve :: Double -> Double -> Polynomial Int Double -> (Double, Double) solve l r p = (area, volume) where area = integrate p l r volume = pi * integrate (sqrPoly p) l r main :: IO () main = getContents >>= putStrLn . uncurry (cojoin $ printf "%.1f\n") . (\(a:b:(l:r:_):_) -> solve l r . P $ zip (map (ToThe . floor) b) a) . map (map read . words) . lines where cojoin f = \x x' -> f x <> f x' integrate :: PolynomialAble pow num => Polynomial pow num -> num -> num -> num integrate coefs lbound rbound = capF rbound - capF lbound where capF = toFn $ reversePowerRule coefs reversePowerRule :: PolynomialAble pow num => Polynomial pow num -> Polynomial pow num reversePowerRule = P . map (uncurry aux) . getTerms aux (ToThe idx) c | idx == -1 = (Ln,c) | otherwise = let idx' = idx + 1 in (ToThe idx', c / fromIntegral idx')

Could be much prettier

fheil0815 + 1 comment wait, i did the same. getting runtime errors for 2-5 though...

solvearea :: Double -> Double -> [Double] -> [Int] -> Double solvearea l r [] [] = 0 solvearea l r (a:aa) (b:bb) | (b==(-1)) = a*((log r) - (log l)) + (solvearea l r aa bb) | otherwise = (a*((r^(b+1))-(l^(b+1))))/ (b+1) + (solvearea l r aa bb) solve :: Double -> Double -> [Double] -> [Int] -> [Double] solve l r a b =[(solvearea l r a b),pi*(solvearea l r ([(x*y)| x<-a,y<-a]) ([(x+y)| x<-b,y<-b]) )]

sbmassey + 1 comment 2-5 have negative exponents, so ^ won't work

jkirkham1 + 0 comments Thanks. This comment was very helpful. I'm just learning Haskell and didn't realise the

`^`

operator wouldn't work with negative exponents. This is very simple to fix:`exp $ log x * y`

works for all of the test cases.

aubee_xc + 0 comments I think the one designed the whole "Functional Programming" section get most inspiration and ideas from SICP, because most questions have corresponding chapters in SICP giving details of techniques and ideas.

blubberdiblub + 3 comments That's how I did it in Racket:

#lang racket (define (integrate-numerically f l r step) (let ([width (exact->inexact (- r l))]) (let ([nsteps (exact-round (/ width step))]) (let ([step (/ width nsteps)]) (* step (let iter ([accu 0] [i 1]) (if (i . > . nsteps) accu (iter (+ accu (f (+ l (* step i)))) (add1 i))))))))) (define (f a b x) (let iter ([accu 0] [a a] [b b]) (if (empty? a) accu (iter (+ accu (* (first a) (expt x (first b)))) (rest a) (rest b))))) (define (circle-area x) (* pi (sqr x))) (define a (sequence->list (with-input-from-string (read-line) in-port))) (define b (sequence->list (with-input-from-string (read-line) in-port))) (define l (read)) (define r (read)) (define f-parametrized (curry f a b)) (define f-revolution (compose circle-area f-parametrized)) (println (integrate-numerically f-parametrized l r 0.001)) (println (integrate-numerically f-revolution l r 0.001))

I'm open for suggestions, as I'm a newbie Racketeer.

meriororen + 0 comments I think you could also use let* instead of nesting multiple let's there.

prof_israel + 0 comments [deleted]prof_israel + 0 comments [deleted]

Sort 64 Discussions, By:

Please Login in order to post a comment