{"action":"created","issue":{"url":"https://api.github.com/repos/golang/go/issues/12332","labels_url":"https://api.github.com/repos/golang/go/issues/12332/labels{/name}","comments_url":"https://api.github.com/repos/golang/go/issues/12332/comments","events_url":"https://api.github.com/repos/golang/go/issues/12332/events","html_url":"https://github.com/golang/go/issues/12332","id":103146146,"number":12332,"title":"proposal: package in standard library for computing with fixed-size 128 bits base-10 decimal.","user":{"login":"rin01","id":9582469,"avatar_url":"https://avatars.githubusercontent.com/u/9582469?v=3","gravatar_id":"","url":"https://api.github.com/users/rin01","html_url":"https://github.com/rin01","followers_url":"https://api.github.com/users/rin01/followers","following_url":"https://api.github.com/users/rin01/following{/other_user}","gists_url":"https://api.github.com/users/rin01/gists{/gist_id}","starred_url":"https://api.github.com/users/rin01/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rin01/subscriptions","organizations_url":"https://api.github.com/users/rin01/orgs","repos_url":"https://api.github.com/users/rin01/repos","events_url":"https://api.github.com/users/rin01/events{/privacy}","received_events_url":"https://api.github.com/users/rin01/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/golang/go/labels/Proposal","name":"Proposal","color":"ededed"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":14,"created_at":"2015-08-26T00:50:52Z","updated_at":"2015-09-01T18:31:32Z","closed_at":null,"body":"### Preamble\r\n\r\nIn financial computation, base-10 computation is mandatory.\r\nDiscussion can be found in the proposal [proposal: math/big: Decimal #12127](https://github.com/golang/go/issues/12127) for big.Decimal.\r\n\r\nA numeric type in the standard library usable for financial and commercial applications would be a big plus.\r\n\r\n### Existing solutions\r\n\r\nFor the moment, there exist 14 package that implement base-10 numbers.\r\nhttps://godoc.org/?q=decimal\r\n\r\nThey all seem experimental, except https://github.com/shopspring/decimal which is used in production.\r\n\r\nIts Decimal type is defined as:\r\n\r\n    type Decimal struct {\r\n        value *big.Int\r\n        exp int32\r\n    }\r\n\r\nSo, it is a __arbitrary-precision__ type. But this proposal is about __fixed-size__ decimal type.\r\n\r\n\r\n### Need to retrieve currency values stored as decimal in SQL databases\r\n\r\nBase-10 numbers are primarily used for financial computation, for dealing with currency values.\r\n\r\nThese values are already stored as base-10 fixed-point datatypes (NUMERIC, DECIMAL, MONEY) in SQL databases (MySQL, MS SQL Server, Oracle, etc), but working with them in Go is not so easy.\r\n\r\nEven if a big.Decimal type would eventually be added, the API of package math/big is more complex that what is needed for most financial or commercial applications.\r\n\r\nA simpler data type, __fixed-size 128bits floating-point decimal__ would be an optimal trade-off.\r\n\r\nIn the field of decimal data type, the work of Mike Cowlishaw is paramount:\r\nhttps://en.wikipedia.org/wiki/Mike_Cowlishaw\r\nhttp://speleotrove.com/decimal/\r\n\r\nNote that the Java implementation of java.math.BigDecimal is based on the work of M. Cowlishaw:\r\nhttp://www.drdobbs.com/jvm/fixed-floating-and-exact-computation-wit/184405721\r\n\r\n### Financial and commercial applications' requirements\r\n\r\nThe usual range for monetary values can be estimated as follows.\r\nAssets under management for a very large multinational insurance company is:\r\n\r\n`$265,507,000,000`\r\n\r\nThis figure is the sum of amounts that can have 8 digits after decimal point, because this precision is needed when working with foreign currency conversion.\r\n\r\nThis means that for a large company, a decimal data type must cope with figures like:\r\n\r\n`100,000,000,000.00000000`, that is, 20 significant digits.\r\n\r\nA `decimal128` fixed-size data type provides __34 significant digits__, which can easily store these figures.\r\nWe can even store USA national debt of $18,000,000,000,000 in it with full precision.\r\n\r\nWhen doing financial computation, intermediate calculation can require some more digits, and 34 significant digits of decimal128 can easily provide them for most real cases of financial computation.\r\n\r\nSmaller datatype like decimal 64bits only has 16 significant digits, which is not enough for financial computation.\r\nIt is always possible to save them with the proper precision in SQL database tables, to spare storage, but to make arithmetic on them, it is safer to always use a decimal 128bits.\r\n\r\n### Package for prototyping\r\n\r\nSo far, there exists no implementation of fixed-size decimal type, so I wrote this package to experiment with it.\r\nIt is a thin wrapper around the [decNumber](http://speleotrove.com/decimal/dnfloat.html) package of Mike Cowlishaw written in C.\r\nOnly the decQuad type has been implemented, as it is a 128bits fixed-size data type.\r\n\r\n`decnum.Quad` is a floating-point base-10 number with 34 significant digits, and size is 128 bits.\r\nWorking with them is almost as easy as working with float64:\r\n    - decnum.Quad is a value, and not a pointer.\r\n    - all arithmetic is done on values, not pointers.\r\n    - computation errors are tracked by denum.Context.\r\n\r\nhttps://github.com/rin01/decnum\r\nhttps://godoc.org/github.com/rin01/decnum\r\n\r\nThis package tries to demonstrate that decnum.Quad is easy to work with, and is a proposal for the base of an API.\r\n__A complete package would implement all functions described in this document:__\r\nhttp://speleotrove.com/decimal/dnfloat.html\r\nThe only difference is that values are passed by value instead of pointers.\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/golang/go/issues/comments/136821330","html_url":"https://github.com/golang/go/issues/12332#issuecomment-136821330","issue_url":"https://api.github.com/repos/golang/go/issues/12332","id":136821330,"user":{"login":"rin01","id":9582469,"avatar_url":"https://avatars.githubusercontent.com/u/9582469?v=3","gravatar_id":"","url":"https://api.github.com/users/rin01","html_url":"https://github.com/rin01","followers_url":"https://api.github.com/users/rin01/followers","following_url":"https://api.github.com/users/rin01/following{/other_user}","gists_url":"https://api.github.com/users/rin01/gists{/gist_id}","starred_url":"https://api.github.com/users/rin01/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rin01/subscriptions","organizations_url":"https://api.github.com/users/rin01/orgs","repos_url":"https://api.github.com/users/rin01/repos","events_url":"https://api.github.com/users/rin01/events{/privacy}","received_events_url":"https://api.github.com/users/rin01/received_events","type":"User","site_admin":false},"created_at":"2015-09-01T18:31:31Z","updated_at":"2015-09-01T18:31:31Z","body":"@griesemer presently, the context only contains two fields;\r\n  - the rounding mode\r\n  - the status\r\n\r\nThe status will be _incorporated as a field in the number struct_, which size will become 128bits + 8bits = 136bits.\r\n\r\n    type Quad struct {\r\n        val    C.decQuad    // val is 128 bits floating-point value\r\n        status C.uint8_t    // all errors that occured during generation of val\r\n    }\r\n\r\nWhen an operation fails, it will set the proper error status flags in this field, where it can be checked.\r\n\r\nThe rounding mode for most operations, like Add, Multiply, etc, can be the always ROUND_HALF_EVEN, as rounding mode has no effect except for pathological cases.\r\nFor operations like RoundWithMode, and explicit rounding argument is passed.\r\n\r\nThe \"merging\" of context, that is, the status field, happens like this:\r\n\r\n    r = a.Add(b)\r\n\r\n`r.status` will be set to   `a.status | b.status | operation status`\r\n\r\nPhilosophically, the status contains information like `Invalid operation`, `Division impossible`, etc, which are meta-data to the value itself.\r\nA `NaN` or another value has no sense if we don't know how it has been generated, and if errors occurred during its generation.\r\nThat's why the status field should be an inherent part of the number.\r\n\r\nWhen I will have made another prototype package, things will become clearer.\r\n\r\n\r\n\r\n\r\n\r\n\r\n"}}