printing the perfect divisor factors

I have created this C++ file that allows me to check for perfect integer numbers ranging from 1 - 1000, and then print them.  I have done this, but now I am trying to include the divisors of each perfect number that prints on the screen, and I am stuck.  I tried adding a void printFactors (int number), but it was just printing all the numbers and it went crazy.  Any ideas, without adding another function to my code?  Thanks

#include <iostream>	//allows program to perform input and output
 
using std::cout;	//program uses cout
using std::cin;		//program uses cin
using std::endl;	//program uses endl
 
bool perfect (int number) // declare perfect integer function
{
	bool perfect;
	int number1 = 0;
	for (int i = 1; i != number; i++)
	{
		if (number%i == 0)
		{
			number1 += i;
		}
	}
	if (number1 == number)
		perfect = true;
	else
		perfect = false;
	return perfect;
 
}//end perfect integer function
 
 
int main()	//function main begins program execution
{
	int number = 1000;
 
	for (int i = 1; i <= number; i++)
	{
		if (perfect(i) == true)
			cout << i << endl;	// print i
			
	}
	return 0;
}	//end main function

Open in new window

rebelcowgirl_73Asked:
Who is Participating?
 
Infinity08Connect With a Mentor Commented:
>> Thanks so much for all of your help!!!!!!!!!!!!!!

No problem ;) Code looks good too.

Here's how you can make it slightly better :

        cout << "1";
        for (int i = 2; i != number; i++) {
            if (number%i == 0) {
                    cout << " + " << i;
            }
        }

since we already know the first divisor, we can immediately print it ...
0
 
Infinity08Connect With a Mentor Commented:
>> but now I am trying to include the divisors of each perfect number that prints on the screen

You already found the divisors here :

                if (number%i == 0)
                {
                        number1 += i;
                }

In this if block, i is a divisor of number. I'm sure you can make it work with that hint :) Give it a try.
0
 
kaylanreilorCommented:
Infinity08 is right but I think you already knew it.
So I propose a code.
Concerning the algo, I've only change the condition of your loop in the perfect function because there is no need to go further than the half of the propose number.
#include <iostream>
#include <vector>
 
using namespace std;
 
bool perfect(int,vector<int>*);
 
int main()
{
	int number = 1000;
	vector<int> divisors; 
	for (int i = 1; i <= number; i++)
	{
		divisors.clear();
		if (perfect(i,&divisors) == true)
		{
			cout << "Here is a new perfect number : ";
			cout << i << endl;
			cout << "And its divisors are :" << endl;
			for(size_t j=0;j<divisors.size();j++)
				cout << divisors[j] << endl;
		}
			
	}
         return 0;
}
 
bool perfect(int number,vector<int>* pvec)
{
	int number1 = 0;
	for (int i = 1; i <= number/2; i++)
	{
		if (number%i == 0)
		{
			number1 += i;
			pvec->push_back(i);
		}
	}
	if (number1 == number)
		return true;
	return false;
}

Open in new window

0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
Infinity08Commented:
kaylanreilor, since this is an assignment, we're not allowed to just post the solution. We have to go into tutor mode, and help the asker find the solution himself.

btw, why pass a vector by pointer ? A reference would work a lot better ;)
0
 
Infinity08Commented:
Oh, and an imo better approach would be to put the code for finding the divisors in a separate function, which can then be used to determine if the value is a perfect number.
0
 
rebelcowgirl_73Author Commented:
we haven't learned vectors and all that, we are only in the first few weeks of C++.
0
 
Infinity08Commented:
>> we haven't learned vectors and all that, we are only in the first few weeks of C++.

You don't need vectors ... Just take a look at the hint in my first post ... Did that get you going ?

Think of the desired output you want, and how you can achieve that. Compare it with the output you have now, and what you need to add to get to the desired output.

I'm intentionally vague ... If I'm too vague, tell me so. But give it a try ;)
0
 
itsmeandnobodyelseConnect With a Mentor Commented:
>>>> we haven't learned vectors and all that, we are only in the first few weeks of C++.

You can't print out the factors in the loop in perfect fucntion cause you won't know before loop end whether the number is perfect or not. One way out is to pass an array where the perfect function adds all factors and when perfect returned true, you could print out the factors as well by simply iterating the factors returned in the array (that is the solution kaylanraylor had posted). Infinity proposed a second way where you would have a second function whcih prints the numbers *after* you found out that it was perfect. That would be in main like:

            if (perfect(i) == true)
                                {
                     cout << "perfect: " << i << " divisors: " << printdivisors(i) << endl;      

The printdivisors would be much similar to the perfect function beside that it *knows* that the passed number ws perfect and therefore could output any divisor with cout:
            if (number%i == 0)
            {
                                       cout << i << ' ';    // prints the number + a space


What I personally don't like with that solution is that the printdivisors actually has redundant code. The array solution is fine but if you won't (can't) use dynamic arrays I would recooemnd against either.

A third way is to have the perfect function make the printouts as well:

      bool find_perfect_and_print (int number)
      {
            ...
            // in case of a perfect number we have to find the divisors again
            // so we have a outer loop with exactly two iterations
            for (int n = 0; n < 2; ++n)
            {
      for (int i = 1; i < number; i++)
      {
                      if (number%i == 0)
                      {
                            if (n == 0)
                                  ....     // add the divisor
                            else /* if (n == 1) */
                                  ....    // print the divisor                          
                      }
                      // handle case (n == 0) and return false if number isn't perfect
                      // if number is perfect print it and continue the loop so that it prints the divisors
                      ...
              }
             return true;  // if come here we actually *know* it is perfect
      }

You see the function is a little bit 'bumpy' and actually it seems not to be well defined cause it makes two quite different things like calculating and printing, so I would recommend a 4th way. Here, the main idea is that the number of divisors for any (32bit) integer is 31 (factor is all 2). If we use primes for factors only (and omit the 1 as it always was factor) we see that the maximum number of prime factors for an integer is 10  (2*3*5*7*11*13*17*19*23) cause the next prime would make the product > 2^32. Because of that small number we could define a fix-sized array in the main, pass it to the perfect and let the perfect fill all the divisors:

     int main()      //function main begins program execution
     {
            int numdivisors = 0;        // that is to take the number of divisors
            int divisors[16] = { 0 };  // that is splendid as told above
                                                   // = { 0 } makes all elements 0
            ....

Then, pass the array to the perfect function (similar to that kaylanreilor posted)


                     if (perfect(i, divisors, numdivisors ) == true)

To make that compile the perfect has to be declared as

     bool perfect(int number, int divisors[], int& numdivisors);


Note the 'int&' . It makes the numdivisors passed by reference. That way the calling function gets the value back when it was changed in the perfect.

To make the wole thing running there are only three points left todo:

1. initialized  the numdivisors to 0 at begin of perfect
2. Fill the divisors array in perfect whenever you add a divisor to number1.
    and increment the numdivisors.
   
    if (number%i == 0)
    {
           divisors[numdivisors] = i;
           ++numdivisors;
           ....    // add to number1

3. In main when perfect(i, ....) was true, print the divisors from 0 to numdivisors-1    

Regards, Alex
0
 
rebelcowgirl_73Author Commented:
ok, I decided before I read the last few entries to try adding a print function that would allow me to see the divisors listed after the perfect # was displayed.  Wow, I just want to say thanks to itsmeandnobodyelse and infinity08 for trying tso hard to help me.  I have added my code below, but now when it prints, it prints wierd.  What I mean to say is I was hoping it would print like this:
6 1 2 3 ( I would fix it with words later)
but it is printing like this
1 2 3 6 0 (dont exactly know where the 0 is coming from)

My other problem is we are only suppose to have the main function nd the perfect function.  adding the printAdvisors function is more then we asked for in the instructions.  Here's hoping you two can see my mistake and help!  I would prefer to not have the additional function but would settle for figuring out why it is printing weird.  Thanks so much for trying to teach me rather then just giving me the answers.  I am extremely new to C++, and the only parts we have really discussed is the basics.  We have not gotten into arrays and vectors and all that.  I barely know how to seperate functions and not include everthing in main.  Thanks again....

Only included the changed main and the new printDivisors,  perfect has not changed.
bool printDivisors (int number)
{
	bool perfect;
	for (int i = 1; i != number; i++)
		if (number%i == 0)
		{	
                       cout << i << " ";
		     perfect = true;
		}else
		     perfect = false;
	return perfect;
}	
int main()	//function main begins program execution
{
	int number = 1000;
	for (int i = 1; i <= number; i++)
	{
	      if (perfect(i) == true)
		cout << i << printDivisors(i) <<endl;   // print i
	}
	return 0;
}	//end main function

Open in new window

0
 
Infinity08Connect With a Mentor Commented:
>> but it is printing like this

The code should print in the correct order because of this line :

                cout << i << printDivisors(i) <<endl;   // print i

that prints the perfect number first and then the divisors.

The extra 0 at the end is because it also prints the return value of the printDivisors(i) call which is a bool. Instead use this code :

              if (perfect(i) == true) {
                cout << i << " : ";
                printDivisors(i);
                cout <<endl;   // print i
              }
0
 
Infinity08Connect With a Mentor Commented:
Note that your printDivisors function does not need to return anything, nor does it need the perfect boolean value, so it can just be :

        void printDivisors (int number)
        {
                for (int i = 1; i != number; i++)
                        if (number%i == 0)
                        {
                               cout << i << " ";
                        }
        }

That's it.

Now, your code does what it needs to do, which is good !

We can make it better though ... As Alex already pointed out, you calculate the divisors twice, which is a waste of time (not to mention that it is done with two different functions).

The only way to get around this is to calculate the divisors once and store them somewhere to be used by the perfect and the printDivisors functions.
You said you hadn't learned about vectors yet. Have you learned about arrays ?
0
 
Infinity08Commented:
>> The code should print in the correct order because of this line :

Actually, that isn't true, because the behavior is undefined. But never mind about that. With the fix I mentioned, it's all ok.
0
 
rebelcowgirl_73Author Commented:
No I have not learned about arrays yet.  I tried to change the printDivisors function to void as you suggested but not it is printing more than just the divisors from the perfect numbers, llike the problems I was having before, the printing goes hay-wire.  Any Ideas?  
0
 
rebelcowgirl_73Author Commented:
I also see that it does in fact for some reason print backwards as in
1 2 3 6 (6 should be at the beginning because it is the perfect number or (i))
I have made no changes because the suggestions you made caused it to print more then just the divisors of the 3 perfect numbers between 2 and 1000
0
 
Infinity08Commented:
>> I tried to change the printDivisors function to void as you suggested

Did you make the other change I suggested too ?

              if (perfect(i) == true) {
                cout << i << " : ";
                printDivisors(i);
                cout <<endl;   // print i
              }

instead of :

                cout << i << printDivisors(i) <<endl;   // print i
0
 
rebelcowgirl_73Author Commented:
yes I made the changes all of them but it prints alot of lines having nothing to do with the 3 perfect #s between 2 - 1000 as I posted.
0
 
Infinity08Commented:
Can you post the complete code you're using now ?
0
 
rebelcowgirl_73Author Commented:
I guess in trying all the different ways and changing words around somewhere I must have messed up the code somewhere, because I just walked threw the steps again and now it is working correctly.  Again thanks for the lesson.

One final question is there a way to take the program and only use 2 functions (main and perfect) and still get it to print this way!

Thanks
0
 
rebelcowgirl_73Author Commented:
Also do you know of a way to but a plus sign in between the divisors?  
Would kind of like it to read more like this:
6: 1 + 2 + 3
It would seem to make more since when trying to see the divisors, but I cant seem to figure out a way to get the plus sign between the divisors.

It now prints like this:
6: 1 2 3 which is great it is doing what it is suppose to.  

I too am trying to be vague incase someone else needs to learn this also, but I can include my code if it would help you answer this question.  Thanks again!!!!!
0
 
Infinity08Connect With a Mentor Commented:
>> One final question is there a way to take the program and only use 2 functions (main and perfect) and still get it to print this way!

There's always a way. For example, you can put the code for printing inside the perfect function ... It doesn't make a lot of sense though. Do you have a requirement to do it that way ?


>> Also do you know of a way to but a plus sign in between the divisors?  

Sure. Right now, you put a space between the values :

        cout << i << " ";

You just have to replace that space with a +


>> I too am trying to be vague incase someone else needs to learn this also, but I can include my code if it would help you answer this question.

Well, it IS your question, so you don't have a reason to be vague ;) It's admirable though, but right now, the main goal is to help you :)


Just one thing : if anything is not clear, then please ask about it. It's best to understand the way the code works. Feel free to ask anything, no matter how silly it might seem.
0
 
rebelcowgirl_73Author Commented:
>>There's always a way. For example, you can put the code for printing inside the perfect function ... It doesn't make a lot of sense though. Do you have a requirement to do it that way ?

I dont know if you would call it a requirement, but the instructions stare just the two methods and not a third for printing, also the print method has been just vaguely discussed.

>>Sure. Right now, you put a space between the values :

        cout << i << " ";

You just have to replace that space with a +

wouldn't that make it so when the perfect numbers display they will have the + sign and not the divisors?
0
 
Infinity08Commented:
>> I dont know if you would call it a requirement, but the instructions stare just the two methods and not a third for printing, also the print method has been just vaguely discussed.

Then I assume it's not bad to have them in two functions.

If you do want them in one, then you can do that of course. Just put everything into one function.


>> wouldn't that make it so when the perfect numbers display they will have the + sign and not the divisors?

Depends which one you modify ;) Of course you have to modify the one that prints the divisors. Note that you'll also have to account for the last one, because you don't want a trailing +.

0
 
rebelcowgirl_73Author Commented:
I was just about to ask for the trailing one, because I don't know how to get rid of it...
0
 
Infinity08Commented:
>> because I don't know how to get rid of it...

The trick is to treat the first divisor differently inside the loop.

Right now, this code prints the divisors :

                for (int i = 1; i != number; i++)
                        if (number%i == 0)
                        {
                               cout << i << " + ";
                        }

If we put the + before the i :

                               cout << " + " << i;

and make sure that the first divisor is printed like this :

                               cout << i;

then the output will be good.

So, how do we distinguish the first divisor from the others ? That's easy. The first divisor is always 1. I'm sure that hint will help you :)

Give it a try ...
0
 
rebelcowgirl_73Author Commented:
for (int i = 1; i != number; i++)
      if (number%i == 0)
      {
         if (i == 1)
            cout << i;
         else
            cout << " + " << i;
      }
Thanks so much for all of your help!!!!!!!!!!!!!!
0
All Courses

From novice to tech pro — start learning today.