gcc type promotion bug?
#include <stdio.h>
intmain(int argc, char **argv)
{
long a = 0x70000037L;
float f = 0.01;
long b = a + 1L/f;
printf("%lx, %lx\n", b, a + 100L);
return 0;
}In the above, 1/f = 100, so the two numbers printed out should be the same. For me it prints out "70000080, 7000009b". Same for gcc 2.96 and 3.0.3.
By trying various numbers for 'a', it appears to me that it is demoting 'a' to a float when evaluating 'b', thus truncating it to 24 significant bits. I thought all mixed mode arithmetic was supposed to be promoted to doubles for evaluation. This is breaking parted 1.6 on ia64.
Richard
Richard Hirst <[email protected]> writes:
|> #include <stdio.h>
|>
|> int
|> main(int argc, char **argv)
|> {
|> long a = 0x70000037L;
|> float f = 0.01;
|> long b = a + 1L/f;
|>
|> printf("%lx, %lx\n", b, a + 100L);
|> return 0;
|> }
|>
|>
|>
|> In the above, 1/f = 100, so the two numbers printed out should be the
|> same. For me it prints out "70000080, 7000009b". Same for gcc 2.96
|> and 3.0.3.
|>
|> By trying various numbers for 'a', it appears to me that it is demoting
|> 'a' to a float when evaluating 'b', thus truncating it to 24 significant
|> bits. I thought all mixed mode arithmetic was supposed to be promoted
|> to doubles for evaluation.No. There are no operands of type double or long double involved, so the ususal arithmetic conversions (6.3.1.8) choose float as the common type:
Otherwise, if the corresponding real type of either operand is float, the other operand is converted, without change of type domain, to a type whose corresponding real type is float.
Andreas.
Signature · 4 lines
Andreas Schwab, SuSE Labs, [email protected] SuSE GmbH, Deutschherrnstr. 15-19, D-90429 Nürnberg Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different."
Quoted 6 lines · Andreas Schwab
No. There are no operands of type double or long double involved, so the ususal arithmetic conversions (6.3.1.8) choose float as the common type:
Otherwise, if the corresponding real type of either operand is float, the other operand is converted, without change of type domain, to a type whose corresponding real type is float.
OK, thanks. I looked at (out of date) K&R, which told me all floating point arithmetic in C was done in double precision, and I tried my program on i386, where it appeared to worked fine.
Cheers,
Richard
Richard Hirst <[email protected]> writes:
|> On Tue, Apr 16, 2002 at 10:31:02PM +0200, Andreas Schwab wrote: |> > No. There are no operands of type double or long double involved, so the |> > ususal arithmetic conversions (6.3.1.8) choose float as the common type: |> > |> > Otherwise, if the corresponding real type of either operand is float, |> > the other operand is converted, without change of type domain, to a |> > type whose corresponding real type is float. |> |> OK, thanks. I looked at (out of date) K&R, which told me all floating |> point arithmetic in C was done in double precision, and I tried my |> program on i386, where it appeared to worked fine.
The standard explicitly allows for using a higher precision and range for floating point computation than those of the nominal type.
Andreas.
Signature · 4 lines
Andreas Schwab, SuSE Labs, [email protected] SuSE GmbH, Deutschherrnstr. 15-19, D-90429 Nürnberg Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different."