Skip to content

Commit c1cab4d

Browse files
rico227RicoSteinkemsivasubramaniaan
authored
multipleof does not work for floats (#986)
* add function to calculate remainder for floats correctly without rounding errors and fix checking if a number is a multipleOf for floats * fix formatting * add unit test * rm copyright --------- Co-authored-by: Steinke, Rico <[email protected]> Co-authored-by: Muthurajan Sivasubramanian <[email protected]>
1 parent dffbff4 commit c1cab4d

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

src/languageservice/parser/jsonParser07.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { isArrayEqual } from '../utils/arrUtils';
2727
import { Node, Pair } from 'yaml';
2828
import { safeCreateUnicodeRegExp } from '../utils/strings';
2929
import { FilePatternAssociation } from '../services/yamlSchemaService';
30+
import { floatSafeRemainder } from '../utils/math';
3031

3132
const localize = nls.loadMessageBundle();
3233
const MSG_PROPERTY_NOT_ALLOWED = 'Property {0} is not allowed.';
@@ -935,7 +936,7 @@ function validate(
935936
const val = node.value;
936937

937938
if (isNumber(schema.multipleOf)) {
938-
if (val % schema.multipleOf !== 0) {
939+
if (floatSafeRemainder(val, schema.multipleOf) !== 0) {
939940
validationResult.problems.push({
940941
location: { offset: node.offset, length: node.length },
941942
severity: DiagnosticSeverity.Warning,

src/languageservice/utils/math.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export function floatSafeRemainder(val: number, step: number): number {
2+
const valDecCount = (val.toString().split('.')[1] || '').length;
3+
const stepDecCount = (step.toString().split('.')[1] || '').length;
4+
const decCount = Math.max(valDecCount, stepDecCount);
5+
const valInt = parseInt(val.toFixed(decCount).replace('.', ''));
6+
const stepInt = parseInt(step.toFixed(decCount).replace('.', ''));
7+
return (valInt % stepInt) / Math.pow(10, decCount);
8+
}

test/jsonParser.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1541,6 +1541,28 @@ describe('JSON Parser', () => {
15411541
}
15421542
});
15431543

1544+
it('multipleOfFloat', function () {
1545+
const schema: JsonSchema.JSONSchema = {
1546+
type: 'array',
1547+
items: {
1548+
type: 'number',
1549+
multipleOf: 0.05,
1550+
},
1551+
};
1552+
{
1553+
const { textDoc, jsonDoc } = toDocument('[0.9]');
1554+
const semanticErrors = jsonDoc.validate(textDoc, schema);
1555+
1556+
assert.strictEqual(semanticErrors.length, 0);
1557+
}
1558+
{
1559+
const { textDoc, jsonDoc } = toDocument('[42.3222222]');
1560+
const semanticErrors = jsonDoc.validate(textDoc, schema);
1561+
1562+
assert.strictEqual(semanticErrors.length, 1);
1563+
}
1564+
});
1565+
15441566
it('dependencies with array', function () {
15451567
const schema: JsonSchema.JSONSchema = {
15461568
type: 'object',

0 commit comments

Comments
 (0)