Decimal to Double conversion in Swift 3

后端 未结 7 1439
春和景丽
春和景丽 2020-12-29 01:42

I\'m migrating a project from Swift 2.2 to Swift 3, and I\'m trying to get rid of old Cocoa data types when possible.

My problem is

相关标签:
7条回答
  • 2020-12-29 01:53

    Solution that works in Swift 4

    let double = 3.14
    let decimal = Decimal(double)
    let doubleFromDecimal = NSDecimalNumber(decimal: decimal).doubleValue
    print(doubleFromDecimal)
    
    0 讨论(0)
  • 2020-12-29 01:58

    In Swift open source, the implementation is actually done in Decimal.swift, but it is private. You can re-use the code from there.

    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)
        }
    }
    
    0 讨论(0)
  • 2020-12-29 02:06

    Swift 5

    let doubleValue = Double(truncating: decimalValue as NSNumber)
    
    0 讨论(0)
  • 2020-12-29 02:06

    You are supposed to use as operator to cast a Swift type to its bridged underlying Objective-C type. So just use as like this.

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

    In Swift 4, Decimal is NSDecimalNumber. Here's citation from Apple's official documentation in Xcode 10.

    Important

    The Swift overlay to the Foundation framework provides the Decimal structure, which bridges to the NSDecimalNumber class. For more information about value types, see Working with Cocoa Frameworks in Using Swift with Cocoa and Objective-C (Swift 4.1).

    There's no NSDecimal anymore. There was confusing NSDecimal type in Swift 3, but it seems to be a bug. No more confusion.

    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.

    0 讨论(0)
  • 2020-12-29 02:08

    Another solution that works in Swift 3 is to cast the Decimal to NSNumber and create the Double from that.

    let someDouble = Double(someDecimal as NSNumber)
    

    As of Swift 4.2 you need:

    let someDouble = Double(truncating: someDecimal as NSNumber)
    
    0 讨论(0)
  • 2020-12-29 02:12

    Decimal in Swift 3 is not NSDecimalNumber. It's NSDecimal, completely different type.

    You should just keep using NSDecimalNumber as you did before.

    0 讨论(0)
提交回复
热议问题