可自定义存储数据总空间的的类int_128函数库


前言

        在直接粘贴代码之前,我想先讲一讲这段代码的来历。我的第一篇CSDN就是关于类int_128的函数的。正如我在那篇结尾提及的那样,我当时就在考虑拓展完成那段代码的思路,真正将其改写为可以直接调用的函数。然而实际上,我也确实做了,但是效果及其不尽如人意。

        由于当时刚学习C++,对于各种C++操作不熟悉,该代码在现在看来极其屎山。又由于上一代码为实现函数之间尽量独立,复制粘贴即可使用,导致其极为冗余复杂,出现了一些我当时无力理解修复的BUG,再加上由于本学期课业压力的逐渐加重,我闲置了这部分代码一段时间。

        再此拾起这份工作还是三天前,我大致拓展了MD5信息指纹和RSA加密技术的相关算法(这些都是相当有意思的东西,以后有时间我会再详细说说),其中RSA算法中需要找到两个极大的质数,这就令我想到了这段代码,碰巧这段时间空闲时间较多,于是就花了大概三个晚自习了重新编写调试这段代码。


一、函数使用须知

  1. 为了尽量减少代码量,避免之前工作中出现的循环过多逻辑混乱,该组函数之间存在相互引用,若需使用某一函数,最好复制以下的所有函数。
  2. 本函数事实上定义了一数据类型(超长整数),由两部分组成:用于存储的数组L和表示存储所用位数的N,L使用该函数已自动更新,N由return返回。(至于为什么不直接用struct,是因为写完才想起来,懒得改了)
  3. 本段代码再Dev C++5.11上完成调试,可能在其他编译器上出现问题。
  4. LEN是规定的单个超长整数可使用存储空间,可自行根据需要更改。
  5. 本代码仅适用于整数类型的加减乘除。

二、代码

1.函数及其作用

int numToList(int L[],long long n);	//已经证明可用 
//将整数转化为超长整数; 
long long listToNum(int L[],int N);	//已经证明可用
//将超长整数转化为整数;
void printList(int L[],int N);	//已经证明可用
//打印超长整数; 
int LcomparList(int L1[],int L2[],int N1,int N2);	//已经证明可用 
//比较两超长整数大小;
int sumList(int L[],int N,long long num);	//已经证明可用
//对超长整数做整数加法; 
int LsumList(int L1[],int L2[],int N1,int N2);	//已经证明可用
//将两个超长整数相加;
int multiList(int L[],int N,long long num);	//已经证明可用
//对超长整数做整数乘法; 
int LmultiList(int L1[],int L2[],int N1,int N2);	//已经证明可用
//对超长整数做超长整数乘法;
int subList(int L[],int N,long long num);	//已经证明可用
//对超长整数做整数减法; 
int LsubList(int L1[],int L2[],int N1,int N2);	//已经证明可用 
//两个超长整数相减; 
int divList(int L[],int times[],int N,int tN,long long num);	//已经证明可用
//对超长整数做整除; 
int remaList(int L[],int Left[],int N,long long num);	//已经证明可用,效率低下 
//对超长整数求余; 
int LdivList(int L1[],int L2[],int times[],int N1,int N2,int tN);	//已经证明可用
//对超长整数做超长整数除法; 
int LremaList(int L1[],int L2[],int Left[],int N1,int N2);	//已经证明可用,效率低下 
//对超长整数做超长整数求余;
  1. numToList() 作用:将num转化为超长整数存入L中,返回N

  2. listToNum() 作用:结合存储于L中的超长整数与N,返回为longlong类型的num

  3. printList() 作用:结合存储于L中的超长整数与N打印超长整数L

  4. LcomparList() 作用:比较两个超长整数L1、L2的大小,根据大于等于小于分别返回1,0,-1

  5. sumList() 作用:将常数num加至超长整数L上,返回新产生的N

  6. LsumList() 作用:将超长整数L2加至L1上,返回新的L1的N1

  7. multiList() 作用:将超长整数与一整数num相乘,返回新产生的N

  8. LmultiList() 作用:取超长整数L1的超长整数L2倍,返回新产生的N1

  9. subList() 作用:将超长整数L减去一常数num上,返回新产生的N

  10. Lsublist() 作用:将超长整数L1减去L2,返回新的L1的N1

  11. divList() 作用:将超长整数L整除一常数num,存入超长整数times中,返回times的tN

  12. remaList() 作用:将超长整数L整除一常数num求余,存入超长整数Left中,返回Left的LN

  13. LdivList() 作用:将超长整数L1整除超长常数L2,存入超长整数times中,返回times的tN

  14. LremaList() 作用:将超长整数L整除超长常数L2求余,存入超长整数Left中,返回Left的LN

2.具体函数实现

代码如下:

#include <iostream>
#include <bits/stdc++.h>
#define LEN 100 
using namespace std; 

int numToList(int L[],long long n);	//已经证明可用 
//将整数转化为超长整数; 
long long listToNum(int L[],int N);	//已经证明可用
//将超长整数转化为整数;
void printList(int L[],int N);	//已经证明可用
//打印超长整数; 
int LcomparList(int L1[],int L2[],int N1,int N2);	//已经证明可用 
//比较两超长整数大小;
int sumList(int L[],int N,long long num);	//已经证明可用
//对超长整数做整数加法; 
int LsumList(int L1[],int L2[],int N1,int N2);	//已经证明可用
//将两个超长整数相加;
int multiList(int L[],int N,long long num);	//已经证明可用
//对超长整数做整数乘法; 
int LmultiList(int L1[],int L2[],int N1,int N2);	//已经证明可用
//对超长整数做超长整数乘法;
int subList(int L[],int N,long long num);	//已经证明可用
//对超长整数做整数减法; 
int LsubList(int L1[],int L2[],int N1,int N2);	//已经证明可用 
//两个超长整数相减; 
int divList(int L[],int times[],int N,int tN,long long num);	//已经证明可用
//对超长整数做整除; 
int remaList(int L[],int Left[],int N,long long num);	//已经证明可用,效率低下 
//对超长整数求余; 
int LdivList(int L1[],int L2[],int times[],int N1,int N2,int tN);	//已经证明可用
//对超长整数做超长整数除法; 
int LremaList(int L1[],int L2[],int Left[],int N1,int N2);	//已经证明可用,效率低下 
//对超长整数做超长整数求余;


int main()	//测试函数,仅供各种测试使用 
{
//	long long n1 = 123123123123123;
//	long long n2 = 10000000;
//	int L1[LEN] = {0};
//	int L2[LEN] = {0};
//	int times[LEN] = {0};
//	int tN = 1; 
//	int Left[LEN] = {0};
//	int N1 = numToList(L1,n1);
//	int N2 = numToList(L2,n2);
//	N1 = LsubList(L1,L2,N1,N2);
//	printList(L1,N1);
//	N1 = LsubList(L1,L2,N1,N2);
//	printList(L1,N1);
//	N1 = multiList(L1,N1,n2);
//	tN = divList(L1,times,N1,tN,3);
//	tN = LdivList(L1,L2,times,N1,N2,tN);
//	printList(times,tN);
//	int LN = LremaList(L1,L2,Left,N1,N2);
//	printList(Left,LN);
    return 0;
}

//将整数转化为超长整数;
int numToList(int L[],long long n)
{
	if(n<0)	//在零位存储符号 
	{
		n = -n;
		L[0] = 1;
	}
	else
		L[0] = 0;
	int i = 1;	//从L的第一位开始存; 
	while(true)
	{
		L[i] = n%1000000000;	//将数字的每九位存入一个int单元;
		n = n/1000000000; 
		if(n==0)	//当n存完则结束; 
			break;
		i++;
	}
	return i; 
}

//将超长整数转化为整数;
long long listToNum(int L[],int N)
{
	long long num = 0;
	if(N>1000000000000000000)
	{
		cout<<"超出可存储长度"<<endl;
		return 0; 
	}
	for(int i=N;i>=1;i--)
		num = num*1000000000+L[i];
	return num;
}

//打印超长整数;
void printList(int L[],int N)
{
	if(L[0]==1)
		cout<<'-';
	int i = N; //从最高位开始打印 
	while(true)
	{
		if(i==0)	//如果打印完最后一个int,则停止; 
			break;
		int j = 0;	//填补该位
		if(i!=N)
		{
			int num = L[i];
			while(true)	 
			{
				num = num/10;
				j++;
				if(num==0)
					break;
			} 
			for(int k=0;k<9-j;k++)
				cout<<"0";
		} 
		cout<<L[i];
		i--;
	} 
	cout<<endl;
}

//比较两超长整数大小;(需引用LsubList) 
int LcomparList(int L1[],int L2[],int N1,int N2)
{ 
	int tempL1[LEN] = {0};	//复制L1,L2避免改变其中存储的值 
	int tempL2[LEN] = {0};
	for(int i=0;i<=N1;i++)
		tempL1[i] = L1[i];
	for(int i=0;i<N2;i++)
		tempL2[i] = L2[i];
	int N = LsubList(tempL1,tempL2,N1,N2);
	if(tempL1[0]==1)
		return -1;
	else
	{
		if(N==1&&tempL1[1]==0)
			return 0;
		else
			return 1;
	}
} 

//对超长整数做整数加法;(需引用numToList,LsumList)
int sumList(int L[],int N,long long num)
{
	int tempL[LEN];
	int tempN = numToList(tempL,num);
	return LsumList(L,tempL,N,tempN); 
} 

//对超长整数做整数减法;
int subList(int L[],int N,long long num)
{
	int tempL[LEN];
	int tempN = numToList(tempL,num);
	if(tempL[0]==1)
		tempL[0] = 0;
	else
		tempL[0] = 1;
	return LsumList(L,tempL,N,tempN);
}

//将两个超长整数相加; 
int LsumList(int L1[],int L2[],int N1,int N2)	
{
	int N;	//预判加法执行后超长整数占位数 
	if(L1[0]==L2[0])	//两个超长整数的符号相同 
	{
		N = max(N1,N2);
		for(int i=1;i<=N;i++)
		{
			L1[i] += L2[i];	//各位int数值相加 
			if(L1[i]>=1000000000)	//如果有即将溢出的,十位归零,上位进一 
			{
				L1[i] = L1[i]%1000000000;
				L1[i+1] += 1;
				if(i==N)	//如果是最高位的int即将溢出,对使用位数加一 
				{
					N++;
					break; 
				}
			}
		}
	}
	else	//两超长整数一正一负 
	{
		N = max(N1,N2);
		if(L1[0]==1)	//将负数标签转化为int内的符号 
		{
			L1[0] = 0;
			for(int i=1;i<=N1;i++)
				L1[i] = -L1[i];
		}
		if(L2[0]==1)	//将负数标签转化为int内的符号
		{
			L2[0] = 0;
			for(int i=1;i<=N2;i++)
				L2[i] = -L2[i];
		}
		for(int i=1;i<=N;i++)
		{
			L1[i] += L2[i];
		}
		while(L1[N]==0)	//重新定位最高int 
		{
			if(N==1)
				break; 
			N--;	
		}
		if(L1[N]<0)	//判断最终为正还是为负~负 
		{
			L1[0] = 1;	//将符号标签设置为负 
			for(int i=1;i<=N;i++)
				L1[i] = -L1[i];	//翻转,使得方式简化 
			for(int i=1;i<=N;i++)
			{
				if(L1[i]<0)	//不够则上取下用
				{
					L1[i] = 1000000000+L1[i];
					L1[i+1]--;
				}
			}
			while(L1[N]==0)	//再次重新定位最高位(可能最高位被1-1=0了)
			{
				if(N==1)
					break;
				N--;
			}
			if(L1[N]<0)	//最高位为符号为负的唯一可能部分,该符号已经存储至L[0],将存储位转正 
				L1[N] = -L1[N];	 
		}
		else	//判断最终为正还是为负~正 
		{
			for(int i=1;i<=N;i++)
			{
				if(L1[i]<0)	//不够则上取下用 
				{
					L1[i] = 1000000000+L1[i];
					L1[i+1]--;
				}
			}
			while(L1[N]==0)	//再次重新定位最高位(可能最高位被1-1=0了) 
			{
				if(N==1)
					break;
				N--;
			}
		}
	}
	return N;
}

//两个超长整数相减;(需引用LsumList)
int LsubList(int L1[],int L2[],int N1,int N2)
{
	int tempL2[LEN] = {0};
	for(int i=0;i<=N2;i++)
		tempL2[i] = L2[i];
	if(tempL2[0]==1)
		tempL2[0] = 0;
	else if(tempL2[0]==0)
		tempL2[0] = 1;
	return LsumList(L1,tempL2,N1,N2);
}

//对超长整数做乘法;(需引用LsumList) 
int multiList(int L[],int N,long long num) 
{
	bool iffu = 0;
	if(num<0)	//存符号,归正 
	{
		num = -num;
		iffu = 1;
	}
	int tempL[LEN] = {0};
	for(int i=0;i<=N;i++)	//复制输入的超长整数L到tempL中 
		tempL[i] = L[i];
	int tempN = N; 
	for(int i=1;i<num;i++)	//在L的基础上相加num-1次 
		N = LsumList(L,tempL,N,tempN);	//对超长整数L的占位N进行重新赋值;
	if(iffu)	//返回符号 
	{
		if(L[0]==1)
			L[0] = 0;
		if(L[0]==0)
			L[0] = 1;
	} 
	return N; 
}

//对超长整数做超长整数乘法;
int LmultiList(int L1[],int L2[],int N1,int N2)
{
	int tempL1[LEN] = {0};//将L1中的值转移至tempL2中进行操作,不改变L1的值 
	for(int i=0;i<=N1;i++)
		tempL1[i] = L1[i];
	int tempN1 = N1;
	int tempL2[LEN] = {0};//将L2中的值转移至tempL2中进行操作,不改变L2的值 
	for(int i=1;i<=N2;i++) 
		tempL2[i] = L2[i];
	int tempN2 = N2;
	bool iffu = 0;
	if(L2[0]==1)
		iffu = 1;
	int tL[LEN] = {0};	//对tempL2多次减法,小于零时停止,记录轮数
	tempN2 = subList(tempL2,tempN2,1);
	while(LcomparList(tempL2,tL,tempN2,1)==1)
	{
		N1 = LsumList(L1,tempL1,N1,tempN1);
		tempN2 = subList(tempL2,tempN2,1);
	}
	if(iffu)
	{
		if(L1[0]==0)
			L1[0] = 1;
		if(L1[0]==1) 
			L1[0] = 0;
	}
	return N1;
}

//对超长整数做整除;(需引用subList,sumList,LcomparList)
int divList(int L[],int times[],int N,int tN,long long num)
{
	bool iffu1 = 0;
	bool iffu2 = 0;
	if(num<0)
	{
		num = -num;
		iffu2 = 1;
	}
	int tempL[LEN] = {0};
	for(int i=1;i<=N;i++)	//将L中的值转移至tempL中进行操作,不改变L的值 
		tempL[i] = L[i];
	int tempN = N;
	if(L[0]<0)
		iffu1 = 1;
	while(tempL[0]==0)	//对tempL1多次减法,小于零时停止,记录轮数
	{
		tempN = subList(tempL,tempN,num);
		tN = sumList(times,tN,1);
	}
	tN = subList(times,tN,1);
	if(iffu1^iffu2)
		times[0] = 1;
	return tN;
} 

//对超长整数求余; 
int remaList(int L[],int Left[],int N,long long num)
{
	bool iffu = 0;
	Left[0] = 0;
	if(num<0)
		num = -num;
	int LN = N;	//将L中的值转移至Left中 
	for(int i=1;i<=N;i++)
		Left[i] = L[i];
	if(L[0]==1)
		iffu = 1;
	while(Left[0]==0)	//对Left多次减法,小于零时停止 
		LN = subList(Left,LN,num);
	LN = sumList(Left,LN,num);	//补充多减的一步
	if(iffu)
		Left[0] = 1;
	return LN; 
} 

//对超长整数做超长整数除法;(需引用LsubList,subList,sumList,LcomparList)
int LdivList(int L1[],int L2[],int times[],int N1,int N2,int tN)
{

	int tempL1[LEN] = {0};
	for(int i=0;i<=N1;i++)	//将L1中的值转移至tempL1中进行操作,不改变L1的值 
		tempL1[i] = L1[i];
	int tempN1 = N1;
	while(tempL1[0]==0)	//对tempL1多次减法,小于零时停止,记录轮数 
	{
		tempN1 = LsubList(tempL1,L2,tempN1,N2);
		tN = sumList(times,tN,1);
	}
	tN = subList(times,tN,1);
	return tN;
}

int LremaList(int L1[],int L2[],int Left[],int N1,int N2)
{
	int LN = N1;	//将L1中的值转移至Left中 
	for(int i=0;i<=N1;i++)
		Left[i] = L1[i];
	while(!(Left[0]==1))
		LN = LsubList(Left,L2,LN,N2);
	LN = LsumList(Left,L2,LN,N2);	//补充多减去的一步 
	return LN; 
} 


3.代码效果测评

  1. 使用乘法函数时尽量小数在后,可以提高效率
  2. 求商和求整的函数运算效率很低,非必要不使用

总结

        本代码是我拓展RSA加密算法的衍生产品,在之前概念的基础上拓展了对负数的处理,希望对学习任务中有超大数字处理的同学有一定的帮助。

        另外,由于时间有限,未对该代码做更加详细的测试,如果哪位同学在使用过程中发现了什么bug,请马上在评论中告知我,我会就代码做进一步的修改。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
unordered_map 是 C++ 标准库中的容器,用于实现键值对的映射。默认情况下,unordered_map 可以使用基本数据型作为键和值,如 int、double、string 等。但是,如果你想要使用自定义数据型作为键或值,需要满足以下两个条件: 1. 自定义数据型需要定义哈希函数(hash function):unordered_map 使用哈希函数将键映射到特定的存储桶中。你需要为自定义数据型实现一个哈希函数,以便 unordered_map 可以正确地定位和操作键值对。 2. 自定义数据型需要定义相等运算符(equality operator):unordered_map 使用相等运算符来比较两个键是否相等。你需要为自定义数据型实现相等运算符,以便 unordered_map 可以正确地判断键的相等性。 下面是一个示例,演示了如何在 unordered_map 中使用自定义数据型: ```cpp #include <iostream> #include <unordered_map> class MyCustomType { public: int x; int y; bool operator==(const MyCustomType& other) const { return (x == other.x) && (y == other.y); } }; // 哈希函数的实现 // 这里简单地将 x 和 y 的值相加作为哈希值 struct MyCustomTypeHash { std::size_t operator()(const MyCustomType& obj) const { return std::hash<int>()(obj.x + obj.y); } }; int main() { std::unordered_map<MyCustomType, int, MyCustomTypeHash> myMap; MyCustomType key1; key1.x = 1; key1.y = 2; MyCustomType key2; key2.x = 3; key2.y = 4; myMap[key1] = 10; myMap[key2] = 20; std::cout << myMap[key1] << std::endl; // 输出 10 std::cout << myMap[key2] << std::endl; // 输出 20 return 0; } ``` 在上述示例中,我们定义了一个名为 MyCustomType 的自定义数据型,并为其实现了相等运算符和哈希函数。然后,我们使用 MyCustomType 作为 unordered_map 的键型,并将 MyCustomTypeHash 作为自定义的哈希函数。这样,我们就可以在 unordered_map 中使用自定义数据型了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值