Go should have a primitive decimal type


(Ali Koyuncu) #21

If it is a cent why not 19.25 ? If the API has documentation and says it will return the money in cents, there shouldn’t be any problem.

From stripe API doc:

All API requests expect amounts to be provided in a currency’s smallest unit. For example, to charge $10 USD, provide an amount value of 1000 (i.e, 1000 cents).


(Ivan Matmati) #22

Hi,

If you see this kind of message in your bank application run away. A payment message without currency ? Is it only possible ? :slight_smile:


(Phillip) #23

Exactly. There shouldn’t be any problem. However, this tactic has led to problems because it means $19.25 in some APIs and $1925 in others. All software development everywhere would be more efficient and less bug-prone if we knew we could safely assume it was $1925. Also, some developers will naively assume it’s $1925 especially rookies.

From a certain perspective, this makes all use of penny tactics tech-debt because a better solution exists that doesn’t drop precision as soon as you multiply or divide unless there is some significant performance boost from only working with the pennies.


(Ivan Matmati) #25

It’s an interesting observation. I guess that an open API (with different languages within clients application) should be designed with the minimum requirement. And we know that not all languages have arbitrary precision decimals.
Concerning your example of 50 000$, I doubt it is realistic. Any remainder should be paid in the last payment not just lost for the receiver. And even if you had decimals in your example, you just can’t pay thousandth of a currency.


(Jay Poss) #26

Please provide specific example where Money func does not work.
Thanks.
I would not recommend for large company without more research. I work for a small company and so far no problems.
Example using Money func.

    var x float64 = 9999999999
    var y float64 = .1
    for i := 0; i < 10; i++ {
        x = Money(x + y)
        fmt.Printf("%.3f\n", x)
    }
    if x == 10000000000 {
        fmt.Println("x = 10 Billion Exactly")
    }
Results:
9999999999.100
9999999999.200
9999999999.300
9999999999.400
9999999999.500
9999999999.600
9999999999.700
9999999999.800
9999999999.900
10000000000.000
x = 10 Billion Exactly




(Norbert Melzer) #27

Im Happy to do so, once I’m back home.


edit

Here it is, the code on the playground panics, because the amount hasn’t actually changed after adding something on top, thats why you do not ever use floats for money! This has nothing to do with the size of the company. This is axiomatic!

https://play.golang.org/p/6V38GHbMEwk


(Phillip) #28

It is true that you could make up the deficit in the final calculation automatically assuming you knew what the total was supposed to be.

What about when you don’t? Let’s say someone got a raise in the middle of the year on some day. Now you no longer know what the value is supposed to be unless you do some weird non-standard calculation.

Unfortunately I cannot discuss implementation, but let’s just say it’s easier to accumulate the fractions.


(Sean Killian) #29

Why does math/big.Rat not work?


(Phillip) #30

Oh it works. It definitely works.

The issue is how long it takes to think about and code in Go versus languages with native decimal primitives.

Try it for yourself when you have time because I cannot post work towards a fractions of cents solution.

Do it in Go, and then do it in C#. I’m not sure how familiar you are with C#, but just in case you aren’t, the notation for decimal constants is, for example 19.25m, and the static method to round is Decimal.Round, where Decimal.Round(19.255m,2) will round to two places.