I am doing an exercise where I need to find a positive integers p and q which are factors of another natural number n.
Following the formula n=pq*q where p is a squarefree number.
However, for some instances of the program my compiler detects a memory error saying that I am accessing an uninitialized value.
The logic I tried is as follows. Firstly, I took the number that needs to be factored (name it n). Next I found all factors of the number n and placed them in a vector. After that, check if every element of that vector is squarefree. If true, put the element in another vector(a vector of squarefree factors of the number n). After that, go through every element of the vector of squarefree factors and solve the equation q=sqrt(n/p) where p is the squarefree factor from the vector. Additionally, I check the condition if(int(sqrt(n/p))==sqrt(n/p)) because the square root needs to be a positive integer.
#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;
}
For example, my program works if I enter the number 99, but doesn't work if I enter 39. Can anyone give any insight?
Thanks!
As you said, for 39 it doesn't work. Have you checked what it's doing with 39? You should do it, as it is the best way to debug your program.
Let's have a look at it together. First it tries to find all the factors, and it finds 1, 3 and 13: this looks fine.
Then, it checks whether each of those numbers is squarefree, and they all are: this also looks correct.
Then, it checks whether any of the squarefree factors satisfy the equality you are looking for. None of them does (39 is 3 x 13, there's no way it can contain a squared factor). This means that if (int(sqrt(n / x)) == sqrt(n / x)) is never true, and that block is never run. What's the value of sqfree_number and squared at that point? It is never initialised. Using uninitialised values leads to "undefined behaviour", that is, your program can do anything. In this case, p and q end up containing random values.
How can you fix it? Consider this: if n doesn't satisfy your equation, that is, it can't be expressed as pq*q, what, exactly, should the program output? Would your output, as it is now, ever make sense? No. This means you have to modify your program so that it covers a case you hadn't considered.
A way is to add a bool found = false; just before your final for loop. When you find the factors, before breaking, set that variable to true. Then, outside the loop, check it: is it true? Then you can return the correct values. But if it's still false, it means the equality doesn't hold, and you can't return correct values. You have to find a way to signal this to the caller (which is your main function), so that it can print an appropriate message.
And how can you signal it? In general, you could change your Factorise_the_number (by the way, the name of functions should start with a lowercase letter; uppercase letters are usually used for classes) to return a bool. Or you could use a trick: return a special value for p and q that cannot be the result of the calculation. Like -1. Then, before printing, check: if the values are -1, it means the number can't be expressed as pq*q.
Related
I'm supposed to write a small code that generates a random number between 2 and 100 and then checks if its a perfect number. I don't get any bugs from the compiler but the output doesn't show my cout lines like " x is a perfect number". Can someone help me with finding the reason?
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
bool PerfectCheck(int x) {
int t; // divisor
int sum; // sum of divisors
for (t = 0; t <= x; t++ ) {
if (x%t == 0) {
sum = sum + t;
}
}
if (sum == x)
return true;
else
return false;
}
int main() {
srand(time(NULL));
int x = rand()%(100-2+1)+2;
if (PerfectCheck(x) == true )
cout << x << "is a perfect number.";
else
cout << x << "is not a perfect number.";
return 0;
}
There are three problems in your PerfectCheck function. First, you don't initialize the sum variable, so it can start off with any value whatsoever; you should set it to zero explicitly in the declaration.
Second, your for loop starts with t as zero, and you check x % t. The modulo operator implicitly involves a division, so using a left-hand value of zero has the same issue as trying to divide by zero, which will cause a crash.
Third, when checking for a perfect number, don't use that number itself in the sum; so, stop your loop with t < x instead of t <= x.
Also, as mentioned in the comments, you can simplify the return statement. The code below works, in the tests I have performed:
bool PerfectCheck(int x)
{
int sum = 0; // sum of divisors - MUST BE INITIALIZED (to zero)
for (int t = 1; t < x; t++) { // DO NOT INCLUDE X ITSELF!!
if (x % t == 0) {
sum += t;
}
}
return (sum == x); // This will already give a "true" or "false" bool value.
}
You could actually make the code a tiny bit more 'efficient', by initializing sum to 1 and then starting the loop from t = 2 (all numbers divide by 1, after all).
Feel free to ask for further clarification and/or explanation.
if (x%t == 0) calculates the remainder after dividing x by t and compares the result with 0. That statement is correct, but look at the previous code for (t = 0; t <= x; t++ ) {. The first value of t is 0, so you have a division by zero. More than likely that is crashing your program which is why you see no output. Change for (t = 0; t <= x; t++ ) { to for (t = 1; t <= x; t++ ) {.
Also I believe the definition of a perfect number does not include division by the number itself. So the for loop should actually be for (t = 1; t < x; t++ ) {.
Finally you are using the sum variable to add up the divisors but you do not give it an initial value. Your code should say int sum = 0;.
Three errors in a ten line program (plus various style issues). Imagine how many errors here might be in a 5000 line program. Programming is tricky, you have to be very focused and get your code exactly right, nearly right is not good enough.
I am working on a program in which I must print out the number of primes, including 1 and 239, from 1 - 239 ( I know one and or two may not be prime numbers, but we will consider them as such for this program) It must be a pretty simple program because we have only gone over some basics. So far my code is as such, which seems like decent logical flow to me, but doesnt produce output.
#include <iostream>
using namespace std;
int main()
{
int x;
int n = 1;
int y = 1;
int i = 0;
while (n<=239)
{x = n % y;
if (x = 0)
i++;
if (y < n)
y++;
n++;
while (i == 2)
cout << n;
}
return 0;
}
The way I want this to work is to take n, as long as n is 239 or less, and preform modulus division with every number from 1 leading up to n. Every time a number y goes evenly into n, a counter will be increased by 1. if the counter is equal to 2, then the number is prime and we print it to the screen. Any help would be so greatly appreciated. Thanks
std::cout << std::to_string(2) << std::endl;
for (unsigned int i = 3; i<240; i += 2) {
unsigned int j = 3;
int sq = sqrt(i);
for (; j <= sq; j += 2) if (!(i%j)) break;
if (j>sq) std::cout << std::to_string(i) << std::endl;
}
first of all, the prime definition: A prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.
so you can skip all the even numbers (and hence ... i+=2).
Moreover no point to try to divide for a number greater than sqrt(i), because then it will have a divisor less than sqrt(i) and the code finds that and move to the next number.
Considering only odd numbers, means that we can skip even numbers as divisors (hence ... j+=2).
In your code there are clearly beginner errors, like (x = 0) instead of x==0. but also the logic doesn't convince. I agree with #NathanOliver, you need to learn to use a debugger to find all the errors. For the rest, good luck with the studies.
lets start with common errors:
first you want to take input from user using cin
cin>>n; // write it before starting your while loop
then,
if (x = 0)
should be:
if (x == 0)
change your second while loop to:
while (i == 2){
cout << n;
i++;
}
Given X, M, N where X = element to be searched in an array and N = access only first N elements in an array and M = array size, how do we find an element in an array with maximum (N+1) comparisons?
For example,
A = [3,5,2,9,8,4,1,6,7] here M = 9
Let's have N = 6 and X = 5 => So for this case, access only first 6 elements of an array and try to find whether X is present in it or not? Here answer will return true. But for X = 6 answer will be false.
This problem is not about time complexity. it's about number of comparisons you make. For example, Brute force method looks like this.
void search(vector<int> A){
for(int i=0; i<N; i++){ // [i < N is also comparison which is N times]
if(A[i] != X) continue; // [N comparisons ]
else return true;
}
return false;
}
Time complexity is O(n) but number of comparisons will be 2*N. Reduce this comparisons to (N+1). I tried to solve it but did not get solution. Is there any solution actually for this?
Idea
Modify N+1-th element to have X value and eliminate range check. Then once you have found element with X value (which is going to be true if M < N), check it's index (this is a last check that you can perform). If it's equal to N+1 then you haven't found one.
Analysis
Despite that the approach eliminates comparisons duplication, it's still has one "extra" comparison:
bool search(int* a, int n, int x)
{
a[n] = x;
int idx = 0;
while (a[idx] != x) // n + 1 comparisons in case if value hasn't been found
++idx;
return idx < n; // (n + 2)-th comparison in case if value hasn't been found
}
Solution (not perfect, though)
I can see only one way to cut that extra comparison with this approach: is to use the fact that zero integer value converts to false and any integer value not equal to zero converts to true. Using this the code is going to look like this:
bool search(int* a, int n, int x)
{
a[n] = x;
int idx = 0;
while (a[idx] != x) // n + 1 comparisons in case if value hasn't been found
++idx;
return idx - n; // returns 0 only when idx == n, which means that value is not found
}
Below is a calculation for primes. I was trying to deconstruct it to get a better understanding of loops. Also, I would like to tweak this function to find primes by comparing a number to its square root instead of this way:
(assume proper declarations are made before int main)
// Determines whether the number is prime
bool isPrime (long n)
{
int a;
if (n == 1)
{
return false;
}
for (a = 2; a <= (n / 2); a++)
{
if ((n % a) == 0)
{
return false;
}
}
return true;
}
However, observing this loop, I have a question to see if I am observing this function correctly to start with. From what I see, it looks like int a; is the counter and it is starting at 2 since 0 and 1 are not prime. n should be the formal variable. It states that for every number which is less than or equal to itself when divided by two, returns a true for bool if there is a remainder of more than zero. At the same time, if a number divides by two evenly (so no remainder) then it is not considered prime (the bool returns false). Does that sound about right? If not, please do let me know where I made a wrong turn. If I got it right, on to the second half of the program.
Now here, primeCount; is limited with primeCount (2, 50000); in main but The first function feeds into here:
// Counts and organizes the prime numbers using the isPrime function
long primeCount (long x, long y)
{
bool prime;
int b;
int c = 1000;
int counter = 0;
int totalSum = 0;
for (b = 1; b <= y; b++)
{
prime = isPrime (b);
if (prime == true)
{
counter++;
}
if (b == c)
{
cout << setw(10) << left << (b - 999) << setw(10) << left << b << setw(12) << counter << endl;
cout << fixed << showpoint << setprecision(2) << endl;
totalSum = totalSum + counter;
counter = 0;
c = c + 1000;
}
}
Now, I figure x and y are formal variables but I don't know what x is supposed to represent. Does it represent int c; ? The for loop in that function completely confused me. I don't understand it. Any light that can be shed on that would be appreciated.
As for the square root inquiry, would I need to use 3 nested for loops in order to get the primes?Like this:
for (a > m => b)
for (a==m => b==m)
for (a < m => b>m)
Would locating the primes this way be more or less complicated than the way illustrated here? I know this is a lot to tackle. IF you guys suggest that I break it into separate posts, I'll edit this one and post the second half in a different post. Thanks for the assist! Just a freshman C++ programmer trying to make heads and tails out of this stuff :)
The first function isPrime() does what it is supposed to. Returns true if a number is prime and returns false if it is not. The reason why the loop variable a runs only till n/2 is because any number n cannot have a factor that is greater than n/2 (apart from itself). EXAMPLES? 6 -- 1, 2, 3 and 6, 12 -- 1, 2, 3, 4, 6 and 12. The loop is just trying to see if a has any factors (numbers that divide it without leaving a remainder). If it does it is not a prime (return false) else it is (return true).
However I feel that primeCount() doesn't completely do what it is intended to.
From the definition of primeCount() I think it is meant to compute the total number of prime numbers from x to y (in your case 2 to 50000, since you mentioned main() calls primeCount(2, 50000)). However for it to do this the for loop must be changed to this
for (b = x; b <= y; b++)
The role of the variable c here is to keep a check for every thousandth value of the loop variable b.
Notice that on 1st run when b = 1000 i.e b == c the program prints the number of primes that it encountered until now (counter). After that the counter is reset to 0 and c is now 2000.Then, b goes on from 1001 to 2000 and the same thing repeats till b is 50000.
Overall, The idea is to print the number of primes that exist within each 1000 natural numbers from 2 to 50000.
for (a = 2; a <= (n / 2); a++)
{
if ((n % a) == 0)
{
return false;
}
}
This is the "for" loop you use. It checks the remainder of n when dividing by each "a", iterating from 2, up to n/(one half (integral division) of n). If ANY of these remainders is zero, then n is a composite, and there's no point continuing onward. We just return a false - the number is not prime.
It is safe to assume that if we have not found a divisor of n until (n/2), the number is a prime, so AFTER we try all possibile guesses for divisors, if we got that far, we return that the number IS prime.
#include <iostream>
#include <cstdlib>
typedef unsigned long long int ULL;
ULL gcd(ULL a, ULL b)
{
for(; b >0 ;)
{
ULL rem = a % b;
a = b;
b = rem;
}
return a;
}
void pollard_rho(ULL n)
{
ULL i = 0,y,k,d;
ULL *x = new ULL[2*n];
x[0] = rand() % n;
y = x[0];
k = 2;
while(1){
i = i+1;
std::cout << x[i-1];
x[i] = (x[i-1]*x[i-1]-1)%n;
d = gcd(abs(y - x[i]),n);
if(d!= 1 && d!=n)
std::cout <<d<<std::endl;
if(i+1==k){
y = x[i];
k = 2*k;
}
}
}
int main()
{
srand(time(NULL));
pollard_rho(10);
}
This implementation is derived from CLRS 2nd edition (Page number 894). while(1) looks suspicious to me. What should be the termination condition for the while loop?
I tried k<=n but that doesn't seem to work. I get segmentation fault. What is the flaw in the code and how to correct it?
I only have a 1st edition of CLRS, but assuming it's not too different from the 2nd ed., the answer to the termination condition is on the next page:
This procedure for finding a factor may seem somewhat mysterious at first. Note, however, that POLLARD-RHO never prints an incorrect answer; any number it prints is a nontrivial divisor of n. POLLARD-RHO may not print anything at all, though; there is no guarantee that it will produce any results. We shall see, however, that there is good reason to expect POLLARD-RHO to print a factor of p of n after approximately sqrt(p) iterations of the while loop. Thus, if n is composite, we can expect this procedure to discover enough divisors to factor n completely after approximately n1/4 update, since every prime factor p of n except possibly the largest one is less than sqrt(n).
So, technically speaking, the presentation in CLRS doesn't have a termination condition (that's probably why they call it a "heuristic" and "procedure" rather than an "algorithm") and there are no guarantees that it will ever actually produce anything useful. In practice, you'd likely want to put some iteration bound based on the expected n1/4 updates.
Why store all those intermediary values? You really don't need to put x and y in a array. Just use 2 variables which you keep reusing, x and y.
Also, replace while(1) with while(d == 1) and cut the loop before
if(d!= 1 && d!=n)
std::cout <<d<<std::endl;
if(i+1==k){
y = x[i];
k = 2*k;
So your loop should become
while(d == 1)
{
x = (x*x - 1) % n;
y = (y*y - 1) % n;
y = (y*y - 1) % n;
d = abs(gcd(y-x,n))%n;
}
if(d!=n)
std::cout <<d<<std::endl;
else
std::cout<<"Can't find result with this function \n";
Extra points if you pass the function used inside the loop as a parameter to pollard, so that if it can't find the result with one function, it tries another.
Try replacing while(1) { i = i + 1; with this:
for (i = 1; i < 2*n; ++i) {