如何将字符串转换为双精度

我正在尝试用swift语言编写BMI程序。 我有这个问题:如何转换字符串为双精度?< / p >

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

double myDouble = [myString doubleValue];

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

375284 次浏览

试试这个:

   var myDouble = myString.bridgeToObjectiveC().doubleValue
println(myDouble)

请注意

在Beta 5中删除。这已经不管用了?

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

let string = NSString(string: mySwiftString)
string.doubleValue

下面是一个扩展方法,允许你简单地调用doubleValue()在一个Swift字符串上,并得到一个双返回(示例输出先来)

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
}
}

没有错误检查,但如果需要,可以添加它。

我们可以使用CDouble值,它将通过myString.doubleValue获得

或者你可以这样做:

var myDouble = Double((mySwiftString.text as NSString).doubleValue)

为了更敏捷一点,使用NSFormatter()避免强制转换为NSString,并在字符串不包含Double值时返回nil(例如。"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应用locale是非常容易的,如下所示

let formatter = NSNumberFormatter()
formatter.locale = NSLocale(localeIdentifier: "fr_FR")
let double = formatter.numberFromString("100,25")

最后,如果字符串中包含货币符号,则可以在格式化器上使用NSNumberFormatterCurrencyStyle

Swift 2 Update 有新的可失败的初始化器,允许你以更习惯和安全的方式来做这件事(正如许多答案所指出的,NSString的double值不是很安全,因为它对非数字值返回0。这意味着"foo""0"doubleValue是相同的)

let myDouble = Double(myString)

这将返回一个可选类型,因此在诸如传入"foo"doubleValue将返回0的情况下,可失败的初始化器将返回nil。你可以使用guardif-let,或map来处理Optional<Double>

< >强原函: 你不需要像接受的答案那样使用NSString构造函数。你可以像这样简单地桥接它:

(swiftString as NSString).doubleValue

你可以使用StringEx。它扩展了String的字符串到数字的转换,包括toDouble()

extension String {
func toDouble() -> Double?
}

它验证字符串,如果不能转换为double则失败。

例子:

import StringEx


let str = "123.45678"
if let num = str.toDouble() {
println("Number: \(num)")
} else {
println("Invalid string")
}

从Swift 1.1开始,你可以直接将String传递给const char *参数。

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

atofstrtod接受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
var stringValue = "55"


var convertToDouble = Double((stringValue as NSString).doubleValue)

1.

let strswift = "12"
let double = (strswift as NSString).doubleValue

2.

var strswift= "10.6"
var double : Double = NSString(string: strswift).doubleValue

也许这对你有帮助。

请到操场上检查!

let sString = "236.86"


var dNumber = NSNumberFormatter().numberFromString(sString)
var nDouble = dNumber!
var eNumber = Double(nDouble) * 3.7

顺便说一下,在我的Xcode中

.toDouble() -不存在

从非数值字符串中创建值0.0

如前所述,实现这一目标的最佳方法是直接铸造:

(myString as NSString).doubleValue

在此基础上,你可以创建一个流畅的本地Swift String扩展:

extension String {
var doubleValue: Double {
return (self as NSString).doubleValue
}
}

这允许你直接使用:

myString.doubleValue

它会帮你选角。如果苹果确实添加了一个doubleValue到本机字符串,你只需要删除扩展和你的其余代码将自动编译好!

这是基于@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
}

我发现更可读添加一个扩展字符串如下:

extension String {
var doubleValue: Double {
return (self as NSString).doubleValue
}
}

然后你就可以写代码了:

myDouble = myString.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中,最好的方法是避免像Objective-C开发人员那样思考。所以你不应该“将一个字符串转换为Double”,而应该“从一个字符串初始化一个Double”。苹果医生在这里: https://developer.apple.com/library/ios//documentation/Swift/Reference/Swift_Double_Structure/index.html#//apple_ref/swift/structctr/Double/s:FSdcFMSdFSSGSqSd_ < / p >

它是一个可选的init,所以你可以使用nil合并操作符(??)来设置默认值。例子:

let myDouble = Double("1.1") ?? 0.0

Swift 4.2+字符串到双

您应该使用新的类型初始化器在字符串和数值类型(Double, Float, Int)之间进行转换。它将返回一个可选类型(Double?),它将有正确的值,如果字符串不是数字,则为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类型(和货币)的博客文章

在Swift 2.0中使用此代码

let strWithFloat = "78.65"
let floatFromString = Double(strWithFloat)

具有可选区域设置的扩展

斯威夫特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
}
}
}

我的问题是逗号,所以我这样解决它:

extension String {
var doubleValue: Double {
return Double((self.replacingOccurrences(of: ",", with: ".") as NSString).doubleValue)
}
}

斯威夫特3

要清除,现在有一个默认的方法:

public init?(_ text: String)` of `Double` class.

它可以用于所有类。

let c = Double("-1.0")
let f = Double("0x1c.6")
let i = Double("inf")

等。

斯威夫特3上,你可以使用:

if let myDouble = NumberFormatter().number(from: yourString)?.doubleValue {
print("My double: \(myDouble)")
}
< p >注意: —如果字符串中包含除数字、适合区域设置的组或小数分隔符以外的任何字符,解析将失败。 —忽略字符串中任何开头或结尾的空格分隔符。例如,字符串" 5 "," 5 "和" 5 "都产生数字5

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

我还没有看到我一直在寻找的答案。 我只是把我的贴在这里,希望它能帮助到任何人。这个答案是有效的除非你不需要特定的格式

斯威夫特3

extension String {
var toDouble: Double {
return Double(self) ?? 0.0
}
}

斯威夫特4.0

试试这个

 let str:String = "111.11"
let tempString = (str as NSString).doubleValue
print("String:-",tempString)

斯威夫特4

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

斯威夫特:4和5

可能有两种方法:

  1. String -> Int -> Double:

    let strNumber = "314"
    if let intFromString = Int(strNumber){
    let dobleFromInt = Double(intFromString)
    print(dobleFromInt)
    }
    
  2. String -> NSString -> Double

    let strNumber1 = "314"
    let NSstringFromString = NSString(string: strNumber1)
    let doubleFromNSString = NSstringFromString.doubleValue
    print(doubleFromNSString)
    

Use it anyway you like according to you need of the code.

斯威夫特4

extension String {
func toDouble() -> Double {
let nsString = self as NSString
return nsString.doubleValue
}
}

在某些情况下使用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

自动检测语言环境是没有问题的。注意,grouingseparator在法语区域设置中的字符串“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)

在字符串包含其他字符的情况下,如:"27.8 °C""52.523553 kM""Total: 349.0"

这适用于Swift 4:

let anyString = "52.523553 kM"
let digitsCharacterSet = CharacterSet.init(charactersIn: "0123456789.")
let doubleResult = Double(anyString.components(separatedBy:digitsCharacterSet.inverted).joined())

谨慎!这不适用于包含多个.的字符串,如"27.8 °C 3.5 kM"