Arithmetic/Rational: Difference between revisions

Content added Content deleted
m (→‎{{header|Quackery}}: tweaked commentary)
Line 1,947: Line 1,947:
<div style="text-align:right;font-size:7pt">''<nowiki>[</nowiki>This section is included from [[Arithmetic/Rational/JavaScript|a subpage]] and should be edited there, not here.<nowiki>]</nowiki>''</div>
<div style="text-align:right;font-size:7pt">''<nowiki>[</nowiki>This section is included from [[Arithmetic/Rational/JavaScript|a subpage]] and should be edited there, not here.<nowiki>]</nowiki>''</div>
{{:Arithmetic/Rational/JavaScript}}
{{:Arithmetic/Rational/JavaScript}}

=={{header|jq}}==
{{works with|jq}}
'''Works with gojq, the Go implementation of jq'''

In this entry, a jq module for rational arithmetic is first
presented. It can be included or imported using jq's "include" or
"import" directives. The module is slightly incomplete but is
presented here so that it can be included by reference in the jq
solution (forthcoming) at the RC page [[Faulhaber%27s_triangle]].

The constructor is named "r" rather than "frac", mainly because "r" is
short and handy for what is here more than a simple constructor (it
can also be used for normalization and to divide one rational by
another), and because name conflicts can easily be resolved using jq's
module system.

The other operators for working with rationals also begin with the letter "r":
* `rabs` for unary `abs`
* `rinv` for unary inverse
* `rminus` for unary minus

* `radd` for addition
* `rdiv` for division
* `requal` for testing equality
* `rmult` for multiplication
* `rpp` for pretty-printing
<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 with 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 "Rational";'''
<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;

# $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;

def r: r(.;1);

# 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;

# 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: rmult(-1; .);

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);

# pretty print ala Julia
def rpp: "\(.n) // \(.d)";</lang>

'''Perfect Numbers'''
<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 )
</lang>
{{out}}
<pre>
6
28
496
8128
</pre>



=={{header|Julia}}==
=={{header|Julia}}==