Thursday, 23 November 2006

Number fun

Numbers are pretty interesting things, as well as the obvious mathematical use people also attribute emotional, psychological, mythological and religious reactions to certain numbers. Everyone has numbers they like and don't like, history and superstition show that westerners perceive the number 7 as not only lucky but also there are associations with cognitive psychology whereas the chinese see the number 8 as especially fortuitous. Funky stuff. In fact numerology explores this relationship between numbers and other systems (religious, physical, living, etc). My study into this is fairly limited, but it's always been interesting playing around with numbers and I've a stack of JavaScript number object extensions that I carry around in an html file wherever I go to work.

So here they are. I can't take full credit for all of these, I've based some of them on other snippets of code I've found around the place. Notably from codingforums.com so thanks to all who have contributed. I should point out that there's not much explaning that will be done as to why they work - they've been chopped right down to the bare minimum of overhead in most cases and work beautifully, but often look complex. I may well post up another time how they work in more detail.

1) First up is a classic. Rounding a number to a specified number of decimal places. It takes an optional argument n for the number of decimal places to round to. If no argument is supplied, the number will be rounded to 2 decimal places.

Number.prototype.toDecimals = function(n) {
  var n = (isNaN(n)) ? 2 : n;
  var nT = Math.pow(10, n);
  function pad(s) {
    s = s || '.';
    return (s.length > n) ? s : pad(s + '0');
  }
  return (isNaN(this)) ? this : (new String(Math.round(this*nT) / nT)).replace(/(\.\d*)?$/, pad);
}


Usage:
var intNumber = 9.23423;
var intRounded = intNumber.toDecimals(); // output: 9.23
var intRoundedToFourPlaces = intNumber.toDecimals(4); // output: 9.2342

2) Make an ordinal string (eg 1st, 2nd, 3rd) from a number. I use this a lot in date formatting. The argument n is just a locally declared variable, this function does not need any arguments passed to it.


Number.prototype.toOrdinal = function(n) {
  return ( this + ["th","st","nd","rd"][(!(((n = this % 10) > 3) || (Math.floor(this % 100/10) == 1))) * n] );
}


Usage:
var intNumber = 13;
var intOrdinal = intNumber.toOrdinal(); // output: "13th"

3) Convert a decimal number (also known as base ten or denary number) to hexidecimal (base 16 or hex) string. Hexidecimal is the numeral system that computers use. This is very useful for html colour codes which use 3 pairs of hexidecimal values to dictate the red, green and blue mix of the colour (so #CC130F is actually - CC 13 0F).

Number.prototype.toHexidecimal = function() {
  return this.toString(16).toUpperCase();
}


Usage:
var intNumber = 28;
var intHexidecimal = intNumber.toHexidecimal(); // output: "1C"


4) Convert a decimal number to binary. This is used the least out of the previous 3 number extensions, but it's included because it's elegant!

Number.prototype.toBinary = function() {
  return this.toString(2);
}


Usage:
var intNumber = 13;
var intBinary = intNumber.toBinary(); // output: 1101

You can also use these by putting parentheses (round brackets) around the number and calling the method. For example (13).toBinary(); outputs 1101, (40).toOrdinal(); outputs "40th", etc.

You may well notice that the 3rd and 4th number extensions (toHexidecimal() and toBinary()) use the native JavaScript object toString() method. When used with JavaScript numbers, this toString method allows you to pass an argument called a radix. In pretty much every numeral system we use, a radix refers to the number of unique digits that the chosen numeral system can use (including 0). So in the case of toBinary() we pass a radix of 2 because there are two digits that binary can use 0 and 1. In the case of decimal there are 10 they are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 and in the case of toHexidecimal() there are 16 which are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. The letters A-F are used in hexidecimal to complete the number of unique digits for that numbering system (the decimal equivelant would be 10-15 but as all those numbers (0, 1, 2, 3, 4, 5) have been used previously, they need to be replaced with unique digits).

So go, have fun with the numbers, be nerdy and spread the word!