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