【问题标题】:Fermat's factorisation in C++费马在 C++ 中的因式分解
【发布时间】:2012-05-15 11:51:30
【问题描述】:

为了好玩,我一直在用 C++ 实现一些数学知识,并且一直在尝试实现 Fermats Factorisation Method,但是,我不知道我理解它应该返回什么。我有这个实现,返回105 用于维基百科文章中给出的示例编号 5959。

维基百科中的伪代码如下所示:

尝试不同的 a 值,希望它是一个正方形。

FermatFactor(N): // N should be odd
    a → ceil(sqrt(N))
    b2 → a*a - N
    while b2 isn't a square:
        a → a + 1    // equivalently: b2 → b2 + 2*a + 1
        b2 → a*a - N //               a → a + 1
    endwhile
    return a - sqrt(b2) // or a + sqrt(b2)

我的 C++ 实现,如下所示:

int FermatFactor(int oddNumber)
{
    double a = ceil(sqrt(static_cast<double>(oddNumber)));
    double b2 = a*a - oddNumber;
    std::cout << "B2: " << b2 << "a: " << a << std::endl;

    double tmp = sqrt(b2);
    tmp = round(tmp,1);
    while (compare_doubles(tmp*tmp, b2))  //does this line look correct?
    {
        a = a + 1;
        b2 = a*a - oddNumber;
        std::cout << "B2: " << b2 << "a: " << a << std::endl;
        tmp = sqrt(b2);
        tmp = round(tmp,1);
    }

    return static_cast<int>(a + sqrt(b2));
}

bool compare_doubles(double a, double b)
{
    int diff = std::fabs(a - b);
    return diff < std::numeric_limits<double>::epsilon();
}

它应该返回什么?好像只是返回a + b,这不是5959的因素?

编辑

double cint(double x){
    double tmp = 0.0;
    if (modf(x,&tmp)>=.5)
        return x>=0?ceil(x):floor(x);
    else
        return x<0?ceil(x):floor(x);
}

double round(double r,unsigned places){
    double off=pow(10,static_cast<double>(places));
    return cint(r*off)/off;
}

【问题讨论】:

  • static_cast&lt;double&gt;(b2)?有什么原因吗?还有compare_doubles是怎么定义的?
  • @jli b2 在我之前的实现中是一个int,让我改变它,它没有存在的理由
  • 我会为tmpb2 使用整数类型。为了使测试通过,无论如何您都需要一个整数平方根b2。事实上,所有局部变量的整数实现都返回 101。:)
  • 什么是二元轮函数?

标签: c++ math factorization


【解决方案1】:

请注意,您应该对整数类型进行所有这些计算,而不是浮点类型。它会简单得多(而且可能更正确)。


您的compare_doubles 函数错误。 diff 应该是 double

一旦你解决了这个问题,你就需要修复你的测试线。 compare_doubles 如果其输入“几乎相等”,将返回 true。您需要在它们“不几乎相等”时循环。

所以:

bool compare_doubles(double a, double b)
{
    double diff = std::fabs(a - b);
    return diff < std::numeric_limits<double>::epsilon();
}

还有:

while (!compare_doubles(tmp*tmp, b2))  // now it is
{

您将获得此输入的正确结果 (101)。

您还需要使用 0round 函数称为“位置”,正如 vhallac 指出的那样 - 您不应该四舍五入到小数点后一位数。

您链接的 Wikipedia 文章具有允许您从 Na-b 中识别 b 的等式。

【讨论】:

  • 嘿,我错过了int diff 错误。 :)
  • 添加参考,为集体努力制作 CW ;-)
【解决方案2】:

你的代码有两个问题:

  1. compare_doubles 当它们足够接近时返回 true。因此,while 循环条件被反转。
  2. round 函数需要小数点后的位数。所以你应该使用round(x, 0)

正如我所建议的,将int 用于您的数据类型更容易。 Here's 使用整数实现的工作代码。

【讨论】:

  • 该死的,错过了回合错误:)
  • :) 你的回答更全面。随意添加到您的,以便它可以被选为正确的。
【解决方案3】:

这两个因素是(a+b)和(a-b)。它正在返回其中之一。你可以很容易地得到另一个。

N = (a+b)*(a-b)
a-b = N/(a+b)

【讨论】:

  • 我应该如何从a + b 轻松获得另一个??
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多