【问题标题】:Factorization of really big numbers in CC中真正大数的因式分解
【发布时间】:2019-03-16 00:39:08
【问题描述】:

我正在写一篇关于质数在当今密码学中的重要性的文章。我想开发一个小型应用程序,显示用 C(至少对我来说是低级语言)编写的程序需要多长时间才能将复合数分解为素数。我想出了一个简单的算法来做到这一点,但我遇到了一个问题:

我希望用户能够输入巨大的数字,例如:77777777777777777777777777772

所以计算机需要几个小时来处理它,显示我们基于素数的密码学有多好。

但在 C 中,我能找到的最大数据类型是 LONG,最高可达 2147483646。

你们知道我如何能够在 C 中输入和处理一个大数字吗?

提前致谢

【问题讨论】:

  • 查找“多字整数”或“任意精度整数”。有诸如 GMP 之类的库可以对此类对象进行算术运算。
  • "在 C 中我能找到的最大数据类型是 LONG" --> 试试uintmax_t。那至少是18446744073709551615。 7777777777777777777777777772(一个 93 位的数字)还不够。查看支持int128_t 的实现。当然这个数字777...772 不是素数。
  • 但是即使你这样做,它也只是显示你的算法的行为,而不是分解实际上很难。
  • @harold,您认为如何向学生展示现代计算机将复合数分解为素数是多么困难的最佳方式?我愿意接受建议,因为我确实希望他们理解这个概念
  • 好吧,我不确定。大数的因式分解技术,例如 GNFS,需要大量的基础工作才能理解它们的作用,并且由于过于复杂而无法作为练习来重现。更简单的算法在处理目前不被认为难以分解的数字时遇到很多问题,例如 RSA-100

标签: c math numbers integer primes


【解决方案1】:

真正大数的因式分解
我希望用户能够输入巨大的数字,例如:7777777777777777777777777772

这是一个 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

不过,正确的答案是使用更高效的算法并然后考虑所需的类型。

【讨论】:

  • 谢谢,伙计!它打开了我对这个问题的想法!我想这是正确的方法!正如我所说,一旦我完成了这个用于教育目的的项目,我就会在这里发布 Github 存储库!来自巴西的欢呼
【解决方案2】:

就像你在纸上做的一样。您将数字分成几部分并使用长除法、长加法和长乘法。

也许最简单的方法是将数字存储为以 10 为底的字符串,然后编写代码对这些字符串执行您需要的所有操作。你可以像在纸上那样做加法。乘法将通过一位数乘法与加法相结合(您已经做过)来完成。以此类推。

有很多库可以为您执行此操作,例如 libgmp 的 MPZ 库和 OpenSSL 的 BN 库。

【讨论】:

  • 为了将数字分解成碎片,我必须在 char 数组上分解它,对吧?事实证明,用 C 语言做起来太难了,例如,用 Java 做起来会容易得多。您会推荐我使用 Java 还是 C 中的其他替代方案?
  • @MatheusMinguini 我会在 C 中使用 gmp,或者在 Java 中使用 BigInteger。我自己更喜欢 C,但这完全是个人对语言本身的偏好。
  • @MatheusMinguini 语言的选择是个人喜好,但我不会推荐 C,因为缺少带有析构函数和值语义的类,因此很难使用。例如,具有提升多精度的 C++ 将是一个不错的选择。 JavaScript 也有一个不错的大数字库。
  • 感谢所有回答并帮助我解决这个问题的人!我真的很感激!我最终使用了 Java,一旦我完成项目,我就会在此处发布 GitHub 存储库
【解决方案3】:

你可以使用结构体,只设置你想要的数字,下面的代码没有经过测试,但应该给你一些方向。

我相信这应该使您能够获得大约 4294967295 (max_int) 的 x x 的幂,即您在结构中定义的位置

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
    }
}

【讨论】:

  • 谢谢,伙计!我确实测试过它并且它有效!但我更喜欢使用 Java,这是一种我更习惯和更有经验的语言!不过,我确实感谢您为帮助我所做的努力!再次感谢
  • 我不知道你在哪里要求 java,但我假设(不知道 java)你可以做同样的事情,不客气!
猜你喜欢
  • 2011-02-08
  • 1970-01-01
  • 2012-05-15
  • 1970-01-01
  • 1970-01-01
  • 2014-01-28
  • 1970-01-01
  • 1970-01-01
  • 2019-10-23
相关资源
最近更新 更多