Problem? with float()
Jose E. Marchesi
jemarch@gnu.org
Wed Mar 11 20:25:00 GMT 2026
> Hello everyone,
>
> I am having a problem printing anything beyond one or more asterisks with
> the float proc.
>
> At first I thought it was just my inexperience / ignorance, so I tried some
> examples from McGettrick:
>
> begin
> puts(float(123.4567,12,5,2));
> puts("'n");
> puts(float(123.4567,-10,5,-1));
> puts("'n");
>
> skip
> end
>
> He suggests this should produce
>
> +12.34567e+1
> 1.23457e2 (blank just in front)
>
> Am I missing something? Thanks in advance!
Hm, perhaps I got the proc wrong from the RR. This is what we have
right now in the standard prelude (libga68/standard.a68.in):
pub proc float = (Number v, int width, after, exp) string:
case v in
{iter L {} {long} {long long}}
{iter L_ {} {long_} {long_long_}}
({L} real x):
if int before = ABS width - ABS exp - (after /= 0 | after+1 | 0) - 2;
SIGN before + SIGN after > 0
then string s, {L} real y := ABS x, int p := 0;
{L_}standardize (y, before, after, p);
s := fixed (SIGN (x * y), SIGN width * (ABS width - ABS exp - 1),
after) + "*^" + whole (p, exp);
if exp = 0 OR char_in_string (errorchar, loc int, s)
then float (x, width, (after /= 0 | after-1 | 0),
(exp > 0 | exp+1 | exp-1))
else s
fi
else { XXX undefined } skip; ABS width * errorchar
fi,
({L} int x): float ({L} real (x), width, after, exp)
{reti {,}}
esac;
The idea was to replace it with van Vliet's:
PROC float = (NUMBER v, INT width, after, exp) STRING:
IF INT abs width = ABS width, sign after = SIGN after,
INT exp places:= ABS exp;
INT last:= abs width - exp places - 2;
INT before:= last - after - sign after;
SIGN before + sign after <= 0
# partial test for correctness of parameters #
THEN 1 MAX abs width * errorchar
ELIF INT first:= 1, exponent:= before, rp:= last + 1;
[-1 : abs width - sign after] CHAR s, BOOL exp sign = exp > 0;
BOOL neg:= subfixed(v, after, exponent, s, TRUE);
# 's[1 : before + after + 2]' contains the relevant
digits, 's[before + 1]' = "." #
exponent -:= before;
# now 'exponent' is the real exponent #
WHILE
IF rp > last
THEN
IF power10(s, rp, last)
THEN first:= 0; s[before]:= ".";
s[before + 1]:= (before = 0 | rp:= 1; "0" | "9");
before -:= 1; last -:= 1; exponent +:= 1
FI
# move the decimal point one place
to the left and adjust the various parameters #
FI;
exp sign EXPLENGTH exponent > exp places AND last >= first
# the exponent does not fit and it is
still possible to sacrifice digits #
DO last -:= 1; exp places +:= 1;
CASE SIGN(last - before - 1) + 2
IN
(before -:= 1; exponent +:= 1),
# "after" = 0, so decrement 'before' #
(before +:= 1; exponent -:= 1;
REF CHAR sb1 = s[before + 1]; s[before]:= sb1; sb1:= ".")
# "after":= 0, so the decimal point also disappears;
as a consequence, 'before' can be incremented #
# OUT "after" is decremented, but still greater than 0 #
ESAC
OD;
last < first # no digits left in mantissa #
THEN abs width * errorchar
ELSE round(s, rp, last);
INT p:= first;
WHILE s[p] = "0" AND s[p + 1] /= "." AND p < last
DO s[p]:= " "; p +:= 1 OD;
# change "000.00" to " 0.00" #
s[p - 1]:= (neg | "-" |: width > 0 | "+" | " ");
s[last +:= 1]:= "e"; INT l = last + exp places;
# convert exponent into 's[last + 1 : l]': #
neg:= subwhole(exponent, last +:= 1, l, s);
(neg OR exp sign | s[last - 1]:= (neg | "-" | "+"));
# place sign of exponent #
s[first - 1 : l]
FI;
More information about the Algol68
mailing list