提取大数前四位

转自若流芳千古

 

当一个数非常大时,如何求出其前几位呢?

如果是给定一个特定的数,当然可以逐步取出每一位即可。如

a得个位,a/10得百位,a/10/10得千位。

但是,当求x^y的前几位时怎么办呢?若x,y都非常大,则显然很难解决:也许可以用大数乘法,暴力求解,结果自然是既占内存,又耗时间。

还有,此题斐波拉契数列的前几位,显然求出每个斐波拉契数是不现实的。因此,可以采用取对数的方法来解决。

先看对数的性质,loga(b^c)=c*loga(b),loga(b*c)=loga(b)+loga(c);假设给出一个数10234432,那么log10(10234432)=log10(1.0234432*10^7)=log10(1.0234432)+7
log10(1.0234432)就是log10(10234432)的小数部分.

log10(1.0234432)=0.010063744

10^0.010063744=1.023443198,

要求该数的前4位,则将1.023443198*1000即可。

因此,pow(10.0,x的小数部分)即可方便求出x的前几位。

求一数的前4位的对数方法可以表述为:

double x,temp;

while(scanf("%lf",&x)!=EOF)

{

temp=log(x)/log(10.0);

temp=temp-floor(temp); //floor(temp)函数求出小于temp的最大整数

temp=pow(10.0,temp);

while(temp<1000)

temp*=10;

//printf("%.0lf\n",temp); //采用浮点表达法时会四舍五入

printf("%d\n",(int)temp);//此处不需四舍五入,直接舍弃后面的位

}

}

 

下面给出斐波那契数列通项公式:

但是这个题要是直接套公式还是会超时,所以我们将通项公式左右取对数,化简得

log10(F(n))=-0.5*log10(5.0)+((double)n)*log(s)/log(10.0)+log10(1-((1-√5)/(1+√5))^n)

s  =  (1+sqrt(5.0))/2.0;

 

 

例子转自xieqinghuang

 

#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
//const int N = 2;
struct Mat
{
   int matrix[N][N]; 
};
Mat mat, mt;
int n, m = 10000;
Mat mul(Mat a, Mat b) ///***********************
{ 
 int i, j, k;
 Mat c; 
 for (i = 0; i <2 ; i++)          //N
  for (j = 0; j < 2; j++)     //N
  {
   c.matrix[i][j] = 0;  
   for (k = 0; k < 2; k++) //N   
   {   
       c.matrix[i][j] += a.matrix[i][k] * b.matrix[k][j]; 
    if (c.matrix[i][j] >= m) //m=10000,即取最后四位。    
     c.matrix[i][j] %= m;    
   }   
  }  
  return c;  
}//****************************************8
Mat solve(int m)
{ 
 Mat mt;
 if (m==1)
  return mat; 
 if (m%2==1)  //m为奇数时。(m&1)
  return mul(solve(m-1), mat); 
 else //m 为偶数。
 {  
  mt = solve(m / 2);  
  return mul(mt, mt);  
 } 
}
//*********************************************
inline void init()
{
 mat.matrix[0][0] = mat.matrix[0][1] = mat.matrix[1][0] = 1;
 mat.matrix[1][1] = 0; 
}
int main()
{ 
 int f[40] = { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 }; 
 int i; 
 for (i = 11; i < 40; ++i)  
 {  
  f[i] = f[i - 1] + f[i - 2];  
 }
 //freopen("t", "r", stdin); 
 while (scanf("%d", &n) != EOF)  
 {  
  if (n < 40)   //小于八位的直接输出!
  {  
   printf("%d\n", f[n]);  
   continue;   
  }  
  double temp = (1 + sqrt(5.0)) / 2.0; 
  double val = n * log10(temp) - 0.5 * log10(5.0);  
  temp = val - (int) val;  
  temp = pow(10.0, temp);  
  //while(temp < 1000)  
  temp *= 1000;  
  printf("%d...", (int) temp); //输出前四位!! 
  Mat ans;           //[1 1]
  init(); //********** // [1 0]给矩阵赋值。
  ans = solve(n - 1); //*********************???????????????????????????
  i = ans.matrix[0][0];
  if (i < 10)  
   printf("000%d\n", i);  
  else if (i < 100)   
   printf("00%d\n", i); 
  else if (i < 1000)   
   printf("0%d\n", i); 
  else  
   printf("%d\n", i); 
 } 
 return 0; 
}

<提取的公因式s,然后将后面化成两式相乘的形式>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值