Swift - 如何将String转换为Double

时间:2014-06-04 07:36:42

标签: swift

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

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

double myDouble = [myString doubleValue];

但是我如何用Swift语言实现这个目标呢?

30 个答案:

答案 0 :(得分:266)

Swift 2更新 有一些新的可用的初始化器允许你以更惯用和安全的方式执行此操作(正如许多答案所指出的,NSString的双值不是很安全,因为它对非数值返回0。这意味着{{ 1 {} doubleValue"foo"是相同的。)

"0"

这会返回一个可选项,因此在传递let myDouble = Double(myString) "foo"将返回0的情况下,可用的初始化程序将返回doubleValue。您可以使用nilguardif-let来处理map

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

Optional<Double>

答案 1 :(得分:132)

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

展开值以使用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")

详细了解我的blog post about converting String to Double types (and currency)

答案 2 :(得分:71)

对于更多Swift的感觉,使用NSFormatter()可以避免转换为NSString,并在字符串不包含nil值时返回Double(例如“test”)不会返回0.0)。

let double = NSNumberFormatter().numberFromString(myString)?.doubleValue

或者,扩展Swift的String类型:

extension String {
    func toDouble() -> Double? {
        return NSNumberFormatter().numberFromString(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

答案 3 :(得分:53)

此处的另一个选项是将其转换为NSString并使用:

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

答案 4 :(得分: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

这是扩展方法:

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

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

答案 5 :(得分:19)

从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

答案 6 :(得分:10)

在Swift 2.0中,最好的方法是避免像Objective-C开发人员一样思考。因此,您不应该“将字符串转换为双精度”,但您应该“从字符串初始化Double”。 Apple doc在这里: 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

答案 7 :(得分:9)

试试这个:

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

注意

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

答案 8 :(得分:9)

SWIFT 3 上,您可以使用:

(function(){
    'use strict';

    angular
        .module('hsAdmin.users')
        .factory('UsersService', UsersService);

    UsersService.$inject = ['fb', '$firebaseArray', '$firebaseObject','$q','$rootScope'];

    function UsersService(fb, $firebaseArray, $firebaseObject,$q,$rootScope){
        var service = {
            GetUsers:GetUsers
        };
        return service;


        function GetUsers(){
            var query = fb.child('/users');
            return $firebaseArray(query).$loaded();
        }

        function GetUserById(id){
            var query = fb.child('/users/' + id);
            return $firebaseObject(query).$loaded();
        }
    }
})();

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

取自文件: https://developer.apple.com/reference/foundation/numberformatter/1408845-number

答案 9 :(得分:8)

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

Swift 3

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

答案 10 :(得分:7)

这是建立在@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
}

答案 11 :(得分:5)

请在操场上查看!

let sString = "236.86"

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

顺便说一下我的Xcode

.toDouble() - 不存在

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

答案 12 :(得分:5)

SWIFT 4

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

答案 13 :(得分:4)

1

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

2

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

可能对你有帮助。

答案 14 :(得分:4)

Swift 4.0

试试这个

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

答案 15 :(得分:4)

SWIFT 3

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

import 'react-native' import React from 'react' import renderer from 'react-test-renderer' jest.mock('react-native-intercom', () => 'Intercom') jest.mock('react-native-push-notification', () => { return { configure: () => 'none' } }) jest.mock('react-native-udp') jest.mock('react-native-uuid') jest.mock('react-native-localization') jest.mock('react-native-google-signin', () => 'GoogleSignin') import { Login } from '../' describe('Containers', () => { it('renders component correctly', () => { const tree = renderer.create( <Login /> ).toJSON() expect(tree).toMatchSnapshot() }) }) 课程的

public init?(_ text: String)

它可以用于所有类。

Double let c = Double("-1.0") let f = Double("0x1c.6")等等。

答案 16 :(得分:3)

正如已经指出的,实现这一目标的最佳方法是直接投射:

(myString as NSString).doubleValue

从中构建,您可以制作一个灵活的原生Swift String扩展名:

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

这允许您直接使用:

myString.doubleValue

将为您执行演员表演。如果Apple确实在本地String中添加了doubleValue,您只需要删除扩展名,其余代码将自动编译好!

答案 17 :(得分:3)

使用可选语言环境扩展

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

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

答案 18 :(得分:1)

快捷键4

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

答案 19 :(得分:1)

斯威夫特: - 4

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

  1. 字符串 - &gt; Int - &gt;双:

    let strNumber = "314"
    let intFromString = Int(strNumber)
    let dobleFromInt = Double(intFromString!)
    print(dobleFromInt)
    
  2. 字符串 - &gt; NSString - &gt;双

    let strNumber = "314"
    let NSstringFromString = NSString(string: strNumber as! NSString)
    let doubleFromNSString = NSstringFromString.doubleValue
    print(doubleFromNSString)
    
  3. 根据您的需要,无论如何都要使用它。

答案 20 :(得分:1)

您可以使用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")
}

答案 21 :(得分:1)

或者你可以这样做:

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

答案 22 :(得分:0)

在某些情况下,使用SseEmitter是从字符串中提取数字的一种非常方便的方法。在解码和处理不同的数字格式和区域设置时,它几乎与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)
        }

    }
}

自动检测语言环境没有问题。请注意,字符串“ Mon salaire est 9999,99€”在法语语言环境中的groupingSeparator不是空格,尽管它可以完全像空格一样呈现(此处不是)。这就是为什么下面的代码可以正常工作而不会过滤掉// 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 个字符的原因。

!$0.isWhitespace

答案 23 :(得分:0)

如果字符串包含其他字符,例如:"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"

答案 24 :(得分:0)

在Swift 2.0中使用此代码

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

答案 25 :(得分:0)

什么也有效:

// 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.

答案 26 :(得分:-1)

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

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

答案 27 :(得分:-1)

我发现在String中添加扩展名更具可读性,如下所示:

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

然后你就可以编写代码了:

myDouble = myString.doubleValue

答案 28 :(得分:-3)

var stringValue = "55"

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

答案 29 :(得分:-6)

我们可以使用将通过myString.doubleValue

获得的CDouble值