diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 32dd98dd842e..49f38ebbeca5 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -1565,15 +1565,27 @@ function isValidForStep(viewValue, stepBase, step) { // and `viewValue` is expected to be a valid stringified number. var value = Number(viewValue); + var isNonIntegerValue = !isNumberInteger(value); + var isNonIntegerStepBase = !isNumberInteger(stepBase); + var isNonIntegerStep = !isNumberInteger(step); + // Due to limitations in Floating Point Arithmetic (e.g. `0.3 - 0.2 !== 0.1` or // `0.5 % 0.1 !== 0`), we need to convert all numbers to integers. - if (!isNumberInteger(value) || !isNumberInteger(stepBase) || !isNumberInteger(step)) { - var decimalCount = Math.max(countDecimals(value), countDecimals(stepBase), countDecimals(step)); + if (isNonIntegerValue || isNonIntegerStepBase || isNonIntegerStep) { + var valueDecimals = isNonIntegerValue ? countDecimals(value) : 0; + var stepBaseDecimals = isNonIntegerStepBase ? countDecimals(stepBase) : 0; + var stepDecimals = isNonIntegerStep ? countDecimals(step) : 0; + + var decimalCount = Math.max(valueDecimals, stepBaseDecimals, stepDecimals); var multiplier = Math.pow(10, decimalCount); value = value * multiplier; stepBase = stepBase * multiplier; step = step * multiplier; + + if (isNonIntegerValue) value = Math.round(value); + if (isNonIntegerStepBase) stepBase = Math.round(stepBase); + if (isNonIntegerStep) step = Math.round(step); } return (value - stepBase) % step === 0; diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index f810ce6bb78c..47515471122e 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -2787,6 +2787,13 @@ describe('input', function() { helper.changeInputValueTo('3.5'); expect(inputElm).toBeValid(); expect($rootScope.value).toBe(3.5); + + // 1.16 % 0.01 === 0.009999999999999896 + // 1.16 * 100 === 115.99999999999999 + $rootScope.step = 0.01; + helper.changeInputValueTo('1.16'); + expect(inputElm).toBeValid(); + expect($rootScope.value).toBe(1.16); } ); }); @@ -3656,7 +3663,9 @@ describe('input', function() { it('should correctly validate even in cases where the JS floating point arithmetic fails', function() { - var inputElm = helper.compileInput(''); + $rootScope.step = 0.1; + var inputElm = helper.compileInput( + ''); var ngModel = inputElm.controller('ngModel'); expect(inputElm.val()).toBe(''); @@ -3681,6 +3690,13 @@ describe('input', function() { helper.changeInputValueTo('3.5'); expect(inputElm).toBeValid(); expect($rootScope.value).toBe(3.5); + + // 1.16 % 0.01 === 0.009999999999999896 + // 1.16 * 100 === 115.99999999999999 + $rootScope.step = 0.01; + helper.changeInputValueTo('1.16'); + expect(inputElm).toBeValid(); + expect($rootScope.value).toBe(1.16); } ); }