답변:
스위프트 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 형식 (및 통화)으로 변환하는 방법 에 대한 내 블로그 게시물 에서 자세한 내용을 읽으십시오 .
스위프트 2 업데이트
가 많은 답변이 언급 한대로가 아닌 숫자 값에 0을 반환하기 때문에,있는 NSString의 두 배 값이 매우 안전하지 않습니다 (더 관용적하고 안전한 방법으로이 작업을 수행 할 수 있도록 새로운 failable 이니셜이 수단.있는 그 doubleValue
의 "foo"
와 "0"
있습니다 똑같다.)
let myDouble = Double(myString)
이것은 선택 사항을 반환하므로 0을 반환 한 "foo"
위치를 전달하는 경우 doubleValue
실패 가능한 초기화 프로그램이 반환 nil
됩니다. 당신은을 사용할 수 있습니다 guard
, if-let
또는 map
을 처리하는Optional<Double>
Original Post : 승인 된 제안과 같이 NSString 생성자를 사용할 필요는 없습니다. 다음과 같이 간단히 브리지 할 수 있습니다.
(swiftString as NSString).doubleValue
- [NSString doubleValue]
인 Double
에 나란히 놓이는으로 기민한에 Double?
( Optional<Double>
). 이것은 문서에서 "...- 정규식"[-+]? [0-9] + "와만 일치하는 문자열 만 허용합니다." toInt()
를 반환 Int?
하고 나타내는 Swift String 함수 와 다릅니다 .
.toInt()
것이 좋습니다. 그러나 이것은 Swift에서 정확히 똑같은 일을하는 방법에 대한 답변이었습니다.
Double.init?(_ text: String)
이제 사용할 수있는 실패 가능한 이니셜 라이저가 있습니다.
좀 더 스위프트 느낌의 경우을 사용 NSFormatter()
하면 캐스팅을 피하고 문자열에 값이 포함되지 않은 경우 NSString
반환 합니다 (예 : "test"는 반환되지 않음 ).nil
Double
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 ()를 호출하고 double back을 얻는 확장 메소드입니다 (예제 출력 우선)
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
및 strtod
동의를 0x
앞에 둔 16 진수 문자열을 :
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 개발자처럼 생각하지 않는 것입니다. 따라서 "String을 Double로 변환"하지 말고 "String에서 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)
노트
베타 5에서 제거되었습니다. 더 이상 작동하지 않습니까?
이것은 @Ryu의 답변을 기반으로합니다.
점이 분리 자로 사용되는 국가에있는 한 그의 솔루션은 훌륭합니다. 기본적으로 NSNumberFormatter
장치 로캘이 사용됩니다. 따라서 숫자가 점을 구분 기호로 사용하는 경우 (보통 @PeterK.와 같이 프랑스 포함) 기본 구분 기호로 쉼표가 사용되는 모든 국가에서 이는 실패합니다. 이 NSNumberFormatter의 로캘을 미국으로 설정하고 구분 기호로 점을 사용하여 선을 바꾸려면
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
스위프트 : 4와 5
이를 수행하는 두 가지 방법이 있습니다.
문자열-> 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
기본 문자열 에 a 를 추가 하면 확장을 제거하면 나머지 코드가 자동으로 올바르게 컴파일됩니다!
선택적 로케일이있는 확장
스위프트 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
}
}
}
작동하는 것 :
// 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.
사용 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 값을 사용할 수 있습니다