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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 10:29:34  来源:igfitidea点击:

Decimal to Double conversion in Swift 3

iosswiftmigrationtype-conversionswift3

提问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.

我的问题在这里:迁移NSDecimalNumberDecimal.

I used to bridge NSDecimalNumberto Doubleboth ways in Swift 2.2:

我用来桥接NSDecimalNumberDouble这两种方式雨燕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 的解决方案是投射DecimaltoNSNumberDouble从中创建。

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 中,DecimalNSDecimalNumber. 这是 Xcode 10 中 Apple 官方文档的引用。

Important

The Swift overlay to the Foundation framework provides the Decimalstructure, which bridges to the NSDecimalNumberclass. 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)
    }
}