Jump to content

Arithmetic/Rational: Difference between revisions

Improved and updated D entry
(Updated D entry)
(Improved and updated D entry)
Line 368:
 
=={{header|D}}==
<lang d>import std.bigint, std.traits, std.conv;
Rational implementation based on BigInt. Currently this is not fast.
<lang d>import std.bigint, std.traits;
 
T gcd(T)(/*in*/ T a, /*in*/ T b) /*pure nothrow*/ {
// std.numeric.gcd doesn't work with BigInt.
return (b != 0) ? gcd(b, a % b) : (a < 0) ? -a : a;
}
Line 380 ⟶ 379:
}
 
struct RationalRationalT(T) {
BigInt toBig(T : BigInt)(/*const*/ ref T n) pure nothrow { return n; }
/*const*/ private BigIntT num, den; // numeratorNumerator & denominator.
 
BigInt toBig(T)(in ref T n) pure nothrow if (isIntegral!T) {
return BigInt(n);
}
 
struct Rational {
/*const*/ private BigInt num, den; // numerator & denominator
 
private enum Type { NegINF = -2,
Line 395 ⟶ 388:
PosINF = 2 };
 
this(U : RationalRationalT)(U n) pure nothrow {
num = n.num;
den = n.den;
Line 401 ⟶ 394:
 
this(U)(in U n) pure nothrow if (isIntegral!U) {
num = toBigtoT(n);
den = 1UL;
}
 
this(U, V)(/*in*/ U n, /*in*/ V d) /*pure nothrow*/ {
num = toBigtoT(n);
den = toBigtoT(d);
/*const*/ BigIntT common = gcd(num, den);
if (common != 0) {
num /= common;
Line 416 ⟶ 409:
den = 0;
}
if (den < 0) { // assureAssure den is non-negative.
num = -num;
den = -den;
Line 422 ⟶ 415:
}
 
BigIntstatic nomeratorT toT(U) (/*constin*/ ref U n) pure nothrow @propertyif (is(U == T)) {
return BigInt(n);
}
 
BigInt toBig( static T toT(U)(in ref TU n) pure nothrow if (isIntegral!is(U == T)) {
T result = n;
return result;
}
 
T nomerator() /*const*/ pure nothrow @property {
return num;
}
 
BigIntT denominator() /*const*/ pure nothrow @property {
return den;
}
Line 437 ⟶ 439:
return ((num < 0) ? "-" : "+") ~ "infRat";
}
return toDecimalStringtext(num) ~ (den == 1 ? "" : ("/" ~ text(den)));
(den == 1 ? "" : ("/" ~ toDecimalString(den)));
}
 
RationalRationalT opBinary(string op)(/*in*/ RationalRationalT r)
/*const pure nothrow*/ if (op == "+" || op == "-") {
BigIntT common = lcm(den, r.den);
BigIntT n = mixin("common / den * num" ~ op ~
"common / r.den * r.num" );
return RationalRationalT(n, common);
}
 
RationalRationalT opBinary(string op)(/*in*/ RationalRationalT r)
/*const pure nothrow*/ if (op == "*") {
return RationalRationalT(num * r.num, den * r.den);
}
 
RationalRationalT opBinary(string op)(/*in*/ RationalRationalT r)
/*const pure nothrow*/ if (op == "/") {
return RationalRationalT(num * r.den, den * r.num);
}
 
RationalRationalT opBinary(string op, TU)(in TU r)
/*const pure nothrow*/ if (isIntegral!TU && (op == "+" ||
op == "-" || op == "*" || op == "/")) {
return opBinary!op(RationalRationalT(r));
}
 
RationalRationalT opBinary(string op)(in size_t p)
/*const pure nothrow*/ if (op == "^^") {
return RationalRationalT(num ^^ p, den ^^ p);
}
 
RationalRationalT opBinaryRight(string op, TU)(in TU l)
/*const pure nothrow*/ if (isIntegral!TU) {
return RationalRationalT(l).opBinary!op(RationalRationalT(num, den));
}
 
RationalRationalT opUnaryopOpAssign(string op, U)(in U l)
/*const pure nothrow*/ {
mixin("this = this " ~ op ~ "l;");
return this;
}
 
RationalT opUnary(string op)()
/*const pure nothrow*/ if (op == "+" || op == "-") {
return RationalRationalT(mixin(op ~ "num"), den);
}
 
bool opCast(TU)() const if (is(TU == bool)) {
return num != 0;
}
 
int opEquals(TU)(/*in*/ TU r) /*const pure nothrow*/ {
RationalRationalT rhs = RationalRationalT(r);
if (type() == Type.NaRAT || rhs.type() == Type.NaRAT)
return false;
Line 491 ⟶ 498:
}
 
int opCmp(TU)(/*in*/ TU r) /*const pure nothrow*/ {
auto rhs = RationalRationalT(r);
if (type() == Type.NaRAT || rhs.type() == Type.NaRAT)
throw new Exception("Compare invloveinvolve ana NaRAT.");
if (type() != Type.NORMAL ||
rhs.type() != Type.NORMAL) // for infinite
return (type() == rhs.type()) ? 0 :
((type() < rhs.type()) ? -1 : 1);
BigIntU diff = num * rhs.den - den * rhs.num;
return (diff == 0) ? 0 : ((diff < 0) ? -1 : 1);
}
Line 512 ⟶ 519:
}
 
alias Rational = RationalT!BigInt;
version (arithmetic_rational_main) { // test part
void main() {
import std.stdio, std.math;
 
version (arithmetic_rational_main) { // test partTest.
foreach (p; 2 .. 2 ^^ 19) {
void main() {
auto sum = Rational(1, p);
import std.stdio, std.math;
immutable limit = 1 + cast(uint)sqrt(cast(real)p);
foreachalias (factor;RatL 2= .. limit)RationalT!long;
 
if (p % factor == 0)
foreach (immutable p; 2 .. 2 ^^ 19) {
sum = sum + Rational(1, factor) + Rational(factor, p);
if ( auto sum.denominator == RatL(1, p);
writefln("Sumimmutable oflimit recipr.= factors1 of+ %6s = %s exactly%s",cast(uint)sqrt(cast(real)p);
p, sum,foreach (sumimmutable ==factor; 1)2 ? ", perfect.". : "."limit);
if (p % factor == 0)
sum = sum += RationalRatL(1, factor) + RationalRatL(factor, p);
if (sum.denominator == 1)
writefln("Sum of recipr. factors of 120%6s = 2%s exactly.%s",
p, sum, (sum == 1) ? ", perfect." : ".");
}
}
}
}</lang>
Use the <code>-version=rational_arithmetic_main</code> compiler switch to run the test code.
{{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.</pre>
Run-time is about 9.5 seconds. It's quite slow because in DMD v.2.060 BigInts have no memory optimizations.
 
Output using p up to 2^^19, as requested by the task:
<pre>Sum of recipr. factors of 6 = 1 exactly, perfect.
Sum of recipr. factors of 28 = 1 exactly, perfect.
Line 550 ⟶ 549:
Sum of recipr. factors of 32760 = 3 exactly.
Sum of recipr. factors of 523776 = 2 exactly.</pre>
Currently RationalT!BigInt is not fast.
 
=={{header|Elisa}}==
Cookies help us deliver our services. By using our services, you agree to our use of cookies.