httk.core.precision =================== .. py:module:: httk.core.precision .. autoapi-nested-parse:: How precisely a number was written down. A data file states its numbers to a definite number of digits, and that is a claim about precision: ``0.3333`` says the value is known to about ``1e-4``, while ``0.33`` says only ``1e-2``. Recovering that claim is what lets a matching tolerance — or an spglib ``symprec`` — be *derived from the data* rather than guessed at, which is otherwise a recurring source of arbitrary constants. The value returned is an **absolute** bound, in whatever units the number was written in. It is not a relative precision and not a significant-figure count: ``0.0001`` and ``9999.9999`` both report ``1e-4``. This is deliberately a separate concept from the *arithmetic* precision in :mod:`~httk.core.exactmath`, which governs how far an inexact computation is carried. This module is about what the source said; that one is about what we compute. Functions --------- .. autoapisummary:: httk.core.precision.decimal_precision httk.core.precision.combined_precision Module Contents --------------- .. py:function:: decimal_precision(text: object) -> fractions.Fraction | None The absolute precision implied by how a number was written, or ``None``. ``None`` means the literal makes no precision claim, which is a different thing from claiming perfect precision. It is returned for an empty or missing value, for CIF's ``?`` and ``.`` placeholders, for anything that is not a decimal literal, and — this one matters — for an exact rational such as ``"1/3"``, which states a value rather than a measurement and so should not drag a structure's precision down to the width of its last digit. Examples, all exact: * ``"0.123"`` -> ``1/1000`` — three digits after the point * ``"-0.5"`` -> ``1/10`` — the sign is not part of the claim * ``".25"`` -> ``1/100`` — a leading point is still two digits * ``"5."`` -> ``1`` — a trailing point states no fraction * ``"10"`` -> ``1`` — an integer literal is precise to the unit * ``"1.2e-3"`` -> ``1/10000`` — one digit, then scaled by the exponent * ``"1/3"`` -> ``None`` — exact, not measured * ``"?"`` -> ``None`` — no value at all .. py:function:: combined_precision(values: collections.abc.Iterable[object]) -> fractions.Fraction | None The precision of a set of values taken together: the **coarsest** of them. A structure is only as precisely stated as its least precisely stated number, so one sloppy ``0.5`` among a table of six-decimal coordinates really does mean the table is good to ``1e-1``. Taking the coarsest is the conservative reading and the one that keeps a derived tolerance from being too tight to match anything. Each value may be a literal to be interpreted by :func:`decimal_precision`, or an already-computed precision as a :class:`~fractions.Fraction`, :class:`int`, or :class:`float` — a standard uncertainty read from a file, say. Floats convert through their decimal spelling, so ``0.005`` lands on ``1/200`` rather than a binary approximation of it. Values that state no precision are skipped, and ``None`` is returned when none of them state one.