nholthaus / units

a compile-time, header-only, dimensional analysis and unit conversion library built on c++14 with no dependencies.
http://nholthaus.github.io/units/
MIT License
962 stars 138 forks source link

Slug definition appears to be off by a few parts per billion #289

Open chiphogg opened 2 years ago

chiphogg commented 2 years ago

Please include the following information in your issue:

  1. Which version of units you are using: 2.3.1, although this problem exists on all versions, including 3.x.

  2. Which compiler exhibited the problem (including compiler version): All of them: it's a wrong definition in the code.


A slug is defined as the mass accelerated by 1 ft/s^2 by a net force of one lbf. This works out to some exact number of kilograms, which we can find using the following other exact definitions:

When I simplify this, I get that a slug is exactly (8896443230521 / 609600000000) kg, which works out to 14.5939029372063648293963... (etc.).

However, the units library slug is defined as exactly 14.5939029 kg. This amounts to an error of a few parts per billion. The error propagates to related units, e.g., foot-pounds of torque.

I think you could fix this: the numerator and denominator both fit into a std::intmax_t for std::ratio. However, since you're using std::ratio to represent unit magnitudes, instead of a vector space representation, you'll probably be more vulnerable to overflow when defining related units.

chiphogg commented 2 years ago

slug_to_kg

Here's me showing the steps to make it easy for others to reproduce. I'm using only integers, and I believe they all trace back to exact definitions. The end result matches the definition in the library exactly before truncation, which adds to my confidence that I performed the computation correctly. The red-underlined digits are the ones omitted by the library.

nholthaus commented 2 years ago

Mr. Hogg,

Thank you for the issue. I think you're right and your analysis is correct.

The aim of units as opposed to other C++ dimensional analysis libraries is to be the most easy-to-use syntactically (including dreaded implicit conversions), and to be absolutely precise with unit definitions unless it's absolutely unusable due to overflow, etc. In this case, units does not meet that standard, so I'll put in the fix.