poj 1001 字符串乘法以及处理精度问题
2024-08-31 10:27:01
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
string r;
int n,dianwei;
const int R_LEN=;
short result[R_LEN],jieguo[R_LEN],chengshu[];
while(cin>>r>>n)
{
int len=;
for(int i=;i<R_LEN;++i) jieguo[i]=result[i]=;//初始化为0
for(int i=;i<;++i) chengshu[i]=;
dianwei = ;
size_t pos = r.find(".");//找到小数点的位置
if(pos != string::npos)
dianwei=(-pos)*n; //结果中的小数点的位数 for(int i=,j=;i>=;--i) //得到倒序数字数组
{
if(r[i]!='.')
{
jieguo[j]=result[j]=chengshu[j]=r[i]-'';//提取数位
++j;
}
} //整数相乘步骤
while(n>=)//指数大于等于2的时候计算,否则就是直接去除多余0输出了
{
--n;
for(int i=;i<R_LEN;++i)//对结果数组一初始化
result[i]=; for(int i=;i<;++i)//乘数数位循环
{
int c;
for(int j=;j<R_LEN;++j)//被乘数数位循环
{
c=chengshu[i]*jieguo[j];
result[i+j]+=c; for(int t=i+j;result[t]>;++t)//处理进位 即当result[t]<=9 该数组不进位时停止
{
result[t+]+=result[t]/;
result[t]=result[t]%;
}
}
}
for(int i=;i<R_LEN;++i)
jieguo[i]=result[i];//结果转存 这里的jieguo数组作用是存上一次的结果,用来和乘数向乘,因为result[]=jieguo[]*chengshu[]
} //找边界步骤
int firstindex=-;
for(int i=R_LEN-;i>=dianwei;--i)//从右往左查找小数点前第一个不为0的数 处理前导0 记录边界
{
if(result[i]>)
{
firstindex=i;//记录 小数点前第一个不为0的数的下标 方便输出
break;
}
}
int lastindex=-;
for(int i=;i<dianwei;++i)//从左往右查找小数点前第一个不为0的数 处理后导0 记录边界
{
if(result[i]>) //记录 小数点前第一个不为0的数的下标 方便输出
{
lastindex=i;
break;
}
} //输出步骤
if(firstindex!=-)//输出小数点前的部分
{
while(firstindex>=dianwei)
{
cout<<result[firstindex];
--firstindex;
}
}
if(lastindex!=-)//如果有小数部分,先输出小数点,再输出小数部分
{
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[], result[maxn], temp[maxn];
//先找到小数的位置
int weishu=,pos=-;
for (int i = ; i < ; i++)
if (r[i] == '.')
pos = i;
if(pos!=-)
weishu = (-pos )*n;//为result的下标 前面有weishu个数字
//初始化
for (int i = ; i < maxn; i++)
result[i]=temp[i]=;
for (int i = ; i < ; i++)
a[i]=; int j = ;
for (int i = ; i >=; i--)
{
if (r[i] != '.')
{
result[j]=temp[j]= a[j] = r[i]-'';
j++;
}
}
//整数相乘
while(n>=)
{
--n;
for(int i=;i<maxn;i++)//对结果数组一初始化
result[i]=;
for (int i = ; i < ; i++)
{
for (int j = ; j < maxn; j++)
{
result[i + j] += temp[j] * a[i];
//处理进位问题
for (int t = i + j; result[t] > ; ++t) //这里改变了上面的i
{
result[t + ] += result[t] / ;
result[t] = result[t] % ;
}
}
}
for (int h = ; h < maxn; h++)
temp[h] = result[h]; }
//找界限
//找前导
int firstloc = -;
//int x = 0;
for (int i = maxn-; i >= weishu; i--)//这里加了个等号 ***这里的等号一定要存在 因为可能不存在小数点,位数为0时也需要求出前导
if (result[i] >)
{
firstloc = i;
//x = 1;//说明小数点前面有数字
break;
}
int endloc = -;
for(int i=;i<weishu;i++)
if (result[i] >)
{
endloc = i;
break;
}
//输出
if(firstloc!=-)//输出小数点前的部分
{
while(firstloc>=weishu)
{
cout<<result[firstloc];
--firstloc;
}
}
if(endloc!=-)//如果有小数部分,先输出小数点,再输出小数部分
{
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[], result[maxn], temp[maxn];
//先找到小数点的位置
int pos = -;
for (int i = ; i < ; i++)
if (r[i] == '.')
pos = i;
int weishu = (-pos )*n;//为result的下标 前面有weishu个数字
//初始化
memset(a, , sizeof(a));
memset(result, , maxn);
memset(temp, , maxn);
int j = ;
for (int i = sizeof(r)-; i >=; i++)
{
if (r[i] != '.')
temp[j]= a[j++] = r[i]-'';
}
//整数相乘
while(n--)
{
for (int i = ; i < ; i++)
{
for (int j = ; j < maxn; j++)
{
result[i + j] += temp[j] * a[i];
//处理进位问题
for (int t = i + j; result[i + j] > ; i++)
{
result[t + ] += result[t] / ;
result[i + j] = result[i + j] % ;
}
}
for (int h = ; h < maxn; h++)
temp[h] = result[h];
}
}
//找界限
//找前导
int firstloc = ;
//int x = 0;
for (int i = maxn; i > pos; i--)
if (result[i] >&& result[i] <=)
{
firstloc = i;
//x = 1;//说明小数点前面有数字
break;
}
int endloc = ;
for(int i=;i<pos;i++)
if (result[i] > && result[i] <= )
{
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[], 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 = -;
for (int i = ; i < ; i++)
if (r[i] == '.')
pos = i;
int weishu=;
if(pos!=-)
weishu = (-pos )*n;
//初始化
memset(a, , sizeof(a));
/*
memset(result, 0, maxn); //***这里错误
memset(temp, 0,maxn);
*/
memset(result, , sizeof(int)*maxn);
memset(temp, , 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 = ;
for (int i = ; i >=; i--)
{
if (r[i] != '.')
{
result[j]=temp[j]= a[j] = r[i]-'';
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>=)
{
n--;
for(int i=;i<maxn;i++)
result[i]=;
for (int i = ; i < ; i++)
{
for (int j = ; j < maxn; j++)
{
result[i + j] += temp[j] * a[i];
//处理进位问题
for (int t = i + j; result[t] > ; t++)
{
result[t + ] += result[t] / ;
result[t] = result[t] % ;
}
}
}
for (int h = ; 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 = -;
for (int i = maxn-; i >=weishu; i--)
if (result[i] >)
{
firstloc = i;
//x = 1;//说明小数点前面有数字
break;
}
int endloc = -;
for(int i=;i<weishu;i++)
if (result[i] >)
{
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!=-)//输出小数点前的部分
{
while(firstloc>=weishu)
{
cout<<result[firstloc];
--firstloc;
}
}
if(endloc!=-)//如果有小数部分,先输出小数点,再输出小数部分
{
cout<<'.';
--weishu;
while(weishu>=endloc)
{
cout<<result[weishu];
--weishu;
}
}
cout<<endl;
}
}
最新文章
- Java双循环break的用法
- Android学习笔记之ExecutorService线程池的应用....
- android 原生dialog对话框
- docker--------------实践(转载)
- NOIP2014_day2:无线网络发射器选址
- c/c++(hiredis)异步调用redis【转】
- You Are the One HDU - 4283 (区间DP)
- Celery
- [转] 如何设置双网卡同时连接内网外网_bpao_新浪博客
- sublime安装PackageControl提示失败(被墙了)
- JSTL_Format标记库
- 关于Oracle归档的一些操作
- HDU 4731 Minimum palindrome (2013成都网络赛,找规律构造)
- redis PUB/SUB(发布/订阅)
- [LeetCode] 476. Number Complement_Easy tag: Bit Manipulation
- RabbitMQ 主题
- MongoDB客户端及监控工具
- codeforces-727A
- 浏览器端用JS实现创建和下载图片
- bootstrapTable表格表头换行