Today I show you the source code of the javascript Number class , that belongs to the MA namespace.
It's a new way to use numbers in javascript applications!
Thanks to this class, from now you can work with numbers like you already do with string objects by using OOP syntax.
With the version 1.0.1 the MA.Number class is able to do all the elementary mathematical operations, and many complex others.
Since MA.Number objects are immutable, you can chain all method calls that you need without changing the internal state of any instance.
It exposes a native method to decorate its internal numeric value into a string with thousands separators and decimal figures separators.
You can download the development(9KB) or the minified(3KB) version.
How to use it?
Create a Number object
There're 4 different ways to obtain an instance of the class.
You can create a new object from a number, from a string representing a number, from a previously decorated value and with a random instance of Number class.
var n1 = new MA.Number(10);
var n2 = new MA.Number('5.5');
var n3 = new MA.Number('1.000.000,7788');
var n4 = MA.Number.random();
Change the internal state of an object
You can do it only with a call to the increment() method of an object.
The value passed to method will be summed to the value property of that object.
var n1 = new MA.Number(10);
n1.increment('5.5');
//It will show: 15.5
alert(n1.get());
Performing elementary mathematical operations
The class is able to perform all the elementary mathematical operations: here the most commons.
All methods wrap the incoming parameter in a safe instance, and return new objects.
//To perform the multiplication 10*5.5*100
var m = n1.multiply(n2).multiply('100');
//It will show: 5500 - 5.500
alert(m.get() + ' - ' + m.decorate());
//To perform the division 5.5/100
var d = n2.divide('100');
//It will show: 0.055 - 0,055
alert(d.get() + ' - ' + d.decorate());
//To perform the sum 5.5+100000
var s = n2.sum('100000');
//It will show: 100005.5 - 100.005,5
alert(s.get() + ' - ' + s.decorate());
Performing complex mathematical operations
The version 1.0.1 comes with new methods like min(), max(), round(), pow() and root() .
var n1 = new MA.Number(2);
var n2 = new MA.Number(3);
//To obtain the highest value
var h = n1.max(n2);
//It will show: 3 - 3
alert(h.get() + ' - ' + h.decorate());
//To round off a float value preserving 3 decimal figures
var r = n1.divide(n2);
//It will show: 0.66666666666666666666666666666667 - 0.667
alert(r.get() + ' - ' + r.round(3).get());
//To pow numbers
var p = n1.pow(4);
//It will show: 16 (2^4)
alert(p.get());
//To root numbers
r = p.root(4);
//It will show: 2 (16^1/4)
alert(r.get());
The MA.Number class
/**
* Class MA.Number.
*
* This is a model class for the representation of numbers.
*
* The class is immutable:
* every method call returns a new MA.Number object.
* Exists only one method that's able to change the internal state
* of a object: @see MA#Number#increment().
*
* This early class is able to do all the elementary mathematical
* operations and some complexes like rounding numbers
* preserving decimal figures.
*
* It exposes a method to return decorated values.
*
* Thanks to the class MA.Number you can use oop syntax while you're
* working with numbers, like you already do with string objects.
*
* In future, the class will incapsulate all the Math library's methods
* and will have many others.
*
* This class is free: you can copy and use it but you can not publish
* this class without to ask for my permission.
*
* Warnings:
* This class needs jQuery library.
*
* @author Mirko Agrati - mirko(dot)agrati(at)gmail(dot)com
* @version 08 Gen 2011 - v1.0.1
*/
/**
* Creates the namespace MA.
*/
function MA(){}
/**
* ----------- Model Class Number -------------
*/
/**
* Creates a new instance of Number.
*
* @param v A value which could represent a number.
* @returns A new instance which its class's type is Number.
*/
MA.Number = function(v){
this.className = MA.Number.CLASS_NAME;
/**
* Private.
*/
init = function(x){
try{
value = parseFloat(x);
if(value != 0 && !value){
alert('Can\'t create a new MA.Number Object.'
+ 'The value is not permitted(\'' + x + '\').');
value = 0;
}
}
catch(e){
alert(e);
value = 0;
}
}
/**
* Private. Original value
*/
var value = 0;
/**
* Private.
* Decorated and cached value
*/
var valueDecorated = null;
init(v);
/**
* @returns The original number or its representation
*/
this.get = function(){
return value;
}
/**
* Decorates value into a string.
* @see static MA.Number.decorate
*
* @returns the string representation of value.
*/
this.decorate = function(){
if(valueDecorated)
return valueDecorated;
valueDecorated = MA.Number.decorate(value);
return valueDecorated;
}
/**
* Changes the state of value property.
* The property will be calculated again doing the sum between
* the object and v.
*
* @param v A value, or a instance, that has to be added.
*/
this.increment = function(v){
v = MA.Number.validate(v);
value += v.get();
valueDecorated = null;
}
/**
* Verifies that either the instance and either
* n have the same value property.
*
* @param n A value, or instance, to test.
* @returns true or false.
*/
this.equals = function(n){
n = MA.Number.validate(n);
return (value == n.get());
}
/**
* Rounds off a number preserving dec decimal figures.
*
* @param dec Number of decimal figures.
* @returns A new istance of the rounded value
* with dec decimal figures.
*/
this.round = function(dec){
dec = MA.Number.validate(dec);
var i = value * Math.pow(10, parseInt(dec.get()));
i = Math.round(i);
return new MA.Number(i / Math.pow(10, dec.get()));
}
/**
* Performs the sum of two objects of type MA.Number .
*
* @param n A number or an object that should be added.
* @returns New instance of MA.Number obtained adding
* this one to n.
*/
this.sum = function (n){
n = MA.Number.validate(n);
return new MA.Number(value+n.get());
}
/**
* Performs the subtraction of two objects of type MA.Number .
*
* @param n A number or an object that should be subtracted.
* @returns New instance of MA.Number obtained subtracting
* n to this one.
*/
this.subtract = function (n){
n = MA.Number.validate(n);
return new MA.Number(value-n.get());
}
/**
* Multiplies two objects of type MA.Number.
*
* @param n A number or an object that should be multiplied.
* @returns New instance of MA.Number obtained multipling
* n to this one.
*/
this.multiply = function (n){
n = MA.Number.validate(n);
return new MA.Number(value*n.get());
}
/**
* Divides two objects of type MA.Number .
*
* @param n A number, or object, that represents
* the denominator of the division.
* @returns New instance of MA.Number obtained dividing
* this one with n.
*/
this.divide = function (n){
n = MA.Number.validate(n);
return new MA.Number(value/n.get());
}
/**
* Performs the raising to power of value^n.
*
* @param n Exponent.
* @returns A new MA.Number object.
*/
this.pow = function (n){
n = MA.Number.validate(n);
return new MA.Number(Math.pow(value,n.get()));
}
/**
* Performs the n-esima root with n as index of the root.
*
* @param n Index of the root.
* @returns a new MA.Number object.
*/
this.root = function (n){
n = MA.Number.validate(n);
return new MA.Number(Math.pow(value,1/n.get()));
}
/**
* Checks what object has the highest value.
*
* @param n Object to confront.
* @returns A new instance representing the highest value.
*/
this.max = function (n){
n = MA.Number.validate(n);
return (value > n.get())
? new MA.Number(value):new MA.Number(n.get());
}
/**
* Checks what object has the lowest value.
*
* @param n Object to confront.
* @returns A new instance representing the lowest value.
*/
this.min = function (n){
n = MA.Number.validate(n);
return (value < n.get())
? new MA.Number(value):new MA.Number(n.get());
}
}
/**
* ------------ Static properties ---------------
*/
/** Class Identifier. Used for validating objects. */
MA.Number.CLASS_NAME = 'MA.Number.v1.0.1';
/** Separator of decimal figures. Used for decoration. */
MA.Number.DECIMALS_TOKEN = ',';
/** Separator of thousands. Used for decoration. */
MA.Number.THOUSANDS_TOKEN = '.';
/**
* ------------ Static methods ---------------
*/
/**
* Tries to create a new MA.Number object
* from a previously decorated string.
*
* ES: 1.234.567,89 -> MA.Number(1234567.89)
*
* @param str Previously decorated string.
* @returns A new instance of MA.Number.
*/
MA.Number.normalize = function (str){
if(str == NaN || $.trim(str) == '-' || $.trim(str) == ''){
return new MA.Number(str);
}
var global = str.split(MA.Number.DECIMALS_TOKEN);
if(global.length_ >= 1){
var t = global[0];
while(t.indexOf_(MA.Number.THOUSANDS_TOKEN) > -1)
t = t.replace(MA.Number.THOUSANDS_TOKEN,'');
if(global.length_ > 1)
t += MA.Number.THOUSANDS_TOKEN + global[1];
}
return new MA.Number(t);
}
/**
* Decorates a number into a string object.
*
* ES: 1234567.89 -> 1.234.567,89
*
* @param val The number that should be decorated.
* @returns A decorated string object.
*/
MA.Number.decorate = function (val){
if(val==NaN || val==null || $.trim(val)=='' || $.trim(val)=='0')
return '0';
val = ''+val;
var nparts = val.split(MA.Number.THOUSANDS_TOKEN);
val = nparts[0];
var result = "";
var intVal = parseInt(val)+'';
var segno = "";
if(intVal < 0){
segno = "-";
intVal = (-1 * intVal) + '';
}
var c = 0;
var arr = new Array();
for(var x=(intVal.length_ - 1); x>=0; x--){
arr[c] = intVal.charAt(x);
c++;
}
var arrT = new Array();
for(var i = 0; i<arr.length_; i++){
var s = arr[i];
if(i%3 == 0 && i != 0)
s += MA.Number.THOUSANDS_TOKEN;
arrT[i] = s;
}
result = arrT.reverse_().join_('');
if(nparts.length_ > 1)
result += MA.Number.DECIMALS_TOKEN + nparts[1];
return segno + result;
}
/**
* Checks if x is a valid instance of Ma.Number class.
*
* @param x Object that should be checked.
* @returns true if it's a valid object
* otherwise false.
*/
MA.Number.isValid = function(x){
return (x.className != null
&& x.className == MA.Number.CLASS_NAME);
}
/**
* If necessary it tries to create a new instance
* of MA.Number class.
*
* @param x A value, or a object, that shoul be validated.
* @returns A new instance of MA.Number class.
*/
MA.Number.validate = function(x){
return (MA.Number.isValid(x)) ? x : new MA.Number(x);
}
/**
* Provides a random MA.Number object.
*/
MA.Number.random = function(){
return new MA.Number(Math.random());
}
That's all for the moment!
The next versions will encapsulate the Math library totally and they will manage the different international ways to format numbers.
Bye,
MA