Swift 3中的十进制到双精度转换

时间:2016-10-06 08:08:49

标签: ios swift migration type-conversion swift3

我正在将项目从 Swift 2.2 迁移到 Swift 3 ,并且我试图在可能的情况下摆脱旧的Cocoa数据类型。

我的问题在于:将NSDecimalNumber迁移到Decimal

我过去常常在 Swift 2.2 中将NSDecimalNumberDouble联系起来:

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 上的主题更多内容。

8 个答案:

答案 0 :(得分:11)

另一个适用于Swift 3的解决方案是将Decimal转换为NSNumber并从中创建Double

let someDouble = Double(someDecimal as NSNumber)

答案 1 :(得分:7)

NSDecimalNumberDecimal被桥接

  

Swift叠加到Foundation框架提供了Decimal   结构,桥接到NSDecimalNumber类。十进制   value类型提供与NSDecimalNumber相同的功能   引用类型,这两者可以在Swift代码中互换使用   与Objective-C API交互。这种行为与如何相似   Swift将标准字符串,数字和集合类型桥接到它们的   相应的基础课程。 Apple Docs

但与其他一些桥接类型一样,缺少某些元素。

要重新获得功能,您可以编写扩展程序:

extension Decimal {
    var doubleValue:Double {
        return NSDecimalNumber(decimal:self).doubleValue
    }
}

// implementation
let d = Decimal(floatLiteral: 10.65)
d.doubleValue

答案 2 :(得分:3)

Swift 3中的

Decimal不是NSDecimalNumber。它是NSDecimal,完全不同的类型。

您应该像以前一样继续使用NSDecimalNumber

答案 3 :(得分:2)

Swift 4

中有效的解决方案
let double = 3.14
let decimal = Decimal(double)
let doubleFromDecimal = NSDecimalNumber(decimal: decimal).doubleValue
print(doubleFromDecimal)

修改:不使用NSDecimalNumber / NSNumber

let double = 3.14
let decimal = Decimal(double)
if let doubleFromDecimal = Double(decimal.description){
    print(doubleFromDecimal)
}

答案 4 :(得分:1)

您应该使用as运算符将Swift类型转换为其 bridged 基础的Objective-C类型。因此,只需像这样使用as

let p = Decimal(1)
let q = (p as NSDecimalNumber).doubleValue

在Swift 4中,Decimal NSDecimalNumber。这是来自Xcode 10中Apple官方文档的引用。

  

重要

     

基金会框架的Swift叠加层提供了Decimal   结构,它桥接到NSDecimalNumber类。欲了解更多   有关值类型的信息,请参阅《使用Cocoa框架》中的   将Swift与Cocoa和Objective-C结合使用(Swift 4.1)。

没有NSDecimal了。 Swift 3中的NSDecimal类型令人困惑,但这似乎是一个错误。 不再混乱。

注意

我看到OP对Swift 4并不感兴趣,但我添加了这个答案,因为仅提及(过时的)Swift 3令我感到困惑。

答案 5 :(得分:0)

雨燕5

let doubleValue = Double(truncating: decimalValue as NSNumber)

答案 6 :(得分:0)

在Swift开源中,implementation实际上是在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)
    }
}

答案 7 :(得分:0)

对于 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