Fix to_human precision rounding

This commit is contained in:
wltsmrz
2014-11-26 11:32:09 -08:00
parent 0d7fc0a573
commit e371cc2c3c
2 changed files with 28 additions and 16 deletions

View File

@@ -1145,33 +1145,29 @@ Amount.prototype.to_human = function(opts) {
fraction_part = fraction_part.replace(/0*$/, '');
if (fraction_part.length || !opts.skip_empty_fraction) {
// Enforce the maximum number of decimal digits (precision)
if (typeof opts.precision === 'number') {
if (opts.precision <= 0) {
var precision = Math.max(0, opts.precision);
precision = Math.min(precision, fraction_part.length);
var rounded = Number('0.' + fraction_part).toFixed(precision);
// increment the int_part if the first decimal is 5 or higher
if (fraction_part.charCodeAt(0) >= 53) {
int_part = (Number(int_part) + 1).toString();
}
fraction_part = '';
if (rounded < 1) {
fraction_part = rounded.substring(2);
} else {
var precision = Math.min(opts.precision, fraction_part.length);
fraction_part = Math.round(fraction_part / Math.pow(10, fraction_part.length - precision)).toString();
int_part = (Number(int_part) + 1).toString();
fraction_part = '';
}
// because the division above will cut off the leading 0's we have to add them back again
// XXX look for a more elegant alternative
while (fraction_part.length < precision) {
fraction_part = '0' + fraction_part;
}
}
}
// Limit the number of significant digits (max_sig_digits)
if (typeof opts.max_sig_digits === 'number') {
// First, we count the significant digits we have.
// A zero in the integer part does not count.
var int_is_zero = +int_part === 0;
var int_is_zero = Number(int_part) === 0;
var digits = int_is_zero ? 0 : int_part.length;
// Don't count leading zeros in the fractional part if the integer part is
@@ -1197,6 +1193,7 @@ Amount.prototype.to_human = function(opts) {
// Enforce the minimum number of decimal digits (min_precision)
if (typeof opts.min_precision === 'number') {
opts.min_precision = Math.max(0, opts.min_precision);
while (fraction_part.length < opts.min_precision) {
fraction_part += '0';
}

View File

@@ -87,7 +87,7 @@ describe('Amount', function() {
assert.strictEqual(Amount.from_human("0.8 XAU").to_human({precision:0}), '1');
});
it('to human, precision 0, precision 16', function() {
assert.strictEqual(Amount.from_human("0.0 XAU").to_human({precision:16}), '0.0');
assert.strictEqual(Amount.from_human("0.0 XAU").to_human({precision:16}), '0');
});
it('to human, precision 0, precision 8, min_precision 16', function() {
assert.strictEqual(Amount.from_human("0.0 XAU").to_human({precision:8, min_precision:16}), '0.0000000000000000');
@@ -101,6 +101,21 @@ describe('Amount', function() {
it('to human, precision 16, min_precision 6, max_sig_digits 20', function() {
assert.strictEqual(Amount.from_human("0.0 XAU").to_human({precision: 16, min_precision: 6, max_sig_digits: 20}), '0.000000');
});
it('to human rounding edge case, precision 2, 1', function() {
assert.strictEqual(Amount.from_human("0.99 XAU").to_human({precision:1}), '1.0');
});
it('to human rounding edge case, precision 2, 2', function() {
assert.strictEqual(Amount.from_human("0.99 XAU").to_human({precision:2}), '0.99');
});
it('to human rounding edge case, precision 2, 3', function() {
assert.strictEqual(Amount.from_human("0.99 XAU").to_human({precision:3}), '0.99');
});
it('to human rounding edge case, precision 2, 3 min precision 3', function() {
assert.strictEqual(Amount.from_human("0.99 XAU").to_human({precision:3, min_precision:3}), '0.990');
});
it('to human rounding edge case, precision 3, 2', function() {
assert.strictEqual(Amount.from_human("0.999 XAU").to_human({precision:2}), '1.00');
});
});
describe('from_human', function() {
it('1 XRP', function() {