summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--index.html70
-rw-r--r--index.js101
-rw-r--r--test/01-basic.js260
3 files changed, 215 insertions, 216 deletions
diff --git a/index.html b/index.html
index 7371a95..8a50c74 100644
--- a/index.html
+++ b/index.html
@@ -11,19 +11,19 @@ button { font-size: 200%; }
<body class="loading">
<div id="numbers">
- <script type="text/html" id="number-template">
- <div>
- <label for="base-{{base}}">{{base}}</label>
- <input id="base-{{base}}" type="text">
- </div>
- </script>
- </div>
+ <script type="text/html" id="number-template">
+ <div>
+ <label for="base-{{base}}">{{base}}</label>
+ <input id="base-{{base}}" type="text">
+ </div>
+ </script>
+ </div>
<div id="buttons">
- <button id="add">+</button>
- <button id="sub">-</button>
- <button id="inv">(-)</button>
- </div>
+ <button id="add">+</button>
+ <button id="sub">-</button>
+ <button id="inv">(-)</button>
+ </div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="./index.js"></script>
@@ -33,8 +33,8 @@ var $inputs = {}
var template = $("#number-template").html()
function init () {
iter(build)
- bind()
- rebuild(0)
+ bind()
+ rebuild(0)
$("body").removeClass("loading")
}
function bind () {
@@ -44,46 +44,46 @@ function bind () {
}
function build (base) {
var $div, $input
- $div = $(template.replace(/{{base}}/g, base))
- $input = $div.find("input")
- $input.on("input", function(){
- var n = basic.toNumber( $input.val(), base )
- if (isNaN(n)) {
- return
- }
- rebuild(n, base)
- })
- $inputs[base] = $input
+ $div = $(template.replace(/{{base}}/g, base))
+ $input = $div.find("input")
+ $input.on("input", function(){
+ var n = basic.toNumber( $input.val(), base )
+ if (isNaN(n)) {
+ return
+ }
+ rebuild(n, base)
+ })
+ $inputs[base] = $input
$("#numbers").prepend($div)
}
function rebuild (n, base) {
iter(function(i){
- if (i == base) return
- var $i = $inputs[i]
- var v = basic.toString(n, i)
- $i.val(v)
+ if (i == base) return
+ var $i = $inputs[i]
+ var v = basic.toString(n, i)
+ $i.val(v)
})
}
function iter (f) {
for (var i = -MAX_BASE; i <= MAX_BASE; i++) {
if (basic.validate_base(i)) {
- f(i)
- }
- }
+ f(i)
+ }
+ }
}
function current () {
var n = basic.toNumber( $inputs[2].val(), 2 )
- if (isNaN(n)) n = 2
- return n
+ if (isNaN(n)) n = 2
+ return n
}
function add () {
- rebuild( current() + 1 )
+ rebuild( current() + 1 )
}
function sub () {
- rebuild( current() - 1 )
+ rebuild( current() - 1 )
}
function inv () {
- rebuild( current() * -1 )
+ rebuild( current() * -1 )
}
init()
diff --git a/index.js b/index.js
index 423295b..3a76979 100644
--- a/index.js
+++ b/index.js
@@ -17,79 +17,78 @@ basic.validate = function (s, b) {
// foreign to a particular base.
basic.validate_digits = function(s, b) {
var A = basic.abedecary.substr(0, Math.abs(b))
- if (b > 0) {
- A = "-" + A
+ if (b > 0) {
+ A = "-" + A
}
- var re = new RegExp ( "[^" + A + "]", "g" )
- return ! re.test(s)
+ var re = new RegExp ( "[^" + A + "]", "g" )
+ return ! re.test(s)
}
// Validate that a base is valid.
basic.validate_base = function(b){
- return (
- ! isNaN(b)
- && b !== 0
- && b !== 1
- && b !== -1
- && (Math.abs(b) % 1) === 0
- && Math.abs(b) <= 36
- )
+ b = Math.abs(b)
+ return (
+ ! isNaN(b)
+ && b > 1
+ && b <= 36
+ && (b % 1) === 0
+ )
}
// 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)) {
- return NaN
- }
+ if (! basic.validate(s, b)) {
+ return NaN
+ }
var n = 0, is_negative = false
- if (s.indexOf("-") == 0) {
- is_negative = true
- s = s.substr(1)
- }
- for (var i = 0, len = s.length; i < len; i++) {
- n += basic.abedecary.indexOf(s[len-1-i]) * Math.pow(b, i)
- }
- if (is_negative) {
- n *= -1
- }
- return n
+ if (s.indexOf("-") == 0) {
+ is_negative = true
+ s = s.substr(1)
+ }
+ for (var i = 0, len = s.length; i < len; i++) {
+ n += basic.abedecary.indexOf(s[len-1-i]) * Math.pow(b, i)
+ }
+ if (is_negative) {
+ n *= -1
+ }
+ return n
}
// Convert an integer n to a string representing that
// integer in base b, big-endian.
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 = ""
- while (n) {
- var remainder = 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 = ""
+ while (n) {
+ var remainder = n % b
n = basic.floor(n / b)
- if (remainder < 0) {
- n += 1
- remainder -= b
- }
- s = basic.abedecary[remainder] + s
- }
- if (is_negative && b > 0) {
- s = "-" + s
- }
- return s
+ if (remainder < 0) {
+ n += 1
+ remainder -= b
+ }
+ s = basic.abedecary[remainder] + s
+ }
+ if (is_negative && b > 0) {
+ s = "-" + s
+ }
+ return s
}
// Remove the mantissa from a number, handling negative numbers
basic.floor = function (n){
if (n >= 0) {
- return Math.floor(n)
+ return Math.floor(n)
}
- return -1 * Math.floor(-n)
+ return -1 * Math.floor(-n)
}
diff --git a/test/01-basic.js b/test/01-basic.js
index 8edb5f4..cb5c194 100644
--- a/test/01-basic.js
+++ b/test/01-basic.js
@@ -14,18 +14,18 @@ describe('basic', function(){
describe('#validate_base()', function(){
it('validates positive bases', function(done){
assert.equal( basic.validate_base(2), true )
- done()
+ done()
})
it('validates negative bases', function(done){
assert.equal( basic.validate_base(-2), true )
- done()
+ 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()
+ done()
})
it('does not validate bad bases', function(done){
assert.equal( basic.validate_base(-1), false )
@@ -34,151 +34,151 @@ describe('basic', function(){
assert.equal( basic.validate_base(NaN), false )
assert.equal( basic.validate_base(Infinity), false )
assert.equal( basic.validate_base(-Infinity), false )
- done()
+ done()
})
it('does not validate non-integer bases', function(done){
- assert.equal( basic.validate_base(1.1), false )
- 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()
+ done()
})
it('validates base 2', function(done){
assert.equal( basic.validate_digits("1010101", 2), true )
assert.equal( basic.validate_digits("1222222", 2), false )
- done()
+ done()
})
it('validates base 3', function(done){
assert.equal( basic.validate_digits("1201120", 3), true )
assert.equal( basic.validate_digits("1234567", 3), false )
- done()
+ done()
})
it('validates base -2', function(done){
assert.equal( basic.validate_digits("1010101", -2), true )
- done()
+ 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()
})
- 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()
- })
- })
})