簡體   English   中英

Swift - 如何將字符串轉換為雙精度

[英]Swift - How to convert String to Double

我正在嘗試用 swift 語言編寫一個 BMI 程序。 我遇到了這個問題:如何將 String 轉換為 Double?

在 Objective-C 中,我可以這樣做:

double myDouble = [myString doubleValue];

但是我怎樣才能用 Swift 語言實現這一點呢?

Swift 2 更新有新的可失敗初始化器,允許您以更慣用和安全的方式執行此操作(正如許多答案所指出的,NSString 的 double 值不是很安全,因為它對於非數字值返回 0。這意味着"foo"doubleValue "foo""0"是相同的。)

let myDouble = Double(myString)

這將返回一個可選值,因此在傳入"foo"類的情況下, doubleValue將返回 0,可失敗的初始化器將返回nil 您可以使用guardif-letmap來處理Optional<Double>

原帖:您不需要像接受的答案建議那樣使用 NSString 構造函數。 你可以像這樣簡單地橋接它:

(swiftString as NSString).doubleValue

Swift 4.2+ 字符串轉雙

您應該使用新的類型初始值設定項在字符串和數字類型(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")

在我的博客文章中閱讀有關將 String 轉換為 Double 類型(和貨幣)的更多信息

為了獲得更多的 Swift 感覺,使用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 非常容易,如下所示:

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

最后,如果您使用字符串包含貨幣符號的貨幣,您可以在格式化程序上使用NSNumberFormatterCurrencyStyle

這里的另一個選擇是將其轉換為NSString並使用它:

let string = NSString(string: mySwiftString)
string.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 *參數。

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

我還沒有看到我正在尋找的答案。 我只是在這里發布我的,以防它可以幫助任何人。 僅當您不需要特定格式時,此答案有效。

斯威夫特 3

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

在 Swift 2.0 中,最好的方法是避免像 Objective-C 開發人員那樣思考。 所以你不應該“將字符串轉換為雙精度”,而應該“從字符串初始化雙精度”。 蘋果文檔在這里: 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

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
}

快速 4

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

斯威夫特 4.0

嘗試這個

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

斯威夫特:4 和 5

可能有兩種方法可以做到這一點:

  1. 字符串 -> 整數 -> 雙精度:

     let strNumber = "314" if let intFromString = Int(strNumber){ let dobleFromInt = Double(intFromString) print(dobleFromInt) }
  2. 字符串 -> NSString -> 雙精度

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

根據您對代碼的需要,隨意使用它。

請在操場上檢查!

let sString = "236.86"

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

順便說一句,在我的 Xcode 中

.toDouble() - 不存在

.doubleValue 從非數字字符串創建值 0.0...

正如已經指出的那樣,實現這一目標的最佳方法是直接鑄造:

(myString as NSString).doubleValue

以此為基礎,你可以制作一個漂亮的原生 Swift String 擴展:

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

這允許您直接使用:

myString.doubleValue

哪個將為您執行鑄造。 如果 Apple 確實向本機 String 添加了doubleValue ,您只需要刪除擴展名,其余代碼將自動編譯正常!

1.

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

2.

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

可能對你有幫助。

斯威夫特 3

要清除,現在有一個默認方法:

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

它可以用於所有類。

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

, 等等。

帶有可選語言環境的擴展

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

或者你可以這樣做:

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

您可以使用StringEx 它使用字符串到數字的轉換來擴展String ,包括toDouble()

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

它驗證字符串,如果不能轉換為雙精度則失敗。

例子:

import StringEx

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

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

自動檢測語言環境沒有問題。 請注意,字符串 "Mon salaire est 9 999,99€" 中法語語言環境中的 groupingSeparator 不是空格,盡管它可能完全呈現為空格(這里不是)。 這就是為什么下面的代碼沒有過濾掉!$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"

我發現將擴展添加到 String 更具可讀性,如下所示:

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

然后你就可以寫你的代碼:

myDouble = myString.doubleValue

我的問題是逗號,所以我這樣解決:

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

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

我們可以使用將通過 myString.doubleValue 獲得的 CDouble 值

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM