Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NewFromFloat shifts the value of the amount in certain currencies. #124

Open
kotaroyamazaki opened this issue Nov 8, 2022 · 4 comments
Open

Comments

@kotaroyamazaki
Copy link

e,g)
Display amount of SDG

input 136.98
expected: $136.98
actual: $136.97

seeing is believing ↓
https://go.dev/play/p/l4imxLkT70u

@kylebragger
Copy link

I am having the same issue:

origPrice := float64(18.99)
cents := money.NewFromFloat(origPrice, money.USD)
int(cents.Amount()) => this is 1898

@SkipHendriks
Copy link

SkipHendriks commented Mar 7, 2023

Floats are the issue:

@kotaroyamazaki https://go.dev/play/p/oNzxYVoZK4K

@kylebragger https://go.dev/play/p/j9lwBeNUllb

The idea of this package is to use the smallest unit of the currency, so cent in case of dollars and use that as int. So 136.98 becomes 13698.

This is know as Fowler's Money pattern which is what this package implements. It is designed to overcome floating point issues like the one you described.

@egtann
Copy link

egtann commented Jan 29, 2024

I was starting with a string in the form of a float, so my solution was to strip non-numeric characters with regex, parse the remaining string as an int, and pass that int to the money package, like this:

nonNumeric := regexp.MustCompile(`\D*`)
amountStr := "18.99"
numStr := nonNumeric.ReplaceAllString(amountStr, "")
num, _ := strconv.ParseInt(numStr, 10, 32) // handle err
val := money.New(num, currency)

@vaihtovirta
Copy link

We encountered the same issue, and decided to switch to https://github.com/shopspring/decimal.

	amount := 73708.43

	// money
	moneyAmount := money.NewFromFloat(amount, "EUR")
	fmt.Println("money cents", moneyAmount.Amount()) // decimal 7370843

	// decimal
	decimalAccount := decimal.NewFromFloat(amount)
	decimalSubunits := decimal.New(100, 0)
	decimalAmountCents := decimalAccount.Mul(decimalSubunits)
	fmt.Println("decimal cents", decimalAmountCents.IntPart()) // money 7370842

@SkipHendriks @Rhymond Hey, just a thought, if floats are causing trouble, why was the NewFromFloat method included in the library to begin with? Maybe it's worth mentioning in the README so other people don't stumble over this again?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants