Почему Swift .intValue возвращает неправильные / странные значения? - PullRequest
0 голосов
/ 05 мая 2020

Я пытаюсь преобразовать десятичное число, которое представляет сумму в долларах. Затем я преобразовал его в NSDecimalNumber, чтобы применить преобразование .intValue.

Однако у меня странное поведение. Сначала он даст мне неточное значение при умножении значения на 100. А при применении .intValue я получаю совершенно неожиданное число. Буду признателен за вашу помощь!

//Issue
let dollars: Decimal = 106.99 * 100 // 10698.999999999997952
let cast = dollars as NSDecimalNumber // 10699
let int = cast.intValue //-7747


//No Problems here
let dollars2: Decimal = 106.98 * 100 // 10698
let cast2 = dollars2 as NSDecimalNumber // 10698
let int2 = cast2.intValue //10698

Ответы [ 2 ]

2 голосов
/ 05 мая 2020

Так же можно попробовать

let dollars = "\(106.99 * 100)"
let cast = NSDecimalNumber(string: dollars)
let int = cast.intValue
0 голосов
/ 05 мая 2020

Decimal s FloatLiteralType равно Double.

Проблема в том, что 106.99 не может быть представлено Double. Просто вставить его в Decimal проблематично c:

Decimal(106.99) == 106.98999999999997952 // true
106.99 as Decimal * 100 // 10698.999999999997952

Итак, вам нужно продезинфицировать свои Double s.

extension Decimal {
  init(dollarsAndCents: Double) {
    self = Self( (dollarsAndCents * 100).rounded() ) / 100
  }
}
extension Decimal {
  var dollarsAndCents: (dollars: Int, cents: Int) {
    (self * 100 as NSDecimalNumber).intValue
    .quotientAndRemainder(dividingBy: 100) as (Int, Int)
  }
}
Decimal(dollarsAndCents: 106.99).dollarsAndCents // (dollars: 106, cents: 99)

На практике это нормально, потому что Decimal для денег. Продезинфицируйте, и вы никогда не столкнетесь с ошибками.

...