[comp.lang.pascal] TP 5.5 int

aindiana@osiris.cso.uiuc.edu (Daiv Stoner) (08/15/90)

A little technical question for all you net wizards.
The following piece of code written and compiled in Turbo Pascal
5.5 on an IBM Model 50 gives strange results.

Here's the code:

program a;
var
 rate,reg:real;
  x,value:real;
begin
  rate:=2.01;
  reg:=12.5;
  value:=rate*reg*100+0.5;
  x := int(value)/100;

writeln('rate=',rate:8:4,'  reg=',reg:8:4,'  total=',rate*reg:8:4,'  x=',x:8:4);
end.

I get this output:

rate=  2.0100  reg= 12.5000  total= 25.1250  x= 25.1200

Borland Tech. Support says "round-off" error.  I say it's a bug.
Any ideas?


--
Daiv Stoner                  +===============================================+
aindiana@osiris.cso.uiuc.edu | I work for the Gov't.  If I want your opinion |
oinxds@ria-emh1.army.mil     | I'll ask you to fill out the necessary forms. |
Disclaimer:  The Dept. of    +===============================================+
Defense doesn't even know what it's doing, let alone what I'm doing.

rowley@cs.umn.edu (Henry A. Rowley) (08/16/90)

In article <1990Aug15.160719.12762@ux1.cso.uiuc.edu> aindiana@osiris.cso.uiuc.edu (Daiv Stoner) writes:
>  rate:=2.01;
>  reg:=12.5;
>  value:=rate*reg*100+0.5;
>  x := int(value)/100;
>writeln('rate=',rate:8:4,'  reg=',reg:8:4,'  total=',rate*reg:8:4,'  x=',x:8:4);
>I get this output:
>
>rate=  2.0100  reg= 12.5000  total= 25.1250  x= 25.1200

It is probably a round off error.  You could verify the following statements
by printing the entire number, not a rounded version of it:  ie writeln(rate),
not writeln(rate:8:4).  Anyway, here is where the round off is occurring:

Lets say the actual value of rate is 25.124999999999999.  Then, if you multiply
by 100, you get  2512.49999999999.  Adding 0.5 gives 2512.999999999.  Then, 
truncate to the integer part of the number, and you get  2512.  Dividing by
one hundred gives you the final answer 25.12.  As you can see, this is due to
rounding errors, not a bug.

Henry A. Rowley          Internet: rowley@cs.umn.edu -or- rowley@ux.acs.umn.edu
THE CONTENT OF THE PROPOSITIONS - _The Shockwave Rider_ by John Brunner--------
#1:  That this is a rich planet.  Therefore poverty and hunger are unworthy of 
it, and since we can abolish them, we must.
#2:  That we are a civilized species.  Therefore none shall henceforth gain 
illict advantage by reason of the fact that we together know more that one of 
us can know.

winfave@dutrun.UUCP (Alexander Verbraeck) (08/16/90)

In article <1990Aug15.160719.12762@ux1.cso.uiuc.edu> aindiana@osiris.cso.uiuc.edu (Daiv Stoner) writes:
>
>
>A little technical question for all you net wizards.
>The following piece of code written and compiled in Turbo Pascal
>5.5 on an IBM Model 50 gives strange results.
>
>Here's the code:
>
>program a;
>var
> rate,reg:real;
>  x,value:real;
>begin
>  rate:=2.01;
>  reg:=12.5;
>  value:=rate*reg*100+0.5;
>  x := int(value)/100;
>
>writeln('rate=',rate:8:4,'  reg=',reg:8:4,'  total=',rate*reg:8:4,'  x=',x:8:4);
>end.
>
>I get this output:
>
>rate=  2.0100  reg= 12.5000  total= 25.1250  x= 25.1200
>
>Borland Tech. Support says "round-off" error.  I say it's a bug.
>Any ideas?
>

I think Borland Tech Support is right: it's a "roud off" error. The
Int() function "Returns the integer part of the argument" according to
page 321 of my TP 5.5 manual. As real values are not stored in decimal
form, but in binary form, it might be that 2.01*12.5*100+0.5 will be
stored as the equivalent of 2512.99999999. The value of
Int(2512.99999999) is, however sadly in this case, 2512 instead of 2513,
the value you would expect. A possible solution: use Int(value+epsilon)
instead of Int(value), with epsilon a value that is very small, for
instance covering only one or two of the least significant bits. This is
especially important in financial programs, as I once found out the hard
way. You'll be loosing cents in no time, when you store financial values
as reals, and then perform arithmetic on them. Solution: either use
(long)ints, or apply the epsilon-trick. I used a function "CleanMoney"
for that, that looked something like this:

function CleanMoney(m:real):real;
begin
  CleanMoney:=Int(100.0*m+epsilon)/100.0;
end;

----------------------------------------------------------------------
Alexander Verbraeck                  e-mail: winfave@dutrun.tudelft.nl
Delft University of Technology               winfave@hdetud1.bitnet
Department of Information Systems            winfave@dutrun.uucp
PO Box 356, 2600 AJ  The Netherlands         dutrun!winfave@hp4nl.uucp
----------------------------------------------------------------------