【问题标题】:Fermat Algorithm for prime factors calculation素因数计算的费马算法
【发布时间】:2015-10-20 18:16:09
【问题描述】:

根据youtubelink质因数可以计算如下:

a = sqrt(N + b^2)

我写了下面的程序来做到这一点,但我没有得到 2345678917 的素数。我知道这是素数,但对于其他素数,程序确实返回 1 和数字本身,但对于这个数字它没有发生。为什么?

#include <stdio.h>
#include <math.h>

void foo(unsigned long long x)
{
    int i;
    for (i=1;i<x;i++)
        if (fmod(sqrt(x + i*i), 1) == 0) {
            printf("%f %f\n", (sqrt(x + i*i) - i), (sqrt(x + i*i)+i));
            return;
        }
}

int main(void) {
    foo((unsigned long long)2345678917);
    return 0;
}

【问题讨论】:

  • 这个问题仍然没有答案,所以请继续发布您的解决方案。

标签: algorithm math prime-factoring


【解决方案1】:

首先i(int)的类型不匹配x(unsigned long long)。将i 的类型更改为unsigned long long 即可开始。

一旦你这样做了,你的程序就会很高兴地宣布 14 * 167548494 = 2345678917。当然,这不是真的,因为两个偶数的乘积不可能是奇数。这里的问题是精度损失,所以你需要实现一个整数的平方测试函数,而不是测试浮点平方根是否是整数。

#include <stdio.h>
#include <math.h>

unsigned long long find_sqrt(unsigned long long x)
{
    unsigned long long lo = 1;
    while (4 * lo * lo <= x) lo *= 2;
    unsigned long long hi = 2 * lo;
    while (lo + 1 < hi) {
        unsigned long long mid = lo + (hi - lo) / 2;
        if (mid * mid <= x) lo = mid;
        else hi = mid;
    }
    return lo * lo == x ? lo : 0;
}

void foo(unsigned long long x)
{
    unsigned long long i;
    for (i=1;i<x;i++) {
        unsigned long long sqrt_x_ii = find_sqrt(x + i*i);
        if (sqrt_x_ii) {
            printf("%llu = %llu * %llu\n",
                   x, sqrt_x_ii - i, sqrt_x_ii + i);
            return;
        }
    }
}

int main(void) {
    foo((unsigned long long) 2345678917);
    return 0;
}

【讨论】:

  • 是的,它要么很慢,要么卡在 inf 循环中,我没有在调试器中停止它进行检查。可能是很长一段时间没有找到任何确切的 sqrts。
  • @nomanpouigt:2345678917 + i*i 是正方形的最小i1172839458。计算超过 10 亿个整数平方根需要超过 5 秒,你不应该感到惊讶。无论如何,这个答案提供了基本信息:即您在浮点精度方面遇到了困难。请注意,对于 i 的值,2345678917 + i*i1375552396587412681,它不能在 IEEE 754 binary64 double 中精确表示(这可能是您的平台正在使用的)。
  • @nomanpouigt:顺便说一下,这个答案中的代码为我编译并运行得很好,产生了输出2345678917 = 1 * 2345678917。给出这个结果确实需要几分钟。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-24
  • 2014-10-16
  • 1970-01-01
  • 1970-01-01
  • 2020-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多