11---
2- date : 2026-08-05
2+ date : 2026-08-06
33authors :
44 - mpusz
55categories :
66 - Metrology
77comments : true
8- draft : true
98---
109
1110# Measurement uncertainty and measured constants
@@ -20,8 +19,8 @@ happily prints ten significant digits of a solar mass computed from a constant t
2019guarantees four.
2120
2221** mp-units** now models this honestly. This post introduces the ` uncertain<T> ` representation
23- type, the ` relative_standard_uncertainty ` metadata for measured constants, and the
24- ` measurement_of ` helper that connects the two .
22+ type, the ` standard_uncertainty ` and ` relative_standard_uncertainty ` metadata for measured
23+ constants, and the ` measurement_of ` helper that connects them .
2524
2625<!-- more -->
2726
@@ -116,20 +115,42 @@ adjective-wrapper naming pattern as `std::optional<T>` and `std::expected<T>`.
116115
117116## Measured constants carry their uncertainty
118117
119- A measured constant now declares its relative standard uncertainty right in its definition,
120- as an exact symbolic magnitude, using the exact term the CODATA table uses:
118+ A measured constant now declares its standard uncertainty right in its definition, as an
119+ exact symbolic expression, using the exact term the CODATA table uses. This is how NIST
120+ publishes `G` in the machine-readable
121+ [CODATA 2018 table](https://physics.nist.gov/cuu/Constants/ArchiveASCII/allascii_2018.txt),
122+ with a quantity name, a value, a standard uncertainty, and a unit:
123+
124+ ```text
125+ Quantity Value Uncertainty Unit
126+ -----------------------------------------------------------------------------
127+ Newtonian constant of gravitation 6.674 30 e-11 0.000 15 e-11 m^3 kg^-1 s^-2
128+ ```
129+
130+ and this is how that row splits into code:
121131
122132``` cpp
123133inline constexpr struct newtonian_constant_of_gravitation final :
124134 named_constant<"G", mag_ratio<667'430, 100'000> * mag_power<10, -11> * cubic(si::metre) / si::kilogram / square(si::second),
125- relative_standard_uncertainty {mag_ratio<22 , 10> * mag_power<10, -5> }> {}
135+ standard_uncertainty {mag_ratio<15 , 10> * mag_power<10, -15> * cubic(si::metre) / si::kilogram / square(si::second) }> {}
126136newtonian_constant_of_gravitation;
127137```
128138
129- The definition reads like the CODATA entry it transcribes: the value ` 6.674 30 × 10⁻¹¹ ` , and
130- the relative standard uncertainty ` 2.2 × 10⁻⁵ ` . No representation type appears anywhere. The
131- metadata is an annotation only. It never participates in unit equality, conversion factors,
132- or symbolic simplification, so nothing about the existing constant behavior changes.
139+ Every column of the row lands in the definition: the value `6.674 30 × 10⁻¹¹` and the
140+ standard uncertainty `0.000 15 × 10⁻¹¹` digit for digit, both in the constant's own unit
141+ `m³ kg⁻¹ s⁻²`. Transcribing the pair verbatim matters more than it may look. NIST
142+ publishes the value and the uncertainty mutually rounded, each to two significant digits
143+ of the uncertainty, so no derived form reproduces them exactly. Storing the relative
144+ uncertainty instead (an earlier iteration of this design) reconstructed a σ that was off by
145+ 6.1% for the fine-structure constant. σ is the number `uncertain<T>` carries, prints, and
146+ propagates, so it is the wrong number to get wrong.
147+
148+ A second wrapper, `relative_standard_uncertainty`, remains for constants whose source
149+ publishes only the relative form. A measured constant declares exactly one of the two, and
150+ the accessors derive the missing form on demand as an exact ratio of canonical magnitudes.
151+ No representation type appears anywhere. The metadata is an annotation only. It never
152+ participates in unit equality, conversion factors, or symbolic simplification, so nothing
153+ about the existing constant behavior changes.
133154
134155Exact constants simply do not have this parameter. This makes exact-vs-measured a
135156distinction the type system can see, expressed by the new `MeasuredConstant` concept.
@@ -157,8 +178,8 @@ const quantity two_suns = 2.0 * iau::unit_symbols::M_SUN;
157178
158179std::cout << two_suns << "\n"; // 2 M_☉
159180std::cout << two_suns.in(kg) << "\n"; // 3.97682e+30 kg
160- std::cout << two_suns.in<uncertain<double >>(kg) << " \n " ; // 3.97682e+30 ± 8.749e +25 kg
161- std::cout << value_cast<kg, uncertain<double >>(two_suns) << " \n " ; // 3.97682e+30 ± 8.749e +25 kg
181+ std::cout << two_suns.in<uncertain<double>>(kg) << "\n"; // 3.97682e+30 ± 8.93761e +25 kg
182+ std::cout << value_cast<kg, uncertain<double>>(two_suns) << "\n"; // 3.97682e+30 ± 8.93761e +25 kg
162183```
163184
164185The first two lines are exact: ` two_suns ` in its own unit, and the sanctioned central
@@ -175,7 +196,7 @@ const quantity two_suns = uncertain<double>{2.0} * iau::unit_symbols::M_SUN;
175196
176197std::cout << two_suns << "\n"; // 2 ± 0 M_ ☉
177198std::cout << two_suns.in(iau::unit_symbols::M_EARTH) << "\n"; // 665892 ± 0 M_ ⊕
178- std::cout << two_suns.in(kg) << "\n"; // 3.97682e+30 ± 8.749e +25 kg
199+ std::cout << two_suns.in(kg) << "\n"; // 3.97682e+30 ± 8.93761e +25 kg
179200```
180201
181202`two_suns` is exactly two suns even in an uncertainty-capable representation. Both masses
@@ -211,8 +232,8 @@ std::cout << "M_sun = " << solar_mass.in(kg) << "\n";
211232```
212233
213234``` text
214- G = 6.6743e-11 ± 1.46835e -15 m³ kg⁻¹ s⁻²
215- M_sun = 1.98841e+30 ± 4.3745e +25 kg
235+ G = 6.6743e-11 ± 1.5e -15 m³ kg⁻¹ s⁻²
236+ M_sun = 1.98841e+30 ± 4.46881e +25 kg
216237```
217238
218239The solar mass example is the payoff. The IAU defines the nominal solar mass parameter
@@ -249,23 +270,29 @@ both units is fully correlated with itself, and it cancels symbolically before t
249270is ever applied, which is exactly why the solar-to-Earth-mass conversion reports zero rather
250271than a small non-zero number.
251272
252- ** Coverage.** ` iau::G ` and every measured constant in the three HEP CODATA namespaces carry
253- the uncertainty published by their own release. Constants that are exact by definition carry
254- nothing at all, which is what makes the distinction visible to the type system in the first
255- place.
273+ ** Coverage.** Every measured constant in the three HEP CODATA namespaces carries the
274+ uncertainty published by its own release. The new
275+ [ ` codata ` ] ( ../../users_guide/systems/codata.md ) system goes further: its headers are
276+ generated from the NIST tables and cover every constant of the 2014, 2018, and 2022
277+ adjustments (roughly 230 per adjustment), each transcribing the published value and
278+ standard uncertainty digit for digit, with an independent verification step recomputing
279+ every emitted value against its source row. ` iau::G ` now imports the CODATA constant
280+ rather than duplicating it. Constants that are exact by definition carry nothing at all,
281+ which is what makes the distinction visible to the type system in the first place.
256282
257283## Printing what the standard prints
258284
259285The default text output is the ` value ± σ ` form, the notation engineers read every day:
260286
261287``` cpp
262- std::cout << G.in(m3 / kg / s2) << " \n " ; // 6.6743e-11 ± 1.46835e -15 m³ kg⁻¹ s⁻²
288+ std::cout << G.in(m3 / kg / s2) << " \n " ; // 6.6743e-11 ± 1.5e -15 m³ kg⁻¹ s⁻²
263289```
264290
265291ISO 80000-1:2022, 7.2.4 specifies a different one. The value is quoted to the last
266292significant digit of the uncertainty, and the uncertainty follows in parentheses, counted
267- in units of that digit. Appending ` ~ ` to the format spec selects it. The tilde marks the
268- output as an approximation, because unlike the default form this one rounds the value:
293+ in units of that digit. Appending ` ~ ` to the format spec selects it. Where the default form
294+ prints what the object holds, this one quotes the value to the precision the uncertainty
295+ justifies, which is how measurement results are reported:
269296
270297``` cpp
271298std::println ("{::N[ ~ ] }", G.in(m3 / kg / s2)); // 6.67430(15)e-11 m³ kg⁻¹ s⁻²
@@ -303,6 +330,9 @@ documentation:
303330 it: the mass of the planet from a pendulum, a radius, and `G`
304331- [Faster-than-lightspeed constants](../../users_guide/framework_basics/faster_than_lightspeed_constants.md)
305332 explains why constants are units in the first place
333+ - [The CODATA system](../../users_guide/systems/codata.md) documents the generated
334+ constants: one namespace and one header per adjustment, and the essential and complete
335+ tiers
306336- [CODATA fundamental physical constants](https://physics.nist.gov/cuu/Constants/) are the
307337 source of the values and uncertainties transcribed into the systems
308338- [JCGM 100 (GUM)](https://www.bipm.org/en/committees/jc/jcgm/publications) is the
0 commit comments