我知道如何制作斐波那契数字列表,但我不知道如何测试给定数字是否属于斐波那契列表-一种想到的方法是生成fib列表。直到该数字为止,并查看它是否属于数组,但是必须有另一个更简单,更快速的方法。
有任何想法吗 ?
我知道如何制作斐波那契数字列表,但我不知道如何测试给定数字是否属于斐波那契列表-一种想到的方法是生成fib列表。直到该数字为止,并查看它是否属于数组,但是必须有另一个更简单,更快速的方法。
有任何想法吗 ?
Answers:
一个很好的测试是,当且仅当5 N^2 + 4
或是5N^2 – 4
平方数时,N是斐波那契数。有关如何有效测试数字是否为平方的想法,请参阅SO讨论。
希望这可以帮助
虽然有几个人指出了完美平方解决方案,但它涉及对斐波那契数进行平方运算,从而经常产生大量产品。
甚至可以以标准的64位整数保存少于80个斐波那契数。
这是我的解决方案,它的运行完全小于要测试的数量。
(用C#编写,使用诸如double
和的基本类型long
。但是该算法应该适用于较大的类型。)
static bool IsFib(long T, out long idx)
{
double root5 = Math.Sqrt(5);
double phi = (1 + root5) / 2;
idx = (long)Math.Floor( Math.Log(T*root5) / Math.Log(phi) + 0.5 );
long u = (long)Math.Floor( Math.Pow(phi, idx)/root5 + 0.5);
return (u == T);
}
out
。
参数#2是斐波纳契数列的“索引”。
如果要测试的值T
是斐波那契数,那么idx
它将是斐波那契数列中该数字从1开始的索引。(一个值得注意的例外)
斐波那契数列是1 1 2 3 5 8 13
,等等
。3是数列中的第4个数字:IsFib(3, out idx);
returntrue
和value 4
。
8是序列中的第六个数字:IsFib(8, out idx);
将返回true
和value 6
。
13是第七个数字;IsFib(13, out idx);
将返回true
并有价值7
。
一个例外是IsFib(1, out idx);
,2
即使值1出现在索引1和2上,也会返回。
如果IsFib
传递了非斐波那契数,它将返回false
,其值idx
将是小于的最大斐波那契数的索引T
。
16不是斐波那契值。IsFib(16, out idx);
将返回false
并有价值7
。
您可以使用Binet公式将索引7转换为斐波那契值13,该值是小于16的最大数。
#!/bin/bash
victim="144"
curl http://aux.planetmath.org/files/objects/7680/fib.txt | sed 's/^[0-9]*//;s/[ \t]//g' | grep "^$victim$" >/dev/null 2>/dev/null
if [[ $? -eq 0 ]] ; then
echo "$victim is a fibonacci number"
else
echo "$victim aint"
fi
正整数ω是斐波那契数
当且仅当一个 5ω 2 + 4和5ω 2 - 4是完全平方
摘自Alfred Posamentier和Ingmar Lehmann的(出色的)FIBONACCI编号
bool isFibonacci(int w)
{
double X1 = 5 * Math.Pow(w, 2) + 4;
double X2 = 5 * Math.Pow(w, 2) - 4;
long X1_sqrt = (long)Math.Sqrt(X1);
long X2_sqrt = (long)Math.Sqrt(X2);
return (X1_sqrt*X1_sqrt == X1) || (X2_sqrt*X2_sqrt == X2) ;
}
在1k
和之间打印斐波那契数的代码段10k
。
for (int i = 1000; i < 10000; i++)
{
if (isFibonacci(i))
Console.Write(" "+i);
}
天哪,只有四个!
用其他方法
from math import *
phi = 1.61803399
sqrt5 = sqrt(5)
def F(n):
return int((phi**n - (1-phi)**n) /sqrt5)
def isFibonacci(z):
return F(int(floor(log(sqrt5*z,phi)+0.5))) == z
print [i for i in range(1000,10000) if isFibonacci(i)]
基于我和psmears的早期回答,我编写了此C#代码。
它逐步执行,可以明显地减少和优化:
// Input: T: number to test.
// Output: idx: index of the number in the Fibonacci sequence.
// eg: idx for 8 is 6. (0, 1, 1, 2, 3, 5, 8)
// Return value: True if Fibonacci, False otherwise.
static bool IsFib(long T, out int idx)
{
double root5 = Math.Sqrt(5);
double PSI = (1 + root5) / 2;
// For reference, IsFib(72723460248141) should show it is the 68th Fibonacci number
double a;
a = T*root5;
a = Math.Log(a) / Math.Log(PSI);
a += 0.5;
a = Math.Floor(a);
idx = (Int32)a;
long u = (long)Math.Floor(Math.Pow(PSI, a)/root5 + 0.5);
if (u == T)
{
return true;
}
else
{
idx = 0;
return false;
}
}
测试显示,此方法适用于前69个斐波那契数字,但分解为第70个。
F(69) = 117,669,030,460,994 - Works
F(70) = 190,392,490,709,135 - Fails
总而言之,除非您使用某种BigInt库,否则最好有一个简单的斐波那契数表查找表并进行检查,而不是运行算法。
在线提供了前300个号码的列表。
但是,如果您有足够的精度,并且不会溢出您的数字表示系统,那么这段代码确实概述了可行的算法。
摘自Wikipedia:http://en.wikipedia.org/wiki/Fibonacci_number
当且仅当5z ^ 2 + 4或5z ^ 2-4-4的一个是理想平方时,正整数z就是斐波那契数。
回复:艾哈迈德(Ahmad)的代码-一种比较简单的方法,没有递归或指针,相当幼稚,但是几乎不需要任何计算能力来处理除泰坦尼克号之外的任何数字(大约2N的加法来验证Nth fib数,这在现代机器上将花费毫秒最坏的
//如果找到任何内容,则返回pos;否则,则返回0(C / C ++将任何值!= 0都视为true,因此最终结果相同)
int isFib (long n)
{
int pos = 2;
long last = 1;
long current = 1;
long temp;
while (current < n)
{
temp = last;
last = current;
current = current + temp;
pos++;
}
if (current == n)
return pos;
else
return 0;
}
斐波那契数的一般表达式是F(n)= [[((1 + sqrt(5))/ 2] sup n + 1-[(1-sqrt(5))/ 2] sup n + 1] / sqrt (5).....(*)对于大n,第二个指数变为零,并执行数值运算,我们得到F(n)= [(1.618)sup n + 1] / 2.236
如果K是要测试的数字,log(k * 2.2336)/ log(1.618)应该是整数!
例如,K等于13,我的计算器给出的答案是7.00246。K等于14时,答案是7.1564。
您可以采用最接近答案的整数并用(*)代替以确认结果为K,从而增加结果的置信度
Scala版本-
def isFib(n: Int): Boolean = {
def checkFib(f1: Int = 1, f2: Int = 1): Boolean = {
if(n == f1 || n == f2) true
else if(n < f2) false
else checkFib(f2, f1+f2)
}
checkFib()
}
Java解决方案可以按以下方式完成。但是仍然可以优化
以下解决方案适用于
T是测试用例的数量,N是数量范围
import java.util.Scanner;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class FibonacciTester {
private static BigDecimal zero = BigDecimal.valueOf(0);
private static BigDecimal one = BigDecimal.valueOf(1);
private static BigDecimal two = BigDecimal.valueOf(2);
private static BigDecimal four = BigDecimal.valueOf(4);
private static BigDecimal five = BigDecimal.valueOf(5);
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
BigDecimal[] inputs = new BigDecimal[n];
for (int i = 0; i < n; i++) {
inputs[i] = sc.nextBigDecimal();
}
for (int i = 0; i < inputs.length; i++) {
if (isFibonacci(inputs[i]))
System.out.println("IsFibo");
else
System.out.println("IsNotFibo");
}
}
public static boolean isFibonacci(BigDecimal num) {
if (num.compareTo(zero) <= 0) {
return false;
}
BigDecimal base = num.multiply(num).multiply(five);
BigDecimal possibility1 = base.add(four);
BigDecimal possibility2 = base.subtract(four);
return (isPerfectSquare(possibility1) || isPerfectSquare(possibility2));
}
public static boolean isPerfectSquare(BigDecimal num) {
BigDecimal squareRoot = one;
BigDecimal square = one;
BigDecimal i = one;
BigDecimal newSquareRoot;
int comparison = -1;
while (comparison != 0) {
if (comparison < 0) {
i = i.multiply(two);
newSquareRoot = squareRoot.add(i).setScale(0, RoundingMode.HALF_UP);
} else {
i = i.divide(two);
newSquareRoot = squareRoot.subtract(i).setScale(0, RoundingMode.HALF_UP);
}
if (newSquareRoot.compareTo(squareRoot) == 0) {
return false;
}
squareRoot = newSquareRoot;
square = squareRoot.multiply(squareRoot);
comparison = square.compareTo(num);
}
return true;
}
}
int isfib(int n /* number */, int &pos /* position */)
{
if (n == 1)
{
pos=2; // 1 1
return 1;
}
else if (n == 2)
{
pos=3; // 1 1 2
return 1;
}
else
{
int m = n /2;
int p, q, x, y;
int t1=0, t2 =0;
for (int i = m; i < n; i++)
{
p = i;
q = n -p; // p + q = n
t1 = isfib(p, x);
if (t1) t2 = isfib(q, y);
if (t1 && t2 && x == y +1)
{
pos = x+1;
return 1; //true
}
}
pos = -1;
return 0; //false
}
}
这个怎么样?
#include <stdio.h>
#include <math.h>
int main()
{
int number_entered, x, y;
printf("Please enter a number.\n");
scanf("%d", &number_entered);
x = y = 5 * number_entered^2 + 4; /*Test if 5N^2 + 4 is a square number.*/
x = sqrt(x);
x = x^2;
if (x == y)
{
printf("That number is in the Fibonacci sequence.\n");
}
x = y = 5 * number_entered^2 - 4; /*Test if 5N^2 - 4 is a square number.*/
x = sqrt(x);
x = x^2;
if (x == y)
{
printf("That number is in the Fibonacci sequence.\n");
}
else
{
printf("That number isn't in the Fibonacci sequence.\n");
}
return 0;
}
这样行吗?
^
是按位XOR运算符。您需要x * x
或pow(x,2)
平方一个数字。程序逻辑中也存在问题。