  /**
 * Number.prototype.format
 *
 * Formats the number and returns as a string.
 * Formatting begins from the decimal separator or if not present the right-most character.
 * Surround the fractional separator by brackets.
 *
 * Examples:
 * var x = 12345678.9
 * Number.format('$###,###[.]##'); //Returns per American currency formatting: $12,345,678.90
 * Number.format('&#8377;##,###[.]##'); //Returns per Indian Rupee formatting (afaik): &#8377;1,23,45,678.90
 * Number.format('###.###[,]##&#8364;'); //Returns per German Euros formatting: 12.345.678,90&#8364;
 * Number.format('#,###&#x5793; #,###&#x43AC; #,###&#x5146; #,###&#x5104; #,###&#x4E07; #,###[.]##'); //Returns per Japanese/Chinese formatting (afaik): 12.345.678,90&#8364; (12億 3,456万 7,890.12)
 * NOTE: Formatting examples were based off of those at http://www.xencraft.com/resources/multi-currency.html#group 2011-03-03
 * @param string frmt Desired Format.
 * @returns string The formatted number.
 */
Number.prototype.format = function(frmt) {
  var frmts = frmt.match(/(.+)(\[.+\])(.*)/i), //Parse format
  num = this.toString().split(/[\.]/), //Parse current number value
  r = num[0].split(''), //Return value
  r_cursor = r.length,
  frmt,
  frmt_len,
  frmt_sep_last,
  frmt_cursor,
  pend_str = '';

  if (frmts) {
    frmts = [
      frmts[1].match(/(&#[a-f0-9x]+;|#+|[^#]+)/ig),
      frmts[2],
      frmts[3].match(/(&#[a-f0-9x]+;|#+|[^#]+)/ig)
    ];
  } else {
    frmts = [
      frmt.match(/(&#[a-f0-9x]+;|#+|[^#]+)/ig),
      [],
      []
    ];
  }

  /*
   * Move from inside out, adding formatting
   */
  if (frmts[0][0].replace(/#/g, '').length > 0) {
    //Has a prepend character
    pend_str = frmts[0][0];
    frmts[0].splice(0,1);
  }
  frmt_cursor = frmts[0].length - 1;

  while (frmt_cursor > -1 && r_cursor > 0) {
    if (frmts[0][frmt_cursor].replace(/#/g, '') == '') {
     //Numeric formatting, so move r_cursor forward this many places
     r_cursor -= frmts[0][frmt_cursor].length;
    } else {
      //Separator character
      r.splice(r_cursor, 0, frmts[0][frmt_cursor]);
      frmt_sep_last = frmt_cursor;
    }
    frmt_cursor--;
    if (frmt_cursor < 0 && r_cursor > -1) {
      frmt_cursor = frmt_sep_last;
    }
  }
  if (pend_str.length > 0) {
    r.splice(0, 0, pend_str);
  }
  //Check for append string
  pend_str = '';
  if (frmts[2] && frmts[2].length > 0) {
    if (frmts[2][frmts[2].length - 1].replace(/#/g, '').length > 0) {
      //Has a prepend character
      pend_str = frmts[2][frmts[2].length - 1];
      frmts[2].pop();
    }
  }

  if (num[1] && frmts[2].length>0) { //Has a fractional part
    if (frmts[1].length > 0) {
      r.push(frmts[1].substr(1, frmts[1].length-2));
    }
    r_cursor = r.length;
    r = r.concat(num[1].split(''));
    frmt_cursor = 0;
    frmt_len = frmts[2].length;


    while (frmt_cursor < frmt_len) {
      if (frmts[2][frmt_cursor].replace(/#/g, '') == '') {
       //Numeric formatting, so move r_cursor forward this many places
       r_cursor += frmts[2][frmt_cursor].length;
      } else {
        //Separator character
        r.splice(r_cursor, 0, frmts[2][frmt_cursor]);
        frmt_sep_last = frmt_cursor;
        r_cursor += frmts[2][frmt_cursor].length;
      }
      frmt_cursor++;
      if (r_cursor > r.length) {
        //Need to pad r with zeroes as formatting indicates more spaces of accuracy
        for (var i=(r_cursor-r.length); i>0; i--) {
        r.push(0);
        }
      } else if (frmt_cursor >= frmt_len) {
        frmt_cursor = frmt_sep_last;
      }
    }
  }
  if (pend_str.length > 0) {
    r.push(pend_str);
  }
  return r.join('');
}
