Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 37 additions & 25 deletions mathics/builtin/atomic/numbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,20 +148,20 @@ def convert_float(x, base, exponents):

class Accuracy(Builtin):
"""
<url>:Accuracy: https://en.wikipedia.org/wiki/Accuracy_and_precision</url> (WMA <url>:Accuracy: https://reference.wolfram.com/language/ref/Accuracy.html</url>)

<dl>
<dt>'Accuracy[$x$]'
<dd>examines the number of significant digits of $expr$ after the decimal point in the number x.
</dl>
This is rather a proof-of-concept than a full implementation.

<i>This is rather a proof-of-concept than a full implementation.</i>

Accuracy of a real number is estimated from its value and its precision:

>> Accuracy[3.1416`2]
= 1.50298

Notice that the value is not exactly equal to the obtained in WMA: This is due to the different way in which
Precision is handled in SymPy.
Notice that the value is not exactly equal to the obtained in WMA: This is due to the different way in which 'Precision' is handled in SymPy.

Accuracy for exact atoms is $Infinity$:
>> Accuracy[1]
Expand All @@ -176,9 +176,20 @@ class Accuracy(Builtin):
Accuracy of expressions is given by the minimum accuracy of its elements:
>> Accuracy[F[1, Pi, A]]
= Infinity

>> Accuracy[F[1.3, Pi, A]]
= 14.8861

'Accuracy' for the value 0 is a fixed-precision Real number:
>> 0``2
= 0.00

In compound expressions, the 'Accuracy' is fixed by the number with
the lowest 'Accuracy':
>> Accuracy[{{1, 1.`},{1.``5, 1.``10}}]
= 5.

See also <url>:'Precision': /doc/reference-of-built-in-symbols/atomic-elements-of-expressions/representation-of-numbers/precision/</url>.
"""

summary_text = "find the accuracy of a number"
Expand Down Expand Up @@ -954,40 +965,41 @@ def apply(self, expr, evaluation):

class Precision(Builtin):
"""
<url>:Precision: https://en.wikipedia.org/wiki/Accuracy_and_precision</url> (WMA <url>:Precision: https://reference.wolfram.com/language/ref/Precision.html</url>)

<dl>
<dt>'Precision[$expr$]'
<dd>examines the number of significant digits of $expr$.
</dl>
This is rather a proof-of-concept than a full implementation.
Precision of compound expression is not supported yet.

<i>This is rather a proof-of-concept than a full implementation.</i>

The precision of an exact number, e.g. an Integer, is 'Infinity':

>> Precision[1]
= Infinity

A fraction is an exact number too, so its Precision is 'Infinity':

>> Precision[1/2]
= Infinity
>> Precision[0.5]
= MachinePrecision

#> Precision[0.0]
= MachinePrecision
#> Precision[0.000000000000000000000000000000000000]
= 0.
#> Precision[-0.0]
= MachinePrecision
#> Precision[-0.000000000000000000000000000000000000]
= 0.
Numbers entered in the form $digits$`$p$ are taken to have precision $p$:

#> 1.0000000000000000 // Precision
= MachinePrecision
#> 1.00000000000000000 // Precision
= 17.
>> Precision[1.23`10]
= 10.

#> 0.4 + 2.4 I // Precision
Precision of a machine‐precision number is 'MachinePrecision':
>> Precision[0.5]
= MachinePrecision
#> Precision[2 + 3 I]
= Infinity

#> Precision["abc"]
= Infinity
In compound expressions, the 'Precision' is fixed by the number with
the lowest 'Precision':
>> Precision[{{1, 1.`},{1.`5, 1.`10}}]
= 5.


See also <url>:'Accuracy': /doc/reference-of-built-in-symbols/atomic-elements-of-expressions/representation-of-numbers/accuracy/</url>.
"""

rules = {
Expand Down
42 changes: 19 additions & 23 deletions mathics/doc/documentation/1-Manual.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -196,50 +196,46 @@ The result of the previous query to \Mathics can be accessed by '%':

<section title="Precision and Accuracy">

\Mathics handles relative ('Precision') and absolute ('Accuracy') uncertanties in numerical quantities. 'Precision' is set by adding a single reversed quote $`$
and the numerical value of the precision right after the last digit of the mantissa. For example,
\Mathics handles relative and absolute uncertanties in numerical quantities. The <em>precision</em> or relative accuracy, is set by adding a RawBackquote character ('`') and the number of digits of precision in the mantissa. For example:

>> a = 3.1416`3
>> 3.1416`3
= 3.14

set $a$ with a number having a relative uncertainty of $10^{-3}$, in a way that this number is numerically equivalent to $3.1413`4$:
Above, two decimal places are shown in output after the decimal point, but three places of precision are stored.

>> a == 3.1413`4
The relative uncertainty of '3.1416`3' is 10^-3. It is numerically equivalent, in three places after the decimal point, to 3.1413`4:

>> 3.1416`3 == 3.1413`4
= True

We can recover the precision of the number by using 'Precision'
We can get the precision of the number by using the \Mathics <url>:'Precision': /doc/reference-of-built-in-symbols/atomic-elements-of-expressions/representation-of-numbers/precision/</url> function:

>> Precision[a]
= 3.
>> Precision[3.1413`4]
= 4.

Up to the precision, $a$ is equivalent to $\pi$, so
While 3.1419 not the closest approximation to Pi in 4 digits after the decimal point (or with precision 4), for 3 digits of precision it is:

>> Pi - a
= 0.
>> Pi == a
>> Pi == 3.141987654321`3
= True

In a similar way, 'Accuracy' is set by adding a double reversed quote $``$
and the numerical value of the accuracy right after the last digit of the mantissa. For example,
<url>The absolute accuracy of a number, is set by adding a two RawBackquotes '``' and the number digits.

For example:

>> a = 13.1416``4
>> 13.1416``4
= 13.142

set $a$ with a number having a absolute uncertainty of $10^{-4}$, in a way that this number is numerically equivalent to $13.1413``4$:
is a number having a absolute uncertainty of 10^-4. This number is numerically equivalent to '13.1413``4':

>> a == 13.1413``4
>> 13.1416``4 == 13.1413``4
= True

For $0$, 'Precision' is ignored, since corresponds to a zero uncertainty:

>> 0`4
= 0

while 'Accuracy' is taken into account by storing the value as a fixed precision Real number:
The absolute accuracy for the value 0 is a fixed-precision Real number:

>> 0``4
= 0.0000

See also <url>:Accuracy and precision: https://en.wikipedia.org/wiki/Accuracy_and_precision</url>.
</section>


Expand Down
42 changes: 42 additions & 0 deletions test/builtin/atomic/test_numbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,45 @@ def test_n():
("N[1.01234567890123456789`, 2] // Precision", "MachinePrecision"),
):
check_evaluation(str_expr, str_expected)


def test_accuracy():
for str_expr, str_expected in (
("0`4", "0"),
("Accuracy[0.0]", "15."),
("Accuracy[0.000000000000000000000000000000000000]", "36."),
("Accuracy[-0.0]", "15."),
# In WMA, this gives 36. Seems to be a rounding issue
# ("Accuracy[-0.000000000000000000000000000000000000]", "36."),
("1.0000000000000000 // Accuracy", "15."),
("1.00000000000000000 // Accuracy", "17."),
# Returns the accuracy of ```2.4```
(" 0.4 + 2.4 I // Accuracy", "14.6198"),
("Accuracy[2 + 3 I]", "Infinity"),
('Accuracy["abc"]', "Infinity"),
# Returns the accuracy of ``` 3.2`3 ```
('Accuracy[F["a", 2, 3.2`3]]', "2.49482"),
('Accuracy[{{a, 2, 3.2`},{2.1`5, 3.2`3, "a"}}]', "2.49482"),
# Another case of issues with rounding. In Mathics, this returns
# 2.67776
# ('Accuracy[{{a, 2, 3.2`},{2.1``3, 3.2``5, "a"}}]', '3.'),
):
check_evaluation(str_expr, str_expected)


def test_precision():
for str_expr, str_expected in (
("0`4", "0"),
("Precision[0.0]", "MachinePrecision"),
("Precision[0.000000000000000000000000000000000000]", "0."),
("Precision[-0.0]", "MachinePrecision"),
("Precision[-0.000000000000000000000000000000000000]", "0."),
("1.0000000000000000 // Precision", "MachinePrecision"),
("1.00000000000000000 // Precision", "17."),
(" 0.4 + 2.4 I // Precision", "MachinePrecision"),
("Precision[2 + 3 I]", "Infinity"),
('Precision["abc"]', "Infinity"),
('Precision[F["a", 2, 3.2`3]]', "3."),
('Precision[{{a,2,3.2`},{2.1`5, 2.`3, "a"}}]', "3."),
):
check_evaluation(str_expr, str_expected)