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}}== |