Writing a function that determines if a number is perfect

  • Thread starter Thread starter Valour549
  • Start date Start date
  • Tags Tags
    Function Writing
Join the discussion
Ask a follow-up here, or get your own question answered by working scientists, mathematicians and engineers — people, not an autocomplete.
Real named experts · corrections over time · the nuance an AI answer skips
10 replies · 4K views
Valour549
Messages
57
Reaction score
4
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;
  count<<"Enter a number: ";
  cin>>n;
  int re= perfect(n);
  if(re==n)
    count<<"\n\nYes!\n  It Is A perfect number.\n\n";
  else
    count<<"\n\nNo! \n  It Is Not A Perfect Number.\n\n";
}
 
Physics news on Phys.org
Valour549 said:
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;
  count<<"Enter a number: ";
  cin>>n;
  int re= perfect(n);
  if(re==n)
    count<<"\n\nYes!\n  It Is A perfect number.\n\n";
  else
    count<<"\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:
  • Like
Likes   Reactions: 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
 
  • Like
Likes   Reactions: 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;
   
    count<<"Enter a number: ";
    cin>>n;
    result=isPerfect(n);
   
    if(result==1)
        count<<n<<" is a perfect number!"<<endl;
    else
        count<<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 count<<number<<" is a perfect number!"<<endl;
  else
        return count<<number<<"is not a perfect number."<<endl;
}

and then I'll change the function main part to
Code:
int main()
{
    int n, result;
   
    count<<"Enter a number: ";
    cin>>n;
    result=isPerfect(n);
    count<<result;
   
    return 0;   
}
 
Valour549 said:
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 count<<number<<" is a perfect number!"<<endl;
  else
        return count<<number<<"is not a perfect number."<<endl;
}

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

    count<<"Enter a number: ";
    cin>>n;
    result=isPerfect(n);
    count<<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.
 
  • Like
Likes   Reactions: jtbell and Valour549
I tried it and turns out I can't. I think the compiler is saying that I can't put count after return

if(number==sum && number!=0)// prevent zero from being a perfect number
return count<<number<<" is a perfect number!"<<endl;
else
return count<<number<<"is not a perfect number."<<endl;
 
Valour549 said:
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 count

   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;
 
    count<<"Enter a number: ";
    cin>>n;
    result=isPerfect(n);
    count<<result;
 
    return 0; 
}
 
  • Like
Likes   Reactions: Valour549
Valour549 said:
I tried it and turns out I can't. I think the compiler is saying that I can't put count after return

That's because you've defined your function to return an 'int,' whereas 'count' is an object of type 'ostream'.
 
  • Like
Likes   Reactions: 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:
Valour549 said:
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: