Page 2 of 2 FirstFirst
1
2
  1. #21
    The Patient
    10+ Year Old Account
    Join Date
    Mar 2010
    Location
    St. Louis, MO
    Posts
    221
    It's been a really long time but... edit, nvm. You're already on the right track.

    Just take a look at your variables used, and simplify it. There's no need to create a new variable when you can reuse one.
    Last edited by Ailthas; 2011-11-08 at 02:26 AM.

  2. #22
    I'm setting d's value in the main and in the function. a, b, and c's values are set in the main after the user inputs them...hmm. Do I have to declare d AFTER the last scanf?

  3. #23
    Code:
    #include <stdio.h>
    #include <math.h>
    
    double posQuadraticEquation(int a, int b, int c);
    
    int main()
    {
             int a;
            int b;
            int c;
    
    
            printf("Please enter an integer for 'a'.\n");
            scanf("%d", &a);
    
            printf("Please enter an integer for 'b'.\n");
            scanf("%d", &b);
    
            printf("Please enter an integer for 'c'.\n");
            scanf("%d", &c);
    
           double answer = posQuadraticEquation(a, b, c);
           if{answer != null)
                 printf("With the values you entered, the positive portion of the Quadratic equation comes out to %lf\n", answer);
            }
    }
    
    double posQuadraticEquation(int a, int b, int c)
    { 
            double d = (b*b - 4*a*c);
            double answer;
    
            if(d<0)
            {
             printf("The integers you have entered result in an imaginary number. Please try again.\n");
             return null;
            }
            else
            {
            answer = -b/(2*a) + (sqrt(d) / (2*a));
    
            return answer;
            }
    }
    Last edited by tierJah; 2011-11-08 at 02:32 AM. Reason: forgot to declare vars in main v.v

  4. #24
    Quote Originally Posted by kcidsekildrazzilb View Post
    I'm setting d's value in the main and in the function. a, b, and c's values are set in the main after the user inputs them...hmm. Do I have to declare d AFTER the last scanf?
    You can declare it before that. You can't give it the value of a+b+c or whatever before that. If you initialize your values ahead of time, you'll see why. What the compiler currently sees your code as is
    int a = UNDEFINED;
    int b = UNDEFINED;
    int c = UNDEFINED;
    double d = some math with undefined numbers.

    In practice most compilers give things default values. So what you do is most likely going to be interpretted as
    int a = 0;
    int b = 0;
    int c = 0;
    double d = that stuff;
    //get values

    But either way you don't change d after that. You only change d if you assign it again. Do you know what to do now?

  5. #25
    Deleted
    Quote Originally Posted by Cactrot View Post
    When I compile it still returns something. NAN I believe. Don't suppose anyone has a reference for what the standard calls for if you have a function that has a return value and doesn't return? (which once again, you shouldn't do, even if the standard allows for it.)
    This is undefined behaviour. The NaN is coming off the stack where the return value should be.

  6. #26
    Quote Originally Posted by tierJah View Post
    code
    Sorry, but that code doesn't compile or work for C. Aside from the redeclaration of a,b,and c in the function, you return null which isn't allowed in a function with a double return type.

    ---------- Post added 2011-11-07 at 06:32 PM ----------

    Quote Originally Posted by thekrik View Post
    This is undefined behaviour. The NaN is coming off the stack where the return value should be.
    Mm, I figured it'd be something like that. It was one of those things where I went "I know this is bad. I just don't know if it's undefined behavior bad, or just bad practice/habit bad."

  7. #27
    OKAY WAIT. I think I understand.


    if(d = (b*b-4*a*c)<0)
    {printf("The integers you have entered result in an imaginary number. Please try again.\n");}

    And then the else will call the function and do all that jazz? Let me try it real quick.

  8. #28
    Quote Originally Posted by kcidsekildrazzilb View Post
    OKAY WAIT. I think I understand.


    if(d = (b*b-4*a*c)<0)
    {printf("The integers you have entered result in an imaginary number. Please try again.\n");}

    And then the else will call the function and do all that jazz? Let me try it real quick.
    Almost. Don't put the assgnment in the if statement. It should be its own statement prior to the if check.

  9. #29
    true, its been awhile since I did any work in C. I was thinking of the double as an object, lol.

  10. #30
    #include <stdio.h>
    #include <math.h>


    double posQuadraticEquation(int a, int b, int c);


    int main()
    {
    int a;
    int b;
    int c;




    printf("Please enter an integer for 'a'.\n");
    scanf("%d", &a);


    printf("Please enter an integer for 'b'.\n");
    scanf("%d", &b);


    printf("Please enter an integer for 'c'.\n");
    scanf("%d", &c);


    double answer = posQuadraticEquation(a, b, c);

    if (answer < 0)
    {
    printf("The integers you have entered result in an imaginary number. Please try again.\n");
    }
    else
    {
    printf("With the values you entered, the positive portion of the Quadratic equation comes out to %lf\n", answer);
    }


    }


    double posQuadraticEquation(int a, int b, int c)
    {
    double answer;
    double d = (b*b - 4*a*c);
    if (d<0)
    {
    return -1;
    }
    else
    {
    answer = -b/(2*a) + (sqrt(d) / (2*a));
    return answer;
    }

    }

  11. #31
    It works!! Here's my code now:

    Code:
    #include <stdio.h>
    #include <math.h>
    
    double posQuadraticEquation(int a, int b, int c);
    
    int main()
    {
            int a;
            int b;
            int c;
            double d;
    
            printf("Please enter an integer for 'a'.\n");
            scanf("%d", &a);
    
            printf("Please enter an integer for 'b'.\n");
            scanf("%d", &b);
    
            printf("Please enter an integer for 'c'.\n");
            scanf("%d", &c);
    
            if(d = (b*b-4*a*c)<0)
            {printf("The integers you have entered result in an imaginary number. Please try again.\n");}
    
    
            else
            {
            double answer = posQuadraticEquation(a, b, c);
    
            printf("With the values you entered, the positive portion of the Quadratic equation comes out to %lf\n", answer);
            }
    }
    
    double posQuadraticEquation(int a, int b, int c)
    {
            double answer;
            double d;
    
            answer = -b/(2*a) + (sqrt(d) / (2*a));
    
            return answer;
    }
    Is there a way to clean this up? Also, I'm not sure what you mean by the assignment should be it's own statement? It didn't work if I put it outside of the IF statement.

  12. #32
    Quote Originally Posted by kcidsekildrazzilb View Post
    It works!! Here's my code now:

    Code:
    #include <stdio.h>
    #include <math.h>
    
    double posQuadraticEquation(int a, int b, int c);
    
    int main()
    {
            int a;
            int b;
            int c;
            double d;
    
            printf("Please enter an integer for 'a'.\n");
            scanf("%d", &a);
    
            printf("Please enter an integer for 'b'.\n");
            scanf("%d", &b);
    
            printf("Please enter an integer for 'c'.\n");
            scanf("%d", &c);
    
            if(d = (b*b-4*a*c)<0)
            {printf("The integers you have entered result in an imaginary number. Please try again.\n");}
    
    
            else
            {
            double answer = posQuadraticEquation(a, b, c);
    
            printf("With the values you entered, the positive portion of the Quadratic equation comes out to %lf\n", answer);
            }
    }
    
    double posQuadraticEquation(int a, int b, int c)
    {
            double answer;
            double d;
    
            answer = -b/(2*a) + (sqrt(d) / (2*a));
    
            return answer;
    }
    Is there a way to clean this up? Also, I'm not sure what you mean by the assignment should be it's own statement? It didn't work if I put it outside of the IF statement.
    d = b*b-4*a*c; // this is an assignment. it gives d the value of the stuff that comes after it.
    if( d < 0) // this is the conditional. This should evaluate to true or false. It's asking "is d less than zero".
    What you have now is asking "is the assignment of d equals this stuff less than zero". Which can work, but it's really really bad practice.

    Remember that for c/c++ when you say d = something, what you're doing is saying "evaluate this calculation, and give d the resulting number". If you change a,b,c after that it does not affect d, because d doesn't equal some function of abc, it equals some number (i.e. 5) which just so happens to have been calculated from those.

    Oh, just noticed another bug! You're using d in your function, but it's not being passed in. That means when you use it in there you're using an undefined value (probably 0.0)!

    It's good practice to ALWAYS give your variables a default value.
    Instead of
    double d; // which is double d = undefined, which generally is d = 0.0, but not guaranteed.
    do
    double d = 0.0;
    This helps you keep track of if you're using the value you really want to use!
    Last edited by Cactrot; 2011-11-08 at 02:50 AM.

  13. #33
    Hmm. So where would I put the d = b*b-4*a*c then exactly? I tried a couple different spots but get a compiling error.

  14. #34
    I think you're close enough now. This is how I'd clean up your code.

    Code:
    #include <stdio.h>
    #include <math.h>
    
    double posQuadraticEquation(int a, int b, int c);
    
    int main()
    {
            int a = 0;
            int b = 0;
            int c = 0;
            double d = 0.0;
    
            printf("Please enter an integer for 'a'.\n");
            scanf("%d", &a);
    
            printf("Please enter an integer for 'b'.\n");
            scanf("%d", &b);
    
            printf("Please enter an integer for 'c'.\n");
            scanf("%d", &c);
            
            d = (b*b-4*a*c);
            if(d < 0)
            {
             printf("The integers you have entered result in an imaginary number. Please try again.\n");
            }
            else
            {
            printf("With the values you entered, the positive portion of the Quadratic equation comes out to %lf\n", posQuadraticEquation(a, b, c));
            }
    }
    
    double posQuadraticEquation(int a, int b, int c)
    {
            double answer = 0;
            double d = (b*b-4*a*c);
    
            answer = -b/(2*a) + (sqrt(d) / (2*a));
            return answer;
    }
    You'll note I put the assignment on its own line, then checked d. Since you're actually doing 2 things here, it's generally better to separate them out. You especially don't want to mix assignment and checking conditions. First do the assignment (d=something). Then do the check if it's within bounds. As you progress, you'll end up wanting to combine some things (but still not assignment and conditions, generally,) but as you're learning I find that breaking it down to each individual step makes it easier.

    Ironically, in the condensed code I moved the function call to into the printf statement.

    So here are a few other ways to do it. I've snipped out some code to make it smaller.
    Code:
    double* posQuadraticEquation(int a, int b, int c);
    int main()
    {
            int a,b,c;
            getValues(a,b,c);
    
            double* answer = posQuadraticEquation(a, b, c);
      
    if(answer) //same as if(answer != NULL)
            printf("With the values you entered, the positive portion of the Quadratic equation comes out to %lf\n", answer);
    }
    
    double posQuadraticEquation(int a, int b, int c)
    {
    double* answer;
    double d = (b*b - 4*a*c);
     
     
    if(d<0)
    { printf("The integers you have entered result in an imaginary number. Please try again.\n");
      return NULL;
    }
    else
    {
            answer = new double;
            *answer = -b/(2*a) + (sqrt(d) / (2*a)); 
            return answer;
    }
    }
    That one requires you know what pointers are. (They are amazing, and death to crappy other languages that hide memory management from you.)

    You can also change your code so that in the function when you declare answer use
    Code:
    double answer=0.0/0.0; //makes it NAN
    and then before your print
    Code:
    if(answer!=answer)
    printf("your print statement you wanted out");
    In the standard answer!=answer should be true if and only if answer is NAN. Unfortunately, this doesn't actually work well since many compilers don't follow the rules (gcc/g++ for example, is non compliant :-( )

    Checking d's value before going into the equation is probably the simplest most intro-CS style way to do it. Unfortunately, it seems like unless you know about pointers or passing a bool by reference to get if the return value is valid, your teacher is actually guiding you towards some bad practices with this example. le sigh. Sometimes I wonder if teachers actually do their test problems before giving them out.

    One note for your implementation is that you calculated d twice. You could, instead, just pass it in as well. That way you only calculate it once. Obviously not going to ruin your runtime of a program this small, but those optimizations become more important later.

    Another fun tidbit about CS: half the things you will learn to optimize as you progress in CS will end up being pointless to optimize, since the compiler will do it for you (and sometimes the optimization you do is actually counter-productive! Read this c++ enthusiasts that were taught to pass by reference for speed.)

    ---------- Post added 2011-11-07 at 07:06 PM ----------

    So, lets clear up some terms. First is declare/declaration. That's when you give a variable a name.
    int a;
    double b;
    Those are declarations.

    Then there's an assignment
    a = 3;
    b = 1.1;
    For basic types (int, double, float, char, etc) you need to have an assignment before you use them. You CAN use them before that, but the behavior is undefined. You'd hate to lose points on an assignment because your code works for you, but not for your professor because he compiled with something else, wouldn't you?

    There's also initialization
    int c = 0;
    double d = 3.5;
    This is basically a declaration and an assignment done at the same time. There's some reasons it's slightly different than declaring and then assigning, but nothing you need to worry about for a long time.
    Remember that a variable needs to be declared before it can be used, and should be assigned before it's used on the right side of any equation. Until a variable is assigned, it could be anything!

    I hope my long winded explanations hasn't caused too much confusion. Since we've arrived at the answer, please feel free to ask if you have any questions about why I did it a certain way, or anything else!
    Last edited by Cactrot; 2011-11-08 at 02:56 AM. Reason: Ack, missed a semi-colon!

  15. #35
    Was just checking over what's next on the syllabus. Pointers are next But everyone, thank you so much for the help, especially cactrot. I understand this a lottttttttttttttt better now! Coding is so stressful, but I gotta admit after seeing a program run correctly makes me happy.

    And no worries about the long explanation, it helped out a lot. I'm gonna have to save this thread for future reference haha.
    Last edited by Njtobknets; 2011-11-08 at 03:20 AM.

  16. #36
    Quote Originally Posted by kcidsekildrazzilb View Post
    Was just checking over what's next on the syllabus. Pointers are next But everyone, thank you so much for the help, especially cactrot. I understand this a lottttttttttttttt better now! Coding is so stressful, but I gotta admit after seeing a program run correctly makes me happy.

    And no worries about the long explanation, it helped out a lot. I'm gonna have to save this thread for future reference haha.
    Glad to help. I always try to give a good explanation of the why. Lack of understanding now will only make it harder later. Feel free to shoot me a PM and I can give you my AIM name or something to contact me by if you need help in the future. A lot of people have a looot of trouble with pointers. Though to some it comes naturally. Don't be afraid to ask people for help, but (especially with pointers) be wary of advice without explanation. It's not uncommon to get incorrect advice with those!

  17. #37
    First up, if you do maths with integers, you will get an integer result. This is massively important. Your current function will do the following:

    1) promote d to a double, then get it's square root as a double

    2) multiply 2 by a, resulting in an integer.

    3) divide the answer from 1) by 2). Since 2) is an int, the result will be an int. Any floating point information will be lost at that point.

    4) similarly it will divide -b by 2 and then discard any floating point information.

    5) the two truncated numbers will be added together for a result that will be incorrect most of the time.

    to fix this you need to make sure every number in the calculation is a double. Either change the function to be

    double posQuadraticEquation(double a, double b, double c)

    OR

    cast every int to a double in the formula

    answer = -(double)b/(2*(double)a) + (sqrt(d) / (2*(double)a));

    I would suggest you do the former, because it results in an overall more useful function.

    Next some style issues. I'd recommend you don't have posQuadraticEquation print out anything. If you ever want to use the function again, then having it's error output as a print statement basically makes it useless. As an example, with your current code, how would you go about having the program loop until the user gives valid input?

    So other's advice to move that pre-check code outside the function is good - personally I might change it so that instead of printing, you explicitly return NAN from the function if it will fail and then check for NAN in the main program. A NAN always fails comparisons, so

    if(answer != answer)
    {
    printf( "no, bad monkey! try again" );
    return 1;
    }

    printf("%f", answer);
    return 0;

    will detect them.

    P.s. depending on your platform, you may have an easy #include that lets you use NAN (in math.h on linux and xmath.h on windows). If you dont, just use

    double function NAN()
    {
    unsigned long long raw = 0x7ff0000000000000;
    double d = *( double* )&raw;
    return d;
    }

    to get a NAN.

  18. #38
    First up, if you do maths with integers, you will get an integer result. This is massively important. Your current function will do the following:

    1) promote d to a double, then get it's square root as a double

    2) multiply 2 by a, resulting in an integer.

    3) divide the answer from 1) by 2). Since 2) is an int, the result will be an int. Any floating point information will be lost at that point.

    4) similarly it will divide -b by 2 and then discard any floating point information.

    5) the two truncated numbers will be added together for a result that will be incorrect most of the time.

    to fix this you need to make sure every number in the calculation is a double. Either change the function to be

    double posQuadraticEquation(double a, double b, double c)

    OR

    cast every int to a double in the formula

    answer = -(double)b/(2*(double)a) + (sqrt(d) / (2*(double)a));

    I would suggest you do the former, because it results in an overall more useful function.

    Next some style issues. I'd recommend you don't have posQuadraticEquation print out anything. If you ever want to use the function again, then having it's error output as a print statement basically makes it useless. As an example, with your current code, how would you go about having the program loop until the user gives valid input?

    So other's advice to move that pre-check code outside the function is good - personally I might change it so that instead of printing, you explicitly return NAN from the function if it will fail and then check for NAN in the main program. A NAN always fails comparisons, so

    if(answer != answer)
    {
    printf( "no, bad monkey! try again" );
    return 1;
    }

    printf("%f", answer);
    return 0;

    will detect them.

    P.s. depending on your platform, you may have an easy #include that lets you use NAN (in math.h on linux and xmath.h on windows). If you dont, just use

    double function NAN()
    {
    unsigned long long raw = 0x7ff0000000000000;
    double d = *( double* )&raw;
    return d;
    }

    to get a NAN.

  19. #39
    Quote Originally Posted by Saeviomage View Post
    First up, if you do maths with integers, you will get an integer result. This is massively important. Your current function will do the following:

    1) promote d to a double, then get it's square root as a double

    2) multiply 2 by a, resulting in an integer.

    3) divide the answer from 1) by 2). Since 2) is an int, the result will be an int. Any floating point information will be lost at that point.

    4) similarly it will divide -b by 2 and then discard any floating point information.

    5) the two truncated numbers will be added together for a result that will be incorrect most of the time.

    to fix this you need to make sure every number in the calculation is a double. Either change the function to be

    double posQuadraticEquation(double a, double b, double c)

    OR

    cast every int to a double in the formula

    answer = -(double)b/(2*(double)a) + (sqrt(d) / (2*(double)a));

    I would suggest you do the former, because it results in an overall more useful function.

    Next some style issues. I'd recommend you don't have posQuadraticEquation print out anything. If you ever want to use the function again, then having it's error output as a print statement basically makes it useless. As an example, with your current code, how would you go about having the program loop until the user gives valid input?

    So other's advice to move that pre-check code outside the function is good - personally I might change it so that instead of printing, you explicitly return NAN from the function if it will fail and then check for NAN in the main program. A NAN always fails comparisons, so

    if(answer != answer)
    {
    printf( "no, bad monkey! try again" );
    return 1;
    }

    printf("%f", answer);
    return 0;

    will detect them.

    P.s. depending on your platform, you may have an easy #include that lets you use NAN (in math.h on linux and xmath.h on windows). If you dont, just use

    double function NAN()
    {
    unsigned long long raw = 0x7ff0000000000000;
    double d = *( double* )&raw;
    return d;
    }

    to get a NAN.
    Good catch on the int/double stuff. I'd point out that you don't really need to cast all of them as a double. You can just do
    answer = -(double)b/(2*a) + (sqrt(d) / (2*a));
    changing b to a double here makes the first part result in a double (double/int = double) then adds sqrt(d)/(2a) which is double/int, meaning double again. double + double = double.

    I also want to point out that the answer!=answer failing only when it's NAN doesn't work with some common compilers, like gcc. They do not follow the standard in regards to that. So it's probably not a great idea to rely on it.

    While I agree that ideally the function shouldn't print any output, having it not do so involves doing some checks that aren't exactly the basic CS stuff. The guy's class isn't even to pointers yet, checking against the NAN raw value is probably going to raise a red flag to his teacher about it. It's hard to have style before you have the basics to back it up.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •