【梅森素数分治法运算大整数】2022-01-25(草稿)

缘由各位老师好!求助编辑一个大整数的快速乘除法可调用程序 - VB6论坛 - 编程论坛

 

目前仅发现51个梅森素数,最大的是M82589933(即2的82589933-1),有24862048位。
就如题主所述:我想用普通电脑,用特殊算法试试,但速度太慢了,不行,不能实现。(特殊算法就是指,仅仅算一步除法,进行初步判断,比如:一般人认为对于梅森数若指数p是4x+3型的奇数,指数p若是素数,且2p+1也是素数,则该梅森数可以被2p+1整除,若是不能整除呢?那就基本可以确定是素数了,这样的情况是很稀少的。比如99368963是个素数,2*99368963=198737927也是素数,2^99368963-1是否能被198737927整除呢?如果不能被整除,那就可能是素数,几乎是确定的。第51个梅森素数没有这个数大呢,如果这个数是素数就是第52个梅森素数。)
家用普通电脑创建这样一个数组是否满足需求_int64 a[100000]{},公共_int64 cf[10000000]{};
相信数值运算远比字符运算快得多得多多
这就是我的分治法,不同以往字符运算,与其在字符上绞尽脑汁,不如跳出字符,另寻新途。

void 二的次方数组(_int64* 数, int 长, _int64 次)
{
	_int64 溢 = 0, 段 = 0, 乘数 = 0, 序 = 长 - 1, 模 = 1E+9, 次方 = 1;
	数[序] = 1;
	while (次方)
	{
		if ((乘数 = 数[序]) > 0)
		{
			数[序] = (乘数 - 乘数 / 模*模) * 2 + 溢;
			溢 = 数[序] / 模;
			数[序] -= 溢*模;

			段 = (乘数 / 模) * 2 + 溢;
			溢 = 段 / 模;
			数[序] += (段 - 段 / 模*模)*模;
			//cout << 数[序] << "\t" << 溢 << "\t:";
			--序;
		}
		else
		{
			数[序] += 溢;
			if (++次方 > 次 || 数[0] > 0)
			{
				while (序 < 长)
				    写入文本("..\\Debug\\回复专用\\二次方数据" + std::to_string(次方) + ".txt", std::to_string(数[序++]) + "\n");
				次方 = 0;
			}
			else;
			if (次方 % 4000000 == 0)
			{
				写入文本("..\\Debug\\回复专用\\二次方数据" + std::to_string(次方) + ".txt", std::to_string(序) + "\n");
				while (++序 < 长)
					写入文本("..\\Debug\\回复专用\\二次方数据" + std::to_string(次方) + ".txt", std::to_string(数[序]) + "\n");
				//次方 = 0;
			}
			else;
			序 = 长 - 1; 溢 = 0;
			//cout << 次方 << "\n";
		}
	}
}
	_int64 a[900000]{}, al = 900000, x = 0, p = 0;
	clock_t 开始 = clock();
	二的次方数组(a, 100000, 99368963);
	clock_t 结束 = clock();

	while (x < al)if (a[x] || p)
		std::cout << setw(18) << setfill('0') << a[x], ++x, ++p;
	else ++x;
	std::cout << "\t" << p << "\n";
void 写入文本(string 文件名, string 内容)
{
	std::ofstream 文件(文件名, std::ios::app);
	文件 << 内容;//第一条数据会少1位数,后面的就是18位数了.<< setw(18) << setfill('0') 
}
void findfile(std::string path, std::string mode)
{
	_finddata_t file;
	intptr_t HANDLE;
	std::string Onepath = path + mode;
	HANDLE = _findfirst(Onepath.c_str(), &file);
	if (HANDLE == -1L)std::cout << "无法匹配文件夹路径" << std::endl;
	do {
		if (file.attrib)
		{
			std::string newPath = path + file.name;
			std::cout << file.name << " " << std::endl;
		}//判断是否有子目录   & _A_SUBDIR
		//if ((strcmp(file.name, ".") != 0) && (strcmp(file.name, "..") != 0))//判断是否为"."当前目录,".."上一层目录
		//{
		//	std::string newPath = path + "\\" + file.name;
		//	findfile(newPath, mode);
		//}
		//else
		//	std::cout << file.name << " " << std::endl;
	} while (_findnext(HANDLE, &file) == 0);
	_findclose(HANDLE);
}
void findfile(std::string path, std::string mode, _int64* 数, int 长)
{
	_finddata_t file;
	intptr_t HANDLE = _findfirst((path + mode).c_str(), &file);
	if (HANDLE == -1L)
		std::cout << "无法匹配文件夹路径" << std::endl;
	else;
	do
	{
		if (file.attrib)
			std::string newPath = path + file.name;
		else;
	} while (_findnext(HANDLE, &file) == 0);
	读取文本(path + file.name, 数, 长);
	_findclose(HANDLE);
}


	std::string mode = "\\二次方数据*.txt";
	std::string path = "..\\Debug\\回复专用";
	findfile(path, mode);


SYSTEMTIME timeDest;
	SetWindowPos(GetConsoleWindow(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);//控制台程序置顶窗口
void 二的次方数组(_int64* 数, int 长, _int64 次)
{
	_int64 溢 = 0, 段 = 0, 乘数 = 0, 序 = 长 - 1, 模 = 1E+9, 次方 = 1;
	读取文本("..\\Debug\\回复专用\\", "二次方数据*.txt", 数, 长, 次方);
    char 时间[128]; _strtime_s(时间, 128); printf("时间:%s次方%d\n", 时间, 次方);
	if (次方 == 1)数[序] = 1; else;
	while (次方)
	{
		if (数[序] > 0)//(乘数 = 数[序])
		{
			数[序] = 数[序] * 2 + 溢;// std::cout << 数[序] << "\t";
			溢 = 数[序] / 1E+18;
			数[序] -= 溢*1E+18;
			--序;
		}
		else
		{
			数[序] += 溢;
			if (++次方 > 次 || 数[0] > 0)
			{
				while (序 < 长)
					写入文本("..\\Debug\\回复专用\\二次方数据" + std::to_string(次方) + ".txt", std::to_string(数[序++]) + "\n");
				次方 = 0;
			}
			else if (次方 % 200000 == 0){_strtime_s(时间, 128); printf("次方%d 时间:%s\n", 次方, 时间);}
			else if (次方 % 2000000 == 0)
			{
				写入文本("..\\Debug\\回复专用\\二次方数据" + std::to_string(次方) + ".txt", std::to_string(序) + "\n");
				while (++序 < 长)
					写入文本("..\\Debug\\回复专用\\二次方数据" + std::to_string(次方) + ".txt", std::to_string(数[序]) + "\n");
                _strtime_s(时间, 128); printf("时间:%s数据输出完成。\n", 时间);
			}
			else;
			序 = 长 - 1; 溢 = 0;
		}
	}
}
void 读取文本(std::string 路径, std::string 文件名, _int64* 数, int 长, _int64& 次方)
{
	_finddata_t file;
	std::string newPath = 路径 + 文件名, 读取 = "";
	_int64 cf = 0; int j = 0, jj = 0;
	intptr_t HANDLE = _findfirst((路径 + 文件名).c_str(), &file);
	if (HANDLE == -1L)
		std::cout << "无法匹配文件夹路径" << std::endl;
	else
	do
	{
		if (file.attrib)
		{
			newPath = 路径 + file.name;
			j = newPath.find("数据") + 4;
			jj = newPath.find(".txt");
			cf = _atoi64(newPath.substr(j, jj - j).c_str());
			if (次方 < cf)
				次方 = cf, 读取 = newPath; else;
		}
		else;
	} while (_findnext(HANDLE, &file) == 0);
	_findclose(HANDLE);
	std::string 读 = "";
	int 序 = 0, 位 = 0;
	std::ifstream 文件(读取);
	if (!文件.eof())
	{
		while (getline(文件, 读))
		if (序 == 0)
			序 = _atoi64(读.c_str());
		else
			数[++序] = _atoi64(读.c_str());
		文件.close();
	}
	else;
	std::cout << 数[序] << "\t" << 读 << "\n";
}
void 二的次方数组(_int64 数[][10000000], _int64 长, _int64 次)
{
	_int64 溢 = 0, 序 = 长 - 1, 次方 = 1, 组 = 0;
	二的次方数组读取文本("..\\Debug\\回复专用\\", "二次方数据*.txt", 数, 长, 次方);
	char 时间[128]; _strtime_s(时间, 128); printf("时间:%s 次方%d\n", 时间, 次方);
	if (次方 == 1)数[组][序] = 1; else;
	while (次方 && 序 > -1)
	{
		if (数[组][序] > 0)
		{
			数[组][序] = 数[组][序] * 2 + 溢;
			溢 = 数[组][序] / 1E+18;
			数[组][序] -= 溢*1E+18;
			if (--序 < 0 && 组 < 1) ++组, 序 = 长 - 1;// --序;
		}
		else
		{
			数[组][序] += 溢;
			if (++次方 > 次 || 数[组][0] > 1E+18 || 次方 % 40000 == 0)
			{
				_strtime_s(时间, 128); printf("时间:%s ", 时间); std::cout << "次方" << 次方 << " 数量" << 长 - 序 << " ";
				写入文本("..\\Debug\\回复专用\\二次方数据" + std::to_string(次方) + ".txt", std::to_string(序) + "\n");
				while (++序 < 长)
				{
					写入文本("..\\Debug\\回复专用\\二次方数据" + std::to_string(次方) + ".txt", std::to_string(数[组][序]) + "\n");
					显示进度(长, 序);
				}
				_strtime_s(时间, 128); printf(":%s数据保存完成。\n", 时间);
				if (次方 > 次 || 数[组][0] > 1E+18) 次方 = 0;
			}
			if (次方 % 10000 == 0)
			{
				std::string 标题 = "VsC++:" + std::to_string(次方);
				system(("title " + 标题).data());
			}
			序 = 长 - 1; 组 = 溢 = 0;
		}
	}
}

果如预想的一样优化修改程序后运算历时减少一半不止,运算200万只用了2小时,原来需要6小时,可以这样总结,本次设计的加法减法二次方乘法都采用了最快速代码进行优化,最大限度提高运算速度,也不耽误在电脑上做其他事情开其他程序,由此可以看出语句越精简耗时越少效率越高不可忽视非常重要,尤其对于有时间要求的程序设计是要特别注意语句的精炼。同时也完成了接续运算功能,读取前面保存的数据文本文件转到数组,从而不再担忧时间问题,随时随地可以使用接续运算。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值