HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Summations and products and factorials oh my

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
andsummationsfactorialsproducts

Problem

The proper title of this question should be "Summations and products, and factorials oh my!".

After getting quite a bit of useful feedback on this question from @mjolka, and a comment, I decided that there were many things to be improved.

These are the following things that I've added/changed:

  • A factorial function which uses the product function.



  • Support for getting the sum, and product of sequences with no elements.



  • Strongly typed anonymous function parameters.



Again, for those who don't know, a summation is defined as follows:


$$\sum_{n=a}^{b}f(n)$$

And a product is defined as follows:


$$\prod_{n=a}^{b}f(n)$$

I'd like to know the following things, which are more or less mostly the same as the ones in the last question:

  • Am I writing this in a proper functional way?



  • How can I reduce the repetitiveness in my code?



  • Is there a way to improve performance? It already runs pretty fast, at approximately \$0.025\$ seconds for inputs of \$10\$).



  • Anything else?



Here's the code:

let inline summation (f: (double -> double)) low high =
    match (low, high) with
    | (low, high) when low <> high ->
        { low .. high } 
        |> Seq.map f
        |> Seq.sum
    | (low, high) when low = high -> 0.0
    | _ -> -1.0

let inline product (f: (double -> double)) low high =
    match (low, high) with
    | (low, high) when low <> high ->
        { low .. high }
        |> Seq.map f
        |> Seq.fold Checked.op_Multiply 1.0
    | (low, high) when low = high -> 1.0
    | _ -> -1.0

let inline factorial n =
    product (fun x -> x) 1.0 n


Here's a few small tests to ensure that the code works:

[]
let main argv =
    System.Console.WriteLine(summation (fun x -> x) 1.0 10.0)
    System.Console.WriteLine(product (fun x -> x) 1.0 10.0)
    System.Console.WriteLine(factorial 10.0)
    0


And here's expected output of the above tests:

55
3628800
3628800

Solution

Some comments:

|> Seq.map f
    |> Seq.sum


is just

Seq.sumBy f


Otherwise, if perf really matters I would avoid using Seq, and probably combine the map and fold in the product case.

Also, rather than

match (low, high) with
| (low, high) when low <> high ->
    { low .. high } 
    |> Seq.map f
    |> Seq.sum
| (low, high) when low = high -> 0.0


I would use an if to avoid the warning about incomplete pattern match so it would become

if low=high then 0.0
else   {low .. high} |> Seq.sumBy f

Code Snippets

|> Seq.map f
    |> Seq.sum
Seq.sumBy f
match (low, high) with
| (low, high) when low <> high ->
    { low .. high } 
    |> Seq.map f
    |> Seq.sum
| (low, high) when low = high -> 0.0
if low=high then 0.0
else   {low .. high} |> Seq.sumBy f

Context

StackExchange Code Review Q#108231, answer score: 3

Revisions (0)

No revisions yet.