Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site unm-cvax.UUCP Path: utzoo!watmath!clyde!floyd!cmcl2!lanl-a!unm-cvax!janney From: janney@unm-cvax.UUCP Newsgroups: net.lang.pascal Subject: Re: Floating Point trunc? Message-ID: <709@unm-cvax.UUCP> Date: Mon, 20-Feb-84 22:18:50 EST Article-I.D.: unm-cvax.709 Posted: Mon Feb 20 22:18:50 1984 Date-Received: Tue, 21-Feb-84 08:46:18 EST References: <20300001@hp-dcde.UUCP> Organization: Univ. of New Mexico, Albuquerque Lines: 52 David Barrett (hp-dcde!barrett) asks for a standard, machine-independant way to remove the fractional part of a Pascal real without converting it to an integer in the process. The following is my attempt at a solution: note that I am not an expert on floating point number representation and I make no guarantee that this will work on all machines. Also, note that floating point numbers large enough to cause integer overflow very probably don't even have an "integer part": truncation will get you a multiple of some small power of 2. function ftrunc(x: real): real; {removes the "fractional part" of x in a reasonably standard and machine independant way. This is done by using the limited resolution of floating point numbers--you add to x a number so big that the fractional part of x must be thrown away. This assumes that the floating point representation contains such a number, and that the radix of the exponent is some power of 2. Unfortunately, some machines just throw the fractional part away, but other machines use it for rounding. Still other machines round for some fractional parts of .5 and truncate for the others. This version tries to detect rounding after the fact and correct for it. THERE MAY BE STRANGE FLOATING POINT REPRESENTATIONS FOR WHICH THIS FAILS. x must not be negative. In a real program, big would be global and its value would be calculated only once. } var big, y: real; begin {find the smallest number big such that big + 0.4 = big} big := 1.0; while big + 0.4 > big do {0.4 is to avoid problems with rounding} big := big * 2; if x >= big then ftrunc := x {x has no "fractional part"} else begin y := x + big; {This is done in separate assignments to help ensure evaluation order. Beware of optimisers!} y := y - big; if y > x then ftrunc := y - 1.0 {rounding} else ftrunc := y {no rounding} end end; {ftrunc} As far as I know, this or some approach like it is the only way to do this in Jensen-and-Wirth Pascal. Jim Janney ucbvax!lbl-csam!lanl-a!unm-cvax!janney