今天,我们开发的AI笔试题工具,ai扁食——AI程序员笔试系统给我出了中级Golang题目,就是这道题:《请编写一个函数,接收一个整数参数n,输出n的阶乘结果》,希望我写一个函数,输出n的阶乘结果。我开始的时候没觉得有什么问题,大概写了个实现如下:
- // 循环计算n的阶乘
- func factorial(n int) int {
- var result = 1
- for i := 1; i <= n; i++ {
- result *= i
- }
- return result
- }
或者使用递归也行:
- // 计算n的阶乘
- func factorial1(n int) int {
- if n == 1 {
- return 1
- }
- return n * factorial1(n-1)
- }
后来觉得不对,这看起来不像一个中级题目啊。
跑了个简单测试例,发现这两个实现居然在21的时候就溢出int了。
- 21的阶乘是-4249290049419214848
- 21的阶乘是-4249290049419214848
哦,果然隐藏了一个考点。
那golang其实给我们提供了一个大数库:
math.Big
Big库的循环实现版本如下:
- // 计算n的阶乘,使用math/big包
- func factorial3(n int) *big.Int {
- var result = big.NewInt(1)
- for i := 1; i <= n; i++ {
- result.Mul(result, big.NewInt(int64(i)))
- }
- return result
- }
或者递归版本
- // 计算n的阶乘,使用math/big包,递归实现
- func factorial8(n int) *big.Int {
- if n == 1 {
- return big.NewInt(1)
- }
- var result = big.NewInt(int64(n))
- return result.Mul(result, factorial8(n-1))
- }
最终选择提交了循环版本,递归版本在递归深度较深的时候有非必要的消耗,循环就好。