Fixed function format for precision > 20 (see #100)

This commit is contained in:
josdejong 2013-11-28 13:38:08 +01:00
parent 9338e0a4ec
commit 0ae1879884
2 changed files with 88 additions and 9 deletions

View File

@ -141,12 +141,10 @@ exports.format = function format(value, options) {
// handle the various notations
switch (notation) {
case 'fixed':
return value.toFixed(precision || 0);
// Note: the (precision || 0) is needed for BigNumber, which has an
// undefined default precision instead of 0.
return exports.toFixed(value, precision);
case 'scientific':
return exports.toScientific(value, precision);
return exports.toExponential(value, precision);
case 'auto':
// determine lower and upper bound for scientific notation.
@ -187,12 +185,12 @@ exports.format = function format(value, options) {
str = new BigNumber(value.toPrecision(precision)).toString();
}
else { // Number
str = parseFloat(value.toPrecision(precision)) + '';
str = parseFloat(value.toPrecision(precision ? Math.min(precision, 21) : precision)) + '';
}
}
else {
// scientific notation
str = exports.toScientific(value, precision);
str = exports.toExponential(value, precision);
}
// restore BigNumber configuration
@ -248,21 +246,43 @@ function _isBetween(value, lower, upper) {
/**
* Format a number in scientific notation. Like '1.23e+5', '2.3e+0', '3.500e-3'
* @param {Number} value
* @param {Number | BigNumber} value
* @param {Number} [precision] Number of digits in formatted output.
* If not provided, the maximum available digits
* is used.
* @returns {string} str
*/
exports.toScientific = function toScientific (value, precision) {
exports.toExponential = function toExponential (value, precision) {
if (precision !== undefined) {
return value.toExponential(precision - 1);
if (value instanceof BigNumber) {
return value.toExponential(precision - 1);
}
else { // Number
return value.toExponential(Math.min(precision - 1, 20));
}
}
else {
return value.toExponential();
}
};
/**
* Format a number with fixed notation.
* @param {Number | BigNumber} value
* @param {Number} [precision=0] Optional number of decimals after the
* decimal point. Zero by default.
*/
exports.toFixed = function toFixed (value, precision) {
if (value instanceof BigNumber) {
return value.toFixed(precision || 0);
// Note: the (precision || 0) is needed as the toFixed of BigNumber has an
// undefined default precision instead of 0.
}
else { // Number
return value.toFixed(Math.min(precision, 20));
}
};
/**
* Count the number of significant digits of a number.
*

View File

@ -63,6 +63,62 @@ describe('number', function() {
assert.equal(number.digits(120.5e50), 4);
});
it('should format a number using toFixed', function() {
assert.equal(number.toFixed(2.34), '2');
assert.equal(number.toFixed(2.34, 1), '2.3');
assert.equal(number.toFixed(2.34e10, 1), '23400000000.0');
assert.equal(number.toFixed(2.34e-10, 1), '0.0');
assert.equal(number.toFixed(2, 20), '2.00000000000000000000');
assert.equal(number.toFixed(2, 21), '2.00000000000000000000');
assert.equal(number.toFixed(2, 22), '2.00000000000000000000');
assert.equal(number.toFixed(2, 30), '2.00000000000000000000');
});
it('should format a bignumber using toFixed', function() {
var DECIMAL_PLACES = BigNumber.config().DECIMAL_PLACES;
BigNumber.config(100);
assert.equal(number.toFixed(new BigNumber(2.34)), '2');
assert.equal(number.toFixed(new BigNumber(2.34), 1), '2.3');
assert.equal(number.toFixed(new BigNumber(2), 20), '2.00000000000000000000');
assert.equal(number.toFixed(new BigNumber(2), 21), '2.000000000000000000000');
assert.equal(number.toFixed(new BigNumber(2), 22), '2.0000000000000000000000');
assert.equal(number.toFixed(new BigNumber(2), 30), '2.000000000000000000000000000000');
// restore global bignumber configuration
BigNumber.config(DECIMAL_PLACES);
});
it('should format a number using toExponential', function() {
assert.equal(number.toExponential(2.34), '2.34e+0');
assert.equal(number.toExponential(2.34e+3), '2.34e+3');
assert.equal(number.toExponential(2.34e-3), '2.34e-3');
assert.equal(number.toExponential(2.34e+3, 2), '2.3e+3');
assert.equal(number.toExponential(2e+3, 20), '2.0000000000000000000e+3');
assert.equal(number.toExponential(2e+3, 21), '2.00000000000000000000e+3');
assert.equal(number.toExponential(2e+3, 22), '2.00000000000000000000e+3');
assert.equal(number.toExponential(2e+3, 30), '2.00000000000000000000e+3');
});
it('should format a bignumber using toExponential', function() {
var DECIMAL_PLACES = BigNumber.config().DECIMAL_PLACES;
BigNumber.config(100);
assert.equal(number.toExponential(new BigNumber(2.34)), '2.34e+0');
assert.equal(number.toExponential(new BigNumber(2.34e+3)), '2.34e+3');
assert.equal(number.toExponential(new BigNumber(2.34e-3)), '2.34e-3');
assert.equal(number.toExponential(new BigNumber(2.34e+3), 2), '2.3e+3');
assert.equal(number.toExponential(new BigNumber(2e+3), 20), '2.0000000000000000000e+3');
assert.equal(number.toExponential(new BigNumber(2e+3), 21), '2.00000000000000000000e+3');
assert.equal(number.toExponential(new BigNumber(2e+3), 22), '2.000000000000000000000e+3');
assert.equal(number.toExponential(new BigNumber(2e+3), 30), '2.00000000000000000000000000000e+3');
assert.equal(number.toExponential(new BigNumber('2e+300'), 30), '2.00000000000000000000000000000e+300');
assert.equal(number.toExponential(new BigNumber('2e-300'), 30), '2.00000000000000000000000000000e-300');
// restore global bignumber configuration
BigNumber.config(DECIMAL_PLACES);
});
it('should convert a number into a bignumber (when possible)', function() {
assert.deepEqual(number.toBigNumber(2.34), new BigNumber(2.34));
assert.deepEqual(number.toBigNumber(0), new BigNumber(0));
@ -189,6 +245,9 @@ describe('number', function() {
assert.equal(number.format(123e-6, {precision: 8}), '1.23e-4'); // should remove trailing zeros
assert.equal(number.format(3e+6, {precision: 8}), '3e+6'); // should remove trailing zeros
assert.equal(number.format(1234, {precision: 2}), '1200');
// overflow the maximum allowed precision of 20
assert.equal(number.format(2.3, {precision: 30}), '2.3');
});
it('auto notation with custom lower and upper bound', function () {