我有一个编写一个方法的赋值,该方法确定一个数字是否是Fibonacci序列的一部分。
同时使用公式:
正整数z是斐波那契数,当且仅当5z ^ 2 + 4或5z ^ 2 - 4中的一个是完美的正方形时
我定义了以下适用于小数和大Fibonacci数的方法,但是,无论出于何种原因,我的赋值规范在处理大的非Fibonacci数时会抛出错误,特别是在运行is_fibonacci?(927372692193078999171)
时。显然,该方法返回true
而不是false
。其他一切似乎都是正确的,所以我有点拉扯我的头发为什么这不起作用。有什么建议?
def is_fibonacci?(i)
bigNumber1 = Math.sqrt((5*(i**2)+4))
bigNumber2 = Math.sqrt((5*(i**2)-4))
if bigNumber1 == bigNumber1.round || bigNumber2 == bigNumber2.round
return true
else
return false
end
end
答案 0 :(得分:8)
如其他地方所述,问题在于Floats的精确度。 BigDecimal提供任意精度算术:
require 'bigdecimal'
def is_fibonacci?(i)
i = BigDecimal.new(i)
bigNumber1 = (5*(i**2)+4).sqrt(0)
bigNumber2 = (5*(i**2)-4).sqrt(0)
return (bigNumber1 == bigNumber1.round || bigNumber2 == bigNumber2.round)
end
is_fibonacci? 927372692193078999171 # => false
is_fibonacci? 927372692193078999176 # => true
答案 1 :(得分:3)
问题是Math.sqrt
返回一个浮点值,通常只是对实平方根的估计。对于大数字,您只需获得类似1234567600000.0的内容,您的代码将始终将其视为整数。
实现自己的任意精度,整数平方根函数。一个天真的方法可能是这样的:
def is_fibonacci?(i)
n1 = 5 * i**2 + 4
n2 = n1 - 8
is_square?(n1) or is_square?(n2)
end
# find floor(sqrt(i)) by nesting intervals
def sqrt(i)
a, b = 0, i
while a + 1 < b
m = (a + b) / 2
if m**2 > i
b = m
else
a = m
end
end
a
end
def is_square?(i)
s = sqrt(i)
s ** 2 == i
end
答案 2 :(得分:0)
比奈的公式需要计算平方根。这是我的解决方案,使用内置的Bignum和Newton的方法来检查平方根。
def isSQRT(x)
return true if [0,1,4,9,16,25,36,49,64,81,100].include?x
z = x / 10 #first guess
z=z-(z*z-x)/(2*z) while (z-1)**2 > x
return true if (z-1)**2 == x
false
end
def is_fibonacci?(num)
isSQRT(5*num**2+4) || isSQRT(5*num**2-4)
end
此外,有一种方法可以在不使用Binet的情况下弄清楚,如Kenneth's memoization method by Hash所示。所以你可以通过内置的has_value方法检查一个数字?(数字)。
fibo = Hash.new{ |h,k| h[k] = ( k<=2 ? 1 : h[k-2] + h[k-1] ) }
fibo[500] #=> instant result of Fibonacci!
答案 3 :(得分:0)
这是一种仅适用于 Ruby 的核心 API 方法的方法。它返回一个布尔值
def fibonacci?(number_sought)
num = 2
result = [1, 1] until num >= number_sought
result << result[-1] + result[-2]
if result.include?(number_sought) then break
elsif result[-1] > number_sought then return false
else next
end
num += 1
end
!!result
end
p fibonacci?(10946)
p fibonacci?(927372692193078999176)
如果你想返回数组:
def fibonacci(number_sought)
num = 2
result = [1, 1] until num >= number_sought
result << result[-1] + result[-2]
if result.include?(number_sought) then break
elsif result[-1] > number_sought then return result
else next
end
num += 1
end
result
end