如何将Python实现的Pisano周期函数转为正确的JavaScript版本?
问题描述
我正在完成Codewars上的Pisano周期题目,需要返回斐波那契序列的周期长度。
我找到的Python代码如下,这个函数返回的是斐波那契序列的模版本而非周期长度:
def pisanoPython(divisor): '''Returns a modulo version of the Fibonacci sequence''' fib = [0,1] while True: fib.append((fib[-1]+fib[-2]) % divisor) if fib[-1] == 1 and fib[-2] == 0: return fib[:-2] >>> pisanoPython(3) [0,1,1,2,0,2,2,1]
以下是我写的JavaScript代码,但输出结果错误:
function pisanoJavascript(n){ let fib = [0,1]; let isRepeated = true; while(isRepeated) { let lastVal = fib[fib.length-1] let secondLastVal = fib[fib.length-2] let remainder = (lastVal + secondLastVal) % n fib.push(remainder) if(lastVal === 1 && secondLastVal === 0) isRepeated = false } return fib.slice(0,-2).length }
我遵循了Python函数的逻辑,但不知道遗漏了哪部分。我发现if(lastVal === 1 && secondLastVal === 0)这行代码总是触发循环退出,或许需要以不同方式初始化fib数组。为何这两个函数逻辑一致却结果不同?如何让JavaScript版本正常工作?
问题分析与解决
你的JavaScript代码和Python代码的核心差异在于循环退出的判断时机与条件:
错误根源
Python代码是在添加新元素后,检查数组的最后两位是否为0,1(fib[-2]是倒数第二个元素,fib[-1]是刚添加的新元素)——这是Pisano周期结束的标志,因为斐波那契序列从0,1起始,当模运算后的序列再次出现0,1时,周期就会重复。
而你的原JS代码,是在添加新元素之前,判断当前数组的最后两位是否为0,1——但初始数组就是[0,1],所以第一次循环直接触发退出,根本没开始计算周期。
修正后的JavaScript代码
把判断条件改成和Python逻辑对齐:添加新元素后,检查数组最后两位是否为0,1:
function pisanoJavascript(n) { let fib = [0, 1]; while (true) { let lastVal = fib[fib.length - 1]; let secondLastVal = fib[fib.length - 2]; let remainder = (lastVal + secondLastVal) % n; fib.push(remainder); // 检查刚添加元素后的最后两位是否为0和1 if (fib[fib.length - 2] === 0 && fib[fib.length - 1] === 1) { break; } } // 去掉最后重复的起始0,1,返回周期长度 return fib.slice(0, -2).length; } // 测试示例 console.log(pisanoJavascript(3)); // 输出8,符合预期
逻辑对齐说明
- Python代码的
fib[-1] ==1 and fib[-2] ==0,本质是判断数组最后两位为0,1(倒数第二个是0,最后一个是1) - 修正后的JS代码在添加新元素后做同样的判断,确保遍历到完整的周期后才停止循环,返回的长度就是正确的Pisano周期值。
内容的提问来源于stack exchange,提问作者likewoahlala
相关产品推荐
相关产品推荐

