我找到了一个代码,用于确定数字是否为斐波纳契数。我希望有人能够更轻松地分解它。
def is_fibonacci?(i, current = 1, before = 0)
return true if current == i || i == 0
return false if current > i
is_fibonacci?(i, current + before, current)
end
is_fibonacci?(3) # => true
is_fibonacci?(4) # => false
我知道一个方法在递归中调用自身,并且需要有一个基本情况,但同样,我很难看到正在发生的事情。任何帮助将不胜感激。
答案 0 :(得分:2)
最简单的可视化方法是逐步完成一个方法调用计算,假设我们想要评估is_fibonacci?(8)
,那么ruby将设置current = 1, before = 0
,因为我没有覆盖默认值
然后,由于i
不是0或8,它必须递归,因此会发生以下方法调用:
is_fibonacci?(8, 1, 1)
is_fibonacci?(8, 2, 1)
is_fibonacci?(8, 3, 2)
is_fibonacci?(8, 5, 3)
is_fibonacci?(8, 8, 5)
最后,is_fibonacci?(8, 8, 5)
可以从i == current (8 == 8)
开始终止,因此它返回true。
current
和before
参数正在'重建'斐波纳契序列,如果它们点击i
,那么答案是真的,但如果它们超过i
,那就错了。
答案 1 :(得分:1)
首先,它检查i
(请求的数字)是否等于Fibonaccy计算的数字,该数字传递给current
变量,或者为零。如果等于,则返回true
:
return true if current == i || i == 0
第二次检查i
是否低于current
变量。如果是,则i
var将永远不会成为斐波纳契数,因此返回false
:
return false if current > i
至少我们调用计算下一个数字的下一个Fibonaccy数,作为第二个参数的当前和前一个数字的总和,以及下一步的第三个参数的前一个当前数字。
is_fibonacci?(i, current + before, current)
请注意,最好的方法是将尾部递归(在您的示例中为shewn)扩展为循环。
答案 2 :(得分:1)
基本上,它是一个带3
个参数的函数。
i
- 您正在测试的数字,看它是否是序列的一部分。
current
- 您正在测试的当前斐波那契数字,默认为1
,因此您无需提供第二个参数。
before
- 序列中current
数字之前的斐波纳契数,默认为0
,因此您无需提供第三个参数。
示例值
如果current
为5
,则before
为3
如果current
为8
,则before
为5
该函数比较第一个参数i
的值,并查看它是否等于0
或current
斐波那契值。如果它等于current
或0
,则它是斐波纳契数(因为0
是序列中的第一个数字)。
然后查看current
是否大于i
。如果它更大,则不在序列中。这是因为如果4
是5
值,则无法继续检查序列中是否current
。
如果这两种情况都不匹配,我们只需再次调用该函数,传递i
的值,查找序列current + before
中的下一个数字,以及before
的值将是序列中的current
数字。
示例:
i
为15
,current
为5
,before
为3
。再次调用该函数时,它将调用
is_fibonacci?(i, current + before, current)
将评估为
is_fibonacci?(15, 5 + 3, 5
注意强>
Ruby有一个很好的语法,if
可以在之后来发生。
if a < b
puts "#{a} is greater than #{b}"
与
完全相同puts "#{a} is greater than #{b}" if a < b
它只是减少了行数,而且读起来更像英语。
答案 3 :(得分:1)
如果is_fibonacci?
有两个值10
和144
,您可以查看通话跟踪。它显然是计算斐波纳契数小于或等于给定值,然后在递归中进行比较。
is_fibonacci?(10, current = 1, before = 0)
is_fibonacci?(10, current = 1, before = 1)
is_fibonacci?(10, current = 2, before = 1)
is_fibonacci?(10, current = 3, before = 2)
is_fibonacci?(10, current = 5, before = 3)
is_fibonacci?(10, current = 8, before = 5)
is_fibonacci?(10, current = 13, before = 8)
is_fibonacci?(144, current = 1, before = 0)
is_fibonacci?(144, current = 1, before = 1)
is_fibonacci?(144, current = 2, before = 1)
is_fibonacci?(144, current = 3, before = 2)
is_fibonacci?(144, current = 5, before = 3)
is_fibonacci?(144, current = 8, before = 5)
is_fibonacci?(144, current = 13, before = 8)
is_fibonacci?(144, current = 21, before = 13)
is_fibonacci?(144, current = 34, before = 21)
is_fibonacci?(144, current = 55, before = 34)
is_fibonacci?(144, current = 89, before = 55)
is_fibonacci?(144, current = 144, before = 89)
10 : false , 144 : true
以下是为前10个斐波那契数字提供此输出的代码:
def fib(n)
if n <= 0 then 1
else
fib(n-1) + fib(n - 2)
end
end
def is_fibonacci?(i, current = 1, before = 0, level=0)
puts (" " * level) + " is_fibonacci?(#{i}, current = #{current}, before = #{before})"
if current == i || i == 0 then
return true
elsif current > i then
return false
else
is_fibonacci?(i, current + before, current, level+1)
end
end
(0..10).each do |i|
n = fib(i)
ifib =is_fibonacci?(i)
nfib = is_fibonacci?(n)
puts "#{i} : #{ifib} , #{n} : #{nfib}"
end