Arithmetic/Rational: Difference between revisions

m
(→‎{{header|Groovy}}: various code improvements)
m (→‎{{header|Wren}}: Minor tidy)
 
(88 intermediate revisions by 43 users not shown)
Line 1:
{{task|Arithmetic operations}}[[Category:Arithmetic]]
{{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.
 
;Task:
For example:
Create a reasonably complete implementation of rational arithmetic in the particular language using the idioms of the language.
 
 
;Example:
Define a new type called '''frac''' with binary operator "//" of two integers that returns a '''structure''' made up of the numerator and the denominator (as per a rational number).
 
Line 14 ⟶ 18:
Use the new type '''frac''' to find all [[Perfect Numbers|perfect numbers]] less than 2<sup>19</sup> by summing the reciprocal of the factors.
 
 
'''See also'''
;Related tasks:
* [[Perfect Numbers]]
* &nbsp; [[Perfect Numbers]]
* &nbsp; [[Check Machin-like formulas]]
<br><br>
 
=={{header|Action!}}==
Calculations on a real Atari 8-bit computer take quite long time. It is recommended to use an emulator capable with increasing speed of Atari CPU.
{{libheader|Action! Tool Kit}}
<syntaxhighlight lang="action!">INCLUDE "D2:REAL.ACT" ;from the Action! Tool Kit
 
TYPE Frac=[INT num,den]
 
REAL half
 
PROC PrintFrac(Frac POINTER x)
PrintI(x.num) Put('/) PrintI(x.den)
RETURN
 
INT FUNC Gcd(INT a,b)
INT tmp
 
IF a<b THEN
tmp=a a=b b=tmp
FI
 
WHILE b#0
DO
tmp=a MOD b
a=b
b=tmp
OD
RETURN (a)
 
PROC Init(INT n,d Frac POINTER res)
IF d>0 THEN
res.num=n res.den=d
ELSEIF d<0 THEN
res.num=-n res.den=-d
ELSE
Print("Denominator cannot be zero!")
Break()
FI
RETURN
 
PROC Assign(Frac POINTER x,res)
Init(x.num,x.den,res)
RETURN
 
PROC Neg(Frac POINTER x,res)
Init(-x.num,x.den,res)
RETURN
 
PROC Inverse(Frac POINTER x,res)
Init(x.den,x.num)
RETURN
 
PROC Abs(Frac POINTER x,res)
IF x.num<0 THEN
Neg(x,res)
ELSE
Assign(x,res)
FI
RETURN
 
PROC Add(Frac POINTER x,y,res)
INT common,xDen,yDen
common=Gcd(x.den,y.den)
xDen=x.den/common
yDen=y.den/common
Init(x.num*yDen+y.num*xDen,xDen*y.den,res)
RETURN
 
PROC Sub(Frac POINTER x,y,res)
Frac n
 
Neg(y,n) Add(x,n,res)
RETURN
 
PROC Mult(Frac POINTER x,y,res)
Init(x.num*y.num,x.den*y.den,res)
RETURN
 
PROC Div(Frac POINTER x,y,res)
Frac i
 
Inverse(y,i) Mult(x,i,res)
RETURN
 
BYTE FUNC Greater(Frac POINTER x,y)
Frac diff
 
Sub(x,y,diff)
IF diff.num>0 THEN
RETURN (1)
FI
RETURN (0)
 
BYTE FUNC Less(Frac POINTER x,y)
RETURN (Greater(y,x))
 
BYTE FUNC GreaterEqual(Frac POINTER x,y)
Frac diff
 
Sub(x,y,diff)
IF diff.num>=0 THEN
RETURN (1)
FI
RETURN (0)
 
BYTE FUNC LessEqual(Frac POINTER x,y)
RETURN (GreaterEqual(y,x))
 
BYTE FUNC Equal(Frac POINTER x,y)
Frac diff
 
Sub(x,y,diff)
IF diff.num=0 THEN
RETURN (1)
FI
RETURN (0)
 
BYTE FUNC NotEqual(Frac POINTER x,y)
IF Equal(x,y) THEN
RETURN (0)
FI
RETURN (1)
 
INT FUNC Sqrt(INT x)
REAL r1,r2
 
IF x=0 THEN
RETURN (0)
FI
IntToReal(x,r1)
Power(r1,half,r2)
RETURN (RealToInt(r2))
 
PROC Main()
DEFINE MAXINT="32767"
INT i,f,max2
Frac sum,tmp1,tmp2,tmp3,one
 
Put(125) PutE() ;clear screen
ValR("0.5",half)
Init(1,1,one)
FOR i=2 TO MAXINT
DO
Init(1,i,sum) ;sum=1/i
max2=Sqrt(i)
FOR f=2 TO max2
DO
IF i MOD f=0 THEN
Init(1,f,tmp1) ;tmp1=1/f
Add(sum,tmp1,tmp2) ;tmp2=sum+1/f
Init(f,i,tmp3) ;tmp3=f/i
Add(tmp2,tmp3,sum) ;sum=sum+1/f+f/i
FI
OD
 
IF Equal(sum,one) THEN
PrintF("%I is perfect%E",i)
FI
OD
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Rational.png Screenshot from Atari 8-bit computer]
<pre>
6 is perfect
28 is perfect
496 is perfect
8128 is perfect
</pre>
 
=={{header|Ada}}==
Line 24 ⟶ 200:
{{works with|ALGOL 68|Standard - no extensions to language used}}
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386}}
<langsyntaxhighlight lang="algol68"> MODE FRAC = STRUCT( INT num #erator#, den #ominator#);
FORMAT frac repr = $g(-0)"//"g(-0)$;
Line 154 ⟶ 330:
candidate, ENTIER sum, real sum, ENTIER sum = 1))
FI
OD</langsyntaxhighlight>
{{out}}
<pre>
Line 167 ⟶ 343:
Sum of reciprocal factors of 523776 = 2 exactly, about 2.0000000000000000000000000005
</pre>
 
=={{header|Arturo}}==
 
Arturo comes with built-in support for rational numbers.
 
<syntaxhighlight lang="rebol">a: to :rational [1 2]
b: to :rational [3 4]
 
print ["a:" a]
print ["b:" b]
 
print ["a + b :" a + b]
print ["a - b :" a - b]
print ["a * b :" a * b]
print ["a / b :" a / b]
print ["a // b :" a // b]
print ["a % b :" a % b]
 
print ["reciprocal b:" reciprocal b]
print ["neg a:" neg a]
 
print ["pi ~=" to :rational 3.14]</syntaxhighlight>
 
{{out}}
 
<pre>a: 1/2
b: 3/4
a + b : 5/4
a - b : -1/4
a * b : 3/8
a / b : 2/3
a // b : 2/3
a % b : 1/2
reciprocal b: 4/3
neg a: -1/2
pi ~= 157/50</pre>
 
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
<langsyntaxhighlight lang="bbcbasic"> *FLOAT64
DIM frac{num, den}
DIM Sum{} = frac{}, Kf{} = frac{}, One{} = frac{}
Line 231 ⟶ 443:
a.num /= a : a.den /= a
IF a.den < 0 a.num *= -1 : a.den *= -1
ENDPROC</langsyntaxhighlight>
Output:
<pre>
Line 242 ⟶ 454:
=={{header|C}}==
C does not have overloadable operators. The following implementation <u>''does not define all operations''</u> so as to keep the example short. Note that the code passes around struct values instead of pointers to keep it simple, a practice normally avoided for efficiency reasons.
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#define FMT "%lld"
Line 310 ⟶ 522:
 
return 0;
}</langsyntaxhighlight>
See [[Rational Arithmetic/C]]
 
=={{header|C sharp|C#}}==
<div style="text-align:right;font-size:7pt">''<nowiki>[</nowiki>This section is included from [[Arithmetic/Rational/C sharp|a subpage]] and should be edited there, not here.<nowiki>]</nowiki>''</div>
{{:Arithmetic/Rational/C sharp}}
Line 320 ⟶ 532:
{{libheader|Boost}}
Boost provides a rational number template.
<langsyntaxhighlight lang="cpp">#include <iostream>
#include "math.h"
#include "boost/rational.hpp"
Line 346 ⟶ 558:
}
return 0;
}</langsyntaxhighlight>
 
===Without using external libraries===
<syntaxhighlight lang="c++">
#include <cmath>
#include <cstdint>
#include <iostream>
#include <numeric>
#include <stdexcept>
 
class Rational {
public:
/// Constructors ///
Rational() : numer(0), denom(1) {}
 
Rational(const int64_t number) : numer(number), denom(1) {}
 
Rational(const int64_t& numerator, const int64_t& denominator) : numer(numerator), denom(denominator) {
if ( numer == 0 ) {
denom = 1;
} else if ( denom == 0 ) {
throw std::invalid_argument("Denominator cannot be zero: " + denom);
} else if ( denom < 0 ) {
numer = -numer;
denom = -denom;
}
 
int64_t divisor = std::gcd(numerator, denom);
numer = numer / divisor;
denom = denom / divisor;
}
 
Rational(const Rational& other) : numer(other.numer), denom(other.denom) {}
 
/// Operators ///
Rational& operator=(const Rational& other) {
if ( *this != other ) { numer = other.numer; denom = other.denom; }
return *this;
}
 
bool operator!=(const Rational& other) const { return ! ( *this == other ); }
 
bool operator==(const Rational& other) const {
if ( numer == other.numer && denom == other.denom ) { return true; }
return false;
}
 
Rational& operator+=(const Rational& other) {
*this = Rational(numer* other.denom + other.numer * denom, denom * other.denom);
return *this;
}
 
Rational operator+(const Rational& other) const { return Rational(*this) += other; }
 
Rational& operator-=(const Rational& other) {
Rational temp(other);
temp.numer = -temp.numer;
return *this += temp;
}
Rational operator-(const Rational& other) const { return Rational(*this) -= other; }
 
Rational& operator*=(const Rational& other) {
*this = Rational(numer * other.numer, denom * other.denom);
return *this;
}
Rational operator*(const Rational& other) const { return Rational(*this) *= other; };
 
Rational& operator/=(const Rational other) {
Rational temp(other.denom, other.numer);
*this *= temp;
return *this;
}
 
Rational operator/(const Rational& other) const { return Rational(*this) /= other; };
 
bool operator<(const Rational& other) const { return numer * other.denom < denom * other.numer; }
 
bool operator<=(const Rational& other) const { return ! ( other < *this ); }
 
bool operator>(const Rational& other) const { return other < *this; }
 
bool operator>=(const Rational& other) const { return ! ( *this < other ); }
 
Rational operator-() const { return Rational(-numer, denom); }
 
Rational& operator++() { numer += denom; return *this; }
 
Rational operator++(int) { Rational temp = *this; ++*this; return temp; }
 
Rational& operator--() { numer -= denom; return *this; }
 
Rational operator--(int) { Rational temp = *this; --*this; return temp; }
 
friend std::ostream& operator<<(std::ostream& outStream, const Rational& other) {
outStream << other.numer << "/" << other.denom;
return outStream;
}
 
/// Methods ///
Rational reciprocal() const { return Rational(denom, numer); }
 
Rational positive() const { return Rational(abs(numer), denom); }
 
int64_t to_integer() const { return numer / denom; }
 
double to_double() const { return (double) numer / denom; }
 
int64_t hash() const { return std::hash<int64_t>{}(numer) ^ std::hash<int64_t>{}(denom); }
private:
int64_t numer;
int64_t denom;
};
 
int main() {
std::cout << "Perfect numbers less than 2^19:" << std::endl;
const int32_t limit = 1 << 19;
for ( int32_t candidate = 2; candidate < limit; ++candidate ) {
Rational sum = Rational(1, candidate);
int32_t square_root = (int32_t) sqrt(candidate);
for ( int32_t factor = 2; factor <= square_root; ++factor ) {
if ( candidate % factor == 0 ) {
sum += Rational(1, factor);
sum += Rational(1, candidate / factor);
}
}
 
if ( sum == Rational(1) ) {
std::cout << candidate << std::endl;
}
}
}
</syntaxhighlight>
{{ out }}
<pre>
Perfect numbers less than 2^19:
6
28
496
8128
</pre>
 
=={{header|Clojure}}==
Ratios are built in to Clojure and support math operations already. They automatically reduce and become Integers if possible.
<langsyntaxhighlight Clojurelang="clojure">user> 22/7
22/7
user> 34/2
17
user> (+ 37/5 42/9)
181/15</langsyntaxhighlight>
 
=={{header|Common Lisp}}==
Common Lisp has rational numbers built-in and integrated with all other number types. Common Lisp's number system is not extensible so reimplementing rational arithmetic would require all-new operator names.
<langsyntaxhighlight lang="lisp">(loop for candidate from 2 below (expt 2 19)
for sum = (+ (/ candidate)
(loop for factor from 2 to (isqrt candidate)
Line 365 ⟶ 718:
sum (+ (/ factor) (/ (floor candidate factor)))))
when (= sum 1)
collect candidate)</langsyntaxhighlight>
 
=={{header|D}}==
<langsyntaxhighlight lang="d">import std.bigint, std.traits, std.conv;
 
// std.numeric.gcd doesn't work with BigInt.
Line 551 ⟶ 904:
}
}
}</langsyntaxhighlight>
Use the <code>-version=rational_arithmetic_main</code> compiler switch to run the test code.
{{out}}
Line 564 ⟶ 917:
Sum of recipr. factors of 523776 = 2 exactly.</pre>
Currently RationalT!BigInt is not fast.
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{libheader| Boost.Rational}}[[https://github.com/MaiconSoft/DelphiBoostLib]]
{{Trans|C#}}
<syntaxhighlight lang="delphi">
program Arithmetic_Rational;
 
{$APPTYPE CONSOLE}
 
uses
System.SysUtils,
Boost.Rational;
 
var
sum: TFraction;
max: Integer = 1 shl 19;
candidate, max2, factor: Integer;
 
begin
for candidate := 2 to max - 1 do
begin
sum := Fraction(1, candidate);
max2 := Trunc(Sqrt(candidate));
for factor := 2 to max2 do
begin
if (candidate mod factor) = 0 then
begin
sum := sum + Fraction(1, factor);
sum := sum + Fraction(1, candidate div factor);
end;
end;
if sum = Fraction(1) then
Writeln(candidate, ' is perfect');
end;
Readln;
end.</syntaxhighlight>
{{out}}
<pre>6 is perfect
28 is perfect
496 is perfect
8128 is perfect</pre>
=={{header|EchoLisp}}==
EchoLisp supports rational numbers as native type. "Big" rational i.e bigint/bigint are not supported.
<syntaxhighlight lang="lisp">
;; Finding perfect numbers
(define (sum/inv n) ;; look for div's in [2..sqrt(n)] and add 1/n
(for/fold (acc (/ n)) [(i (in-range 2 (sqrt n)))]
#:break (> acc 1) ; no hope
(when (zero? (modulo n i ))
(set! acc (+ acc (/ i) (/ i n))))))
</syntaxhighlight>
{{out}}
<syntaxhighlight lang="lisp">
;; rational operations
(+ 1/42 1/666) → 59/2331
42/666 → 7/111
(expt 3/4 7) → 2187/16384 ; 3/4 ^7
(/ 6 8) → 3/4 ;; / operator → rational
(// 6 8) → 0.75 ;; // operator → float
(* 6/7 14/12) → 1
 
;; even perfect numbers (up to 100000)
(for [(i (in-range 4 100000 2))] ;; 8 seconds
(when (= (sum/inv i) 1)
(printf "🍏 🍒 🍓 %d is perfect." i)))
 
🍏 🍒 🍓 6 is perfect.
🍏 🍒 🍓 28 is perfect.
🍏 🍒 🍓 496 is perfect.
🍏 🍒 🍓 8128 is perfect.
</syntaxhighlight>
 
=={{header|Elisa}}==
<langsyntaxhighlight Elisalang="elisa">component RationalNumbers;
type Rational;
Rational(Numerator = integer, Denominater = integer) -> Rational;
Line 626 ⟶ 1,050:
else GCD (A, mod(B,A)) ];
 
end component RationalNumbers;</langsyntaxhighlight>
Tests
<langsyntaxhighlight Elisalang="elisa">use RationalNumbers;
 
PerfectNumbers( Limit = integer) -> multi(integer);
Line 641 ⟶ 1,065:
];
 
PerfectNumbers(10000)?</langsyntaxhighlight>
{{out}}
<pre>
Line 650 ⟶ 1,074:
</pre>
 
=={{header|Elixir}}==
<syntaxhighlight lang="elixir">defmodule Rational do
import Kernel, except: [div: 2]
defstruct numerator: 0, denominator: 1
def new(numerator), do: %Rational{numerator: numerator, denominator: 1}
def new(numerator, denominator) do
sign = if numerator * denominator < 0, do: -1, else: 1
{numerator, denominator} = {abs(numerator), abs(denominator)}
gcd = gcd(numerator, denominator)
%Rational{numerator: sign * Kernel.div(numerator, gcd),
denominator: Kernel.div(denominator, gcd)}
end
def add(a, b) do
{a, b} = convert(a, b)
new(a.numerator * b.denominator + b.numerator * a.denominator,
a.denominator * b.denominator)
end
def sub(a, b) do
{a, b} = convert(a, b)
new(a.numerator * b.denominator - b.numerator * a.denominator,
a.denominator * b.denominator)
end
def mult(a, b) do
{a, b} = convert(a, b)
new(a.numerator * b.numerator, a.denominator * b.denominator)
end
def div(a, b) do
{a, b} = convert(a, b)
new(a.numerator * b.denominator, a.denominator * b.numerator)
end
defp convert(a), do: if is_integer(a), do: new(a), else: a
defp convert(a, b), do: {convert(a), convert(b)}
defp gcd(a, 0), do: a
defp gcd(a, b), do: gcd(b, rem(a, b))
end
 
defimpl Inspect, for: Rational do
def inspect(r, _opts) do
"%Rational<#{r.numerator}/#{r.denominator}>"
end
end
 
Enum.each(2..trunc(:math.pow(2,19)), fn candidate ->
sum = 2 .. round(:math.sqrt(candidate))
|> Enum.reduce(Rational.new(1, candidate), fn factor,sum ->
if rem(candidate, factor) == 0 do
Rational.add(sum, Rational.new(1, factor))
|> Rational.add(Rational.new(1, div(candidate, factor)))
else
sum
end
end)
if sum.denominator == 1 do
:io.format "Sum of recipr. factors of ~6w = ~w exactly ~s~n",
[candidate, sum.numerator, (if sum.numerator == 1, do: "perfect!", else: "")]
end
end)</syntaxhighlight>
 
{{out}}
<pre>
Sum of recipr. factors of 6 = 1 exactly perfect!
Sum of recipr. factors of 28 = 1 exactly perfect!
Sum of recipr. factors of 120 = 2 exactly
Sum of recipr. factors of 496 = 1 exactly perfect!
Sum of recipr. factors of 672 = 2 exactly
Sum of recipr. factors of 8128 = 1 exactly perfect!
Sum of recipr. factors of 30240 = 3 exactly
Sum of recipr. factors of 32760 = 3 exactly
Sum of recipr. factors of 523776 = 2 exactly
</pre>
 
=={{header|ERRE}}==
<syntaxhighlight lang="erre">PROGRAM RATIONAL_ARITH
 
!
! for rosettacode.org
!
 
TYPE RATIONAL=(NUM,DEN)
 
DIM SUM:RATIONAL,ONE:RATIONAL,KF:RATIONAL
 
DIM A:RATIONAL,B:RATIONAL
PROCEDURE ABS(A.->A.)
A.NUM=ABS(A.NUM)
END PROCEDURE
 
PROCEDURE NEG(A.->A.)
A.NUM=-A.NUM
END PROCEDURE
 
PROCEDURE ADD(A.,B.->A.)
LOCAL T
T=A.DEN*B.DEN
A.NUM=A.NUM*B.DEN+B.NUM*A.DEN
A.DEN=T
END PROCEDURE
 
PROCEDURE SUB(A.,B.->A.)
LOCAL T
T=A.DEN*B.DEN
A.NUM=A.NUM*B.DEN-B.NUM*A.DEN
A.DEN=T
END PROCEDURE
 
PROCEDURE MULT(A.,B.->A.)
A.NUM*=B.NUM A.DEN*=B.DEN
END PROCEDURE
 
PROCEDURE DIVIDE(A.,B.->A.)
A.NUM*=B.DEN
A.DEN*=B.NUM
END PROCEDURE
 
PROCEDURE EQ(A.,B.->RES%)
RES%=A.NUM*B.DEN=B.NUM*A.DEN
END PROCEDURE
 
PROCEDURE LT(A.,B.->RES%)
RES%=A.NUM*B.DEN<B.NUM*A.DEN
END PROCEDURE
 
PROCEDURE GT(A.,B.->RES%)
RES%=A.NUM*B.DEN>B.NUM*A.DEN
END PROCEDURE
 
PROCEDURE NE(A.,B.->RES%)
RES%=A.NUM*B.DEN<>B.NUM*A.DEN
END PROCEDURE
 
PROCEDURE LE(A.,B.->RES%)
RES%=A.NUM*B.DEN<=B.NUM*A.DEN
END PROCEDURE
 
PROCEDURE GE(A.,B.->RES%)
RES%=A.NUM*B.DEN>=B.NUM*A.DEN
END PROCEDURE
 
PROCEDURE NORMALIZE(A.->A.)
LOCAL A,B,T
A=A.NUM B=A.DEN
WHILE B<>0 DO
T=A
A=B
B=T-B*INT(T/B)
END WHILE
A.NUM/=A A.DEN/=A
IF A.DEN<0 THEN A.NUM*=-1 A.DEN*=-1 END IF
END PROCEDURE
 
BEGIN
ONE.NUM=1 ONE.DEN=1
FOR N=2 TO 2^19-1 DO
SUM.NUM=1 SUM.DEN=N
FOR K=2 TO SQR(N) DO
IF N=K*INT(N/K) THEN
KF.NUM=1 KF.DEN=K
ADD(SUM.,KF.->SUM.)
NORMALIZE(SUM.->SUM.)
KF.DEN=INT(N/K)
ADD(SUM.,KF.->SUM.)
NORMALIZE(SUM.->SUM.)
END IF
END FOR
EQ(SUM.,ONE.->RES%)
IF RES% THEN PRINT(N;" is perfect") END IF
END FOR
END PROGRAM</syntaxhighlight>
{{out}}
<pre> 6 is perfect
28 is perfect
496 is perfect
8128 is perfect
</pre>
 
=={{header|F_Sharp|F#}}==
The F# Powerpack library defines the BigRational data type.
<langsyntaxhighlight lang="fsharp">type frac = Microsoft.FSharp.Math.BigRational
 
let perf n = 1N = List.fold (+) 0N (List.map (fun i -> if n % i = 0 then 1N/frac.FromInt(i) else 0N) [2..n])
 
for i in 1..(1<<<19) do if (perf i) then printfn "%i is perfect" i</langsyntaxhighlight>
 
=={{header|Factor}}==
<code>ratio</code> is a built-in numeric type.
<syntaxhighlight lang="factor">USING: generalizations io kernel math math.functions
math.primes.factors math.ranges prettyprint sequences ;
IN: rosetta-code.arithmetic-rational
 
2/5 ! literal syntax 2/5
2/4 ! automatically simplifies to 1/2
5/1 ! automatically coerced to 5
26/5 ! mixed fraction 5+1/5
13/178 >fraction ! get the numerator and denominator 13 178
8 recip ! get the reciprocal 1/8
 
! ratios can be any size
12417829731289312/61237812937138912735712
8 ndrop ! clear the stack
! arithmetic works the same as any other number.
 
: perfect? ( n -- ? )
divisors rest [ recip ] map-sum 1 = ;
 
"Perfect numbers <= 2^19: " print
2 19 ^ [1,b] [ perfect? ] filter .</syntaxhighlight>
{{out}}
<pre>
Perfect numbers <= 2^19:
V{ 6 28 496 8128 }
</pre>
 
=={{header|Fermat}}==
Fermat supports rational aritmetic natively.
<syntaxhighlight lang="fermat">
for n=2 to 2^19 by 2 do
s:=3/n;
m:=1;
while m<=n/3 do
if Divides(m,n) then s:=s+1/m; fi;
m:=m+1;
od;
if s=2 then !!n fi;
od;</syntaxhighlight>
{{out}}
<pre>
6
28
496
8128
</pre>
 
=={{header|Forth}}==
<langsyntaxhighlight lang="forth">\ Rationals can use any double cell operations: 2!, 2@, 2dup, 2swap, etc.
\ Uses the stack convention of the built-in "*/" for int * frac -> int
 
Line 697 ⟶ 1,354:
 
: rat-inc tuck + swap ;
: rat-dec tuck - swap ;</langsyntaxhighlight>
 
=={{header|Fortran}}==
{{works with|Fortran|90 and later}}
<langsyntaxhighlight lang="fortran">module module_rational
 
implicit none
Line 936 ⟶ 1,593:
end function rational_modulo
 
end module module_rational</langsyntaxhighlight>
Example:
<langsyntaxhighlight lang="fortran">program perfect_numbers
 
use module_rational
Line 965 ⟶ 1,622:
end do
 
end program perfect_numbers</langsyntaxhighlight>
{{out}}
<pre>6
Line 971 ⟶ 1,628:
496
8128</pre>
 
=={{header|Frink}}==
Rational numbers are built into Frink and the numerator and denominator can be arbitrarily-sized. They are automatically simplified and collapsed into integers if necessary. All functions in the language can work with rational numbers. Rational numbers are treated as exact. Rational numbers can exist in complex numbers or intervals.
<syntaxhighlight lang="frink">
1/2 + 2/3
// 7/6 (approx. 1.1666666666666667)
 
1/2 + 1/2
// 1
 
5/sextillion + 3/quadrillion
// 600001/200000000000000000000 (exactly 3.000005e-15)
 
8^(1/3)
// 2 (note the exact integer result.)
</syntaxhighlight>
 
=={{header|GAP}}==
Rational numbers are built-in.
<langsyntaxhighlight lang="gap">2/3 in Rationals;
# true
2/3 + 3/4;
# 17/12</langsyntaxhighlight>
 
=={{header|Go}}==
Line 992 ⟶ 1,665:
 
Code here implements the perfect number test described in the task using the standard library.
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,023 ⟶ 1,696:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,039 ⟶ 1,712:
=={{header|Groovy}}==
Groovy does not provide any built-in facility for rational arithmetic. However, it does support arithmetic operator overloading. Thus it is not too hard to build a fairly robust, complete, and intuitive rational number class, such as the following:
<langsyntaxhighlight lang="groovy">class Rational extends Number implements Comparable {
final BigInteger num, denom
 
Line 1,047 ⟶ 1,720:
Rational(BigDecimal decimal) {
this(
decimal.scale() < 0 ? decimal.unscaledValue() * 10 **( -decimal.scale()) : decimal.unscaledValue(),
decimal.scale() < 0 ? 1 : 10 **( decimal.scale()))
)
}
 
Line 1,057 ⟶ 1,731:
 
private List reduce(BigInteger n, BigInteger d) {
BigInteger sign = ((n < 0) !=^ (d < 0)) ? -1 : 1
(n, d) = [n.abs(), d.abs()]
BigInteger commonFactor = gcd(n, d)
Line 1,064 ⟶ 1,738:
}
 
public Rational toLeastTerms() { reduce(num, denom) as Rational }
 
private BigInteger gcd(BigInteger n, BigInteger m) {
Line 1,124 ⟶ 1,798:
Object asType(Class type) {
switch (type) {
case this.getClass()class: return this
case [Boolean.class, Boolean.TYPE]: return asBoolean()
case BigDecimal.class: return toBigDecimal()
case BigInteger.class: return toBigInteger()
case [Double.class, Double.TYPE]: return toDouble()
case [Float.class, Float.TYPE]: return toFloat()
case [Integer.class, Integer.TYPE]: return toInteger()
case [Long.class, Long.TYPE]: return toLong()
case String.class: return toString()
default: throw new ClassCastException("Cannot convert from type Rational to type " + type)
}
Line 1,140 ⟶ 1,814:
 
int compareTo(o) {
o instanceof Rational \
? compareTo(o as Rational) \
: o instanceof Number \
? compareTo(o as Number)\
: (Double.NaN as int)
}
Line 1,154 ⟶ 1,828:
"${num}//${denom}"
}
}</langsyntaxhighlight>
 
The following ''RationalCategory'' class allows for modification of regular ''Number'' behavior when interacting with ''Rational''.
<langsyntaxhighlight lang="groovy">import org.codehaus.groovy.runtime.DefaultGroovyMethods
 
class RationalCategory {
Line 1,170 ⟶ 1,844:
: DefaultGroovyMethods.asType(a, type)
}
}</langsyntaxhighlight>
 
Test Program (mixes the ''RationalCategory'' methods into the ''Number'' class):
<langsyntaxhighlight lang="groovy">Number.metaClass.mixin RationalCategory
 
def x = [5, 20] as Rational
Line 1,259 ⟶ 1,933:
catch (Throwable t) { println t.message }
try { println (α as char) }
catch (Throwable t) { println t.message }</langsyntaxhighlight>
{{out}}
<pre style="height:30ex;overflow:scroll;">1//4
Line 1,316 ⟶ 1,990:
</pre>
The following uses the ''Rational'' class, with ''RationalCategory'' mixed into ''Number'', to find all perfect numbers less than 2<sup>19</sup>:
<langsyntaxhighlight lang="groovy">Number.metaClass.mixin RationalCategory
 
def factorize = { target ->
Line 1,340 ⟶ 2,014:
def trackProgress = { if ((it % (100*1000)) == 0) { println it } else if ((it % 1000) == 0) { print "." } }
 
(1..(2**19)).findResults { trackProgress(it); perfect(it) }.each { println(); print it }</langsyntaxhighlight>
{{out}}
<pre>...................................................................................................100000
Line 1,355 ⟶ 2,029:
=={{header|Haskell}}==
Haskell provides a <code>Rational</code> type, which is really an alias for <code>Ratio Integer</code> (<code>Ratio</code> being a polymorphic type implementing rational numbers for any <code>Integral</code> type of numerators and denominators). The fraction is constructed using the <code>%</code> operator.
<langsyntaxhighlight lang="haskell">import Data.Ratio ((%))
 
-- simplyPrints printsthe allfirst theN perfect numbers.
main = mapM_ print [candidatedo
let n = 4
| candidate <- [2 .. 2^19],
mapM_ print $
getSum candidate == 1]
take
where getSum candidate = 1 % candidate +
n
sum [1 % factor + 1 % (candidate `div` factor)
[ candidate
| factor <- [2 .. floor(sqrt(fromIntegral(candidate)))],
| candidate <- [2 .. 2 ^ 19]
candidate `mod` factor == 0]</lang>
, getSum candidate == 1 ]
where
getSum candidate =
1 % candidate +
sum
[ 1 % factor + 1 % (candidate `div` factor)
| factor <- [2 .. floor (sqrt (fromIntegral candidate))]
, candidate `mod` factor == 0 ]
</syntaxhighlight>
 
For a sample implementation of <code>Ratio</code>, see [http://www.haskell.org/onlinereport/ratio.html the Haskell 98 Report].
Line 1,376 ⟶ 2,059:
Additional procedures are implemented here to complete the task:
* 'makerat' (make), 'absrat' (abs), 'eqrat' (=), 'nerat' (~=), 'ltrat' (<), 'lerat' (<=), 'gerat' (>=), 'gtrat' (>)
<langsyntaxhighlight Iconlang="icon">procedure main()
limit := 2^19
 
Line 1,409 ⟶ 2,092:
if rsum.numer = rsum.denom = 1 then
return c
end</langsyntaxhighlight>
{{out}}
<pre>Perfect numbers up to 524288 (using rational arithmetic):
Line 1,426 ⟶ 2,109:
Testing absrat( (-1/1), ) ==> returned (1/1)</pre>
The following task functions are missing from the IPL:
<langsyntaxhighlight Iconlang="icon">procedure verifyrat(p,r1,r2) #: verification tests for rational procedures
return write("Testing ",p,"( ",rat2str(r1),", ",rat2str(\r2) | &null," ) ==> ","returned " || rat2str(p(r1,r2)) | "failed")
end
Line 1,486 ⟶ 2,169:
end
 
link rational</langsyntaxhighlight>
The {{libheader|Icon Programming Library}} provides [http://www.cs.arizona.edu/icon/library/src/procs/rational.icn rational] and [http://www.cs.arizona.edu/icon/library/src/procs/numbers.icn gcd in numbers]. Record definition and usage is shown below:
<langsyntaxhighlight Iconlang="icon"> record rational(numer, denom, sign) # rational type
 
addrat(r1,r2) # Add rational numbers r1 and r2.
Line 1,502 ⟶ 2,185:
subrat(r1,r2) # Subtract rational numbers r1 and r2.
 
gcd(i, j) # returns greatest common divisor of i and j</langsyntaxhighlight>
 
=={{header|J}}==
Rational numbers in J may be formed from fixed precision integers by first upgrading them to arbitrary precision integers and then dividing them:
J implements rational numbers:
<syntaxhighlight lang="j"> (x: 3) % (x: -4)
<lang j> 3r4*2r5
_3r4
3r10</lang>
3 %&x: -4
_3r4</syntaxhighlight>
Note that the syntax is analogous to the syntax for floating point numbers, but uses <code>r</code> to separate the numerator and denominator instead of <code>e</code> to separate the mantissa and exponent.
Thus:
<syntaxhighlight lang="j">
| _3r4 NB. absolute value
3r4
-2r5 NB. negation
_2r5
3r4+2r5 NB. addition
23r20
3r4-2r5 NB. subtraction
7r20
3r4*2r5 NB. multiplication
3r10
3r4%2r5 NB. division
15r8
3r4 <.@% 2r5 NB. integer division
1
3r4 (-~ <.)@% 2r5 NB. remainder
_7r8
3r4 < 2r5 NB. less than
0
3r4 <: 2r5 NB. less than or equal
0
3r4 > 2r5 NB. greater than
1
3r4 >: 2r5 NB. greater than or equal
1
3r4 = 2r5 NB. equal
0
3r4 ~: 2r5 NB. not equal
1</syntaxhighlight>
 
You can also coerce numbers directly to rational using x: (or to integer or floating point as appropriate using its inverse)
 
<syntaxhighlight lang="j"> x: 3%4
3r4
x:inv 3%4
0.75</syntaxhighlight>
 
Increment and decrement are also included in the language, but you could just as easily add or subtract 1:
 
<syntaxhighlight lang="j"> >: 3r4
7r4
<: 3r4
_1r4</syntaxhighlight>
 
J does not encourage the use of specialized mutators, but those could also be defined:
 
<syntaxhighlight lang="j">mutadd=:adverb define
(m)=: (".m)+y
)
 
mutsub=:adverb define
(m)=: (".m)-y
)</syntaxhighlight>
 
Note that the name whose association is being modified in this fashion needs to be quoted (or you can use an expression to provide the name):
 
<syntaxhighlight lang="j"> n=: 3r4
'n' mutadd 1
7r4
'n' mutsub 1
3r4
'n' mutsub 1
_1r4</syntaxhighlight>
 
(Bare words to the immediate left of the assignment operator are implicitly quoted - but this is just syntactic sugar because that is such an overwhelmingly common case.)
 
That said, note that J's floating point numbers work just fine for the stated problem:
<langsyntaxhighlight lang="j"> is_perfect_rational=: 2 = (1 + i.) +/@:%@([ #~ 0 = |) ]</langsyntaxhighlight>
Faster version (but the problem, as stated, is still tremendously inefficient):
<langsyntaxhighlight lang="j">factors=: */&>@{@((^ i.@>:)&.>/)@q:~&__
is_perfect_rational=: 2= +/@:%@,@factors</langsyntaxhighlight>
Exhaustive testing would take forever:
<langsyntaxhighlight lang="j"> I.is_perfect_rational@"0 i.2^19
6 28 496 8128
I.is_perfect_rational@x:@"0 i.2^19x
6 28 496 8128</langsyntaxhighlight>
More limited testing takes reasonable amounts of time:
<langsyntaxhighlight lang="j"> (#~ is_perfect_rational"0) (* <:@+:) 2^i.10x
6 28 496 8128</langsyntaxhighlight>
 
=={{header|Java}}==
Uses BigRational class: [[Arithmetic/Rational/Java]]
<langsyntaxhighlight lang="java">public class BigRationalFindPerfectNumbers {
public static void main(String[] args) {
int MAX_NUM = 1 << 19;
System.out.println("Running BigRational built-in tests");
System.out.println("Searching for perfect numbers in the range [1, " + (MAX_NUM - 1) + "]");
if (BigRational.testFeatures()) {
 
int MAX_NUM = (1 << 19);
BigRational TWO = BigRational.valueOf(2);
System.out.println();
System.out.println("Searching for perfect(int numbersi in= the range [1,; "i +< (MAX_NUM; - 1i++) + "]");{
BigRational TWOreciprocalSum = BigRational.valueOf(2)ONE;
for (int i = 1; if (i <> MAX_NUM; i++1) {
BigRational reciprocalSum = reciprocalSum.add(BigRational.ONEvalueOf(i).reciprocal());
if (i > 1 int maxDivisor = (int) Math.sqrt(i);
if (maxDivisor >= i)
reciprocalSum = reciprocalSum.add(BigRational.valueOf(i).reciprocal());
int maxDivisor = (int)Math.sqrt(i) maxDivisor--;
 
if (maxDivisor >= i)
for (int divisor = 2; divisor <= maxDivisor--; divisor++) {
for (int divisor = 2; divisor <= maxDivisor; if (i % divisor++ == 0) {
reciprocalSum = reciprocalSum.add(BigRational.valueOf(divisor).reciprocal());
if ((i % divisor) == 0) {
reciprocalSum int dividend = reciprocalSum.add(BigRational.valueOf(i / divisor).reciprocal());
int dividend = i / if (divisor; != dividend)
if (divisor ! reciprocalSum = reciprocalSum.add(BigRational.valueOf(dividend).reciprocal());
}
reciprocalSum = reciprocalSum.add(BigRational.valueOf(dividend).reciprocal());
}
if (reciprocalSum.equals(TWO))
System.out.println(String.valueOf(i) + " is a perfect number");
}
if (reciprocalSum.equals(TWO))
System.out.println(String.valueOf(i) + " is a perfect number");
}
}
}</syntaxhighlight>
return;
}
}</lang>
{{out}}
<pre>Searching for perfect numbers in the range [1, 524287]
<pre>Running BigRational built-in tests
PASS: BaseConstructor-1
PASS: BaseConstructor-2
PASS: BaseConstructor-3
PASS: BaseConstructor-4
PASS: Inequality-1
PASS: Inequality-2
PASS: IntegerConstructor-1
PASS: IntegerConstructor-2
...(omitted for brevity)...
PASS: Reciprocal-4
PASS: Signum-1
PASS: Signum-2
PASS: Signum-3
PASS: Numerator-1
PASS: Numerator-2
PASS: Denominator-1
PASS: Denominator-2
Passed all tests
 
Searching for perfect numbers in the range [1, 524287]
6 is a perfect number
28 is a perfect number
Line 1,585 ⟶ 2,315:
{{:Arithmetic/Rational/JavaScript}}
 
=={{header|Luajq}}==
{{works with|jq}}
<lang lua>function gcd(a,b) return a == 0 and b or gcd(b % a, a) end
'''Works with gojq, the Go implementation of jq'''
 
In this entry, a jq module for rational arithmetic is first
do
presented. It can be included or imported using jq's "include" or
local function coerce(a, b)
"import" directives. The module includes functions for taking
if type(a) == "number" then return rational(a, 1), b end
square roots and for converting a rational to a decimal string
if type(b) == "number" then return a, rational(b, 1) end
or decimal string approximation,
return a, b
and is sufficient for the jq solution at [[Faulhaber%27s_triangle#jq]].
end
rational = setmetatable({
__add = function(a, b)
local a, b = coerce(a, b)
return rational(a.num * b.den + a.den * b.num, a.den * b.den)
end,
__sub = function(a, b)
local a, b = coerce(a, b)
return rational(a.num * b.den - a.den * b.num, a.den * b.den)
end,
__mul = function(a, b)
local a, b = coerce(a, b)
return rational(a.num * b.num, a.den * b.den)
end,
__div = function(a, b)
local a, b = coerce(a, b)
return rational(a.num * b.den, a.den * b.num)
end,
__pow = function(a, b)
if type(a) == "number" then return a ^ (b.num / b.den) end
return rational(a.num ^ b, a.den ^ b) --runs into a problem if these aren't integers
end,
__concat = function(a, b)
if getmetatable(a) == rational then return a.num .. "/" .. a.den .. b end
return a .. b.num .. "/" .. b.den
end,
__unm = function(a) return rational(-a.num, -a.den) end}, {
__call = function(z, a, b) return setmetatable({num = a / gcd(a, b),den = b / gcd(a, b)}, z) end} )
end
 
The constructor is named "r" rather than "frac", mainly because "r" is
print(rational(2, 3) + rational(3, 5) - rational(1, 10) .. "") --> 7/6
short and handy for what is here more than a simple constructor (it
print((rational(4, 5) * rational(5, 9)) ^ rational(1, 2) .. "") --> 2/3
can also be used for normalization and to divide one rational by
print(rational(45, 60) / rational(5, 2) .. "") --> 3/10
another), and because name conflicts can easily be resolved using jq's
print(5 + rational(1, 3) .. "") --> 16/3
module system.
 
The other operators for working with rationals also begin with the letter "r":
function findperfs(n)
 
local ret = {}
'''Comparisons'''
for i = 1, n do
*`requal`, `rgreaterthan`, `rgreaterthanOrEqual`, `rlessthan`, `rlessthanOrEqual`
sum = rational(1, i)
 
for fac = 2, i^.5 do
'''Printing'''
if i % fac == 0 then
* `rpp` for pretty-printing
sum = sum + rational(1, fac) + rational(fac, i)
* `r_to_decimal` for a decimal string representation
end
 
'''Unary'''
* `rabs` for unary `abs`
* `rfloor` like `floor`
* `rinv` for unary inverse
* `rminus` for unary minus
* `rround` for rounding
 
'''Arithmetic'''
* `radd` for addition
* `rminus` for subtraction
* `rmult` for multiplication
* `rdiv` for division
* `rsqrt` for square roots
<br>
In the following notes, "Rational" refers to a reduced-form rational
represented by a JSON object of the form {n:$n, d:$d} where
n signifies the numerator and d the denominator, and $d > 0.
 
The notation `$p // $q` is also used, and this is the form used for
pretty-printing by the filter rpp/0.
 
All the "r"-prefixed functions defined here are polymorphic in the
sense that an integer or rational can be used where a Rational
would normally be expected. This may be especially useful
in the case of requal/2.
 
'''module {"name": "Rational"};'''
<syntaxhighlight lang="jq"># a and b are assumed to be non-zero integers
def gcd(a; b):
# subfunction expects [a,b] as input
# i.e. a ~ .[0] and b ~ .[1]
def rgcd: if .[1] == 0 then .[0]
else [.[1], .[0] % .[1]] | rgcd
end;
[a,b] | rgcd;
 
# To take advantage of gojq's support for accurate integer division:
def idivide($j):
. as $i
| ($i % $j) as $mod
| ($i - $mod) / $j ;
 
# To take advantage of gojq's arbitrary-precision integer arithmetic:
def power($b): . as $in | reduce range(0;$b) as $i (1; . * $in);
 
# $p should be an integer or a rational
# $q should be a non-zero integer or a rational
# Output: a Rational: $p // $q
def r($p;$q):
def r: if type == "number" then {n: ., d: 1} else . end;
# The remaining subfunctions assume all args are Rational
def n: if .d < 0 then {n: -.n, d: -.d} else . end;
def rdiv($a;$b):
($a.d * $b.n) as $denom
| if $denom==0 then "r: division by 0" | error
else r($a.n * $b.d; $denom)
end;
if $q == 1 and ($p|type) == "number" then {n: $p, d: 1}
elif $q == 0 then "r: denominator cannot be 0" | error
else if ($p|type == "number") and ($q|type == "number")
then gcd($p;$q) as $g
| {n: ($p/$g), d: ($q/$g)} | n
else rdiv($p|r; $q|r)
end
end;
 
# Polymorphic (integers and rationals in general)
def requal($a; $b):
if $a | type == "number" and $b | type == "number" then $a == $b
else r($a;1) == r($b;1)
end;
 
# Input: a Rational
# Output: a Rational with a denominator that has no more than $digits digits
# and such that |rBefore - rAfter| < 1/(10|power($digits)
# where $digits should be a positive integer.
def rround($digits):
if .d | length > $digits
then (10|power($digits)) as $p
| .d as $d
| r($p * .n | idivide($d); $p)
else . end;
 
# Polymorphic; see also radd/0
def radd($a; $b):
def r: if type == "number" then {n: ., d: 1} else . end;
($a|r) as {n: $na, d: $da}
| ($b|r) as {n: $nb, d: $db}
| r( ($na * $db) + ($nb * $da); $da * $db );
 
# Polymorphic; see also rmult/0
def rmult($a; $b):
def r: if type == "number" then {n: ., d: 1} else . end;
($a|r) as {n: $na, d: $da}
| ($b|r) as {n: $nb, d: $db}
| r( $na * $nb; $da * $db ) ;
 
# Input: an array of rationals (integers and/or Rationals)
# Output: a Rational computed using left-associativity
def rmult:
if length == 0 then r(1;1)
elif length == 1 then r(.[0]; 1) # ensure the result is Rational
else .[0] as $first
| reduce .[1:][] as $x ($first; rmult(.; $x))
end;
 
# Input: an array of rationals (integers and/or Rationals)
# Output: a Rational computed using left-associativity
def radd:
if length == 0 then r(0;1)
elif length == 1 then r(.[0]; 1) # ensure the result is Rational
else .[0] as $first
| reduce .[1:][] as $x ($first; radd(. ; $x))
end;
 
def rabs: r(.;1) | r(.n|length; .d|length);
 
def rminus: r(-1 * .n; .d);
 
def rminus($a; $b): radd($a; rmult(-1; $b));
 
# Note that rinv does not check for division by 0
def rinv: r(1; .);
 
def rdiv($a; $b): r($a; $b);
 
# Input: an integer or a Rational, $p
# Output: $p < $q
def rlessthan($q):
# lt($b) assumes . and $b have the same sign
def lt($b):
. as $a
| ($a.n * $b.d) < ($b.n * $a.d);
 
if $q|type == "number" then rlessthan(r($q;1))
else if type == "number" then r(.;1) else . end
| if .n < 0
then if ($q.n >= 0) then true
else . as $p | ($q|rminus | rlessthan($p|rminus))
end
else lt($q)
end
end;
if sum.den == sum.num then
 
ret[#ret + 1] = i
def rgreaterthan($q):
. as $p | $q | rlessthan($p);
 
def rlessthanOrEqual($q): requal(.;$q) or rlessthan($q);
def rgreaterthanOrEqual($q): requal(.;$q) or rgreaterthan($q);
 
# Input: non-negative integer or Rational
def rsqrt(precision):
r(.;1) as $n
| (precision + 1) as $digits
| def update: rmult( r(1;2); radd(.x; rdiv($n; .x))) | rround($digits);
 
| def update: rmult( r(1;2); radd(.x; rdiv($n; .x)));
 
r(1; 10|power(precision)) as $p
| { x: .}
| .root = update
| until( rminus(.root; .x) | rabs | rlessthan($p);
.x = .root
| .root = update )
| .root ;
 
# Use native floats
# q.v. r_to_decimal(precision)
def r_to_decimal: .n / .d;
 
# Input: a Rational, or {n, d} in general, or an integer.
# Output: a string representation of the input as a decimal number.
# If the input is a number, it is simply converted to a string.
# Otherwise, $precision determines the number of digits after the decimal point,
# obtained by truncating, but trailing 0s are omitted.
# Examples assuming $digits is 5:
# -0//1 => "0"
# 2//1 => "2"
# 1//2 => "0.5"
# 1//3 => "0.33333"
# 7//9 => "0.77777"
# 1//100 => "0.01"
# -1//10 => "-0.1"
# 1//1000000 => "0."
def r_to_decimal($digits):
if .n == 0 # captures the annoying case of -0
then "0"
elif type == "number" then tostring
elif .d < 0 then {n: -.n, d: -.d}|r_to_decimal($digits)
elif .n < 0
then "-" + ((.n = -.n) | r_to_decimal($digits))
else (10|power($digits)) as $p
| .d as $d
| if $d == 1 then .n|tostring
else ($p * .n | idivide($d) | tostring) as $n
| ($n|length) as $nlength
| (if $nlength > $digits then $n[0:$nlength-$digits] + "." + $n[$nlength-$digits:]
else "0." + ("0"*($digits - $nlength) + $n)
end) | sub("0+$";"")
end
end;
 
return table.concat(ret, '\n')
# Assume . is an integer or in canonical form
end
def rfloor:
print(findperfs(2^19))</lang>
if type == "number" then r(.;1)
elif 0 == .n or (0 < .n and .n < .d) then r(0;1)
elif 0 < .n or (.n % .d == 0) then .d as $d | r(.n | idivide($d); 1)
else rminus( r( - .n; .d) | rfloor | rminus; 1)
end;
 
# pretty print ala Julia
def rpp: "\(.n) // \(.d)";</syntaxhighlight>
 
'''Perfect Numbers'''
<syntaxhighlight lang="jq">
# divisors as an unsorted stream
def divisors:
if . == 1 then 1
else . as $n
| label $out
| range(1; $n) as $i
| ($i * $i) as $i2
| if $i2 > $n then break $out
else if $i2 == $n
then $i
elif ($n % $i) == 0
then $i, ($n/$i)
else empty
end
end
end;
 
def is_perfect:
requal(2; [divisors | r(1;. )] | radd);
# Example:
range(1;pow(2;19)) | select( is_perfect )
</syntaxhighlight>
{{out}}
<pre>
6
28
496
8128
</pre>
 
=={{header|Julia}}==
Julia has native support for rational numbers. Rationals are expressed as <tt>m//n</tt>, where <tt>m</tt> and <tt>n</tt> are integers. In addition to supporting most of the usual mathematical functions in a natural way on rationals, the methods <tt>num</tt> and <tt>den</tt> provide the fully reduced numerator and denominator of a rational value.
{{works with|Julia|1.2}}
<syntaxhighlight lang="julia">using Primes
divisors(n) = foldl((a, (p, e)) -> vcat((a * [p^i for i in 0:e]')...), factor(n), init=[1])
 
isperfect(n) = sum(1 // d for d in divisors(n)) == 2
 
lo, hi = 2, 2^19
println("Perfect numbers between ", lo, " and ", hi, ": ", collect(filter(isperfect, lo:hi)))
</syntaxhighlight>
 
{{out}}
<pre>
Perfect numbers between 2 and 524288: [6, 28, 496, 8128]
</pre>
 
=={{header|Kotlin}}==
As it's not possible to define arbitrary symbols such as // to be operators in Kotlin, we instead use infix functions idiv (for Ints) and ldiv (for Longs) as a shortcut to generate Frac instances.
<syntaxhighlight lang="scala">// version 1.1.2
 
fun gcd(a: Long, b: Long): Long = if (b == 0L) a else gcd(b, a % b)
 
infix fun Long.ldiv(denom: Long) = Frac(this, denom)
 
infix fun Int.idiv(denom: Int) = Frac(this.toLong(), denom.toLong())
 
fun Long.toFrac() = Frac(this, 1)
 
fun Int.toFrac() = Frac(this.toLong(), 1)
 
class Frac : Comparable<Frac> {
val num: Long
val denom: Long
 
companion object {
val ZERO = Frac(0, 1)
val ONE = Frac(1, 1)
}
constructor(n: Long, d: Long) {
require(d != 0L)
var nn = n
var dd = d
if (nn == 0L) {
dd = 1
}
else if (dd < 0) {
nn = -nn
dd = -dd
}
val g = Math.abs(gcd(nn, dd))
if (g > 1) {
nn /= g
dd /= g
}
num = nn
denom = dd
}
 
constructor(n: Int, d: Int) : this(n.toLong(), d.toLong())
operator fun plus(other: Frac) =
Frac(num * other.denom + denom * other.num, other.denom * denom)
 
operator fun unaryPlus() = this
 
operator fun unaryMinus() = Frac(-num, denom)
 
operator fun minus(other: Frac) = this + (-other)
 
operator fun times(other: Frac) = Frac(this.num * other.num, this.denom * other.denom)
 
operator fun rem(other: Frac) = this - Frac((this / other).toLong(), 1) * other
 
operator fun inc() = this + ONE
operator fun dec() = this - ONE
 
fun inverse(): Frac {
require(num != 0L)
return Frac(denom, num)
}
 
operator fun div(other: Frac) = this * other.inverse()
fun abs() = if (num >= 0) this else -this
 
override fun compareTo(other: Frac): Int {
val diff = this.toDouble() - other.toDouble()
return when {
diff < 0.0 -> -1
diff > 0.0 -> +1
else -> 0
}
}
 
override fun equals(other: Any?): Boolean {
if (other == null || other !is Frac) return false
return this.compareTo(other) == 0
}
 
override fun hashCode() = num.hashCode() xor denom.hashCode()
 
override fun toString() = if (denom == 1L) "$num" else "$num/$denom"
fun toDouble() = num.toDouble() / denom
 
fun toLong() = num / denom
}
 
fun isPerfect(n: Long): Boolean {
var sum = Frac(1, n)
val limit = Math.sqrt(n.toDouble()).toLong()
for (i in 2L..limit) {
if (n % i == 0L) sum += Frac(1, i) + Frac(1, n / i)
}
return sum == Frac.ONE
}
 
fun main(args: Array<String>) {
var frac1 = Frac(12, 3)
println ("frac1 = $frac1")
var frac2 = 15 idiv 2
println("frac2 = $frac2")
println("frac1 <= frac2 is ${frac1 <= frac2}")
println("frac1 >= frac2 is ${frac1 >= frac2}")
println("frac1 == frac2 is ${frac1 == frac2}")
println("frac1 != frac2 is ${frac1 != frac2}")
println("frac1 + frac2 = ${frac1 + frac2}")
println("frac1 - frac2 = ${frac1 - frac2}")
println("frac1 * frac2 = ${frac1 * frac2}")
println("frac1 / frac2 = ${frac1 / frac2}")
println("frac1 % frac2 = ${frac1 % frac2}")
println("inv(frac1) = ${frac1.inverse()}")
println("abs(-frac1) = ${-frac1.abs()}")
println("inc(frac2) = ${++frac2}")
println("dec(frac2) = ${--frac2}")
println("dbl(frac2) = ${frac2.toDouble()}")
println("lng(frac2) = ${frac2.toLong()}")
println("\nThe Perfect numbers less than 2^19 are:")
// We can skip odd numbers as no known perfect numbers are odd
for (i in 2 until (1 shl 19) step 2) {
if (isPerfect(i.toLong())) print(" $i")
}
println()
}</syntaxhighlight>
 
{{out}}
<pre>
frac1 = 4
frac2 = 15/2
frac1 <= frac2 is true
frac1 >= frac2 is false
frac1 == frac2 is false
frac1 != frac2 is true
frac1 + frac2 = 23/2
frac1 - frac2 = -7/2
frac1 * frac2 = 30
frac1 / frac2 = 8/15
frac1 % frac2 = 4
inv(frac1) = 1/4
abs(-frac1) = -4
inc(frac2) = 17/2
dec(frac2) = 15/2
dbl(frac2) = 7.5
lng(frac2) = 7
 
The Perfect numbers less than 2^19 are:
6 28 496 8128
</pre>
 
=={{header|Liberty BASIC}}==
Testing all numbers up to 2 ^ 19 takes an excessively long time.
<syntaxhighlight lang="lb">
<lang lb>
n=2^19
for testNumber=1 to n
Line 1,767 ⟶ 2,881:
end if
end function
</syntaxhighlight>
 
=={{header|Lingo}}==
A new 'frac' data type can be implemented like this:
<syntaxhighlight lang="lingo">-- parent script "Frac"
property num
property denom
 
----------------------------------------
-- @constructor
-- @param {integer} numerator
-- @param {integer} [denominator=1]
----------------------------------------
on new (me, numerator, denominator)
if voidP(denominator) then denominator = 1
if denominator=0 then return VOID -- rule out division by zero
g = me._gcd(numerator, denominator)
if g<>0 then
numerator = numerator/g
denominator = denominator/g
else
numerator = 0
denominator = 1
end if
if denominator<0 then
numerator = -numerator
denominator = -denominator
end if
me.num = numerator
me.denom = denominator
return me
end
 
----------------------------------------
-- Returns string representation "<num>/<denom>"
-- @return {string}
----------------------------------------
on toString (me)
return me.num&"/"&me.denom
end
 
----------------------------------------
--
----------------------------------------
on _gcd (me, a, b)
if a = 0 then return b
if b = 0 then return a
if a > b then return me._gcd(b, a mod b)
return me._gcd(a, b mod a)
end</syntaxhighlight>
 
Lingo does not support overwriting built-in operators, so 'frac'-operators must be implemented as functions:
<syntaxhighlight lang="lingo">-- Frac library (movie script)
 
----------------------------------------
-- Shortcut for creating 'frac' values
-- @param {integer} numerator
-- @param {integer} denominator
-- @return {instance}
----------------------------------------
on frac (numerator, denominator)
return script("Frac").new(numerator, denominator)
end
 
----------------------------------------
-- All functions below this comment only support 'fracs', i.e. instances
-- of the Frac Class, as arguments. An integer n is casted to frac via frac(n).
----------------------------------------
 
-- Optionally supports more than 2 arguments
on fAdd (a, b) -- ...
res = a
repeat with i = 2 to the paramCount
p = param(i)
num = res.num * p.denom + res.denom * p.num
denom = res.denom * p.denom
res = frac(num, denom)
end repeat
return res
end
 
on fSub (a, b)
return frac(a.num * b.den - a.den * b.num, a.den * b.den)
end
 
-- Optionally supports more than 2 arguments
on fMul (a, b) -- ...
res = a
repeat with i = 2 to the paramCount
p = param(i)
res = frac(res.num * p.num, res.denom * p.denom)
end repeat
return res
end
 
on fDiv (a, b)
return frac(a.num * b.denom, a.denom * b.num)
end
 
on fAbs (f)
return frac(abs(f.num), f.denom)
end
 
on fNeg (f)
return frac(-f.num, f.denom)
end
 
on fEQ (a, b)
diff = fSub(a, b)
return diff.num=0
end
 
on fNE (a, b)
return not fEQ (a, b)
end
 
on fGT (a, b)
diff = fSub(a, b)
return diff.num>0
end
 
on fLT (a, b)
diff = fSub(a, b)
return diff.num<0
end
 
on fGE (a, b)
diff = fSub(a, b)
return diff.num>=0
end
 
on fLE (a, b)
diff = fSub(a, b)
return diff.num<=0
end</syntaxhighlight>
Usage:
<syntaxhighlight lang="lingo">f = frac(2,3)
put f.toString()
-- "2/3"
 
-- fractions are normalized on the fly
f = frac(4,6)
put f.toString()
-- "2/3"
 
-- casting integer to frac
f = frac(23)
put f.toString()
-- "23/1"</syntaxhighlight>
 
Finding perfect numbers:
<syntaxhighlight lang="lingo">-- in some movie script
----------------------------------------
-- Prints all perfect numbers up to n
-- @param {integer|float} n
----------------------------------------
on findPerfects (n)
repeat with i = 2 to n
sum = frac(1, i)
cnt = sqrt(i)
repeat with fac = 2 to cnt
if i mod fac = 0 then sum = fAdd(sum, frac(1, fac), frac(fac, i))
end repeat
if sum.denom = sum.num then put i
end repeat
end</syntaxhighlight>
<syntaxhighlight lang="lingo">findPerfects(power(2, 19))
-- 6
-- 28
-- 496
-- 8128</syntaxhighlight>
 
=={{header|Lua}}==
<syntaxhighlight lang="lua">function gcd(a,b) return a == 0 and b or gcd(b % a, a) end
 
do
local function coerce(a, b)
if type(a) == "number" then return rational(a, 1), b end
if type(b) == "number" then return a, rational(b, 1) end
return a, b
end
rational = setmetatable({
__add = function(a, b)
local a, b = coerce(a, b)
return rational(a.num * b.den + a.den * b.num, a.den * b.den)
end,
__sub = function(a, b)
local a, b = coerce(a, b)
return rational(a.num * b.den - a.den * b.num, a.den * b.den)
end,
__mul = function(a, b)
local a, b = coerce(a, b)
return rational(a.num * b.num, a.den * b.den)
end,
__div = function(a, b)
local a, b = coerce(a, b)
return rational(a.num * b.den, a.den * b.num)
end,
__pow = function(a, b)
if type(a) == "number" then return a ^ (b.num / b.den) end
return rational(a.num ^ b, a.den ^ b) --runs into a problem if these aren't integers
end,
__concat = function(a, b)
if getmetatable(a) == rational then return a.num .. "/" .. a.den .. b end
return a .. b.num .. "/" .. b.den
end,
__unm = function(a) return rational(-a.num, -a.den) end}, {
__call = function(z, a, b) return setmetatable({num = a / gcd(a, b),den = b / gcd(a, b)}, z) end} )
end
 
print(rational(2, 3) + rational(3, 5) - rational(1, 10) .. "") --> 7/6
print((rational(4, 5) * rational(5, 9)) ^ rational(1, 2) .. "") --> 2/3
print(rational(45, 60) / rational(5, 2) .. "") --> 3/10
print(5 + rational(1, 3) .. "") --> 16/3
 
function findperfs(n)
local ret = {}
for i = 1, n do
sum = rational(1, i)
for fac = 2, i^.5 do
if i % fac == 0 then
sum = sum + rational(1, fac) + rational(fac, i)
end
end
if sum.den == sum.num then
ret[#ret + 1] = i
end
end
return table.concat(ret, '\n')
end
print(findperfs(2^19))</syntaxhighlight>
 
=={{header|M2000 Interpreter}}==
http://www.rosettacode.org/wiki/M2000_Interpreter_rational_numbers
 
<syntaxhighlight lang="m2000 interpreter">
Class Rational {
\\ this is a compact version for this task
numerator as decimal, denominator as decimal
gcd=lambda->0
lcm=lambda->0
operator "+" {
Read l
denom=.lcm(l.denominator, .denominator)
.numerator<=denom/l.denominator*l.numerator+denom/.denominator*.numerator
if .numerator==0 then denom=1
.denominator<=denom
}
Group Real {
value {
link parent numerator, denominator to n, d
=n/d
}
}
Group ToString$ {
value {
link parent numerator, denominator to n, d
=Str$(n)+"/"+Str$(d,"")
}
}
class:
Module Rational (.numerator, .denominator) {
if .denominator=0 then Error "Zero denominator"
sgn=Sgn(.numerator)*Sgn(.denominator)
.denominator<=abs(.denominator)
.numerator<=abs(.numerator)*sgn
gcd1=lambda (a as decimal, b as decimal) -> {
if a<b then swap a,b
g=a mod b
while g {
a=b:b=g: g=a mod b
}
=abs(b)
}
gdcval=gcd1(abs(.numerator), .denominator)
if gdcval<.denominator and gdcval<>0 then
.denominator/=gdcval
.numerator/=gdcval
end if
.gcd<=gcd1
.lcm<=lambda gcd=gcd1 (a as decimal, b as decimal) -> {
=a/gcd(a,b)*b
}
}
}
sum=rational(1, 1)
onediv=rational(1,1)
divcand=rational(1,1)
Profiler
For sum.denominator= 2 to 2**15 {
divcand.denominator=sum.denominator
For onediv.denominator=2 to sqrt(sum.denominator) {
if sum.denominator mod onediv.denominator = 0 then {
divcand.numerator=onediv.denominator
sum=sum+onediv+divcand
}
}
if sum.real=1 then Print sum.denominator;" is perfect"
sum.numerator=1
}
Print timecount
</syntaxhighlight>
 
</lang>
=={{header|Maple}}==
Maple has full built-in support for arithmetic with fractions (rational numbers). Fractions are treated like any other number in Maple.
<syntaxhighlight lang="maple">
<lang Maple>
> a := 3 / 5;
a := 3/5
Line 1,781 ⟶ 3,195:
> denom( a );
5
</syntaxhighlight>
</lang>
However, while you can enter a fraction such as "4/6", it will automatically be reduced so that the numerator and denominator have no common factor:
<syntaxhighlight lang="maple">
<lang Maple>
> b := 4 / 6;
b := 2/3
</syntaxhighlight>
</lang>
All the standard arithmetic operators work with rational numbers. It is not necessary to call any special routines.
<syntaxhighlight lang="maple">
<lang Maple>
> a + b;
19
Line 1,810 ⟶ 3,224:
> a - 1;
-2/5
</syntaxhighlight>
</lang>
Notice that fractions are treated as exact quantities; they are not converted to floats. However, you can get a floating point approximation to any desired accuracy by applying the function evalf to a fraction.
<syntaxhighlight lang="maple">
<lang Maple>
> evalf( 22 / 7 ); # default is 10 digits
3.142857143
Line 1,819 ⟶ 3,233:
3.142857142857142857142857142857142857142857142857142857142857142857\
142857142857142857142857142857143
</syntaxhighlight>
</lang>
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
Mathematica has full support for fractions built-in. If one divides two exact numbers it will be left as a fraction if it can't be simplified. Comparison, addition, division, product et cetera are built-in:
<syntaxhighlight lang="mathematica">4/16
<lang Mathematica>4/16
3/8
8/4
Line 1,848 ⟶ 3,262:
 
Numerator[6/9]
Denominator[6/9]</langsyntaxhighlight>
gives back:
<pre>1/4
Line 1,877 ⟶ 3,291:
3</pre>
As you can see, Mathematica automatically handles fraction as exact things, it doesn't evaluate the fractions to a float. It only does this when either the numerator or the denominator is not exact. I only showed integers above, but Mathematica can handle symbolic fraction in the same and complete way:
<langsyntaxhighlight Mathematicalang="mathematica">c/(2 c)
(b^2 - c^2)/(b - c) // Cancel
1/2 + b/c // Together</langsyntaxhighlight>
gives back:
<syntaxhighlight lang="mathematica">1/2
<lang Mathematica>1/2
b+c
(2 b+c) / (2 c)</langsyntaxhighlight>
Moreover it does simplification like Sin[x]/Cos[x] => Tan[x]. Division, addition, subtraction, powering and multiplication of a list (of any dimension) is automatically threaded over the elements:
<langsyntaxhighlight Mathematicalang="mathematica">1+2*{1,2,3}^3</langsyntaxhighlight>
gives back:
<syntaxhighlight lang Mathematica="mathematica">{3, 17, 55}</langsyntaxhighlight>
To check for perfect numbers in the range 1 to 2^25 we can use:
<langsyntaxhighlight Mathematicalang="mathematica">found={};
CheckPerfect[num_Integer]:=If[Total[1/Divisors[num]]==2,AppendTo[found,num]];
Do[CheckPerfect[i],{i,1,2^25}];
found</langsyntaxhighlight>
gives back:
<langsyntaxhighlight Mathematicalang="mathematica">{6, 28, 496, 8128, 33550336}</langsyntaxhighlight>
Final note; approximations of fractions to any precision can be found using the function N.
 
=={{header|Maxima}}==
<langsyntaxhighlight lang="maxima">/* Rational numbers are builtin */
a: 3 / 11;
3/11
Line 1,927 ⟶ 3,341:
 
ratnump(a);
true</langsyntaxhighlight>
 
=={{header|Modula-2}}==
Line 1,933 ⟶ 3,347:
{{:Arithmetic/Rational/Modula-2}}
 
=={{header|NimrodModula-3}}==
<div style="text-align:right;font-size:7pt">''<nowiki>[</nowiki>This section is included from [[Arithmetic/Rational/Modula-3|a subpage]] and should be edited there, not here.<nowiki>]</nowiki>''</div>
<lang nimrod>import math
{{:Arithmetic/Rational/Modula-3}}
 
=={{header|Nim}}==
<syntaxhighlight lang="nim">import math
 
proc `^`[T](base, exp: T): T =
Line 1,957 ⟶ 3,375:
type Rational* = tuple[num, den: int64]
 
proc fromInt*(x: TIntegerSomeInteger): Rational =
result.num = x
result.den = 1
Line 2,031 ⟶ 3,449:
if sum.den == 1:
echo "Sum of recipr. factors of ",candidate," = ",sum.num," exactly ",
if sum.num == 1: "perfect!" else: ""</langsyntaxhighlight>
Output:
<pre>Sum of recipr. factors of 6 = 1 exactly perfect!
Line 2,044 ⟶ 3,462:
 
=={{header|Objective-C}}==
See [[Arithmetic/Rational/Objective-C]].
<div style="text-align:right;font-size:7pt">''<nowiki>[</nowiki>This section is included from [[Arithmetic/Rational/Objective-C|a subpage]] and should be edited there, not here.<nowiki>]</nowiki>''</div>
{{:Arithmetic/Rational/Objective-C}}
 
=={{header|OCaml}}==
OCaml's Num library implements arbitrary-precision rational numbers:
<langsyntaxhighlight lang="ocaml">#load "nums.cma";;
open Num;;
 
Line 2,062 ⟶ 3,479:
Printf.printf "Sum of recipr. factors of %d = %d exactly %s\n%!"
candidate (int_of_num !sum) (if int_of_num !sum = 1 then "perfect!" else "")
done;;</langsyntaxhighlight>
[http://forge.ocamlcore.org/projects/pa-do/ Delimited overloading] can be used to make the arithmetic expressions more readable:
<langsyntaxhighlight lang="ocaml">let () =
for candidate = 2 to 1 lsl 19 do
let sum = ref Num.(1 / of_int candidate) in
Line 2,074 ⟶ 3,491:
Printf.printf "Sum of recipr. factors of %d = %d exactly %s\n%!"
candidate Num.(to_int !sum) (if Num.(!sum = 1) then "perfect!" else "")
done</langsyntaxhighlight>
It might be implemented like this:
 
A type for rational numbers might be implemented like this:
[insert implementation here]
 
First define the interface, hiding implementation details:
<syntaxhighlight lang="ocaml">(* interface *)
module type RATIO =
sig
type t
(* construct *)
val frac : int -> int -> t
val from_int : int -> t
 
(* integer test *)
val is_int : t -> bool
 
(* output *)
val to_string : t -> string
 
(* arithmetic *)
val cmp : t -> t -> int
val ( +/ ) : t -> t -> t
val ( -/ ) : t -> t -> t
val ( */ ) : t -> t -> t
val ( // ) : t -> t -> t
end</syntaxhighlight>
 
then implement the module:
<syntaxhighlight lang="ocaml">(* implementation conforming to signature *)
module Frac : RATIO =
struct
open Big_int
 
type t = { num : big_int; den : big_int }
(* short aliases for big_int values and functions *)
let zero, one = zero_big_int, unit_big_int
let big, to_int, eq = big_int_of_int, int_of_big_int, eq_big_int
let (+~), (-~), ( *~) = add_big_int, sub_big_int, mult_big_int
(* helper function *)
let rec norm ({num=n;den=d} as k) =
if lt_big_int d zero then
norm {num=minus_big_int n;den=minus_big_int d}
else
let rec hcf a b =
let q,r = quomod_big_int a b in
if eq r zero then b else hcf b r in
let f = hcf n d in
if eq f one then k else
let div = div_big_int in
{ num=div n f; den = div d f } (* inefficient *)
(* public functions *)
let frac a b = norm { num=big a; den=big b }
let from_int a = norm { num=big a; den=one }
 
let is_int {num=n; den=d} =
eq d one ||
eq (mod_big_int n d) zero
let to_string ({num=n; den=d} as r) =
let r1 = norm r in
let str = string_of_big_int in
if is_int r1 then
str (r1.num)
else
str (r1.num) ^ "/" ^ str (r1.den)
let cmp a b =
let a1 = norm a and b1 = norm b in
compare_big_int (a1.num*~b1.den) (b1.num*~a1.den)
 
let ( */ ) {num=n1; den=d1} {num=n2; den=d2} =
norm { num = n1*~n2; den = d1*~d2 }
 
let ( // ) {num=n1; den=d1} {num=n2; den=d2} =
norm { num = n1*~d2; den = d1*~n2 }
let ( +/ ) {num=n1; den=d1} {num=n2; den=d2} =
norm { num = n1*~d2 +~ n2*~d1; den = d1*~d2 }
let ( -/ ) {num=n1; den=d1} {num=n2; den=d2} =
norm { num = n1*~d2 -~ n2*~d1; den = d1*~d2 }
end</syntaxhighlight>
 
Finally the use type defined by the module to perform the perfect number calculation:
<syntaxhighlight lang="ocaml">(* use the module to calculate perfect numbers *)
let () =
for i = 2 to 1 lsl 19 do
let sum = ref (Frac.frac 1 i) in
for factor = 2 to truncate (sqrt (float i)) do
if i mod factor = 0 then
Frac.(
sum := !sum +/ frac 1 factor +/ frac 1 (i / factor)
)
done;
if Frac.is_int !sum then
Printf.printf "Sum of reciprocal factors of %d = %s exactly %s\n%!"
i (Frac.to_string !sum) (if Frac.to_string !sum = "1" then "perfect!" else "")
done</syntaxhighlight>
which produces this output:
 
Sum of reciprocal factors of 6 = 1 exactly perfect!
Sum of reciprocal factors of 28 = 1 exactly perfect!
Sum of reciprocal factors of 120 = 2 exactly
Sum of reciprocal factors of 496 = 1 exactly perfect!
Sum of reciprocal factors of 672 = 2 exactly
Sum of reciprocal factors of 8128 = 1 exactly perfect!
Sum of reciprocal factors of 30240 = 3 exactly
Sum of reciprocal factors of 32760 = 3 exactly
Sum of reciprocal factors of 523776 = 2 exactly
 
=={{header|Ol}}==
Otus Lisp has rational numbers built-in and integrated with all other number types.
<syntaxhighlight lang="scheme">
(define x 3/7)
(define y 9/11)
(define z -2/5)
 
; demonstrate builtin functions:
 
(print "(abs " z ") = " (abs z))
(print "- " z " = " (- z))
(print x " + " y " = " (+ x y))
(print x " - " y " = " (- x y))
(print x " * " y " = " (* x y))
(print x " / " y " = " (/ x y))
(print x " < " y " = " (< x y))
(print x " > " y " = " (> x y))
 
; introduce new functions:
 
(define (+:= x) (+ x 1))
(define (-:= x) (- x 1))
 
(print "+:= " z " = " (+:= z))
(print "-:= " z " = " (-:= z))
 
; finally, find all perfect numbers less than 2^15:
 
(lfor-each (lambda (candidate)
(let ((sum (lfold (lambda (sum factor)
(if (= 0 (modulo candidate factor))
(+ sum (/ 1 factor) (/ factor candidate))
sum))
(/ 1 candidate)
(liota 2 1 (+ (isqrt candidate) 1)))))
(if (= 1 (denominator sum))
(print candidate (if (eq? sum 1) ", perfect" "")))))
(liota 2 1 (expt 2 15)))
</syntaxhighlight>
{{Out}}
<pre>
(abs -2/5) = 2/5
- -2/5 = 2/5
3/7 + 9/11 = 96/77
3/7 - 9/11 = -30/77
3/7 * 9/11 = 27/77
3/7 / 9/11 = 11/21
3/7 < 9/11 = #true
3/7 > 9/11 = #false
+:= -2/5 = 3/5
-:= -2/5 = -7/5
6, perfect
28, perfect
120
496, perfect
672
8128, perfect
30240
32760
</pre>
=={{header|ooRexx}}==
<syntaxhighlight lang="oorexx">
<lang ooRexx>
loop candidate = 6 to 2**19
sum = .fraction~new(1, candidate)
Line 2,094 ⟶ 3,680:
end
 
::class fraction public inherit orderable
::method init
expose numerator denominator
use strict arg numerator, denominator = 1
 
if numeratordenominator == 0 then raise syntax 98.900 array("Fraction denominator =cannot 0be zero")
else if denominator == 0 then raise syntax 98.900 array("Fraction denominator cannot be zero")
 
-- if the denominator is negative, make the numerator carry the sign
Line 2,245 ⟶ 3,830:
 
::requires rxmath library
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,256 ⟶ 3,841:
=={{header|PARI/GP}}==
Pari handles rational arithmetic natively.
<langsyntaxhighlight lang="parigp">for(n=2,1<<19,
s=0;
fordiv(n,d,s+=1/d);
if(s==2,print(n))
)</langsyntaxhighlight>
 
=={{header|Perl}}==
Perl's <code>Math::BigRat</code> core module implements arbitrary-precision rational numbers. The <code>bigrat</code> pragma can be used to turn on transparent BigRat support:
<langsyntaxhighlight lang="perl">use bigrat;
 
foreach my $candidate (2 .. 2**19) {
Line 2,276 ⟶ 3,861:
print "Sum of recipr. factors of $candidate = $sum exactly ", ($sum == 1 ? "perfect!" : ""), "\n";
}
}</langsyntaxhighlight>
It might be implemented like this:
 
=={{header|Phix}}==
[insert implementation here]
{{Trans|Tcl}}
Phix does not support operator overloading (I am strongly opposed to such nonsense), nor does it have a native fraction library, but it might look a bit like this.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">without</span> <span style="color: #000000;">warning</span> <span style="color: #000080;font-style:italic;">-- (several unused routines in this code)</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">NUM</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">DEN</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">2</span>
<span style="color: #008080;">type</span> <span style="color: #000000;">frac</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">2</span> <span style="color: #008080;">and</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">[</span><span style="color: #000000;">NUM</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">and</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DEN</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">normalise</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">d</span><span style="color: #0000FF;"><</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">n</span>
<span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">d</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">g</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">gcd</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">/</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">/</span><span style="color: #000000;">g</span><span style="color: #0000FF;">}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_new</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">d</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">normalise</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #7060A8;">abs</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">[</span><span style="color: #000000;">NUM</span><span style="color: #0000FF;">]),</span><span style="color: #000000;">r</span><span style="color: #0000FF;">[</span><span style="color: #000000;">DEN</span><span style="color: #0000FF;">]}</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_inv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">reverse</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">an</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ad</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">bn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bd</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">normalise</span><span style="color: #0000FF;">(</span><span style="color: #000000;">an</span><span style="color: #0000FF;">*</span><span style="color: #000000;">bd</span><span style="color: #0000FF;">+</span><span style="color: #000000;">bn</span><span style="color: #0000FF;">*</span><span style="color: #000000;">ad</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ad</span><span style="color: #0000FF;">*</span><span style="color: #000000;">bd</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">an</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ad</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">bn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bd</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">normalise</span><span style="color: #0000FF;">(</span><span style="color: #000000;">an</span><span style="color: #0000FF;">*</span><span style="color: #000000;">bd</span><span style="color: #0000FF;">-</span><span style="color: #000000;">bn</span><span style="color: #0000FF;">*</span><span style="color: #000000;">ad</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ad</span><span style="color: #0000FF;">*</span><span style="color: #000000;">bd</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">an</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ad</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">bn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bd</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">normalise</span><span style="color: #0000FF;">(</span><span style="color: #000000;">an</span><span style="color: #0000FF;">*</span><span style="color: #000000;">bn</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ad</span><span style="color: #0000FF;">*</span><span style="color: #000000;">bd</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_div</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">an</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ad</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">bn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bd</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">normalise</span><span style="color: #0000FF;">(</span><span style="color: #000000;">an</span><span style="color: #0000FF;">*</span><span style="color: #000000;">bd</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ad</span><span style="color: #0000FF;">*</span><span style="color: #000000;">bn</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_eq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">==</span><span style="color: #000000;">b</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_ne</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">b</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_lt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">frac_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)[</span><span style="color: #000000;">NUM</span><span style="color: #0000FF;">]<</span><span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_gt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">frac_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)[</span><span style="color: #000000;">NUM</span><span style="color: #0000FF;">]></span><span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_le</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">frac_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)[</span><span style="color: #000000;">NUM</span><span style="color: #0000FF;">]<=</span><span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">frac_ge</span><span style="color: #0000FF;">(</span><span style="color: #000000;">frac</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">frac_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)[</span><span style="color: #000000;">NUM</span><span style="color: #0000FF;">]>=</span><span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">is_perfect</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">frac</span> <span style="color: #000000;">total</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">frac_new</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">f</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">factors</span><span style="color: #0000FF;">(</span><span style="color: #000000;">num</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">total</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">frac_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">total</span><span style="color: #0000FF;">,</span><span style="color: #000000;">frac_new</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">frac_eq</span><span style="color: #0000FF;">(</span><span style="color: #000000;">total</span><span style="color: #0000FF;">,</span><span style="color: #000000;">frac_new</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">get_perfect_numbers</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">lim</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span><span style="color: #0000FF;">?</span><span style="color: #000000;">13</span><span style="color: #0000FF;">:</span><span style="color: #000000;">19</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">lim</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">is_perfect</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"perfect: %d\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"elapsed: %3.2f seconds\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">pn5</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">)*(</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">13</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- 5th perfect number</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">is_perfect</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pn5</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"perfect: %d\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pn5</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">get_perfect_numbers</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
perfect: 6
perfect: 28
perfect: 496
perfect: 8128
elapsed: 13.56 seconds
perfect: 33550336
</pre>
=== mpq ===
{{libheader|Phix/mpfr}}
Turned out to be slightly slower than native, but worth it for large number support.<br>
See also [[Bernoulli_numbers#Phix|Bernoulli_numbers]] for another example of mpqs in action.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">/</span><span style="color: #004080;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">is_perfect</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">num</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">mpq</span> <span style="color: #000000;">tot</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpq_init</span><span style="color: #0000FF;">(),</span>
<span style="color: #000000;">fth</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpq_init</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">f</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">factors</span><span style="color: #0000FF;">(</span><span style="color: #000000;">num</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">f</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">mpq_set_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fth</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">f</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
<span style="color: #7060A8;">mpq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tot</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tot</span><span style="color: #0000FF;">,</span><span style="color: #000000;">fth</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #7060A8;">mpq_cmp_si</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tot</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">get_perfect_numbers</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">lim</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()=</span><span style="color: #004600;">JS</span><span style="color: #0000FF;">?</span><span style="color: #000000;">13</span><span style="color: #0000FF;">:</span><span style="color: #000000;">19</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #000000;">lim</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">is_perfect</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"perfect: %d\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"elapsed: %3.2f seconds\n"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">pn5</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">)*(</span><span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">13</span><span style="color: #0000FF;">)-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #000080;font-style:italic;">-- 5th perfect number</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">is_perfect</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pn5</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"perfect: %d\n"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pn5</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">get_perfect_numbers</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
perfect: 6
perfect: 28
perfect: 496
perfect: 8128
elapsed: 17.31 seconds
perfect: 33550336
</pre>
<small>Note that power(2,19) took over 270s under mpfr.js, so reduced to power(2,13) on that platform, making it finish in 0.99s</small>
 
=={{header|Perl 6Picat}}==
A naive addition algorithm is used, so the program is slow.
Perl 6 supports rational arithmetic natively.
 
<lang perl6>for 2..2**19 -> $candidate {
<syntaxhighlight lang="picat">
my $sum = 1 / $candidate;
main =>
for 2 .. ceiling(sqrt($candidate)) -> $factor {
foreach (I in 2..2**19, is_perfect(I))
if $candidate %% $factor {
println(I)
$sum += 1 / $factor + 1 / ($candidate / $factor);
end. }
}
is_perfect(N) => sum_rationals([$frac(1,D) : D in divisors(N)]) == $frac(2,1).
if $sum.denominator == 1 {
 
say "Sum of reciprocal factors of $candidate = $sum exactly", ($sum == 1 ?? ", perfect!" !! ".");
divisors(N) = [I : I in 1..N, N mod I == 0].
}
 
}</lang>
add(frac(A,B), frac(C,D)) = new_fract(A*D+B*C, B*D).
Note also that ordinary decimal literals are stored as Rats, so the following loop always stops exactly on 10 despite 0.1 not being exactly representable in floating point:
 
<lang perl6>for 1.0, 1.1, 1.2 ... 10 { .say }</lang>
new_fract(A,B) = $frac(Num, Den) =>
The arithmetic is all done in rationals, which are converted to floating-point just before display so that people don't have to puzzle out what 53/10 means.
G = gcd(A,B),
Num = A // G,
Den = B // G.
 
sum_rationals([X]) = X.
sum_rationals([X,Y|T]) = sum_rationals([add(X,Y)|T]).
</syntaxhighlight>
{{out}}
<pre>
6
28
496
8128
</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(load "@lib/frac.l")
 
(for (N 2 (> (** 2 19) N) (inc N))
Line 2,312 ⟶ 4,075:
"Perfect " N
", sum is " (car Sum)
(and (= 1 (car Sum)) ": perfect") ) ) ) )</langsyntaxhighlight>
{{out}}
<pre>Perfect 6, sum is 1: perfect
Line 2,324 ⟶ 4,087:
Perfect 523776, sum is 2</pre>
 
=={{header|PL/I}}==
<syntaxhighlight lang="pli">*process source attributes xref or(!);
arat: Proc Options(main);
/*--------------------------------------------------------------------
* Rational Arithmetic
* (Mis)use the Complex data type to represent fractions
* real(x) is used as numerator
* imag(x) is used as denominator
* Output:
* a=-3/7 b=9/2
* a*b=-27/14
* a+b=57/14
* a-b=-69/14
* a/b=-2/21
* -3/7<9/2
* 9/2>-3/7
* -3/7=-3/7
* 26.01.2015 handle 0/0
*-------------------------------------------------------------------*/
Dcl (abs,imag,mod,real,sign,trim) Builtin;
Dcl sysprint Print;
Dcl (candidate,max2,factor) Dec Fixed(15);
Dcl sum complex Dec Fixed(15);
Dcl one complex Dec Fixed(15);
 
one=mk_fr(1,1);
Put Edit('First solve the task at hand')(Skip,a);
Do candidate = 2 to 10000;
sum = mk_fr(1, candidate);
max2 = sqrt(candidate);
Do factor = 2 to max2;
If mod(candidate,factor)=0 Then Do;
sum=fr_add(sum,mk_fr(1,factor));
sum=fr_add(sum,mk_fr(1,candidate/factor));
End;
End;
If fr_cmp(sum,one)='=' Then Do;
Put Edit(candidate,' is a perfect number')(Skip,f(7),a);
Do factor = 2 to candidate-1;
If mod(candidate,factor)=0 Then
Put Edit(factor)(f(5));
End;
End;
End;
 
Put Edit('','Then try a few things')(Skip,a);
Dcl a Complex Dec Fixed(15);
Dcl b Complex Dec Fixed(15);
Dcl p Complex Dec Fixed(15);
Dcl s Complex Dec Fixed(15);
Dcl d Complex Dec Fixed(15);
Dcl q Complex Dec Fixed(15);
Dcl zero Complex Dec Fixed(15);
zero=mk_fr(0,1); Put Edit('zero=',fr_rep(zero))(Skip,2(a));
a=mk_fr(0,0); Put Edit('a=',fr_rep(a))(Skip,2(a));
/*--------------------------------------------------------------------
a=mk_fr(-3333,0); Put Edit('a=',fr_rep(a))(Skip,2(a));
=> Request mk_fr(-3333,0)
Denominator must not be 0
IBM0280I ONCODE=0009 The ERROR condition was raised
by a SIGNAL statement.
At offset +00000276 in procedure with entry FT
*-------------------------------------------------------------------*/
a=mk_fr(0,3333); Put Edit('a=',fr_rep(a))(Skip,2(a));
Put Edit('-3,7')(Skip,a);
a=mk_fr(-3,7);
b=mk_fr(9,2);
p=fr_mult(a,b);
s=fr_add(a,b);
d=fr_sub(a,b);
q=fr_div(a,b);
r=fr_div(b,a);
Put Edit('a=',fr_rep(a))(Skip,2(a));
Put Edit('b=',fr_rep(b))(Skip,2(a));
Put Edit('a*b=',fr_rep(p))(Skip,2(a));
Put Edit('a+b=',fr_rep(s))(Skip,2(a));
Put Edit('a-b=',fr_rep(d))(Skip,2(a));
Put Edit('a/b=',fr_rep(q))(Skip,2(a));
Put Edit('b/a=',fr_rep(r))(Skip,2(a));
Put Edit(fr_rep(a),fr_cmp(a,b),fr_rep(b))(Skip,3(a));
Put Edit(fr_rep(b),fr_cmp(b,a),fr_rep(a))(Skip,3(a));
Put Edit(fr_rep(a),fr_cmp(a,a),fr_rep(a))(Skip,3(a));
 
mk_fr: Proc(n,d) Recursive Returns(Dec Fixed(15) Complex);
/*--------------------------------------------------------------------
* make a Complex number
* normalize and cancel
*-------------------------------------------------------------------*/
Dcl (n,d) Dec Fixed(15);
Dcl (na,da) Dec Fixed(15);
Dcl res Dec Fixed(15) Complex;
Dcl x Dec Fixed(15);
na=abs(n);
da=abs(d);
Select;
When(n=0) Do;
real(res)=0;
imag(res)=1;
End;
When(d=0) Do;
Put Edit('Request mk_fr('!!n_rep(n)!!','!!n_rep(d)!!')')
(Skip,a);
Put Edit('Denominator must not be 0')(Skip,a);
Signal error;
End;
Otherwise Do;
x=gcd(na,da);
real(res)=sign(n)*sign(d)*na/x;
imag(res)=da/x;
End;
End;
Return(res);
End;
 
fr_add: Proc(a,b) Returns(Dec Fixed(15) Complex);
/*--------------------------------------------------------------------
* add 'fractions' a and b
*-------------------------------------------------------------------*/
Dcl (a,b,res) Dec Fixed(15) Complex;
Dcl (an,ad,bn,bd) Dec Fixed(15);
Dcl (rd,rn) Dec Fixed(15);
Dcl x Dec Fixed(15);
an=real(a);
ad=imag(a);
bn=real(b);
bd=imag(b);
rd=ad*bd;
rn=an*bd+bn*ad;
x=gcd(rd,rn);
real(res)=rn/x;
imag(res)=rd/x;
Return(res);
End;
 
fr_sub: Proc(a,b) Returns(Dec Fixed(15) Complex);
/*--------------------------------------------------------------------
* subtract 'fraction' b from a
*-------------------------------------------------------------------*/
Dcl (a,b) Dec Fixed(15) Complex;
Dcl b2 Dec Fixed(15) Complex;
real(b2)=-real(b);
imag(b2)=imag(b);
Return(fr_add(a,b2));
End;
 
fr_mult: Proc(a,b) Returns(Dec Fixed(15) Complex);
/*--------------------------------------------------------------------
* multiply 'fractions' a and b
*-------------------------------------------------------------------*/
Dcl (a,b,res) Dec Fixed(15) Complex;
real(res)=real(a)*real(b);
imag(res)=imag(a)*imag(b);
Return(res);
End;
 
fr_div: Proc(a,b) Returns(Dec Fixed(15) Complex);
/*--------------------------------------------------------------------
* divide 'fraction' a by b
*-------------------------------------------------------------------*/
Dcl (a,b) Dec Fixed(15) Complex;
Dcl b2 Dec Fixed(15) Complex;
real(b2)=imag(b);
imag(b2)=real(b);
If real(a)=0 & real(b)=0 Then
Return(mk_fr(1,1));
Return(fr_mult(a,b2));
End;
 
fr_cmp: Proc(a,b) Returns(char(1));
/*--------------------------------------------------------------------
* compare 'fractions' a and b
*-------------------------------------------------------------------*/
Dcl (a,b) Dec Fixed(15) Complex;
Dcl (an,ad,bn,bd) Dec Fixed(15);
Dcl (a2,b2) Dec Fixed(15);
Dcl (rd) Dec Fixed(15);
Dcl res Char(1);
an=real(a);
ad=imag(a);
If ad=0 Then Do;
Put Edit('ad=',ad,'candidate=',candidate)(Skip,a,f(10));
Signal Error;
End;
bn=real(b);
bd=imag(b);
rd=ad*bd;
a2=abs(an*bd)*sign(an)*sign(ad);
b2=abs(bn*ad)*sign(bn)*sign(bd);
Select;
When(a2<b2) res='<';
When(a2>b2) res='>';
Otherwise Do;
res='=';
End;
End;
Return(res);
End;
 
fr_rep: Proc(f) Returns(char(15) Var);
/*--------------------------------------------------------------------
* Return the representation of 'fraction' f
*-------------------------------------------------------------------*/
Dcl f Dec Fixed(15) Complex;
Dcl res Char(15) Var;
Dcl (n,d) Pic'(14)Z9';
Dcl x Dec Fixed(15);
Dcl s Dec Fixed(15);
n=abs(real(f));
d=abs(imag(f));
x=gcd(n,d);
s=sign(real(f))*sign(imag(f));
res=trim(n/x)!!'/'!!trim(d/x);
If s<0 Then
res='-'!!res;
Return(res);
End;
 
n_rep: Proc(x) Returns(char(15) Var);
/*--------------------------------------------------------------------
* Return the representation of x
*-------------------------------------------------------------------*/
Dcl x Dec Fixed(15);
Dcl res Char(15) Var;
Put String(res) List(x);
res=trim(res);
Return(res);
End;
 
gcd: Proc(a,b) Returns(Dec Fixed(15)) Recursive;
/*--------------------------------------------------------------------
* Compute the greatest common divisor
*-------------------------------------------------------------------*/
Dcl (a,b) Dec Fixed(15) Nonassignable;
If b=0 then Return (abs(a));
Return(gcd(abs(b),mod(abs(a),abs(b))));
End gcd;
 
lcm: Proc(a,b) Returns(Dec Fixed(15));
/*--------------------------------------------------------------------
* Compute the least common multiple
*-------------------------------------------------------------------*/
Dcl (a,b) Dec Fixed(15) Nonassignable;
if a=0 ! b=0 then Return (0);
Return(abs(a*b)/gcd(a,b));
End lcm;
 
End;</syntaxhighlight>
{{out}}
<pre>First solve the task at hand
6 is a perfect number 2 3
28 is a perfect number 2 4 7 14
496 is a perfect number 2 4 8 16 31 62 124 248
8128 is a perfect number 2 4 8 16 32 64 127 254 508 1016 2032 4064
 
Then try a few things
zero=0/1
a=0/1
a=0/1
-3,7
a=-3/7
b=9/2
a*b=-27/14
a+b=57/14
a-b=-69/14
a/b=-2/21
b/a=1/0
-3/7<9/2
9/2>-3/7
-3/7=-3/7</pre>
 
=={{header|Prolog}}==
Prolog supports rational numbers, where P/Q is written as P rdiv Q.
<syntaxhighlight lang="prolog">
divisor(N, Div) :-
Max is floor(sqrt(N)),
between(1, Max, D),
divmod(N, D, _, 0),
(Div = D; Div is N div D, Div =\= D).
 
divisors(N, Divs) :-
setof(M, divisor(N, M), Divs).
 
recip(A, B) :- B is 1 rdiv A.
 
sumrecip(N, A) :-
divisors(N, [1 | Ds]),
maplist(recip, Ds, As),
sum_list(As, A).
 
perfect(X) :- sumrecip(X, 1).
 
main :-
Limit is 1 << 19,
forall(
(between(1, Limit, N), perfect(N)),
(format("~w~n", [N]))),
halt.
 
?- main.
</syntaxhighlight>
{{Out}}
<pre>
6
28
496
8128
</pre>
=={{header|Python}}==
{{works with|Python|3.0}}
Python 3's standard library already implements a Fraction class:
<langsyntaxhighlight lang="python">from fractions import Fraction
 
for candidate in range(2, 2**19):
Line 2,336 ⟶ 4,406:
if sum.denominator == 1:
print("Sum of recipr. factors of %d = %d exactly %s" %
(candidate, int(sum), "perfect!" if sum == 1 else ""))</langsyntaxhighlight>
It might be implemented like this:
<langsyntaxhighlight lang="python">def lcm(a, b):
return a // gcd(a,b) * b
 
Line 2,370 ⟶ 4,440:
return float(self.numerator / self.denominator)
def __int__(self):
return (self.numerator // self.denominator)</langsyntaxhighlight>
 
=={{header|Quackery}}==
 
Quackery comes with a rational arithmetic library coded in Quackery, <code>bigrat.qky</code>, and documented in '''The Book of Quackery.pdf'''. Both are available at [https://github.com/GordonCharlton/Quackery the Quackery Github repository].
 
<code>factors</code> is defined at [[Factors of an integer#Quackery]].
 
<syntaxhighlight lang="quackery"> [ $ "bigrat.qky" loadfile ] now!
 
[ -2 n->v rot
factors witheach
[ n->v 1/v v+ ]
v0= ] is perfect ( n -> b )
 
19 bit times [ i^ perfect if [ i^ echo cr ] ]</syntaxhighlight>
 
{{out}}
 
<pre>6
28
496
8128
</pre>
 
=={{header|Racket}}==
Line 2,377 ⟶ 4,470:
 
Example:
<langsyntaxhighlight lang="racket">
-> (* 1/7 14)
2
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
{{Works with|rakudo|2016.08}}
Raku supports rational arithmetic natively.
<syntaxhighlight lang="raku" line>(2..2**19).hyper.map: -> $candidate {
my $sum = 1 / $candidate;
for 2 .. ceiling(sqrt($candidate)) -> $factor {
if $candidate %% $factor {
$sum += 1 / $factor + 1 / ($candidate / $factor);
}
}
if $sum.nude[1] == 1 {
say "Sum of reciprocal factors of $candidate = $sum exactly", ($sum == 1 ?? ", perfect!" !! ".");
}
}</syntaxhighlight>
Note also that ordinary decimal literals are stored as Rats, so the following loop always stops exactly on 10 despite 0.1 not being exactly representable in floating point:
<syntaxhighlight lang="raku" line>for 1.0, 1.1, 1.2 ... 10 { .say }</syntaxhighlight>
The arithmetic is all done in rationals, which are converted to floating-point just before display so that people don't have to puzzle out what 53/10 means.
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX pgmprogram implements a reasonably complete rational arithmetic (fract.using fractions).*/
L=length(2**19 - 1) /*saves time by checking even #snumbers. */
do j=2 by 2 to 2**19 - 1; by 2 s=0 /*ignore unity (which can't be perfect)*/
$mostDivs=divisorseDivs(j); s=0; @= @= /*getobtain divisors,>1; zero sum,; null @. */
do k=1 for words(mostDivs) /*unity isn't return from doeDivs k=2 to words($) /*ignore unityhere.*/
r='1/'word($mostDivs, k); @=@ r; s=fractFun$fun(r, , s)
end /*k*/
if s\==1 then iterate /*Is sum not equal to unity? Skip it.*/
say 'perfect number:' right(j, L) ' " fractions:'" @
end /*j*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────FRACTDIV subroutine─────────────────*/
fractDiv$div: procedure; parse arg x; x=space(x,0); f= 'FractDivfractional division'
parse var x n '/' d; d=p(d 1)
if d=0 then call err 'division by zero:' x
if \isNumdatatype(n,'N') then call err 'a not numericnon─numeric numerator:' x
if \isNumdatatype(d,'N') then call err 'a not numericnon─numeric denominator:' x
return n/d
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────FRACTFUN subroutine─────────────────*/
fractFun$fun: procedure; parse arg z.1,,z.2 1 zz.2,f; arg ,op; op=p(op '+')
fF= 'FractFunfractionalFunction'; do j=1 for 2; z.j=translate(z.j, '/', "_"); end /*j*/
if abbrev('ADD' , op) then op=' "+'"
if abbrev('DIVIDE' , op) then op=' "/'"
if abbrev('INTDIVIDE' , op, 4) then op=' "÷'"
if abbrev('MODULOMODULUS' , ,op, 3) | abbrev('MODULUSMODULO', ,op, 3) then op=' "//'"
if abbrev('MULTIPLY' , op) then op=' "*'"
if abbrev('POWER' , op) then op=' "^'"
if abbrev('SUBTRACT' , op) then op=' "-'"
if z.1=='' then z.1= (op\=="+" & op\=='-') /*unary +,-*/
if z.2=='' then z.2= (op\=="+" & op\=='-')
z_=z.2
/* [↑] verification of both fractions.*/
 
do j=1 for 2 /*verification of both fractions.*/
if pos('/', z.j)==0 then z.j=z.j"/1"; parse var z.j n.j '/' d.j
if \isNumdatatype(n.j,'N') then call err 'a not numericnon─numeric numerator:' n.j
if \isNumdatatype(d.j,'N') then call err 'a not numericnon─numeric denominator:' d.j
if d.j=0 then call err 'a denominator of zero:' d.j
n.j=n.j/1; d.j=d.j/1
do while \isInt(n.j); n.j=(n.j*10)/1; d.j=(d.j*10)/1
enddo /*while*/ \datatype(n.j,'W'); n.j=(n.j*10)/*1; [↑] normalize both numbersd. j=(d.j*10)/1
end /*while*/ /* [↑] {xxx/1} normalizes a number. */
if d.j=0 then call err 'a denominator of zero:' d.j
g=gcd(n.j, d.j); if g=0 then iterate; n.j=n.j/g; d.j=d.j/g
end /*j*/
 
select
when op=='+' | op=='-' then do; l=lcm(d.1,d.2); do j=1 for 2; n.j=l*n.j/d.j; d.j=l
end /*j*/
if op=='-' then n.2= -n.2; t=n.1 + n.2; u=l
end
when op=='**' | op=='↑' |,
op=='^' then do; if \isIntdatatype(z_,'W') then call err 'a not integernon─integer power:' z_
t=1; u=1; do j=1 for abs(z_); t=t*n.1; u=u*d.1
end /*j*/
if z_<0 then parse value t u with u t /*swap U and T */
end
when op=='/' then do; if n.2=0 then call err 'a zero divisor:' zz.2
t=n.1*d.2; u=n.2*d.1
end
when op=='÷' then do; if n.2=0 then call err 'a zero divisor:' zz.2
t=trunc(fractDiv$div(n.1 '/' d.1)); u=1
end /* [↑] integer division. this is integer division. */
when op=='//' then do; if n.2=0 then call err 'a zero divisor:' zz.2
_=trunc(fractDiv$div(n.1 '/' d.1)); t=_ - trunc(_) * d.1; u=1
end /* [↑] modulus division. */
when op=='ABS' then do; t=abs(n.1); u=abs(d.1); end
when op=='+' |,
when op=='-*' then do; l t=lcm(dn.1 d* n.2); do j=1 for 2; n.ju=l*n.j/d.j;1 * d.j=l2; end
when op=='EQ' | op=='=' then return $div(n.1 '/' d.1) = fDiv(n.2 '/' end /*j*/d.2)
when op=='NE' | op=='\=' | op=='╪' | ,
if op=='-' then n.2=-n.2; t=n.1+n.2; u=l
end op=='¬=' then return $div(n.1 '/' d.1) \= fDiv(n.2 '/' d.2)
when op=='ABSGT' | thenop=='>' do; t=abs then return $div(n.1); '/' u=abs(d.1); > fDiv(n.2 end'/' d.2)
when op=='*LT' | op=='<' then do; t=n.1*n.2; u=d then return $div(n.1* '/' d.2;1) < fDiv(n.2 '/' endd.2)
when op=='GE' | op=='≥' | op=='>=' then return $div(n.1 '/' d.1) >= fDiv(n.2 '/' d.2)
when op=='EQ' |,
when op=='LE' | op=='≤' | op=='<=' then return fractDiv$div(n.1 '/' d.1) <= fractDivfDiv(n.2 '/' d.2)
otherwise call err 'an illegal function:' op
when op=='NE' | op=='\=' | op=='╪' |,
op=='¬=' then return fractDiv(n.1 '/' d.1) \= fractDiv(n.2 '/' d.2)
when op=='GT' |,
op=='>' then return fractDiv(n.1 '/' d.1) > fractDiv(n.2 '/' d.2)
when op=='LT' |,
op=='<' then return fractDiv(n.1 '/' d.1) < fractDiv(n.2 '/' d.2)
when op=='GE' | op=='≥' |,
op=='>=' then return fractDiv(n.1 '/' d.1) >= fractDiv(n.2 '/' d.2)
when op=='LE' | op=='≤' |,
op=='<=' then return fractDiv(n.1 '/' d.1) <= fractDiv(n.2 '/' d.2)
otherwise call err 'an illegal function:' op
end /*select*/
 
if t==0 then return 0; g=gcd(t, u); t=t/g; u=u/g
if u==1 then return t
return t'/'u
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*─────────────────────────────general 1─line subs─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────*/
eDivs: procedure; parse arg x 1 b,a
divisors: procedure; parse arg x 1 b; if x=1 then return 1; a=1; o=x//2; do j=2+o by 1+o while j*j<x; if x//j\==0 then iterate; a=a j; b=x%j b; end; if j*j==x then b=j b; return a b
do j=2 while j*j<x; if x//j\==0 then iterate; a=a j; b=x%j b; end
err: say; say '***error!***'; say; say f "detected" arg(1); say; exit 13
if j*j==x then return a j b; return a b
gcd:procedure;$=;do i=1 for arg();$=$ arg(i);end;parse var $ x z .;if x=0 then x=z;x=abs(x);do j=2 to words($);y=abs(word($,j));if y=0 then iterate;do until _==0;_=x//y;x=y;y=_;end;end;return x
/*───────────────────────────────────────────────────────────────────────────────────────────────────*/
isInt: return datatype(arg(1),'W')
err: say; say '***error*** ' f " detected" arg(1); say; exit 13
isNum: return datatype(arg(1),'N')
lcmgcd: procedure; $=procedure; do j=1 forparse arg(); $=$ arg(j)x,y; end; if x=abs(word($,1)); 0 then return y; do k=2 to words($); until !_=abs(word($,k)); if !=0 then return 0; x_=x*!/gcd(/y; x,!)=y; y=_; end; return x
plcm: procedure; parse arg x,y; if y=0 then return word0; x=x*y/gcd(arg(1)x,1 y)</lang>; return x
p: return word( arg(1), 1)</syntaxhighlight>
Programming note: &nbsp; the &nbsp; '''eDivs, gcd, lcm''' &nbsp; functions are optimized functions for this program only.
 
'''output'''
<pre>
Line 2,484 ⟶ 4,593:
 
=={{header|Ruby}}==
Ruby has a Rational class in it's core since 1.9. Before that it was in standard library:
<syntaxhighlight lang="ruby">
<lang ruby>require 'rational' #Only needed in Ruby < 1.9
 
for candidate in 2 .. 2**19
sum = Rational(1, candidate)
for factor in 2 .. Integer. sqrt(candidate**0.5)
if candidate % factor == 0
sum += Rational(1, factor) + Rational(1, candidate / factor)
Line 2,498 ⟶ 4,606:
[candidate, sum.to_i, sum == 1 ? "perfect!" : ""]
end
end</langsyntaxhighlight>
{{out}}
<pre>
Line 2,512 ⟶ 4,620:
</pre>
 
=={{header|SchemeRust}}==
<syntaxhighlight lang="rust">use std::cmp::Ordering;
Scheme has native rational numbers.
use std::ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign, Neg};
{{works with|Scheme|R5RS}}
<lang scheme>; simply prints all the perfect numbers
(do ((candidate 2 (+ candidate 1))) ((>= candidate (expt 2 19)))
(let ((sum (/ 1 candidate)))
(do ((factor 2 (+ factor 1))) ((>= factor (sqrt candidate)))
(if (= 0 (modulo candidate factor))
(set! sum (+ sum (/ 1 factor) (/ factor candidate)))))
(if (= 1 (denominator sum))
(begin (display candidate) (newline)))))</lang>
It might be implemented like this:
 
fn gcd(a: i64, b: i64) -> i64 {
[insert implementation here]
match b {
0 => a,
_ => gcd(b, a % b),
}
}
 
fn lcm(a: i64, b: i64) -> i64 {
a / gcd(a, b) * b
}
 
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord)]
pub struct Rational {
numerator: i64,
denominator: i64,
}
 
impl Rational {
fn new(numerator: i64, denominator: i64) -> Self {
let divisor = gcd(numerator, denominator);
Rational {
numerator: numerator / divisor,
denominator: denominator / divisor,
}
}
}
 
impl Add for Rational {
type Output = Self;
 
fn add(self, other: Self) -> Self {
let multiplier = lcm(self.denominator, other.denominator);
Rational::new(self.numerator * multiplier / self.denominator +
other.numerator * multiplier / other.denominator,
multiplier)
}
}
 
impl AddAssign for Rational {
fn add_assign(&mut self, other: Self) {
*self = *self + other;
}
}
 
impl Sub for Rational {
type Output = Self;
 
fn sub(self, other: Self) -> Self {
self + -other
}
}
 
impl SubAssign for Rational {
fn sub_assign(&mut self, other: Self) {
*self = *self - other;
}
}
 
impl Mul for Rational {
type Output = Self;
 
fn mul(self, other: Self) -> Self {
Rational::new(self.numerator * other.numerator,
self.denominator * other.denominator)
}
}
 
impl MulAssign for Rational {
fn mul_assign(&mut self, other: Self) {
*self = *self * other;
}
}
 
impl Div for Rational {
type Output = Self;
 
fn div(self, other: Self) -> Self {
self *
Rational {
numerator: other.denominator,
denominator: other.numerator,
}
}
}
 
impl DivAssign for Rational {
fn div_assign(&mut self, other: Self) {
*self = *self / other;
}
}
 
impl Neg for Rational {
type Output = Self;
 
fn neg(self) -> Self {
Rational {
numerator: -self.numerator,
denominator: self.denominator,
}
}
}
 
impl PartialOrd for Rational {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
(self.numerator * other.denominator).partial_cmp(&(self.denominator * other.numerator))
}
}
 
impl<T: Into<i64>> From<T> for Rational {
fn from(value: T) -> Self {
Rational::new(value.into(), 1)
}
}
 
fn main() {
let max = 1 << 19;
for candidate in 2..max {
let mut sum = Rational::new(1, candidate);
for factor in 2..(candidate as f64).sqrt().ceil() as i64 {
if candidate % factor == 0 {
sum += Rational::new(1, factor);
sum += Rational::new(1, candidate / factor);
}
}
 
if sum == 1.into() {
println!("{} is perfect", candidate);
}
}
}
</syntaxhighlight>
 
=={{header|Scala}}==
<langsyntaxhighlight lang="scala">class Rational(n: Long, d:Long) extends Ordered[Rational]
{
require(d!=0)
Line 2,571 ⟶ 4,800:
def apply(n:Long)=new Rational(n)
implicit def longToRational(i:Long)=new Rational(i)
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="scala">def find_perfects():Unit=
{
for (candidate <- 2 until 1<<19)
Line 2,587 ⟶ 4,816:
printf("Perfect number %d sum is %s\n", candidate, sum)
}
}</langsyntaxhighlight>
 
=={{header|Scheme}}==
Scheme has native rational numbers.
{{works with|Scheme|R5RS}}
<syntaxhighlight lang="scheme">; simply prints all the perfect numbers
(do ((candidate 2 (+ candidate 1))) ((>= candidate (expt 2 19)))
(let ((sum (/ 1 candidate)))
(do ((factor 2 (+ factor 1))) ((>= factor (sqrt candidate)))
(if (= 0 (modulo candidate factor))
(set! sum (+ sum (/ 1 factor) (/ factor candidate)))))
(if (= 1 (denominator sum))
(begin (display candidate) (newline)))))</syntaxhighlight>
It might be implemented like this:
 
[insert implementation here]
 
=={{header|Seed7}}==
Line 2,597 ⟶ 4,841:
in the library [http://seed7.sourceforge.net/libraries/bigrat.htm bigrat.s7i].
 
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "rational.s7i";
 
Line 2,625 ⟶ 4,869:
end if;
end for;
end func;</langsyntaxhighlight>
 
{{out}}
Line 2,633 ⟶ 4,877:
496 is perfect
8128 is perfect
</pre>
 
=={{header|Sidef}}==
Sidef has built-in support for rational numbers.
<syntaxhighlight lang="ruby">for n in (1 .. 2**19) {
var frac = 0
 
n.divisors.each {|d|
frac += 1/d
}
 
if (frac.is_int) {
say "Sum of reciprocal divisors of #{n} = #{frac} exactly #{
frac == 2 ? '- perfect!' : ''
}"
}
}</syntaxhighlight>
{{out}}
<pre>
Sum of reciprocal divisors of 1 = 1 exactly
Sum of reciprocal divisors of 6 = 2 exactly - perfect!
Sum of reciprocal divisors of 28 = 2 exactly - perfect!
Sum of reciprocal divisors of 120 = 3 exactly
Sum of reciprocal divisors of 496 = 2 exactly - perfect!
Sum of reciprocal divisors of 672 = 3 exactly
Sum of reciprocal divisors of 8128 = 2 exactly - perfect!
Sum of reciprocal divisors of 30240 = 4 exactly
Sum of reciprocal divisors of 32760 = 4 exactly
Sum of reciprocal divisors of 523776 = 3 exactly
</pre>
 
=={{header|Slate}}==
Slate uses infinite-precision fractions transparently.
<langsyntaxhighlight lang="slate">54 / 7.
20 reciprocal.
(5 / 6) reciprocal.
(5 / 6) as: Float.</langsyntaxhighlight>
 
=={{header|Smalltalk}}==
Smalltalk uses ''naturally'' and transparently infinite precision fractions (through the class Fraction):
<pre>st> 54/7
54/7
Line 2,657 ⟶ 4,930:
0.8333333333333334
</pre>
{{works with|GNU Smalltalk}} (and all others)
<langsyntaxhighlight lang="smalltalk">| sum |
2 to: (2 raisedTo: 19) do: [ :candidate |
sum := candidate reciprocal.
Line 2,675 ⟶ 4,948:
ifFalse: [ ' ' ] }) displayNl
]
].</langsyntaxhighlight>
 
=={{header|Swift}}==
 
<syntaxhighlight lang="swift">import Foundation
 
extension BinaryInteger {
@inlinable
public func gcd(with other: Self) -> Self {
var gcd = self
var b = other
 
while b != 0 {
(gcd, b) = (b, gcd % b)
}
 
return gcd
}
 
@inlinable
public func lcm(with other: Self) -> Self {
let g = gcd(with: other)
 
return self / g * other
}
}
 
public struct Frac<NumType: BinaryInteger & SignedNumeric>: Equatable {
@usableFromInline
var _num: NumType
 
@usableFromInline
var _dom: NumType
 
@usableFromInline
init(_num: NumType, _dom: NumType) {
self._num = _num
self._dom = _dom
}
 
@inlinable
public init(numerator: NumType, denominator: NumType) {
let divisor = numerator.gcd(with: denominator)
 
self._num = numerator / divisor
self._dom = denominator / divisor
}
 
@inlinable
public static func + (lhs: Frac, rhs: Frac) -> Frac {
let multiplier = lhs._dom.lcm(with: rhs.denominator)
 
return Frac(
numerator: lhs._num * multiplier / lhs._dom + rhs._num * multiplier / rhs._dom,
denominator: multiplier
)
}
 
@inlinable
public static func += (lhs: inout Frac, rhs: Frac) {
lhs = lhs + rhs
}
 
@inlinable
public static func - (lhs: Frac, rhs: Frac) -> Frac {
return lhs + -rhs
}
 
@inlinable
public static func -= (lhs: inout Frac, rhs: Frac) {
lhs = lhs + -rhs
}
 
@inlinable
public static func * (lhs: Frac, rhs: Frac) -> Frac {
return Frac(numerator: lhs._num * rhs._num, denominator: lhs._dom * rhs._dom)
}
 
@inlinable
public static func *= (lhs: inout Frac, rhs: Frac) {
lhs = lhs * rhs
}
 
@inlinable
public static func / (lhs: Frac, rhs: Frac) -> Frac {
return lhs * Frac(_num: rhs._dom, _dom: rhs._num)
}
 
@inlinable
public static func /= (lhs: inout Frac, rhs: Frac) {
lhs = lhs / rhs
}
 
@inlinable
prefix static func - (rhs: Frac) -> Frac {
return Frac(_num: -rhs._num, _dom: rhs._dom)
}
}
 
extension Frac {
@inlinable
public var numerator: NumType {
get { _num }
set {
let divisor = newValue.gcd(with: denominator)
 
_num = newValue / divisor
_dom = denominator / divisor
}
}
 
@inlinable
public var denominator: NumType {
get { _dom }
set {
let divisor = newValue.gcd(with: numerator)
 
_num = numerator / divisor
_dom = newValue / divisor
}
}
}
 
extension Frac: CustomStringConvertible {
public var description: String {
let neg = numerator < 0 || denominator < 0
 
return "Frac(\(neg ? "-" : "")\(abs(numerator)) / \(abs(denominator)))"
}
}
 
extension Frac: Comparable {
@inlinable
public static func <(lhs: Frac, rhs: Frac) -> Bool {
return lhs._num * rhs._dom < lhs._dom * rhs._num
}
}
 
extension Frac: ExpressibleByIntegerLiteral {
public init(integerLiteral value: Int) {
self._num = NumType(value)
self._dom = 1
}
}
 
 
for candidate in 2..<1<<19 {
var sum = Frac(numerator: 1, denominator: candidate)
 
let m = Int(ceil(Double(candidate).squareRoot()))
 
for factor in 2..<m where candidate % factor == 0 {
sum += Frac(numerator: 1, denominator: factor)
sum += Frac(numerator: 1, denominator: candidate / factor)
}
 
if sum == 1 {
print("\(candidate) is perfect")
}
}</syntaxhighlight>
 
{{out}}
 
<pre>6 is perfect
28 is perfect
496 is perfect
8128 is perfect</pre>
 
=={{header|Tcl}}==
Line 2,684 ⟶ 5,123:
{{incomplete|TI-89 BASIC}}
While TI-89 BASIC has built-in rational and symbolic arithmetic, it does not have user-defined data types.
 
=={{header|Wren}}==
{{libheader|Wren-math}}
{{libheader|Wren-rat}}
The latter module already contains support for rational number arithmetic.
<syntaxhighlight lang="wren">import "./math" for Int
import "./rat" for Rat
 
System.print("The following numbers (less than 2^19) are perfect:")
for (i in 2...(1<<19)) {
var sum = Rat.new(1, i)
for (j in Int.properDivisors(i)[1..-1]) sum = sum + Rat.new(1, j)
if (sum == Rat.one) System.print(" %(i)")
}</syntaxhighlight>
 
{{out}}
<pre>
The following numbers (less than 2^19) are perfect:
6
28
496
8128
</pre>
 
=={{header|zkl}}==
Enough of a Rational class for this task (ie implement the testing code "nicely").
<syntaxhighlight lang="zkl">class Rational{ // Weenie Rational class, can handle BigInts
fcn init(_a,_b){ var a=_a, b=_b; normalize(); }
fcn toString{
if(b==1) a.toString()
else "%d//%d".fmt(a,b)
}
var [proxy] isZero=fcn{ a==0 };
fcn normalize{ // divide a and b by gcd
g:= a.gcd(b);
a/=g; b/=g;
if(b<0){ a=-a; b=-b; } // denominator > 0
self
}
fcn abs { a=a.abs(); self }
fcn __opNegate{ a=-a; self } // -Rat
fcn __opAdd(n){
if(Rational.isChildOf(n)) self(a*n.b + b*n.a, b*n.b); // Rat + Rat
else self(b*n + a, b); // Rat + Int
}
fcn __opSub(n){ self(a*n.b - b*n.a, b*n.b) } // Rat - Rat
fcn __opMul(n){
if(Rational.isChildOf(n)) self(a*n.a, b*n.b); // Rat * Rat
else self(a*n, b); // Rat * Int
}
fcn __opDiv(n){ self(a*n.b,b*n.a) } // Rat / Rat
fcn __opEQ(r){ // Rat==Rat, Rat==n
if(Rational.isChildOf(r)) a==r.a and b=r.b;
else b==1 and a==r;
}
}</syntaxhighlight>
<syntaxhighlight lang="zkl">foreach p in ([2 .. (2).pow(19)]){
sum,limit := Rational(1,p), p.toFloat().sqrt();
foreach factor in ([2 .. limit]){
if(p%factor == 0) sum+=Rational(1,factor) + Rational(factor,p);
}
if(sum.b==1) println("Sum of recipr. factors of %6s = %s exactly%s"
.fmt(p, sum, (sum==1) and ", perfect." or "."));
}</syntaxhighlight>
{{out}}
<pre>
Sum of recipr. factors of 6 = 1 exactly, perfect.
Sum of recipr. factors of 28 = 1 exactly, perfect.
Sum of recipr. factors of 120 = 2 exactly.
Sum of recipr. factors of 496 = 1 exactly, perfect.
Sum of recipr. factors of 672 = 2 exactly.
Sum of recipr. factors of 8128 = 1 exactly, perfect.
Sum of recipr. factors of 30240 = 3 exactly.
Sum of recipr. factors of 32760 = 3 exactly.
Sum of recipr. factors of 523776 = 2 exactly.
</pre>
9,476

edits