⚠️ Warning: This is a draft ⚠️
This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.
If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.
// the constructor function Rational(numerator, denominator) { if (denominator === undefined) denominator = 1; else if (denominator == 0) throw "divide by zero"; this.numer = numerator; if (this.numer == 0) this.denom = 1; else this.denom = denominator; this.normalize(); } // getter methods Rational.prototype.numerator = function() {return this.numer}; Rational.prototype.denominator = function() {return this.denom}; // clone a rational Rational.prototype.dup = function() { return new Rational(this.numerator(), this.denominator()); }; // conversion methods Rational.prototype.toString = function() { if (this.denominator() == 1) { return this.numerator().toString(); } else { // implicit conversion of numbers to strings return this.numerator() + '/' + this.denominator() } }; Rational.prototype.toFloat = function() {return eval(this.toString())} Rational.prototype.toInt = function() {return Math.floor(this.toFloat())}; // reduce Rational.prototype.normalize = function() { // greatest common divisor var a=Math.abs(this.numerator()), b=Math.abs(this.denominator()) while (b != 0) { var tmp = a; a = b; b = tmp % b; } // a is the gcd this.numer /= a; this.denom /= a; if (this.denom < 0) { this.numer *= -1; this.denom *= -1; } return this; } // absolute value // returns a new rational Rational.prototype.abs = function() { return new Rational(Math.abs(this.numerator()), this.denominator()); }; // inverse // returns a new rational Rational.prototype.inv = function() { return new Rational(this.denominator(), this.numerator()); }; // // arithmetic methods // variadic, modifies receiver Rational.prototype.add = function() { for (var i = 0; i < arguments.length; i++) { this.numer = this.numer * arguments[i].denominator() + this.denom * arguments[i].numerator(); this.denom = this.denom * arguments[i].denominator(); } return this.normalize(); }; // variadic, modifies receiver Rational.prototype.subtract = function() { for (var i = 0; i < arguments.length; i++) { this.numer = this.numer * arguments[i].denominator() - this.denom * arguments[i].numerator(); this.denom = this.denom * arguments[i].denominator(); } return this.normalize(); }; // unary "-" operator // returns a new rational Rational.prototype.neg = function() { return (new Rational(0)).subtract(this); }; // variadic, modifies receiver Rational.prototype.multiply = function() { for (var i = 0; i < arguments.length; i++) { this.numer *= arguments[i].numerator(); this.denom *= arguments[i].denominator(); } return this.normalize(); }; // modifies receiver Rational.prototype.divide = function(rat) { return this.multiply(rat.inv()); } // increment // modifies receiver Rational.prototype.inc = function() { this.numer += this.denominator(); return this.normalize(); } // decrement // modifies receiver Rational.prototype.dec = function() { this.numer -= this.denominator(); return this.normalize(); } // // comparison methods Rational.prototype.isZero = function() { return (this.numerator() == 0); } Rational.prototype.isPositive = function() { return (this.numerator() > 0); } Rational.prototype.isNegative = function() { return (this.numerator() < 0); } Rational.prototype.eq = function(rat) { return this.dup().subtract(rat).isZero(); } Rational.prototype.ne = function(rat) { return !(this.eq(rat)); } Rational.prototype.lt = function(rat) { return this.dup().subtract(rat).isNegative(); } Rational.prototype.gt = function(rat) { return this.dup().subtract(rat).isPositive(); } Rational.prototype.le = function(rat) { return !(this.gt(rat)); } Rational.prototype.ge = function(rat) { return !(this.lt(rat)); }
;Testing
function assert(cond, msg) { if (!cond) throw msg; } print('testing') var a, b, c, d, e, f; //test creation a = new Rational(0); assert(a.toString() == "0", "Rational(0).toString() == '0'") a = new Rational(2); assert(a.toString() == "2", "Rational(2).toString() == '2'") a = new Rational(1,2); assert(a.toString() == "1/2", "Rational(1,2).toString() == '1/2'") b = new Rational(2,-12); assert(b.toString() == "-1/6", "Rational(1,6).toString() == '1/6'") f = new Rational(0,9) a = new Rational(1,3) b = new Rational(1,2) c = new Rational(1,3) assert(!(a.eq(b)), "1/3 == 1/2") assert(a.eq(c), "1/3 == 1/3") assert(a.ne(b), "1/3 != 1/2") assert(!(a.ne(c)), "1/3 != 1/3") assert(a.lt(b), "1/3 < 1/2") assert(!(b.lt(a)), "1/2 < 1/3") assert(!(a.lt(c)), "1/3 < 1/3") assert(!(a.gt(b)), "1/3 > 1/2") assert(b.gt(a), "1/2 > 1/3") assert(!(a.gt(c)), "1/3 > 1/3") assert(a.le(b), "1/3 <= 1/2") assert(!(b.le(a)), "1/2 <= 1/3") assert(a.le(c), "1/3 <= 1/3") assert(!(a.ge(b)), "1/3 >= 1/2") assert(b.ge(a), "1/2 >= 1/3") assert(a.ge(c), "1/3 >= 1/3") a = new Rational(1,2) b = new Rational(1,6) a.add(b); assert(a.eq(new Rational(2,3)), "1/2 + 1/6 == 2/3") c = a.neg(); assert(a.eq(new Rational(2,3)), "neg(1/2) == -1/2") assert(c.eq(new Rational(2,-3)), "neg(1/2) == -1/2") d = c.abs(); assert(c.eq(new Rational(-2,3)), "abs(neg(1/2)) == 1/2") assert(d.eq(new Rational(2,3)), "abs(neg(1/2)) == 1/2") b.subtract(a); assert(b.eq(new Rational(-1,2)), "1/6 - 1/2 == -1/3") c = a.neg().abs(); assert(c.eq(a), "abs(neg(1/2)) == 1/2") c = (new Rational(-1,3)).inv(); assert(c.toString() == '-3', "inv(1/6 - 1/2) == -3") try { e = f.inv(); throw "should have been an error: " +f + '.inv() = ' + e } catch (e) { assert(e == "divide by zero", "0.inv() === error") } b = new Rational(1,6) b.add(new Rational(2,3), new Rational(4,2)); assert(b.toString() == "17/6", "1/6+2/3+4/2 == 17/6"); a = new Rational(1,3); b = new Rational(1,6) c = new Rational(5,6); d = new Rational(1/5); e = new Rational(2); f = new Rational(0,9); assert(c.dup().multiply(d).eq(b), "5/6 * 1/5 = 1/6") assert(c.dup().multiply(d,e).eq(a), "5/6 * 1/5 *2 = 1/3") assert(c.dup().multiply(d,e,f).eq(f), "5/6 * 1/5 *2*0 = 0") c.divide(new Rational(5)); assert(c.eq(b), "5/6 / 5 = 1/6b") try { e = c.divide(f) throw "should have been an error: " + c + "/" + f + '= ' + e } catch (e) { assert(e == "divide by zero", "0.inv() === error") } print('all tests passed');
;Finding perfect numbers
function factors(num) { var factors = new Array(); var sqrt = Math.floor(Math.sqrt(num)); for (var i = 1; i <= sqrt; i++) { if (num % i == 0) { factors.push(i); if (num / i != i) factors.push(num / i); } } factors.sort(function(a,b){return a-b}); // numeric sort return factors; } function isPerfect(n) { var sum = new Rational(0); var fctrs = factors(n); for (var i = 0; i < fctrs.length; i++) sum.add(new Rational(1, fctrs[i])); // note, fctrs includes 1, so sum should be 2 return sum.toFloat() == 2.0; } // find perfect numbers less than 2^19 for (var n = 2; n < Math.pow(2,19); n++) if (isPerfect(n)) print("perfect: " + n); // test 5th perfect number var n = Math.pow(2,12) * (Math.pow(2,13) - 1); if (isPerfect(n)) print("perfect: " + n);
{{out}}
perfect: 6
perfect: 28
perfect: 496
perfect: 8128
perfect: 33550336