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

proposal: spec: add decimal float types (IEEE 754-2008) #19787

Open
typeless opened this issue Mar 30, 2017 · 18 comments

Comments

@typeless
Copy link

typeless commented Mar 30, 2017

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.

@bradfitz

This comment has been minimized.

Copy link
Member

bradfitz commented Mar 30, 2017

Related: #12127, #19770

@gopherbot gopherbot added this to the Proposal milestone Mar 30, 2017
@gopherbot gopherbot added the Proposal label Mar 30, 2017
@bronze1man

This comment has been minimized.

Copy link
Contributor

bronze1man commented Mar 31, 2017

I think this proposal can be implement outside golang runtime, builtin and builtin package.
Does any implement exist?

@typeless

This comment has been minimized.

Copy link
Author

typeless commented Mar 31, 2017

@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.

@rsc rsc added the Go2 label Apr 3, 2017
@rsc rsc changed the title proposal: builtin decimal types (IEEE 754-2008) proposal: spec: add decimal float types (IEEE 754-2008) Jun 16, 2017
@deanveloper

This comment has been minimized.

Copy link

deanveloper commented Jul 30, 2018

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

@deanveloper

This comment has been minimized.

Copy link

deanveloper commented Sep 10, 2018

Adding onto this - If we had operator overloading, this could be implemented as a 3rd party lib instead

@bradfitz

This comment has been minimized.

Copy link
Member

bradfitz commented Feb 12, 2019

Some useful information in:
http://open-std.org/JTC1/SC22/WG21/docs/papers/2014/n3871.html

In particular, this reference was useful:

The need for support of exact decimal computations is recognized in many communities and supported in several systems, although different alternatives for the support are chosen. Below is a list of example programming languages with decimal support:

  • The C committee is working on a Decimal TR as TR 24732. The decimal support in C uses built-in types _Decimal32, _Decimal64, and _Decimal128.
  • Java provides decimal arithmetic by java.math.BigDecimal, an arbitrary sized integer with an integer scale for the decimal places.
  • Python provides decimal.Decimal which is a fixed point decimal representation. The number of decimal digits can be set globally.
  • .Net provides System.Decimal which is a 128 bit decimal floating point. The details of this represntation are slightly different from the 128 bit decimal floating point in IEEE 754–2008. System.Decimal is accessible in C# as decimal.
  • SQL provides a fixed point decimal representation where the number of digits and the number of fractional digits can be chosen for each context.
  • Ruby provides BigDecimal, an arbitrary sized integer with an integer scale for the decimal places.
@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

ianlancetaylor commented Feb 12, 2019

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.

@ericlagergren

This comment has been minimized.

Copy link
Contributor

ericlagergren commented Feb 12, 2019

It would help to have a clear idea of who would want to use these new types.

From manually polling people who use my (big) decimal package:

  • Banks
  • CAD
  • Numerical analysis
  • Databases (see: cockroachdb/apd)
  • E-commerce sites
  • Bitcoin sites
@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

ianlancetaylor commented Feb 12, 2019

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 Rat type does not suggest that we should add a rational number type to the language.

@ericlagergren

This comment has been minimized.

Copy link
Contributor

ericlagergren commented Feb 12, 2019

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 math/ package, like math and math/cmplx.

@djadala

This comment has been minimized.

Copy link
Contributor

djadala commented Feb 13, 2019

In this proposal, i expect only fixed size decimals, and i need them for financial computations.

@ianlancetaylor

This comment has been minimized.

Copy link
Contributor

ianlancetaylor commented Feb 13, 2019

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 int64 type? Just pointing to a paper would be great. Thanks.

@deanveloper

This comment has been minimized.

Copy link

deanveloper commented Feb 13, 2019

Section 1.1 discusses a few reasons here - http://speleotrove.com/decimal/IEEE-cowlishaw-arith16.pdf

@ericlagergren

This comment has been minimized.

Copy link
Contributor

ericlagergren commented Feb 13, 2019

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

@djadala

This comment has been minimized.

Copy link
Contributor

djadala commented Feb 13, 2019

In my company, we used all 3 alternatives:
decimal in c/c++
int64 in go, c/c++,
float in c/c++, perl

floats are not exact numbers, making some elementary calculations can give surprising ( for financial people) results.
just storing and loading float64 from database (oracle use some sort of decimals for numbers) can lead to inexact value, and some financial applications are 90% database io.
int64s mostly works, but are cumbersome (IMO), in all IO to external systems (including databases) you must convert them to "right" form.

hope this is useful

@alanfo

This comment has been minimized.

Copy link

alanfo commented Jun 15, 2019

As I can personally testify, the 128 bit decimal type is great for writing financial applications in C# which need to be accurate to the cent, penny etc. as you don't have to worry about the rounding errors which can accumulate if you use their float or double types. The results are always exact even for the largest amounts likely to be encountered in practice.

The alternative is to always work in cents using their 64 bit long type and then div/rem by 100 when you need to display or store the final result. However, this is both tedious and error prone and may even not be large enough when you're dealing with some currencies.

The twin drawbacks are the extra memory required and performance - decimal is much slower than double which in turn is slower than long. However, for most financial programmers this is a price worth paying for the convenience they gain from using decimal.

Back in pre-.NET days, VB6 etc. had a 64 bit Currency type which (IIRC) was scaled to 4 d.p. This was more than adequate for applications which didn't need to process large amounts of money and I always thought it was a mistake not to support it in .NET as well.

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 dec64 and dec128 respectively) would be adequate as I can't see much point nowadays in having a 32 bit type as well.

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 dec64 or dec128. So for example, we'd have:

    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
@typeless

This comment has been minimized.

Copy link
Author

typeless commented Jul 5, 2019

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.
The shortcoming of making decimal as a third-party package is that libraries working with it are hard to cooperate. For example, a package provides finance calculations based on a particular decimal type would not be naturally composable with another decimal type belonging to a time series data store. Then, it would create a situation where a financial application might have to include multiple decimal packages, and programmers have to write conversion code between them, which is clumsy and inefficient.

@alanfo

This comment has been minimized.

Copy link

alanfo commented Jul 10, 2019

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
10 participants
You can’t perform that action at this time.