The Fibonacci numbers become very large quickly. To compute large Fibonacci numbers, you need to implement some kind of BigNum
. Here is a version the makes a BigNum
that is implemented internally as an array of digits. For example, 12345
is implemented internally as [1, 2, 3, 4, 5]
. This makes it easy to represent arbitrarily large numbers.
Addition is implemented by making the two arrays the same size, then map
is used to add the elements, finally the carryAll
function restores the array to single digits.
For example 12345 + 67
:
[1, 2, 3, 4, 5] + [6, 7] // numbers represented as arrays
[1, 2, 3, 4, 5] + [0, 0, 0, 6, 7] // pad the shorter array with 0's
[1, 2, 3, 10, 12] // add the arrays element-wise
[1, 2, 4, 1, 2] // perform carry operation
Here is the implementation of BigNum
. It is also CustomStringConvertible
which makes it possible to print the result as a String
.
struct BigNum: CustomStringConvertible {
var arr = [Int]()
// Return BigNum value as a String so it can be printed
var description: String { return arr.map(String.init).joined() }
init(_ arr: [Int]) {
self.arr = carryAll(arr)
}
// Allow BigNum to be initialized with an `Int`
init(_ i: Int = 0) {
self.init([i])
}
// Perform the carry operation to restore the array to single
// digits
func carryAll(_ arr: [Int]) -> [Int] {
var result = [Int]()
var carry = 0
for val in arr.reversed() {
let total = val + carry
let digit = total % 10
carry = total / 10
result.append(digit)
}
while carry > 0 {
let digit = carry % 10
carry = carry / 10
result.append(digit)
}
return result.reversed()
}
// Enable two BigNums to be added with +
static func +(_ lhs: BigNum, _ rhs: BigNum) -> BigNum {
var arr1 = lhs.arr
var arr2 = rhs.arr
let diff = arr1.count - arr2.count
// Pad the arrays to the same length
if diff < 0 {
arr1 = Array(repeating: 0, count: -diff) + arr1
} else if diff > 0 {
arr2 = Array(repeating: 0, count: diff) + arr2
}
return BigNum(zip(arr1, arr2).map { $0 + $1 })
}
}
// This function is based upon this question:
// https://stackoverflow.com/q/52975875/1630618
func fibonacci(to n: Int) {
guard n >= 2 else { return }
var array = [BigNum(0), BigNum(1)]
for i in 2...n {
array.append(BigNum())
array[i] = array[i - 1] + array[i - 2]
print(array[i])
}
}
fibonacci(to: 400)
Output:
1
2
3
5
8
...
67235063181538321178464953103361505925388677826679492786974790147181418684399715449
108788617463475645289761992289049744844995705477812699099751202749393926359816304226
176023680645013966468226945392411250770384383304492191886725992896575345044216019675