Thread: Why does parenthesis around a fraction (5/9) break my program? Beginner!

  1. #1
    Registered User
    Join Date
    Sep 2015
    Posts
    3

    Why does parenthesis around a fraction (5/9) break my program? Beginner!

    Hey, I just started trying to learn programming so please be gentle. I tried to think of some easy practice programs to make and conversion came to mind so I tried to make a little temperature conversion program. In the conversion equation there's a fraction 5/9 and I put parenthesis around it because I didn't think it would change the result and I thought it made it easier to read. The parenthesis make the result always come out to be zero. When I remove the parenthesis the result is correct. Why is this?

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main()
    {
        float fDegrees;
        float cDegrees;
        char fDegreesString[20];
        char cDegreesString[20];
        char desiredConversion;
    
    
        printf("Would you like to convert from Celcius or Farenheit? \nEnter C or F.\n");
        desiredConversion = getchar();
        getchar();
    
    
        if (desiredConversion == 'C' || desiredConversion == 'c')
        {
            printf("What is the temperature in C?\n");
            gets(cDegreesString);
            cDegrees = atoi(cDegreesString);
            fDegrees = (cDegrees * (9 / 5)) + 32;
            printf("The temperature in F is %.1f degrees.\n", fDegrees);
        }
    
    
        else if (desiredConversion == 'F' || desiredConversion == 'f')
        {
            printf("What is the temperature in F?\n");
            gets(fDegreesString);
            fDegrees = atoi(fDegreesString);
            cDegrees = (fDegrees-32)*(5/9);
            printf("The temperature in C is %.1f degrees.\n", cDegrees);
        }
    
    
        else
            printf("You must type C or F.\n");
    
    
        return 0;
    }
    Any other suggestions you have to make this better would be great. GCC shows a warning that I shouldn't use gets. Any suggestion on what I should use instead?

    Thanks!

  2. #2
    Guest
    Guest
    I reckon (5/9) gets truncated into an integer, whereas without the parentheses the compiler sees the context of the whole statement and doesn't do so.

    Code:
    float i = 5 / 9; // 0.555
    float j = (5 / 9); // (int / int) == int(0.555) == 0
    Multiplying by that 0 will thus always give you 0.

    By making one of the operands a floating-point literal, you can correct this:
    Code:
    float k = (5.0 / 9);
    Last edited by Guest; 09-05-2015 at 05:18 PM.

  3. #3
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,111
    (5/9) results in an integer value, NOT a floating point value. You want ((double)5/9). Cast 5 to a double, then 9 will also be promoted, resulting in a double result.

    gets() has been depreciated in C99, and eliminated in C11. You should NEVER use gets(), but use fgets() instead.

  4. #4
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    To elaborate, it's because of order of operations, and the fact that, when an expression has mixed integers and floating-point operands, the integers are promoted into floats to do the math.

    Code:
    (fDegrees-32)*5/9;
    In this case, fDegrees is a float, so 32 is converted to 32.0 and the result is a float. Next, the float is multiplied by 5, so 5 is promoted to a float, too. Finally, 9 is promoted to a float as floating-point division is done.

    Code:
    (fDegrees-32)*(5/9);
    Here fDegrees-32 is still a float, but the parentheses mean that 5/9 is evaluated before the multiplication. Since 5 and 9 are integer literals, it does integer division, and 5/9 = 0 in integer division.

    The simplest way to fix this is to use floating-point literals such as (5.0f/9.0f)

    You also likely want atof() not atoi() as you're trying to parse floating-point values, not integers.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  5. #5
    Registered User
    Join Date
    Sep 2015
    Posts
    3
    This is great information! I'm familiar with the concept of int/float/double/decimal but I hadn't thought of needing to specify the granularity of literal numbers. Typecasting is a concept I'm aware of but I didn't realize that it was something I could/should do with literal numbers. I only thought of it pertaining to variables.

    I played around with different ways of diving numbers to see what different results I get. It appears that all numbers are assumed to be integers unless you specifically state them to be something else. I'm sure that's probably common knowledge but I had't learned that yet.

    Code:
    #include <stdio.h>
    
    
    int main()
    {
        float a = 7;
        float b = 11;
        float c = 0;
    
    
        c = 7 / 11;// = 0
        c = a / b;// = 0.636364
        c = (float) 7 / (float) 11;// = 0.636364
        c = 7.0f / 11.0f;// = 0.636364
    
    
        return 0;
    }

  6. #6
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,111
    It appears that all numbers are assumed to be integers unless you specifically state them to be something else.
    5 is an integer, since no decimal point appears in the constant.
    5.0 or 5. is a double since the decimal point is part of the constant.

    There is no "assumption" about it.

    You might want to review the chapters on all forms of data.

  7. #7
    Registered User
    Join Date
    Mar 2014
    Location
    Corning, New York, USA
    Posts
    96
    Quote Originally Posted by Cat View Post
    To elaborate, it's because of order of operations, and the fact that, when an expression has mixed integers and floating-point operands, the integers are promoted into floats to do the math.

    Code:
    (fDegrees-32)*5/9;
    In this case, fDegrees is a float, so 32 is converted to 32.0 and the result is a float. Next, the float is multiplied by 5, so 5 is promoted to a float, too. Finally, 9 is promoted to a float as floating-point division is done.

    Code:
    (fDegrees-32)*(5/9);
    Here fDegrees-32 is still a float, but the parentheses mean that 5/9 is evaluated before the multiplication. Since 5 and 9 are integer literals, it does integer division, and 5/9 = 0 in integer division.

    The simplest way to fix this is to use floating-point literals such as (5.0f/9.0f)

    You also likely want atof() not atoi() as you're trying to parse floating-point values, not integers.
    I was going to point out he was using the wrong formula and that he should also be using atof but you beat me to it. For the OP though, here are some other formulas you can use as well.

    C = (F - 32) * 5 / 9 (this is the one you're trying to use)
    C = (F - 32) / (9 / 5) (notice how this one requires the parenthesis around the 9/5. The division of 9/5 must get divided into whatever F-32 is. We don't want F-32 getting divided by just 9).
    C = (F - 32) / 1.8

  8. #8
    Registered User
    Join Date
    Sep 2015
    Posts
    3
    Thanks for all of the information, this is great!

    To sum it all up:
    -I should be using atof instead of atoi. This totally makes sense. I'm dealing with floats throughout the whole thing, it's silly not to use atof.
    -I should use fgets instead of gets. fgets grabs the \n from hitting enter in the console. I probably have to do a little shenanigans to get rid of that if I don't want to use the \n.
    -I should use doubles or floats by putting 5.0 instead of 5 or typecasting the integers as floats. I definitely will look more into basic forms of data

    The only thing I don't get is how is the formula I'm using wrong? I wrote this up and I get the same answer using all four versions of the formula; 37.777779

    Code:
    #include <stdio.h>
    
    
    int main()
    {
        float c1;
        float c2;
        float c3;
        float c4;
    
    
        float f = 100;
    
    
        c1 = (f - 32.0) * 5.0 / 9.0;
        printf("%f\n", c1);
        c2 = (f - 32.0) * (5.0 / 9.0);
        printf("%f\n", c2);
        c3 = (f - 32.0) / (9.0 / 5.0);
        printf("%f\n", c3);
        c4 = (f - 32.0) / 1.8;
        printf("%f\n", c4);
    
    
        return 0;
    }

  9. #9
    Registered User
    Join Date
    Mar 2014
    Location
    Corning, New York, USA
    Posts
    96
    Quote Originally Posted by sandwichface View Post
    Thanks for all of the information, this is great!

    To sum it all up:
    -I should be using atof instead of atoi. This totally makes sense. I'm dealing with floats throughout the whole thing, it's silly not to use atof.
    -I should use fgets instead of gets. fgets grabs the \n from hitting enter in the console. I probably have to do a little shenanigans to get rid of that if I don't want to use the \n.
    -I should use doubles or floats by putting 5.0 instead of 5 or typecasting the integers as floats. I definitely will look more into basic forms of data

    The only thing I don't get is how is the formula I'm using wrong? I wrote this up and I get the same answer using all four versions of the formula; 37.777779

    Code:
    #include <stdio.h>
    
    
    int main()
    {
        float c1;
        float c2;
        float c3;
        float c4;
    
    
        float f = 100;
    
    
        c1 = (f - 32.0) * 5.0 / 9.0;
        printf("%f\n", c1);
        c2 = (f - 32.0) * (5.0 / 9.0);
        printf("%f\n", c2);
        c3 = (f - 32.0) / (9.0 / 5.0);
        printf("%f\n", c3);
        c4 = (f - 32.0) / 1.8;
        printf("%f\n", c4);
    
    
        return 0;
    }
    I might of worded that a bit better. When I said you was using the wrong formula, what I meant was you're using:
    Code:
     cDegrees = (fDegrees-32)*(5/9);
    As Cat has previously noted, one of your problems lie in your parenthesis at the end there.
    Code:
     cDegrees = (fDegrees-32)*(5/9);
    and
    Code:
     cDegrees = (fDegrees-32)*5/9; 
    are two different formulas. On my system, if you remove the parenthesis at the end there like:
    Code:
     cDegrees = (fDegrees-32)*5/9;
    it works fine.

  10. #10
    Registered User
    Join Date
    Mar 2014
    Location
    Corning, New York, USA
    Posts
    96
    Oh, the reason the second example works is because you're doing the type cast to float by putting a .0 after the decimal. You're no longer dividing an integer by an integer. You're now dividing a float by a float. Previously, by removing the parenthesis, you get this:
    cDegress = (fDegrees-32) * 5 / 9;

    We do parenthesis first
    float = (float - int) * int / int;

    (float - int) got promoted (converted) to a float and now we're multiplying it the int data type
    float = (float * int) / int;

    (float * int) got promoted to a float and now we're doing the division by an int data type
    float = float / int;

    int got promoted to a float when we divided so the answer is now a float data type
    float = float;

    The way the C compiler handles operations like this is because of the size of the different variables. Int is smaller than float. So when you do something like float - int, int gets converted into float because the int datatype might not be able to hold the variable length or you would loose the precision (the stuff after the decimal point). Anything in parenthesis gets handled first. With your first way, it would of looked something like this:

    cDegress = (fDegrees-32) * (5 / 9);

    First the compiler processes (float - int) and then it processes (int / int)
    float = (float - int) * (int / int);

    Because with the int data type, we must have whole numbers, so (int / int) becomes 0
    float = (float) * 0

    anything multiplied by 0 is 0.
    float = 0


    Also, C = (F - 32) / (9 / 5) is the formula, but in C, you would need for this to work successfully, C = (F - 32) / (9.0f / 5) or C = (F - 32) / (9 / 5.0f) or C = (F - 32) / (9.0f / 5.0f)

    I hope this clears things up a bit and I'm sorry for the confusion.
    Last edited by Spork Schivago; 09-05-2015 at 10:14 PM.

  11. #11
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by sandwichface View Post
    -I should use fgets instead of gets. fgets grabs the \n from hitting enter in the console. I probably have to do a little shenanigans to get rid of that if I don't want to use the \n.
    I usually define a function called chomp that gets rid of a trailing new line if it exists. Here is how you define it:

    Code:
    #include <string.h>
    
    void chomp(char *buf)
    {
        char *p = strrchr(buf, '\n');
        if (p) *p = '\0';
    }
    Use it like this:
    Code:
    #include <stdio.h>
    
    #define MAXCOUNT 1000
    char linebuf[MAXCOUNT];
    
    int main(void)
    {
        while (fgets(linebuf, MAXCOUNT, stdin) != NULL) {
            chomp(linebuf);
            printf("You said \"%s\".\n", linebuf);
        }
        return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Program to convert from decimal to fraction
    By acho.arnold in forum C Programming
    Replies: 16
    Last Post: 07-12-2013, 04:10 PM
  2. Fraction Program...
    By hottiefee in forum C++ Programming
    Replies: 15
    Last Post: 01-18-2011, 09:04 PM
  3. Replies: 1
    Last Post: 05-29-2010, 05:24 AM
  4. Replies: 18
    Last Post: 03-26-2008, 09:01 AM
  5. Problem with reducing fraction program
    By Turtal in forum C Programming
    Replies: 12
    Last Post: 12-07-2007, 02:25 AM