1
0
mirror of https://github.com/MikeMcl/decimal.js.git synced 2024-10-27 20:34:12 +00:00

v4.0.0 toFormat amended

This commit is contained in:
Michael Mclaughlin 2014-11-10 16:00:14 +00:00
parent 67bb6b838f
commit 8d7a9969de
6 changed files with 383 additions and 137 deletions

View File

@ -11,7 +11,6 @@ An arbitrary-precision Decimal type for JavaScript.
- Includes a `toFraction` and correctly-rounded `exp`, `ln`, `log` and `sqrt` functions - Includes a `toFraction` and correctly-rounded `exp`, `ln`, `log` and `sqrt` functions
- Supports non-integer powers - Supports non-integer powers
- Works with numbers with or without fraction digits in bases from 2 to 64 inclusive - Works with numbers with or without fraction digits in bases from 2 to 64 inclusive
- Stores values in an accessible decimal floating-point format
- No dependencies - No dependencies
- Wide platform compatibility: uses JavaScript 1.5 (ECMAScript 3) features only - Wide platform compatibility: uses JavaScript 1.5 (ECMAScript 3) features only
- Comprehensive [documentation](http://mikemcl.github.io/decimal.js/) and test set - Comprehensive [documentation](http://mikemcl.github.io/decimal.js/) and test set
@ -27,8 +26,8 @@ those involving division.
This library also adds `exp`, `ln` and `log` functions, among others, and supports non-integer powers. This library also adds `exp`, `ln` and `log` functions, among others, and supports non-integer powers.
Another major difference is that this library enables multiple Decimal constructors to be created Another major difference is that this library enables multiple Decimal constructors to be created
each with their own configuration (e.g. precision and range). This is, however, a significantly each with their own configuration. This is, however, a significantly larger library than
larger library than *bignumber.js* and the even smaller [big.js](https://github.com/MikeMcl/big.js/). *bignumber.js* and the even smaller [big.js](https://github.com/MikeMcl/big.js/).
## Load ## Load
@ -96,12 +95,17 @@ Like JavaScript's Number type, there are `toExponential`, `toFixed` and `toPreci
and a base can be specified for `toString`. and a base can be specified for `toString`.
x.toString(16) // 'ff.8' x.toString(16) // 'ff.8'
There is a `toFraction` method with an optional *maximum denominator* argument There is a `toFormat` method,
y = new Decimal(355) y = new Decimal(1e6)
pi = y.dividedBy(113) // '3.1415929204' y.toFormat(2) // '1,000,000.00'
a `toFraction` method with an optional *maximum denominator* argument
z = new Decimal(355)
pi = z.dividedBy(113) // '3.1415929204'
pi.toFraction() // [ '7853982301', '2500000000' ] pi.toFraction() // [ '7853982301', '2500000000' ]
pi.toFraction(1000) // [ '355', '113' ] pi.toFraction(1000) // [ '355', '113' ]
@ -111,15 +115,16 @@ and `isNaN` and `isFinite` methods, as `NaN` and `Infinity` are valid `Decimal`
y = new Decimal(Infinity) // 'Infinity' y = new Decimal(Infinity) // 'Infinity'
x.isNaN() && !y.isNaN() && !x.isFinite() && !y.isFinite() // true x.isNaN() && !y.isNaN() && !x.isFinite() && !y.isFinite() // true
All calculations are rounded to the number of significant digits specified by the `precision` property All calculations are rounded according to the number of significant digits and rounding mode
of the Decimal constructor and rounded using the rounding mode specified by the `rounding` property. specified by the `precision` and `rounding` properties of the Decimal constructor.
As mentioned above, multiple Decimal constructors can be created, each with their own independent As mentioned above, multiple Decimal constructors can be created, each with their own independent
configuration which applies to all Decimal numbers created from it. configuration which applies to all Decimal numbers created from it.
// Set the precision and rounding of the default Decimal constructor
Decimal.config({ precision: 5, rounding: 4 }) Decimal.config({ precision: 5, rounding: 4 })
// constructor is a factory method and it can also accept a configuration object // Create another Decimal constructor, optionally passing in a configuration object
Decimal10 = Decimal.constructor({ precision: 10, rounding: 1 }) Decimal10 = Decimal.constructor({ precision: 10, rounding: 1 })
x = new Decimal(5) x = new Decimal(5)
@ -178,7 +183,7 @@ then
will create *decimal.min.js*. will create *decimal.min.js*.
The *decimal.min.js* already present was created with *Microsoft Ajax Minifier 5.8*. The *decimal.min.js* already present was created with *Microsoft Ajax Minifier 5.11*.
## Feedback ## Feedback
@ -198,6 +203,9 @@ See LICENCE.
## Change Log ## Change Log
####4.0.0
* 10/11/2014 `toFormat` amended to use `Decimal.format` object for more flexible configuration.
####3.0.1 ####3.0.1
* 8/06/2014 Surround crypto require in try catch. See issue #5 * 8/06/2014 Surround crypto require in try catch. See issue #5

View File

@ -1,10 +1,10 @@
/*! decimal.js v3.0.1 https://github.com/MikeMcl/decimal.js/LICENCE */ /*! decimal.js v4.0.0 https://github.com/MikeMcl/decimal.js/LICENCE */
;(function (global) { ;(function (global) {
'use strict'; 'use strict';
/* /*
* decimal.js v3.0.1 * decimal.js v4.0.0
* An arbitrary-precision Decimal type for JavaScript. * An arbitrary-precision Decimal type for JavaScript.
* https://github.com/MikeMcl/decimal.js * https://github.com/MikeMcl/decimal.js
* Copyright (c) 2014 Michael Mclaughlin <M8ch88l@gmail.com> * Copyright (c) 2014 Michael Mclaughlin <M8ch88l@gmail.com>
@ -1260,25 +1260,74 @@
/* /*
* Return a string representing the value of this Decimal in normal notation rounded using * Return a string representing the value of this Decimal in fixed-point notation to dp decimal
* rounding mode rounding to dp fixed decimal places, with the integer part of the number * places, rounded using rounding mode rm or Decimal.rounding if rm is omitted, and formatted
* separated into thousands by string sep1 or ',' if sep1 is null or undefined, and the * according to the following properties of the Decimal.format object.
* fraction part separated into groups of five digits by string sep2. *
* Decimal.format = {
* decimalSeparator : '.',
* groupSeparator : ',',
* groupSize : 3,
* secondaryGroupSize : 0,
* fractionGroupSeparator : '\xA0', // non-breaking space
* fractionGroupSize : 0
* };
*
* If groupFractionDigits is truthy, fraction digits will be separated into 5-digit groupings
* using the space character as separator.
* *
* [sep1] {string} The grouping separator of the integer part of the number.
* [sep2] {string} The grouping separator of the fraction part of the number.
* [dp] {number} Decimal places. Integer, -MAX_DIGITS to MAX_DIGITS inclusive. * [dp] {number} Decimal places. Integer, -MAX_DIGITS to MAX_DIGITS inclusive.
* [rm] {number} Rounding mode. Integer, 0 to 8 inclusive
* *
* Non-breaking thin-space: \u202f * (If dp or rm are invalid the error message will give the offending method call as toFixed.)
*
* If dp is invalid the error message will incorrectly give the method as toFixed.
* *
*/ */
P['toFormat'] = function ( sep1, dp, sep2 ) { P['toFormat'] = function( dp, rm ) {
var arr = this.toFixed(dp).split('.'); var x = this;
return arr[0].replace( /\B(?=(\d{3})+$)/g, sep1 == null ? ',' : sep1 + '' ) + if ( !x['c'] ) {
( arr[1] ? '.' + ( sep2 ? arr[1].replace( /\d{5}\B/g, '$&' + sep2 ) : arr[1] ) : '' ); return x.toString();
}
var i,
isNeg = x['s'] < 0,
format = x['constructor']['format'],
groupSeparator = format['groupSeparator'],
g1 = +format['groupSize'],
g2 = +format['secondaryGroupSize'],
arr = x.toFixed( dp, rm ).split('.'),
intPart = arr[0],
fractionPart = arr[1],
intDigits = isNeg ? intPart.slice(1) : intPart,
len = intDigits.length;
if (g2) {
len -= ( i = g1, g1 = g2, g2 = i );
}
if ( g1 > 0 && len > 0 ) {
i = len % g1 || g1;
intPart = intDigits.substr( 0, i );
for ( ; i < len; i += g1 ) {
intPart += groupSeparator + intDigits.substr( i, g1 );
}
if ( g2 > 0 ) {
intPart += groupSeparator + intDigits.slice(i);
}
if (isNeg) {
intPart = '-' + intPart;
}
}
return fractionPart
? intPart + format['decimalSeparator'] + ( ( g2 = +format['fractionGroupSize'] )
? fractionPart.replace( new RegExp( '\\d{' + g2 + '}\\B', 'g' ),
'$&' + format['fractionGroupSeparator'] )
: fractionPart )
: intPart;
}; };
@ -1566,8 +1615,8 @@
log10(x_significand) = ln(x_significand) / ln(10) log10(x_significand) = ln(x_significand) / ln(10)
*/ */
e = b == 0 || !isFinite(b) e = b == 0 || !isFinite(b)
? mathfloor( yN * ( ? mathfloor( yN * ( Math.log( '0.' + coefficientToString( x['c'] ) ) /
Math.log( '0.' + coefficientToString( x['c'] ) ) / Math.LN10 + x['e'] + 1 ) ) Math.LN10 + x['e'] + 1 ) )
: new Decimal( b + '' )['e']; : new Decimal( b + '' )['e'];
// Estimate may be incorrect e.g.: x: 0.999999999999999999, y: 2.29, e: 0, r.e:-1 // Estimate may be incorrect e.g.: x: 0.999999999999999999, y: 2.29, e: 0, r.e:-1
@ -1875,7 +1924,7 @@
n %= LOGBASE; n %= LOGBASE;
} }
k =mathpow( 10, LOGBASE - n ); k = mathpow( 10, LOGBASE - n );
rd = c[ci] % k | 0; rd = c[ci] % k | 0;
if ( repeating == null ) { if ( repeating == null ) {
@ -2816,7 +2865,7 @@
been repeated previously) and the first 4 rounding digits 9999? been repeated previously) and the first 4 rounding digits 9999?
If so, restart the summation with a higher precision, otherwise If so, restart the summation with a higher precision, otherwise
E.g. with precision: 12, rounding: 1 e.g. with precision: 12, rounding: 1
ln(135520028.6126091714265381533) = 18.7246299999 when it should be 18.72463. ln(135520028.6126091714265381533) = 18.7246299999 when it should be 18.72463.
sd - guard is the index of first rounding digit. sd - guard is the index of first rounding digit.
@ -2853,7 +2902,7 @@
Decimal = x['constructor']; Decimal = x['constructor'];
// Don't round if sd is null or undefined. // Don't round if sd is null or undefined.
r: if ( sd != i ) { r: if ( sd != null ) {
// Infinity/NaN. // Infinity/NaN.
if ( !( xc = x['c'] ) ) { if ( !( xc = x['c'] ) ) {
@ -2978,7 +3027,7 @@
for ( ; ; ) { for ( ; ; ) {
// Is the digit to be rounded up in the first element of xc. // Is the digit to be rounded up in the first element of xc?
if ( xci == 0 ) { if ( xci == 0 ) {
// i will be the length of xc[0] before k is added. // i will be the length of xc[0] before k is added.
@ -3132,6 +3181,16 @@
* crypto {boolean|number} * crypto {boolean|number}
* modulo {number} * modulo {number}
* *
* format {object} See Decimal.prototype.toFormat
* decimalSeparator {string}
* groupSeparator {string}
* groupSize {number}
* secondaryGroupSize {number}
* groupFractionDigits {boolean|number}
*
* A format object will replace the existing Decimal.format object without any property
* checking.
*
* E.g. * E.g.
* Decimal.config({ precision: 20, rounding: 4 }) * Decimal.config({ precision: 20, rounding: 4 })
* *
@ -3143,12 +3202,13 @@
parse = Decimal['errors'] ? parseInt : parseFloat; parse = Decimal['errors'] ? parseInt : parseFloat;
if ( obj == u || typeof obj != 'object' && if ( obj == u || typeof obj != 'object' &&
// 'config() object expected: {obj}'
!ifExceptionsThrow( Decimal, 'object expected', obj, c ) ) { !ifExceptionsThrow( Decimal, 'object expected', obj, c ) ) {
return Decimal; return Decimal;
} }
// precision {number|number[]} Integer, 1 to MAX_DIGITS inclusive. // precision {number} Integer, 1 to MAX_DIGITS inclusive.
if ( ( v = obj[ p = 'precision' ] ) != u ) { if ( ( v = obj[ p = 'precision' ] ) != u ) {
if ( !( outOfRange = v < 1 || v > MAX_DIGITS ) && parse(v) == v ) { if ( !( outOfRange = v < 1 || v > MAX_DIGITS ) && parse(v) == v ) {
@ -3264,6 +3324,18 @@
} }
} }
// format {object}
if ( ( obj = obj[ p = 'format' ] ) != u ) {
if ( typeof obj == 'object' ) {
Decimal[p] = obj;
} else {
// 'config() format object expected: {obj}'
ifExceptionsThrow( Decimal, 'format object expected', obj, c );
}
}
return Decimal; return Decimal;
} }
@ -3376,14 +3448,13 @@
if ( typeof n != 'string' ) { if ( typeof n != 'string' ) {
// TODO: modify so regex test below is avoided if type is number.
// If n is a number, check if minus zero. // If n is a number, check if minus zero.
n = ( isNum = typeof n == 'number' || toString.call(n) == '[object Number]' ) && n = ( isNum = typeof n == 'number' || toString.call(n) == '[object Number]' ) &&
n === 0 && 1 / n < 0 ? '-0' : n + ''; n === 0 && 1 / n < 0 ? '-0' : n + '';
} }
orig = n; orig = n;
if ( b == e && isValid.test(n) ) { if ( b == null && isValid.test(n) ) {
// Determine sign. // Determine sign.
x['s'] = n.charAt(0) == '-' ? ( n = n.slice(1), -1 ) : 1; x['s'] = n.charAt(0) == '-' ? ( n = n.slice(1), -1 ) : 1;
@ -3404,7 +3475,7 @@
x['s'] = n.charAt(0) == '-' ? ( n = n.replace( /^-(?!-)/, '' ), -1 ) : 1; x['s'] = n.charAt(0) == '-' ? ( n = n.replace( /^-(?!-)/, '' ), -1 ) : 1;
if ( b != e ) { if ( b != null ) {
if ( ( b == (b | 0) || !Decimal['errors'] ) && if ( ( b == (b | 0) || !Decimal['errors'] ) &&
!( outOfRange = !( b >= 2 && b < 65 ) ) ) { !( outOfRange = !( b >= 2 && b < 65 ) ) ) {
@ -3415,8 +3486,7 @@
// Any number in exponential form will fail due to the e+/-. // Any number in exponential form will fail due to the e+/-.
if ( valid = new RegExp( if ( valid = new RegExp(
'^' + d + '(?:\\.' + d + ')?$', b < 37 ? 'i' : '' ).test(n) '^' + d + '(?:\\.' + d + ')?$', b < 37 ? 'i' : '' ).test(n) ) {
) {
if (isNum) { if (isNum) {
@ -3478,7 +3548,7 @@
} }
// Exponential form? // Exponential form?
if ( ( i = n.search( /e/i ) ) > 0 ) { if ( ( i = n.search(/e/i) ) > 0 ) {
// Determine exponent. // Determine exponent.
if ( e < 0 ) { if ( e < 0 ) {
@ -3863,19 +3933,19 @@
// The exponent value at and beneath which toString returns exponential notation. // The exponent value at and beneath which toString returns exponential notation.
// Number type: -7 // Number type: -7
Decimal['toExpNeg'] = -7; // 0 to -EXP_LIMIT Decimal['toExpNeg'] = -7; // 0 to -EXP_LIMIT
// The exponent value at and above which toString returns exponential notation. // The exponent value at and above which toString returns exponential notation.
// Number type: 21 // Number type: 21
Decimal['toExpPos'] = 21; // 0 to EXP_LIMIT Decimal['toExpPos'] = 21; // 0 to EXP_LIMIT
// The minimum exponent value, beneath which underflow to zero occurs. // The minimum exponent value, beneath which underflow to zero occurs.
// Number type: -324 (5e-324) // Number type: -324 (5e-324)
Decimal['minE'] = -EXP_LIMIT; // -1 to -EXP_LIMIT Decimal['minE'] = -EXP_LIMIT; // -1 to -EXP_LIMIT
// The maximum exponent value, above which overflow to Infinity occurs. // The maximum exponent value, above which overflow to Infinity occurs.
// Number type: 308 (1.7976931348623157e+308) // Number type: 308 (1.7976931348623157e+308)
Decimal['maxE'] = EXP_LIMIT; // 1 to EXP_LIMIT Decimal['maxE'] = EXP_LIMIT; // 1 to EXP_LIMIT
// Whether Decimal Errors are ever thrown. // Whether Decimal Errors are ever thrown.
Decimal['errors'] = true; // true/false Decimal['errors'] = true; // true/false
@ -3883,6 +3953,16 @@
// Whether to use cryptographically-secure random number generation, if available. // Whether to use cryptographically-secure random number generation, if available.
Decimal['crypto'] = false; // true/false Decimal['crypto'] = false; // true/false
// Format specification for the Decimal.prototype.toFormat method
Decimal.format = {
decimalSeparator : '.',
groupSeparator : ',',
groupSize : 3,
secondaryGroupSize : 0,
fractionGroupSeparator : '\xA0', // non-breaking space
fractionGroupSize : 0
};
/* ********************** END OF CONSTRUCTOR DEFAULT PROPERTIES ********************* */ /* ********************** END OF CONSTRUCTOR DEFAULT PROPERTIES ********************* */

4
decimal.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -92,6 +92,7 @@ li span{float:right;margin-right:10px;color:#c0c0c0}
<li><a href="#errors" >errors</a></li> <li><a href="#errors" >errors</a></li>
<li><a href="#modulo" >modulo</a></li> <li><a href="#modulo" >modulo</a></li>
<li><a href="#crypto" >crypto</a></li> <li><a href="#crypto" >crypto</a></li>
<li><a href="#format" >format</a></li>
<li class='spacer'>&nbsp;</li> <li class='spacer'>&nbsp;</li>
<li><a href="#modes">ROUND_UP</a></li> <li><a href="#modes">ROUND_UP</a></li>
<li><a href="#modes">ROUND_DOWN</a></li> <li><a href="#modes">ROUND_DOWN</a></li>
@ -348,7 +349,15 @@ Decimal.config({
maxE: 9e15, maxE: 9e15,
errors: true, errors: true,
crypto: false, crypto: false,
modulo: 1 modulo: 1,
format: {
decimalSeparator : '.',
groupSeparator : ',',
groupSize : 3,
secondaryGroupSize : 0,
fractionGroupSeparator : '\xA0', // non-breaking space
fractionGroupSize : 0
}
})</pre> })</pre>
<p> <p>
The properties of a Decimal constructor can also be set by direct assignment, but that will The properties of a Decimal constructor can also be set by direct assignment, but that will
@ -553,13 +562,16 @@ x.equals(y) // true</pre>
<a href='#rounding'><code>rounding</code></a>, <a href='#minE'><code>minE</code></a>, <a href='#rounding'><code>rounding</code></a>, <a href='#minE'><code>minE</code></a>,
<a href='#maxE'><code>maxE</code></a>, <a href='#toExpNeg'><code>toExpNeg</code></a>, <a href='#maxE'><code>maxE</code></a>, <a href='#toExpNeg'><code>toExpNeg</code></a>,
<a href='#toExpPos'><code>toExpPos</code></a>, <a href='#errors'><code>errors</code></a>, <a href='#toExpPos'><code>toExpPos</code></a>, <a href='#errors'><code>errors</code></a>,
<a href='#modulo'><code>modulo</code></a> and <a href='#crypto'><code>crypto</code></a> are <a href='#modulo'><code>modulo</code></a>, <a href='#crypto'><code>crypto</code></a> and
set using the <a href='#Dconfig'><code>config</code></a> method. <a href='#format'><code>format</code></a> are set using the
<a href='#Dconfig'><code>config</code></a> method.
</p> </p>
<p> <p>
As simple object properties they can be set directly without using As simple object properties they can be set directly without using
<a href='#Dconfig'><code>config</code></a>, and it is fine to do so, but the values assigned <a href='#Dconfig'><code>config</code></a>, and it is fine to do so, but the values assigned
will not then be checked for validity. For example: will not then be checked for validity (the properties of the
<a href='#Dconfig'><code>format</code></a> object are not checked by
<code>config</code>). For example:
</p> </p>
<pre>Decimal.config({ precision: 0 }) <pre>Decimal.config({ precision: 0 })
// 'Decimal Error: config() precision out of range: 0' // 'Decimal Error: config() precision out of range: 0'
@ -851,6 +863,47 @@ Decimal.config({ crypto: true })</pre>
<h5 id="format">format</h5>
<p><i>object</i>
<p>
The <code>format</code> object configures the format of the string returned by the
<a href='#toFo'><code>toFormat</code></a> method.
</p>
<p>
The example below shows the properties of the <code>format</code> object
that are recognised, and their default values.
</p>
<p>
Unlike setting other properties using <code>config</code>, the values of the
properties of the <code>format</code> object will not be checked for validity. The existing
<code>format</code> object will simply be replaced by the object that is passed in. Only the
<a href='#toFo'><code>toFormat</code></a> method ever references a Decimal constructor's
<code>format</code> object property.
</p>
<p>
See <a href='#toFo'><code>toFormat</code></a> for examples of usage, and of setting
<code>format</code> properties individually and directly without using <code>config</code>.
</p>
<pre>
Decimal.config({
format : {
// the decimal separator
decimalSeparator : '.',
// the grouping separator of the integer part of the number
groupSeparator : ',',
// the primary grouping size of the integer part of the number
groupSize : 3,
// the secondary grouping size of the integer part of the number
secondaryGroupSize : 0,
// the grouping separator of the fraction part of the number
fractionGroupSeparator : ' ',
// the grouping size of the fraction part of the number
fractionGroupSize : 0
}
});</pre>
<h6 id="modes">Rounding modes</h6> <h6 id="modes">Rounding modes</h6>
<p> <p>
The library's enumerated rounding modes are stored as properties of a Decimal constructor. The library's enumerated rounding modes are stored as properties of a Decimal constructor.
@ -1617,47 +1670,61 @@ y.toFixed(5) // '3.45600'</pre>
<h5 id="toFo"> <h5 id="toFo">
toFormat<code class='inset'>.toFormat([sep1 [, dp [, sep2]]]) <i>&rArr; string</i></code> toFormat<code class='inset'>.toFormat([dp [, rm]]) <i>&rArr; string</i></code>
</h5> </h5>
<p> <p>
<code>sep1</code>: <i>string</i>: the grouping separator of the integer part of the number <code>dp</code>: <i>number</i>: integer, 0 to 1e+9 inclusive<br />
<br /> <code>rm</code>: <i>number</i>: integer, 0 to 8 inclusive
<code>sep2</code>: <i>string</i>: the grouping separator of the fraction part of the number
<br />
<code>dp</code>: <i>number</i>: integer, 0 to 8 inclusive
</p> </p>
<p> <p>
<i> Returns a string representing the value of this Decimal in fixed-point notation rounded to
This method is a placeholder and is likely to be subject to change / further development. <code>dp</code> decimal places using rounding mode <code>rm</code> (as
</i> <a href='#toFi'><code>toFixed</code></a>), and formatted according to the properties of this
Decimal's constructor's <a href='#format'><code>format</code></a> object property.
</p> </p>
<p> <p>
Returns a string representing the value of this Decimal to <code>dp</code> decimal places, See the examples below for the properties of the <a href='#format'><code>format</code></a>
(see <a href='#toFi'><code>toFixed</code></a>), but with the integer part of the number object, their types and their usage.
separated by <code>sep1</code> into groups of three digits, and the fraction part of the
number separated into groups of five digits by <code>sep2</code>.
</p>
<p>
If <code>sep1</code> is <code>null</code> or undefined, the integer part groupings will be
separated by a comma.
</p>
<p>
If <code>sep2</code> is <code>null</code> or undefined, the fraction part groupings will not
be separated.
</p> </p>
<p> <p>
If <code>dp</code> is omitted or is <code>null</code> or undefined, then the return value is If <code>dp</code> is omitted or is <code>null</code> or undefined, then the return value is
not rounded to a fixed number of decimal places. not rounded to a fixed number of decimal places.
</p> </p>
<p>A useful separator character is the non-breaking thin-space: <code>\u202f</code>.<p> <p>
if <code>rm</code> is omitted or is <code>null</code> or undefined, rounding mode
<a href='#rounding'><code>rounding</code></a> is used.
</p>
<pre> <pre>
x = new Decimal('1.23456000000000000000789e+9') // Using config to assign values to the format object
x.toFormat() // '1,234,560,000.00000000000789' Decimal.config({
x.toFormat(' ') // '1 234 560 000.00000000000789' format : {
x.toFormat(',', 2) // '1,234,560,000.00' decimalSeparator : '.',
x.toFormat(' ', 2) // '1 234 560 000.00' groupSeparator : ',',
x.toFormat(',', 12, ' ') // '1 ,234,560,000.00000 00000 08' groupSize : 3,
x.toFormat('-', 14, '-') // '1-234-560-000.00000-00000-0789'</pre> secondaryGroupSize : 0,
fractionGroupSeparator : ' ',
fractionGroupSize : 0
}
});
x = new Decimal('123456789.123456789')
x.toFormat() // '123,456,789.123456789'
x.toFormat(1) // '123,456,789.1'
// Assigning the format properties directly
Decimal.format.groupSeparator = ' ';
Decimal.format.fractionGroupSize = 5;
x.toFormat() // '123 456 789.12345 6789'
// Assigning the format object directly
Decimal.format = {
decimalSeparator = ',',
groupSeparator = '.',
groupSize = 3,
secondaryGroupSize = 2
}
x.toFormat() // '12.34.56.789,123456789'</pre>

View File

@ -1,7 +1,7 @@
{ {
"name": "decimal.js", "name": "decimal.js",
"description": "An arbitrary-precision Decimal type for JavaScript.", "description": "An arbitrary-precision Decimal type for JavaScript.",
"version": "3.0.1", "version": "4.0.0",
"keywords": [ "keywords": [
"arbitrary", "arbitrary",
"precision", "precision",
@ -31,6 +31,6 @@
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"test": "node ./test/every-test.js", "test": "node ./test/every-test.js",
"build": "uglifyjs decimal.js -c -m -o decimal.min.js --preamble '/* decimal.js v3.0.1 https://github.com/MikeMcl/decimal.js/LICENCE */'" "build": "uglifyjs decimal.js -c -m -o decimal.min.js --preamble '/* decimal.js v4.0.0 https://github.com/MikeMcl/decimal.js/LICENCE */'"
} }
} }

View File

@ -49,8 +49,8 @@ var count = (function toFormat(Decimal) {
} }
} }
function T(expected, value, sep1, dp, sep2){ function T(expected, value, dp){
assert(String(expected), new Decimal(value).toFormat(sep1, dp, sep2)); assert(expected, new Decimal(value).toFormat(dp));
} }
log('\n Testing toFormat...'); log('\n Testing toFormat...');
@ -62,32 +62,40 @@ var count = (function toFormat(Decimal) {
toExpPos: 9e15, toExpPos: 9e15,
minE: -9e15, minE: -9e15,
maxE: 9e15, maxE: 9e15,
errors: true errors: true,
format: {
decimalSeparator : '.',
groupSeparator : ',',
groupSize : 3,
secondaryGroupSize : 0,
fractionGroupSeparator : ' ',
fractionGroupSize : 0
}
}); });
T(0, 0); T('0', 0);
T(1, 1); T('1', 1);
T(-1, -1); T('-1', -1);
T(123.456, 123.456); T('123.456', 123.456);
T(NaN, NaN); T('NaN', NaN);
T(Infinity, 1/0); T('Infinity', 1/0);
T(-Infinity, -1/0); T('-Infinity', -1/0);
T(0, 0, ' '); T('0', 0, null);
T(1, 1, ' '); T('1', 1, undefined);
T(-1, -1, ' '); T('-1', -1, 0);
T(123.456, 123.456, ' '); T('123.456', 123.456, 3);
T(NaN, NaN, ' '); T('NaN', NaN, 0);
T(Infinity, 1/0, ' '); T('Infinity', 1/0, 3);
T(-Infinity, -1/0, ' '); T('-Infinity', -1/0, 0);
T('0.0', 0, ' ', 1); T('0.0', 0, 1);
T('1.00', 1, ' ', 2); T('1.00', 1, 2);
T('-1.000', -1, ' ', 3); T('-1.000', -1, 3);
T('123.4560', 123.456, ' ', 4); T('123.4560', 123.456, 4);
T(NaN, NaN, ' ', 5); T('NaN', NaN, 5);
T(Infinity, 1/0, ' ', 6); T('Infinity', 1/0, 6);
T(-Infinity, -1/0, ' ', 7); T('-Infinity', -1/0, 7);
T('9,876.54321', 9876.54321); T('9,876.54321', 9876.54321);
T('4,018,736,400,000,000,000,000', '4.0187364e+21'); T('4,018,736,400,000,000,000,000', '4.0187364e+21');
@ -108,42 +116,125 @@ var count = (function toFormat(Decimal) {
T('99', 99); T('99', 99);
T('9', 9); T('9', 9);
T('999 999 999 999 999', 999999999999999, ' ', 0, ' ');
T('99 999 999 999 999.0', 99999999999999, ' ', 1, ' ');
T('9 999 999 999 999.00', 9999999999999, ' ', 2, ' ');
T('999 999 999 999.000', 999999999999, ' ', 3, ' ');
T('99 999 999 999.0000', 99999999999, ' ', 4, ' ');
T('9 999 999 999.00000', 9999999999, ' ', 5, ' ');
T('999 999 999.00000 0', 999999999, ' ', 6, ' ');
T('99 999 999.00000 00', 99999999, ' ', 7, ' ');
T('9 999 999.00000 000', 9999999, ' ', 8, ' ');
T('999 999.00000 0000', 999999, ' ', 9, ' ');
T('99 999.00000 00000', 99999, ' ', 10, ' ');
T('9 999.00000 00000 0', 9999, ' ', 11, ' ');
T('999.00000 00000 00', 999, ' ', 12, ' ');
T('99.00000 00000 000', 99, ' ', 13, ' ');
T('9.00000 00000 0000', 9, ' ', 14, ' ');
T('1.00000 00000 00000', 1, ' ', 15, ' ');
T('1.00000 00000 0000', 1, ' ', 14, ' ');
T('1.00000 00000 000', 1, ' ', 13, ' ');
T('1.00000 00000 00', 1, ' ', 12, ' ');
T('1.00000 00000 0', 1, ' ', 11, ' ');
T('1.00000 00000', 1, ' ', 10, ' ');
T('1.00000 0000', 1, ' ', 9, ' ');
T('76,852.342091', '7.6852342091e+4'); T('76,852.342091', '7.6852342091e+4');
T('4 018 736 400 000 000 000 000', '4.0187364e+21', ' ');
T('76 852.342091', '7.6852342091e+4', ' ');
T('76 852.34', '7.6852342091e+4', ' ', 2);
T('76 852.34209 10871 45832 64089', '7.685234209108714583264089e+4', ' ', 20, ' '); Decimal.format.groupSeparator = ' ';
T('76 852.34209 10871 45832 64089 7', '7.6852342091087145832640897e+4', ' ', 21, ' ');
T('76 852.34209 10871 45832 64089 70000', '7.6852342091087145832640897e+4', ' ', 25, ' ');
T('76 852.34', '7.6852342091087145832640897e+4', ' ', 2, ' ');
T('1,234,560,000.00000 00000 08', '1.23456000000000000000789e+9', ',', 12, ' '); T('76 852.34', '7.6852342091e+4', 2);
T('1-234-560-000.00000-00000-0789', '1.23456000000000000000789e+9', '-', 14, '-'); T('76 852.342091', '7.6852342091e+4');
T('76 852.3420910871', '7.6852342091087145832640897e+4', 10);
Decimal.format.fractionGroupSize = 5;
T('4 018 736 400 000 000 000 000', '4.0187364e+21');
T('76 852.34209 10871 45832 64089', '7.685234209108714583264089e+4', 20);
T('76 852.34209 10871 45832 64089 7', '7.6852342091087145832640897e+4', 21);
T('76 852.34209 10871 45832 64089 70000', '7.6852342091087145832640897e+4', 25);
T('999 999 999 999 999', 999999999999999, 0);
T('99 999 999 999 999.0', 99999999999999, 1);
T('9 999 999 999 999.00', 9999999999999, 2);
T('999 999 999 999.000', 999999999999, 3);
T('99 999 999 999.0000', 99999999999, 4);
T('9 999 999 999.00000', 9999999999, 5);
T('999 999 999.00000 0', 999999999, 6);
T('99 999 999.00000 00', 99999999, 7);
T('9 999 999.00000 000', 9999999, 8);
T('999 999.00000 0000', 999999, 9);
T('99 999.00000 00000', 99999, 10);
T('9 999.00000 00000 0', 9999, 11);
T('999.00000 00000 00', 999, 12);
T('99.00000 00000 000', 99, 13);
T('9.00000 00000 0000', 9, 14);
T('1.00000 00000 00000', 1, 15);
T('1.00000 00000 0000', 1, 14);
T('1.00000 00000 000', 1, 13);
T('1.00000 00000 00', 1, 12);
T('1.00000 00000 0', 1, 11);
T('1.00000 00000', 1, 10);
T('1.00000 0000', 1, 9);
Decimal.format.fractionGroupSize = 0;
T('4 018 736 400 000 000 000 000', '4.0187364e+21');
T('76 852.34209108714583264089', '7.685234209108714583264089e+4', 20);
T('76 852.342091087145832640897', '7.6852342091087145832640897e+4', 21);
T('76 852.3420910871458326408970000', '7.6852342091087145832640897e+4', 25);
T('999 999 999 999 999', 999999999999999, 0);
T('99 999 999 999 999.0', 99999999999999, 1);
T('9 999 999 999 999.00', 9999999999999, 2);
T('999 999 999 999.000', 999999999999, 3);
T('99 999 999 999.0000', 99999999999, 4);
T('9 999 999 999.00000', 9999999999, 5);
T('999 999 999.000000', 999999999, 6);
T('99 999 999.0000000', 99999999, 7);
T('9 999 999.00000000', 9999999, 8);
T('999 999.000000000', 999999, 9);
T('99 999.0000000000', 99999, 10);
T('9 999.00000000000', 9999, 11);
T('999.000000000000', 999, 12);
T('99.0000000000000', 99, 13);
T('9.00000000000000', 9, 14);
T('1.000000000000000', 1, 15);
T('1.00000000000000', 1, 14);
T('1.0000000000000', 1, 13);
T('1.000000000000', 1, 12);
T('1.00000000000', 1, 11);
T('1.0000000000', 1, 10);
T('1.000000000', 1, 9);
Decimal.config({
format: {
decimalSeparator : '.',
groupSeparator : ',',
groupSize : 3,
secondaryGroupSize : 2
}
});
T('9,876.54321', 9876.54321);
T('10,00,037.123', '1000037.123456789', 3);
T('4,01,87,36,40,00,00,00,00,00,000', '4.0187364e+21');
T('99,99,99,99,99,99,999', 999999999999999);
T('9,99,99,99,99,99,999', 99999999999999);
T('99,99,99,99,99,999', 9999999999999);
T('9,99,99,99,99,999', 999999999999);
T('99,99,99,99,999', 99999999999);
T('9,99,99,99,999', 9999999999);
T('99,99,99,999', 999999999);
T('9,99,99,999', 99999999);
T('99,99,999', 9999999);
T('9,99,999', 999999);
T('99,999', 99999);
T('9,999', 9999);
T('999', 999);
T('99', 99);
T('9', 9);
Decimal.format.decimalSeparator = ',';
Decimal.format.groupSeparator = '.';
T('1.23.45.60.000,000000000008', '1.23456000000000000000789e+9', 12);
Decimal.format.groupSeparator = '';
T('10000000000123456789000000,0000000001', '10000000000123456789000000.000000000100000001', 10);
Decimal.format.groupSeparator = ' ';
Decimal.format.groupSize = 1;
Decimal.format.secondaryGroupSize = 4;
T('4658 0734 6509 8347 6580 3645 0,6', '4658073465098347658036450.59764985763489569875659876459', 1);
Decimal.format.fractionGroupSize = 2;
Decimal.format.fractionGroupSeparator = ':';
Decimal.format.secondaryGroupSize = null;
T('4 6 5 8 0 7 3 4 6 5 0 9 8 3 4 7 6 5 8 0 3 6 4 5 0,59:76:49:85:76:34:89:56:98:75:65:98:76:45:9', '4658073465098347658036450.59764985763489569875659876459' );
log('\n ' + passed + ' of ' + total + ' tests passed in ' + (+new Date() - start) + ' ms \n'); log('\n ' + passed + ' of ' + total + ' tests passed in ' + (+new Date() - start) + ' ms \n');
return [passed, total]; return [passed, total];