[net.lang.pascal] Floating Point trunc?

barrett@hp-dcde.UUCP (02/15/84)

Ok.  I have a nitty gritty pascal question for people.

All I want to do is to remove the fractional part of a real number,
in a machine-independent fashion using vanilla J&W pascal only. 
You are NOT allowed to generate an integer during the calculation, ala
 
 real_value := trunc(real_value);   { integer overflow may occur }

			any ideas?

						Dave Barrett
						(hp-dcd!barrett)

ags@pucc-i (Seaman) (02/18/84)

>  All I want to do is to remove the fractional part of a real number,
>  in a machine-independent fashion using vanilla J&W pascal only. 
>  You are NOT allowed to generate an integer during the calculation, ala
>   
>   real_value := trunc(real_value);   { integer overflow may occur }

Here is a quick hack which I think will do the job:

	function ftrunc(x : real) : real;
	  var y : real;
	  begin
	    y := abs(x);
	    if y <= maxint then
	      ftrunc := trunc(x)
	    else if y = y + 1.0 then
	      ftrunc := x
	    else begin
	      y := ftrunc(x/maxint) * maxint;
	      ftrunc := y + ftrunc(x-y)
	      end
	  end;

-- 

Dave Seaman
..!pur-ee!pucc-i:ags

"Against people who give vent to their loquacity 
by extraneous bombastic circumlocution."

janney@unm-cvax.UUCP (02/21/84)

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