簡體   English   中英

Swift 3 中的十進制到雙精度轉換

[英]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的主題。

NSDecimalNumberDecimal橋接

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 的解決方案是將DecimalNSNumber並從中創建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)

斯威夫特 5

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 中, DecimalNSDecimalNumber 這是 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.

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