I found out this snippet of code which works, but I do not understand why it does. It converts an Int to its representation in binary.
repBinario::Int -> Int
repBinario 0 = 0
repBinario x = 10 * repBinario (x `div` 2) + x `mod` 2
I know what div and mod do. However, how does it place each number that comes from mod together?
In short, it multiplies the accumulated result by 10 on each iteration.
To get a clearer understanding of what's going on we can divide your function into two simpler ones. The first one will convert an integer into a list of binary digits. The other will then do exactly the thing that bothers you: concat a list of binary digits into an integer.
extractBinDigits :: Int -> [Int]
extractBinDigits =
unfoldr (\x -> if x == 0 then Nothing else Just (mod x 2, div x 2))
concatDigits :: [Int] -> Int
concatDigits =
foldr (\a b -> a + b * 10) 0
As you see we simply fold the list multiplying the accumulator by 10 on each step and adding each digit to it.
Then your original function becomes just this:
repBinario :: Int -> Int
repBinario =
concatDigits . extractBinDigits
Division now lets us inspect and reuse the finer pieces of our program providing us with greater flexibility. E.g., by adding another simple function you can now convert the integer into a string in one go:
showDigits :: [Int] -> String
showDigits =
reverse . map (chr . (+ 48))
repStringyBinario :: Int -> String
repStringyBinario =
showDigits . extractBinDigits
Let’s go through an example, then:
repBinario 5
Substitute definition of repBinario 5:
10 * repBinario (5 `div` 2) + 5 `mod` 2
Reduce div and mod:
10 * repBinario 2 + 1
^
Here we have produced our first digit, marked with ^.
Substitute definition of repBinario 2:
10 * (10 * repBinario (2 `div` 2) + 2 `mod` 2) + 1
^
Reduce div and mod:
10 * (10 * repBinario 1 + 0) + 1
^ ^
Substitute definition of repBinario 1:
10 * (10 * (10 * repBinario (1 `div` 2) + 1 `mod` 2) + 0) + 1
^ ^
Reduce div and mod:
10 * (10 * (10 * repBinario 0 + 1) + 0) + 1
^ ^ ^
Substitute definition of repBinario 0:
10 * (10 * (10 * 0 + 1) + 0) + 1
^ ^ ^
Reduce:
101
At each step, (`mod` 2) gets the least significant binary digit, and (`div` 2) shifts the number rightward, discarding the digit and passing the rest of the number recursively to divBinario. At the end, we do the opposite process: (+ d) adds the current digit to the result, and (* 10) shifts the number leftward so we can add more digits.
What you get is a decimal number that looks identical to the binary representation of the original input.
If you remove the multiplication by 10, you get popCount, a function that gives you the population count of a number—the number of 1 bits in its binary representation:
popCount 0 = 0
popCount x = popCount (x `div` 2) + x `mod` 2
popCount 5 == 2
I think it would be best to calculate this function for a small value by hand - this is possible since this is a pure function therefore you can replace left hand side with its definition (i.e. right hand side) - the fancy computer science word for this feature is "referential transparency".
repBinario 24 = 10 * repBinario (24 `div` 2) + 24 `mod` 2
= 10 * repBinario 12 + 0
= 10 * (10 * repBinario (12 `div` 2) + 12 `mod` 2)
= 100 * repBinario 6 + 0
= 100 * (10 * repBinario (6 `div` 2) + 6 `mod` 2)
= 1000 * repBinario 3 + 0
= 1000 * (10 * repBinario (3 `div` 2) + 3 `mod` 2)
= 10000 * repBinario 1 + 1000 * 1
= 10000 (10 * repBinario (1 `div` 2) + 1 `mod` 2) + 1000
= 10000 (10 * repBinario 0 + 1) + 1000
= 10000 (10 * 0 + 1) + 1000
= 10000 * 1 + 1000
= 11000
in those steps I just evaluated the function by its definition and used the fact that integer-addition/multiplication obey the law of distribution.
Related
The number π can be calculated with the following infinite series sum:
I want to define a Haskell function roughlyPI that, given a natural number k, calculates the series sum from 0 to the k value.
Example: roughlyPi 1000 (or whatever) => 3.1415926535897922
What I did was this (in VS Code):
roughlyPI :: Double -> Double
roughlyPI 0 = 2
roughlyPI n = e1/e2 + (roughlyPI (n-1))
where
e1 = 2**(n+1)*(factorial n)**2
e2 = factorial (2*n +1)
factorial 0 = 1
factorial n = n * factorial (n-1)
but it doesn't really work....
*Main> roughlyPI 100
NaN
I don't know what's wrong. I'm new to Haskell, by the way.
All I really want is to be able to type in a number that will give me PI at the end. It can't be that hard...
As mentioned in the comments, we need to avoid large divisions and instead intersperse smaller divisions within the factorials. We use Double for representing PI but even Double has its limits. For instance 1 / 0 == Infinity and (1 / 0) / (1 / 0) == Infinity / Infinity == NaN.
Luckily, we can use algebra to simplify the formula and hopefully delay the blowup of our Doubles. By dividing within our factorial the numbers don't grow too unwieldy too quickly.
This solution will calculate roughlyPI 1000, but it fails on 1023 with NaN because 2 ^ 1024 :: Double == Infinity. Note how each iteration of fac has a division as well as a multiplication to help keep the numbers from blowing up. If you are trying to approximate PI with a computer, I believe there are better algorithms, but I tried to keep it as conceptually close to your attempt as possible.
roughlyPI :: Integer -> Double
roughlyPI 0 = 2
roughlyPI k = e + roughlyPI (k - 1)
where
k' = fromIntegral k
e = 2 ** (k' + 1) * fac k / (2 * k' + 1)
where
fac 1 = 1 / (k' + 1)
fac p = (fromIntegral p / (k' + fromIntegral p)) * fac (p - 1)
We can do better than having a blowup of Double after 1000 by doing computations with Rationals then converting to Double with realToFrac (credit to #leftaroundabout):
roughlyPI' :: Integer -> Double
roughlyPI' = realToFrac . go
where
go 0 = 2
go k = e + go (k - 1)
where
e = 2 ^ (k + 1) * fac k / (2 * fromIntegral k + 1)
where
fac 1 = 1 % (k + 1)
fac p = (p % (k + p)) * fac (p - 1)
For further reference see Wikipedia page on approximations of PI
P.S. Sorry for the bulky equations, stackoverflow does not support LaTex
First note that your code actually works:
*Main> roughlyPI 91
3.1415926535897922
The problem, as was already said, is that when you try to make the approximation better, the factorial terms become too big to be representable in double-precision floats. The simplest – albeit somewhat brute-force – way to fix that is to do all the computation in rational arithmetic instead. Because numerical operations in Haskell are polymorphic, this works with almost the same code as you have, only the ** operator can't be used since that allows fractional exponents (which are in general irrational). Instead, you should use integer exponents, which is anyway the conceptually right thing. That requires a few fromIntegral:
roughlyPI :: Integer -> Rational
roughlyPI 0 = 2
roughlyPI n = e1/e2 + (roughlyPI (n-1))
where
e1 = 2^(n+1)*fromIntegral (factorial n^2)
e2 = fromIntegral . factorial $ 2*n + 1
factorial 0 = 1
factorial n = n * factorial (n-1)
This now works also for much higher degrees of approximation, although it takes a long time to carry around the giant fractions involved:
*Main> realToFrac $ roughlyPI 1000
3.141592653589793
The way to go in such cases is to calculate the ratio of consecutive terms and calculate the terms by rolling multiplications of the ratios:
-- 1. -------------
pi1 n = Sum { k = 0 .. n } T(k)
where
T(k) = 2^(k+1)(k!)^2 / (2k+1)!
-- 2. -------------
ts2 = [ 2^(k+1)*(k!)^2 / (2k+1)! | k <- [0..] ]
pis2 = scanl1 (+) ts2
pi2 n = pis2 !! n
-- 3. -------------
T(k) = 2^(k+1)(k!)^2 / (2k+1)!
T(k+1) = 2^(k+2)((k+1)!)^2 / (2(k+1)+1)!
= T(k) 2 (k+1)^2 / (2k+2) (2k+3)
= T(k) (k+1)^2 / ( k+1) (2k+3)
= T(k) (k+1) / (k+1 + k+2)
= T(k) / (1 + (k+2)/(k+1))
= T(k) / (2 + 1 /(k+1))
-- 4. -------------
ts4 = scanl (/) 2 [ 2 + 1/(k+1) | k <- [0..]] :: [Double]
pis4 = scanl1 (+) ts4
pi4 n = pis4 !! n
This way we share and reuse the calculations as much as possible. This leads to the most efficient code, hopefully leading to the smallest cumulative numerical error. The formula also turned out to be exceptionally simple, and could even be simplified further as ts5 = scanl (/) 2 [ 2 + recip k | k <- [1..]].
Trying it out:
> pis2 = scanl1 (+) $ [ fromIntegral (2^(k+1))*fromIntegral (product[1..k])^2 /
fromIntegral (product[1..(2*k+1)]) | k <- [0..] ] :: [Double]
> take 8 $ drop 30 pis2
[3.1415926533011587,3.141592653447635,3.141592653519746,3.1415926535552634,
3.141592653572765,3.1415926535813923,3.141592653585647,3.141592653587746]
> take 8 $ drop 90 pis2
[3.1415926535897922,3.1415926535897922,NaN,NaN,NaN,NaN,NaN,NaN]
> take 8 $ drop 30 pis4
[3.1415926533011587,3.141592653447635,3.141592653519746,3.1415926535552634,
3.141592653572765,3.1415926535813923,3.141592653585647,3.141592653587746]
> take 8 $ drop 90 pis4
[3.1415926535897922,3.1415926535897922,3.1415926535897922,3.1415926535897922,
3.1415926535897922,3.1415926535897922,3.1415926535897922,3.1415926535897922]
> pis4 !! 1000
3.1415926535897922
I am trying to define a function that computes for any positive integer the square of its factorial
(I am a beginner in Haskell any tips or help is appreciated)
I have tried a couple different ways one i believe to work and one definition i don't understand why it doesn't work
Function i believe works:
squarefact:: Int -> Int
squarefact 0 = 1
squarefact n = n * n * squarefact(n-1)
Function I don't understand why it doesn't work:
squarefact:: Int -> Int
squarefact 0 = 1
squarefact n = (n * squarefact(n-1) ) * (n * squarefact(n-1) )
An explanation and walk through of the dunctions defined would help me understand them better thanks.
The equation
squarefact n = (n * squarefact(n-1) ) * (n * squarefact(n-1) )
could be rewritten in mathematical notation as
(n!)^2 = n * ((n-1)!)^2 * n * ((n-1)!)^2
but this identity is incorrect. The right hand side includes factors 1,2,....,n-1 four times instead of only two, as in the left hand side.
By comparison,
squarefact n = n * n * squarefact(n-1)
is correct, since on both sides all the factors occur exactly twice.
A factorial function can be defined in Haskell as
factorial n = product [1..n]
(where product is a function that calculates the product of all the numbers in a given list.)
Hence,
squarefact n = square (factorial n) =
= square (product [1..n])
= product [1..n] * product [1..n]
= 1 * 2 * 3 * ... * (n-1) * n *
1 * 2 * 3 * ... * (n-1) * n
= product [1..(n-1)] * n * product [1..(n-1)] * n
= n * n * square (product [1..(n-1)])
= n * n * squarefact (n-1)
The equality re-writes break down for n=0 ( squarefact 0 /= 0 * 0 * squarefact (-1) ), so it must be handled as a special case.
Implement a function that calculates the value of e ^ x, x is a parameter of the function, an integer.
To do this, use the Taylor series expansion to calculate the potency of e.
The function will receives as a parameter, in addition to the exponent x, the number of terms of the series, which will operate as a maximum value of n.
For the resolution of this function, recursion must be used.
I made this:
factorial 0 = 1
factorial n = n * factorial (n-1)
consigna3::Int->Int->Float
consigna3 _ 0 = 1
consigna3 x n = (fromIntegral(x^n) / fromIntegral(factorial n)) + consigna3 x (n-1)
But some results are wrong, this is what I expected:
Ejemplo 1: Main> funcion3 1 1
2.0
Ejemplo 2: Main> funcion3 1 10
2.718282
Ejemplo 3: Main> funcion3 2 10
7.388997
Ejemplo 4: Main> funcion3 10 20
21991.48
Ejemplo 5: Main> funcion3 10 30
22026.46
Ejemplo 6: Main> funcion3 0 30
1.0
The results (10 20) and (10 30) do not match what the function I did returns.
What I am doing wrong? Thanks and sorry for my English.
You are using Int for calculations that will overflow an Int. Instead, convert to Float right away, and then using Float for everything. So:
consigna3 x n = ((fromIntegral x)^n / factorial (fromIntegral n)) + consigna3 x (n-1)
There are two critical changes from Int to Float here: first, you do x^n where x :: Int, but I do fromIntegral x^n where fromIntegral x :: Float; second, you do factorial n where n :: Int, but I do factorial (fromIntegral n) where fromIntegral n :: Float.
In GHCI, I get these results:
div (-7) ( 2) = -4
div ( 7) (-2) = -4
div (-7) (-2) = 3
mod ( 7) ( 2) = 1
mod ( 7) (-2) = -1
mod (-7) ( 2) = 1
mod (-7) (-2) = -1
and div 4 (-3) is -2, and mod 4 (-3) is -2.
I can't understand how to get those results. Is there some laws or rules?
And what are right calculation steps ?
Usually it a good idea to first look at the documentation. For the mod function, we see:
mod :: a -> a -> a
integer modulus, satisfying
(x `div` y)*y + (x `mod` y) == x
So x `mod` y is calculated as:
mod x y = x - y * (div x y) -- logically equivalent definition
And:
div :: a -> a -> a
integer division truncated toward negative infinity.
So in case the division is -3.5, the div will return -4.
So:
mod 7 2 = 7 - 2*(div 7 2) = 7 - 2 * 3 = 7 - 6 = 1
mod 7 (-2) = 7 - (-2)*(div 7 (-2)) = 7 - (-2) * (-4) = 7 - 8 = -1
mod (-7) 2 = (-7) - 2 * (div (-7) 2) = (-7) - 2 * (-4) = (-7) + 8 = 1
mod (-7) (-2) = (-7) - (-2) * (div (-7) (-2)) = -7 - (-2) * 3 = -7 + 6 = -1
I'm reading the Learn you some Haskell for the Greater Good book, as I was playing around with recursion in Haskell I implemented the fibonacci function, the recursive version is simple, probably can be improved:
-- recursive fibonacci numbers
rfib :: Int -> Int
rfib 0 = 0
rfib 1 = 1
rfib n = rfib (n-1) + rfib(n-2)
As I was googling to learn more I stumbled upon this article:
http://java.dzone.com/articles/what-fibonacci-taught-me-about
The author shows the fibonacci formula:
I decided to implement it in Haskell using rational numbers to avoid floating point imprecisions. My implementation looks like this:
fibMultiplier = (toRational 1) / (toRational (sqrt 5))
firstFibTerm n = (((toRational 1) + (toRational (sqrt 5))) / toRational 2) ^ n
secondFibTerm n = (((toRational 1) - (toRational (sqrt 5))) / toRational 2) ^ n
fib :: Int -> Int
fib n = truncate (fromRational (fibMultiplier * firstFibTerm n) - (fibMultiplier * secondFibTerm n))
As a beginner I am sure that the code above can be drastically improved, can you point me what can be improved or some mistakes I've made?
I apreciate the help.
UPDATE
So, after playing around with the suggestions, I found that using Data.Real.Constructible is fast and precise, with no rounding errors. My final implementation is:
fib :: Int -> Construct
fib n = ( ( (1 / (sqrt 5)) * ( (( 1 + (sqrt 5) ) / 2) ^ n ) ) -
( (1 / (sqrt 5)) * ( (( 1 - (sqrt 5) ) / 2) ^ n ) ) )::Construct
I also implemented a function that returns a list of the n fibonacci numbers:
fibList :: Int -> [Construct]
fibList n = [fib(x) | x <- [0..n]]
Using this function we can compare the results of the different implementations:
-- recursive fibonacci numbers
rfib :: Int -> Int
rfib 0 = 0
rfib 1 = 1
rfib n = rfib (n-1) + rfib(n-2)
-- recursive fibonacci sequence
rfibList :: Int -> [Int]
rfibList n = [rfib(x) | x <- [0..n]]
-- rfibList 20 returns: [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765]
-----------------------------------
-- fibonacci number using Double and truncate
doubleFib :: Integer -> Integer
doubleFib n = truncate ( ( (1 / (sqrt 5)) * ( (( 1 + (sqrt 5) ) / 2) ^ n ) ) -
( (1 / (sqrt 5)) * ( (( 1 - (sqrt 5) ) / 2) ^ n ) ) )
-- fibonacci list using Double and truncate
doubleFibList :: Integer -> [Integer]
doubleFibList n = [doubleFib(x) | x <- [0..n]]
-- doubleFibList 20 returns: [0,1,0,2,3,5,8,13,21,34,55,89,143,232,377,610,986,1597,2584,4181,6764]
-----------------------------------
-- fibonacci number using Construct
constructFib :: Int -> Construct
constructFib n = ( ( (1 / (sqrt 5)) * ( (( 1 + (sqrt 5) ) / 2) ^ n ) ) -
( (1 / (sqrt 5)) * ( (( 1 - (sqrt 5) ) / 2) ^ n ) ) )::Construct
-- fibonacci list using construct
constructFibList :: Int -> [Construct]
constructFibList n = [constructFib(x) | x <- [0..n]]
-- constructFibList 20 returns: [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765]
Notice that we get a rounding error on the doubleFibList, the 16th number should be 987 but we get 986. The recursive implementation is slow, the Double implementation is imprecise, but using Construct we can get a fast and precise fibonacci sequence, much better than my old implementation using toRational.
(You can't use your sqrt version, use Data.Real.Constructible instead)
import Data.Real.Constructible
fib :: Int -> Construct
fib n = (((1+sqrt(5))/2)^n - ((1-sqrt(5))/2)^n)/sqrt(5)