diff --git a/CHANGES.rst b/CHANGES.rst index 1c6391d6..5a8463b6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,21 +7,33 @@ Unreleased 4.x Changes: - Includes the `main` branch in continuous integration automation. +- [**BREAKING**] Previously when tallying the uncertainty for a `UFloat` object, the + contribution from other `UFloat` objects with `std_dev == 0` were excluded. Now this + special casing for `std_dev == 0` has been removed so that the contribution from all + contributing `UFloat` objects is included. This changes the behavior in certain + corner cases where `UFloat` `f` is derived from `UFloat` `x`, `x` has `x.s == 0`, but + the derivative of `f` with respect to `x` is `NaN`. For example, previously + `(-1)**ufloat(1, 0)` gave `-1.0+/-0`. The justification for this was that the second + `UFloat` with `std_dev` of `0` should be treated like a regular float. Now the same + calculation returns `-1.0+/-nan`. In this case the `UFloat` in the second argument + of the power operator is treated as a degenerate `UFloat`. Removes: -- [*BREAKING*] Removes certain deprecated `umath` functions and +- [**BREAKING**] Removes certain deprecated `umath` functions and `AffineScalarFunc`/`UFloat` methods. The following `umath` functions are removed: `ceil`, `copysign`, `fabs`, `factorial`, `floor`, `fmod`, `frexp`, `ldexp`, `modf`, `trunc`. The following `AffineScalarFunc`/`UFloat` methods are removed: `__floordiv__`, `__mod__`, `__abs__`, `__trunc__`, `__lt__`, `__le__`, `__gt__`, `__ge__`, `__bool__`. -- [*BREAKING*] Previously it was possible for a `UFloat` object to compare equal to a +- [**BREAKING**] Previously it was possible for a `UFloat` object to compare equal to a `float` object if the `UFloat` `standard_deviation` was zero and the `UFloat` `nominal_value` was equal to the `float`. Now, when an equality comparison is made between a `UFloat` object and another object, if the object is not a `UFloat` then the equality comparison is deferred to this other object. For the specific case of `float` this means that the equality comparison always returns `False`. +- [**BREAKING**] The `uncertainties` package is generally dropping formal support for + edge cases involving `UFloat` objects with `std_dev == 0`. Unreleased ---------- diff --git a/doc/tech_guide.rst b/doc/tech_guide.rst index 5a028cac..0ff7a653 100644 --- a/doc/tech_guide.rst +++ b/doc/tech_guide.rst @@ -197,16 +197,6 @@ This indicates that **the derivative required by linear error propagation theory is not defined** (a Monte-Carlo calculation of the resulting random variable is more adapted to this specific case). -However, even in this case where the derivative at the nominal value -is infinite, the :mod:`uncertainties` package **correctly handles -perfectly precise numbers**: - ->>> umath.sqrt(ufloat(0, 0)) -0.0+/-0 - -is thus the correct result, despite the fact that the derivative of -the square root is not defined in zero. - .. _math_def_num_uncert: Mathematical definition of numbers with uncertainties diff --git a/tests/test_power.py b/tests/test_power.py index 6bfb44f6..90790f55 100644 --- a/tests/test_power.py +++ b/tests/test_power.py @@ -88,17 +88,10 @@ def test_power_derivatives(first_ufloat, second_ufloat, first_der, second_der): power_zero_std_dev_result_cases = [ (0, p, 0), - (zero, p, 0), - (float("nan"), zero, 1), - (one, float("nan"), 1), (p, 0, 1), (zero, 0, 1), (-p, 0, 1), - (-10.3, zero, 1), - (0, zero, 1), (0.3, zero, 1), - (-p, zero, 1), - (zero, zero, 1), (p, zero, 1), (one, -3, 1), (one, -3.1, 1), diff --git a/uncertainties/core.py b/uncertainties/core.py index 85db46f9..9436057d 100644 --- a/uncertainties/core.py +++ b/uncertainties/core.py @@ -469,26 +469,10 @@ def error_components(self): object take scalar values (and are not a tuple, like what math.frexp() returns, for instance). """ - - # Calculation of the variance: - error_components = {} - - for variable, derivative in self.derivatives.items(): - # print "TYPE", type(variable), type(derivative) - - # Individual standard error due to variable: - - # 0 is returned even for a NaN derivative (in this case no - # multiplication by the derivative is performed): an exact - # variable obviously leads to no uncertainty in the - # functions that depend on it. - if variable._std_dev == 0: - # !!! Shouldn't the errors always be floats, as a - # convention of this module? - error_components[variable] = 0 - else: - error_components[variable] = abs(derivative * variable._std_dev) - + error_components = { + variable: abs(derivative * variable._std_dev) + for variable, derivative in self.derivatives.items() + } return error_components @property