valuations
is a list of maps containing prices in USD as floats.
Here’s what we’ve whipped up to calculate the total sum of all records in valuations
-
def normalize(float), do: trunc(float * :math.pow(10, 2))
def grand_total, do: Enum.sum(Enum.map(valuations, &normalize(&1.value_USD))) / 100
Surely there has to be a more elegant way to accomplish this. What would you suggest?
kip
November 7, 2020, 7:17am
2
If the values are floats then I would have expected the following to work:
Enum.reduce(maps, 0, &(&1.value_USD + &2))
But your code suggests that the data are not actually floats but may integers as cents? In which case maybe:
Enum.reduce(maps, 0, &(&1.value_USD + &2)) |> div(100)
Although that will truncate to dollars. The use of :math.pow(10, 2)
would be easier to understand as just 100
I think.
1 Like
That did the trick! Thanks so much
The Elixir way to write this would be to use pipes.
valuations
|> Enum.map(&trunc(&1.value_USD * 100))
|> Enum.sum()
|> Kernel./(100)
There might be no need for a normalize function, when You could use trunc directly.
But as mentionned by @kip , when You have a collection as input, and a single element as output, Enum.reduce() is your best friend
2 Likes
One trick, for better results sort list of floats to have smallest one summed up first. This will stabilise summing.
1 Like
NobbZ
November 7, 2020, 9:46am
6
The smallest or those with the smallest absolute value?
You shouldn’t do monetary calculations in floats, as floats are imprecise by design, the money market doesn’t like such imprecisnesses, as those can make money disappear or appear from/to thin air…
2 Likes