我正在做一个练习,需要找到一个正整数p
和q
,它们是另一个自然数n
的因数。
遵循公式n=pq*q
,其中p是 squarefree 数。
但是,对于程序的某些实例,我的编译器检测到一个内存错误,表明我正在访问未初始化的值。
我尝试的逻辑如下。首先,我采用了需要分解的数字(将其命名为n)。接下来,我找到了所有数为n的因子,并将它们放在向量中。之后,检查该向量的每个元素是否都是 squarefree 。如果为true,则将元素放在另一个向量中(n个无平方因子的向量)。之后,遍历平方无因数向量的每个元素,并求解方程q=sqrt(n/p)
,其中p是向量中的平方无因数。另外,我检查条件if(int(sqrt(n/p))==sqrt(n/p))
,因为平方根必须是一个正整数。
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
// Function that checks if the number is squarefree
bool isSquareFree(int n)
{
if (n % 2 == 0)
n = n / 2;
if (n % 2 == 0)
return false;
for (int i = 3; i <= sqrt(n); i += 2)
{
if (n % i == 0)
{
n = n / i;
if (n % i == 0)
return false;
}
}
return true;
}
void Factorise_the_number(int n, int &p, int &q)
{
if (n <= 0)
return 0;
vector<int> factors(0); // vector of factors
vector<int> sqfree_factors(0); // vector of squarefree factors
int sqfree_number; // the number "p"
int squared; // is essentially the number "q"
for (int i = 1; i <= n / 2; i++)
{
if (n % i == 0)
factors.push_back(i); // takes all factors of the number "n"
}
for (int i = 0; i < factors.size(); i++)
{
if (isSquareFree(factors.at(i)))
sqfree_factors.push_back(factors.at(i));
} // checks if each factor is squarefree. if yes, put it in a separate vector
for (auto x : sqfree_factors)
{
if (int(sqrt(n / x)) == sqrt(n / x))
{ // if true, we found the numbers
squared = sqrt(n / x);
sqfree_number = x;
break;
}
}
p = sqfree_number;
q = squared;
}
int main()
{
int n, p = 0, q = 0;
cin >> n;
Factorise_the_number(n, p, q);
cout << p << " " << q;
return 0;
}
例如,如果我输入数字99
,则我的程序可以工作,但是如果输入39
,则该程序不工作。谁能提供任何见识?
谢谢!
答案 0 :(得分:0)
正如您所说,对于39而言,它是行不通的。您是否检查过39的功能?您应该这样做,因为这是调试程序的最佳方法。
让我们一起看一下。首先,它尝试查找所有因素,然后找到1、3和13:这看起来不错。
然后,它检查这些数字中的每个数字是否都是无平方的,并且都为:这看起来也是正确的。
然后,它检查是否有任何平方自由因数满足您要寻找的相等性。它们都不起作用(39是3 x 13,它不可能包含平方因子)。这意味着if (int(sqrt(n / x)) == sqrt(n / x))
永远不会为真,并且该块永远不会运行。此时sqfree_number
和squared
的值是多少?它从未被初始化。使用未初始化的值会导致“未定义的行为”,也就是说,您的程序可以执行任何操作。在这种情况下,p
和q
最终将包含随机值。
如何解决?考虑一下:如果n
不满足您的等式,也就是说,它不能表示为pq * q,那么程序应该输出什么呢?您现在的输出是否有意义?否。这意味着您必须修改程序,使其涵盖您没有考虑的情况。
一种方法是在最后一个bool found = false;
循环之前添加一个for
。找到因素后,将其断开之前,将该变量设置为true
。然后,在循环之外检查它:是true
吗?然后,您可以返回正确的值。但是,如果它仍然是false
,则意味着等式不成立,并且您将无法返回正确的值。您必须找到一种向呼叫者发送信号的方法(这是您的main
函数),以便它可以打印适当的消息。
您怎么发信号呢?通常,您可以更改Factorise_the_number
(顺便说一句,函数名称应以小写字母开头;类通常使用大写字母)以返回bool
。或者,您可以使用一个技巧:为p
和q
返回一个特殊值,该值不能作为计算结果。像-1。然后,在打印之前,检查:如果值是-1,则表示该数字不能表示为pq * q。