LarryBattle / Ratio.js

Rational numbers for Javascript
http://larrybattle.github.com/Ratio.js/
MIT License
113 stars 9 forks source link

Default `alwaysReduce` to true to avoid data corruption. #42

Open LarryBattle opened 11 years ago

LarryBattle commented 11 years ago

Default alwaysReduce to true to avoid data corruption.

LarryBattle commented 11 years ago

I'm not if reduce should be set to true as a default since there is a significant performance penalty... More testing will need to be done.

LarryBattle commented 11 years ago

There needs to be a condition that prevents using the simplified fraction if it turns out to be longer than the original. Test Case:

var checkRatioSimplify = function (min, max) {
    var badValues = [],
    expect,
    output;

    if (max <= min) {
        throw new Error("Min is too high");
    }
    for (var i = min, len = max; i < len; i++) {
        expect = "1/" + i;
        output = Ratio.parse(1, i).simplify().toString();
        if (expect !== output) {
            badValues.push([expect, output]);
        }
    }
    return badValues;
};
test("test if simplify() returns shortest fraction", function(){
    var x = checkRatioSimplify(1,1e3);
    deepEqual( [], x);
};
LarryBattle commented 11 years ago

Here's a better test.

var checkRatioSimplify = function (min, max, fn, includeValues) {
    var badValues = includeValues ? [] : 0,
    x = [],
    expect,
    output;

    if (max <= min) {
        throw new Error("Min is too high");
    }
    for (var i = min, len = max; i < len; i++) {
        expect = "1/" + i;
        x = fn(1 / i);
        output = x ? x[0] + "/" + x[1] : "null";

        if (expect !== output) {
            if (includeValues) {
                var a = 1 / i,
                b = x[0] / x[1];
                badValues.push([expect, output, a, b, (a == b) ? "Same" : "Diff"]);
            } else {
                badValues++;
            }
        }
    }
    return badValues;
};
var runTest = function (name, min, max, fn, includeValues) {
    console.time(name);
    var x = checkRatioSimplify(min, max, fn, includeValues);
    console.timeEnd(name);
    var amountTested = (max - min);
    var amount = includeValues ? x.length : x;
    var errRate = (100 * (amount / amountTested)).toFixed(2);
    console.log("%s: Error rate = %s%, [%s, %s] has %s different fractions.", name, errRate, min, max, x);
    if (includeValues) {
        console.log(JSON.stringify(x, null, 2));
    }
};

var MIN = 1,
MAX = 1e4;
runTest("Ratio.getApprox()", MIN, MAX, function (d) {
    return Ratio.getApprox(d);
});
runTest("Ratio.simplify()", MIN, MAX, function (d) {
    return Ratio.simplify(d);
});
console.log("done");