Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Writing a function that determines if a number is perfect

  1. Jan 23, 2016 #1
    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 (C):
    #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";
    }
     
  2. jcsd
  3. Jan 23, 2016 #2

    Samy_A

    User Avatar
    Science Advisor
    Homework Helper

    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: Jan 23, 2016
  4. Jan 23, 2016 #3

    jtbell

    User Avatar

    Staff: Mentor

    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:

    Code (C):

        if (condition)
            return 1;
        else
            return 0;
     
    Then in the calling function, you can have a statement like this:

    Code (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.

    Code (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 (Text):

    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:

    Code (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
     
  5. Jan 23, 2016 #4
    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 (C):
    #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.
     
  6. Jan 23, 2016 #5
    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 (C):
    ...
    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 (C):
    int main()
    {
        int n, result;
       
        cout<<"Enter a number: ";
        cin>>n;
        result=isPerfect(n);
        cout<<result;
       
        return 0;  
    }
     
  7. Jan 23, 2016 #6

    Samy_A

    User Avatar
    Science Advisor
    Homework Helper

    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.
     
  8. Jan 23, 2016 #7
    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;
     
  9. Jan 23, 2016 #8

    jtbell

    User Avatar

    Staff: Mentor

    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 (C):


    #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 (C):
    int main()
    {
        int n;
        string result;
     
        cout<<"Enter a number: ";
        cin>>n;
        result=isPerfect(n);
        cout<<result;
     
        return 0;
    }
     
  10. Jan 23, 2016 #9

    jtbell

    User Avatar

    Staff: Mentor

    That's because you've defined your function to return an 'int,' whereas 'cout' is an object of type 'ostream'.
     
  11. Jan 23, 2016 #10
    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.
     
  12. Jan 25, 2016 #11
    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:
    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: Jan 25, 2016
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Writing a function that determines if a number is perfect
Loading...