UNPKG

28.9 kBJavaScriptView Raw
1/*! @preserve
2 * numeral.js
3 * version : 1.5.4
4 * author : Adam Draper
5 * license : MIT
6 * http://adamwdraper.github.com/Numeral-js/
7 */
8
9(function() {
10
11 /************************************
12 Variables
13 ************************************/
14
15 var numeral,
16 VERSION = '1.5.4',
17 // internal storage for language config files
18 languages = {},
19 defaults = {
20 currentLanguage: 'en',
21 zeroFormat: null,
22 nullFormat: null,
23 defaultFormat: '0,0'
24 },
25 options = {
26 currentLanguage: defaults.currentLanguage,
27 zeroFormat: defaults.zeroFormat,
28 nullFormat: defaults.nullFormat,
29 defaultFormat: defaults.defaultFormat
30 };
31
32
33 /************************************
34 Constructors
35 ************************************/
36
37
38 // Numeral prototype object
39 function Numeral(number) {
40 this._value = number;
41 }
42
43 /**
44 * Implementation of toFixed() that treats floats more like decimals
45 *
46 * Fixes binary rounding issues (eg. (0.615).toFixed(2) === '0.61') that present
47 * problems for accounting- and finance-related software.
48 */
49 function toFixed (value, maxDecimals, roundingFunction, optionals) {
50 var splitValue = value.toString().split('.'),
51 minDecimals = maxDecimals - (optionals || 0),
52 boundedPrecision,
53 optionalsRegExp,
54 power,
55 output;
56
57 // Use the smallest precision value possible to avoid errors from floating point representation
58 if (splitValue.length === 2) {
59 boundedPrecision = Math.min(Math.max(splitValue[1].length, minDecimals), maxDecimals);
60 } else {
61 boundedPrecision = minDecimals;
62 }
63
64 power = Math.pow(10, boundedPrecision);
65
66 //roundingFunction = (roundingFunction !== undefined ? roundingFunction : Math.round);
67 // Multiply up by precision, round accurately, then divide and use native toFixed():
68 output = (roundingFunction(value * power) / power).toFixed(boundedPrecision);
69
70 if (optionals > maxDecimals - boundedPrecision) {
71 optionalsRegExp = new RegExp('\\.?0{1,' + (optionals - (maxDecimals - boundedPrecision)) + '}$');
72 output = output.replace(optionalsRegExp, '');
73 }
74
75 return output;
76 }
77
78 /************************************
79 Formatting
80 ************************************/
81
82 // determine what type of formatting we need to do
83 function formatNumeral(n, format, roundingFunction) {
84 var output;
85
86 // figure out what kind of format we are dealing with
87 if (format.indexOf('$') > -1) { // currency!!!!!
88 output = formatCurrency(n, format, roundingFunction);
89 } else if (format.indexOf('%') > -1) { // percentage
90 output = formatPercentage(n, format, roundingFunction);
91 } else if (format.indexOf(':') > -1) { // time
92 output = formatTime(n, format);
93 } else { // plain ol' numbers or bytes
94 output = formatNumber(n._value, format, roundingFunction);
95 }
96
97 // return string
98 return output;
99 }
100
101 // revert to number
102 function unformatNumeral(n, string) {
103 var stringOriginal = string,
104 thousandRegExp,
105 millionRegExp,
106 billionRegExp,
107 trillionRegExp,
108 binarySuffixes = ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'],
109 decimalSuffixes = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
110 bytesMultiplier = false,
111 power;
112
113 if (string.indexOf(':') > -1) {
114 n._value = unformatTime(string);
115 } else {
116 if (string === options.zeroFormat || string === options.nullFormat) {
117 n._value = 0;
118 } else {
119 if (languages[options.currentLanguage].delimiters.decimal !== '.') {
120 string = string.replace(/\./g, '').replace(languages[options.currentLanguage].delimiters.decimal, '.');
121 }
122
123 // see if abbreviations are there so that we can multiply to the correct number
124 thousandRegExp = new RegExp('[^a-zA-Z]' + languages[options.currentLanguage].abbreviations.thousand + '(?:\\)|(\\' + languages[options.currentLanguage].currency.symbol + ')?(?:\\))?)?$');
125 millionRegExp = new RegExp('[^a-zA-Z]' + languages[options.currentLanguage].abbreviations.million + '(?:\\)|(\\' + languages[options.currentLanguage].currency.symbol + ')?(?:\\))?)?$');
126 billionRegExp = new RegExp('[^a-zA-Z]' + languages[options.currentLanguage].abbreviations.billion + '(?:\\)|(\\' + languages[options.currentLanguage].currency.symbol + ')?(?:\\))?)?$');
127 trillionRegExp = new RegExp('[^a-zA-Z]' + languages[options.currentLanguage].abbreviations.trillion + '(?:\\)|(\\' + languages[options.currentLanguage].currency.symbol + ')?(?:\\))?)?$');
128
129 // see if bytes are there so that we can multiply to the correct number
130 for (power = 0; power <= binarySuffixes.length && !bytesMultiplier; power++) {
131 if (string.indexOf(binarySuffixes[power]) > -1) { bytesMultiplier = Math.pow(1024, power + 1); }
132 else if (string.indexOf(decimalSuffixes[power]) > -1) { bytesMultiplier = Math.pow(1000, power + 1); }
133 else { bytesMultiplier = false; }
134 }
135
136 // do some math to create our number
137 n._value = ((bytesMultiplier) ? bytesMultiplier : 1) * ((stringOriginal.match(thousandRegExp)) ? Math.pow(10, 3) : 1) * ((stringOriginal.match(millionRegExp)) ? Math.pow(10, 6) : 1) * ((stringOriginal.match(billionRegExp)) ? Math.pow(10, 9) : 1) * ((stringOriginal.match(trillionRegExp)) ? Math.pow(10, 12) : 1) * ((string.indexOf('%') > -1) ? 0.01 : 1) * (((string.split('-').length + Math.min(string.split('(').length - 1, string.split(')').length - 1)) % 2) ? 1 : -1) * Number(string.replace(/[^0-9\.]+/g, ''));
138
139 // round if we are talking about bytes
140 n._value = (bytesMultiplier) ? Math.ceil(n._value) : n._value;
141 }
142 }
143 return n._value;
144 }
145
146 function formatCurrency(n, format, roundingFunction) {
147 var symbolIndex = format.indexOf('$'),
148 openParenIndex = format.indexOf('('),
149 minusSignIndex = format.indexOf('-'),
150 space = '',
151 spliceIndex,
152 output;
153
154 // check for space before or after currency
155 if (format.indexOf(' $') > -1) {
156 space = ' ';
157 format = format.replace(' $', '');
158 } else if (format.indexOf('$ ') > -1) {
159 space = ' ';
160 format = format.replace('$ ', '');
161 } else {
162 format = format.replace('$', '');
163 }
164
165 // format the number
166 output = formatNumber(n._value, format, roundingFunction);
167
168 // position the symbol
169 if (symbolIndex <= 1) {
170 if (output.indexOf('(') > -1 || output.indexOf('-') > -1) {
171 output = output.split('');
172 spliceIndex = 1;
173 if (symbolIndex < openParenIndex || symbolIndex < minusSignIndex) {
174 // the symbol appears before the "(" or "-"
175 spliceIndex = 0;
176 }
177 output.splice(spliceIndex, 0, languages[options.currentLanguage].currency.symbol + space);
178 output = output.join('');
179 } else {
180 output = languages[options.currentLanguage].currency.symbol + space + output;
181 }
182 } else {
183 if (output.indexOf(')') > -1) {
184 output = output.split('');
185 output.splice(-1, 0, space + languages[options.currentLanguage].currency.symbol);
186 output = output.join('');
187 } else {
188 output = output + space + languages[options.currentLanguage].currency.symbol;
189 }
190 }
191
192 return output;
193 }
194
195 function formatPercentage(n, format, roundingFunction) {
196 var space = '',
197 output,
198 value = n._value * 100;
199
200 // check for space before %
201 if (format.indexOf(' %') > -1) {
202 space = ' ';
203 format = format.replace(' %', '');
204 } else {
205 format = format.replace('%', '');
206 }
207
208 output = formatNumber(value, format, roundingFunction);
209
210 if (output.indexOf(')') > -1) {
211 output = output.split('');
212 output.splice(-1, 0, space + '%');
213 output = output.join('');
214 } else {
215 output = output + space + '%';
216 }
217
218 return output;
219 }
220
221 function formatTime(n) {
222 var hours = Math.floor(n._value / 60 / 60),
223 minutes = Math.floor((n._value - (hours * 60 * 60)) / 60),
224 seconds = Math.round(n._value - (hours * 60 * 60) - (minutes * 60));
225 return hours + ':' + ((minutes < 10) ? '0' + minutes : minutes) + ':' + ((seconds < 10) ? '0' + seconds : seconds);
226 }
227
228 function unformatTime(string) {
229 var timeArray = string.split(':'),
230 seconds = 0;
231 // turn hours and minutes into seconds and add them all up
232 if (timeArray.length === 3) {
233 // hours
234 seconds = seconds + (Number(timeArray[0]) * 60 * 60);
235 // minutes
236 seconds = seconds + (Number(timeArray[1]) * 60);
237 // seconds
238 seconds = seconds + Number(timeArray[2]);
239 } else if (timeArray.length === 2) {
240 // minutes
241 seconds = seconds + (Number(timeArray[0]) * 60);
242 // seconds
243 seconds = seconds + Number(timeArray[1]);
244 }
245 return Number(seconds);
246 }
247
248 function formatNumber(value, format, roundingFunction) {
249 var negP = false,
250 signed = false,
251 optDec = false,
252 abbr = '',
253 abbrK = false, // force abbreviation to thousands
254 abbrM = false, // force abbreviation to millions
255 abbrB = false, // force abbreviation to billions
256 abbrT = false, // force abbreviation to trillions
257 abbrForce = false, // force abbreviation
258 bytes = '',
259 ord = '',
260 abs = Math.abs(value),
261 binarySuffixes = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'],
262 decimalSuffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
263 min,
264 max,
265 power,
266 w,
267 precision,
268 thousands,
269 d = '',
270 neg = false;
271
272 // check if number is zero and a custom zero format has been set
273 if (value === 0 && options.zeroFormat !== null) {
274 return options.zeroFormat;
275 } else if (value === null && options.nullFormat !== null) {
276 return options.nullFormat;
277 } else {
278 // see if we should use parentheses for negative number or if we should prefix with a sign
279 // if both are present we default to parentheses
280 if (format.indexOf('(') > -1) {
281 negP = true;
282 format = format.slice(1, -1);
283 } else if (format.indexOf('+') > -1) {
284 signed = true;
285 format = format.replace(/\+/g, '');
286 }
287
288 // see if abbreviation is wanted
289 if (format.indexOf('a') > -1) {
290 // check if abbreviation is specified
291 abbrK = format.indexOf('aK') >= 0;
292 abbrM = format.indexOf('aM') >= 0;
293 abbrB = format.indexOf('aB') >= 0;
294 abbrT = format.indexOf('aT') >= 0;
295 abbrForce = abbrK || abbrM || abbrB || abbrT;
296
297 // check for space before abbreviation
298 if (format.indexOf(' a') > -1) {
299 abbr = ' ';
300 }
301
302 format = format.replace(new RegExp(abbr + 'a[KMBT]?'), '');
303
304 if (abs >= Math.pow(10, 12) && !abbrForce || abbrT) {
305 // trillion
306 abbr = abbr + languages[options.currentLanguage].abbreviations.trillion;
307 value = value / Math.pow(10, 12);
308 } else if (abs < Math.pow(10, 12) && abs >= Math.pow(10, 9) && !abbrForce || abbrB) {
309 // billion
310 abbr = abbr + languages[options.currentLanguage].abbreviations.billion;
311 value = value / Math.pow(10, 9);
312 } else if (abs < Math.pow(10, 9) && abs >= Math.pow(10, 6) && !abbrForce || abbrM) {
313 // million
314 abbr = abbr + languages[options.currentLanguage].abbreviations.million;
315 value = value / Math.pow(10, 6);
316 } else if (abs < Math.pow(10, 6) && abs >= Math.pow(10, 3) && !abbrForce || abbrK) {
317 // thousand
318 abbr = abbr + languages[options.currentLanguage].abbreviations.thousand;
319 value = value / Math.pow(10, 3);
320 }
321 }
322
323 // see if we are formatting binary bytes
324 if (format.indexOf('b') > -1) {
325 // check for space before
326 if (format.indexOf(' b') > -1) {
327 bytes = ' ';
328 format = format.replace(' b', '');
329 } else {
330 format = format.replace('b', '');
331 }
332
333 for (power = 0; power <= binarySuffixes.length; power++) {
334 min = Math.pow(1024, power);
335 max = Math.pow(1024, power + 1);
336
337 if (value >= min && value < max) {
338 bytes = bytes + binarySuffixes[power];
339 if (min > 0) {
340 value = value / min;
341 }
342 break;
343 }
344 }
345 }
346
347 // see if we are formatting decimal bytes
348 if (format.indexOf('d') > -1) {
349 // check for space before
350 if (format.indexOf(' d') > -1) {
351 bytes = ' ';
352 format = format.replace(' d', '');
353 } else {
354 format = format.replace('d', '');
355 }
356
357 for (power = 0; power <= decimalSuffixes.length; power++) {
358 min = Math.pow(1000, power);
359 max = Math.pow(1000, power+1);
360
361 if (value >= min && value < max) {
362 bytes = bytes + decimalSuffixes[power];
363 if (min > 0) {
364 value = value / min;
365 }
366 break;
367 }
368 }
369 }
370
371 // see if ordinal is wanted
372 if (format.indexOf('o') > -1) {
373 // check for space before
374 if (format.indexOf(' o') > -1) {
375 ord = ' ';
376 format = format.replace(' o', '');
377 } else {
378 format = format.replace('o', '');
379 }
380
381 ord = ord + languages[options.currentLanguage].ordinal(value);
382 }
383
384 if (format.indexOf('[.]') > -1) {
385 optDec = true;
386 format = format.replace('[.]', '.');
387 }
388
389 w = value.toString().split('.')[0];
390 precision = format.split('.')[1];
391 thousands = format.indexOf(',');
392
393 if (precision) {
394 if (precision.indexOf('[') > -1) {
395 precision = precision.replace(']', '');
396 precision = precision.split('[');
397 d = toFixed(value, (precision[0].length + precision[1].length), roundingFunction, precision[1].length);
398 } else {
399 d = toFixed(value, precision.length, roundingFunction);
400 }
401
402 w = d.split('.')[0];
403
404 if (d.indexOf('.') > -1) {
405 d = languages[options.currentLanguage].delimiters.decimal + d.split('.')[1];
406 } else {
407 d = '';
408 }
409
410 if (optDec && Number(d.slice(1)) === 0) {
411 d = '';
412 }
413 } else {
414 w = toFixed(value, null, roundingFunction);
415 }
416
417 // format number
418 if (w.indexOf('-') > -1) {
419 w = w.slice(1);
420 neg = true;
421 }
422
423 if (thousands > -1) {
424 w = w.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + languages[options.currentLanguage].delimiters.thousands);
425 }
426
427 if (format.indexOf('.') === 0) {
428 w = '';
429 }
430
431 return ((negP && neg) ? '(' : '') + ((!negP && neg) ? '-' : '') + ((!neg && signed) ? '+' : '') + w + d + ((ord) ? ord : '') + ((abbr) ? abbr : '') + ((bytes) ? bytes : '') + ((negP && neg) ? ')' : '');
432 }
433 }
434
435 /************************************
436 Top Level Functions
437 ************************************/
438
439 numeral = function(input) {
440 if (numeral.isNumeral(input)) {
441 input = input.value();
442 } else if (input === 0 || typeof input === 'undefined') {
443 input = 0;
444 } else if (input === null) {
445 input = null;
446 } else if (!Number(input)) {
447 input = numeral.fn.unformat(input);
448 }
449
450 return new Numeral(input);
451 };
452
453 // version number
454 numeral.version = VERSION;
455
456 // compare numeral object
457 numeral.isNumeral = function(obj) {
458 return obj instanceof Numeral;
459 };
460
461
462 // This function will load languages and then set the global language. If
463 // no arguments are passed in, it will simply return the current global
464 // language key.
465 numeral.language = function(key, values) {
466 if (!key) {
467 return options.currentLanguage;
468 }
469
470 key = key.toLowerCase();
471
472 if (key && !values) {
473 if (!languages[key]) {
474 throw new Error('Unknown language : ' + key);
475 }
476
477 options.currentLanguage = key;
478 }
479
480 if (values || !languages[key]) {
481 loadLanguage(key, values);
482 }
483
484 return numeral;
485 };
486
487 numeral.reset = function() {
488 for (var property in defaults) {
489 options[property] = defaults[property];
490 }
491 };
492
493 // This function provides access to the loaded language data. If
494 // no arguments are passed in, it will simply return the current
495 // global language object.
496 numeral.languageData = function(key) {
497 if (!key) {
498 return languages[options.currentLanguage];
499 }
500
501 if (!languages[key]) {
502 throw new Error('Unknown language : ' + key);
503 }
504
505 return languages[key];
506 };
507
508 numeral.language('en', {
509 delimiters: {
510 thousands: ',',
511 decimal: '.'
512 },
513 abbreviations: {
514 thousand: 'k',
515 million: 'm',
516 billion: 'b',
517 trillion: 't'
518 },
519 ordinal: function(number) {
520 var b = number % 10;
521 return (~~(number % 100 / 10) === 1) ? 'th' :
522 (b === 1) ? 'st' :
523 (b === 2) ? 'nd' :
524 (b === 3) ? 'rd' : 'th';
525 },
526 currency: {
527 symbol: '$'
528 }
529 });
530
531 numeral.zeroFormat = function(format) {
532 options.zeroFormat = typeof(format) === 'string' ? format : null;
533 };
534
535 numeral.nullFormat = function (format) {
536 options.nullFormat = typeof(format) === 'string' ? format : null;
537 };
538
539 numeral.defaultFormat = function(format) {
540 options.defaultFormat = typeof(format) === 'string' ? format : '0.0';
541 };
542
543 numeral.validate = function(val, culture) {
544
545 var _decimalSep,
546 _thousandSep,
547 _currSymbol,
548 _valArray,
549 _abbrObj,
550 _thousandRegEx,
551 languageData,
552 temp;
553
554 //coerce val to string
555 if (typeof val !== 'string') {
556 val += '';
557 if (console.warn) {
558 console.warn('Numeral.js: Value is not string. It has been co-erced to: ', val);
559 }
560 }
561
562 //trim whitespaces from either sides
563 val = val.trim();
564
565 //if val is just digits return true
566 if ( !! val.match(/^\d+$/)) {
567 return true;
568 }
569
570 //if val is empty return false
571 if (val === '') {
572 return false;
573 }
574
575 //get the decimal and thousands separator from numeral.languageData
576 try {
577 //check if the culture is understood by numeral. if not, default it to current language
578 languageData = numeral.languageData(culture);
579 } catch (e) {
580 languageData = numeral.languageData(numeral.language());
581 }
582
583 //setup the delimiters and currency symbol based on culture/language
584 _currSymbol = languageData.currency.symbol;
585 _abbrObj = languageData.abbreviations;
586 _decimalSep = languageData.delimiters.decimal;
587 if (languageData.delimiters.thousands === '.') {
588 _thousandSep = '\\.';
589 } else {
590 _thousandSep = languageData.delimiters.thousands;
591 }
592
593 // validating currency symbol
594 temp = val.match(/^[^\d]+/);
595 if (temp !== null) {
596 val = val.substr(1);
597 if (temp[0] !== _currSymbol) {
598 return false;
599 }
600 }
601
602 //validating abbreviation symbol
603 temp = val.match(/[^\d]+$/);
604 if (temp !== null) {
605 val = val.slice(0, -1);
606 if (temp[0] !== _abbrObj.thousand && temp[0] !== _abbrObj.million && temp[0] !== _abbrObj.billion && temp[0] !== _abbrObj.trillion) {
607 return false;
608 }
609 }
610
611 _thousandRegEx = new RegExp(_thousandSep + '{2}');
612
613 if (!val.match(/[^\d.,]/g)) {
614 _valArray = val.split(_decimalSep);
615 if (_valArray.length > 2) {
616 return false;
617 } else {
618 if (_valArray.length < 2) {
619 return ( !! _valArray[0].match(/^\d+.*\d$/) && !_valArray[0].match(_thousandRegEx));
620 } else {
621 if (_valArray[0].length === 1) {
622 return ( !! _valArray[0].match(/^\d+$/) && !_valArray[0].match(_thousandRegEx) && !! _valArray[1].match(/^\d+$/));
623 } else {
624 return ( !! _valArray[0].match(/^\d+.*\d$/) && !_valArray[0].match(_thousandRegEx) && !! _valArray[1].match(/^\d+$/));
625 }
626 }
627 }
628 }
629
630 return false;
631 };
632
633 /************************************
634 Helpers
635 ************************************/
636
637 function loadLanguage(key, values) {
638 languages[key] = values;
639 }
640
641 /************************************
642 Floating-point helpers
643 ************************************/
644
645 // The floating-point helper functions and implementation
646 // borrows heavily from sinful.js: http://guipn.github.io/sinful.js/
647
648 // Production steps of ECMA-262, Edition 5, 15.4.4.21
649 // Reference: http://es5.github.io/#x15.4.4.21
650 if (!Array.prototype.reduce) {
651 Array.prototype.reduce = function(callback /*, initialValue*/) {
652 'use strict';
653 if (this === null) {
654 throw new TypeError('Array.prototype.reduce called on null or undefined');
655 }
656
657 if (typeof callback !== 'function') {
658 throw new TypeError(callback + ' is not a function');
659 }
660
661 var t = Object(this), len = t.length >>> 0, k = 0, value;
662
663 if (arguments.length === 2) {
664 value = arguments[1];
665 } else {
666 while (k < len && !(k in t)) {
667 k++;
668 }
669
670 if (k >= len) {
671 throw new TypeError('Reduce of empty array with no initial value');
672 }
673
674 value = t[k++];
675 }
676 for (; k < len; k++) {
677 if (k in t) {
678 value = callback(value, t[k], k, t);
679 }
680 }
681 return value;
682 };
683 }
684
685 /**
686 * Computes the multiplier necessary to make x >= 1,
687 * effectively eliminating miscalculations caused by
688 * finite precision.
689 */
690 function multiplier(x) {
691 var parts = x.toString().split('.');
692 if (parts.length < 2) {
693 return 1;
694 }
695 return Math.pow(10, parts[1].length);
696 }
697
698 /**
699 * Given a variable number of arguments, returns the maximum
700 * multiplier that must be used to normalize an operation involving
701 * all of them.
702 */
703 function correctionFactor() {
704 var args = Array.prototype.slice.call(arguments);
705 return args.reduce(function(prev, next) {
706 var mp = multiplier(prev),
707 mn = multiplier(next);
708 return mp > mn ? mp : mn;
709 }, -Infinity);
710 }
711
712
713 /************************************
714 Numeral Prototype
715 ************************************/
716
717
718 numeral.fn = Numeral.prototype = {
719
720 clone: function() {
721 return numeral(this);
722 },
723
724 format : function (inputString, roundingFunction) {
725 return formatNumeral(this,
726 inputString ? inputString : options.defaultFormat,
727 (roundingFunction !== undefined) ? roundingFunction : Math.round
728 );
729 },
730
731 unformat : function (inputString) {
732 if (Object.prototype.toString.call(inputString) === '[object Number]') {
733 return inputString;
734 }
735 return unformatNumeral(this, inputString ? inputString : options.defaultFormat);
736 },
737
738 value: function() {
739 return this._value;
740 },
741
742 valueOf: function() {
743 return this._value;
744 },
745
746 set: function(value) {
747 this._value = Number(value);
748 return this;
749 },
750
751 add: function(value) {
752 var corrFactor = correctionFactor.call(null, this._value, value);
753
754 function cback(accum, curr, currI, O) {
755 return accum + corrFactor * curr;
756 }
757 this._value = [this._value, value].reduce(cback, 0) / corrFactor;
758 return this;
759 },
760
761 subtract: function(value) {
762 var corrFactor = correctionFactor.call(null, this._value, value);
763
764 function cback(accum, curr, currI, O) {
765 return accum - corrFactor * curr;
766 }
767 this._value = [value].reduce(cback, this._value * corrFactor) / corrFactor;
768 return this;
769 },
770
771 multiply: function(value) {
772 function cback(accum, curr, currI, O) {
773 var corrFactor = correctionFactor(accum, curr);
774 return (accum * corrFactor) * (curr * corrFactor) /
775 (corrFactor * corrFactor);
776 }
777 this._value = [this._value, value].reduce(cback, 1);
778 return this;
779 },
780
781 divide: function(value) {
782 function cback(accum, curr, currI, O) {
783 var corrFactor = correctionFactor(accum, curr);
784 return (accum * corrFactor) / (curr * corrFactor);
785 }
786 this._value = [this._value, value].reduce(cback);
787 return this;
788 },
789
790 difference: function(value) {
791 return Math.abs(numeral(this._value).subtract(value).value());
792 }
793
794 };
795
796 /************************************
797 Exposing Numeral
798 ************************************/
799
800 // CommonJS module is defined
801 if (typeof module !== 'undefined' && module.exports) {
802 module.exports = numeral;
803 }
804
805 /*global ender:false */
806 if (typeof ender === 'undefined') {
807 // here, `this` means `window` in the browser, or `global` on the server
808 // add `numeral` as a global object via a string identifier,
809 // for Closure Compiler 'advanced' mode
810 this['numeral'] = numeral;
811 }
812
813 /*global define:false */
814 if (typeof define === 'function' && define.amd) {
815 define([], function() {
816 return numeral;
817 });
818 }
819}).call(this);