From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.5-pre1 (2020-06-20) on ip-172-31-74-118.ec2.internal X-Spam-Level: X-Spam-Status: No, score=-1.9 required=3.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.5-pre1 Date: 20 Nov 91 02:55:01 GMT From: csus.edu!wupost!cs.utexas.edu!sun-barr!cronkite.Central.Sun.COM!newstop!s unaus!assip.csasyd!condor!daves@ucdavis.ucdavis.edu (Dave Smart) Subject: Re: Red-faced professor gets bitten in search for portability Message-ID: List-Id: In <1991Nov16.000120.25606@milton.u.washington.edu> mfeldman@milton.u.washingto n.edu (Michael Feldman) writes: > In article <11919@spim.mips.COM> murphy@mips.com (Mike Murphy) writes: > > > >You are right about your first version not being portable, but > >your second version seems a bit convulated to me. Why not just > >check whether you indeed rounded down after doing the integer conversion? > >For example: > > FUNCTION Trunc (X: Float) RETURN Integer IS > > itrunc : integer = integer(x - 0.5); > > BEGIN > > if x - float(itrunc) >= 1.0 then > > -- rounded down, so add back a 1 > > return itrunc+1; > > else > > return itrunc; > > end if; > > END Trunc; > Sure - this seems equivalent. I kinda like the halving and doubling, > because these are pretty fast to implement (as shifts) given a > good optimizer. Your method has the advantage, I suppose, of being immune > to a possible overflow from the doubling. This code works (after fixing the syntax error). Yours doesn't, Mike. Your FUNCTION Trunc (X: Float) RETURN Integer IS BEGIN RETURN Integer(2.0 * X) / 2; END Trunc; still takes the integer before the division. In fact, as you've now doubled th e number, the horrible rounding beast is twice as active (i.e. 0.25 and 0.75 both fall victim). I think Mike Murphy's code looks awkward because it's sort of upside down. The problem can be restated as: "if integer () rounds up, return one less than the value of integer (), otherwise return the value of integer ()". This translates to: function trunc (number: float) return integer is begin if float (integer (number)) > number then -- does it round up? return integer (number) - 1; -- yes - stop it! else return integer (number); -- no - ok as it is. end if; end trunc; (I'm assuming that my compiler is clever enough to eliminate the redundant conv ersions to integer.) Dave >>From here down - my program which checks out all four trunc functions: -------------------------------- with integer_io; use integer_io; with text_io; use text_io; procedure x is package floating_io is new float_io (float); use floating_io; r: float; check: integer; error, first: boolean; FUNCTION Trunc_mf1 (X: Float) RETURN Integer IS BEGIN RETURN Integer(X - 0.5); END Trunc_mf1; FUNCTION Trunc_mf2 (X: Float) RETURN Integer IS BEGIN RETURN Integer(2.0 * X) / 2; END Trunc_mf2; FUNCTION Trunc_mm1 (X: Float) RETURN Integer IS itrunc : integer := integer(x - 0.5); BEGIN if x - float(itrunc) >= 1.0 then return itrunc+1; -- rounded down, so add back a 1 else return itrunc; end if; END Trunc_mm1; function trunc_ds1 (number: float) return integer is begin if float (integer (number)) > number then -- does it round up? return integer (number) - 1; -- yes - stop it! else return integer (number); -- no - ok as it is. end if; end trunc_ds1; procedure try (message: string; value: integer) is begin put (" " & message & " => "); put (value, 2); if first then check := value; first := false; elsif check /= value then error := true; end if; end try; begin -- x r := -5.0; loop put (r, 3, 2, 0); first := true; error := false; try ("mf1", trunc_mf1 (r)); try ("mf2", trunc_mf2 (r)); try ("mm1", trunc_mm1 (r)); try ("ds1", trunc_ds1 (r)); if error then put (" ******"); end if; new_line; r := r + 0.25; exit when r > 5.0; end loop; end; ---------------------------- -- David Smart, Computer Sciences of Australia. Net: daves@assip.csasyd.oz.au