js-quantities icon indicating copy to clipboard operation
js-quantities copied to clipboard

Lacking precision necessary for required comparisons

Open kyrofa opened this issue 3 years ago • 10 comments

This test passes

it("should compare properly", function() {
  var galQty = Qty("1 gal");
  var qtQty = Qty("4 qt");
  expect(galQty.eq(qtQty)).toBeTrue();
});

However, for more complex units it fails:

it("should compare properly", function() {
  var galQty = Qty("1 gal/acre");
  var qtQty = Qty("4 qt/acre");
  expect(galQty.eq(qtQty)).toBeTrue();
});

This is due to a lack of precision. If you take a look at baseScalar in the latter test, you'll see that they're VERY close down to twenty decimal places or so, but then differ. These types of problems are generally solved by using a library like big.js, but that does mean taking on a dependency. How do you feel about that? A less-great option would be to check how close the values are in compareTo and claim that they're equal if they're "close enough" (this is how I'm working around this issue locally for now). Is there another more preferred way to solve this problem? Happy to do the legwork, just need to know what will be approved.

kyrofa avatar Feb 03 '22 19:02 kyrofa

Look at src/quantities/definitions.js. Their definitions aren't exact. They are defined in terms of cubic meter, and doing the math, quart is not 1/4 gallon.

I'm not sure which one is less precise, or how to make them precise, but going by the current definitions, they really are not equal.

rage-shadowman avatar Mar 18 '22 19:03 rage-shadowman

They should be equal though, agreed?

kyrofa avatar Mar 18 '22 19:03 kyrofa

Yeah, the definition of a US gallon is 4 quarts. I'm just not sure how best to correct it, or what the true quantity would be in terms of cubic meters.

rage-shadowman avatar Mar 18 '22 19:03 rage-shadowman

Yeah I think ideally these would be ratios (rationals), and then we'd use something like big.js to retain precision. I don't know where to find such magical ratios, though, if these are lacking precision.

kyrofa avatar Mar 18 '22 20:03 kyrofa

Self correction:

I was wrong with the above. The definition of quart in the file is exactly 1/4 gallon. Double imprecision seems to be the real issue here. If we can't do something to make the numbers exact (not sure if defining based on whole number numerator/denominator rather than floating point numbers would help, and if so, how much work that would take), then maybe adding an optional precision argument to the equality comparison? (kinda like what you suggested as a compromise solution but keeps exactness checks intact if the argument is not supplied and allows user to determine how close is close enough)

rage-shadowman avatar Mar 18 '22 20:03 rage-shadowman

Well, the fact that the first test passed indicates that we may have enough precision. But we start losing it when we start dividing down the units. If we converted these to rationals (even just starting with the decimal values, but turn them into reduced num/den combos), then used big.js from there, that could very well be enough. I didn't want to start down that path without buy-in, though, given how much pride the README takes in having no deps.

kyrofa avatar Mar 18 '22 20:03 kyrofa

not sure if defining based on whole number numerator/denominator rather than floating point numbers would help

Not on its own, we'll still lose precision as we operate on them. We need to KEEP them as rationals as we operate, which is where big.js comes in.

kyrofa avatar Mar 18 '22 20:03 kyrofa

If that works, then IMO true precision would be great! But will that really work? Is everything truly definable using rational numbers like that? Or will we still end up needing some sort of precision argument in the equality checks? (I do see Math.PI used in some of the definitions)

rage-shadowman avatar Mar 18 '22 20:03 rage-shadowman

I didn't want to start down that path without buy-in, though, given how much pride the README takes in having no deps.

As far as "no deps" goes, I don't know what @gentooboontoo would say, but I don't think you'll have any arguments against adding a precision argument to the equality checks.

rage-shadowman avatar Mar 18 '22 20:03 rage-shadowman

If that works, then IMO true precision would be great! But will that really work? Is everything truly definable using rational numbers like that?

Probably not all of them, but if we use ruby units for inspiration it seems like most of them.

kyrofa avatar Mar 18 '22 20:03 kyrofa