Golang实现大数幂最后一位函数在Codewars测试用例失败求助
问题分析与修复
你的代码核心问题在于无法处理超大指数字符串:ParseInt函数使用strconv.ParseInt将字符串转成int,但当n2的数值超过int64的最大值(9223372036854775807)时,转换会失败(你忽略了错误返回值),导致exponent被错误赋值为0或其他无效值,进而触发remainder == 0的分支,返回lastDigit(1),这就是测试用例返回1而非预期7/3的原因。
另外,代码里还有一个拼写错误:reminder应该是remainder,不过这可能是笔误,本地测试时也许没触发到这个分支。
修复方案
要解决大指数问题,我们需要直接对字符串形式的指数进行模运算,而不是转换成整数。因为最后一位数字的循环周期最多是4,所以只需要计算指数模4(或模2,针对周期为2的数字)的结果即可,无需处理完整的超大指数。
关键步骤
- 单独处理指数为0的情况:如果
n2是"0",直接返回1(任何数的0次幂都是1,题目说明输入有效)。 - 计算底数的最后一位数字
num,这部分你的代码是对的。 - 针对不同的
num,计算指数的有效模值:- 对于
0,1,5,6:最后一位永远是自身,直接返回。 - 对于
4,9:周期为2,计算指数模2,模为0则返回6(4的偶次幂)或1(9的偶次幂),否则返回4或9。 - 对于
2,3,7,8:周期为4,计算指数模4,若模为0则用4代替(因为指数非0时,模0等价于周期长度4),再计算num^模值的最后一位。
- 对于
修正后的代码
package kata import "strconv" // 计算大数字字符串的模 func modString(s string, mod int) int { result := 0 for _, c := range s { digit := int(c - '0') result = (result*10 + digit) % mod } return result } func LastDigit(n1, n2 string) int { // 处理指数为0的情况 if n2 == "0" { return 1 } // 获取底数的最后一位 lastChar := n1[len(n1)-1] num := int(lastChar - '0') switch lastChar { case '0', '1', '5', '6': return num case '4': // 4的周期是2:4^1=4, 4^2=6, 循环 expMod := modString(n2, 2) if expMod == 0 { return 6 } return 4 case '9': // 9的周期是2:9^1=9, 9^2=1, 循环 expMod := modString(n2, 2) if expMod == 0 { return 1 } return 9 default: // 2,3,7,8的周期是4 expMod := modString(n2, 4) // 指数非0时,模0等价于4 if expMod == 0 { expMod = 4 } // 计算num^expMod的最后一位,避免用math.Pow(可能有精度问题) result := 1 for i := 0; i < expMod; i++ { result = (result * num) % 10 } return result } }
代码说明
modString函数:遍历字符串的每一位,逐步计算模值,避免了超大数字溢出问题。- 替换
math.Pow为循环计算:math.Pow处理整数时可能有精度丢失(比如大指数时),循环取模更可靠。 - 严格处理每种数字的周期逻辑:确保不同数字的幂次最后一位循环正确。
内容的提问来源于stack exchange,提问作者twentyfourk
相关产品推荐
相关产品推荐

