I'm learning F#. The code below gets a number e.g. 100 and list of factors and should divide that number by the factors without any rest. (There is an actual code I've got in C#, but this is F# port).
I especially didn't liked equalsDifference function.. any better solution?
namespace RozbijaczApp module Rozbijacz = let precision = 2 let minUnit = 1m / (pown 10m precision) let round x = System.Math.Round(decimal x, precision, System.MidpointRounding.AwayFromZero) let mainMapper factor factorSum x = round (x * factor / factorSum) let equalsDifference minUnit (difference: decimal) (l: decimal list) = let listSize = List.length l let mutable acc = difference [for i in [0..listSize-1] do let element = l |> List.item i if acc <> 0m then if difference < 0m then if element >= minUnit then acc <- acc + minUnit yield element - minUnit else yield element else acc <- acc - minUnit yield element + minUnit else yield element ] let divider (number:decimal) factors = let factorsSum = factors |> List.sum let result = factors |> List.map (fun x -> mainMapper number factorsSum x) let controlSum = result |> List.sum let difference = number - controlSum printfn "Difference %O" difference // add or substract diffenernce by minUnit for results let fixResult = equalsDifference minUnit difference result let finalControlSum = fixResult |> List.sum let finalDifference = number - finalControlSum printfn "Final difference %O should by zero"finalDifference fixResult
let factors = [0.2m;0.3m;0.4m] let results = Rozbijacz.divider 100m factors printfn "Result: %A" results
ok, as you suggested map is better:
let equalsDifference minUnit (difference: decimal) (l: decimal list) = let listSize = List.length l let mutable acc = difference let resp = l |> List.map (fun element -> ( if acc <> 0m then if difference < 0m then if element >= minUnit then acc <- acc + minUnit element - minUnit else element else acc <- acc - minUnit element + minUnit else element ) ) resp
But is this enough? Any F# magic?