poj 1001 字符串乘法以及处理精度问题
#include<iostream> #include<cstring> using namespace std; int main() { string r; int n,dianwei; const int R_LEN=160; short result[R_LEN],jieguo[R_LEN],chengshu[6]; while(cin>>r>>n) { int len=0; for(int i=0;i<R_LEN;++i) jieguo[i]=result[i]=0;//初始化为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; //结果中的小数点的位数 for(int i=5,j=0;i>=0;--i) //得到倒序数字数组 { if(r[i]!='.') { jieguo[j]=result[j]=chengshu[j]=r[i]-'0';//提取数位 ++j; } } //整数相乘步骤 while(n>=2)//指数大于等于2的时候计算,否则就是直接去除多余0输出了 { --n; for(int i=0;i<R_LEN;++i)//对结果数组一初始化 result[i]=0; for(int i=0;i<5;++i)//乘数数位循环 { int c; for(int j=0;j<R_LEN;++j)//被乘数数位循环 { c=chengshu[i]*jieguo[j]; result[i+j]+=c; for(int t=i+j;result[t]>9;++t)//处理进位 即当result[t]<=9 该数组不进位时停止 { result[t+1]+=result[t]/10; result[t]=result[t]%10; } } } for(int i=0;i<R_LEN;++i) jieguo[i]=result[i];//结果转存 这里的jieguo数组作用是存上一次的结果,用来和乘数向乘,因为result[]=jieguo[]*chengshu[] } //找边界步骤 int firstindex=-1; for(int i=R_LEN-1;i>=dianwei;--i)//从右往左查找小数点前第一个不为0的数 处理前导0 记录边界 { if(result[i]>0) { firstindex=i;//记录 小数点前第一个不为0的数的下标 方便输出 break; } } int lastindex=-1; for(int i=0;i<dianwei;++i)//从左往右查找小数点前第一个不为0的数 处理后导0 记录边界 { if(result[i]>0) //记录 小数点前第一个不为0的数的下标 方便输出 { lastindex=i; break; } } //输出步骤 if(firstindex!=-1)//输出小数点前的部分 { while(firstindex>=dianwei) { cout<<result[firstindex]; --firstindex; } } if(lastindex!=-1)//如果有小数部分,先输出小数点,再输出小数部分 { cout<<'.'; --dianwei; while(dianwei>=lastindex) { cout<<result[dianwei]; --dianwei; } } cout<<endl; } }
我自己重写的一遍
#include<iostream> #include<cstdio> #include<string> #include<string.h> #include<cstring> using namespace std; #define maxn 160 int main() { string r; int n; while (cin >> r >> n) { int a[6], result[maxn], temp[maxn]; //先找到小数的位置 int weishu=0,pos=-1; for (int i = 0; i < 6; i++) if (r[i] == '.') pos = i; if(pos!=-1) weishu = (5-pos )*n;//为result的下标 前面有weishu个数字 //初始化 for (int i = 0; i < maxn; i++) result[i]=temp[i]=0; for (int i = 0; i < 6; i++) a[i]=0; int j = 0; for (int i = 5; i >=0; i--) { if (r[i] != '.') { result[j]=temp[j]= a[j] = r[i]-'0'; j++; } } //整数相乘 while(n>=2) { --n; for(int i=0;i<maxn;i++)//对结果数组一初始化 result[i]=0; for (int i = 0; i < 5; i++) { for (int j = 0; j < maxn; j++) { result[i + j] += temp[j] * a[i]; //处理进位问题 for (int t = i + j; result[t] > 9; ++t) //这里改变了上面的i { result[t + 1] += result[t] / 10; result[t] = result[t] % 10; } } } for (int h = 0; h < maxn; h++) temp[h] = result[h]; } //找界限 //找前导 int firstloc = -1; //int x = 0; for (int i = maxn-1; i >= weishu; i--)//这里加了个等号 ***这里的等号一定要存在 因为可能不存在小数点,位数为0时也需要求出前导 if (result[i] >0) { firstloc = i; //x = 1;//说明小数点前面有数字 break; } int endloc = -1; for(int i=0;i<weishu;i++) if (result[i] >0) { endloc = i; break; } //输出 if(firstloc!=-1)//输出小数点前的部分 { while(firstloc>=weishu) { cout<<result[firstloc]; --firstloc; } } if(endloc!=-1)//如果有小数部分,先输出小数点,再输出小数部分 { cout<<'.'; --weishu; while(weishu>=endloc) { cout<<result[weishu]; --weishu; } } cout<<endl; } }
总结(心得)
1.数组一定不能越界
例如:
#define maxn=100;
for(int i=0;i<=100;i++)
这是绝对错误的,不能越界
2.要考虑清楚情况
要分好条件,不能漏情况
3.for语句里面要注意
for(i=maxn;;i--)
for(i=0;;i++)
3.memset的使用
// memset(result, 0, maxn); 这是错误的表达
memset(result, 0, sizeof(int)*maxn);
这是最初写的一份(有很多错误)
#include<iostream> #include<cstdio> #include<string> #include<string.h> #include<cstring> using namespace std; #define maxn 160 int main() { string r; int n; while (cin >> r >> n) { int a[6], result[maxn], temp[maxn]; //先找到小数点的位置 int pos = -1; for (int i = 0; i < 6; i++) if (r[i] == '.') pos = i; int weishu = (5-pos )*n;//为result的下标 前面有weishu个数字 //初始化 memset(a, 0, sizeof(a)); memset(result, 0, maxn); memset(temp, 0, maxn); int j = 0; for (int i = sizeof(r)-1; i >=0; i++) { if (r[i] != '.') temp[j]= a[j++] = r[i]-'0'; } //整数相乘 while(n--) { for (int i = 0; i < 5; i++) { for (int j = 0; j < maxn; j++) { result[i + j] += temp[j] * a[i]; //处理进位问题 for (int t = i + j; result[i + j] > 9; i++) { result[t + 1] += result[t] / 10; result[i + j] = result[i + j] % 10; } } for (int h = 0; h < maxn; h++) temp[h] = result[h]; } } //找界限 //找前导 int firstloc = 0; //int x = 0; for (int i = maxn; i > pos; i--) if (result[i] >0&& result[i] <=9) { firstloc = i; //x = 1;//说明小数点前面有数字 break; } int endloc = 0; for(int i=0;i<pos;i++) if (result[i] >0 && result[i] <= 9) { endloc = i; break; } //输出 for (int i = firstloc; i > pos; i--) cout << result[i]; cout << "." << endl; for (int i = endloc; i < pos; i++) cout << result[i]; } }
错误在上面的标记已经改正
#include<iostream> #include<cstdio> #include<string> #include<string.h> #include<cstring> using namespace std; #define maxn 160 int main() { string r; int n; while (cin >> r >> n) { int a[6], result[maxn], temp[maxn]; //先找到小数点的位置 //***这里错误 未考虑到如果没有小数点的话 weishu时为多少 /*int pos = -1; for (int i = 0; i < 6; i++) if (r[i] == '.') pos = i; int weishu = (5-pos )*n;//为result的下标 前面有weishu个数字*/ int pos = -1; for (int i = 0; i < 6; i++) if (r[i] == '.') pos = i; int weishu=0; if(pos!=-1) weishu = (5-pos )*n; //初始化 memset(a, 0, sizeof(a)); /* memset(result, 0, maxn); //***这里错误 memset(temp, 0,maxn); */ memset(result, 0, sizeof(int)*maxn); memset(temp, 0, sizeof(int)*maxn); //给这些数组赋值 //*****这里错误 未加上result[j]=result[j]=.... 加上时因为在整数相乘那一步 当n<2时是不参加那些步骤的 所有result[]是需要赋值的 /*int j = 0; for (int i = sizeof(r); i >=0; i++) //注意:这里数组越界了,另外当i取到最大值,i自然是i-- { if (r[i] != '.') temp[j]= a[j++] = r[i]-'0'; //另外这里j++放进表达式,可能会产生temp[j]与a[j++]里面的j值不同 }*/ int j = 0; for (int i = 5; i >=0; i--) { if (r[i] != '.') { result[j]=temp[j]= a[j] = r[i]-'0'; j++; } } //整数相乘 /*while(n--) { for (int i = 0; i < 5; i++) { for (int j = 0; j < maxn; j++) { result[i + j] += temp[j] * a[i]; //处理进位问题 for (int t = i + j; result[i + j] > 9; i++) //******错误result[i + j]中的i+j可是一个定值在该循环语句中 未起预想中的作用 { result[t + 1] += result[t] / 10; result[i + j] = result[i + j] % 10; //******错误result[i + j]中的i+j可是一个定值 } } for (int h = 0; h < maxn; h++) temp[h] = result[h]; } } */ while(n>=2) { n--; for(int i=0;i<maxn;i++) result[i]=0; for (int i = 0; i < 5; i++) { for (int j = 0; j < maxn; j++) { result[i + j] += temp[j] * a[i]; //处理进位问题 for (int t = i + j; result[t] > 9; t++) { result[t + 1] += result[t] / 10; result[t] = result[t] % 10; } } } for (int h = 0; h < maxn; h++) temp[h] = result[h]; } //找界限 //找前导 /*int firstloc = 0; //***错误 未考虑到前导不存在的情况 for (int i = maxn; i > pos; i--)//****错误 未考虑到不存在小数点 则前导可以取为0的情况 可以改成i>=pos if (result[i] >0&& result[i] <=9) { firstloc = i; //x = 1;//说明小数点前面有数字 break; }*/ int firstloc = -1; for (int i = maxn-1; i >=weishu; i--) if (result[i] >0) { firstloc = i; //x = 1;//说明小数点前面有数字 break; } int endloc = -1; for(int i=0;i<weishu;i++) if (result[i] >0) { endloc = i; break; } //输出 /*for (int i = firstloc; i > pos; i--) //***错误 不是pos 应该是weishu cout << result[i]; cout << "." << endl; for (int i = endloc; i < pos; i++) cout << result[i];*/ /*for (int i = firstloc; i >weishu; i--) //***错误 不是pos 应该是weishu cout << result[i]; cout << "." << endl; for (int i = endloc; i < weishu; i++) cout << result[i];*/ if(firstloc!=-1)//输出小数点前的部分 { while(firstloc>=weishu) { cout<<result[firstloc]; --firstloc; } } if(endloc!=-1)//如果有小数部分,先输出小数点,再输出小数部分 { cout<<'.'; --weishu; while(weishu>=endloc) { cout<<result[weishu]; --weishu; } } cout<<endl; } }