Adding a series of floats

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?

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 :slight_smile:

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 :slight_smile:

2 Likes

One trick, for better results sort list of floats to have smallest one summed up first. This will stabilise summing.

1 Like

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

Absolute

1 Like