September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -1,30 +1,27 @@
|
|||
class BigRationalFindPerfectNumbers {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Running BigRational built-in tests");
|
||||
if (BigRational.testFeatures()) {
|
||||
int MAX_NUM = (1 << 19);
|
||||
System.out.println();
|
||||
System.out.println("Searching for perfect numbers in the range [1, " + (MAX_NUM - 1) + "]");
|
||||
BigRational TWO = BigRational.valueOf(2);
|
||||
for (int i = 1; i < MAX_NUM; i++) {
|
||||
BigRational reciprocalSum = BigRational.ONE;
|
||||
if (i > 1)
|
||||
reciprocalSum = reciprocalSum.add(BigRational.valueOf(i).reciprocal());
|
||||
int maxDivisor = (int)Math.sqrt(i);
|
||||
if (maxDivisor >= i)
|
||||
maxDivisor--;
|
||||
for (int divisor = 2; divisor <= maxDivisor; divisor++) {
|
||||
if ((i % divisor) == 0) {
|
||||
reciprocalSum = reciprocalSum.add(BigRational.valueOf(divisor).reciprocal());
|
||||
int dividend = i / divisor;
|
||||
if (divisor != dividend)
|
||||
reciprocalSum = reciprocalSum.add(BigRational.valueOf(dividend).reciprocal());
|
||||
}
|
||||
public class BigRationalFindPerfectNumbers {
|
||||
public static void main(String[] args) {
|
||||
int MAX_NUM = 1 << 19;
|
||||
System.out.println("Searching for perfect numbers in the range [1, " + (MAX_NUM - 1) + "]");
|
||||
|
||||
BigRational TWO = BigRational.valueOf(2);
|
||||
for (int i = 1; i < MAX_NUM; i++) {
|
||||
BigRational reciprocalSum = BigRational.ONE;
|
||||
if (i > 1)
|
||||
reciprocalSum = reciprocalSum.add(BigRational.valueOf(i).reciprocal());
|
||||
int maxDivisor = (int) Math.sqrt(i);
|
||||
if (maxDivisor >= i)
|
||||
maxDivisor--;
|
||||
|
||||
for (int divisor = 2; divisor <= maxDivisor; divisor++) {
|
||||
if (i % divisor == 0) {
|
||||
reciprocalSum = reciprocalSum.add(BigRational.valueOf(divisor).reciprocal());
|
||||
int dividend = i / divisor;
|
||||
if (divisor != dividend)
|
||||
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");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
127
Task/Arithmetic-Rational/Kotlin/arithmetic-rational.kotlin
Normal file
127
Task/Arithmetic-Rational/Kotlin/arithmetic-rational.kotlin
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
// 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()
|
||||
}
|
||||
163
Task/Arithmetic-Rational/OoRexx/arithmetic-rational.rexx
Normal file
163
Task/Arithmetic-Rational/OoRexx/arithmetic-rational.rexx
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
loop candidate = 6 to 2**19
|
||||
sum = .fraction~new(1, candidate)
|
||||
max2 = rxcalcsqrt(candidate)~trunc
|
||||
|
||||
loop factor = 2 to max2
|
||||
if candidate // factor == 0 then do
|
||||
sum += .fraction~new(1, factor)
|
||||
sum += .fraction~new(1, candidate / factor)
|
||||
end
|
||||
end
|
||||
if sum == 1 then say candidate "is a perfect number"
|
||||
end
|
||||
|
||||
::class fraction inherit orderable
|
||||
::method init
|
||||
expose numerator denominator
|
||||
use strict arg numerator, denominator = 1
|
||||
|
||||
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
|
||||
if denominator < 0 then do
|
||||
numerator = -numerator
|
||||
denominator = - denominator
|
||||
end
|
||||
|
||||
|
||||
-- find the greatest common denominator and reduce to
|
||||
-- the simplest form
|
||||
gcd = self~gcd(numerator~abs, denominator~abs)
|
||||
|
||||
numerator /= gcd
|
||||
denominator /= gcd
|
||||
|
||||
-- fraction instances are immutable, so these are
|
||||
-- read only attributes
|
||||
::attribute numerator GET
|
||||
::attribute denominator GET
|
||||
|
||||
-- calculate the greatest common denominator of a numerator/denominator pair
|
||||
::method gcd private
|
||||
use arg x, y
|
||||
|
||||
loop while y \= 0
|
||||
-- check if they divide evenly
|
||||
temp = x // y
|
||||
x = y
|
||||
y = temp
|
||||
end
|
||||
return x
|
||||
|
||||
-- calculate the least common multiple of a numerator/denominator pair
|
||||
::method lcm private
|
||||
use arg x, y
|
||||
return x / self~gcd(x, y) * y
|
||||
|
||||
::method abs
|
||||
expose numerator denominator
|
||||
-- the denominator is always forced to be positive
|
||||
return self~class~new(numerator~abs, denominator)
|
||||
|
||||
::method reciprocal
|
||||
expose numerator denominator
|
||||
return self~class~new(denominator, numerator)
|
||||
|
||||
-- convert a fraction to regular Rexx number
|
||||
::method toNumber
|
||||
expose numerator denominator
|
||||
|
||||
if numerator == 0 then return 0
|
||||
return numerator/denominator
|
||||
|
||||
::method negative
|
||||
expose numerator denominator
|
||||
return self~class~new(-numerator, denominator)
|
||||
|
||||
::method add
|
||||
expose numerator denominator
|
||||
use strict arg other
|
||||
-- convert to a fraction if a regular number
|
||||
if \other~isa(.fraction) then other = self~class~new(other, 1)
|
||||
|
||||
multiple = self~lcm(denominator, other~denominator)
|
||||
newa = numerator * multiple / denominator
|
||||
newb = other~numerator * multiple / other~denominator
|
||||
return self~class~new(newa + newb, multiple)
|
||||
|
||||
::method subtract
|
||||
use strict arg other
|
||||
return self + (-other)
|
||||
|
||||
::method times
|
||||
expose numerator denominator
|
||||
use strict arg other
|
||||
-- convert to a fraction if a regular number
|
||||
if \other~isa(.fraction) then other = self~class~new(other, 1)
|
||||
return self~class~new(numerator * other~numerator, denominator * other~denominator)
|
||||
|
||||
::method divide
|
||||
use strict arg other
|
||||
-- convert to a fraction if a regular number
|
||||
if \other~isa(.fraction) then other = self~class~new(other, 1)
|
||||
-- and multiply by the reciprocal
|
||||
return self * other~reciprocal
|
||||
|
||||
-- compareTo method used by the orderable interface to implement
|
||||
-- the operator methods
|
||||
::method compareTo
|
||||
expose numerator denominator
|
||||
-- convert to a fraction if a regular number
|
||||
if \other~isa(.fraction) then other = self~class~new(other, 1)
|
||||
|
||||
return (numerator * other~denominator - denominator * other~numerator)~sign
|
||||
|
||||
-- we still override "==" and "\==" because we want to bypass the
|
||||
-- checks for not being an instance of the class
|
||||
::method "=="
|
||||
expose numerator denominator
|
||||
use strict arg other
|
||||
|
||||
-- convert to a fraction if a regular number
|
||||
if \other~isa(.fraction) then other = self~class~new(other, 1)
|
||||
-- Note: these are numeric comparisons, so we're using the "="
|
||||
-- method so those are handled correctly
|
||||
return numerator = other~numerator & denominator = other~denominator
|
||||
|
||||
::method "\=="
|
||||
use strict arg other
|
||||
return \self~"\=="(other)
|
||||
|
||||
-- some operator overrides -- these only work if the left-hand-side of the
|
||||
-- subexpression is a quaternion
|
||||
::method "*"
|
||||
forward message("TIMES")
|
||||
|
||||
::method "/"
|
||||
forward message("DIVIDE")
|
||||
|
||||
::method "-"
|
||||
-- need to check if this is a prefix minus or a subtract
|
||||
if arg() == 0 then
|
||||
forward message("NEGATIVE")
|
||||
else
|
||||
forward message("SUBTRACT")
|
||||
|
||||
::method "+"
|
||||
-- need to check if this is a prefix plus or an addition
|
||||
if arg() == 0 then
|
||||
return self -- we can return this copy since it is imutable
|
||||
else
|
||||
forward message("ADD")
|
||||
|
||||
::method string
|
||||
expose numerator denominator
|
||||
if denominator == 1 then return numerator
|
||||
return numerator"/"denominator
|
||||
|
||||
-- override hashcode for collection class hash uses
|
||||
::method hashCode
|
||||
expose numerator denominator
|
||||
return numerator~hashcode~bitxor(numerator~hashcode)
|
||||
|
||||
::requires rxmath library
|
||||
|
|
@ -1,92 +1,87 @@
|
|||
/*REXX pgm implements a reasonably complete rational arithmetic (fract.)*/
|
||||
L=length(2**19-1) /*saves time by checking even #s.*/
|
||||
do j=2 to 2**19-1 by 2 /*ignore unity (can't be perfect)*/
|
||||
$=divisors(j); s=0; @= /*get divisors, zero sum, null @.*/
|
||||
do k=2 to words($) /*ignore unity.*/
|
||||
r='1/'word($,k); @=@ r; s=fractFun(r,,s)
|
||||
end /*k*/
|
||||
if s\==1 then iterate
|
||||
say 'perfect number:' right(j,L) ' fractions:' @
|
||||
/*REXX program implements a reasonably complete rational arithmetic (using fractions).*/
|
||||
L=length(2**19 - 1) /*saves time by checking even numbers. */
|
||||
do j=2 by 2 to 2**19 - 1; s=0 /*ignore unity (which can't be perfect)*/
|
||||
mostDivs=eDivs(j); @= /*obtain divisors>1; zero sum; null @. */
|
||||
do k=1 for words(mostDivs) /*unity isn't return from eDivs here.*/
|
||||
r='1/'word(mostDivs, k); @=@ r; s=$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 done.*/
|
||||
/*──────────────────────────────────FRACTDIV subroutine─────────────────*/
|
||||
fractDiv: procedure; parse arg x; x=space(x,0); f='FractDiv'
|
||||
parse var x n '/' d; d=p(d 1)
|
||||
if d=0 then call err 'division by zero:' x
|
||||
if \isNum(n) then call err 'a not numeric numerator:' x
|
||||
if \isNum(d) then call err 'a not numeric denominator:' x
|
||||
return n/d
|
||||
/*──────────────────────────────────FRACTFUN subroutine─────────────────*/
|
||||
fractFun: procedure; parse arg z.1,,z.2 1 zz.2,f; arg ,op; op=p(op '+')
|
||||
f='FractFun'; 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('MODULO' ,op,3) | abbrev('MODULUS' ,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\=='-')
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
$div: procedure; parse arg x; x=space(x,0); f= 'fractional division'
|
||||
parse var x n '/' d; d=p(d 1)
|
||||
if d=0 then call err 'division by zero:' x
|
||||
if \datatype(n,'N') then call err 'a non─numeric numerator:' x
|
||||
if \datatype(d,'N') then call err 'a non─numeric denominator:' x
|
||||
return n/d
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
$fun: procedure; parse arg z.1,,z.2 1 zz.2; arg ,op; op=p(op '+')
|
||||
F= 'fractionalFunction'; 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('MODULUS' , op, 3) | abbrev('MODULO', 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\=='-')
|
||||
if z.2=='' then z.2= (op\=="+" & op\=='-')
|
||||
z_=z.2
|
||||
|
||||
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 \isNum(n.j) then call err 'a not numeric numerator:' n.j
|
||||
if \isNum(d.j) then call err 'a not numeric denominator:' 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
|
||||
end /*while*/ /* [↑] normalize both numbers. */
|
||||
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
|
||||
/* [↑] verification of both fractions.*/
|
||||
do j=1 for 2
|
||||
if pos('/', z.j)==0 then z.j=z.j"/1"; parse var z.j n.j '/' d.j
|
||||
if \datatype(n.j,'N') then call err 'a non─numeric numerator:' n.j
|
||||
if \datatype(d.j,'N') then call err 'a non─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 \datatype(n.j,'W'); n.j=(n.j*10)/1; d.j=(d.j*10)/1
|
||||
end /*while*/ /* [↑] {xxx/1} normalizes a number. */
|
||||
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 \isInt(z_) then call err 'a not 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
|
||||
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(n.1 '/' d.1)); u=1
|
||||
end /* [↑] integer division. */
|
||||
when op=='//' then do; if n.2=0 then call err 'a zero divisor:' zz.2
|
||||
_=trunc(fractDiv(n.1 '/' d.1)); t=_-trunc(_)*d.1; u=1
|
||||
end /* [↑] modulus division. */
|
||||
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=='ABS' then do; t=abs(n.1); u=abs(d.1); end
|
||||
when op=='*' then do; t=n.1*n.2; u=d.1*d.2; end
|
||||
when op=='EQ' |,
|
||||
op=='=' then return fractDiv(n.1 '/' d.1) = fractDiv(n.2 '/' d.2)
|
||||
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
|
||||
op=='^' then do; if \datatype(z_,'W') then call err 'a non─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($div(n.1 '/' d.1)); u=1
|
||||
end /* [↑] this is integer division. */
|
||||
when op=='//' then do; if n.2=0 then call err 'a zero divisor:' zz.2
|
||||
_=trunc($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=='*' then do; t=n.1 * n.2; u=d.1 * d.2; end
|
||||
when op=='EQ' | op=='=' then return $div(n.1 '/' d.1) = fDiv(n.2 '/' d.2)
|
||||
when op=='NE' | op=='\=' | op=='╪' | ,
|
||||
op=='¬=' then return $div(n.1 '/' d.1) \= fDiv(n.2 '/' d.2)
|
||||
when op=='GT' | op=='>' then return $div(n.1 '/' d.1) > fDiv(n.2 '/' d.2)
|
||||
when op=='LT' | op=='<' then return $div(n.1 '/' d.1) < fDiv(n.2 '/' d.2)
|
||||
when op=='GE' | op=='≥' | op=='>=' then return $div(n.1 '/' d.1) >= fDiv(n.2 '/' d.2)
|
||||
when op=='LE' | op=='≤' | op=='<=' then return $div(n.1 '/' d.1) <= fDiv(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 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─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────*/
|
||||
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
|
||||
err: say; say '***error!***'; say; say f "detected" arg(1); say; exit 13
|
||||
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')
|
||||
isNum: return datatype(arg(1),'N')
|
||||
lcm: procedure; $=; do j=1 for arg(); $=$ arg(j); end; x=abs(word($,1)); do k=2 to words($); !=abs(word($,k)); if !=0 then return 0; x=x*!/gcd(x,!); end; return x
|
||||
p: return word(arg(1),1)
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
eDivs: procedure; parse arg x 1 b,a
|
||||
do j=2 while j*j<x; if x//j\==0 then iterate; a=a j; b=x%j b; end
|
||||
if j*j==x then return a j b; return a b
|
||||
/*───────────────────────────────────────────────────────────────────────────────────────────────────*/
|
||||
err: say; say '***error*** ' f " detected" arg(1); say; exit 13
|
||||
gcd: procedure; parse arg x,y; if x=0 then return y; do until _==0; _=x//y; x=y; y=_; end; return x
|
||||
lcm: procedure; parse arg x,y; if y=0 then return 0; x=x*y/gcd(x, y); return x
|
||||
p: return word( arg(1), 1)
|
||||
|
|
|
|||
30
Task/Arithmetic-Rational/Zkl/arithmetic-rational-1.zkl
Normal file
30
Task/Arithmetic-Rational/Zkl/arithmetic-rational-1.zkl
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
8
Task/Arithmetic-Rational/Zkl/arithmetic-rational-2.zkl
Normal file
8
Task/Arithmetic-Rational/Zkl/arithmetic-rational-2.zkl
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
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 "."));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue