-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
proposal: spec: add decimal float types (IEEE 754-2008) #19787
Comments
I think this proposal can be implement outside golang runtime, builtin and builtin package. |
@bronze1man Yes, there are thirty-party packages and proposals for including a decimal package into std. But this proposal is about adding fixed-size decimal floating point types, along with the existing binary floating point types using the existing arithmetic operators, rather than introducing a new package. |
I made my own post for this without seeing this one first. Here are the reasons I believe that a decimal float type would be good for Go - #26699 |
Adding onto this - If we had operator overloading, this could be implemented as a 3rd party lib instead |
Some useful information in: In particular, this reference was useful:
|
It would help to have a clear idea of who would want to use these new types. It would also help if the proposal spelled out the new types and how untyped constants would be handled. |
From manually polling people who use my (big) decimal package:
|
Thanks! But we shouldn't confuse big decimals with this proposal, which is for fixed size decimals. It's not obvious to me that people who use the former will want to use the latter. For example, the fact that people use the math/big |
I think there's more overlap than it would seem. A 128-bit decimal gives you 34 significant digits which is plenty for most regular usage, like wanting to perform accurate monetary arithmetic. And, as Brad's link mentioned, four of the six listed languages have only big decimals. So, I think it's somewhat germane :) A point to consider (though I'm definitely in support of adding decimal type(s)): if decimals are added there will likely need to be support in the |
In this proposal, i expect only fixed size decimals, and i need them for financial computations. |
For people like me who know nothing, can you expand on why decimal floats are better for financial computations that 1) ordinary floats; 2) the |
Section 1.1 discusses a few reasons here - http://speleotrove.com/decimal/IEEE-cowlishaw-arith16.pdf |
That PDF is good. His FAQ sections is good as well: http://speleotrove.com/decimal/decifaq1.html#inexact TL;DR: floats are inaccurate because they can't exactly store base 10 numbers. Integers (representing the smallest currency amount, e.g. 1 cent USD) work well, but can be annoying to use for anything other than basic arithmetic. And for non-monetary calculations integers don't work. E.g., http://speleotrove.com/decimal/decifaq4.html#order |
In my company, we used all 3 alternatives: floats are not exact numbers, making some elementary calculations can give surprising ( for financial people) results. hope this is useful |
As I can personally testify, the 128 bit The alternative is to always work in cents using their 64 bit The twin drawbacks are the extra memory required and performance - Back in pre-.NET days, VB6 etc. had a 64 bit So, yes, if you'd like Go to appeal to financial programmers, I think that adding language support for fixed point decimal types would certainly be worthwhile and I'd suggest that 64 bit and 128 bit types (perhaps named As far as untyped constants are concerned, I'd suggest that they should work in a similar fashion to what they do now for the other basic numeric types. So literals would accommodate themselves to whatever type was required, there'd be conversions to/from the other numeric types and so on. However, no untyped numeric constant would have a default type of either a := 123.45 // a is float64
b := dec128(123.45) // b is dec128
var c = dec64(a) // c is dec64
d := b + 6 // d is dec128
var e dec64 = 678.9 // e is dec64 |
I believe most people can agree that there is a need for decimals. The question is whether the standard library should provide it or whether it should be a primitive type. |
As @deanveloper indicated earlier, the lack of operator overloading in Go would also be a problem if decimal support were provided as a library rather than built into the language. In fact, I suspect most folks would prefer to stick with what they currently do rather than having to deal with named methods for the basic arithmetic operations. Whilst it's true that you have to do this already for 'big' number arithmetic, the difference is that you have no choice if you need to deal with such numbers. |
Just some background from data/database people's point of view. Decimal64/128 is really a big help. As said in previous posts, dec32 is probably not interesting. Unfortunately IEEE allow two different formats for decimal, BID and DPD -- I believe one is from Intel and the other from IBM -- therefore, it is necessary to decide on one format and maybe code conversion routines between these two. Both formats have high quality open source implementations. Decimal64/128 is slower than double, but not too slow, we measured 2 to 3 x compared to double, which is quite impressive. Databases, for example, PostgreSQL, have to implement their own decimal/numerical type. In case of PostgreSQL, it is a variable length data type, supporting greater precision (but, decimal128 is enough for almost everybody), but much slower. We need a native decimal64/128 type instead of cgo binding to intel/IBM library because cgo cost may just killed it. |
Here, we're working with a proprietary language that is made for quickly developing business applications. Today, I've helped a colleague fix a bug that was due to using binary floats instead of a builtin monetary type. The latter is an 80 bits fixed precision number with 6 decimal places, and it has always been sufficient for us. I plan to present Go to my team, but I am a bit afraid of their reaction when I tell them how to write calculations with an external lib. I think any serious business application should use decimal types. Maybe some developers don't realize that until an accountant asks them why their report doesn't show exactly same numbers as his Excel sheet. A builtin dec128 would completely fulfill our need. |
I have just stumbled upon this striking example: Trying to round 35.855 to 2 decimal places gives unexpected result.
|
@tc-hib Thanks. I understand that floating point numbers behave in ways that people find surprising (https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). That's not the question I was trying to ask. |
Oh, sorry I didn't get it. Decimal type is a true silver bullet for all of us who don't need to save every cpu cycle, yet have to follow strict business rules. We simply use it everywhere. Once we've done that, it is really hard to go back, so we would always prefer translating our formulas to method calls rather than using ints or floats. There are many legacy business apps (in COBOL for example, quite old), Excel sheets, etc. using decimal arithmetic as fluently as integers. I think Go would be a good fit for modernizing all those commerce specific apps thanks to its simplicity, but it would require "translating" every calculation carefully. I believe using integers and floats is trickier than it seems, because we often have varying number of decimal places (3 for purchases, 2 for sales, and some intermediate calculations not rounded, such as taxes and commercial agreements). If we're only adding and multiplying numbers, or dividing by multiples of 5 and 2, users expect exact results. In fact, they expect same results as Excel sheet or pen and paper. I must admit i don't have much experience in workarounds, because I've always been working with decimal types, and we nearly never use binary floats, as strange as it may seem. |
The upcoming "Structured Field Values for HTTP" RFC will have a decimal type. To support structured headers and trailers properly in the stdlib, support for decimal floating point will be mandatory. |
https://www.reddit.com/r/golang/comments/l4x9zs/introducing_gofinancial/ |
I am new to Golang and found it surprising that after more than a decade maintainers aren’t convinced yet that having native support for decimals is essential for many applications. |
Well, it's a lot of work. And having reread the comments, I see that there is still no clear statement of exactly what types should be added to the language. I have a feeling that different people on this issue are talking about somewhat different things. |
This proposal is about floats as defined by IEEE 754-2008, and I think most of us would be happy with only a 128 bit float. I wouldn't expect a built-in type that "works like an int" to support arbitrary precision. |
For a language proposal we need to be precise. You are suggesting adding |
I believe decimal128 would suffice, yes, and it would be a huge improvement for all business apps, avoiding a lot of subtle bugs, especially for beginners. Having decimal64 or decimal32 seems like premature optimisation to me. Once we use decimal floats, we've usually already accepted their cost. Most of the time we'd rather have fixed point decimals for best performance anyway. Having a float128 doesn't solve the same issue, that is, correctness in some representation. And I don't think the need would be as common as for the decimal type. |
@ericlagergren Ah, you mean e.g. accrued interest, math.Pow, etc.? |
To whom it may concern: there is a new, decent decimal128 implementation: github.com/woodsbury/decimal128. I've tested it and it's probably the best. I don't understand why the author hasn't advertised this package anywhere yet. |
That any better than the shopspring one that's been around for years? |
It is better because it is fixed size (128 bits), not arbitrary precision. If i want to do scientific calculations, i will use arbitrary-precision, but for financial i want fixed type. |
Yes. Just make benchmarks for your case, and you will see the difference. |
shopspring uses |
I agree that adding
Initially my thinking was that #9455 should be a higher priority than this, but after reading through comments in both that thread and this, and after porting a fairly large code base off of
I am left unsatisfied by the disarray of packages, sometimes compatible at the seams, but each never feeling whole. Working with currencies and combining Would a proposal to add a single |
I know there was a proposal about decimal as an std package.
But according to https://en.wikipedia.org/wiki/Decimal_floating_point, there have already been multiple compliant hardware implementations, and supported by several commonly used programming languages. I think having decimal as first-class citizen like the other part of the IEEE-754 standard makes sense.
The upside is we don't have to spend the effort on API design upfront to make it useful like math.big. We can just limit the scope of the operations only within the Go's existing arithmetic operators. Designing a good numerical/arithmetic API beyond the conventional operators is harder and can be deferred later with no harm.
The text was updated successfully, but these errors were encountered: