0

我试图找到一组双打的因子,所以我首先将它们转换为整数并使用 % 找到除数。

选项1

我遇到的问题是,当我的循环中发生转换时,我会丢失一些信息,特别是如果调用以下函数:

func factors(number: Double) -> [Double] {
    var result = [Double]()
    var divisor = 0.1

    let temporaryIncreasedNumber = Int(number) * 10

        while number > divisor {
            let theNewDivisor = divisor * 10
            print("\(divisor) * \(10) = \(theNewDivisor) for \(divisor), \(temporaryIncreasedNumber) % \(Int(theNewDivisor)) is \(temporaryIncreasedNumber % Int(theNewDivisor))")
            if temporaryIncreasedNumber % Int(theNewDivisor)  == 0 {
                //print ("dividing \(temporaryIncreasedNumber) by \(theNewDivisor) for \(divisor)")
                result.append(divisor);
            }

            divisor += 0.1
        }
    return result
}

20,所以:

factors(number: 20.0))

例如,如果我查看输出:

1.1 * 10 = 11.0 for 1.1, 200 % 10 is 0

不知何故,当我做手术时200 % Int(1.1 * 10)Int(1.1 * 10)给我的是 10,而不是 11,我不知道为什么?这当然通过了验证,A % B == 0但不应该是因为200 % 11 = 2

我在 Playground 中手动执行了以下操作,但这工作正常并给了我结果200 % 11 = 2

let myX = 20.0
let myY = 1.1
let myCalc = Int(myX * 10.0) % Int(myY * 10.0)
let myCalc2 = 200 % 11

选项 2

或者,如果我只是简单地处理并仅使用双打操作,我仍然会得到不一致的值。如果我将代码简化为:

func factors(number: Double) -> [Double] {
    var result = [Double]()
    var divisor = 0.1

        while number > divisor {
            let whole = (number/divisor).rounded(.towardZero)
            print ("reminder of \(number) by \(divisor) = \((number/divisor) - whole)")
            if (number/divisor) - whole  == 0.0 {
                result.append(divisor);
            }

            divisor = divisor + 0.1
        }
    return result
}

factors(number: 20.0)

请注意,我没有明确使用截断提醒,以便我可以检查出什么问题。

看看下面的操作,它给出了一个意想不到的结果:

reminder of 20.0 by 0.8 = 3.5527136788005e-15

但是,如果我在操场上手动执行以下操作:

let test = (20.0/0.8) - (20.0/0.8).rounded(.towardZero)

结果是0!


为什么 while 循环中的行为不同?我的代码有问题吗?

4

1 回答 1

0

在直接联系 Apple 后,他们建议问题是因为转换 Int -> Double 反之亦然。在他们的回复中...

浮点是基于二进制的,所以 1.1 并不是理想值 1 1/10,它是 1.09999……,而 1.1 *10.0 实际上是 10.999………… Double-to-Int 转换截断

如果您需要进一步的精度,他们建议使用 Decimal 代替,这就是我的情况。我通过使用DecimalNSDecimalNumber操作的组合找到了一种解决方案(这样我就可以从小数中提取双精度数来舍入它)。

func factors2(number: Double) -> [Decimal] {
    var result = [Decimal]()
    var divisor = Decimal(0.1)

    let decimalNumber = Decimal(number)

        while decimalNumber >= divisor {

            let operation = (decimalNumber/divisor)
            let wholeDecimal = NSDecimalNumber(decimal: operation)
            let whole = wholeDecimal.doubleValue.rounded(.towardZero)
            print ("reminder of \(decimalNumber) by \(divisor) = \((decimalNumber/divisor) - Decimal(whole))")
            if (decimalNumber/divisor) - Decimal(whole)  == 0.0 {
                result.append(divisor);
            }

            divisor += 0.1
        }
    return result
}

print(factors2(number: 20.0))

此解决方案提供正确的输出。在示例中,20.0 的小数因子(从 0.1 到 20.0 的计数形式)为:

[0.1, 0.2, 0.4, 0.5, 0.8, 1, 2, 2.5, 4, 5, 10, 20]
于 2018-04-30T22:10:46.733 回答