2017-04-08 35 views
2
分隔千

我有以下浮动:1123455432.67899如何从一个浮动值与小数斯威夫特

我期望的结果是一个字符串:1,123,455,432.67899

最好的情况正确,和基于位置.(US /欧洲)

struct Number { 
    static let withSeparator: NumberFormatter = { 
     let formatter = NumberFormatter() 
     formatter.groupingSeparator = "," 
     formatter.numberStyle = .decimal 
     return formatter 
    }() 
} 

let myFloat: Float = 1123455432.67899 
let myNumber = NSNumber(value: myFloat) 
let formatter = Number.withSeparator 
if let result = formatter.string(from: myNumber) { 
    print(result) 
} 

此格式的伟大工程,只要我的持股量没有小数,ALS只要我有小数,它开始“计算”。它基于第三个十进制数字计算向上/向下。

我错过了什么?什么是获得从不管有多少十进制数一Float一个String: 1,123,455,432.67899的最佳方式?非常感谢帮助。

编辑:

我的确切功能:

func formatValue(_ value: String) -> String { 

    if let double = Double(value) { 

     let formatter = Number.withSeparator 
     if let result = formatter.string(from: NSNumber(value: double)) { 
      return result 
     } else { 
      return value 
     } 
    } else { 
     return value 
    } 
} 

value总是例如5.5555555555一个数字。但在这个特定的情况下,result = 5.556。的Float

+0

您确定要指定'grouping'分离器','?并非所有地方都使用它。 – Alexander

+0

不,我不需要有分离由'被迫,',这只是示例代码 –

+2

甲'Float'是一个32位的二进制浮点数。它可以表示约7位十进制数字,比较https://en.wikipedia.org/wiki/IEEE_floating_point。对于精确*十进制*算术,使用'(NS)DecimalNumber' –

回答

4

使用Double相反,您指定的值不是很好的可表示在Float

// [... your current code ...] 
let myDouble: Double = 1123455432.67899 
let myNumber = NSNumber(value: myDouble) 
// [... your current code ...] 

1,123,455,432.679

e+XX符号Float在默认情况下是不是作秀,那是因为Float不能存储所有数字。请参阅:

let myFloat2: Float = 1123455432.67899 
print(myFloat2 == 1123455432) // true 
let notRepresentable = Float(exactly:1123455432.67899) // nil 
+0

它并不能真正帮助我解决问题。如果我使用确切的代码,但与双重,我把十进制数字,它开始更改数字从第三小数在 –

+0

我在put = 5.5555555555,输出= 5.556 –

+5

@DavidSeek你得到3位小数,因为这是默认的数字格式化程序。使用'formatter.maximumFractionDigits = 9'。 – rmaddy

1

从根本上说,您的问题来自于Float浮点不精确。使用双精度浮点数据类型(Double)将减轻此,在一定程度上。

而且,你不应该硬编码groupingSeperator,而是让它从当前的区域设置(这是默认行为)推断。

import Foundation 

let numberFormatter: NumberFormatter = { 
    let nf = NumberFormatter() 
    nf.numberStyle = .decimal 
    return nf 
}() 


let myDouble = 1123455432.67899 
let myNumber = NSNumber(value: myDouble) 

// It's also directly initializable from a literal 
// let myNumber: NSNumber = 1123455432.67899 

guard let result = numberFormatter.string(from: myNumber) else { fatalError() } 

print(result) 
+3

不需要将格式化程序的语言环境设置为当前语言环境 - 这是默认设置。 – rmaddy

+0

@rmaddy很酷,不知道这个。 – Alexander

+0

Btw不需要初始化一个新的NSNumber对象。只是用于:而不是: –

1

除了luk2302's answer,我建议把它作为一种方法添加到Double扩展,如下:

extension Double { 
    func formattedString(_ maximumFractionDigits: Int = 5) -> String? { 
     let numberFormatter = NumberFormatter() 
     numberFormatter.numberStyle = .decimal 
     numberFormatter.maximumFractionDigits = maximumFractionDigits 

     return numberFormatter.string(for:self) 
    } 
} 

if let formattedString = 1123455432.67899.formattedString() { 
    print(formattedString) // 1,123,455,432.67899 
} 

它可能提高易获得所需的字符串。

感谢您的@rmaddy@LeoDabus提供有用的注意事项。

+0

'guard'声明的要点是什么?只需返回'numberFormatter.string'的结果即可。 – rmaddy

+0

不要设置groupingSeparator。根据用户的区域设置让它默认正确。 – rmaddy

+0

Btw不需要初始化一个新的NSNumber对象。只用于:而不是从: –