home *** CD-ROM | disk | FTP | other *** search
- { CALCUTIL: Calculator Utilities. }
- { Copyright (C) 1984 by QCAD Systems Inc., All Rights Reserved. }
-
- {******************}
- procedure WRITE_VALUE(R: real);
- { writes r to the screen in a 'reasonable' format. must resort
- to Turbo's exponential notation in extreme cases. }
- const
- MIN_MAGNITUDE = -38;
- { Turbo Pascal has roughly 12 decimal digits of precision;
- keep the last one as a guard digit. }
- PRECISION = 11;
- var
- MAGNITUDE: integer;
- FRACTION: real;
- FUZZ: real; { number to compare against for roundoff }
-
- {..................}
- procedure WRITE_FRACTION(FRACTION: real; DIGITS: integer);
- { chunk out zero or more digits of the fraction, until either
- the digit count gives out, or we run into the fuzz. }
- begin
- while (abs(fraction) > fuzz) and (digits > 0) do begin
- fraction := fraction * 10.0;
- write(trunc(fraction):1);
- fuzz := fuzz * 10.0;
- digits := digits-1;
- fraction := frac(fraction)
- end
- end;
-
- begin { write_value }
- { first, establish some useful information about R. }
- if r = 0.0 then
- magnitude := 0
- else
- magnitude := trunc(ln(abs(r))/ln(10.0));
- if magnitude-precision >= min_magnitude then begin
- fuzz := exp((magnitude-precision+1)*ln(10.0));
- { Turbo reals tend to err toward zero; use the fuzz to
- compensate for this effect. }
- if r<0.0 then
- r := r-fuzz
- else if r>0.0 then
- r := r+fuzz
- end
- else
- fuzz := 0.0;
- fraction := abs(frac(r));
- { now, decide what to do with R. }
- if (abs(r) >= maxint) or (magnitude < -3) then
- { big enough or small enough for a possible loss of precision:
- use exponential notation. }
- write(r)
- else if fraction < fuzz then
- { essentially whole number of small magnitude }
- write(trunc(r):1)
- else begin
- { real number in ddd.ddd format. }
- if (-1.0 < r) and (r < 0.0) then
- write('-'); { trunc eliminates minus sign for these numbers }
- write(trunc(r):1, '.');
- write_fraction(fraction, precision-magnitude)
- end
- end { write_value };
-
- {******************}
- procedure EVAL_BINOP(OP: operator; OPND1, OPND2: semrecp;
- RESULT: semrecp);
- { evaluate the given binary operator, setting up the result
- semantic record with the resulting value. if there is an
- error, result will generally contain a non-value (because
- it is set up to be 'other' rather than 'float' by default).
- most of the code here is for error handling. }
- var V1, V2: real; { operand values }
- SEM_TYPE: semtype; { type of result }
- begin
- if opnd2 = nil then begin
- { actually, its a unary operator }
- if opnd1^.semt = float then begin
- case op of
- uminus: result^.rval := -opnd1^.rval;
- ELSE error('internal problems in eval_binop')
- end;
- result^.semt := float
- end
- end
- else if opnd1^.semt <> float then
- result^ := opnd2^
- else if opnd2^.semt <> float then
- result^ := opnd1^
- else begin
- { both values are good }
- v1 := opnd1^.rval;
- v2 := opnd2^.rval;
- sem_type := float;
- case op of
- divide: if v2 <> 0.0 then
- v1 := v1/v2
- else begin
- write('Attempt to divide ');
- write_value(v1);
- writeln(' by zero.');
- sem_type := other
- end;
- mpy: v1 := v1*v2;
- plus: v1 := v1+v2;
- minus: v1 := v1-v2;
- end;
- result^.semt := sem_type;
- result^.rval := v1
- end
- end;
-
- {******************}
- procedure INIT_SEM;
- { No semantics initialization needed. }
- begin
- end;
-
- {******************}
- procedure END_SEM;
- { No semantics conclusion needed. }
- begin
- end;
-