Skip to content

Instantly share code, notes, and snippets.

@leontastic
Last active November 28, 2016 03:15
Show Gist options
  • Select an option

  • Save leontastic/8e42bbfb0d97b8f4f5dc to your computer and use it in GitHub Desktop.

Select an option

Save leontastic/8e42bbfb0d97b8f4f5dc to your computer and use it in GitHub Desktop.

Revisions

  1. leontastic revised this gist Sep 8, 2015. 1 changed file with 41 additions and 4 deletions.
    45 changes: 41 additions & 4 deletions fraction.js
    Original file line number Diff line number Diff line change
    @@ -18,6 +18,9 @@
    subtract([n|Number|Fraction]) => [Fraction] returns fraction minus n
    multiply([n|Number|Fraction]) => [Fraction] returns fraction multiplied by n
    divide([n|Number|Fraction]) => [Fraction] returns fraction divided by n
    mod([n|Number|Fraction]) => [Fraction] returns fraction mod n
    lt([n|Number|Fraction]) => [Boolean] returns true if fraction is less than n
    gt([n|Number|Fraction]) => [Boolean] returns true if fraction is greater than n
    toNumber() => [Number] returns the native Number representation of the fraction
    */

    @@ -65,7 +68,7 @@ class Fraction {

    // add a number or fraction to this fraction
    add(n) {
    if (!n instanceof Fraction) n = new Fraction(n);
    if (!(n instanceof Fraction)) n = new Fraction(n);
    let output = new Fraction(this); // copy this fraction

    let multiple = Fraction.lcm(output.denominator, n.denominator);
    @@ -77,7 +80,7 @@ class Fraction {

    // subtract a number or fraction from this fraction
    subtract(n) {
    if (!n instanceof Fraction) n = new Fraction(n);
    if (!(n instanceof Fraction)) n = new Fraction(n);
    let output = new Fraction(this); // copy this fraction

    let multiple = Fraction.lcm(output.denominator, n.denominator);
    @@ -89,7 +92,7 @@ class Fraction {

    // multiply this fraction by a number or fraction
    multiply(n) {
    if (!n instanceof Fraction) n = new Fraction(n);
    if (!(n instanceof Fraction)) n = new Fraction(n);
    let output = new Fraction(this); // copy this fraction

    output.numerator *= n.numerator;
    @@ -100,7 +103,7 @@ class Fraction {

    // divide this fraction by a number or fraction
    divide(n) {
    if (!n instanceof Fraction) n = new Fraction(n);
    if (!(n instanceof Fraction)) n = new Fraction(n);
    let output = new Fraction(this); // copy this fraction

    output.numerator *= n.denominator;
    @@ -109,6 +112,40 @@ class Fraction {
    return output;
    }

    // mod this fraction by a number or fraction (same as JS modulo operator '%')
    mod(n) {
    if (!(n instanceof Fraction)) n = new Fraction(n);
    let output = new Fraction(this); // copy this fraction

    if (output.gt(0)) {
    while (output.gt(n)) {
    output = output.subtract(n);
    }
    } else {
    while (output.lt(n)) {
    output = output.add(n);
    }
    }

    return output.toNumber();
    }

    // check if this fraction is less than a number or fraction
    lt(n) {
    if (!(n instanceof Fraction)) n = new Fraction(n);
    let output = new Fraction(this); // copy this fraction

    return output.toNumber() < n.toNumber();
    }

    // check if this fraction is greater than a number or fraction
    gt(n) {
    if (!(n instanceof Fraction)) n = new Fraction(n);
    let output = new Fraction(this); // copy this fraction

    return output.toNumber() > n.toNumber();
    }

    // get Number representation of fraction
    toNumber() {
    return this.numerator / this.denominator;
  2. leontastic revised this gist Sep 5, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion fraction.js
    Original file line number Diff line number Diff line change
    @@ -18,7 +18,7 @@
    subtract([n|Number|Fraction]) => [Fraction] returns fraction minus n
    multiply([n|Number|Fraction]) => [Fraction] returns fraction multiplied by n
    divide([n|Number|Fraction]) => [Fraction] returns fraction divided by n
    toNumber() => [] returns the native Number representation of the fraction
    toNumber() => [Number] returns the native Number representation of the fraction
    */

    class Fraction {
  3. leontastic created this gist Sep 5, 2015.
    116 changes: 116 additions & 0 deletions fraction.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,116 @@
    /*
    Fraction: an ES6 class to preserve decimal precision in rational number arithmetic
    Notes:
    - reliably preserves decimal precision for floats that can be represented in decimal with 16 decimal places or less
    - for decimals with more than 16 decimal places, precision is preserved up to 16 decimal places
    CONSTRUCTOR:
    constructor([a|Number|Fraction]) => [Fraction]: returns a Fraction from a number
    STATIC METHODS:
    gcd([a|Number], [b|Number]) => [Number] recursively finds greatest common denominator of a and b
    lcm([a|Number], [b|Number]) => [Number] finds the lowest common multiple of a and b (depends on gcd(a,b))
    INSTANCE METHODS:
    reduce() => [] reduces the fraction to simplest terms (used internally to always keep simplest terms)
    add([n|Number|Fraction]) => [Fraction] returns fraction plus n
    subtract([n|Number|Fraction]) => [Fraction] returns fraction minus n
    multiply([n|Number|Fraction]) => [Fraction] returns fraction multiplied by n
    divide([n|Number|Fraction]) => [Fraction] returns fraction divided by n
    toNumber() => [] returns the native Number representation of the fraction
    */

    class Fraction {
    constructor(num) {
    if (typeof num === 'number') {
    this.numerator = num;
    this.denominator = 1;
    } else if (num instanceof Fraction) {
    this.numerator = num.numerator;
    this.denominator = num.denominator;
    } else {
    throw new Error('Invalid conversion to Fraction');
    }

    // we always want the numerator to be an integer
    // convert float to integer via string manipulation
    // (since multiplication sometimes results in floating point errors)
    if (this.numerator % 1 !== 0) {
    let exp = (this.numerator + '').replace(/^-?\d*\.?|0+$/g, '').length; // count number of decimal places
    this.numerator = parseInt((this.numerator + '').replace('.', '')); // strip decimal point and parse as integer
    this.denominator = Math.pow(10, exp);
    }

    // new fractions should always be in lowest terms
    this.reduce();
    }

    // GCD utility (recursive algorithm)
    static gcd(a, b) {
    return b ? Fraction.gcd(b, a % b) : a;
    }

    // LCM utility (depends on Fraction.gcd)
    static lcm(a, b) {
    return Math.abs(a * b) / Fraction.gcd(a, b);
    }

    // reduces fraction to simplest terms
    reduce() {
    let d = Fraction.gcd(this.numerator, this.denominator);
    this.numerator /= d;
    this.denominator /= d;
    }

    // add a number or fraction to this fraction
    add(n) {
    if (!n instanceof Fraction) n = new Fraction(n);
    let output = new Fraction(this); // copy this fraction

    let multiple = Fraction.lcm(output.denominator, n.denominator);
    output.numerator = output.numerator * (multiple / output.denominator) + n.numerator * (multiple / n.denominator);
    output.denominator = multiple;
    output.reduce();
    return output;
    }

    // subtract a number or fraction from this fraction
    subtract(n) {
    if (!n instanceof Fraction) n = new Fraction(n);
    let output = new Fraction(this); // copy this fraction

    let multiple = Fraction.lcm(output.denominator, n.denominator);
    output.numerator = output.numerator * (multiple / output.denominator) - n.numerator * (multiple / n.denominator);
    output.denominator = multiple;
    output.reduce();
    return output;
    }

    // multiply this fraction by a number or fraction
    multiply(n) {
    if (!n instanceof Fraction) n = new Fraction(n);
    let output = new Fraction(this); // copy this fraction

    output.numerator *= n.numerator;
    output.denominator *= n.denominator;
    output.reduce();
    return output;
    }

    // divide this fraction by a number or fraction
    divide(n) {
    if (!n instanceof Fraction) n = new Fraction(n);
    let output = new Fraction(this); // copy this fraction

    output.numerator *= n.denominator;
    output.denominator *= n.numerator;
    output.reduce();
    return output;
    }

    // get Number representation of fraction
    toNumber() {
    return this.numerator / this.denominator;
    }
    }