回答:
Swift 4.2+文字列からダブルへ
String型と数値型(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型(および通貨)に変換する方法については、私のブログ投稿をご覧ください。
スウィフト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>
)。これは、ドキュメントで "...正規表現" [-+]?[0-9] + "のみに一致する文字列を受け入れる" toInt()
を返しInt?
、それを記述するSwift String関数とは異なります。 "
.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
文字列に通貨記号が含まれている通貨で作業している場合は、フォーマッタで使用できます。
ここでの別のオプションは、これをに変換して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
}
}
エラーチェックはありませんが、必要に応じて追加できます。
スウィフト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
ます。
atof
接頭辞付きの16進数文字列を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開発者のように考えることを避けることです。したがって、「文字列をDoubleに変換する」のではなく、「文字列からDoubleを初期化する」必要があります。こちらの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
これを試して
let str:String = "111.11"
let tempString = (str as NSString).doubleValue
print("String:-",tempString)
スウィフト:4および5
これを行うには、おそらく2つの方法があります。
文字列-> Int-> Double:
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)
コードの必要性に応じて、とにかくそれを使用してください。
すでに指摘したように、これを達成する最良の方法は直接キャストすることです:
(myString as NSString).doubleValue
これを基にして、滑らかなネイティブSwift String拡張機能を作成できます。
extension String {
var doubleValue: Double {
return (self as NSString).doubleValue
}
}
これにより、次のものを直接使用できます。
myString.doubleValue
どちらがキャストを実行します。AppleがをdoubleValue
ネイティブ文字列に追加する場合は、拡張機能を削除するだけで、残りのコードは自動的に正常にコンパイルされます。
オプションのロケールを持つ拡張
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
}
}
}
スウィフト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)
myString.doubleValueによって取得されるCDouble値を使用できます