获取所有方法将数字表示为两个整数的乘积

时间:2019-03-19 15:38:34

标签: c++ factors

最近我一直在寻找数字的除数,因此决定尝试制作一个程序,该程序以各种方式打印将数字N表示为两个整数的乘积。我写了一篇关于正数的文章,只考虑了正数来构成乘积。

#include <iostream>
#include <cmath>

int main()
{
    int n;
    std::cin >> n;

    int root = std::sqrt(n);
    for(int i = 1; i <= root; i++)
    {
        if(n % i != 0)
            continue;

        int j = n / i;  
        std::cout << i << ", " << j << std::endl;
    }

    return 0;
}

上面的代码只是找到N的所有因数并将它们成对打印。效果很好,但我想尝试使其找到所有可能的方法,不仅获得正数,而且还可以达到N。

例如,如果我在上面的程序中输入10,结果将是(1,10),(2,5);这些是正确的,但是还有其他方法可以将两个数字相乘并得到10。它涉及负数:(-1,-10),(-2,-5)也是解决方案,因为当您将两个负数相乘时,最后得到一个积极的结果。

如果我希望程序只对正N值起作用,而且还能找到负数倍数,那么我可以只打印i和j的负数,因为您只能通过将两个正数或两个负数相乘来获得正数在一起。

那行得通,但是现在我想让此代码在负N值上运行。例如,N = -10的预期输出为:(-1,10),(1,-10),(2,-5),(-2,5);

问题是,上述算法只能找到正数的正因数,因为它涉及平方根(仅针对正数定义),并且循环从正数开始并以正数结束。

我注意到我可以只计算N的绝对值的平方根,然后使循环从-root开始,然后从root结束,从而遍历N的负除数。但是,我必须确保跳过0,因为未定义0除法,这使其崩溃。我最终得到的代码如下:

#include <iostream>
#include <cmath>

int main()
{
    int n;
    std::cin >> n;

    int root_n = std::sqrt(std::abs(n));
    for(int i = -root_n; i <= root_n; i++)
    {
        if(i == 0 || n % i != 0)
            continue;

        int j = n / i;  
        std::cout << i << ", " << j << std::endl;
    }

    return 0;
}

它对我提出的所有测试均正常工作,但我不确定这是否是编写它的最佳方法。有什么我可以改善的吗?

谢谢!

编辑:根据Caleth的建议使用std :: div进行了尝试(还使用了VS中的ReSharper插件为我提供了重构建议):

#include <iostream>
#include <cstdlib>

int main()
{
    int n;
    std::cin >> n;

    const int sqrt_n = std::sqrt(std::abs(n));
    for(auto i = -sqrt_n; i <= sqrt_n; i++)
    {
        if (i == 0)
            continue;

        const auto div_res = std::div(n, i);
        if (div_res.rem)
            continue;

        std::cout << i << ", " << div_res.quot << std::endl;
    }

    return 0;
}

我可以只计算一次std :: div而不是计算余数,再计算商,它返回一个包含两个值的结构。

1 个答案:

答案 0 :(得分:0)

一个主要的观察结果是,除符号外,数字的负除数和正除数相同。如果只看正数并自己处理符号,则可以节省一半的时间。例如,

int main()
{
    int n;
    std::cin >> n;

    int root_n = std::sqrt(std::abs(n));

    for(int i = 1; i <= root_n; i++) \\ don't loop over negative numbers now
    {
        if(n % i != 0) \\ not necessary to check for 0 anymore
            continue;

        int j = n / i;  
        std::cout << i << ", " << j << "\n";
        std::cout << -i << ", " << -j << "\n";  \\ corresponding negative
    }

    return 0;
}

您可能会注意到我删除了std::endl ---您实际上并不需要经常刷新流。让输出缓冲随心所欲更快。

如果您正在寻找其他方法来修改程序,则可以尝试查找素因数分解,然后从中计算除数列表。对于大型,高度复合的输入,这将更快。但这也完全不同。