Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit e5f454c

Browse files
committed
fix(numberFilter): correctly round fractions despite floating-point arithmetics issues in JS
Closes #7870 Closes #7878
1 parent 67c11b9 commit e5f454c

File tree

2 files changed

+11
-2
lines changed

2 files changed

+11
-2
lines changed

src/ng/filter/filters.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
131131
var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
132132
if (match && match[2] == '-' && match[3] > fractionSize + 1) {
133133
numStr = '0';
134+
number = 0;
134135
} else {
135136
formatedText = numStr;
136137
hasExponent = true;
@@ -145,8 +146,11 @@ function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
145146
fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
146147
}
147148

148-
var pow = Math.pow(10, fractionSize + 1);
149-
number = Math.floor(number * pow + 5) / pow;
149+
// safely round numbers in JS without hitting imprecisions of floating-point arithmetics
150+
// inspired by:
151+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
152+
number = +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
153+
150154
var fraction = ('' + number).split(DECIMAL_SEP);
151155
var whole = fraction[0];
152156
fraction = fraction[1] || '';

test/ng/filter/filtersSpec.js

+5
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,18 @@ describe('filters', function() {
145145
expect(number(.99, 2)).toEqual("0.99");
146146
expect(number(.999, 3)).toEqual("0.999");
147147
expect(number(.9999, 3)).toEqual("1.000");
148+
expect(number(1.9, 2)).toEqual("1.90");
149+
expect(number(1.99, 2)).toEqual("1.99");
150+
expect(number(1.999, 3)).toEqual("1.999");
151+
expect(number(1.9999, 3)).toEqual("2.000");
148152
expect(number(1234.567, 0)).toEqual("1,235");
149153
expect(number(1234.567, 1)).toEqual("1,234.6");
150154
expect(number(1234.567, 2)).toEqual("1,234.57");
151155
expect(number(1.255, 0)).toEqual("1");
152156
expect(number(1.255, 1)).toEqual("1.3");
153157
expect(number(1.255, 2)).toEqual("1.26");
154158
expect(number(1.255, 3)).toEqual("1.255");
159+
expect(number(0, 8)).toEqual("0.00000000");
155160
});
156161

157162
it('should filter exponentially large numbers', function() {

0 commit comments

Comments
 (0)