Rhymond/go-money

Question about the rounding for NewFromFloat

TimothyIp opened this issue · 5 comments

Love the new addition of NewFromFloat. Just wanted to get a clearer understanding of always rounding trailing decimals down when given.

 cents := money.NewFromFloat(99.999999, money.USD)
 //->  cents: 9999

Just want to know the why between getting 9999 vs 10000?

Thanks!

Hi @TimothyIp
To be honest there was not much of a discussion about this new feature. The current formula:

int64(99.9999 * 10^(fraction))

The rounding is done by casting float to integer and this is how it works in Go.
Maybe @npinochet can give you a bit more details

The rounding is done by casting float to integer and this is how it works in Go.

That's correct, I made the function thinking more about simplicity rather than usability.
Maybe we can have the discussion here, I think rounding is aceptable in this case, the formula can be adjusted for it:

factor = 10^fraction
int64((99.9999 + 0.5 / factor) * factor)

Just want to give thanks to the both of you for taking the time out of your day for answering this question of mine.

I can see the winner being simplicity here. I just went down a rabbit hole of all the different ways you can round cents (round down, round up, banker's rounding, ...etc).

I could see it just being as simple as having the consumer provide the float into NewFromFloat already rounded to their specific use case. (Which will solve my use case)

As for changing the internals of the function, that part i'm unsure of. I'm with keeping the behaviour in line with Go, since this rounding topic can get quite opinionated.

An additional function could be added that would do the explicit rounding for a given float, something like NewFromFloatRounded.

Thank you for opening this discussion :)
I agree that there are many ways to handle rounding in regards to currencies, I believe it's better to keep it simple.

There may be cases where floats like 99.999999 may appear, but that could mean that somewhere you did some float arithmetics before converting them to Money, which beats the use of this library.

If rounding is really necesary, one could always pre round the float before passing it to the function (NewFromFloat(99.999999 + 0.005))

Hopefully, this convo will help for posterity if someone needs specific rounding for a use-case and how they can achieve this with NewFromFloat. Going to close this. Thanks!