Inconsistent behavior between Scala tail recursion vs imperative - scala

I'm currently attempting to learn functional programming (and Scala) together. I'm porting some code from a FORTRAN routine for calculating a particular modified normalisation of the associated Legendre polynomials. My direct imperative translation of the original code is modpLgndr1 (which I have checked against the original algorithm). My initial attempt at writing the code in a functional form is in modpLgdnr2.
import math.pow, abs, sqrt, Pi
def xfact(m: Int): Double = {
if (m <= 1) 1.0
else {
if (m % 2 == 1) m.toDouble / sqrt(m.toDouble) * xfact(m - 1)
else 1.0 / sqrt(m.toDouble) * xfact(m - 1)
}
}
//this is a very un-scala function....
def modpLgndr1(l: Int, m: Int, x: Double): Double = {
assert(0 <= m && m <= l && abs(x) <= 1.0)
val dl = l.toDouble
val dm = m.toDouble
val norm = sqrt(2.0 * dl + 1.0) / sqrt(4.0 * Pi)
var pmm = norm
if (m != 0) pmm = (pow(-1, m)).toDouble * pmm * xfact(2 * m) * pow((1.0-x * x), (dm / 2.0))
if (l == m) pmm
else {
var pmmp1 = x * pmm * sqrt(2.0 * m + 1.0)
if (l == m + 1) pmmp1
else {
var pll = 0.0
var dll = 0.0
for (ll <- m + 2 to l) {
dll = ll.toDouble
pll = (x * (2.0 * dll - 1.0) * pmmp1 - sqrt(pow((dll - 1.0), 2.0) - dm * dm) * pmm) / sqrt(pow(dll, 2.0) - pow(dm, 2.0))
pmm = pmmp1
pmmp1 = pll
}
pll
}
}
}
def modpLgndr2(l: Int, m: Int, x: Double): Double = {
assert(0 <= m && m <= l && abs(x) <= 1.0)
val dl = l.toDouble
val dm = m.toDouble
val norm = sqrt(2.0 * dl + 1.0) / sqrt(4.0 * Pi)
val pmm = if (m == 0) norm else (pow(-1, m)).toDouble * norm * xfact(2 * m) * pow((1.0-x * x), (dm / 2.0))
if (l == m) pmm
else {
val pmmp1 = x * pmm * sqrt(2.0 * m + 1.0)
if (l == m + 1) pmmp1
else {
def mplacc(ll: Int, acc1: Double, acc2: Double): Double = {
val dll = ll.toDouble
val pll = (x * (2.0 * dll - 1.0) * acc2 - sqrt(pow((dll - 1.0), 2.0) - dm * dm) * acc1) / sqrt(pow(dll, 2.0) - pow(dm, 2.0))
if (ll == m + 2) pll
else mplacc(ll - 1, acc2, pll)
}
mplacc(l, pmm, pmmp1)
}
}
}
If I call the two functions I get output like this:
scala> for (i <- 0 to 10) println(modpLgndr1(10,i,0.2))
0.16685408398957746
-0.2769345073769805
-0.1575129272628402
0.2948210515201088
0.12578847877176355
-0.3292975894931367
-0.058267280378036426
0.37448134558730417
-0.08024600262585084
-0.40389602261165075
0.4424459249420354
scala> for (i <- 0 to 10) println(modpLgndr2(10,i,0.2))
0.16685408398957752
-0.2772969351441124
-0.1578618478786792
0.29654926805696474
0.1349402872678466
-0.33707342609134694
-0.06901634276825179
0.38912154672892657
-0.08024600262585084
-0.40389602261165075
0.4424459249420354
Essentially, for m = 0, l-2, l-1, l the code agrees; otherwise there is a significant discrepancy. That seems to tell me that the problem is in calling the mplacc function. To me, mplacc just looks like a recursive form of the for loop in modpLgndr1. Why am I wrong?

Related

Interest Rate Function

I found some code online regarding a finance calculator function but I'm not sure what it does, I'm still new to swift so if someone could explain the purpose of the function I would appreciate it a lot
func calculateAnnualInterestRate() -> Double {
let numberOfMonths = Double(self.NumberofPayments)
var x = 1 + (((self.MonthlyPayment * numberOfMonths/self.loan) - 1) / 12)
func F(_ x: Double) -> Double {
let F = self.loan * x * pow(1 + x, numberOfMonths) / (pow(1 + x, numberOfMonths) - 1) - self.MonthlyPayment
return F;
}
func F_Prime(_ x: Double) -> Double {
let F_Prime = self.loan * pow(x + 1, numberOfMonths - 1) * (x * pow(x + 1, numberOfMonths) + pow(x + 1, numberOfMonths) - (numberOfMonths * x) - x - 1) / pow(pow(x + 1, numberOfMonths) - 1, 2)
return F_Prime
}
while(abs(F(x)) > Double(0.000001)) {
x = x - F(x) / F_Prime(x)
}
let I = Double(12 * x * 100)
if I < 0 || I.isNaN || I.isInfinite {
self.interest = 0.0;
return self.interest
} else {
self.interest = I.roundTo2()
return self.interest
}
}
I know that the function is necessary for the calculation of interest rate but I'm not sure what the F and F_Prime

Recursive sum function, How do i limit the sum?

The goal is to code this sum into a recursive function.
Sum
I have tried so far to code it like this.
def under(u: Int): Int = {
var i1 = u/2
var i = i1+1
if ( u/2 == 1 ) then u + 1 - 2 * 1
else (u + 1 - 2 * i) + under(u-1)
}
It seems like i am running into an issue with the recursive part but i am not able to figure out what goes wrong.
In theory, under(5) should produce 10.
Your logic is wrong. It should iterate (whether through loop, recursion or collection is irrelevant) from i=1 to i=n/2. But using n and current i as they are.
(1 to (n/2)).map(i => n + 1 - 2 * i).sum
You are (more or less) running computations from i=1 to i=n (or rather n down to 1) but instead of n you use i/2 and instead of i you use i/2+1. (sum from i=1 to i=n of (n/2 + 1 - 2 * i)).
// actually what you do is more like (1 to n).toList.reverse
// rather than (1 to n)
(1 to n).map(i => i/2 + 1 - 2 * (i/2 + 1)).sum
It's a different formula. It has twice the elements to sum, and a part of each of them is changing instead of being constant while another part has a wrong value.
To implement the same logic with recursion you would have to do something like:
// as one function with default args
// tail recursive version
def under(n: Int, i: Int = 1, sum: Int = 0): Int =
if (i > n/2) sum
else under(n, i+1, sum + (n + 2 - 2 * i))
// not tail recursive
def under(n: Int, i: Int = 1): Int =
if (i > n/2) 0
else (n + 2 - 2 * i) + under(n, i + 1)
// with nested functions without default args
def under(n: Int): Int = {
// tail recursive
def helper(i: Int, sum: Int): Int =
if (i > n/2) sum
else helper(i + 1, sum + (n + 2 - 2 * i))
helper(1, 0)
}
def under(n: Int): Int = {
// not tail recursive
def helper(i: Int): Int =
if (i > n/2) 0
else (n + 2 - 2 * i) + helper(i + 1)
helper(1)
}
As a side note: there is no need to use any iteration / recursion at all. Here is an explicit formula:
def g(n: Int) = n / 2 * (n - n / 2)
that gives the same results as
def h(n: Int) = (1 to n / 2).map(i => n + 1 - 2 * i).sum
Both assume that you want floored n / 2 in the case that n is odd, i.e. both of the functions above behave the same as
def j(n: Int) = (math.ceil(n / 2.0) * math.floor(n / 2.0)).toInt
(at least until rounding errors kick in).

Tail Recursive function for the sum of fractions

I am trying to convert this recursive function into a tail recursive function
def sumOfFractions(n: Int): Double = {
require(n > 0, "Parameter n has to be greater than 0");
if (n==1)
1.0
else
1.0 / n + sumOfFractions(n - 1)
}
I thought that this solution would work but when it runs it just returns 1.0
def sumOfFractions(n:Int):Double = {
def inner(acc:Int, n:Int): Double={
if(n <= 1)1.0
else
{
inner(acc+(1/n),n-1)
}
}
inner(0,n)
}
I think this is because the accumulator is not being updated correctly but I don't understand why. The code is in Scala but an example in any language would be helpful.
You need the base case (n <= 1) to return the accumulator, not 1.0. You'll also run into problems because the accumulator is an Int instead of a Double, which means that + (1 / n) is just adding 0 (the result of dividing 1: Int by any n: Int greater than one).
You can fix this by changing acc's type and making the numerator of the reciprocal a literal double:
def sumOfFractions(n: Int):Double = {
def inner(acc: Double, n: Int): Double =
if (n <= 1) acc else inner(acc + (1.0 / n), n - 1)
inner(0, n)
}
This should work.
Correct your code
1) Return acc (accumulator) when n <= 1
2) Your acc should be Double type
3) Division should be floating point division
def sumOfFractions(n: Int): Double = {
def inner(acc: Double, n:Int): Double = if(n <= 1) acc
else inner(acc + (1.0 / n), n - 1)
inner(0,n)
}
Using foldLeft
def sumOfFractions(n: Int): Double =
(1 to n).foldLeft(0.0)((r, c) => r + (1.0 / c))

Scala Double epsilon calculation in a functional style

A suggested approach to calculate machine epsilon using Java is as follows,
private static float calculateMachineEpsilonFloat() {
float machEps = 1.0f;
do
machEps /= 2.0f;
while ((float) (1.0 + (machEps / 2.0)) != 1.0);
return machEps;
}
How to compute epsilon for scala.Double using Scala in an idiomatic / functional style from this suggested code?
Is that OK?
scala> val s: Stream[Float] = 1.0f #:: s.map(f => f / 2.0f)
s: Stream[Float] = Stream(1.0, ?)
scala> val eps = s.takeWhile(e => e + 1.0f != 1.0f).last
eps: Float = 1.1920929E-7
To get another epsilon (2^{-24}), one can use dropWhile (and, consequently, head) instead.
You can rewrite the do-while loop with recursion:
import scala.annotation.tailrec
def calculateMachineEpsilonFloat = {
#tailrec
def calc(machEps: Float): Float = {
if ((1.0 + (machEps / 2.0)).toFloat != 1.0)
calc(machEps / 2f)
else
machEps
}
calc(1f)
}

Unsure how a method works within a scala class

I'm trying to understand the add method in below class taken from book 'Programming in Scala - Second Edition'.
Is this correct :
The method 'add' takes defines an operator which of type Rational. I don't know what is occurring within the new Rational :
numer * that.denom + that.numer * denom,
denom * that.denom
How are numer & denom be assigned here ? , Why is each expression separated by a comma ?
Entire class :
class Rational(n: Int , d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d/ g
def this(n: Int) = this(n, 1)
def add(that: Rational): Rational =
new Rational(
numer * that.denom + that.numer * denom,
denom * that.denom
)
override def toString = numer +"/" + denom
private def gcd(a: Int, b: Int): Int =
if(b == 0) a else gcd(b, a % b)
}
That two expressions are the arguments to the Rational constructor, thus they will be the private vals n and d respectively. For example
class C(a: Int, b: Int)
val c1 = new C(1, 2) // here 1, 2 is like the two expressions you mention
The add method implements rational number addition:
a c a*d c*b a*d + c*b
--- + --- = ----- + ----- = -----------
b d b*d b*d b*d
where
a = numer
b = denom
c = that.numer
d = that.denom