简体   繁体   中英

NumberFormatter string(from:NSNumber) method has issues with decimal places

Here is my code

let ns = NumberFormatter.init()
ns.allowsFloats = true
ns.maximumFractionDigits = 18 //This is a variable value
ns.minimumFractionDigits = 18 //This is a variable value
ns.roundingMode = .floor
ns.numberStyle = .decimal
let doubleValueOfDecimal : Double = 12.95699999999998
let numb = NSNumber.init(value: doubleValueOfDecimal)
print(numb)
let string = ns.string(from: numb)
print(string)

The following is the output and input doubleValueOfDecimal = 2.95699999999998 Output 2.95699999999998 Optional("2.956999999999980000") But if I input

doubleValueOfDecimal =  12.95699999999998

The output is

12.95699999999998
Optional("12.957000000000000000")

The string conversion rounds up the value. Can someone explain me how this works?

The string conversion is rounding up the decimal places when I want it to show the exact number.

You are falling down the cracks between the expectations of the behaviour of decimal numbers and the reality that Float and Double are binary floating-point , that is the fractional part of decimal numbers are sums of 1/10's, 1/100's etc. while for binary numbers it is sums of 1/2's, 1/4's etc. and some values exact in one are inexact in the other and vice-versa.

Change your code to include:

let doubleValueOfDecimal : Decimal = Decimal(string:"12.95699999999998")!
let numb = doubleValueOfDecimal as NSDecimalNumber

and the output is probably what you expect:

12.95699999999998
12.956999999999980000

The Decimal type is a decimal floating-point value type, NSDecimalNumber is a subclass of NSNumber which holds a Decimal value.

HTH

(Note: you have to initialise the Decimal from a string as using a numeric literal appears to involve the Swift compiler using binary floating point at some point in the process...)

Use wrapper method of NSNumber class. `

 print(numb.stringValue)
let ns = NumberFormatter.init()
ns.allowsFloats = true
ns.maximumFractionDigits = 18
ns.minimumFractionDigits = 18
ns.roundingMode = .floor
ns.numberStyle = .decimal
let numb = NSNumber.init(value: doubleValueOfDecimal)
print(numb)
let string = ns.string(from: numb)
print(numb.stringValue)

Below Output for 2.95699999999998 , 12.95699999999998 values.

Output

2.95699999999998

2.95699999999998

12.95699999999998

12.95699999999998

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM