鱼C论坛

 找回密码
 立即注册
查看: 1626|回复: 1

[已解决]关于C语言计算斐波那契数列

[复制链接]
发表于 2021-2-2 11:51:58 | 显示全部楼层 |阅读模式
20鱼币
原题:题目2:在斐波那契数列中,找出4百万以下的项中值为偶数的项之和

描述:在使用通项公式计算斐波那契第n项值的过程中要用到double型,但是斐波那契数列在20项以后会变得很大很大,这使得用浮点计算后的误差也变得很大很大,得不到精确的整数值。

问题:对于浮点数转化为整型有没有更准确的解决办法?该题中有没有时间开销比较小的算法?

代码片段如下,万分感谢。

通项公式法求第n项
//通项公式求数列第n项  a_n = (1/sqrt(5))*(pow((sqrt(5)+1)/2,n)+pow((sqrt(5)-1)/2,n))
#define F2_FIBONACCI_SWITCH
#ifdef F2_FIBONACCI_SWITCH

#include "math.h"

#define T_1 0.44721359549995f
#define T_2 1.61803398874989f   //浮点运算会带来误差
#define T_3 0.61803398874989f

unsigned long int Fibonacci(int n){
  double tmp = 0.0f;
  tmp = T_1*(pow(T_2,n)+pow(T_3,n));
  return (unsigned long int)(tmp);  //在整型转换过程中,大数计算误差很大,得错误值
}

#endif

递推法求第n项
#define F1_FIBONACCI_SWITCH
#ifdef F1_FIBONACCI_SWITCH
unsigned long int Fibonacci(int n){
  unsigned long int f1=1,f2=1,temp;
  if (n<3) return 1;
  for (int i = 1; i < n; i++) {
    temp = f1;
    f1 = f2;
    f2 = temp +f1;
  }
  return f1;
}
#endif

完整代码
/*
 * 题目2:在斐波那契数列中,找出4百万以下的项中值为偶数的项之和
 */

#include <stdio.h>

unsigned long int Fibonacci(int n);
int IsEven(unsigned long int n);

int main(){
    unsigned long int sum = 0;
    int k = 1;
  for (unsigned long int i = 1; i < 4000000;) {
    i=Fibonacci(k++);
    printf("%ld ",i);
    IsEven(i) && (sum+=i);
  }
  printf("\n%ld\n",sum);
  return 0;
}

#define F1_FIBONACCI_SWITCH
#ifdef F1_FIBONACCI_SWITCH
unsigned long int Fibonacci(int n){
  unsigned long int f1=1,f2=1,temp;
  if (n<3) return 1;
  for (int i = 1; i < n; i++) {
    temp = f1;
    f1 = f2;
    f2 = temp +f1;
  }
  return f1;
}
#endif

int IsEven(unsigned long int n){
  return n%2?0:1;
}

//通项公式求数列第n项  a_n = (1/sqrt(5))*(pow((sqrt(5)+1)/2,n)+pow((sqrt(5)-1)/2,n))
//#define F2_FIBONACCI_SWITCH
#ifdef F2_FIBONACCI_SWITCH

#include "math.h"

#define T_1 0.44721359549995f
#define T_2 1.61803398874989f   //浮点运算会带来误差
#define T_3 0.61803398874989f

unsigned long int Fibonacci(int n){
  double tmp = 0.0f;
  tmp = T_1*(pow(T_2,n)+pow(T_3,n));
  return (unsigned long int)(tmp);  //在整型转换过程中,大数计算误差很大,得错误值
}

#endif
最佳答案
2021-2-2 11:51:59
本帖最后由 sunrise085 于 2021-2-2 13:53 编辑

浮点型转整型,有精度损失是必然的,这是他们的存储方式导致的,没有解决办法。
而且long本来就满足数据大小的要求了,何必非要去使用double来降低精度
斐波那契数列不要用通项公式求了。直接用基本方法累加就挺简单的啊

想找时间开销少的方法,直接写程序,不要花里胡哨的写好几个函数,能省去不少时间
#include <stdio.h>
int main(){
    unsigned long int sum = 0,i=1,temp1=1,temp2;
    int k = 1;
    for (; i < 4000000;) {
        if(i%2==0){
            printf("%d:%ld \n",k++,i);//若只是完成功能,则删掉这一行,printf特别消耗时间!!
            sum+=i;
        }
        temp2=i;
        i=temp1;
        temp1=i+temp2;
    }
    printf("\nsum=%ld\n",sum);
    return 0;
}

最佳答案

查看完整内容

浮点型转整型,有精度损失是必然的,这是他们的存储方式导致的,没有解决办法。 而且long本来就满足数据大小的要求了,何必非要去使用double来降低精度 斐波那契数列不要用通项公式求了。直接用基本方法累加就挺简单的啊 想找时间开销少的方法,直接写程序,不要花里胡哨的写好几个函数,能省去不少时间
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2021-2-2 11:51:59 | 显示全部楼层    本楼为最佳答案   
本帖最后由 sunrise085 于 2021-2-2 13:53 编辑

浮点型转整型,有精度损失是必然的,这是他们的存储方式导致的,没有解决办法。
而且long本来就满足数据大小的要求了,何必非要去使用double来降低精度
斐波那契数列不要用通项公式求了。直接用基本方法累加就挺简单的啊

想找时间开销少的方法,直接写程序,不要花里胡哨的写好几个函数,能省去不少时间
#include <stdio.h>
int main(){
    unsigned long int sum = 0,i=1,temp1=1,temp2;
    int k = 1;
    for (; i < 4000000;) {
        if(i%2==0){
            printf("%d:%ld \n",k++,i);//若只是完成功能,则删掉这一行,printf特别消耗时间!!
            sum+=i;
        }
        temp2=i;
        i=temp1;
        temp1=i+temp2;
    }
    printf("\nsum=%ld\n",sum);
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-15 04:13

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表