21

Teaching myself C and finding that when I do an equation for a temp conversion it won't work unless I change the fraction to a decimal. ie,

tempC=(.555*(tempF-32)) will work but tempC=((5/9)*(tempF-32)) won't work.

Why?
According to the book "C Primer Plus" it should work as I'm using floats for both tempC and tempF.

1

5 Answers 5

19

It looks like you have integer division in the second case:

tempC=((5/9)*(tempF-32)) 

The 5 / 9 will get truncated to zero.

To fix that, you need to make one of them a floating-point type:

tempC=((5./9.)*(tempF-32)) 
Sign up to request clarification or add additional context in comments.

2 Comments

To be picky, the 5.0 / 9.0 syntax gives two doubles. If tempF and tempC are float then the expression should be 5.0f / 9.0f. Otherwise the division might be performed on double precision, which is then rounded to float precision when its result is stored. Hopefully the compiler is smart enough to optimize that minor little issue away, but I wouldn't count on it.
@Lundin it can't optimize that out; if double precision is used, it must be done that way, or an unexpected answer may arise.
3

When you do 5/9, 5 and 9 are both integers and integer division happens. The result of integer division is an integer and it is the quotient of the two operands. So, the quotient in case of 5/9 is 0 and since you multiply by 0, tempC comes out to be 0. In order to not have integer division, atleast one of the two operands must be float.

E.g. if you use 5.0/9 or 5/9.0 or 5.0/9.0, it will work as expected.

Comments

3

5/9 is an integer division not a floating point division. That's why you are getting wrong result.

Make 5 or 9 floating point variable and you will get correct answer.

Like 5.0/9 OR 5/9.0

1 Comment

Agreed. It is always good practice to also add the f denoting floating point to constants. Likewise the u for unsigned integer constants
1

5/9 is an integer expression, as such it gets truncated to 0. your compiler should warn you about this, else you should look into enabling warnings.

5 Comments

I really don't see why it should warn. There is no way for the compiler to tell what value someone wants their integer constants to be.
@Lundin: thats why it would be a (pedantic) warning. if a constant integer expression yields zero, it should either be zero or there was an oversight.
Not necessarily, there may be many cases where you would want a constant expression with the result 0. For example result = SOME_CONSTANT & MASK; may very well result in zero. Lets say you have similar bit masking operations all over the code, with different masks. You wouldn't want hundreds of warnings then, why should you be punished just because you write generic, consistent code without any magic numbers in it?
@Lundin: but thats not a division, I'm only referring to division here.
SOME_CONSTANT / SOMETHING isn't really any different from my example. Lets say that the constant states the number of outputs this build of the program is using, and the division is used to calculate the nature of the output.
0

If you put 5/9 in parenthesis, this will be calculated first, and since those are two integers, it will be done by integer division and the result will be 0, before the rest of the expression is evaluated.

You can rearrange your expression so that the conversion to float occurs first:

tempC=((5/9)*(tempF-32));tempC=(5*(tempF-32))/9;

or of course, as the others say, use floating point constants.

4 Comments

Even if they were not in parenthesis, they could still be evaluated as integers. The order of evaluation of this expression is unspecified behavior in C, the compiler may chose to evaluate left-to-right or right-to-left, and you cannot know which order of evaluation that applies.
Not entirely true. The parenthesis do have an effect! If you make sure that the first calculation that is performed results in a float, the rest of the expression will not revert back to integer. I've augmented my answer to show what I mean.
The rewritten example is not equivalent to removing the parenthesis, you have intentionally changed the order of evaluation. tempC= 5/9 * (tempF-32); is an example with the parenthesis removed. This example may or may not give the desired result, depending on whether the compiler evaluates left-to-right or right-to-left - it relies on unspecified behavior.
I'm not sure what you're trying to prove here. My example rewrote the OP's expression so that it works. Which is what they asked for.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.