8、大数,高精度计算---高精度幂次

大数是算法语言中的数据类型无法表示的数,其位数超过最大数据类型所能表示的范围,所以,在处理大数问题时首先要考虑的是怎样存储大数,然后是在这种存储方式下其处理的实现方法。

一般情况下大数的存储是采用字符数组来存储,即将大数当作一个字符串来存储,而对其处理是按其处理规则在数组中模拟实现。

五  大数幂次。

 

问题来源:   《c程序设计竞赛实训教程》

 

问题描述:

计算国债对于计算机来说是一件很繁重的事情,该问题涉及到的精度很高。现需要你编写一个程序用来计算R的n次方。  这里R是一个实数(0.0<R<99.999),而n是一个整数.

 

问题分析:

计算结果的位数很长,还是涉及到大数的处理,不能用普通类型数表示,只能用数组表示,类似于大数的做法,利用数组来模拟手算过程。为了计算方便,数组中将小数点去掉,记住其位置,然后只计算整数的幂次,最后将小数点在结果中的位置计算出来,放在结果中即可。

其实本质上也是大数乘法的一部分。只是这里涉及了小数点的处理。

思想差不多,也就没自己去写。   下面的代码来自书中的实例源码。

 

[cpp]  view plain copy
  1. #include<stdio.h>  
  2. #include<string.h>  
  3.   
  4. #define N 200  
  5. //函数mult功能:  实现p1中长度为len1的大数和p2中长度为len2的大数相乘,  
  6. //结果保存在p2中,同时返回结果的位长len2  
  7. void Mult( int *p1, int *p2, int len1, int *len2 )  
  8. {  
  9.     int i, j, k, d, ts[N];  
  10.     for ( i=0; i<N; i++ )  
  11.         ts[i] = 0;  
  12.     for ( i=0; i<len1; i++ )  
  13.         for ( j=0; j<*len2; j++ )  
  14.             ts[i+j] += p1[i] * p2[j];      //大数乘法  
  15.     k = len1 + (*len2);                    //结果可能最大位长  
  16.     while ( k>0 && ts[k]==0 )  
  17.         k--;  
  18.     k++;  
  19.     for ( i=0,d=0; i<k; i++ )             //处理进位  
  20.     {  
  21.         p2[i] = ( ts[i] + d ) % 10;  
  22.         d = ( ts[i] + d ) / 10;  
  23.     }  
  24.     if ( d>0 )                          //最高位进位  
  25.     {  
  26.         p2[i] = d;  
  27.         k++;  
  28.     }  
  29.     *len2 = k;  
  30. }  
  31. int main()  
  32. {  
  33.     char str_a[10], str_b[N+1];  
  34.     int i, t, j, k, len_a, len_b, n, pot;  
  35.     int a[10], b[N];  
  36.   
  37.     scanf("%d",&t);        //读入测试组数  
  38.     while ( t-->0 )  
  39.     {  
  40.         scanf("%s%d", str_a, &n );  
  41.         len_a = strlen(str_a);  
  42.         k = len_a - 1;  
  43.         while ( k>=0 && str_a[k] != '.' )       //找出小数点位置  
  44.             k--;  
  45.         if ( k<0 )               //小数点后的位数  
  46.             pot = 0;  
  47.         else  
  48.         {  
  49.             j  = len_a - 1;  
  50.             while ( j>0 && str_a[j]=='0' )      //去掉小数点尾部的0  
  51.                 j--;  
  52.             len_a = j + 1;  
  53.             str_a[len_a] = '\0';  
  54.             pot = len_a -k - 1;            //小数点后的位数  
  55.         }  
  56.         i = len_a - 1;  
  57.         k = 0;  
  58.         while ( i>=0 )  
  59.         {  
  60.             if ( str_a[i] != '.' )    //将大数颠倒存入并且去掉小数点  
  61.                 a[k++] = str_a[i] - '0';  
  62.             i--;  
  63.         }  
  64.   
  65.         for ( i=0; i<N; i++ )  
  66.             b[i] = 0;  
  67.         len_a = len_b = k;  
  68.         for ( i=0; i<len_a; i++ )  
  69.             b[i] = a[i];          //乘数相同  
  70.         for ( i=1; i<n; i++ )  
  71.             Mult( a, b, len_a, &len_b );       //做n-1次相乘  
  72.         k = pot * n;             //小数点位置  
  73.         n = len_b > k? len_b:k;  
  74.         for ( j=0,i=n-1; i>=0; i-- )      //结果转为字符串  
  75.         {  
  76.             if ( i==k-1 )  
  77.                 str_b[j++] = '.';  
  78.             str_b[j++] = b[i] + '0';  
  79.         }  
  80.         str_b[j] = '\0';  
  81.         printf("%s\n",str_b);      //输出结果  
  82.     }  
  83.     return 0;  
  84. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值