這道題屬於高精度乘法運算,要求輸入一個實數R一個指數N,求實數R的N次方,因爲R有5個數位,而N又特別大,所以用C++自帶的數據類型放不下.
解題思路是經過數組儲存每次乘積結果和底數的每一位數,按照乘法上下算式的方法,計算底數乘數數組每一位與臨時結果數組的每一位的乘積,(由於算術運算中是從數的後面往前算的,這裏存儲數時要先倒序,輸出時再顛倒過來,)而後偏移相加,判斷得出的臨時結果數組的每一位是否大於9,經過除法和取模實現進位和取餘.至此得出一個有不少無效數位的結果數組(不少無效的0).
最後判斷結果數組的每一位是否爲0,先輸出小數點前面的數,後輸出小數點後面的數,最終得出乘法結果.
這個題目實際上考的是高精度乘法,高精度的其餘運算和這個差很少,原理都是同樣的.
ios
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.數組
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.函數
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.ui
95.123 12
0.4321 20
5.1234 15
6.7592 9
98.999 10
1.0100 12spa
If you don't know how to determine wheather encounted the end of input:
s is a string and n is an integercode
#include<iostream> #include<cstring> using namespace std; int main() { string r; //底數 int n,dianwei; //指數,小數點位置 const int len=200; //數位長度 short result[len],jieguo[len],chengshu[6]; //最終結果,臨時結果,底數乘數 while(cin>>r>>n) { //初始化 for(int i=0;i<len;++i) jieguo[i]=result[i]=0; for(int i=0;i<6;++i) chengshu[i]=0; dianwei=0; //獲得底數小數點位置 size_t pos = r.find('.'); //若是底數中有小數點 獲取小數點後面有多少位數 if(pos!=string::npos) dianwei=(5-pos)*n; //把底數中全部不是小數點的數字挑出來轉換爲int並賦給最終結果,臨時結果,底數乘數 獲得的是3個5位先後顛倒的數組 之因此顛卻是由於乘法是從後往前乘的 for(int i=5,j=0;i>=0;--i) { if(r[i]!='.') { jieguo[j]=result[j]=chengshu[j]=r[i]-'0'; ++j; } } //當指數大於1時 進行如下運算 等於1時跳過這段程序直接輸出 while(n>=2) { --n; //初始化最終結果數組 for(int i=0;i<len;++i) result[i]=0; for(int i=0;i<5;++i) //從底數乘數的每一位 { //底數乘數每位數和臨時結果每位數相乘的臨時變量 int temp; for(int j=0;j<len;++j) //乘以臨時結果的每一位 { //若是底數乘數某一位是0 不必乘下去了 跳出當前循環 if(chengshu[i]==0) break; temp=chengshu[i]*jieguo[j]; //i+j實現乘法相加時的移位 result[i+j]+=temp; //++t遍歷全部結果數組中大於9的數 用除法和取模實現進位和餘數 for(int t=i+j;result[t]>9;++t) { result[t+1]+=result[t]/10; result[t]=result[t]%10; } } } //把一次乘法後的結果賦給臨時結果來進行下次乘方 for(int i=0;i<len;++i) jieguo[i]=result[i]; } //獲取最終結果從後數第一個不爲0的數做爲第一個數的標誌位 之因此從後數 是由於以前顛倒的數要顛倒回來了 int firstindex=-1; for(int i=len;i>=dianwei;--i) { if(result[i]>0) { firstindex=i; break; } } //獲取 最終結果從前數第一個不爲0的數做爲最後一個數的標誌位 int lastindex=-1; for(int i=0;i<dianwei;++i) { if(result[i]>0) { lastindex=i; break; } } //若是最終結果數組中不全是0 倒序輸出結果數組中小數點前面的數 if(firstindex!=-1) { while(firstindex>=dianwei) { cout<<result[firstindex]; --firstindex; } } //若是最終結果數組中不全是0 倒序輸出結果數組中小數點後面的數 if(lastindex!=-1) { cout<<'.'; --dianwei; while(dianwei>=lastindex) { cout<<result[dianwei]; --dianwei; } } cout<<endl; } }
#附錄:blog
#include <iostream> #include <cstring> using namespace std; const int N=100;//最多100位 int main() { int a[N+1],i; string s1; cin>>s1;//數s1 memset(a,0,sizeof(a)); //數組清0 a[0]=s1.length(); //位數 for(i=1;i<=a[0];i++) { a[i]=s1[a[0]-i]-'0';//將字符轉爲數字並倒序存儲. } return 0; }
#include <iostream> using namespace std; const int N=100;//最多100位 int main() { int a[N+1],i,s,key; cin>>key;//數key memset(a,0,sizeof(a)); //數組清0 i=0;//第0位 while(key) //當key大於0 { a[++i]=key%10;//取第i位的數 key=key/10; } a[0]=i; //共i位數 return 0; }
如下程序都只寫函數,不寫完整程序,全部高精度數存儲都知足上述約定。ip
int compare(int a[],int b[]) //比較a和b的大小關係,若a>b則爲1,a<b則爲-1,a=b則爲0 { int i; if (a[0]>b[0]) return 1;//a的位數大於b則a比b大 if (a[0]<b[0]) return -1;//a的位數小於b則a比b小 for(i=a[0];i>0;i--) //從高位到低位比較 { if (a[i]>b[i]) return 1; if (a[i]<b[i]) return -1; } return 0;//各位都相等則兩數相等。 }
int plus(int a[],int b[]) //計算a=a+b {int i,k; k=a[0]>b[0]?a[0]:b[0]; //k是a和b中位數最大的一個的位數 for(i=1;i<=k;i++) { a[i+1]+=(a[i]+b[i])/10; //如有進位,則先進位 a[i]=(a[i]+b[i])%10; //計算當前位數字,注意:這條語句與上一條不能交換。 } if(a[k+1]>0) { a[0]=k+1; //修正新的a的位數(a+b最多隻能的一個進位) } else { a[0]=k; } return 0; }
int gminus(int a[],int b[]);//計算a=a-b,返加符號位0:正數 1:負數 { int flag,i flag=compare(a,b); //調用比較函數判斷大小 if (falg==0)//相等 { memset(a,0,sizeof(a));return 0; //若a=b,則a=0,也可在return前加一句a[0]=1,表示是 1位數0 } if(flag==1) //大於 { for(i=1;i<=a[0];i++) { if(a[i]<b[i]){ a[i+1]--;a[i]+=10;} //若不夠減則向上借一位 a[i]=a[i]-b[i]; } while(a[a[0]]==0) a[0]--; //修正a的位數 return 0; } if (flag==-1)//小於 則用a=b-a,返回-1 { for(i=1;i<=b[0];i++) { if(b[i]<a[i]){ b[i+1]--;b[i]+=10; //若不夠減則向上借一位 } a[i]=b[i]-a[i];} a[0]=b[0]; while(a[a[0]]==0) a[0]--; //修正a的位數 return -1; } }
int multi1(int a[],long key) //a=a*key,key是單精度數 { int i,k; if (key==0){memset(a,0,sizeof(a));a[0]=1;return 0;} //單獨處理key=0 for(i=1;i<=a[0];i++) { a[i]=a[i]*key;//先每位乘起來 } for(i=1;i<=a[0];i++) { a[i+1]+=a[i]/10;a[i]%=10; //進位 } //注意上一語句退出時i=a[0]+1 while(a[i]>0) { a[i+1]=a[i]/10;a[i]=a[i]%10;i++;a[0]++]; //繼續處理超過原a[0]位數的進位,修正a的位數 } return 0; }