ios Swift 3 中的十进制到双精度转换
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39890795/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Decimal to Double conversion in Swift 3
提问by Zaphod
I'm migrating a project from Swift 2.2to Swift 3, and I'm trying to get rid of old Cocoa data types when possible.
我正在将一个项目从Swift 2.2迁移到Swift 3,并且我试图在可能的情况下摆脱旧的 Cocoa 数据类型。
My problem is here: migrating NSDecimalNumberto Decimal.
我的问题在这里:迁移NSDecimalNumber到Decimal.
I used to bridge NSDecimalNumberto Doubleboth ways in Swift 2.2:
我用来桥接NSDecimalNumber以Double这两种方式雨燕2.2:
let double = 3.14
let decimalNumber = NSDecimalNumber(value: double)
let doubleFromDecimal = decimalNumber.doubleValue
Now, switching to Swift 3:
现在,切换到Swift 3:
let double = 3.14
let decimal = Decimal(double)
let doubleFromDecimal = ???
decimal.doubleValuedoes not exist, nor Double(decimal), not even decimal as Double...
The only hack I come up with is:
decimal.doubleValue不存在,也不存在,Double(decimal)甚至不存在decimal as Double......我想出的唯一黑客是:
let doubleFromDecimal = (decimal as NSDecimalNumber).doubleValue
But that would be completely stupid to try to get rid of NSDecimalNumber, and have to use it once in a while...
但是试图摆脱它是完全愚蠢的NSDecimalNumber,并且不得不偶尔使用它......
Well, either I missed something obvious, and I beg your pardon for wasting your time, or there's a loophole needed to be addressed, in my opinion...
好吧,要么我错过了一些明显的东西,请原谅浪费你的时间,要么有一个漏洞需要解决,在我看来......
Thanks in advance for your help.
在此先感谢您的帮助。
Edit: Nothing more on the subject on Swift 4.
编辑:没有更多关于Swift 4的主题。
Edit: Nothing more on the subject on Swift 5.
编辑:没有更多关于Swift 5的主题。
回答by rmaddy
Another solution that works in Swift 3 is to cast the Decimalto NSNumberand create the Doublefrom that.
另一个适用于 Swift 3 的解决方案是投射DecimaltoNSNumber并Double从中创建。
let someDouble = Double(someDecimal as NSNumber)
As of Swift 4.2 you need:
从 Swift 4.2 开始,您需要:
let someDouble = Double(truncating: someDecimal as NSNumber)
回答by sketchyTech
NSDecimalNumberand Decimalare bridged
NSDecimalNumber并被Decimal桥接
The Swift overlay to the Foundation framework provides the Decimal structure, which bridges to the NSDecimalNumber class. The Decimal value type offers the same functionality as the NSDecimalNumber reference type, and the two can be used interchangeably in Swift code that interacts with Objective-C APIs. This behavior is similar to how Swift bridges standard string, numeric, and collection types to their corresponding Foundation classes. Apple Docs
Swift 覆盖到 Foundation 框架提供了 Decimal 结构,它连接到 NSDecimalNumber 类。Decimal 值类型提供与 NSDecimalNumber 引用类型相同的功能,并且两者可以在与 Objective-C API 交互的 Swift 代码中互换使用。这种行为类似于 Swift 将标准字符串、数字和集合类型桥接到它们相应的 Foundation 类的方式。苹果文档
but as with some other bridged types certain elements are missing.
但与其他一些桥接类型一样,缺少某些元素。
To regain the functionality you could write an extension:
要重新获得功能,您可以编写扩展程序:
extension Decimal {
var doubleValue:Double {
return NSDecimalNumber(decimal:self).doubleValue
}
}
// implementation
let d = Decimal(floatLiteral: 10.65)
d.doubleValue
回答by Pranavan Sp
Solution that works in Swift 4
适用于Swift 4 的解决方案
let double = 3.14
let decimal = Decimal(double)
let doubleFromDecimal = NSDecimalNumber(decimal: decimal).doubleValue
print(doubleFromDecimal)
Edit:Without NSDecimalNumber/NSNumber
编辑:没有NSDecimalNumber/NSNumber
let double = 3.14
let decimal = Decimal(double)
if let doubleFromDecimal = Double(decimal.description){
print(doubleFromDecimal)
}
回答by user28434
Decimalin Swift 3 is not NSDecimalNumber. It's NSDecimal, completely different type.
Decimal在 Swift 3 中不是NSDecimalNumber。它NSDecimal,完全不同的类型。
You should just keep using NSDecimalNumberas you did before.
你应该NSDecimalNumber像以前一样继续使用。
回答by Eonil
You are supposed to use asoperator to cast a Swift type to its bridgedunderlying Objective-C type. So just use aslike this.
您应该使用as运算符将 Swift 类型转换为其桥接的底层 Objective-C 类型。所以就这样使用as。
let p = Decimal(1)
let q = (p as NSDecimalNumber).doubleValue
In Swift 4, DecimalisNSDecimalNumber. Here's citation from Apple's official documentation in Xcode 10.
在 Swift 4 中,Decimal是NSDecimalNumber. 这是 Xcode 10 中 Apple 官方文档的引用。
Important
The Swift overlay to the Foundation framework provides the
Decimalstructure, which bridges to theNSDecimalNumberclass. For more information about value types, see Working with Cocoa Frameworks in Using Swift with Cocoa and Objective-C (Swift 4.1).
重要的
Swift 覆盖到 Foundation 框架提供了
Decimal连接到NSDecimalNumber类的结构。有关值类型的更多信息,请参阅使用 Swift 与 Cocoa 和 Objective-C (Swift 4.1) 中的使用 Cocoa 框架。
There's no NSDecimalanymore.
There was confusing NSDecimaltype in Swift 3, but it seems to be a bug.
No more confusion.
没有NSDecimal了。NSDecimalSwift 3 中有令人困惑的类型,但这似乎是一个错误。没有更多的困惑。
Note
笔记
I see the OP is not interested in Swift 4, but I added this answer because mentioning only about (outdated) Swift 3 made me confused.
我看到 OP 对 Swift 4 不感兴趣,但我添加了这个答案,因为只提到(过时的)Swift 3 让我感到困惑。
回答by RaffAl
Swift 5
斯威夫特 5
let doubleValue = Double(truncating: decimalValue as NSNumber)
回答by Eugene Dudnyk
In Swift open source, the implementationis actually done in Decimal.swift, but it is private. You can re-use the code from there.
在 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)
}
}

