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;
    }
} 
View Code

我自己重写的一遍

#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;
    }
} 
View Code

总结(心得)

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;
    }
} 

 

转载于:https://www.cnblogs.com/Aiahtwo/p/10008405.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值