phys169@csc.canterbury.ac.nz (05/01/91)
In article <1991May1.021059.2129@ux1.cso.uiuc.edu>, husak@ux1.cso.uiuc.edu (BugsBunny) writes: > I'm running the following in TP and get the wrong answer.. Please correct > me if I'm wrong... > > program Is_this_wrong; > var > xx,yy,c1,c2,c3,c4: integer; > begin > xx := 639; yy := 479; > c1 := Trunc(50*xx/639); c2 := Trunc(50*yy/479); > c3 := Trunc(300*xx/639); c4 := Trunc(250*yy/479); > writeln(xx,yy,c1,c2,c3,c4); > end. > This is a common problem: you are multiplying two integers to get a temporary integer result. For example, when calculating 300*xx/639 it works out 300*xx to 16 bits accuracy (same accuracy as the 300 and xx), which is not the 191700 you would expect. Either you should change the declaration of xx & yy to be longint (or reals, if you like), or change the code to.. c1 := Trunc(50.0*xx/639.0); c2 := Trunc(50.0*yy/479.0); c3 := Trunc(300.0*yy/639); c4 := Trunc(250.0*yy/479.0); The reason this works is that 300.0*yy is a real result, which goes on to the division by 639 (or 639.0, either will do, but 639.0 is preferrable). Note that 300*479/639 gives the expected result with TP 5, since 300*479 is evaluated at compile time to give a longint result, so it knows to use 32 bits of accuracy. Another interesting point is that 120*b (where b is a byte variable set to 100) gives the correct answer, when you might have thought it would be clipped to 8 bits. Presumably 100 is an integer constant, not a byte constant. BTW, it is a good idea to make sure range checking is on; it catches some cases like this (but not this particular one, I'm afraid). Hope this helps, Mark Aitchison, Physics, University of Canterbury, New Zealand.
ravn@imada.ou.dk (Thorbjoern Ravn Andersen) (05/06/91)
phys169@csc.canterbury.ac.nz writes: [Stuff deleted] >longint (or reals, if you like), or change the code to.. > c1 := Trunc(50.0*xx/639.0); c2 := Trunc(50.0*yy/479.0); > c3 := Trunc(300.0*yy/639); c4 := Trunc(250.0*yy/479.0); >The reason this works is that 300.0*yy is a real result, which goes on to the >division by 639 (or 639.0, either will do, but 639.0 is preferrable). You may also force the computation into real mode, by doing the division first. Calculating it like c3:= Trunc(300/639 * yy) will have the same result. I do like this because I do not think the .0's are pretty. I do not know, however, how this may affect your portabillity with other compilers. [BTW. This was checked with Turbo 5.0, I do not know if it has been changed in later versions] >BTW, it is a good idea to make sure range checking is on; it catches some >cases like this (but not this particular one, I'm afraid). As far as I know, there is *NO* checking on overflow on integer calculations. The range check is only active in subranges and index variables. -- Thorbj\o{}rn Ravn Andersen 'Normally I kill people for money. You are my ravn@imada.ou.dk friend; I will kill you for nothing' -- Chico Marx Justice, n.: