Arithmetic/Rational: Difference between revisions

From Rosetta Code
Content added Content deleted
m ({{task|Arithmetic operations}})
Line 1: Line 1:
{{task|Arithmetic operations}}
{{task|Arithmetic operations}}
The objective of this task is to create a reasonably complete implementation of
rational arithmetic in the particular language using the idioms of the language.

For example:
Define an new type called '''frac''' with dyadic operator "//" of two integers
Define an new type called '''frac''' with dyadic operator "//" of two integers
that returns a '''structure''' made up of the numerator and the denominator
that returns a '''structure''' made up of the numerator and the denominator
Line 7: Line 11:
with the dyadic '''operators''' for addition '+', subtraction '-',
with the dyadic '''operators''' for addition '+', subtraction '-',
multiplication '×', division '/', integer division '÷', modulo division,
multiplication '×', division '/', integer division '÷', modulo division,
the comparison operators ('<', '&le;', '>', & '&ge;') and equality operators ('=' & '&ne;').
the comparison operators (e.g. '<', '&le;', '>', & '&ge;') and equality operators (e.g. '=' & '&ne;').


Define standard coercion '''operators''' for casting '''int''' to '''frac''' etc.
Define standard coercion '''operators''' for casting '''int''' to '''frac''' etc.


Define standard increment and decrement '''operators''' ('+:=' & '-:=' etc.).
If space allows, define standard increment and decrement '''operators''' (e.g. '+:=' & '-:=' etc.).


Present a simple test each one of the operators above and also use the new type '''frac'''
Finally test the operators:
to find all perfect numbers less then 2<sup>19</sup> by summing the reciprocal of the factors.
Use the new type '''frac''' to find all perfect numbers less then 2<sup>19</sup>
by summing the reciprocal of the factors.
=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==
{{works with|ALGOL 68|Standard - no extensions to language used}}
{{works with|ALGOL 68|Standard - no extensions to language used}}
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386}}
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386}}
<!-- Note: I cannot use <lang=algol> here because algol support UTF-8 characters ÷×≤≥↑ etc sorry -->
<!-- Note: I cannot use <lang=algol> here because algol support UTF-8 characters ÷×≤≥↑ etc sorry -->
MODE FRAC = STRUCT( INT num #erator#, den #ominator#);
<pre>
FORMAT frac repr = $g(-0)"//"g(-0)$;
MODE FRAC = STRUCT( LONG INT num #erator#, den #ominator#);
FORMAT frac repr = $g(-0)"//"g(-0)$;
PROC gcd = (INT a, b) INT: # greatest common divisor #

(a = 0 | b |: b = 0 | a |: ABS a > ABS b | gcd(b, a MOD b) | gcd(a, b MOD a));
PROC gcd = (INT a, b) INT: # greatest common divisor #
(a = 0 | b |: b = 0 | a |: ABS a > ABS b | gcd(b, a MOD b) | gcd(a, b MOD a));
PROC lcm = (INT a, b)INT: # least common multiple #

a OVER gcd(a, b) * b;
PROC long gcd = (LONG INT a, b) LONG INT: # greatest common divisor #
(a = 0 | b |: b = 0 | a |: ABS a > ABS b | long gcd(b, a MOD b) | long gcd(a, b MOD a));
PROC raise not implemented error = ([]STRING args)VOID: (

put(stand error, ("Not implemented error: ",args, newline));
PROC long lcm = (LONG INT a, b)LONG INT: # least common multiple #
stop
a OVER long gcd(a, b) * b;
);

PROC raise not implemented error = ([]STRING args)VOID: (
PRIO // = 9; # higher then the ** operator #
put(stand error, ("Not implemented error: ",args, newline));
OP // = (INT num, den)FRAC: ( # initialise and normalise #
stop
INT common = gcd(num, den);
);
IF den < 0 THEN

( -num OVER common, -den OVER common)
PRIO // = 9; # higher then the ** operator #
ELSE
OP // = (INT num, den)FRAC: ( # initialise and normalise #
INT common = gcd(num, den);
( num OVER common, den OVER common)
FI
IF den < 0 THEN
);
( -num OVER common, -den OVER common)
ELSE
OP + = (FRAC a, b)FRAC: (
( num OVER common, den OVER common)
INT common = lcm(den OF a, den OF b);
FI
FRAC result := ( common OVER den OF a * num OF a + common OVER den OF b * num OF b, common );
);
num OF result//den OF result
OP // = (LONG INT num, den)FRAC: ( # overload LONG version #
);
LONG INT common = long gcd(num, den);
IF den < 0 THEN
OP - = (FRAC a, b)FRAC: a + -b,
( -num OVER common, -den OVER common)
* = (FRAC a, b)FRAC: (
ELSE
( num OVER common, den OVER common)
INT num = num OF a * num OF b,
den = den OF a * den OF b;
FI
INT common = gcd(num, den);
);
(num OVER common) // (den OVER common)

);
OP + = (FRAC a, b)FRAC: (
LONG INT common = long lcm(den OF a, den OF b);
FRAC result := ( common OVER den OF a * num OF a + common OVER den OF b * num OF b, common );
OP / = (FRAC a, b)FRAC: a * FRAC(den OF b, num OF b),# real division #
% = (FRAC a, b)INT: ENTIER (a / b), # integer divison #
num OF result//den OF result
%* = (FRAC a, b)FRAC: a/b - FRACINIT ENTIER (a/b), # modulo division #
);
** = (FRAC a, INT exponent)FRAC:

IF exponent >= 0 THEN
# Monadic - OPerator #
OP - = (FRAC frac)FRAC: (-num OF frac, den OF frac);
(num OF a ** exponent, den OF a ** exponent )
ELSE

(den OF a ** exponent, num OF a ** exponent )
# Diadic - OPerator #
FI;
OP - = (FRAC a, b)FRAC: a + -b;

OP * = (FRAC a, b)FRAC: (
OP REALINIT = (FRAC frac)REAL: num OF frac / den OF frac,
LONG INT num = num OF a * num OF b,
FRACINIT = (INT num)FRAC: num // 1,
den = den OF a * den OF b;
FRACINIT = (REAL num)FRAC: (
# express real number as a fraction # # a future execise! #
LONG INT common = long gcd(num, den);
raise not implemented error(("Convert a REAL to a FRAC","!"));
(num OVER common) // (den OVER common)
SKIP
);
);

OP / = (FRAC a, b)FRAC: a * FRAC(den OF b, num OF b),
% = (FRAC a, b)LONG INT: ENTIER (a / b),
OP < = (FRAC a, b)BOOL: num OF (a - b) < 0,
%* = (FRAC a, b)FRAC: a / b - FRACINIT ENTIER (a / b),
> = (FRAC a, b)BOOL: num OF (a - b) > 0,
** = (FRAC a, INT exponent)FRAC:
<= = (FRAC a, b)BOOL: NOT ( a > b ),
>= = (FRAC a, b)BOOL: NOT ( a < b ),
IF exponent >= 0 THEN
(num OF a ** exponent, den OF a ** exponent )
= = (FRAC a, b)BOOL: (num OF a, den OF a) = (num OF b, den OF b),
/= = (FRAC a, b)BOOL: (num OF a, den OF a) /= (num OF b, den OF b);
ELSE
(den OF a ** exponent, num OF a ** exponent )
# Monadic operators #
FI;
OP - = (FRAC frac)FRAC: (-num OF frac, den OF frac),

OP +:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a + b ),
ABS = (FRAC frac)FRAC: (ABS num OF frac, ABS den OF frac),
+=: = (FRAC a, REF FRAC b)REF FRAC: ( b := a + b ),
ENTIER = (FRAC frac)INT: (num OF frac OVER den OF frac) * den OF frac;
-:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a - b ),
COMMENT Operators for extended characters set, and increment/decrement "commented out" to save space.<!--
*:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a * b ),
/:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a / b ),
OP +:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a + b ),
%:= = (REF FRAC a, FRAC b)REF FRAC: ( a := FRACINIT (a OVER b) ),
+=: = (FRAC a, REF FRAC b)REF FRAC: ( b := a + b ),
%*:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a %* b );
-:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a - b ),
*:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a * b ),

OP < = (FRAC a, b)BOOL: num OF (a - b) < 0,
/:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a / b ),
> = (FRAC a, b)BOOL: num OF (a - b) > 0,
%:= = (REF FRAC a, FRAC b)REF FRAC: ( a := FRACINIT (a % b) ),
<= = (FRAC a, b)BOOL: NOT ( a > b ),
%*:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a %* b );
>= = (FRAC a, b)BOOL: NOT ( a < b ),
# OP aliases for extended character sets (eg: Unicode, APL, ALCOR and GOST 10859) #
= = (FRAC a, b)BOOL: (num OF a, den OF a) = (num OF b, den OF b),
/= = (FRAC a, b)BOOL: (num OF a, den OF a) /= (num OF b, den OF b);
OP × = (FRAC a, b)FRAC: a * b,
÷ = (FRAC a, b)INT: a OVER b,

OP ABS = (FRAC frac)FRAC: (ABS num OF frac, ABS den OF frac),
÷× = (FRAC a, b)FRAC: a MOD b,
ENTIER = (FRAC frac)LONG INT: (num OF frac OVER den OF frac) * den OF frac,
÷* = (FRAC a, b)FRAC: a MOD b,
%× = (FRAC a, b)FRAC: a MOD b,

OP LONGREALINIT = (FRAC frac)LONG REAL: num OF frac / den OF frac,
= (FRAC a, b)FRAC: a <= b,
FRACINIT = (INT num)FRAC: num // 1,
= (FRAC a, b)FRAC: a >= b,
FRACINIT = (LONG INT num)FRAC: num // LONG 1,
= (FRAC a, b)BOOL: a /= b,
FRACINIT = (LONG REAL num)FRAC: (
= (FRAC frac, INT exponent)FRAC: frac ** exponent,
# express real number as a fraction # # a future execise! #
÷×:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a MOD b ),
raise not implemented error(("Convert a LONG REAL to a FRAC","!"));
%×:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a MOD b ),
SKIP
÷*:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a MOD b );
);

# BOLD aliases for CPU that only support uppercase for 6-bit bytes - wrist watches #
COMMENT
OP OVER = (FRAC a, b)INT: a % b,
# OP aliases for extended character sets (eg: Unicode, APL, ALCOR and GOST 10859) #
OP × = (FRAC a, b)FRAC: a * b,
MOD = (FRAC a, b)FRAC: a %*b,
÷ = (FRAC a, b)LONG INT: a OVER b,
LT = (FRAC a, b)BOOL: a < b,
÷× = (FRAC a, b)FRAC: a MOD b,
GT = (FRAC a, b)BOOL: a > b,
÷* = (FRAC a, b)FRAC: a MOD b,
LE = (FRAC a, b)BOOL: a <= b,
= (FRAC a, b)FRAC: a MOD b,
GE = (FRAC a, b)BOOL: a >= b,
= (FRAC a, b)FRAC: a <= b,
EQ = (FRAC a, b)BOOL: a = b,
= (FRAC a, b)FRAC: a >= b,
NE = (FRAC a, b)BOOL: a /= b,
= (FRAC a, b)BOOL: a /= b,
UP = (FRAC frac, INT exponent)FRAC: frac**exponent;
↑ = (FRAC frac, INT exponent)FRAC: frac ** exponent,
# the required standard assignment operators #

÷×:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a MOD b ),
OP PLUSAB = (REF FRAC a, FRAC b)REF FRAC: ( a +:= b ), # PLUS #
%×:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a MOD b ),
PLUSTO = (FRAC a, REF FRAC b)REF FRAC: ( a +=: b ), # PRUS #
÷*:= = (REF FRAC a, FRAC b)REF FRAC: ( a := a MOD b );
MINUSAB = (REF FRAC a, FRAC b)REF FRAC: ( a *:= b ),
DIVAB = (REF FRAC a, FRAC b)REF FRAC: ( a /:= b ),
END COMMENT
OVERAB = (REF FRAC a, FRAC b)REF FRAC: ( a %:= b ),

MODAB = (REF FRAC a, FRAC b)REF FRAC: ( a %*:= b );
# BOLD aliases for CPU that only support uppercase for 6-bit bytes - wrist watches #
OP OVER = (FRAC a, b)LONG INT: a % b,
--> COMMENT
MOD = (FRAC a, b)FRAC: a %*b,
Example: searching for Perfect Numbers.
LT = (FRAC a, b)BOOL: a < b,
GT = (FRAC a, b)BOOL: a > b,
FRAC sum:= FRACINIT 0;
FORMAT perfect = $b(" perfect!","")$;
LE = (FRAC a, b)BOOL: a <= b,
GE = (FRAC a, b)BOOL: a >= b,
FOR i FROM 2 TO 2**19 DO
EQ = (FRAC a, b)BOOL: a = b,
INT candidate := i;
NE = (FRAC a, b)BOOL: a /= b,
FRAC sum := 1 // candidate;
UP = (FRAC frac, INT exponent)FRAC: frac**exponent;
REAL real sum := 1 / candidate;

FOR factor FROM 2 TO ENTIER sqrt(candidate) DO
# the required standard assignment operators #
IF candidate MOD factor = 0 THEN
OP PLUSAB = (REF FRAC a, FRAC b)REF FRAC: ( a +:= b ), # PLUS #
PLUSTO = (FRAC a, REF FRAC b)REF FRAC: ( a +=: b ), # PRUS #
sum := sum + 1 // factor + 1 // ( candidate OVER factor);
real sum +:= 1 / factor + 1 / ( candidate OVER factor)
MINUSAB = (REF FRAC a, FRAC b)REF FRAC: ( a *:= b ),
FI
DIVAB = (REF FRAC a, FRAC b)REF FRAC: ( a /:= b ),
OD;
OVERAB = (REF FRAC a, FRAC b)REF FRAC: ( a %:= b ),
IF den OF sum = 1 THEN
MODAB = (REF FRAC a, FRAC b)REF FRAC: ( a %*:= b );
printf(($"Sum of reciprocal factors of "g(-0)" = "g(-0)" exactly, about "g(0,real width) f(perfect)l$,

candidate, ENTIER sum, real sum, ENTIER sum = 1))
MODE MIXEDFRAC = STRUCT(LONG INT whole, FRAC fraction);
FI
FORMAT mixed frac repr = $g(-0)" "g(-0)"/"g(-0)$;
OD

OP FRACINIT = (MIXEDFRAC frac)FRAC:
(FRACINIT whole OF frac + fraction OF frac ),
MIXEDFRACINIT = (FRAC frac)MIXEDFRAC: (
LONG INT whole = num OF frac OVER den OF frac;
( whole, frac - FRACINIT whole)
);

OP + = (LONG INT whole, FRAC frac)FRAC: FRACINIT whole + frac;

########################################################
# Do the basic test cases for the OPerators +, -, *, / #
########################################################

FORMAT tab=$30k$; # tab to the 30th character #

FRAC la = 2//4, ra = 1//4;
printf(($"Addition: "f(tab)f(frac repr)" + "f(frac repr)" gives "f(frac repr)l$,
la, ra, la + ra));

FRAC lb = 3//4, rb = 2//3;
printf(($"Adding unlike quantities: "f(tab)f(frac repr)" + "f(frac repr)" gives "f(mixed frac repr)l$,
lb, rb, MIXEDFRACINIT(lb + rb)));

FRAC lc = 2//3, rc = 1//2;
printf(($"Subtraction: "f(tab)f(frac repr)" - "f(frac repr)" gives "f(mixed frac repr)l$,
lc, rc, MIXEDFRACINIT(lc - rc)));

FRAC ld = 2//7, rd = 7//8;
printf(($"Multiplication: "f(tab)f(frac repr)" * "f(frac repr)" gives "f(mixed frac repr)l$,
ld, rd, MIXEDFRACINIT(ld * rd)));

FRAC le = FRACINIT 3, re = FRACINIT 3 + 3//4;
printf(($"Mixed numbers: "f(tab)f(mixed frac repr)" * "f(mixed frac repr)" gives "f(mixed frac repr)l$,
MIXEDFRACINIT le, MIXEDFRACINIT re, MIXEDFRACINIT(le * re)));

FRAC lf = 2//3, rf = 2//5;
printf(($"Division: "f(tab)f(frac repr)" / "f(frac repr)" gives "f(mixed frac repr)l$,
lf, rf, MIXEDFRACINIT(lf / rf)));

FORMAT bool repr = $b("Yes","No")$;

FRAC lg = 5//18, rg = 4//17;
printf(($"Comparing fractions"f(tab)
"Q: Is "f(mixed frac repr)" > "f(mixed frac repr)"? - A: "f(bool repr)"!"l$,
MIXEDFRACINIT lg, MIXEDFRACINIT rg, lg > rg));

FRAC frac pi = 355 // 113; # approximately #
MIXEDFRAC mixed frac pi = MIXEDFRACINIT(frac pi);

printf(($"The exact fraction "f(mixed frac repr)" ("f(frac repr)") is approximately equal to "gl$,
mixed frac pi, frac pi, LONGREALINIT(frac pi)));

##################################################################
# Perform a more complicated test searching for Perfect Numbers. #
##################################################################
FRAC sum:= FRACINIT 0;
FORMAT perfect = $b(" perfect!","")$;

FOR i FROM 2 TO 2**19 DO
LONG INT candidate := i;
FRAC sum := LONG 1 // candidate;
LONG REAL real sum := 1 / candidate;
FOR factor FROM 2 TO ENTIER SHORTEN long sqrt(candidate) DO
IF candidate MOD factor = 0 THEN
sum +:= 1 // factor + LONG 1 // ( candidate OVER factor);
real sum +:= LONG 1 / factor + LONG 1 / ( candidate OVER factor)
FI
OD;
IF num OF fraction OF (MIXEDFRACINIT sum) = 0 THEN
printf(($"Sum of reciprocal factors of "g(-0)" = "g(-0)" exactly, about "g(0,long real width) f(perfect)l$,
candidate, ENTIER sum, real sum, ENTIER sum = 1))
FI
OD
</pre>
Output:
Output:
<pre>
<pre>
Addition: 1//2 + 1//4 gives 3//4
Adding unlike quantities: 3//4 + 2//3 gives 1 5/12
Subtraction: 2//3 - 1//2 gives 0 1/6
Multiplication: 2//7 * 7//8 gives 0 1/4
Mixed numbers: 3 0/1 * 3 3/4 gives 11 1/4
Division: 2//3 / 2//5 gives 1 2/3
Comparing fractions Q: Is 0 5/18 > 0 4/17? - A: Yes!
The exact fraction 3 16/113 (355//113) is approximately equal to +3.141592920353982300884955752e +0
Sum of reciprocal factors of 6 = 1 exactly, about 1.0000000000000000000000000001 perfect!
Sum of reciprocal factors of 6 = 1 exactly, about 1.0000000000000000000000000001 perfect!
Sum of reciprocal factors of 28 = 1 exactly, about 1.0000000000000000000000000001 perfect!
Sum of reciprocal factors of 28 = 1 exactly, about 1.0000000000000000000000000001 perfect!

Revision as of 21:43, 13 February 2009

Task
Arithmetic/Rational
You are encouraged to solve this task according to the task description, using any language you may know.

The objective of this task is to create a reasonably complete implementation of rational arithmetic in the particular language using the idioms of the language.

For example: Define an new type called frac with dyadic operator "//" of two integers that returns a structure made up of the numerator and the denominator (as per a rational number).

Further define the appropriate rational monadic operators abs and '-', with the dyadic operators for addition '+', subtraction '-', multiplication '×', division '/', integer division '÷', modulo division, the comparison operators (e.g. '<', '≤', '>', & '≥') and equality operators (e.g. '=' & '≠').

Define standard coercion operators for casting int to frac etc.

If space allows, define standard increment and decrement operators (e.g. '+:=' & '-:=' etc.).

Finally test the operators: Use the new type frac to find all perfect numbers less then 219 by summing the reciprocal of the factors.

ALGOL 68

Works with: ALGOL 68 version Standard - no extensions to language used
Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386
MODE FRAC = STRUCT( INT num #erator#,  den #ominator#);
FORMAT frac repr = $g(-0)"//"g(-0)$;

PROC gcd = (INT a, b) INT: # greatest common divisor #
  (a = 0 | b |: b = 0 | a |: ABS a > ABS b  | gcd(b, a MOD b) | gcd(a, b MOD a));

PROC lcm = (INT a, b)INT: # least common multiple #
  a OVER gcd(a, b) * b;

PROC raise not implemented error = ([]STRING args)VOID: (
  put(stand error, ("Not implemented error: ",args, newline));
  stop
);

PRIO // = 9; # higher then the ** operator #
OP // = (INT num, den)FRAC: ( # initialise and normalise #
  INT common = gcd(num, den);
  IF den < 0 THEN
    ( -num OVER common, -den OVER common)
  ELSE
    ( num OVER common, den OVER common)
  FI
);

OP + = (FRAC a, b)FRAC: (
  INT common = lcm(den OF a, den OF b);
  FRAC result := ( common OVER den OF a * num OF a + common OVER den OF b * num OF b, common );
  num OF result//den OF result
);

OP - = (FRAC a, b)FRAC: a + -b,
   * = (FRAC a, b)FRAC: (
  INT num = num OF a * num OF b,
      den = den OF a * den OF b;
  INT common = gcd(num, den);
  (num OVER common) // (den OVER common)
);

OP /  = (FRAC a, b)FRAC: a * FRAC(den OF b, num OF b),# real division #
   %  = (FRAC a, b)INT: ENTIER (a / b),               # integer divison #
   %* = (FRAC a, b)FRAC: a/b - FRACINIT ENTIER (a/b), # modulo division #
   ** = (FRAC a, INT exponent)FRAC: 
    IF exponent >= 0 THEN
      (num OF a ** exponent, den OF a ** exponent )
    ELSE
      (den OF a ** exponent, num OF a ** exponent )
    FI;

OP REALINIT = (FRAC frac)REAL: num OF frac / den OF frac,
   FRACINIT = (INT num)FRAC: num // 1,
   FRACINIT = (REAL num)FRAC: (
     # express real number as a fraction # # a future execise! #
     raise not implemented error(("Convert a REAL to a FRAC","!"));
     SKIP
   );

OP <  = (FRAC a, b)BOOL: num OF (a - b) <  0,
   >  = (FRAC a, b)BOOL: num OF (a - b) >  0,
   <= = (FRAC a, b)BOOL: NOT ( a > b ),
   >= = (FRAC a, b)BOOL: NOT ( a < b ),
   =  = (FRAC a, b)BOOL: (num OF a, den OF a) = (num OF b, den OF b),
   /= = (FRAC a, b)BOOL: (num OF a, den OF a) /= (num OF b, den OF b);

# Monadic operators #
OP - = (FRAC frac)FRAC: (-num OF frac, den OF frac),
   ABS = (FRAC frac)FRAC: (ABS num OF frac, ABS den OF frac),
   ENTIER = (FRAC frac)INT: (num OF frac OVER den OF frac) * den OF frac;

COMMENT Operators for extended characters set, and increment/decrement "commented out" to save space. COMMENT

Example: searching for Perfect Numbers.

FRAC sum:= FRACINIT 0; 
FORMAT perfect = $b(" perfect!","")$;

FOR i FROM 2 TO 2**19 DO 
  INT candidate := i;
  FRAC sum := 1 // candidate;
  REAL real sum := 1 / candidate;
  FOR factor FROM 2 TO ENTIER sqrt(candidate) DO
    IF candidate MOD factor = 0 THEN
      sum :=  sum + 1 // factor + 1 // ( candidate OVER factor);
      real sum +:= 1 / factor + 1 / ( candidate OVER factor)
    FI
  OD;
  IF den OF sum  = 1 THEN
    printf(($"Sum of reciprocal factors of "g(-0)" = "g(-0)" exactly, about "g(0,real width) f(perfect)l$, 
            candidate, ENTIER sum, real sum, ENTIER sum = 1))
  FI
OD

Output:

Sum of reciprocal factors of 6 = 1 exactly, about 1.0000000000000000000000000001 perfect!
Sum of reciprocal factors of 28 = 1 exactly, about 1.0000000000000000000000000001 perfect!
Sum of reciprocal factors of 120 = 2 exactly, about 2.0000000000000000000000000002
Sum of reciprocal factors of 496 = 1 exactly, about 1.0000000000000000000000000001 perfect!
Sum of reciprocal factors of 672 = 2 exactly, about 2.0000000000000000000000000001
Sum of reciprocal factors of 8128 = 1 exactly, about 1.0000000000000000000000000001 perfect!
Sum of reciprocal factors of 30240 = 3 exactly, about 3.0000000000000000000000000002
Sum of reciprocal factors of 32760 = 3 exactly, about 3.0000000000000000000000000003
Sum of reciprocal factors of 523776 = 2 exactly, about 2.0000000000000000000000000005