fix(currency): Handle not-quite-zero values

IEEE 754 floating point sometimes results in values that are very small,
rather than zero. One example is 1.0 + 1.07 - 2.07, which returns
4.440892098500626e-16 instead of 0.

This change tweaks the number formatting logic so that an exponential
value with a negative exponent that is larger than the precision+1
returns 0 instead. For example: with precision 2, anything with an
exponent of -4, -5 or more would become 0. 9e-3 = 0.009 = 0.01, but 9e-4
= 0.0009 = 0.001 = 0.00. This detail is unlikely to matter since this
quirk is usually only triggered with values very close to zero.

Closes #1469
This commit is contained in:
Braden Shepherdson 2012-10-19 14:29:37 -04:00 committed by Misko Hevery
parent f4517b500c
commit bca1604c12
2 changed files with 18 additions and 2 deletions

View file

@ -117,9 +117,18 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
formatedText = '',
parts = [];
var hasExponent = false;
if (numStr.indexOf('e') !== -1) {
formatedText = numStr;
} else {
var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
if (match && match[2] == '-' && match[3] > fractionSize + 1) {
numStr = '0';
} else {
formatedText = numStr;
hasExponent = true;
}
}
if (!hasExponent) {
var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
// determine fractionSize if it is not specified

View file

@ -91,6 +91,13 @@ describe('filters', function() {
expect(currency()).toBe('');
expect(currency('abc')).toBe('');
});
it('should handle zero and nearly-zero values properly', function() {
// This expression is known to yield 4.440892098500626e-16 instead of 0.0.
expect(currency(1.07 + 1 - 2.07)).toBe('$0.00');
expect(currency(0.008)).toBe('$0.01');
expect(currency(0.003)).toBe('$0.00');
});
});