我正在写一篇有关素数在当今密码学中的重要性的文章。我想开发一个小型应用程序,以显示用C语言(至少对我来说是低级语言)编写的程序需要多长时间才能将复合数分解为其主要因子。我想出了一个简单的算法来做到这一点,但遇到一个问题:
我希望用户能够输入巨大的数字,例如:7777777777777777777777777772
因此,计算机将需要花费几个小时来处理该问题,这表明我们基于素数的密码学有多么出色。
但是在C语言中,我可以找到的最大数据类型是 LONG ,它可以达到2147483646。
你们知道我如何能够用C键入和处理大量数字吗?
预先感谢
答案 0 :(得分:1)
大量数字的分解
我希望用户能够键入巨大的数字,例如:7777777777777777777777777777772
这是一个93位的数字,不是那么大,所以可以简单地用暴力破解它。
如果您可以访问unsigned __int128
,则类似以下内容。 C确实指定了64位类型,但除此之外,您还是自己一个人。
我估计这种适度的分解可能需要几分钟。
https://www.dcode.fr/prime-factors-decomposition以秒为单位报告答案。
当然可以很多改进。
unsigned __int128 factor(unsigned __int128 x) {
if (x <= 3) {
return x;
}
if (x %2 == 0) return 2;
for (unsigned __int128 i = 3; i <= x/i; i += 2) {
static unsigned long n = 0;
if (++n >= 100000000) {
n = 0;
printf(" %llu approx %.0f\n", (unsigned long long) i, (double)(x/i));
fflush(stdout);
}
if (x%i == 0) {
return i;
}
}
return x;
}
void factors(unsigned __int128 x) {
do {
unsigned __int128 f = factor(x);
printf("%llu approx %.0f\n", (unsigned long long) f, (double)x);
fflush(stdout);
x /= f;
} while (x > 1);
}
void factors(unsigned __int128 x) {
do {
unsigned __int128 f = factor(x);
printf("approx %0.f approx %.0f\n", (double) f, (double)x);
fflush(stdout);
x /= f;
} while (x > 1);
}
输出
approx 2 approx 7777777777777778308713283584
approx 2 approx 3888888888888889154356641792
approx 487 approx 1944444444444444577178320896
approx 2687 approx 3992699064567647864619008
99996829 approx 14859790387308
199996829 approx 7429777390798
299996829 approx 4953158749339
399996829 approx 3714859245385
499996829 approx 2971882684351
...
38399996829 approx 38696146902
38499996829 approx 38595637421
approx 1485931918335559335936 approx 1485931918335559335936
正确的答案是使用更高效的算法,然后然后考虑所需的类型。
答案 1 :(得分:0)
与您在纸上进行打印的方式相同。您可以将数字分成几部分,并使用长除法,长加法和长乘法。
也许最简单的方法是将数字存储为以10为底的字符串,并编写代码以对这些字符串执行所需的所有操作。您将在纸上进行加法操作。乘法将通过单数乘法与加法(您已经做过)相结合来完成。依此类推。
有许多库可以为您执行此操作,例如libgmp的MPZ库和OpenSSL的BN库。
答案 2 :(得分:0)
您可以使用结构,只需设置所需的数字,下面的代码未经测试,但应该为您提供一些指导。
我相信,这应该使您能够达到4294967295(max_int)左右的位置,从而达到xx在您在结构中定义的位置的力量
typedef struct big_number{
int thousands;
int millions;
int billions;
}
//Then do some math
big_number add(big_number n1, big_number n2){
int thousands = n1.thousands + n2.thousands;
int millions = n1.millions + n2.millions;
//etc... (note each part of your struct will have a maximum value of 999
if(thousands > 999){
int r = thousands - 999;
millions += r; //move the remainder up
}
}