我计算"长度的方法"在第1474次迭代之后,斐波那契数(即,位数)失败。我获得所需结果的方式可能非常笨拙,所以如果我的方法存在缺陷,请告诉我。我怀疑在无限范围内运行块方法会有一些相当浪费的东西,直到它碰到答案,但在这个阶段它是我得到的最好的。我当然希望做得更好。
对于小于下面数字的数字,它可以正常工作,直到达到第1474个数字:
49922546054780146353198579531352153533212840109029466994098142197617303359523104269471455390562835412104406019654730583800904132982935807202575490044075132631203284854890505808877430837618493577512703453928379390874730829906652067545822236147772760444400628059249610784412153766674534014113720760876471943168
然后返回此错误:
FloatDomainError: Infinity
以下是我的方法的工作原理:
首先,我使用标准公式来获得" nth"斐波那契数列中的数字:
def fibonacci_index(n)
((1 / Math.sqrt(5)) * ((1 + Math.sqrt(5)) / 2) ** (n + 1)).round(0)
end
然后我将输出转换为字符串并测量其长度:
def fibonacci_index_length(n)
fibonacci_index(n).to_s.length
end
最后我创建无限范围并在 while循环中运行块方法:
def find_fibonacci_index_by_length(integer)
# Range to infinity because I don't want to
# limit the size of the numbers I work with
infinity = 1.0 / 0.0
range = (1..infinity)
# while loop to run through the range
running = true
while running
range.each do |n|
f_index = n + 1
f_number = fibonacci_index(n)
f_length = fibonacci_index_length(n)
if fibonacci_index_length(n) == integer && fibonacci_index(n) != 1
puts "f_index: #{f_index}"
puts "f_number: #{f_number}"
puts "f_length: #{f_length}"
running = false
# This breaks from the block
return f_index
elsif fibonacci_index_length(n) == integer && fibonacci_index(n) == 1
running = false
return 1
else
# puts "Still looking, number is #{fibonacci_index(n)}"
puts "Still looking, Fibonacci index: #{f_index}"
puts f_number
end
end
end
end
答案 0 :(得分:3)
在Ruby中,与任何浮点系统一样,可以表达最大值。那里有一个308位数字,浮点数的最大值为Float::MAX
或1.7976931348623157e+308
。
如果要避免该问题,则需要使用Integer数学执行此操作。 Ruby的“bignum”系统可以处理高达数百万个地方的任意长度数字,但要注意,性能越大越好。
这是一个未被优化的替代品:
def fibonacci_index(n)
a = [ 1, 1 ]
while (a.length < n)
a << (a[-1] + a[-2])
end
return a[-1]
end
值得注意的是,基于Float的计算,与浮点数学的任何内容一样,是近似值,而不是精确值。无论何时使用浮点值进行数学运算,这都是非常重要的。这适用于流体动力学模拟或3D渲染,其中足够接近计数。对于每个数字都很重要的事情,或者精确错误可能导致数千或数百万美元损失的货币情况, 。
这是你计算的数字与一个强制使用可靠整数数学的比较:
4992254605477767835147644879936483062623238506802202927705709236175156181701079...
4992254605478014635319857953135215353321284010902946699409814219761730335952310...
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
你可以看到这两个值大相径庭。
答案 1 :(得分:1)
您需要使用整数运算,因为它能够支持无限精度。您使用了精度有限的浮点数。
为了加快计算速度,我建议您缓存序列的值。实现可以简单:
class RecursiveFibonacci
def initialize
@cache = { 1 => 1, 2 => 2 }
end
def [](n)
@cache[n] ||= self[n - 2] + self[n - 1]
end
end
fibonacci = Fibonacci.new
fibonacci[6] #=> 13
您可以添加一些错误检测(例如,在n <= 0
时引发错误)。如果您想使用迭代算法,那么类似下面的内容应该有效:
class IterativeFibonacci
def [](n)
# Add 1 to covert the index from zero-based to one-based.
sequence.take(n + 1).last
end
private
def sequence
Enumerator.new do |yielder|
a, b = 1, 1
yielder << a
loop do
a, b = b, a + b
yielder << a
end
end
end
end
如果你想处理序列的一部分(比如从1到10,000的术语),那么我建议你公开#sequence
并对其进行切片以使算法更快。