diff options
| author | Jules Laplace <jules@okfoc.us> | 2017-03-08 15:46:03 +0100 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2017-03-08 15:46:03 +0100 |
| commit | 26f3fd1352a7fb73b7e8317a45f2a38975467429 (patch) | |
| tree | 7101f0e5b3750b2ae7a8796a4d20f95536a8549a | |
| parent | 4e9c0237d9b4a46dff0c8e80316ad2f4886fae7d (diff) | |
test all functions and fix bugs
| -rw-r--r-- | index.js | 56 | ||||
| -rw-r--r-- | test/01-basic.js | 166 |
2 files changed, 203 insertions, 19 deletions
@@ -6,32 +6,41 @@ basic.abedecary = "0123456789abcdefghijklmnopqrstuvwxyz" // Validate that a string s represents a number in base b basic.validate = function (s, b) { - return (base.validate_base(b) && base.validate_digits(s, b)) + return (basic.validate_base(b) && basic.validate_digits(s, b)) } // Validate that a string does not contain numerals // foreign to a particular base. basic.validate_digits = function(s, b) { - var A = basic.abedecary.substr(0, b) - var re = new RegExp ( "[^" + A + "]" ) - return !! re.match(s) + var A = basic.abedecary.substr(0, Math.abs(b)) + if (b > 0) { + A = "-" + A + } + var re = new RegExp ( "[^" + A + "]", "g" ) + return ! re.test(s) } // Validate that a base is valid. basic.validate_base = function(b){ - return (b !== 0 && b !== 1 && b !== -1 && (Math.abs(b) % 2) === 0) + return ( + ! isNaN(b) + && b !== 0 + && b !== 1 + && b !== -1 + && (Math.abs(b) % 1) === 0 + && Math.abs(b) <= 36 + ) } // Convert a string s representing a number in base b // to an integer. Assumes s is big-endian. basic.toNumber = function (s, b) { - if (! basic.validate(s,b)) { + if (! basic.validate(s, b)) { return NaN } var n = 0 - s = s.reverse() for (var i = 0, len = s.length; i < len; i++) { - n += parseInt(s[i]) * Math.pow(b, i) + n += basic.abedecary.indexOf(s[len-1-i]) * Math.pow(b, i) } return n } @@ -42,23 +51,34 @@ basic.toString = function (n, b) { if (! basic.validate_base(b)) { throw new Error ("invalid base") } + if (n === 0) { + return "0" + } + var is_negative = n < 0 + if (is_negative && b > 0) { + n = Math.abs(n) + } var s = "" - var dividend, residual while (n) { - remainder = basic.mod(n, b) - n = Math.floor(n/b) - if (remainder) { + var remainder = n % b + n = basic.floor(n / b) + if (remainder < 0) { n += 1 + remainder -= b } - s += basic.abedecary[n] + s = basic.abedecary[remainder] + s + } + if (is_negative && b > 0) { + s = "-" + s } return s } -// Compute the residual of N mod M -// Handle negative N and M correctly -basic.mod = function (n,m){ - m = Math.abs(m) - return n-(m * Math.floor(n/m)) +// Remove the mantissa from a number, handling negative numbers +basic.floor = function (n){ + if (n >= 0) { + return Math.floor(n) + } + return -1 * Math.floor(-n) } diff --git a/test/01-basic.js b/test/01-basic.js index 5190008..8edb5f4 100644 --- a/test/01-basic.js +++ b/test/01-basic.js @@ -13,8 +13,172 @@ var basic = require('../index') describe('basic', function(){ describe('#validate_base()', function(){ it('validates positive bases', function(done){ - assert( basic.validate_base(2), true ) + assert.equal( basic.validate_base(2), true ) done() }) + it('validates negative bases', function(done){ + assert.equal( basic.validate_base(-2), true ) + done() + }) + it('does not validate abs(base) > 36', function(done){ + assert.equal( basic.validate_base(36), true ) + assert.equal( basic.validate_base(37), false ) + assert.equal( basic.validate_base(-36), true ) + assert.equal( basic.validate_base(-37), false ) + done() + }) + it('does not validate bad bases', function(done){ + assert.equal( basic.validate_base(-1), false ) + assert.equal( basic.validate_base(0), false ) + assert.equal( basic.validate_base(1), false ) + assert.equal( basic.validate_base(NaN), false ) + assert.equal( basic.validate_base(Infinity), false ) + assert.equal( basic.validate_base(-Infinity), false ) + done() + }) + it('does not validate non-integer bases', function(done){ + assert.equal( basic.validate_base(1.1), false ) + done() + }) + }) + describe('#validate_digits()', function(){ + it('validates negative numbers', function(done){ + assert.equal( basic.validate_digits("-1234567890", 10), true ) + assert.equal( basic.validate_digits("-123456789a", 10), false ) + done() + }) + it('validates base 2', function(done){ + assert.equal( basic.validate_digits("1010101", 2), true ) + assert.equal( basic.validate_digits("1222222", 2), false ) + done() + }) + it('validates base 3', function(done){ + assert.equal( basic.validate_digits("1201120", 3), true ) + assert.equal( basic.validate_digits("1234567", 3), false ) + done() + }) + it('validates base -2', function(done){ + assert.equal( basic.validate_digits("1010101", -2), true ) + done() + }) + it('validates bases up to 36 and -36', function(done){ + for (var i = 2; i <= 36; i++) { + var s = basic.abedecary.substr(0, i).split("").reverse().join("") + assert.equal( basic.validate_digits(s, i), true ) + assert.equal( basic.validate_digits(s, -i), true ) + } + done() + }) }) + describe('#validate()', function(){ + it('validates number and base', function(done){ + assert.equal( basic.validate_digits("1234567890", 10), true ) + assert.equal( basic.validate_digits("1234567890", -10), true ) + assert.equal( basic.validate_digits("123456789a", 10), false ) + assert.equal( basic.validate_digits("123456789a", -10), false ) + done() + }) + }) + describe('#floor()', function(){ + it('removes the mantissa of negative numbers', function(done){ + assert.equal( basic.floor(2.2), 2 ) + assert.equal( basic.floor(-2.2), -2 ) + done() + }) + }) + describe('#toNumber()', function(){ + it('handles base 2', function(done){ + assert.equal( basic.toNumber("00", 2), 0 ) + assert.equal( basic.toNumber("01", 2), 1 ) + assert.equal( basic.toNumber("10", 2), 2 ) + assert.equal( basic.toNumber("11", 2), 3 ) + done() + }) + it('handles base -2', function(done){ + assert.equal( basic.toNumber("00", -2), 0 ) + assert.equal( basic.toNumber("01", -2), 1 ) + assert.equal( basic.toNumber("10", -2), -2 ) + assert.equal( basic.toNumber("11", -2), -1 ) + assert.equal( basic.toNumber("101101", -2), -35 ) + done() + }) + it('handles base 10', function(done){ + assert.equal( basic.toNumber("100", 10), 100 ) + done() + }) + it('inverts toString', function(done){ + assert.equal( basic.toNumber(basic.toString(100, 10), 10), 100 ) + assert.equal( basic.toNumber(basic.toString(100, 3), 3), 100 ) + assert.equal( basic.toNumber(basic.toString(100, 2), 2), 100 ) + assert.equal( basic.toNumber(basic.toString(100, -2), -2), 100 ) + assert.equal( basic.toNumber(basic.toString(100, -3), -3), 100 ) + assert.equal( basic.toNumber(basic.toString(100, -10), -10), 100 ) + done() + }) + }) + describe('#toString()', function(){ + it('handles base 2', function(done){ + assert.equal( basic.toString(0, 2), "0" ) + assert.equal( basic.toString(1, 2), "1" ) + assert.equal( basic.toString(2, 2), "10" ) + assert.equal( basic.toString(3, 2), "11" ) + assert.equal( basic.toString(4, 2), "100" ) + assert.equal( basic.toString(5, 2), "101" ) + assert.equal( basic.toString(6, 2), "110" ) + done() + }) + it('handles base 3', function(done){ + assert.equal( basic.toString(0, 3), "0" ) + assert.equal( basic.toString(1, 3), "1" ) + assert.equal( basic.toString(-1, 3), "-1" ) + assert.equal( basic.toString(2, 3), "2" ) + assert.equal( basic.toString(3, 3), "10" ) + assert.equal( basic.toString(4, 3), "11" ) + assert.equal( basic.toString(5, 3), "12" ) + assert.equal( basic.toString(6, 3), "20" ) + assert.equal( basic.toString(9, 3), "100" ) + assert.equal( basic.toString(26, 3), "222" ) + assert.equal( basic.toString(27, 3), "1000" ) + assert.equal( basic.toString(28, 3), "1001" ) + done() + }) + it('handles base 10', function(done){ + assert.equal( basic.toString(1, 10), "1" ) + assert.equal( basic.toString(2, 10), "2" ) + assert.equal( basic.toString(3, 10), "3" ) + assert.equal( basic.toString(9, 10), "9" ) + assert.equal( basic.toString(10, 10), "10" ) + assert.equal( basic.toString(19, 10), "19" ) + assert.equal( basic.toString(20, 10), "20" ) + assert.equal( basic.toString(-20, 10), "-20" ) + done() + }) + it('handles base -2', function(done){ + assert.equal( basic.toString(0, -2), "0" ) + assert.equal( basic.toString(1, -2), "1" ) + assert.equal( basic.toString(2, -2), "110" ) + assert.equal( basic.toString(3, -2), "111" ) + assert.equal( basic.toString(-1, -2), "11" ) + assert.equal( basic.toString(-2, -2), "10" ) + assert.equal( basic.toString(-3, -2), "1101" ) + assert.equal( basic.toString(-4, -2), "1100" ) + done() + }) + it('handles base -3', function(done){ + assert.equal( basic.toString(119, -3), "22102" ) + done() + }) + it('inverts toNumber', function(done){ + for (var i = 2; i <= 36; i++) { + var s = basic.abedecary.substr(0, i) + .split("") + .reverse() + .join("") + .substr(0, 9) // cutoff here, otherwise we get rounding error + assert.equal( basic.toString(basic.toNumber(s, i), i), s ) + assert.equal( basic.toString(basic.toNumber(s, -i), -i), s ) + } + done() + }) + }) }) |
