我正在将项目从 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 上的主题更多内容。
答案 0 :(得分:11)
另一个适用于Swift 3的解决方案是将Decimal
转换为NSNumber
并从中创建Double
。
let someDouble = Double(someDecimal as NSNumber)
答案 1 :(得分:7)
NSDecimalNumber
和Decimal
被桥接
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)
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)
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