multipleOf logic produces incorrect results
Opened this issue · 1 comments
The logic for multipleOf compares the remainder of a division with the f64 EPSILON constant to decide if a number is a multiple or not. This approach doesn't make sense. EPSILON is simply the difference between 1.0 and the next larger representable number. With regards to the multipleOf calculation this is just an arbitrary constant and comparing remainders to it gives us no guarantees.
EG:
1e-15 is a multiple of 1e-16. But (1e-15 / 1e-16) % 1.0 = 1.7763568394002505e-15
which is greater than epsilon so it is incorrectly said to not be a multiple.
1.3e-16 is not a multiple of 1.3. But (1.3e-16 / 1.3) % 1.0 = 9.999999999999999e-17
which is less than epsilon so it is incorrectly said to be a multiple.
The people over at Monaco have implemented a better way to implement this calculation without introducing incorrect results - https://github.com/microsoft/vscode-json-languageservice/blob/7a478cd29a387cf8813b0a32499e2347102d7a6c/src/parser/jsonParser.ts#L596
At a high level this solution works by multiplying both values by the smallest power of 10 that makes them both whole numbers and does the division on whole numbers to sidestep the issues with floating point math on fractions.