• 软件乘法实现


    【加密算法笔记之代码仓库】

    ------------

    博文声明:本博文隶属加密算法笔记的Integer multiplication一节,提供算法的软件实现,不提供代码解释。

    ------------

    1. 竖式乘法

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    void Reverse(string &A){
    	int ALength = A.size();
    	for (int i = 0; i < ALength / 2; i++)
    	{
    		char temp = A[i];
    		A[i] = A[ALength - 1 - i];
    		A[ALength - 1 - i] = temp;
    	}
    }
    
    void StrToNum(string &A) {
    	for (int i = 0; i < A.size(); i++)
    		A[i] -= '0';
    }
    
    string GetProductOfTwoBigNum(string A, string B)
    {
    	int ALength = A.size();
    	int BLength = B.size();
    
    	//转换为数字
    	StrToNum(A);
    	StrToNum(B);
    
    	//以字符串的形式存储整数,整数最高位在数组最低索引处。
    	//希望从0开始遍历数组,使最低位在低索引处,最故将元素倒序。
    	Reverse(A);
    	Reverse(B);
    
    	int CLength = ALength + BLength;     //乘积最大字符数
    	string C(CLength, NULL);		//最终乘积
    	char V = NULL;				//每位乘积
    	char U = NULL;				//进位
    
    	int c_i;				//乘积索引
    	for (int i = 0; i < BLength; i++)
    	{
    		U = NULL;
    		for (int j = 0; j < ALength; j++)
    		{
    			V = (B[i] * A[j] + C[i + j] + U) % 10;
    			U = (B[i] * A[j] + C[i + j] + U) / 10;	//进位用于下一位计算
    			C[i + j] = V;				//乘积中当前位值更新
    		}
    		C[i + ALength] = U;
    	}
    
    	//乘积输出
    	string strResult;
    	int k = CLength - 1;
    	while (k >= 0 && C[k] == NULL)
    		--k;
    
    	//倒序,高位在左
    	for (; k >= 0; --k)
    		strResult.push_back(C[k] + '0');//转换为字符
    
    	if (strResult.empty())
    		strResult.push_back('0');
    
    	return strResult;
    }
    
    
    int main()
    {
    	string A, B;
    
    	cout << "输入两个乘数:";
    	while (cin >> A >> B)
    	{
    		string strResult = GetProductOfTwoBigNum(A, B);
    		cout << "两数之积:" << strResult << endl;
    		cout << "-------------------------------------------------" << endl;
    		cout << "输入两个乘数:";
    	}
    	return 0;
    }
      
    

    2. Karatsuba分治优化

    #include <iostream>
    #include <string>
    #include<sstream>
    #include<windows.h>
    
    using namespace std;
    
    string mult(string num1, string num2);
    string sub(string num1, string num2);
    string add(string& num1, string& num2);
    void trimPrefix(string& input);
    string addTail(string input, int n);
    string format(string& input, int n);
    int maxLength(string& num1, string& num2);
    
    int main() {
    	string num1 = "123435678432269335678432278456567843226978435678432269226567784565678432269784356784322692265677845656784322697843567843226922656778456567843226978435678432269226567935678432269";//
    	string num2 = "5678456567843226978435678432269784565678432269784356784322692265677845656784322697843567843226922656778456567843226978435678432269226567784565678432269784356784322692265672265678432269932269";//
    
    	string result = mult(num1, num2);
    	cout <<"
    result="<< result;
    	cin >> num1;
    	return 0;
    }
    
    int maxLength(string& num1, string& num2) {
    
    	int length = num1.size() > num2.size() ? num1.size() : num2.size();
    	if (length == 1)
    		return 1;
    	length += length & 1;
    	return length;
    }
    
    //整数位数若不足n则高位补0,使长度为n
    string format(string& input, int n) {
    	if (input.size() >= n)
    		return input;
    
    	string result(n, '0');
    	for (int i = 0; i < input.size(); i++)
    		result[n - input.size() + i] = input[i];
    
    	return result;
    }
    
    //整数尾部补0。相当于移位,扩大倍数
    string addTail(string input, int n) {
    	string result(input.size() + n, NULL);
    	for (int i = 0; i < input.size(); i++)
    		result[i] = input[i];
    
    	for (int i = input.size(); i < result.size(); i++)
    		result[i] = '0';
    
    	return result;
    }
    
    void trimPrefix(string& input) {
    	int k = 0;
    	//禁止对最低位进行判断,全零时保留一位
    	while (k < input.size() - 1 && input[k] == '0')
    		k++;
    	input = input.substr(k, input.size() - k);
    }
    //整数相加
    string add(string& num1, string& num2) {
    	int length = num1.size() > num2.size() ? num1.size() : num2.size();
    
    	//加数位对齐
    	num1 = format(num1, length);
    	num2 = format(num2, length);
    
    	//加法结果多一位存储空间
    	string result(length + 1, NULL);
    
    	int tmp;
    	int addOutput;//位加法结果
    	int carry = 0;//进位标识
    	for (int i = length - 1; i >= 0; i--) {
    		tmp = num1[i] + num2[i] - 96 + carry;//转换为数字 ‘0’对应48
    		addOutput = tmp % 10;
    		carry = tmp / 10;
    		/*
    		这个代码适合verilog
    		if (tmp >= 10) {
    			carry = 1;
    			tmp = tmp - 10;
    		}
    		else {
    			carry = 0;
    		}*/
    		result[i + 1] = addOutput + '0';
    	}
    	result[0] = carry + '0';//最后一次,最高位的进位
    
    	trimPrefix(result);
    	return result;
    }
    
    string sub(string num1, string num2) {
    	int length = num1.size() > num2.size() ? num1.size() : num2.size();
    
    	//减数位对齐
    	num1 = format(num1, length);
    	num2 = format(num2, length);
    
    	//要求num1>=num2
    	for (int i = 0; i < length; i++) {
    		if ((num1[i] == '0' && num2[i] == '0') || num1[i] == num2[i]) {
    			continue;
    		}
    		else if (num1[i] < num2[i]) {
    			MessageBox(NULL, "error", "提示", 64);
    			exit(0);
    		}
    		else break;
    	}
    
    	for (int i = length - 1; i >= 0; i--) {
    		if (num1[i] < num2[i]) {
    			num1[i] = num1[i] + '0' + 10 - num2[i];
    			num1[i - 1] = num1[i - 1] - 1;
    		}
    		else {
    			num1[i] = num1[i] + '0' - num2[i];
    		}
    	}
    
    	trimPrefix(num1);
    	return num1;
    }
    
    string mult(string num1, string num2) {
    	string x1, x0, y1, y0, x0y0, x1y1, sumX, sumY, sumXsumY, sum;
    
    	//两个2n位的数字相乘,不足2n高位补零
    	int N = maxLength(num1, num2);//求两数组中较大数组的长度,如果长度为奇数则+1变偶,方便二分成两部分
    	num1 = format(num1, N);//数组高位存整数的高位数;数字前面补0,使长度为n;
    	num2 = format(num2, N);
    
    	if (num1.size() > 1) {
    		//将大整数平均分成两部分
    		x1 = num1.substr(0, N / 2);
    		x0 = num1.substr(N / 2, N / 2);
    
    		y1 = num2.substr(0, N / 2);
    		y0 = num2.substr(N / 2, N / 2);
    
    		x0y0 = mult(x0, y0);//分治求大整数乘法
    		x1y1 = mult(x1, y1);
    		sumX = add(x1, x0);
    		sumY = add(y1, y0);
    
    		sumXsumY = mult(sumX, sumY);
    
    		string tmp1 = addTail(sub(sumXsumY, add(x0y0, x1y1)), N / 2);//尾部补0,相当于移位
    		string x1y1Temp = addTail(x1y1, N);
    		string tmp2 = add(x1y1Temp, x0y0);
    		sum = add(tmp1, tmp2);
    		trimPrefix(sum);//除去结果前面多余的0
    	}
    	else {
    		int singleMul = (num1[0] - 48) * (num2[0] - 48);
    		sum = std::to_string(singleMul);
    	}
    	return sum;
    }
    

      

      

  • 相关阅读:
    过滤器(Filter)
    DBUtils结果集处理器介绍
    Tomcat配置连接c3p0连接池
    JdbcUtils
    数据库连接池
    JDBC处理事务
    JDBC入门(5)--- 时间类型、大数据
    JDBC入门(4)--- 批处理
    JDBC入门(3)--- PrepareStatement
    JDBC入门(2)--- ResultSet之滚动结果集
  • 原文地址:https://www.cnblogs.com/feicaixian/p/11815449.html
Copyright © 2020-2023  润新知