大数相乘(数组表示)

大数相乘

首先说一下乘法计算的算法:同样是模拟人工计算时的方法。
从低位向高位乘,在竖式计算中,我们是将乘数第一位与被乘数的每一位相乘,记录结果之后,用第二位相乘,记录结果并且左移一位,以此类推,直到计算完最后一位,再将各项结果相加,得出最后结果。
例如:
int a=97
int b=23
23为乘数,97是被乘数:
在这里插入图片描述
为了程序程序计算方便,开辟一个数组,数组的最大长度为:
数组长度 = a的位数 + b的位数 + 1
计算过程为:
arr[i+j] += a[i]a[j]
其中i,j都是从右边向左开始计数的
第一趟的情况:
在这里插入图片描述
第二趟的情况:
在这里插入图片描述

从右向左考虑进位:
如果arr[i]>=10,通过整除10将第i位的进位加到i+1位上,余数部分作为第i位的值,
arr[i+1] += arr[i]/10;
arr[i] %= 10;

在这里插入图片描述

用c++代码实现如下:

//大数相乘,对于正数
string  bigMul(string&a, string&b)
{
	string res = "";
	std::vector<int>c(a.size() + b.size() + 1);		//输出结果最大为size()+b.size()+1,其中加1考虑的是进位

	//考虑逐个位相乘,c[i+j]+=a[i]*a[j] 
	//用a的每一位分别乘以b的每一位上
	//从右边开始遍历
	for (int i = 0; i <a.size(); i++){
		for (int j = 0; j<b.size(); j++){
			int ai = a[a.size() - 1 - i] - '0';	     //从最后一位开始表示最低位置
			int bj = b[b.size() - 1 - j] - '0';
			c[i + j] = c[i + j] + ai*bj;    //注意在原始的基础上累加ai*bj;
		}
	}

	//考虑进位,c中的数据是低位在前高位在后
	for (int i = 0; i<c.size(); i++){
		if (c[i] >= 10)		{
			c[i + 1] += c[i] / 10;
			c[i] %= 10;
		}
	}
	//最后一位表示最高位,c=a*b	中c的高位可能没有进位,需要去掉这些0之后再输出
	for (int i = c.size() - 1; i >= 0; i--)	{
		if (c[i] == 0)c.pop_back();
		else break;
	}
	//反向输出 
	for (int i = c.size() - 1; i >= 0; i--)	{
		//	cout << c[i];
		res += c[i] + '0';	//转化为字符
	}
	//cout << endl;
	return res;}

基于大数相乘,可以解决牛客网上大数浮点指数运算那道题

题目

给定两个数R和n,输出R的n次方,其中0.0<R<99.999, 0<n<=25
输入
95.123 12 0.1 1
输出
548815620517731830194541.899025343415715973535967221869852721 0.1

思路是:
先将表示浮点数的字符串去掉小数点变成整数,并记录小数点的位数,然后用前面的整数的大数乘法计算,最后加上小数点

#include<iostream>
#include<string>
#include<algorithm>
 
 
using namespace std;
 
//大数相乘,对于正数
string  bigMul(string&a, string&b)
{
    string res = "";
    std::vector<int>c(a.size() + b.size() + 1);       //输出结果最大为a.size()+b.size()+1,其中加1考虑的是进位
 
    //考虑逐个位相乘,c[i+j]+=a[i]*a[j]  
    //用a的每一位分别乘以b的每一位上 
    //从右边开始遍历
    for (int i =0; i <a.size(); i++){
        for (int j = 0;j<b.size(); j++){
            int ai = a[a.size()-1-i] - '0';         //从最后一位开始表示最低位置
            int bj = b[b.size()-1-j] - '0'; 
         
            c[i + j ] = c[i + j ] +ai*bj;    //注意在原始的基础上累加ai*bj;
        }
    }
     //考虑进位,c中的数据是低位在前高位在后
    for (int i = 0; i<c.size(); i++){   
        if (c[i] >= 10)
        {
            c[i+1] += c[i] / 10;
            c[i]   %= 10;
        }
    }
     //最后一位表示最高位,c=a*b   中c的高位可能没有进位,需要去掉这些0之后再输出
    for (int i = c.size() - 1; i >= 0; i--)
    {
          if (c[i] == 0)c.pop_back();
        else break; 
    }            
      
    //反向输出 
    for (int i = c.size()-1;i>=0; i--)    {
    //  cout << c[i];
        res += c[i] + '0';  //转化为字符
    }        
    //cout << endl;
     return res; 
}
 
 
 
//浮点数相乘,转化为正式后再相乘
string  bigMulFloat(string&a, string&b)
{ 
    string a_int = "";
    string b_int = "";
    size_t pos1 = a.find('.');
    size_t pos2 = b.find('.');
    int a_post_len = 0;      //小数部分的长度
    int b_post_len = 0;
 
    if (pos1 != a.npos){          //如果能找到小数点   
        a_int += a.substr(0, pos1);  //整数
        a_post_len = a.size() - pos1 - 1;
        a_int += a.substr(pos1 + 1, a_post_len);       //小数部分     
         
    }
    else{
         a_int =a;    //整数
    }
     
    if (pos2 != b.npos) {         //如果能找到小数点    
        b_int += b.substr(0, pos2);  //整数
        b_post_len = b.size() - pos2 - 1;
        b_int += b.substr(pos2 + 1, b_post_len);       //小数部分             
    }
    else{
        b_int=b;
    }
 
     int len = a_post_len + b_post_len;       //a,b小数部分的长度
     string c = bigMul(a_int, b_int);
     //c中小数部分个数为len_end个,正数部分长度为c.size()-len
     string res;
    //将小数点加入
    if (len >= c.size())   {   //如果全是小数,则前缀加一个0,最后表示成0.xxx
        res += "0.";
        for (int i = 0; i < len - c.size(); i++)
            res += '0';
        res += c;
    }
    else{
        res += c.substr(0, c.size() - len);   //整数   
        res += '.';
        res += c.substr(c.size() - len, len);
    }
     //处理小数点后面的0
     int cnt = 0;
     for (cnt = 0; cnt < len; cnt++)    {
         if (res[res.size() - 1] == '0')
             res.pop_back();
         else
             break;
     }
     //如果小数点后面都是0,则小数点也不要
     if (cnt == len)
        res.pop_back();          
     return res; 
}

int main(){
    string a;
    int r;
   vector<string> v_a;
   vector<int>v_r;
         
    while(cin>>a>>r){  
       v_a.push_back(a);
        v_r.push_back(r);
    } 
     
    int n=0;
    for( n=0;n<v_a.size()-1;n++){
         string res="1";
        for(int i=0;i<r;i++)
        {
           res=  bigMulFloat(res,v_a[n]) ;
        } 
        cout<< res<<" ";  
    }
     
    //最后一个输出没有空格
    string res="1";
    for(int i=0;i<r;i++)
    {
        res=  bigMulFloat(res,v_a[n]) ;
    } 
    cout<< res;  
     
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值