Exponentiation(求高精度幂)

Posted Amysear

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Exponentiation(求高精度幂)相关的知识,希望对你有一定的参考价值。

Exponentiation
Time Limit: 500MS   Memory Limit: 10000K
Total Submissions: 175340   Accepted: 42341

Description

Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems. 

This problem requires that you write a program to compute the exact value of Rn where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.

Input

The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9.

Output

The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don\'t print the decimal point if the result is an integer.

Sample Input

95.123 12
0.4321 20
5.1234 15
6.7592  9
98.999 10
1.0100 12

Sample Output

548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201

Hint

If you don\'t know how to determine wheather encounted the end of input: 
s is a string and n is an integer 
C++

while(cin>>s>>n)
{
...
}
c
while(scanf("%s%d",s,&n)==2) //to see if the scanf read in as many items as you want
/*while(scanf(%s%d",s,&n)!=EOF) //this also work */
{
...
}

Source

大意:

对数值很大、精度很高的数进行高精度计算是一类十分常见的问题。比如,对国债进行计算就是属于这类问题。

现在要你解决的问题是:对一个实数R( 0.0 < R < 99.999 ),要求写程序精确计算 R 的 n 次方(Rn),其中n 是整数并且 0 < n <= 25。

Input

T输入包括多组 R 和 n。 R 的值占第 1 到第 6 列,n 的值占第 8 和第 9 列。

Output

对于每组输入,要求输出一行,该行包含精确的 R 的 n 次方。输出需要去掉前导的 0 后不要的 0 。如果输出是整数,不要输出小数点。 

解题思路:

(1)pow精度不够

函数原型:double pow( double x, double y );

头文件:math.h/cmath(C++中)

功能:计算x的y次方

返回值:x不能为负数且y为小数,或者x为0且y小于等于0,返回幂指数的结果。

1 #include<math.h>  
2 #include<stdio.h>  
3 int main()  
4 {  
5   double x=2.0,y=3.0;  
6   printf("%lf raised to %lf is %lf\\n",x,y,pow(x,y));  
7   return 0;  
8 }  

(2)模拟乘法运算过程

  必须自己模拟乘法运算过程,进行高精度的运算。

  题目把输入的数限制在了6位,即只有5位数字,方便了我们解题。

  我们将输入数字,以字符串形式读入,找到小数所在的位数,计算出结果应包含的小数的位数,比如说第一个算式“95.123 12”的小数的位数应该有3*12位。

  解题的关键在于进行数据的处理,即模拟整数乘法,使用倒序数组,为什么使用倒序数组呢?我们模拟一下竖式乘法过程,例如:123*123:

  1  2  3

 x         3

——————

  3  6  9

先用个位乘被乘数;

  1  2  3

 x     2

——————

  2  4  6

  +    3  6   9

——————

  2  7  12  9

在用十位乘被乘数,并相加。

对大于10的进行进位:2  7  12  9 ==》 2  8  2  9

  1  2  3

 x  1

——————

  1  2  3

 +     2  8  2  9

————————

  1  4  11 2  9

在用百位乘被乘数,并相加。

对大于10的进行进位:1  4  11 2  9 ==》 1  5  1  2  9

  从上面的乘法竖式中,我们是向前进位,由于我们不知道最后得到的数据的位数,所以采用倒序存储,向后进位;从0位开始乘,结果也从0位开始存,非常方便。这样得出的结果也是倒序的。

  为了计算方便,我们不把数字多余的0去掉,而是在最后判断小数点的位置,然后输出该输出的数位。

  每次乘法,都是用题目给的r乘上你上一次得出的结果,如果是第一次计算,那么就是r,计算的结果直接加到一个初始化为0的250大小的数组里面,注意是加。乘法的过程很容易模拟出来,就是让乘数让乘数第一位把你的结果的所有位乘一遍,然后再让第二位乘,注意加进数组时,有一个偏移量,乘法竖式都是这么写的,大家体会下。

  开一个250的数组m存储结果,并且开一个250的数组jieguo存储中间结果,并且需要一个长度为6的int型数组存储输入的String类型的数据r。

  输出结果时要小心,因为数组中存储的数位是倒序的,且没有小数点,需要计算从两边向中间的小数点方向第一个不为0数的位置。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<string>
 4 #define MAX 250
 5 using namespace std;
 6 int main()
 7 {
 8     string r;//底数
 9     int n,dian;
10     short Chengshu[6];
11     short m[MAX],jieguo[MAX];
12     while(cin>>r>>n)
13     {
14         for(int i=0;i<=MAX;i++) {m[i]=jieguo[i]=0;}//初始化
15         for(int j=0;j<6;j++) {Chengshu[j]=0;}
16         dian = 0;//小数点位置
17         size_t pos = r.find(".");
18         if(pos != string::npos) dian = (5-pos)*n;
19         for(int i=5,j=0;i>=0;i--)
20         {//注意此处进行倒序存储
21             if(r[i] != \'.\') {
22                     Chengshu[j] = m[j] = jieguo[j] =  r[i]-\'0\';
23                     //此处要给m[]赋值,当n=1时直接输出
24                     j++;
25             }
26         }
27         while(n>=2)//当乘幂大于等于2的时候,等于1可直接处理0输出
28         {
29             for(int i=0;i<MAX;++i) m[i]=0;
30             for(int i=0;i<5;i++)
31             {//chengshu[i]
32                 for(int j=0;j<MAX;j++)
33                 {
34                     if(Chengshu[i]==0) break;
35                     else{
36                         m[i+j] += Chengshu[i]*jieguo[j];
37                         //对>9 的进行处理
38                         for(int t=i+j;m[t]>9;++t)//处理进位
39                         {
40                              m[t+1]+=m[t]/10;
41                              m[t]=m[t]%10;
42                         }
43                     }
44                 }
45             }
46             //更新被乘数
47             for(int k=0;k<MAX;k++)
48             {
49                  jieguo[k] = m[k];
50             }
51             n--;
52         }
53         int first = -1;
54         for(int i=MAX-1;i>=dian;i--)
55         {//从右向左查找第一个不为0的位
56             if(m[i]>0)
57             {
58                 first = i;break;
59             }
60         }
61         int last = dian;
62         for(int j=0;j<dian;j++)
63         {//从左向右查找小数点后第一个不为0的位
64             if(m[j]>0) {
65                 last = j;break;
66             }
67         }
68 
69         if(first != -1)//整数位不全为0
70         {
71             for(int k=first;k>=dian;k--)
72                 cout<<m[k];
73         }
74 
75         if(last != dian)//有小数位
76         {
77             cout<<".";
78             for(int k=dian-1;k>=last;k--)
79                 cout<<m[k];
80         }
81         cout<<endl;
82     }
83     return 0;
84 }

 

 

 

java中有一个类 :java.math.BigDecimal

 

 1 import java.io.*;
 2 import java.util.*;
 3 import java.math.BigDecimal;
 4 
 5 public class Main
 6 {
 7     public static void main(String args[])throws Exception
 8     {
 9         Scanner cin=new Scanner(System.in);
10         while(cin.hasNext())
11         {
12             BigDecimal r=cin.nextBigDecimal();
13             int n=cin.nextInt();
14             r=r.pow(n).stripTrailingZeros();//去掉小数点后面的零
15             String m_string=r.toPlainString();//不带指数段的字符串表示形式
16             if(m_string.charAt(0)==\'0\')
17             m_string=m_string.substring(1);
18             System.out.println(m_string);
19         }
20     }
21 }

 

 

 
 
 

以上是关于Exponentiation(求高精度幂)的主要内容,如果未能解决你的问题,请参考以下文章

Exponentiation(高精度大数)

POJ-1001-Exponentiation(高精度大数)

ACM_Exponentiation(java高精度)

poj1001 Exponentiation

nyoj-155-求高精度幂(java大数)

Java-POJ1001-求高精度幂