UIint64数据溢出问题

UIint64 data overflow issue

我正在解决一个问题:

Each new term in the Fibonacci sequence is generated by adding
the previous two terms. By starting with 1 and 2, the first 10
terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

By considering the terms in the Fibonacci sequence whose values
do not exceed four million, find the sum of the even-valued terms.

以下是我的解决方案:

class FB {
  static func run() {
    var a: UInt64 = 0
    var b: UInt64 = 1

    var c: UInt64 = 0

    var sum: UInt64 = 0

    for _ in 0..<4_000_000 {
      print(c)
      c = a + b // CRASHES
      if c % 2 == 0 {
        sum += c
      }

      a = b
      b = c
    }

    print("SUM: , \(sum)")
  }
}

但如评论中所述,它崩溃了 线程 1:EXC_BAD_INSTRUCTION(代码=EXC_I386_INVOP,子代码=0x0)

为了避免 c 变量溢出,我应该使用什么数据类型?

.. whose values do not exceed four million

表示c不能大于400万。

替换

for _ in 0..<4000000 {

while c < 4000000 {

现在数字类型甚至可以是UInt32

虽然 Vadian 的解决方案将按原样修复您的代码,但我想我会分享我将如何解决这个问题,它使用更实用的方法。

fibSequence 只是 returns Int 的无限序列。我调用该函数来生成一个这样的无限序列,我获取它的元素直到它们到达 4_000_000(这就是 prefix(while:) 正在做的),过滤以仅获取偶数,然后使用它们求和reduce,从 0 的累加器开始,并通过加法组合所有元素 (+)。

这种方法有几个好处,但最主要的是它可以将各种关注点适当地分成小的模块化部分。

  • fibSequence() 只关心 fib 序列,对你的问题的具体细节一无所知。
  • sumEvenFibs(upTo:) 只关心根据您的问题标准进行过滤和求和,并返回总和,对 fib 序列或打印结果一无所知。
  • 在通过调用 sumEvenFibs(upTo:) 计算总和后,单独打印。这使您可以轻松更改对结果的处理方式。您可能不想打印它,而是想用它做一些其他计算,例如将它与奇数 fib 所得的总和进行比较,看看哪个更大。
func fibSequence() -> UnfoldSequence<Int, (Int, Int)> {
    return sequence(state: (0, 1), next: { (state) -> Int in
            state = (state.1, state.0 + state.1)
            return state.0
        })
}

func sumEvenFibs(upTo limit: Int) -> Int {      
    return fibSequence()
        .prefix(while: { [=10=] < limit })
        .filter { [=10=].isMultiple(of: 2) }
        .reduce(0, +)
}


let sum = sumEvenFibs(upTo: 4_000_000)
print("SUM: \(sum)")