Swift - 如何将String转换为Double

ohy*_*yes 229 swift

我正在尝试用快速语言编写BMI程序.我遇到了这个问题:如何将String转换为Double?

在Objective-C中,我可以这样做:

double myDouble = [myString doubleValue];

但是如何在Swift语言中实现这一目标呢?

Jar*_*sen 272

斯威夫特2更新 有新failable初始化,允许你这样做的更地道和安全的方式(尽可能多的答案已经注意到,的NSString的双重价值也不是很安全的,因为它的非数值返回0.这意味着,doubleValue"foo""0"是相同.)

let myDouble = Double(myString)
Run Code Online (Sandbox Code Playgroud)

这会返回一个可选项,因此在传入返回0的情况下"foo",doubleValue可以返回可用的初始化程序nil.您可以使用guard,if-letmap处理Optional<Double>

原帖: 您不需要像接受的答案建议那样使用NSString构造函数.您可以像这样简单地桥接它:

(swiftString as NSString).doubleValue
Run Code Online (Sandbox Code Playgroud)

  • Ohai,Jarsen.这种方法的一个缺点是,如果字符串不是有效的双精度,它将不会失败.相反,你只会得到0.0.也就是说,` - [NSString doubleValue]`的结果是swift中的`Double`和'Double?`(`Optional <Double>`).这与Swift String函数`toInt()`不同,它返回`Int?`并在文档中声明它"...接受与正则表达式匹配的字符串"[ - +]?[0-9] +"只要." (5认同)
  • 在Swift 2.0中,现在可以使用`Double.init?(_ text:String)`可用的初始化程序. (5认同)
  • 实际上这听起来像一首伟大的诗!让我的双浮,我的绳子,我的爱,我的珍贵...... (3认同)
  • 这不是最好的方法.它将失败,具体取决于小数分隔符."."会好起来的.但不是','.NSNumberFormatter将支持当前本地化中使用的小数分隔符. (3认同)

Pau*_*olt 172

Swift 4.2+ String to Double

您应该使用新类型初始值设定项在String和数字类型(Double,Float,Int)之间进行转换.它将返回一个Optional类型(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
Run Code Online (Sandbox Code Playgroud)

使用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!)")
}
Run Code Online (Sandbox Code Playgroud)

您可以使用NumberFormatter该类转换格式化的数字和货币.

let formatter = NumberFormatter()
formatter.locale = Locale.current // USA: Locale(identifier: "en_US")
formatter.numberStyle = .decimal
let number = formatter.number(from: "9,999.99")
Run Code Online (Sandbox Code Playgroud)

货币格式

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")
Run Code Online (Sandbox Code Playgroud)

在我关于将String转换为Double类型(和货币)的博客文章中阅读更多内容.

  • 另一个问题是它不支持除1,000.00之外的其他语言环境中的数字,如果你使用其他格式如1 000,00它会在结尾处截断2位小数.至少这是Objective-C发生的事情. - 根据Apple文档:(它们不支持区域设置)以下便捷方法都跳过初始空格字符(whitespaceSet)并忽略尾随字符.它们不是区域设置感知的.NSScanner或NSNumberFormatter可用于更强大且可识别区域设置的数字解析. (2认同)

Ryu*_*X51 71

对于更多Swift的感觉,使用NSFormatter()避免强制转换NSString,并nil在字符串不包含Double值时返回(例如"test"将不返回0.0).

let double = NSNumberFormatter().numberFromString(myString)?.doubleValue
Run Code Online (Sandbox Code Playgroud)

或者,扩展Swift的String类型:

extension String {
    func toDouble() -> Double? {
        return NSNumberFormatter().numberFromString(self)?.doubleValue
    }
}
Run Code Online (Sandbox Code Playgroud)

并使用它像toInt():

var myString = "4.2"
var myDouble = myString.toDouble()
Run Code Online (Sandbox Code Playgroud)

这将返回一个Double?必须解包的可选项.

强制解包:

println("The value is \(myDouble!)") // prints: The value is 4.2
Run Code Online (Sandbox Code Playgroud)

或者使用if let语句:

if let myDouble = myDouble {
    println("The value is \(myDouble)") // prints: The value is 4.2
}
Run Code Online (Sandbox Code Playgroud)

更新: 对于本地化,将区域设置应用于NSFormatter非常容易,如下所示:

let formatter = NSNumberFormatter()
formatter.locale = NSLocale(localeIdentifier: "fr_FR")
let double = formatter.numberFromString("100,25")
Run Code Online (Sandbox Code Playgroud)

最后,NSNumberFormatterCurrencyStyle如果您使用的字符串包含货币符号,则可以在格式化程序上使用.

  • 实际上,使用NSNumberFormatter()的优点是,如果字符串包含不构成double的字符,则numberFromString:方法将返回nil.在NSString上使用doubleValue的问题是它总是返回一个double(例如0.0表示"test"),无论如何.因此,如果你正在处理所有类型的字符串,并且你想测试字符串是否只是一个双字符,没有其他字符,使用NSNumberFormatter是可行的方法. (12认同)
  • 法语失败了. (4认同)
  • 这是一个很好的解决方案,但仅使用此代码在使用逗号作为分隔符的国家/地区(包括提到的@PeterK 的法国)不起作用。我尝试用解决方案写一条评论,但它太长了,所以我不得不把它作为一个答案。给你:[修改后的解决方案](http://stackoverflow.com/a/31432010/1329733) (2认同)

Kei*_*ley 53

这里的另一个选择是将其转换为NSString并使用:

let string = NSString(string: mySwiftString)
string.doubleValue
Run Code Online (Sandbox Code Playgroud)

  • 我希望有一个更好的方法来做到这一点.例如,我怎么知道解析是否失败. (13认同)
  • @RyanHoffman不幸的是,NSString doubleValue合同从未提供任何相关内容.如果字符串没有以溢出/下溢的数字,HUGE_VAL和-HUGE_VAL的有效表示开头,那么你得到的只是0.0.如果你想知道为什么解析失败,我相信你需要研究NSNumberFormatter,它旨在以更强大的方式处理数字/字符串转换. (2认同)
  • 有一种更简洁的方法来做到这一点.请参阅下面的答案. (2认同)
  • 我已经链接到下面的其他答案.希望@ohyes会在某个时刻回来并将其标记为正确的答案. (2认同)

Mil*_*ith 24

这是一个扩展方法,允许您简单地在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
Run Code Online (Sandbox Code Playgroud)

这是扩展方法:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

没有错误检查,但您可以在需要时添加它.

  • 这绝对是更好的选择.如果您阅读了快速书籍,我们鼓励扩展......这几乎是我想到的最后一个选择!:D我正尽力避免过桥,所以对此赞不绝口! (2认同)

rin*_*aro 19

从Swift 1.1开始,您可以直接传递Stringconst char *参数.

import Foundation

let str = "123.4567"
let num = atof(str) // -> 123.4567

atof("123.4567fubar") // -> 123.4567
Run Code Online (Sandbox Code Playgroud)

如果你不喜欢弃用atof:

strtod("765.4321", nil) // -> 765.4321
Run Code Online (Sandbox Code Playgroud)

一个警告:转换的行为不同于NSString.doubleValue.

atofstrtod接受0x前缀十六进制字符串:

atof("0xffp-2") // -> 63.75
atof("12.3456e+2") // -> 1,234.56
atof("nan") // -> (not a number)
atof("inf") // -> (+infinity)
Run Code Online (Sandbox Code Playgroud)

如果您更喜欢.doubleValue行为,我们仍然可以使用CFString桥接:

let str = "0xff"
atof(str)                      // -> 255.0
strtod(str, nil)               // -> 255.0
CFStringGetDoubleValue(str)    // -> 0.0
(str as NSString).doubleValue  // -> 0.0
Run Code Online (Sandbox Code Playgroud)


Too*_*oom 10

在Swift 2.0中,最好的方法是避免像Objective-C开发人员那样思考.因此,您不应该"将字符串转换为双精度",但您应该"从字符串初始化Double".Apple doc over here: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
Run Code Online (Sandbox Code Playgroud)


Jor*_*nez 10

SWIFT 3上,您可以使用:

if let myDouble = NumberFormatter().number(from: yourString)?.doubleValue {
   print("My double: \(myDouble)")
}
Run Code Online (Sandbox Code Playgroud)

注意: - 如果字符串包含除数字或区域设置相应的组或小数分隔符之外的任何字符,则解析将失败. - 忽略字符串中的任何前导或尾随空格分隔符.例如,字符串"5","5"和"5"都产生数字5.

摘自文档:https: //developer.apple.com/reference/foundation/numberformatter/1408845-number


Tom*_*obo 10

我还没有看到我正在寻找的答案.我只是在这里发帖,以防它可以帮助任何人.只有在您不需要特定格式时,此答案才有效.

斯威夫特3

extension String {
    var toDouble: Double {
        return Double(self) ?? 0.0
    }
}
Run Code Online (Sandbox Code Playgroud)


CW0*_*007 9

试试这个:

   var myDouble = myString.bridgeToObjectiveC().doubleValue
   println(myDouble)
Run Code Online (Sandbox Code Playgroud)

注意

在Beta 5中删除.这不再有效?


Jac*_*b R 7

这是基于@Ryu的答案

只要你在一个用点作为分隔符的国家,他的解决方案就很棒了.默认情况下NSNumberFormatter使用设备区域设置.因此,如果数字使用点作为分隔符(通常就是这种情况),则在使用逗号作为默认分隔符(包括法国为@PeterK.)的所有国家/地区都会失败.要将此NSNumberFormatter的区域设置设置为US,因此使用点作为分隔符替换该线

return NSNumberFormatter().numberFromString(self)?.doubleValue
Run Code Online (Sandbox Code Playgroud)

let numberFormatter = NSNumberFormatter()
numberFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
return numberFormatter.numberFromString(self)?.doubleValue
Run Code Online (Sandbox Code Playgroud)

因此完整的代码变成了

extension String {
    func toDouble() -> Double? {
        let numberFormatter = NSNumberFormatter()
        numberFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
        return numberFormatter.numberFromString(self)?.doubleValue
    }
}
Run Code Online (Sandbox Code Playgroud)

要使用它,只需打电话 "Your text goes here".toDouble()

这将返回一个可选项 Double?

正如@Ryu所说,你可以强行解包:

println("The value is \(myDouble!)") // prints: The value is 4.2
Run Code Online (Sandbox Code Playgroud)

或使用if let声明:

if let myDouble = myDouble {
    println("The value is \(myDouble)") // prints: The value is 4.2
}
Run Code Online (Sandbox Code Playgroud)


Vis*_*iya 6

斯威夫特 4.0

尝试这个

 let str:String = "111.11"
 let tempString = (str as NSString).doubleValue
 print("String:-",tempString)
Run Code Online (Sandbox Code Playgroud)


t4n*_*hpt 6

SWIFT 4

extension String {
    func toDouble() -> Double? {
        let numberFormatter = NumberFormatter()
        numberFormatter.locale = Locale(identifier: "en_US_POSIX")
        return numberFormatter.number(from: self)?.doubleValue
    }
}
Run Code Online (Sandbox Code Playgroud)


Abh*_*ore 6

斯威夫特:4 和 5

可能有两种方法可以做到这一点:

  1. 字符串 -> 整数 -> 双精度:

    let strNumber = "314"
    if let intFromString = Int(strNumber){
        let dobleFromInt = Double(intFromString)
        print(dobleFromInt)
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 字符串 -> NSString -> 双精度

    let strNumber1 = "314"
    let NSstringFromString = NSString(string: strNumber1)
    let doubleFromNSString = NSstringFromString.doubleValue
    print(doubleFromNSString)
    
    Run Code Online (Sandbox Code Playgroud)

根据您对代码的需要,随意使用它。


Mam*_*zur 5

请在操场上查看!

let sString = "236.86"

var dNumber = NSNumberFormatter().numberFromString(sString)
var nDouble = dNumber!
var eNumber = Double(nDouble) * 3.7
Run Code Online (Sandbox Code Playgroud)

顺便说一句,在我的Xcode中

.toDouble() - 不存在

.doubleValue从非数字字符串创建值0.0 ...


Fir*_*iro 5

正如已经指出的那样,实现这一目标的最佳方法是直接铸造:

(myString as NSString).doubleValue
Run Code Online (Sandbox Code Playgroud)

以此为基础,你可以制作一个漂亮的原生 Swift String 扩展:

extension String {
    var doubleValue: Double {
        return (self as NSString).doubleValue
    }
}
Run Code Online (Sandbox Code Playgroud)

这允许您直接使用:

myString.doubleValue
Run Code Online (Sandbox Code Playgroud)

哪个将为您执行铸造。如果 Apple 确实doubleValue向本机 String添加了 a ,您只需要删除扩展名,其余代码将自动编译正常!