All Projects → davdroman → PreciseDecimal

davdroman / PreciseDecimal

Licence: Unlicense License
A Decimal type that plays nicely with literals and Decodable ✨

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to PreciseDecimal

js-big-decimal
Work with large numbers on the client side with high precision.
Stars: ✭ 41 (+127.78%)
Mutual labels:  decimal, precision
Podcasts-UIKit
OUTDATED. A clone of Apple's Podcasts. UIKit version.
Stars: ✭ 145 (+705.56%)
Mutual labels:  codable
verificarlo
A tool for debugging and assessing floating point precision and reproducibility.
Stars: ✭ 51 (+183.33%)
Mutual labels:  precision
ash
Simple iOS app using MVVM and Codable
Stars: ✭ 24 (+33.33%)
Mutual labels:  codable
linked-list
Minimalistic linked lists
Stars: ✭ 73 (+305.56%)
Mutual labels:  double
CKBracketView
Tournament bracket view for iOS. Developed in swift.
Stars: ✭ 38 (+111.11%)
Mutual labels:  double
FTAPIKit
Declarative and generic REST API framework using Codable.
Stars: ✭ 18 (+0%)
Mutual labels:  codable
DoubleFloats.jl
math with more good bits
Stars: ✭ 102 (+466.67%)
Mutual labels:  precision
TOMLDecoder
From TOML to Swift Codable types.
Stars: ✭ 52 (+188.89%)
Mutual labels:  codable
AlamofireCodable
An Alamofire extension which converts JSON response data into swift objects using Codable
Stars: ✭ 47 (+161.11%)
Mutual labels:  codable
AC-iOS-Codeable-and-UserDefaults
No description or website provided.
Stars: ✭ 16 (-11.11%)
Mutual labels:  codable
codable-kit
Conveniences for working with Swift's Codable protocols.
Stars: ✭ 19 (+5.56%)
Mutual labels:  codable
JSONMatching
An easy way to decode JSON data into Model object in pure Swift
Stars: ✭ 13 (-27.78%)
Mutual labels:  jsondecoder
CodablePersist
Store and Cache Anything Codable
Stars: ✭ 18 (+0%)
Mutual labels:  codable
SuperCodable
Codable, but with Super power made custom Codable behavior easy.
Stars: ✭ 23 (+27.78%)
Mutual labels:  codable
decimal-eval
A tiny, safe, fast JavaScript library for decimal arithmetic expressions.
Stars: ✭ 18 (+0%)
Mutual labels:  decimal
cldr-engine
Internationalization and localization in Typescript with Unicode CLDR, batteries included
Stars: ✭ 34 (+88.89%)
Mutual labels:  decimal
Realm-and-Swift-Codable
How to implement Swift 4 Codable with Realm Database
Stars: ✭ 34 (+88.89%)
Mutual labels:  codable
react-native-double-click
A Component Wrapper for Double Click/Tap
Stars: ✭ 42 (+133.33%)
Mutual labels:  double
PotentCodables
🧪 PotentCodables - A potent set of implementations and extensions to the Swift Codable system
Stars: ✭ 32 (+77.78%)
Mutual labels:  codable

PreciseDecimal

CI status

Introduction

Swift has long suffered a problem with its Decimal type: unapparent loss of precision.

This happens with all common ways of initializing:

let badDecimal = Decimal(3.133) // 3.132999999999999488
let badDecimal: Decimal = 3.133 // 3.132999999999999488

But not these ones:

let goodDecimal = Decimal(string: "3.133") // 3.133
let goodDecimal = Decimal(sign: .plus, exponent: -3, significand: 3133) // 3.133

Furthermore, this also applies to JSON decoding 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.

This is something that Apple will most likely fix at some point. In the meantime, PreciseDecimal has your back.

Usage

This library declares a lightweight PreciseDecimal type as a wrapper around Decimal, with precise init and Decodable implementations.

let goodDecimal = PreciseDecimal(3.133) // 3.133
let goodDecimal: PreciseDecimal = 3.133 // 3.133
struct Price: Decodable {
    let amount: PreciseDecimal
}

let json = #"{ "amount": 3.133 }"#.data(using: .utf8)!
let goodDecimal = try JSONDecoder().decode(Price.self, from: json).amount // 3.133

Try it out!

PreciseDecimal supports Arena to effortlessly take it for a spin in a playground before you decide to add it to your codebase.

Simply install Arena and run arena davdroman/PreciseDecimal --platform macos in your terminal.

FAQ

Is this solution bullet-proof?

No.

PreciseDecimal falls short for very high precision numbers. Case in point:

let a = PreciseDecimal(  1234567890.0123456789 )
let b = Decimal(string: "1234567890.0123456789")!
print(a) // 1234567890.0123458
print(b) // 1234567890.0123456789

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

It'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.

Why not make it a @propertyWrapper?

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

Why doesn't it have [x] feature?

In order to keep the library's scope and implementation as lightweight as possible, optimistic for a painless obsolescence once Apple fixes Decimal.

Do feel free to suggest otherwise if I missed a vital part of functionality that should definitely be in this library.

Will Apple ever fix this?

I don't know.

However, you're not alone in your discontent. Here are two relevant issues you can upvote to improve the chances for Apple to see them:

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].