{"id":13412843,"url":"https://github.com/nikolaydubina/fpmoney","last_synced_at":"2025-04-14T19:10:49.171Z","repository":{"id":45786020,"uuid":"502245324","full_name":"nikolaydubina/fpmoney","owner":"nikolaydubina","description":"🧧 Fixed-Point Decimal Money","archived":false,"fork":false,"pushed_at":"2025-03-26T04:12:14.000Z","size":908,"stargazers_count":34,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-13T12:47:41.157Z","etag":null,"topics":["benchmarks","decimal","decimals","encoding","fixed-point","go","golang","money","vocabulary"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nikolaydubina.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-06-11T04:03:58.000Z","updated_at":"2025-04-02T10:52:11.000Z","dependencies_parsed_at":"2024-03-25T04:28:39.757Z","dependency_job_id":"3e5060d8-7702-41ac-9c6e-c98031ebb43f","html_url":"https://github.com/nikolaydubina/fpmoney","commit_stats":{"total_commits":70,"total_committers":2,"mean_commits":35.0,"dds":0.02857142857142858,"last_synced_commit":"722773b4aee28ff0e173440010312a5fff79d6c3"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikolaydubina%2Ffpmoney","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikolaydubina%2Ffpmoney/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikolaydubina%2Ffpmoney/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nikolaydubina%2Ffpmoney/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nikolaydubina","download_url":"https://codeload.github.com/nikolaydubina/fpmoney/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248943456,"owners_count":21186958,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["benchmarks","decimal","decimals","encoding","fixed-point","go","golang","money","vocabulary"],"created_at":"2024-07-30T20:01:29.959Z","updated_at":"2025-04-14T19:10:49.123Z","avatar_url":"https://github.com/nikolaydubina.png","language":"Go","funding_links":[],"categories":["Financial","金融"],"sub_categories":["Search and Analytic Databases","检索及分析资料库","Advanced Console UIs"],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg width=\"300\" height=\"300\" src=\"https://github.com/nikolaydubina/fpmoney/assets/2933061/022c83e3-8a14-4e8f-b1b7-94ab262fa590\"\u003e\n\u003c/p\u003e\n\n## 🧧 Fixed-Point Decimal Money\n\n[![codecov](https://codecov.io/gh/nikolaydubina/fpmoney/branch/master/graph/badge.svg?token=Eh52jhLERp)](https://codecov.io/gh/nikolaydubina/fpmoney)\n[![Go Report Card](https://goreportcard.com/badge/github.com/nikolaydubina/fpmoney)](https://goreportcard.com/report/github.com/nikolaydubina/fpmoney)\n[![Go Reference](https://pkg.go.dev/badge/github.com/nikolaydubina/fpmoney.svg)](https://pkg.go.dev/github.com/nikolaydubina/fpmoney)\n[![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go)\n[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/nikolaydubina/fpmoney/badge)](https://securityscorecards.dev/viewer/?uri=github.com/nikolaydubina/fpmoney)\n\n\u003e _**Be Precise:** using floats to represent currency is almost criminal. — Robert.C.Martin, \"Clean Code\" p.301_\n\n* as fast as `int64`\n* no `float` in parsing nor printing, does not leak precision\n* `ISO 4217`[^1][^2] currency\n* block mismatched currency arithmetics\n* 100 LOC\n* fuzz tests\n\n```go\nvar BuySP500Price = fpmoney.FromInt(9000, fpmoney.SGD)\n\ninput := []byte(`{\"sp500\": {\"amount\": 9000.02, \"currency\": \"SGD\"}}`)\n\ntype Stonks struct {\n    SP500 fpmoney.Amount `json:\"sp500\"`\n}\nvar v Stonks\nif err := json.Unmarshal(input, \u0026v); err != nil {\n    log.Fatal(err)\n}\n\namountToBuy := fpmoney.FromInt(0, fpmoney.SGD)\nif v.SP500.GreaterThan(BuySP500Price) {\n    amountToBuy = amountToBuy.Add(v.SP500.Mul(2))\n}\n\nfmt.Println(amountToBuy)\n// Output: 18000.04 SGD\n```\n\n### Ultra Small Fractions\n\nSome denominations have very low fractions.\nStoring them `int64` you would get.\n\n- `BTC` _satoshi_ is `1 BTC = 100,000,000 satoshi`, which is still enough for ~`92,233,720,368 BTC`.\n- `ETH` _wei_ is `1 ETH = 1,000,000,000,000,000,000 wei`, which is ~`9 ETH`. If you deal with _wei_, you may consider `bigint` or multiple `int64`. In fact, official Ethereum code is in Go and it is using bigint ([code](https://github.com/ethereum/go-ethereum/blob/master/params/denomination.go)).\n\n### Benchmarks\n\n```bash\n$ go test -bench=. -benchmem .\ngoos: darwin\ngoarch: arm64\npkg: github.com/nikolaydubina/fpmoney\ncpu: Apple M3 Max\nBenchmarkCurrency_UnmarshalText-16      510934713                2.213 ns/op           0 B/op          0 allocs/op\nBenchmarkCurrency_AppendText-16         439866170                2.714 ns/op           0 B/op          0 allocs/op\nBenchmarkCurrency_MarshalText-16        88133492                13.52 ns/op            8 B/op          1 allocs/op\nBenchmarkCurrency_String-16             1000000000               1.078 ns/op           0 B/op          0 allocs/op\nBenchmarkArithmetic/add-16              901921378                1.562 ns/op           0 B/op          0 allocs/op\nBenchmarkJSON/small/encode-16            5652006               211.6 ns/op           160 B/op          3 allocs/op\nBenchmarkJSON/small/decode-16            4993570               236.0 ns/op           152 B/op          2 allocs/op\nBenchmarkJSON/large/encode-16            4835323               246.9 ns/op           176 B/op          3 allocs/op\nBenchmarkJSON/large/decode-16            3946946               304.9 ns/op           152 B/op          2 allocs/op\nPASS\nok      github.com/nikolaydubina/fpmoney        11.287s\n```\n\n## References and Related Work\n\n- [ferdypruis/iso4217](https://github.com/ferdypruis/iso4217) was a good inspiration and reference material. it was used in early version as well. it is well maintained and fast library for currencies. \n- `github.com/shopspring/decimal`: fixed precision; faster printing/parsing/arithmetics; currency handling \n- `github.com/Rhymond/go-money`: does not use `float` or `interface{}` in parsing; currency is enum\n- `github.com/ferdypruis/iso4217`: skipped deprecated currencies to fit into `uint8` and smaller struct size\n- https://en.wikipedia.org/wiki/ISO_4217\n\n[^1]: excluding currencies with 4+ minor units `CLF`, `UYW`\n[^2]: excluding deprecated currencies `HRD`, `HRK`, `SLL`, `ZWL`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnikolaydubina%2Ffpmoney","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnikolaydubina%2Ffpmoney","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnikolaydubina%2Ffpmoney/lists"}