Answers:
Swift 4.2+字符串加倍
您应该使用新的类型初始值设定项在String和数字类型(Double,Float,Int)之间进行转换。它会返回一个可选类型(Double?),该类型将具有正确的值;如果String不是数字,则返回nil。
注意:不建议使用NSString doubleValue属性,因为如果无法转换该值(即,错误的用户输入),它将返回0。
let lessPrecisePI = Float("3.14")
let morePrecisePI = Double("3.1415926536")
let invalidNumber = Float("alphabet") // nil, not a valid number
使用if / let解开值以使用它们
if let cost = Double(textField.text!) {
print("The user entered a value price of \(cost)")
} else {
print("Not a valid number: \(textField.text!)")
}
您可以使用NumberFormatter
该类转换带格式的数字和货币。
let formatter = NumberFormatter()
formatter.locale = Locale.current // USA: Locale(identifier: "en_US")
formatter.numberStyle = .decimal
let number = formatter.number(from: "9,999.99")
货币格式
let usLocale = Locale(identifier: "en_US")
let frenchLocale = Locale(identifier: "fr_FR")
let germanLocale = Locale(identifier: "de_DE")
let englishUKLocale = Locale(identifier: "en_GB") // United Kingdom
formatter.numberStyle = .currency
formatter.locale = usLocale
let usCurrency = formatter.number(from: "$9,999.99")
formatter.locale = frenchLocale
let frenchCurrency = formatter.number(from: "9999,99€")
// Note: "9 999,99€" fails with grouping separator
// Note: "9999,99 €" fails with a space before the €
formatter.locale = germanLocale
let germanCurrency = formatter.number(from: "9999,99€")
// Note: "9.999,99€" fails with grouping separator
formatter.locale = englishUKLocale
let englishUKCurrency = formatter.number(from: "£9,999.99")
在我的博客文章上了解更多有关将String转换为Double类型(和货币)的信息。
斯威夫特2更新
有新failable初始化,允许你这样做的更地道和安全的方式(如许多答案都注意到,因为它对于非数值返回0的NSString的双重价值也不是很安全的。这意味着,doubleValue
中"foo"
和"0"
是相同。)
let myDouble = Double(myString)
这将返回一个可选参数,因此,在传递将返回0的"foo"
位置的情况下doubleValue
,失败的初始化器将返回nil
。您可以使用guard
,if-let
或map
处理Optional<Double>
原始帖子: 您不需要像接受的答案所建议的那样使用NSString构造函数。您可以像这样简单地桥接它:
(swiftString as NSString).doubleValue
- [NSString doubleValue]
是Double
在迅速为并列于Double?
(Optional<Double>
)。这与Swift String函数不同,toInt()
后者Int?
在文档中返回并声明“仅接受与正则表达式“ [-+]?[0-9] +”匹配的字符串”。
.toInt()
会更好。但是,这更是对如何做完全相同的事情的答案,但是在Swift中。
Double.init?(_ text: String)
现在有可用的故障初始化程序。
对于更多Swift的感觉,使用NSFormatter()
避免转换为NSString
,并nil
在字符串不包含Double
值时返回(例如“ test”将不返回0.0
)。
let double = NSNumberFormatter().numberFromString(myString)?.doubleValue
另外,扩展Swift的String
类型:
extension String {
func toDouble() -> Double? {
return NumberFormatter().number(from: self)?.doubleValue
}
}
并像这样使用它toInt()
:
var myString = "4.2"
var myDouble = myString.toDouble()
这将返回一个Double?
必须解开的可选内容。
强制展开:
println("The value is \(myDouble!)") // prints: The value is 4.2
或带有if let语句:
if let myDouble = myDouble {
println("The value is \(myDouble)") // prints: The value is 4.2
}
更新: 对于本地化,将语言环境应用于NSFormatter非常容易,如下所示:
let formatter = NSNumberFormatter()
formatter.locale = NSLocale(localeIdentifier: "fr_FR")
let double = formatter.numberFromString("100,25")
最后,NSNumberFormatterCurrencyStyle
如果您正在使用字符串包含货币符号的货币,则可以在格式化程序上使用。
这里的另一个选择是将其转换为an NSString
并使用它:
let string = NSString(string: mySwiftString)
string.doubleValue
(swiftString as NSString).doubleValue
这是一个扩展方法,使您可以简单地在Swift字符串上调用doubleValue()并获得双精度返回(示例输出优先)
println("543.29".doubleValue())
println("543".doubleValue())
println(".29".doubleValue())
println("0.29".doubleValue())
println("-543.29".doubleValue())
println("-543".doubleValue())
println("-.29".doubleValue())
println("-0.29".doubleValue())
//prints
543.29
543.0
0.29
0.29
-543.29
-543.0
-0.29
-0.29
这是扩展方法:
extension String {
func doubleValue() -> Double
{
let minusAscii: UInt8 = 45
let dotAscii: UInt8 = 46
let zeroAscii: UInt8 = 48
var res = 0.0
let ascii = self.utf8
var whole = [Double]()
var current = ascii.startIndex
let negative = current != ascii.endIndex && ascii[current] == minusAscii
if (negative)
{
current = current.successor()
}
while current != ascii.endIndex && ascii[current] != dotAscii
{
whole.append(Double(ascii[current] - zeroAscii))
current = current.successor()
}
//whole number
var factor: Double = 1
for var i = countElements(whole) - 1; i >= 0; i--
{
res += Double(whole[i]) * factor
factor *= 10
}
//mantissa
if current != ascii.endIndex
{
factor = 0.1
current = current.successor()
while current != ascii.endIndex
{
res += Double(ascii[current] - zeroAscii) * factor
factor *= 0.1
current = current.successor()
}
}
if (negative)
{
res *= -1;
}
return res
}
}
没有错误检查,但是可以根据需要添加它。
从Swift 1.1开始,您可以直接传递String
给const char *
parameter。
import Foundation
let str = "123.4567"
let num = atof(str) // -> 123.4567
atof("123.4567fubar") // -> 123.4567
如果您不喜欢弃用的话atof
:
strtod("765.4321", nil) // -> 765.4321
一个警告:转换行为不同于NSString.doubleValue
。
atof
并strtod
接受带0x
前缀的十六进制字符串:
atof("0xffp-2") // -> 63.75
atof("12.3456e+2") // -> 1,234.56
atof("nan") // -> (not a number)
atof("inf") // -> (+infinity)
如果您更喜欢.doubleValue
行为,我们仍然可以使用CFString
桥接:
let str = "0xff"
atof(str) // -> 255.0
strtod(str, nil) // -> 255.0
CFStringGetDoubleValue(str) // -> 0.0
(str as NSString).doubleValue // -> 0.0
NSString
。
在Swift 2.0中,最好的方法是避免像Objective-C开发人员那样思考。因此,您不应“将字符串转换为双精度”,而应“从字符串初始化双精度”。此处的Apple文档:https : //developer.apple.com/library/ios//documentation/Swift/Reference/Swift_Double_Structure/index.html#//apple_ref/swift/structctr/Double/s : FSdcFMSdFSSGSqSd_
这是一个可选的init,因此您可以使用nil合并运算符(??)设置默认值。例:
let myDouble = Double("1.1") ?? 0.0
Double.init?(_ text: String)
在Swift 2.0中可用。你应该提这个。此处的其他答案不是因为人们像Objective-C开发人员那样思考,而是因为此初始化程序较早之前不可用。
在SWIFT 3上,您可以使用:
if let myDouble = NumberFormatter().number(from: yourString)?.doubleValue {
print("My double: \(myDouble)")
}
注意:-如果字符串中包含数字以外的任何字符或与语言环境相称的组或小数点分隔符,则解析将失败。-字符串中的任何前导或尾随空格分隔符都将被忽略。例如,字符串“ 5”,“ 5”和“ 5”都产生数字5。
摘自文档:https : //developer.apple.com/reference/foundation/numberformatter/1408845-number
试试这个:
var myDouble = myString.bridgeToObjectiveC().doubleValue
println(myDouble)
注意
已在Beta 5中删除。这不再有效吗?
这是基于@Ryu的答案
只要您身处一个以圆点作为分隔符的国家,他的解决方案就很棒。默认情况下,NSNumberFormatter
使用设备区域设置。因此,如果数字使用点作为分隔符(通常是这种情况),则在所有使用逗号作为默认分隔符的国家(包括法国,如@PeterK。),此操作将失败。将此NSNumberFormatter的语言环境设置为US,从而使用点作为分隔符替换该行
return NSNumberFormatter().numberFromString(self)?.doubleValue
与
let numberFormatter = NSNumberFormatter()
numberFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
return numberFormatter.numberFromString(self)?.doubleValue
因此,完整的代码变为
extension String {
func toDouble() -> Double? {
let numberFormatter = NSNumberFormatter()
numberFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
return numberFormatter.numberFromString(self)?.doubleValue
}
}
要使用此功能,只需致电 "Your text goes here".toDouble()
这将返回一个可选 Double?
正如@Ryu提到的,您可以强制打开:
println("The value is \(myDouble!)") // prints: The value is 4.2
或使用以下if let
语句:
if let myDouble = myDouble {
println("The value is \(myDouble)") // prints: The value is 4.2
}
NumberFormatter().number(from: myString)?.doubleValue
斯威夫特:4和5
可能有两种方法可以做到这一点:
字符串->整数->双精度:
let strNumber = "314"
if let intFromString = Int(strNumber){
let dobleFromInt = Double(intFromString)
print(dobleFromInt)
}
字符串-> NSString->双精度
let strNumber1 = "314"
let NSstringFromString = NSString(string: strNumber1)
let doubleFromNSString = NSstringFromString.doubleValue
print(doubleFromNSString)
根据您的代码需求随时使用它。
1。
let strswift = "12"
let double = (strswift as NSString).doubleValue
2。
var strswift= "10.6"
var double : Double = NSString(string: strswift).doubleValue
可能对您有帮助。
如前所述,实现此目标的最佳方法是直接投射:
(myString as NSString).doubleValue
在此基础上,您可以制作一个漂亮的本机Swift String扩展:
extension String {
var doubleValue: Double {
return (self as NSString).doubleValue
}
}
这使您可以直接使用:
myString.doubleValue
它将为您执行转换。如果Apple确实doubleValue
向本地String 添加了a ,则只需删除扩展名,其余代码将自动编译!
具有可选语言环境的扩展
斯威夫特2.2
extension String {
func toDouble(locale: NSLocale? = nil) -> Double? {
let formatter = NSNumberFormatter()
if let locale = locale {
formatter.locale = locale
}
return formatter.numberFromString(self)?.doubleValue
}
}
斯威夫特3.1
extension String {
func toDouble(_ locale: Locale) -> Double {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.locale = locale
formatter.usesGroupingSeparator = true
if let result = formatter.number(from: self)?.doubleValue {
return result
} else {
return 0
}
}
}
斯威夫特4
extension String {
func toDouble() -> Double {
let nsString = self as NSString
return nsString.doubleValue
}
}
什么也可以:
// Init default Double variable
var scanned: Double()
let scanner = NSScanner(string: "String to Scan")
scanner.scanDouble(&scanned)
// scanned has now the scanned value if something was found.
在Swift 2.0中使用此代码
let strWithFloat = "78.65"
let floatFromString = Double(strWithFloat)
Scanner
在某些情况下使用是从字符串中提取数字的一种非常方便的方法。它几乎与NumberFormatter
解码和处理不同数字格式和区域设置一样强大。它可以提取具有不同小数点和组分隔符的数字和货币。
import Foundation
// The code below includes manual fix for whitespaces (for French case)
let strings = ["en_US": "My salary is $9,999.99",
"fr_FR": "Mon salaire est 9 999,99€",
"de_DE": "Mein Gehalt ist 9999,99€",
"en_GB": "My salary is £9,999.99" ]
// Just for referce
let allPossibleDecimalSeparators = Set(Locale.availableIdentifiers.compactMap({ Locale(identifier: $0).decimalSeparator}))
print(allPossibleDecimalSeparators)
for str in strings {
let locale = Locale(identifier: str.key)
let valStr = str.value.filter{!($0.isWhitespace || $0 == Character(locale.groupingSeparator ?? ""))}
print("Value String", valStr)
let sc = Scanner(string: valStr)
// we could do this more reliably with `filter` as well
sc.charactersToBeSkipped = CharacterSet.decimalDigits.inverted
sc.locale = locale
print("Locale \(locale.identifier) grouping separator: |\(locale.groupingSeparator ?? "")| . Decimal separator: \(locale.decimalSeparator ?? "")")
while !(sc.isAtEnd) {
if let val = sc.scanDouble() {
print(val)
}
}
}
但是,分隔符存在一些问题,可以将其视为字定界符。
// This doesn't work. `Scanner` just ignores grouping separators because scanner tends to seek for multiple values
// It just refuses to ignore spaces or commas for example.
let strings = ["en_US": "$9,999.99", "fr_FR": "9999,99€", "de_DE": "9999,99€", "en_GB": "£9,999.99" ]
for str in strings {
let locale = Locale(identifier: str.key)
let sc = Scanner(string: str.value)
sc.charactersToBeSkipped = CharacterSet.decimalDigits.inverted.union(CharacterSet(charactersIn: locale.groupingSeparator ?? ""))
sc.locale = locale
print("Locale \(locale.identifier) grouping separator: \(locale.groupingSeparator ?? "") . Decimal separator: \(locale.decimalSeparator ?? "")")
while !(sc.isAtEnd) {
if let val = sc.scanDouble() {
print(val)
}
}
}
// sc.scanDouble(representation: Scanner.NumberRepresentation) could help if there were .currency case
自动检测语言环境没有问题。请注意,法语语言环境中的groupingSeparator字符串“ Mon salaire est 9 999,99€”不是空格,尽管它可以完全按空格显示(此处不是)。这就是为什么下面的代码可以正常工作而!$0.isWhitespace
不会过滤掉字符的原因。
let stringsArr = ["My salary is $9,999.99",
"Mon salaire est 9 999,99€",
"Mein Gehalt ist 9.999,99€",
"My salary is £9,999.99" ]
let tagger = NSLinguisticTagger(tagSchemes: [.language], options: Int(NSLinguisticTagger.Options.init().rawValue))
for str in stringsArr {
tagger.string = str
let locale = Locale(identifier: tagger.dominantLanguage ?? "en")
let valStr = str.filter{!($0 == Character(locale.groupingSeparator ?? ""))}
print("Value String", valStr)
let sc = Scanner(string: valStr)
// we could do this more reliably with `filter` as well
sc.charactersToBeSkipped = CharacterSet.decimalDigits.inverted
sc.locale = locale
print("Locale \(locale.identifier) grouping separator: |\(locale.groupingSeparator ?? "")| . Decimal separator: \(locale.decimalSeparator ?? "")")
while !(sc.isAtEnd) {
if let val = sc.scanDouble() {
print(val)
}
}
}
// Also will fail if groupingSeparator == decimalSeparator (but don't think it's possible)
我的问题是逗号,所以我这样解决:
extension String {
var doubleValue: Double {
return Double((self.replacingOccurrences(of: ",", with: ".") as NSString).doubleValue)
}
}
我们可以使用将由myString.doubleValue获得的CDouble值