Order of precedence and associativity

M

Meske Moday

Okay, I'm confused as to why this is not working the way I think it
should be. The order of precedence and associativity rules for C
dictate that anything within parentheses is evaluated first (left to
right), and for the purpose of my question, followed by multiplicative
operators [*/%], also from left to right.

So, given this simple program:

#include <stdio.h>

int main( void )
{
float f = 27.0f;
float c1 = ( f - 32 ) * 5 / 9;
float c2 = 5 / 9 * ( f - 32 );
printf( "%f\t%f\t%f\n", f, c1, c2 );
return 0;
}

I would expect c1 and c2 to be equal, given the order of precedence and
associativity rules. However, the output is:

27.000000 -2.777778 -0.000000

Can anyone explain to me (1) why c1 and c2 are different, and (2) how I
end up with a negative 0?

Thanks-
MM
 
N

Nick Keighley

Okay, I'm confused as to why this is not working the way I think it
should be. The order of precedence and associativity rules for C
dictate that anything within parentheses is evaluated first (left to
right), and for the purpose of my question, followed by multiplicative
operators [*/%], also from left to right.

a rather over-simplified version of the rules

So, given this simple program:

#include <stdio.h>

int main( void )
{
    float f = 27.0f;
    float c1 = ( f - 32 ) * 5 / 9;
    float c2 = 5 / 9 * ( f - 32 );

5 / 9 is 0
using integer division

    printf( "%f\t%f\t%f\n", f, c1, c2 );
    return 0;

}

I would expect c1 and c2 to be equal, given the order of precedence and
associativity rules. However, the output is:

27.000000       -2.777778       -0.000000

Can anyone explain to me (1) why c1 and c2 are different, and (2) how I
end up with a negative 0?

the negative zero confuses me. Try replacing 5 with 5.0
 
M

Meske Moday

Thank you, but those are the rules, simplified or not, straight from
the ANSI reference.

The multiplicative operators should NOT be evaluated before the
parentheses. The result of operation within the parentheses yields a
float, which should then be applied to the ints. The ints should be
converted to floats.

Anyone else?
Thanks-
MM

Okay, I'm confused as to why this is not working the way I think it
should be. The order of precedence and associativity rules for C
dictate that anything within parentheses is evaluated first (left to
right), and for the purpose of my question, followed by multiplicative
operators [*/%], also from left to right.

a rather over-simplified version of the rules

So, given this simple program:

#include <stdio.h>

int main( void )
{
    float f = 27.0f;
    float c1 = ( f - 32 ) * 5 / 9;
    float c2 = 5 / 9 * ( f - 32 );

5 / 9 is 0
using integer division

    printf( "%f\t%f\t%f\n", f, c1, c2 );
    return 0;

}

I would expect c1 and c2 to be equal, given the order of precedence and
associativity rules. However, the output is:

27.000000       -2.777778       -0.000000

Can anyone explain to me (1) why c1 and c2 are different, and (2) how I
end up with a negative 0?

the negative zero confuses me. Try replacing 5 with 5.0
 
E

Eric Sosman

Okay, I'm confused as to why this is not working the way I think it
should be. The order of precedence and associativity rules for C dictate
that anything within parentheses is evaluated first (left to right), and
for the purpose of my question, followed by multiplicative operators
[*/%], also from left to right.

Sort of. Leave out the evaluation order stuff and replace it
with something like "grouping," and you'd be closer. Precedence and
associativity tell us which operands belong with which operators
(so in `a*b+c/d' we know that the operands of `*' are `a' and `b',
not `a' and `b+c' or `a' and `b+c/d'), but they don't say anything
about the sequence of steps (so in `a*b+c/d' we don't know whether
the multiplication or the division actually happens first).
So, given this simple program:

#include <stdio.h>

int main( void )
{
float f = 27.0f;
float c1 = ( f - 32 ) * 5 / 9;
float c2 = 5 / 9 * ( f - 32 );
printf( "%f\t%f\t%f\n", f, c1, c2 );
return 0;
}

I would expect c1 and c2 to be equal, given the order of precedence and
associativity rules.

You shouldn't expect that. The steps in the c1 computation
are (keeping in mind that they may occur in a different order, but
that however they occur the result must come out the same)

Promote 32 from int to float
Subtract f-32.0f yielding -5.0f
Promote 5 from int to float
Multiply -5.0f by 5.0f yielding -25.0f
Promote 9 from int to float
Divide -25.0f by 9.0f yielding -2.777778 (approximately)

The promotions mentioned above occur because the expression mixes
numbers of different types. So does the c2 computation, but in this
case the outcome is different:

Divide 5 by 9, yielding 0 (5 and 9 are int, so no fraction)
Promote 32 from int to float
Subtract f-32.0f yielding -5.0f
Promote the quotient 0 from int to float
Multiply 0.0f by -5.0f yielding zero (see below)
However, the output is:

27.000000 -2.777778 -0.000000

Can anyone explain to me (1) why c1 and c2 are different, and (2) how I
end up with a negative 0?

Some C implementations (most, even, but not all) distinguish
between "plus zero" and "minus zero." Although the two values are
equal (when compared with `==', for example), the cognoscenti of
fiddly numerical computation find it useful to keep them apart.
For example, if you divide a smallish number by a very large number
the quotient may be so small that it can't be represented exactly,
and may thus wind up as zero -- but the cognoscenti like to think
that it's not "really" zero, just "approximately" zero. In this
view, it's useful to distinguish `1.0/huge/huge -> +0.0' from
`-1.0/huge/huge -> -0.0': One is "very very small but positive"
while the other is "very very small but negative."

... at any rate, that's the rationale as I understand it; I'm
not one of the aforementioned cognoscenti. On systems that make
this distinction, multiplying something by zero gives you a zero,
of course, but with the sign of the "something." In your c2 case,
the "something" was -5.0f, so multiplying by zero gave minus zero.
Not all systems will act this way; some might have given you a plain
zero -- but all would give you a zero of some variety, because the
original `5 / 9' computation is done according to the rules of int
arithmetic and the promotion to float occurs after the fraction has
already been discarded.
 
B

Billy Mays

Okay, I'm confused as to why this is not working the way I think it
should be. The order of precedence and associativity rules for C dictate
that anything within parentheses is evaluated first (left to right), and
for the purpose of my question, followed by multiplicative operators
[*/%], also from left to right.

So, given this simple program:

#include <stdio.h>

int main( void )
{
float f = 27.0f;
float c1 = ( f - 32 ) * 5 / 9;
float c2 = 5 / 9 * ( f - 32 );
printf( "%f\t%f\t%f\n", f, c1, c2 );
return 0;
}

I would expect c1 and c2 to be equal, given the order of precedence and
associativity rules. However, the output is:

27.000000 -2.777778 -0.000000

Can anyone explain to me (1) why c1 and c2 are different, and (2) how I
end up with a negative 0?

Thanks-
MM


The -0.0 is correct.

Also, while parenthesis enclosed statements do execute first,
multiplication, division, and modulus have the same precedence.

Thus evaluation happens like so:

5 / 9 * (27.0 - 32)
5 / 9 * -5.0
0 * -5.0
-0.0



Negative zero is allowed in IEEE 754 floating point values. If you
multiply a positive number by a float with the negative bit set, the
result should be negative. You found an example with your code.
Another example would be if you divided a number by negative infinity vs
positive infinity.

Bill
 
N

Nick Keighley

Thank you, but those are the rules, simplified or not, straight from
the ANSI reference.

The multiplicative operators should NOT be evaluated before the
parentheses. The result of operation within the parentheses yields a
float, which should then be applied to the ints. The ints should be
converted to floats.

Anyone else?
Thanks-
MM

Okay, I'm confused as to why this is not working the way I think it
should be. The order of precedence and associativity rules for C
dictate that anything within parentheses is evaluated first (left to
right), and for the purpose of my question, followed by multiplicative
operators [*/%], also from left to right.
a rather over-simplified version of the rules
5 / 9 is 0
using integer division
the negative zero confuses me.

did you try this?


what is the point of asking advice and then ignoring it?
 
M

Meske Moday

Sorry - I am appreciative of your response. I'm quite aware that 5 / 9
is integer division. Your response did not address the apparent
disparity between very clear precedence and associativity rules and the
actual results.

MM

Thank you, but those are the rules, simplified or not, straight from
the ANSI reference.

The multiplicative operators should NOT be evaluated before the
parentheses. The result of operation within the parentheses yields a
float, which should then be applied to the ints. The ints should be
converted to floats.

Anyone else?
Thanks-
MM

On 15 June, 13:55, Meske Moday <[email protected]> wrote:
Okay, I'm confused as to why this is not working the way I think it
should be. The order of precedence and associativity rules for C
dictate that anything within parentheses is evaluated first (left to
right), and for the purpose of my question, followed by multiplicative
operators [*/%], also from left to right.
a rather over-simplified version of the rules
So, given this simple program:
#include <stdio.h>
int main( void )
{
    float f = 27.0f;
    float c1 = ( f - 32 ) * 5 / 9;
    float c2 = 5 / 9 * ( f - 32 );
5 / 9 is 0
using integer division
    printf( "%f\t%f\t%f\n", f, c1, c2 );
    return 0;

I would expect c1 and c2 to be equal, given the order of precedence and
associativity rules. However, the output is:
27.000000       -2.777778       -0.000000
Can anyone explain to me (1) why c1 and c2 are different, and (2) howI
end up with a negative 0?
the negative zero confuses me.

did you try this?


what is the point of asking advice and then ignoring it?
 
M

Meske Moday

Thank you, but I completely understand integer division. My question
has to do with the apparent disparity between very clear precedence and
associativity rules and the actual output.

MM

On 6/15/2010 8:55 AM, Meske Moday wrote:
[...]
#include <stdio.h>

int main( void )
{
float f = 27.0f;
float c1 = ( f - 32 ) * 5 / 9;
float c2 = 5 / 9 * ( f - 32 );
printf( "%f\t%f\t%f\n", f, c1, c2 );
return 0;
}

I would expect c1 and c2 to be equal, given the order of precedence and
associativity rules. However, the output is:

27.000000 -2.777778 -0.000000

Can anyone explain to me (1) why c1 and c2 are different, and (2) how I
end up with a negative 0?

Question: What is the value of "5 / 9"?

Hint: It's not 0.55555...

Both 5 and 9 are integers, therefore "5 / 9" is done with integer
arithmetic, giving the answer of zero.

As to the "negative zero", perhaps your system says that a negative
number (f-32 is negative) times zero results in negative zero?
 
M

Meske Moday

Thank you! I appreciate your detailed analysis. I'll have to chew on
this a bit.

Again, I very much appreciate your thoughtful response.

MM

Okay, I'm confused as to why this is not working the way I think it
should be. The order of precedence and associativity rules for C dictate
that anything within parentheses is evaluated first (left to right), and
for the purpose of my question, followed by multiplicative operators
[*/%], also from left to right.

Sort of. Leave out the evaluation order stuff and replace it
with something like "grouping," and you'd be closer. Precedence and
associativity tell us which operands belong with which operators
(so in `a*b+c/d' we know that the operands of `*' are `a' and `b',
not `a' and `b+c' or `a' and `b+c/d'), but they don't say anything
about the sequence of steps (so in `a*b+c/d' we don't know whether
the multiplication or the division actually happens first).
So, given this simple program:

#include <stdio.h>

int main( void )
{
float f = 27.0f;
float c1 = ( f - 32 ) * 5 / 9;
float c2 = 5 / 9 * ( f - 32 );
printf( "%f\t%f\t%f\n", f, c1, c2 );
return 0;
}

I would expect c1 and c2 to be equal, given the order of precedence and
associativity rules.

You shouldn't expect that. The steps in the c1 computation
are (keeping in mind that they may occur in a different order, but
that however they occur the result must come out the same)

Promote 32 from int to float
Subtract f-32.0f yielding -5.0f
Promote 5 from int to float
Multiply -5.0f by 5.0f yielding -25.0f
Promote 9 from int to float
Divide -25.0f by 9.0f yielding -2.777778 (approximately)

The promotions mentioned above occur because the expression mixes
numbers of different types. So does the c2 computation, but in this
case the outcome is different:

Divide 5 by 9, yielding 0 (5 and 9 are int, so no fraction)
Promote 32 from int to float
Subtract f-32.0f yielding -5.0f
Promote the quotient 0 from int to float
Multiply 0.0f by -5.0f yielding zero (see below)
However, the output is:

27.000000 -2.777778 -0.000000

Can anyone explain to me (1) why c1 and c2 are different, and (2) how I
end up with a negative 0?

Some C implementations (most, even, but not all) distinguish
between "plus zero" and "minus zero." Although the two values are
equal (when compared with `==', for example), the cognoscenti of
fiddly numerical computation find it useful to keep them apart.
For example, if you divide a smallish number by a very large number
the quotient may be so small that it can't be represented exactly,
and may thus wind up as zero -- but the cognoscenti like to think
that it's not "really" zero, just "approximately" zero. In this
view, it's useful to distinguish `1.0/huge/huge -> +0.0' from
`-1.0/huge/huge -> -0.0': One is "very very small but positive"
while the other is "very very small but negative."

... at any rate, that's the rationale as I understand it; I'm
not one of the aforementioned cognoscenti. On systems that make
this distinction, multiplying something by zero gives you a zero,
of course, but with the sign of the "something." In your c2 case,
the "something" was -5.0f, so multiplying by zero gave minus zero.
Not all systems will act this way; some might have given you a plain
zero -- but all would give you a zero of some variety, because the
original `5 / 9' computation is done according to the rules of int
arithmetic and the promotion to float occurs after the fraction has
already been discarded.
 
M

Meske Moday

Thank you!
MM

Okay, I'm confused as to why this is not working the way I think it
should be. The order of precedence and associativity rules for C dictate
that anything within parentheses is evaluated first (left to right), and
for the purpose of my question, followed by multiplicative operators
[*/%], also from left to right.

So, given this simple program:

#include <stdio.h>

int main( void )
{
float f = 27.0f;
float c1 = ( f - 32 ) * 5 / 9;
float c2 = 5 / 9 * ( f - 32 );
printf( "%f\t%f\t%f\n", f, c1, c2 );
return 0;
}

I would expect c1 and c2 to be equal, given the order of precedence and
associativity rules. However, the output is:

27.000000 -2.777778 -0.000000

Can anyone explain to me (1) why c1 and c2 are different, and (2) how I
end up with a negative 0?

Thanks-
MM


The -0.0 is correct.

Also, while parenthesis enclosed statements do execute first,
multiplication, division, and modulus have the same precedence.

Thus evaluation happens like so:

5 / 9 * (27.0 - 32)
5 / 9 * -5.0
0 * -5.0
-0.0



Negative zero is allowed in IEEE 754 floating point values. If you
multiply a positive number by a float with the negative bit set, the
result should be negative. You found an example with your code.
Another example would be if you divided a number by negative infinity
vs positive infinity.

Bill
 
E

Ersek, Laszlo

Meske Moday wrote:

No, they don't. Between consecutive sequence points, the order of
evaluation is *unspecified*. Precedence affects operator binding, not
order of evaluation.

Somewhat related (I have the DR# from Tim Rentsch, see
<[email protected]>):

http://www.open-std.org/Jtc1/sc22/wg14/www/docs/dr_087.html


It helps me sometimes to parenthesize the expression in question fully.
That is,

5 / 9 * ( f - 32 ) === ((5 / 9) * ( f - 32 ))

Anyway, even the two expressions

-5.0f * 5.0f / 9.0f
5.0f / 9.0f * (-5.0f)

don't need to yield the same result -- rounding errors and their
propagations may differ. See C99 5.1.2.3 p13. Paragraphs 14-15 also
pertain to this thread.

lacos
 
N

Nick Keighley

don't top post

Sorry - I am appreciative of your response. I'm quite aware that 5 / 9
is integer division. Your response did not address the apparent
disparity between very clear precedence and associativity rules and the
actual results.

C doesn't actaully use precedence to determine the order of
evaluation. The precedence rules are a simplified description of what
is actually specified by the grammar. In this case the precedence
rules give the correct answer. In what order do you expect the
expression to be evaluated.

Consider
float c2 = 5 / 9 * ( f - 32 );

that's

load 5
div 9
push
load f
sub 32
mul pop

there are other arrangments that give the same answer but they all
result in 5 / 9 being evaluated and that's zero.

(define c2 (* (/ 5 9) (- f 32)))

the compiler is obliged to evaulate this

(5 / 9) * (f - 32)

which order it evaluates the two sub-expression doesn't matter but
both of them must be evaluated before the multiply.


MM

Thank you, but those are the rules, simplified or not, straight from
the ANSI reference.
The multiplicative operators should NOT be evaluated before the
parentheses. The result of operation within the parentheses yields a
float, which should then be applied to the ints. The ints should be
converted to floats.
Anyone else?
Thanks-
MM
On 2010-06-15 06:07:25 -0700, Nick Keighley said:
Okay, I'm confused as to why this is not working the way I think it
should be. The order of precedence and associativity rules for C
dictate that anything within parentheses is evaluated first (left to
right), and for the purpose of my question, followed by multiplicative
operators [*/%], also from left to right.
a rather over-simplified version of the rules
So, given this simple program:
#include <stdio.h>
int main( void )
{
    float f = 27.0f;
    float c1 = ( f - 32 ) * 5 / 9;
    float c2 = 5 / 9 * ( f - 32 );
5 / 9 is 0
using integer division

    printf( "%f\t%f\t%f\n", f, c1, c2 );
    return 0;
}
I would expect c1 and c2 to be equal, given the order of precedence and
associativity rules. However, the output is:
27.000000       -2.777778       -0.000000
Can anyone explain to me (1) why c1 and c2 are different, and (2) howI
end up with a negative 0?
the negative zero confuses me.
did you try this?
what is the point of asking advice and then ignoring it?
 
M

Meske Moday

Somewhat related (I have the DR# from Tim Rentsch, see
<[email protected]>):

http://www.open-std.org/Jtc1/sc22/wg14/www/docs/dr_087.html



It helps me sometimes to parenthesize the expression in question fully.
That is,

5 / 9 * ( f - 32 ) === ((5 / 9) * ( f - 32 ))

Anyway, even the two expressions

-5.0f * 5.0f / 9.0f
5.0f / 9.0f * (-5.0f)

don't need to yield the same result -- rounding errors and their
propagations may differ. See C99 5.1.2.3 p13. Paragraphs 14-15 also
pertain to this thread.

lacos

Thank you, Iacos.
 
K

Keith Thompson

Meske Moday said:
On 6/15/2010 8:55 AM, Meske Moday wrote:
[...]
#include <stdio.h>

int main( void )
{
float f = 27.0f;
float c1 = ( f - 32 ) * 5 / 9;
float c2 = 5 / 9 * ( f - 32 );
printf( "%f\t%f\t%f\n", f, c1, c2 );
return 0;
}

I would expect c1 and c2 to be equal, given the order of precedence and
associativity rules. However, the output is:

27.000000 -2.777778 -0.000000
[...]

Both 5 and 9 are integers, therefore "5 / 9" is done with integer
arithmetic, giving the answer of zero.

As to the "negative zero", perhaps your system says that a negative
number (f-32 is negative) times zero results in negative zero?

Thank you, but I completely understand integer division. My question
has to do with the apparent disparity between very clear precedence and
associativity rules and the actual output.

Please don't top-post. Any new text should *follow* the quoted
material to which it refers, and quoted material should be trimmed
down to what's relevant to your followup. See:
http://www.caliburn.nl/topposting.html
http://www.cpax.org.uk/prg/writings/topposting.php
for an explanation, and see most of the articles in this newsgroup
for examples. (There's nothing inherently wrong with other forms
of posting, but it's best to follow the local convention.)

There is no disparity between the C expression evaluation rules and the
behavior you're seeing.

An integer argument can be converted to float via the "usual arithmetic
conversions". For example, in this expression:
1 / 3.0
the left operand is promoted from int to float to match the type of the
right operand, and the division yields approximately 0.333333.

But in this expression:
3 / 2 * 5.0
the operands of the "/" operator are 3 and 2. Since they're already
of the same type, no promotion is applied, and the result is 1.
We now have
1 * 5.0
Now the left operand, 1, is promoted to float, and we have
1.0 * 5.0
yielding 5.0.

In most cases, the context in which an expression appears does not
affect the manner in which it's evaluated. An integer division is
an integer division, even if it's the operand of a floating-point
operation. Only *after* it's evaluated might the result be promoted
depending on the context.

This can be confusing at times. You can avoid the confusion by using
consistent types for your operands: 5.0 rather than 5, for example.

Also, as Richard mentioned, precedence rules don't dictate order
of evaluation. In the expression x / y * z, the three operands
could legally be evaluated in any of 6 possible orders: x,y,z x,z,y
y,x,z y,z,x z,x,y z,y,x (this can be relevant if the operands have
side effects).
 
S

Seebs

Thank you, but those are the rules, simplified or not, straight from
the ANSI reference.

You're misunderstanding them.
The multiplicative operators should NOT be evaluated before the
parentheses.

You've gotten confused in the way a lot of people get confused.

There is no "order of evaluation". Evaluation does not occur in an order.
Things are not evaluated before or after other things. That's not what
precedence does.

Precedence controls *BINDING*. It determines which expressions are the
operands of which operators. That doesn't tell you anything about which
of them are evaluated first.
The result of operation within the parentheses yields a
float, which should then be applied to the ints. The ints should be
converted to floats.

Wrong. a / b * c => (a / b) * c

/ and * have the same "precedence", so it's the left-associative property
that carries the day.

-s
 
B

bart.c

Seebs said:
You're misunderstanding them.


You've gotten confused in the way a lot of people get confused.

There is no "order of evaluation". Evaluation does not occur in an order.
Things are not evaluated before or after other things. That's not what
precedence does.

Precedence controls *BINDING*. It determines which expressions are the
operands of which operators. That doesn't tell you anything about which
of them are evaluated first.

In a * (b / c) I would expect the / to be evaluated first.

In a * b / c (that is, (a * b) / c) I would expect the * to be evaluated
first.

So precedence does affect the order in which the operations are done (if not
the order that a,b,c are evaluated).
 
K

Keith Thompson

bart.c said:
In a * (b / c) I would expect the / to be evaluated first.

In a * b / c (that is, (a * b) / c) I would expect the * to be evaluated
first.

So precedence does affect the order in which the operations are done (if not
the order that a,b,c are evaluated).

Right. Barring certain kinds of optimizations, an operator cannot
be evaluated until the values of its operands are available. So, in
a * b / c, the multiplication cannot be performed until after both
a and b have been evaluated, and the division cannot be performed
until after a, b, and c have all been evaluated.

But, as you acknowledge, a, b, and c themselves can be evaluated
in any of the 6 possible orders.

Precedence does affect (but not entirely control) order of evaluation,
but not in the way that a lot of people assume it does.
 
S

Seebs

In a * (b / c) I would expect the / to be evaluated first.
In a * b / c (that is, (a * b) / c) I would expect the * to be evaluated
first.
So precedence does affect the order in which the operations are done (if not
the order that a,b,c are evaluated).

It's really changing the bindings of the operators. The order, *in some
cases*, follows from that.

But what's really changing is what the operands of / are -- whether it's
b and c, or (a * b) and c. Any ordering changes follow from that; the
()s aren't directly affecting order, and in some cases, they really don't
have any effect on ordering.

-s
 
N

Nobody

Sorry - I am appreciative of your response. I'm quite aware that 5 / 9
is integer division. Your response did not address the apparent
disparity between very clear precedence and associativity rules and the
actual results.

There is no disparity. Multiplication and division have equal precedence
and are left-associative. Consequently, the expression

a / b * c

is equivalent to

(a / b) * c

due to left-associativity.

If a and b are integers, (a / b) is computed using integer arithmetic. If
c is float or double, the result of (a / b) will be promoted to double
after the division but before the multiplication.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top