# Writing a function that determines if a number is perfect

• Valour549

#### Valour549

First of all there are plenty of answers on Google for this commonly searched problem, but none of them gives me the solution I am looking for.

What I am looking for is how to write a function which determines whether a parameter number is a perfect-number. Take the code below for example, notice how the function perfect doesn't actually tell you whether number is a perfect-number or not. All it does is add all the divisors of number and put it into sum. The part of the code that actually determines whether number is a perfect-number or not is inside the function main.

In other words, I am wanting to know how to put the actual determination (starting with... if(re==n)...) inside the function perfect, which I'm strugging with since my knowledge of function is that they end with return {expression} (if they do indeed return a value), or simply return; (if they don't return anything at all).
Code:
#include<iostream>
using namespace std;
int perfect(int number)
{
int sum=0;
for(int i=1;i<number;i++)
{
if(number%i==0)
{
sum=sum+i;
}
}
return sum;
}
void main()
{
int n;
cout<<"Enter a number: ";
cin>>n;
int re= perfect(n);
if(re==n)
cout<<"\n\nYes!\n  It Is A perfect number.\n\n";
else
cout<<"\n\nNo! \n  It Is Not A Perfect Number.\n\n";
}

First of all there are plenty of answers on Google for this commonly searched problem, but none of them gives me the solution I am looking for.

What I am looking for is how to write a function which determines whether a parameter number is a perfect-number. Take the code below for example, notice how the function perfect doesn't actually tell you whether number is a perfect-number or not. All it does is add all the divisors of number and put it into sum. The part of the code that actually determines whether number is a perfect-number or not is inside the function main.

In other words, I am wanting to know how to put the actual determination (starting with... if(re==n)...) inside the function perfect, which I'm strugging with since my knowledge of function is that they end with return {expression} (if they do indeed return a value), or simply return; (if they don't return anything at all).
Code:
#include<iostream>
using namespace std;
int perfect(int number)
{
int sum=0;
for(int i=1;i<number;i++)
{
if(number%i==0)
{
sum=sum+i;
}
}
return sum;
}
void main()
{
int n;
cout<<"Enter a number: ";
cin>>n;
int re= perfect(n);
if(re==n)
cout<<"\n\nYes!\n  It Is A perfect number.\n\n";
else
cout<<"\n\nNo! \n  It Is Not A Perfect Number.\n\n";
}
Why not add the test number==sum to your function "perfect", and return 0 if the number is not perfect, and 1 if the number is perfect?

Last edited:
• Valour549
A function that returns a value does not need to have a single 'return' statement as the last statement. Whenever the flow of control encounters a 'return' statement, control returns to the calling function and the specified value is passed back to the calling function as the value of the called function. So you can have something like this:

C:
    if (condition)
return 1;
else
return 0;

Then in the calling function, you can have a statement like this:

C:
if(perfect(n) == 1)
// do something
else
// do something else

Because your function has now effectively become a Boolean function (returns the result of a true/false) decision, I would prefer to redefine the function so it returns a value of type 'bool' (that is, either 'true' or 'false') instead of an int.

C:
bool perfect(int number)
{
// other stuff omitted for brevity
if (sum == number)
return true;
else
return false;
}

You can do this more concisely, because the expression 'sum == number' itself has a Boolean value, so you can return it directly:

Code:
bool perfect(int number)
{
// other stuff omitted for brevity
return (sum == number);
}

(I don't think the parentheses are necessary, but I use them anyway because I think it looks nicer. Other people probably have different opinions.)

Now in your main() you can simply say this:

C:
if(perfect(n))
// do something
else
// do something else

Actually, I think you can do this also with the version of the function that returns an int, because 0 is automatically converted to 'false' and non-zero is automatically converted to 'true' in a Boolean context. You might get a compiler warning about it. I'm not expert on the niceties of the C++ standard here.

By the way, why are you using 'void main()'?

https://isocpp.org/wiki/faq/newbie#main-returns-int

• pbuk and Valour549
I played around with it, do you something like this? I think this is error-free lol though it'd be nice if you could concur.
Code:
#include <iostream>
using namespace std;

int isPerfect(int);

int main()
{
int n, result;

cout<<"Enter a number: ";
cin>>n;
result=isPerfect(n);

if(result==1)
cout<<n<<" is a perfect number!"<<endl;
else
cout<<n<<" is not a perfect number."<<endl;

return 0;
}

int isPerfect(int number)
{
int sum=0, result=0;
for(int counter=1; counter<number; counter++)
{
if(number%counter==0)
sum+=counter;
}

if(number==sum && number!=0) // prevent zero from being a perfect number
result=1;

return result;
}

PS: The code in my first post wasn't my own. I just copied it from another site to make a point.

Now my next question: Is it possible to somehow move the "if... else" portion of the function main into the function isPerfect ?

Say something like this
Code:
...
int isPerfect(int number)
{
int sum=0, result=0;
for(int counter=1; counter<number; counter++)
{
if(number%counter==0)
sum+=counter;
}

if(number==sum && number!=0)// prevent zero from being a perfect number
return cout<<number<<" is a perfect number!"<<endl;
else
return cout<<number<<"is not a perfect number."<<endl;
}

and then I'll change the function main part to
Code:
int main()
{
int n, result;

cout<<"Enter a number: ";
cin>>n;
result=isPerfect(n);
cout<<result;

return 0;
}

Now my next question: Is it possible to somehow move the "if... else" portion of the function main into the function isPerfect ?

Say something like this
Code:
...
int isPerfect(int number)
{
int sum=0, result=0;
for(int counter=1; counter<number; counter++)
{
if(number%counter==0)
sum+=counter;
}

if(number==sum && number!=0)// prevent zero from being a perfect number
return cout<<number<<" is a perfect number!"<<endl;
else
return cout<<number<<"is not a perfect number."<<endl;
}

and then I'll change the function main part to
Code:
int main()
{
int n, result;

cout<<"Enter a number: ";
cin>>n;
result=isPerfect(n);
cout<<result;

return 0;
}
You could do something like this, but I'm not sure it's good practice.
The function isPerfect determines whether a number is perfect or not.
How a program uses this information is another thing: better keep the two tasks separated.

Of course this is not crucial is a very small program such as this one. But in principle I would keep the tasks separated.

• jtbell and Valour549
I tried it and turns out I can't. I think the compiler is saying that I can't put cout after return

if(number==sum && number!=0)// prevent zero from being a perfect number
return cout<<number<<" is a perfect number!"<<endl;
else
return cout<<number<<"is not a perfect number."<<endl;

Now my next question: Is it possible to somehow move the "if... else" portion of the function main into the function isPerfect ?

In order for your new main() to work the way you want it to work, the function has to return a string. But this gets messy, because you have to encode the number into the string. The way to do this in C++ is to use a data type called 'ostringstream'. (Warning: I have not tested this, and it's been a while since I've used stringstreams.)

Code:
#include <string>
#include <sstream>

string isPerfect(int number)
{
int sum=0, result=0;
for(int counter=1; counter<number; counter++)
{
if(number%counter==0)
sum+=counter;
}

ostringstream mystringstream;  // write to mystringstream just like you would to cout

if(number==sum && number!=0)// prevent zero from being a perfect number
mystringstream <<number<<" is a perfect number!"<<endl;
else
mystringstream <<number<<"is not a perfect number."<<endl;
return mystringstream.str();  // extract the string from the stringstream and return it
}

Code:
int main()
{
int n;
string result;

cout<<"Enter a number: ";
cin>>n;
result=isPerfect(n);
cout<<result;

return 0;
}

• Valour549
I tried it and turns out I can't. I think the compiler is saying that I can't put cout after return

That's because you've defined your function to return an 'int,' whereas 'cout' is an object of type 'ostream'.

• Valour549
Ah alright, I think I'll have to settle for what I've got so far for now xD

Thank you so much for all your help; much appreciated.

You "liked" jtbell's post but then did something different! Your code would be clearer (which means more likely to be right first time, easier to debug and easier to maintain) something like this:
I played around with it, do you something like this? I think this is error-free lol though it'd be nice if you could concur.
Code:
int main()
...
// do not declare result, you don't need it
...
if (isPerfect(n))
...
/** (Heading comment omitted for brevity and because there is no one correct way) */
bool isPerfect(int candidate)
{
int sum_of_factors = 0;

// prevent zero from being a perfect number
if (candidate == 0)
{
return false;
}

// iterate over potential factors, adding to sum if counter is a factor
for (int trial_factor = 1; trial_factor < candidate; trial_factor++)
{
if (candidate % trial_factor == 0)
{
sum_of_factors += trial_factor;
}
}

// return result of test for a perfect number
return (candidate == sum_of_factors);
}
Separation of concerns is an important concept in programming (particularly OOP, but it also applies to procedural programming). You should never mix code that performs calculations in the same function as code associated with input or output.

Edit: better variable names

Last edited: