Подтвердить что ты не робот

Десятичное двойное преобразование в Swift 3

Я перевожу проект из Swift 2.2 в Swift 3 и пытаюсь по возможности избавиться от старых типов данных Cocoa.

Моя проблема здесь: миграция NSDecimalNumber в Decimal.

Я использовал, чтобы соединить NSDecimalNumber к Double оба способа Swift 2.2:

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.

4b9b3361

Ответ 1

Другое решение, которое работает в Swift 3, - это отбросить Decimal до NSNumber и создать Double.

let someDouble = Double(someDecimal as NSNumber)

Ответ 2

NSDecimalNumber и Decimal соединены

Наложение Swift на платформу Foundation предоставляет структуру Decimal, которая соединяется с классом NSDecimalNumber. Тип десятичного значения предлагает те же функциональные возможности, что и ссылочный тип NSDecimalNumber, и они могут использоваться взаимозаменяемо в коде Swift, который взаимодействует с API-интерфейсами Objective-C. Это поведение аналогично тому, как Swift соединяет стандартные строковые, числовые типы и типы коллекций с соответствующими им базовыми классами. Apple Docs

но, как и с некоторыми другими мостовыми типами, некоторые элементы отсутствуют.

Чтобы восстановить функциональность, вы можете написать расширение:

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

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

Ответ 3

Decimal в Swift 3 не NSDecimalNumber. Это NSDecimal, совершенно другой тип.

Вы должны просто использовать NSDecimalNumber, как и раньше.

Ответ 4

Решение, которое работает в 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)
}

Ответ 5

Вы должны использовать в as оператора для приведения типа Swift к его мостовому базовому типу Objective-C. Так что просто используйте as это.

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

В Swift 4 Decimal является NSDecimalNumber. Вот цитата из официальной документации Apple в Xcode 10.

Важный

Наложение Swift на платформу Foundation предоставляет структуру Decimal, которая соединяется с классом NSDecimalNumber. Для получения дополнительной информации о типах значений см. Работа с фреймворками Cocoa в Использовании Swift с Cocoa и Objective-C (Swift 4.1).

Там нет NSDecimal больше. В Swift 3 был запутанный тип NSDecimal, но, похоже, это ошибка. Нет больше путаницы.

Заметка

Я вижу, что OP не заинтересован в Swift 4, но я добавил этот ответ, потому что упоминание только о (устаревшем) Swift 3 привело меня в замешательство.

Ответ 6

Swift 5

let doubleValue = Double(truncating: decimalValue as NSNumber)