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)")
我正在解决一个问题:
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)")