[英]Decimal to Double conversion in Swift 3
我正在將一個項目從Swift 2.2遷移到Swift 3 ,並且我試圖在可能的情況下擺脫舊的 Cocoa 數據類型。
我的問題在這里:將NSDecimalNumber
遷移到Decimal
。
我曾經在Swift 2.2 中以兩種方式將NSDecimalNumber
橋接到Double
:
let double = 3.14
let decimalNumber = NSDecimalNumber(value: double)
let doubleFromDecimal = decimalNumber.doubleValue
現在,切換到Swift 3 :
let double = 3.14
let decimal = Decimal(double)
let doubleFromDecimal = ???
decimal.doubleValue
不存在,也不存在Double(decimal)
,甚至不是decimal as Double
......我想出的唯一黑客是:
let doubleFromDecimal = (decimal as NSDecimalNumber).doubleValue
但是試圖擺脫NSDecimalNumber
並且不得不偶爾使用它是完全愚蠢的......
好吧,要么我錯過了一些明顯的東西,請原諒浪費你的時間,要么有一個漏洞需要解決,在我看來......
預先感謝您的幫助。
編輯:沒有更多關於Swift 4的主題。
編輯:沒有更多關於Swift 5的主題。
NSDecimalNumber
和Decimal
橋接
Swift 覆蓋到 Foundation 框架提供了 Decimal 結構,它連接到 NSDecimalNumber 類。 Decimal 值類型提供與 NSDecimalNumber 引用類型相同的功能,並且兩者可以在與 Objective-C API 交互的 Swift 代碼中互換使用。 這種行為類似於 Swift 將標准字符串、數字和集合類型橋接到它們相應的 Foundation 類的方式。 蘋果文檔
但與其他一些橋接類型一樣,缺少某些元素。
要重新獲得功能,您可以編寫擴展程序:
extension Decimal {
var doubleValue:Double {
return NSDecimalNumber(decimal:self).doubleValue
}
}
// implementation
let d = Decimal(floatLiteral: 10.65)
d.doubleValue
另一個適用於 Swift 3 的解決方案是將Decimal
為NSNumber
並從中創建Double
。
let someDouble = Double(someDecimal as NSNumber)
從 Swift 4.2 開始,您需要:
let someDouble = Double(truncating: someDecimal as NSNumber)
適用於Swift 4 的解決方案
let double = 3.14
let decimal = Decimal(double)
let doubleFromDecimal = NSDecimalNumber(decimal: decimal).doubleValue
print(doubleFromDecimal)
let doubleValue = Double(truncating: decimalValue as NSNumber)
Swift 3 中的Decimal
不是NSDecimalNumber
。 它是NSDecimal
,完全不同的類型。
您應該像以前一樣繼續使用NSDecimalNumber
。
您應該使用as
運算符將 Swift 類型轉換為其橋接的底層 Objective-C 類型。 因此,只要使用as
是這樣的。
let p = Decimal(1)
let q = (p as NSDecimalNumber).doubleValue
在 Swift 4 中, Decimal
是NSDecimalNumber
。 這是 Xcode 10 中 Apple 官方文檔的引用。
重要的
Swift 覆蓋到 Foundation 框架提供了
Decimal
結構,它連接到NSDecimalNumber
類。 有關值類型的更多信息,請參閱使用 Swift 與 Cocoa 和 Objective-C (Swift 4.1) 中的使用 Cocoa 框架。
沒有NSDecimal
了。 Swift 3 中有令人困惑的NSDecimal
類型,但這似乎是一個錯誤。 沒有更多的困惑。
我看到 OP 對 Swift 4 不感興趣,但我添加了這個答案,因為只提到(過時的)Swift 3 讓我感到困惑。
在 Swift 開源中, 實現實際上是在Decimal.swift
完成的,但它是私有的。 您可以從那里重新使用代碼。
extension Double {
@inlinable init(_ other: Decimal) {
if other._length == 0 {
self.init(other._isNegative == 1 ? Double.nan : 0)
return
}
var d: Double = 0.0
for idx in (0..<min(other._length, 8)).reversed() {
var m: Double
switch idx {
case 0: m = Double(other._mantissa.0)
break
case 1: m = Double(other._mantissa.1)
break
case 2: m = Double(other._mantissa.2)
break
case 3: m = Double(other._mantissa.3)
break
case 4: m = Double(other._mantissa.4)
break
case 5: m = Double(other._mantissa.5)
break
case 6: m = Double(other._mantissa.6)
break
case 7: m = Double(other._mantissa.7)
break
default: break
}
d = d * 65536 + m
}
if other._exponent < 0 {
for _ in other._exponent..<0 {
d /= 10.0
}
} else {
for _ in 0..<other._exponent {
d *= 10.0
}
}
self.init(other._isNegative != 0 ? -d : d)
}
}
對於 swift 5,函數是
let doubleValue = Double(truncating: decimalValue as NSNumber)
下面的例子,顯示了浮點數。
let decimalValue: Decimal = 3.14159
let doubleValue = Double(truncating: decimalValue as NSNumber)
print(String(format: "%.3f", doubleValue)) // 3.142
print(String(format: "%.4f", doubleValue)) // 3.1416
print(String(format: "%.5f", doubleValue)) // 3.14159
print(String(format: "%.6f", doubleValue)) // 3.141590
print(String(format: "%.7f", doubleValue)) // 3.1415900
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.