Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java BigDecimal in Swift

What data type I can use for parsing Java BigDecimal? In Objective - C it can be done by using NSDecimalNumber. Do I have Swift-native solution (without using NSDecimalNumber)?

like image 309
Srj0x0 Avatar asked Aug 23 '16 20:08

Srj0x0


People also ask

What is a Java BigDecimal?

A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale. If zero or positive, the scale is the number of digits to the right of the decimal point. If negative, the unscaled value of the number is multiplied by ten to the power of the negation of the scale.

Why is BigDecimal used in Java?

The BigDecimal class provides operations on double numbers for arithmetic, scale handling, rounding, comparison, format conversion and hashing. It can handle very large and very small floating point numbers with great precision but compensating with the time complexity a bit.


2 Answers

This may not be what you want, as you are saying swift-native solution. But in Swift 3, an old C-struct based NSDecimal is imported as Decimal, and a big re-arrangement for it has been done as to say "it is nearly Swift-native".

let deca = 1.23 as Decimal //<- This actually may produce some conversion error, while `ExpressibleByFloatLiteral` uses `Double` as an intermediate value.
let decb = 0.01 as Decimal
print(deca + decb == 1.24) //->true

UPDATE Added a simple example, where you can find a calculation error in Double (binary floating point system). (Tested in Xcode 8 beta 6.)

let dblc = 0.000001
let dbld = 100 as Double
let dble = 0.0001
print(dblc * dbld == dble) //->false (as Double cannot represent decimal fractions precisely)

let decc = Decimal(string: "0.000001")! //<- avoiding conversion error
let decd = 100 as Decimal //<- integer literal may not generate conversion error
let dece = Decimal(string: "0.0001")!
print(decc * decd == dece) //->true
like image 153
OOPer Avatar answered Oct 09 '22 17:10

OOPer


You can also use j2obj, a Google project that translates Java code to Objective C, including all the Java types like BigInteger and BigDecimal. Using this I was able to make an XCFramework that incorporates support for those native Java types, including all their functionality from Java, into Swift. Pretty cool, although it's not a small framework.

Basically you just clone j2objc and build locally (cd to its directory and "make dist -j8"). Then make a new Xcode project with a framework target. Follow the steps on Google's j2objc site to add your J2OBJC_HOME to build settings and add the library and header search paths to your new framework project.

Now in your framework's public header you'll want to import "java/math/BigDecimal.h", and you'll want to add to your framework's headers a copy of all the headers needed by BigDecimal.m and its dependencies.

Lastly archive your framework for hardware platforms and build for simulator, then make an XCFramework including all those built .frameworks from the archives and your DerivedData.

Once you have the XCFramework you can add it to any other project whose architectures it supports. And from there use it in code. Note you have to initialize j2bjc classes before making an instance of them.

like image 35
CommaToast Avatar answered Oct 09 '22 17:10

CommaToast