部分高精度算法c语言

部分高精度算法

② 高精度除以低精度;

算法:按照从高位到低位的顺序,逐位相除。在除到第j位时,该位在接受了来自第j+1位的余数后与除数相除,如果最高位为零,则商的长度减一。源程序如下:

#include  <stdio.h>
#define   N  500

main()

{

  int  a[N] = {0}, c[N] = {0};

  int  i, k, d, b;

  char  a1[N]; 

  printf("Input 除数:");

  scanf("%d", &b);

  printf("Input 被除数:");

  scanf("%s", a1);

  k = strlen(a1);

  for(i = 0; i < k; i++)  a[i] = a1[k - i - 1] - '0';

  d = 0;

  for(i = k - 1; i >= 0 ; i--)

  {

     d = d * 10 + a[i];

     c[i] = d / b;

     d = d % b;     

  }  

  while(c[k - 1] == 0 && k > 1)  k--; 

  printf("商=");

  for(i = k - 1; i >= 0; i--)  printf("%d", c[i]);

  printf("\n余数=%d", d);   

}    

③ 高精度乘以高精度(要求用尽可能少的存储单元);

算法:用数组保存两个高精度数,然后逐位相乘,注意考虑进位和总位数。源程序如下:

#include  <stdio.h>

main()

{

  int  a[240] = {0}, b[240] = {0}, c[480] = {0};

  int  i, j, ka, kb, k;

  char  a1[240], b1[240];

  gets(a1);   

  ka = strlen(a1);

  gets(b1);   

  kb = strlen(b1);

  k = ka + kb;

  for(i = 0; i < ka; i++)  a[i] = a1[ka-i-1] - '0';

  for(i = 0; i < kb; i++)  b[i] = b1[kb-i-1] - '0';

  for(i = 0; i < ka; i++)

    for(j = 0; j < kb; j++)

    {

      c[i + j] = c[i + j] + a[i] * b[j];

      c[i + j +1] = c[i + j +1] + c[i + j]/10;

      c[i + j] = c[i + j] % 10;

    }

  if(!c[k])  k--;

  for(i = k-1; i >= 0; i--)  printf("%d", c[i]);       

}    
④ 高精度除以高精度(要求用尽可能少的存储单元);

算法:用计算机模拟手算除法,把除法试商转化为连减。

#include  <stdio.h>

#define   N  500

int  bj(int a[], int b[], int k1, int k2)   /*比较大小函数*/

{

   int i, t, flag;       /*flag作标志位*/

   if(k1 < k2) 

     flag = 0;           /*被除数小于除数返回0*/

   else if(k1 > k2) 

          flag = 1;      /*被除数大于除数返回1*/

        else

          {              /*被除数和除数位数相等则逐位进行比较*/

            i = k1;

            t = 0;

            while(t == 0 && i > 0)

            {

              if(a[i] > b[i]) {t = 1; flag = 1;}

              else if(a[i] == b[i])  i--;

              else  {t = 1; flag = 0;}       

            }

            if(i == 0 && t == 0)  flag = 2;     /*被除数等于除数返回2*/

          }

  return flag;          

}

int  jf(int a[], int b[], int k1, int k2)       /*减法运算*/

{

  int  i, k, d[N];

  for(i = 0; i < k2; i++)  d[i] = b[i];        /*把除数赋给数组d*/

  for(i = k2; i < N; i++)  d[i] = 0;          /*d数组无数据的高位置0*/

  k = k1 - k2 - 1;                            /*计算减法起始位置*/

  if(k < 0)  k = 0;

  if(k > 0)

  {

    for(i = k2 - 1; i >= 0; i--)  d[i + k] = d[i];  /*移动减数位数与被减数对齐*/

    for(i = 0; i < k; i++)  d[i] = 0;            /*移动后的其余位置0*/

  } 

  for(i = 0; i < k1; i++)

  {

    if(a[i] >= d[i])  a[i] -= d[i];

    else

    {

      a[i + 1] = a[i + 1] - 1;

      a[i] = 10 + a[i] - d[i]; 

    }    

  }  

  return k;

}

main()

{
  int  a[N] = {0}, b[N] = {0}, c[N] = {0}, d[N] = {0};

  int  i, ka, kb, m, t, t1, t2, k, x, kd, kk;

  char  a1[N], b1[N]; 

  printf("Input 被除数:");

  scanf("%s", a1);

  ka = strlen(a1);

  for(i = 0; i < ka; i++)  a[i] = a1[ka - i -1] - '0';

  printf("Input 除数:");

  scanf("%s", b1);

  kb = strlen(b1);

  for(i = 0; i < kb; i++)  b[i] = b1[kb - i -1] - '0';

  kd = ka;    /*保存被除数位数  */

  t2 = bj(a, b, ka, kb);

  m = 0;

  do

  {

    while(a[ka - 1] == 0)  ka--;

    t = bj(a, b, ka, kb);   

    if(t >= 1)

    {

      k = jf(a, b, ka, kb);

      c[k]++;     

      if(k > m)  m = k;

      t1 = 0;

      for(i = k; i <= m; i++)

      {

        x = c[i] + t1;

        c[i] = x % 10;

        t1 = x / 10;    

      }

      if(t1 > 0)  {m++; c[m] = t1;  }    

    }   

  }while(t == 1);

  if(t2 == 0) 

  {

    printf("商=0"); 

    printf("\n余数=");

    for(i = kd - 1; i >= 0; i--)  printf("%d", a[i]);

    exit(1); 

  }

  if(t2 == 2)

  {

    printf("商 = 1"); 

    printf("\n余数 = 0");

    exit(1); 

  }

  kk = kd;

  while(!c[kd - 1])  kd--;

  printf("商 = ");

  for(i = kd - 1; i >= 0; i--)  printf("%d", c[i]);

  while(!a[kk])  kk--;

  printf("\n余数 = ");

  if(kk < 0) 

  {

    printf("0"); 

    exit(1);

  }

  for(i = kk; i >= 0; i--)  printf("%d", a[i]);

}

⑤ N!,要求精确到P位(0〈P〈1000〉。

算法:结果用数组a保存,开始时a[0]=1,依次乘以数组中各位,注意进位和数组长度的变化。源程序如下:

#include   <stdio.h>
#define    M   1000

main()

{

  int a[M], i, n, j, flag = 1;

  printf("n=");

  scanf("%d",&n);

  printf("n!=");

  a[0] = 1;

  for(i = 1; i < M; i++) a[i] = 0;

   for(j = 2; j <= n; j++)

   {

     for(i = 0; i < flag; i++) a[i] *= j;

     for(i = 0; i < flag; i++)

       if(a[i] >= 10)

       {

         a[i+1] += a[i]/10;

         a[i] = a[i] % 10;

         if(i == flag-1)  flag++;

       }

    }

  for(j = flag - 1; j >= 0; j--)

    printf("%d", a[j]);

}

问题5. 以字符串方式由键盘输入两个高精度的8进制正整数,串长小于255,以第一个数为被除数,第二个数为除数,进行高精度除法运算

,并显示商和余数。

算法:

问题6. 麦森数

【问题描述】形如2P-1的素数称为麦森数,这时P一定也是个素数。但反过来不一定,即如果P是个素数,2P-1不一定也是素数。到1998年底,

人们已找到了37个麦森数。最大的一个是P=3021377,它有909526位。麦森数有许多重要应用,它与完全数密切相关。

任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示)

【输入格式】

文件中只包含一个整数P(1000<P<3100000)

【输出格式】

第一行:十进制高精度数2P-1的位数。

第2-11行:十进制高精度数2P-1的最后500位数字。(每行输出50位,共输出10行,不足500位时高位补0)

不必验证2P-1与P是否为素数。

【输入样例】

1279

【输出样例】

386

00000000000000000000000000000000000000000000000000

00000000000000000000000000000000000000000000000000

00000000000000104079321946643990819252403273640855

38615262247266704805319112350403608059673360298012

23944173232418484242161395428100779138356624832346

49081399066056773207629241295093892203457731833496

61583550472959420547689811211693677147548478866962

50138443826029173234888531116082853841658502825560

46662248318909188018470682222031405210266984354887

32958028878050869736186900714720710555703168729087

算法:2的幂可以转化成左移运算,为了提高运算速度,可每次左移10位,即每次乘210。对于个位单独考虑,每次左移一位。源程序如下:
#include <stdio.h>
#include <math.h>

#define  MAX  100000

main()
{

   int p;

   int i, j;

   scanf("%d", &p);

   printf("%d\n", (int)(p * log10(2.0)) + 1);

   long  store[110] = {0};

   store[0] = 1;

   int left = p % 10;

   p /= 10;

    for(i = 1; i <= p; i++)

    {

      for(j = 0; j <= 100; j++)

        store[j] <<= 10;

      for(j = 0; j <= 100; j++)

      {

        if(store[j] >= MAX)

        {

          store[j + 1] += store[j] / MAX;

          store[j] %= MAX;

        }

      }

    }

    for(i = 1; i <= left; i++)

    {

      for(j = 0; j <= 100; j++)

        store[j] <<= 1;

      for(j = 0; j <= 100; j++)

      {

        if(store[j] >= MAX)

        {

          store[j + 1] += store[j] / MAX;

          store[j] %= MAX;

        }

      }

    }

    store[0] -= 1;

    for(i = 1; i < 100; i++)

    {

      if(store[i - 1] < 0)

      {

         store[i] -= 1;

         store[i - 1] += MAX;

      }

      else

        break;

    }

    for(i = 99; i >= 0; i--)

    {

      printf("%05d", store[i]);

      if((100 - i) % 10 == 0)

          printf("\n");

    }

}


问题7. 精确计算:1n+2n+3n+…+mN的后K位数,其中1<=n<=9999,1<=m<=9999,1<=K<=99。N,m,K从键盘输入。

  例:输入:n=3 m=3 K=3        输出:36


问题8. 有一个正整数N(N可能达到120位),它是由若干个不大于65535的正整数相乘而得到的。请把这个数分解成素数因子(质因子)的乘积


输入:输入文件只有一行为N的值。
输出:(1)素数因子由小到大分行输出;
     (2)每一行输出一个素数因子和该素数因子的个数,用一个空格分开;
     (3)如果正整数N的分解中有一个以上的大于65535的素数,请按照(1)、(2)的要求输出分解中的小于65535的素数后,在下一行输出

“DATA  ERROR!”。

算法:先将2到65535之间的所有素数保存在数组中,用这个数去除数组中的每一个数,得到一个质因数就打印出来。源程序如下:

#include  <stdio.h>
#include  <math.h>

int length, temp[120];

int sushu(int a[])

{

  int i, j, k = 0, m;

  for(i = 2; i <= 65537; i++)

  {

    m = sqrt(i);

    for(j = 2; j <= m; j++)

      if(i % j == 0)  break;

    if(j > m)

    {

      a[k] = i;

      k++;   

    }        

  }
  return k;    

}


 
 
int divide(int a[], int k)

{

  int i, d = 0;

  for(i = length - 1; i >= 0; i--)

  {

     d = d * 10 + a[i];

     temp[i] = d / k;

     d = d % k;     

  }  

  if(!d)

    {

      while(temp[length - 1] == 0 && length > 1)  length--;

      for(i = 0; i < length; i++)

      {

        a[i] = temp[i];

        temp[i] = 0;     

      }

      for(i = length; i < 120; i++) a[i] = 0;   

    }

    else 

      for(i = 0; i < length; i++)  temp[i] = 0;

  return d;    

}


 
 
main()
{

  int i, k, s, d;       /*s计数器; d余数*/

  int a[6600], b[120] = {0}, c[120] = {0};

  char b1[120];

  gets(b1);
 
  length = strlen(b1);

  for(i = 0; i < length; i++)  b[i] = b1[length - i - 1] - '0';

  k = sushu(a);

  for(i = 0; i < k; i++)

  {

    s = 0;

    d = divide(b, a[i]);

    while(!d)

    {

      s++;

      d = divide(b, a[i]);        

    }

    if(i == k - 1) 

    {

      printf("Data Error!");

      break;

    }

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫一样的女子245

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值