用C中的黄金分割比计算n个fibonacci数模m
我试图计算模为10^9+7的第n个斐波那契数,其中n由用户输入 我用黄金比例来计算斐波那契数 以下代码生成正确的结果,直到n=43。但是对于n>=44,phi超过10^9+7,我开始得到意想不到的结果。此外,如果去除模量,n>=44给出了正确的结果用C中的黄金分割比计算n个fibonacci数模m,c,fibonacci,modulo,C,Fibonacci,Modulo,我试图计算模为10^9+7的第n个斐波那契数,其中n由用户输入 我用黄金比例来计算斐波那契数 以下代码生成正确的结果,直到n=43。但是对于n>=44,phi超过10^9+7,我开始得到意想不到的结果。此外,如果去除模量,n>=44给出了正确的结果 #include <stdio.h> #include <math.h> long double mod=1000000007; long double power(long double base, long long i
#include <stdio.h>
#include <math.h>
long double mod=1000000007;
long double power(long double base, long long int expo)
{
if(base==1 || expo==0)
return 1;
if(expo&1)
{
long double temp = power(base, expo>>1);
return fmodl(base * fmodl(temp*temp, mod), mod);
}
else
{
long double temp=power(base, expo>>1);
return fmodl(temp*temp,mod);
}
}
int main(void) {
// your code goes here
long double phi = (1+powl(5, 0.5))/2;
long double phi_cap = (1 - powl(5, 0.5))/2;
long double root5 = powl(5, 0.5);
long long int n;
scanf("%lld",&n);
long double ans = fmodl( (power(phi, n) - power(phi_cap, n)) * power(root5,mod-2), mod);
printf("%.0Lf\n", ans);
return 0;
}
#包括
#包括
长双模=100000007;
长双电源(长双基地,长长国际博览会)
{
如果(基数=1 | | expo==0)
返回1;
国际单项体育联合会(世博会和第一届)
{
长双温=电源(底座,expo>>1);
返回fmodl(基本*fmodl(温度*temp,mod),mod);
}
其他的
{
长双温=电源(底座,expo>>1);
返回fmodl(温度*温度,mod);
}
}
内部主(空){
//你的密码在这里
长双φ=(1+powl(5,0.5))/2;
长双phi_帽=(1-功率(5,0.5))/2;
长双根5=powl(5,0.5);
长整型n;
scanf(“%lld”、&n);
长双ans=fmodl((功率(φ,n)-功率(φ,n))*功率(root5,mod-2),mod);
printf(“%.0Lf\n”,ans);
返回0;
}
为什么会发生这种情况?使用长双精度存储无理数是错误的吗
谢谢
Fn=φn/√5-ψn/√五,
在哪里
φ=1/2+√5/2 ≅ 1.6180339887ψ = 1/2 - √5/2 = φ - 1 ≅ 0.6180339887 因为Fn中的减法部分总是小于一半,所以我们可以朝着零计算(或者朝负无穷大计算,或者
floor()
,因为Fn对于n是非负的≥ 0):
Fn=⌊ φn/√5.⌋ = 地板(φn/√(五)
如果我们对模M,M感兴趣≥ 我们需要观察上述公式的影响。请注意,表达式“expr MOD M”通常使用in C计算
我们可以应用:对于正实a,b和m,(a mod m)(b mod m)=(a mod m)。地板操作不受影响。这里,a=φn,b=1/√5.这意味着我们可以简化表达式
Fn模块M=⌊ φn/√5.⌋ MOD M
进入
Fn模块M=⌊ (φn模(M)√5) ) / √5.⌋
在这里,我们可以应用,注意到在这一点上的模不是由整数M,而是由M·√五,
换句话说,如果我们有一个函数,它使用浮点模的模幂运算对浮点值进行整数次幂运算,比如
double pow_mod(double base, unsigned int exponent, double modulus);
我们可以使用
#define PHI 1.61803398874989484820458683436563811772
#define SQRT5 2.236067977499789696409173668731276235441;
double fn_mod_m;
unsigned int n, m;
fn_mod_m = floor(pow_mod(PHI, n, SQRT5 * (double)m) / SQRT5);
在这里,是模幂运算的最佳候选者。
Fn=φn/√5-ψn/√五,
在哪里
φ=1/2+√5/2 ≅ 1.6180339887ψ = 1/2 - √5/2 = φ - 1 ≅ 0.6180339887 因为Fn中的减法部分总是小于一半,所以我们可以朝着零计算(或者朝负无穷大计算,或者
floor()
,因为Fn对于n是非负的≥ 0):
Fn=⌊ φn/√5.⌋ = 地板(φn/√(五)
如果我们对模M,M感兴趣≥ 我们需要观察上述公式的影响。请注意,表达式“expr MOD M”通常使用in C计算
我们可以应用:对于正实a,b和m,(a mod m)(b mod m)=(a mod m)。地板操作不受影响。这里,a=φn,b=1/√5.这意味着我们可以简化表达式
Fn模块M=⌊ φn/√5.⌋ MOD M
进入
Fn模块M=⌊ (φn模(M)√5) ) / √5.⌋
在这里,我们可以应用,注意到在这一点上的模不是由整数M,而是由M·√五,
换句话说,如果我们有一个函数,它使用浮点模的模幂运算对浮点值进行整数次幂运算,比如
double pow_mod(double base, unsigned int exponent, double modulus);
我们可以使用
#define PHI 1.61803398874989484820458683436563811772
#define SQRT5 2.236067977499789696409173668731276235441;
double fn_mod_m;
unsigned int n, m;
fn_mod_m = floor(pow_mod(PHI, n, SQRT5 * (double)m) / SQRT5);
在这里,是模幂运算的一个很好的候选者。问题:使用长双精度存储无理数是错误的吗?答:是的,因为它们只能在一定程度上精确。您可能想看看像GMP这样的库(请参阅)。不能应用于有理数,只能应用于整数。@pytheos:谢谢。但我想它对较低的价格仍然有效values@MOehm:谢谢。这是否意味着不可能使用黄金比例来实现这一点?你能举个例子说明什么时候可以使用fmodl()和fmod()之类的函数吗?为什么你想用这种方式计算斐波那契数?因为你认为它更快?问题:使用长双精度存储无理数是错误的吗?答:是的,因为它们只能在一定程度上精确。您可能想看看像GMP这样的库(请参阅)。不能应用于有理数,只能应用于整数。@pytheos:谢谢。但我想它对较低的价格仍然有效values@MOehm:谢谢。这是否意味着不可能使用黄金比例来实现这一点?你能举个例子说明什么时候可以使用fmodl()和fmod()之类的函数吗?为什么你想用这种方式计算斐波那契数?因为你认为它更快?你能解释一下你是如何从M型升级到Mroot5型的吗?我试过使用,但它可能只适用于整数?@raksh93:我在答案中添加了解释;因为
(a mod m)*(b mod m)=(a*b)mod m
。floor操作不受影响,因为它只是从结果中减去一个较小的值(小于1),而移动模运算根本不会影响要计算的值。至于模幂运算,你真的应该使用,取而代之的是:维基百科页面甚至有伪代码来告诉你怎么做。或者你可以使用节省内存的方法,在同一页上使用之前的伪代码。对于实数,如PHI和SQRT5,模块化算法的效果不太好。你能解释一下你是如何从mod M到mod Mroot5的吗?我试过使用,但它可能只适用于整数?@raksh93:我在答案中添加了解释;因为(a mod m)*(b mod m)=(a*b)mod m
。地板