{"id":16685368,"url":"https://github.com/davdroman/precisedecimal","last_synced_at":"2025-03-21T18:33:04.881Z","repository":{"id":43040403,"uuid":"377257289","full_name":"davdroman/PreciseDecimal","owner":"davdroman","description":"A Decimal type that plays nicely with literals and Decodable","archived":false,"fork":false,"pushed_at":"2023-10-16T13:12:21.000Z","size":77,"stargazers_count":31,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-16T00:27:25.900Z","etag":null,"topics":["codable","decimal","double","json","jsondecoder","literals","precision"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davdroman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-15T18:20:15.000Z","updated_at":"2024-08-25T15:13:49.000Z","dependencies_parsed_at":"2024-10-28T11:29:24.501Z","dependency_job_id":"a1d9ab6a-14b1-48ac-8e9a-ac88f99800f7","html_url":"https://github.com/davdroman/PreciseDecimal","commit_stats":{"total_commits":44,"total_committers":2,"mean_commits":22.0,"dds":"0.045454545454545414","last_synced_commit":"b664de1be8da5eed0e1d83170df5b63920f35be0"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davdroman%2FPreciseDecimal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davdroman%2FPreciseDecimal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davdroman%2FPreciseDecimal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davdroman%2FPreciseDecimal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davdroman","download_url":"https://codeload.github.com/davdroman/PreciseDecimal/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244849264,"owners_count":20520678,"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":["codable","decimal","double","json","jsondecoder","literals","precision"],"created_at":"2024-10-12T14:47:06.407Z","updated_at":"2025-03-21T18:33:04.534Z","avatar_url":"https://github.com/davdroman.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PreciseDecimal\n\n![CI status](https://github.com/davdroman/PreciseDecimal/workflows/CI/badge.svg)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fdavdroman%2FPreciseDecimal%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/davdroman/PreciseDecimal)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fdavdroman%2FPreciseDecimal%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/davdroman/PreciseDecimal)\n\n## Introduction\n\nSwift has long suffered a problem with its `Decimal` type: [unapparent loss of precision](https://bugs.swift.org/browse/SR-8409).\n\nThis happens with all common ways of initializing:\n\n```swift\nlet badDecimal = Decimal(3.133) // 3.132999999999999488\n```\n\n```swift\nlet badDecimal: Decimal = 3.133 // 3.132999999999999488\n```\n\nBut not these ones:\n\n```swift\nlet goodDecimal = Decimal(string: \"3.133\") // 3.133\n```\n\n```swift\nlet goodDecimal = Decimal(sign: .plus, exponent: -3, significand: 3133) // 3.133\n```\n\nFurthermore, this also applies to [JSON decoding](https://bugs.swift.org/browse/SR-7054) since it uses `NSJSONSerialization` under the hood, which is presumed to parse decimal numbers as `Double` and then initializing a `Decimal` via its lossy `Double` initializer as exemplified above. A common workaround for this is to receive sensitive `Decimal` values as strings and parsing into `Decimal` with the working string initializer, however oftentimes the format of a JSON payload is out of one's control.\n\nThis is something that Apple will most likely fix at some point. In the meantime, PreciseDecimal has your back.\n\n## Usage\n\nThis library declares a lightweight `PreciseDecimal` type as a wrapper around `Decimal`, with precise `init` and `Decodable` implementations.\n\n```swift\nlet goodDecimal = PreciseDecimal(3.133) // 3.133\n```\n\n```swift\nlet goodDecimal: PreciseDecimal = 3.133 // 3.133\n```\n\n```swift\nstruct Price: Decodable {\n    let amount: PreciseDecimal\n}\n\nlet json = #\"{ \"amount\": 3.133 }\"#.data(using: .utf8)!\nlet goodDecimal = try JSONDecoder().decode(Price.self, from: json).amount // 3.133\n```\n\n## FAQ\n\n### Is this solution bullet-proof?\n\nNo.\n\n`PreciseDecimal` falls short for very high precision numbers. Case in point:\n\n```swift\nlet a = PreciseDecimal(  1234567890.0123456789 )\nlet b = Decimal(string: \"1234567890.0123456789\")!\nprint(a) // 1234567890.0123458\nprint(b) // 1234567890.0123456789\n```\n\nSo if you're going to be dealing with **more than 6 decimal places, this library is not for you**. Instead, the best solution as it currently stands is to represent decimals as strings, especially when it comes to JSON serialization.\n\nIt's up to Apple and only Apple to introduce real `Decimal` literals into the language, as well as fixing the JSON serialization mechanisms in Foundation.\n\n### Why not make it a `@propertyWrapper`?\n\nBecause it's very easy to forget to annotate properties, especially since there aren't any compiler checks or tests to ensure the slight change in behavior it provides, leading to sneaky bugs down the road.\n\n### Why doesn't it have [x] feature?\n\nIn order to keep the library's scope and implementation as lightweight as possible, optimistic for a painless obsolescence once Apple fixes `Decimal`.\n\nDo feel free to [suggest otherwise](https://github.com/davdroman/PreciseDecimal/issues/new) if I missed a vital part of functionality that should *definitely* be in this library.\n\n### Will Apple ever fix this?\n\nI don't know.\n\nHowever, you're [not alone](https://forums.swift.org/t/how-to-initialize-decimal/53630) in your discontent. Here are two relevant issues you can **upvote** to improve the chances for Apple to see them:\n\n- [SR-920](https://bugs.swift.org/browse/SR-920)\n- [SR-7054](https://bugs.swift.org/browse/SR-7054)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavdroman%2Fprecisedecimal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavdroman%2Fprecisedecimal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavdroman%2Fprecisedecimal/lists"}