lvc@cbnews.ATT.COM (Lawrence V. Cipriani) (01/20/89)
This program demonstrates a bug that is in some versions of pcc:
main()
{
float f, g;
unsigned short u, v;
short s, t;
u = 250;
s = 250;
t = 100;
v = 100;
f = t - s;
g = v - u;
printf("f = %f, g = %f\n", f, g);
}
When compiled and executed the output is:
f = -150.000000, g = 65386.000000
The correct value for g is -150.000000. This bug is *not* present
in the cc that comes with SVR3 from AT&T. It is present in SVR2 for
VAX and 3B20.
--
Larry Cipriani, AT&T Network Systems, Columbus OH,
Path: att!cbnews!lvc Domain: lvc@cbnews.ATT.COM
dg@lakart.UUCP (David Goodenough) (01/23/89)
lvc@cbnews.ATT.COM (Lawrence V. Cipriani) sez: ] This program demonstrates a bug that is in some versions of pcc: ] ] main() ] { ] float f, g; ] unsigned short u, v; ] short s, t; ] ] u = 250; ] s = 250; ] ] t = 100; ] v = 100; ] ] f = t - s; ] g = v - u; ] ] printf("f = %f, g = %f\n", f, g); ] } ] ] When compiled and executed the output is: ] ] f = -150.000000, g = 65386.000000 ] ] The correct value for g is -150.000000. No. The correct value for g is 65386.0 [1]. If you read the gospel according to Kernighan and Ritchie [2], it says that when you do mathematics, and at least one of the operands is unsigned, and the other is NOT float or better (as above), it is done in an unsigned manner. Now last time _I_ checked, -150 was a negative number, which simply doesn't exist in the land of unsigned. HOWEVER this type conversion DOES NOT OCCUR ACROSS ASSIGNMENTS. [1] depends on your size of short. 65386.0 is correct for those with 16 bit shorts. Check your system, as your actual mileage may vary. [2] :-) -- dg@lakart.UUCP - David Goodenough +---+ IHS | +-+-+ ....... !harvard!xait!lakart!dg +-+-+ | AKA: dg%lakart.uucp@xait.xerox.com +---+
lvc@cbnews.ATT.COM (Lawrence V. Cipriani) (01/25/89)
In article <3310@cbnews.ATT.COM>, I wrote:
+ This program demonstrates a bug that is in some versions of pcc:
+
+ main()
+ {
+ float f, g;
+ unsigned short u, v;
+ short s, t;
+
+ t = 100; s = 250;
+ v = 100; u = 250;
+ f = t - s; g = v - u;
+
+ printf("f = %f, g = %f\n", f, g);
+ }
+
+ When compiled and executed the output is:
+
+ f = -150.000000, g = 65386.000000
+
+ The correct value for g is -150.000000. This bug is *not* present
+ in the cc that comes with SVR3 from AT&T. It is present in SVR2 for
+ VAX and 3B20.
I consulted with the C compiler gurus in AT&T and they said that the result
as originally stated is correct, and that the value of -150.000000 is wrong.
To force the result to -150.000000 the statement:
g = v - u;
should be:
g = (int)v - (int)u;
Though some compilers even get this wrong, e.g., the SVR2 3b20 C compiler.
--
Larry Cipriani, att!cbnews!lvc or lvc@cbnews.att.com
chris@mimsy.UUCP (Chris Torek) (01/25/89)
The program fragment: float g; unsigned short u, v; u = 250; v = 100; g = v - u; >>... The correct value for g is -150.000000. In article <398@lakart.UUCP> dg@lakart.UUCP (David Goodenough) writes: >No. The correct value for g is 65386.0 [for 16 bit short]. Actually, the answer depends on two (or three) things: If you implement classic C, the answer is some positive number. The type of (u_short-u_short) is the type of (expand(u_short)-expand(u_short)) which is (u_int-u_int) which is u_int. 65368 is a typical value. If you implement pANS C, the answer depends on one thing: The type of (u_short-u_short) is either u_int or int. If sizeof(int)>sizeof(short), expand(u_short) is int, otherwise it is u_int. I consider this `feature' one of the major botches in the pANS (although something like it is necessary to get unsigned chars to produce int values without casts). Now, on a 3B, sizeof(int) > sizeof(short), so the answer depends on whether your compiler implements classic C (65386.0) or pANS C (-150.0). But on a PDP-11, sizeof(int)==sizeof(short), so the answer is 65368.0 in both classic C and pANS C. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
shirono@hcx3.SSD.HARRIS.COM (01/26/89)
In article <3310@cbnews.ATT.COM> lvc@cbnews.ATT.COM (Lawrence V. Cipriani) writes: > main() > { > float f, g; > unsigned short u, v; > short s, t; > > u = 250; s = 250; t = 100; v = 100; > f = t - s; g = v - u; > > printf("f = %f, g = %f\n", f, g); > } > > f = -150.000000, g = 65386.000000 > > The correct value for g is -150.000000. Excuse me... Is the correct value of g REALLY -150.00? Recall that both v and u are unsigned short. (v - u) should therefore be evaluated as unsigned short and then converted to float, right? According to K&R, (p. 183), Unsigned integers, declared ``unsigned,'' obey the laws of arithmetic modulo 2^n where n is the number of bits in the representation. According to K&RII, (p. 36), unsigned numbers are always positive or zero, and obey the laws of arithmetic modulo 2^n, where n is the number of bits in the type. So, assuming sizeof(unsigned short) is 2, then arithmetic of unsigned short is done modulo 2^(16), or 65536. In this case, (100 - 250) mod 65536 = -150 mod 65536 = 65386 mod 65536 = 65386 g = 65386.0 QED --Roberto ______________________________________________________________________________ || Internet: shirono@ssd.harris.com Roberto Shironoshita || Harris Corporation || ...!novavax---\ Computer Systems Division || UUCP: ...!uunet-------!hcx1!shirono || ...!mit-eddie-/ ------------------------------------------------------------------------------ DISCLAIMER: The opinions expressed here are my own; they in no way reflect the opinion or policies of Harris Corporation.
diamond@csl.sony.JUNET (Norman Diamond) (01/26/89)
In article <398@lakart.UUCP>, dg@lakart.UUCP (David Goodenough) writes: > > lvc@cbnews.ATT.COM (Lawrence V. Cipriani) sez: > ] f = -150.000000, g = 65386.000000 > ] The correct value for g is -150.000000. > > No. The correct value for g is 65386.0 [1]. If you read the gospel > according to Kernighan and Ritchie [2], > > [2] :-) Is this first-edition :-) or second-edition :-) ? The subtraction operator was applied to a short and an unsigned short, and the result (either unsigned short or signed int) converted to float. Under the old unsigned-preserving rules, both f and g should have been 65366.0. Under the ANSI value-preserving rules, both f and g should be -150.0. Mr. Cipriani assumed that System V Releases 2 and 3 should support modern semantics. The gurus that he asked, and Mr. Goodenough, perhaps in the interests of backwards compatibility, feel that they should support Version 7 semantics. The System V Release 2 version, in the interests of pleasing everybody, took the middle road. Conclusion: that wasn't a bug, that was a feature. -- Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.jp@relay.cs.net) The above opinions are my own. | Why are programmers criticized for If they're also your opinions, | re-inventing the wheel, when car you're infringing my copyright. | manufacturers are praised for it?
chris@mimsy.UUCP (Chris Torek) (01/26/89)
In article <15620@mimsy.UUCP> I wrote: >Now, on a 3B, sizeof(int) > sizeof(short), so the answer depends >on whether your compiler implements classic C (65386.0) or pANS C >(-150.0). Oops: since sizeof(u_int)==4 and the range is 0..4294967295, a `classic C' compiler should produce 4294967146.0, not 65368.0. Thanks to Chris Aoki at Sun for pointing this out, and to Donn Seeley for further noting that some bits will then `rub off' if this is stored in a 32-bit float (so that you might get, say, 4294967040.0). (Donn also noticed a few typos: 65386 for 65368.) (In general, conversion from unsigned to float should be done using machine instructions of the form: convert signed to float if result < 0, add pow(2.0,32.0) e.g., on a vax, cvtlf r1,r0 jgeq 0f addf2 $0f4294967296.0,r0 0: ... ) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
mouse@mcgill-vision.UUCP (der Mouse) (02/01/89)
In article <3310@cbnews.ATT.COM>, lvc@cbnews.ATT.COM (Lawrence V. Cipriani) writes: > This program demonstrates a bug that is in some versions of pcc: > main() { float f,g; unsigned short u,v; short s,t; > u = 250; s = 250; > v = 100; t = 100; > f = t - s; g = v - u; > printf("f = %f, g = %f\n", f, g); } [code compressed -dM] > When compiled and executed the output is: > f = -150.000000, g = 65386.000000 > The correct value for g is -150.000000. That depends on the promotion rules in use. Using the "unsignedness preserving" rules, the correct value for g is MAXUINT-149. Using the "value preserving" rules, it depends again: if short is the same size as int, the correct result is still MAXUINT-149; if short is smaller than int, the correct result is -150. Your result looks like MAXUINT-149 on a machine with 16-bit ints, of course - or a buggy compiler. This may in fact indicate a bug in your compiler, but you haven't given enough information to convince me of it. der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu