Coming from Maple I do not understand how the precision for numerical computations in Mathematica is specified. I understand that there are various options to commands such as WorkingPrecision
and PrecisionGoal
. But I would like to use the same precision (above machine precision) for a number of computations including matrix operations and the FindRoot
command outside and inside of routines. Also I would like to specify the precision of the output.
3 Answers
How do I tell mathematica that all numbers e.g. 1.5 are actually 20 Digits precision? SetPrecision on all numbers or add the `20 everywhere?
You could force this with $PreRead
. This naive definition is likely inefficient and probably breaks a number of corner cases I have not considered, but here is a rough demonstration:
$PreRead = (# /.
s_String /;
StringMatchQ[s, NumberString] &&
Precision@ToExpression@s == MachinePrecision :> s <> "`20." &);
3/1.5 + Pi/7
Precision[%]
2.4487989505128276055 20.0879
As Alexey notes this breaks if the machine number string already has a "NumberMark" after it e.g. 1.23`
. One could use a more precise string replacement to avoid this.
A different approach is to process at the expression rather than box level, though this simple first attempt probably fails in some cases as well:
$Pre = Function[Null,
Unevaluated[#] /. r_Real?MachineNumberQ :> RuleCondition@SetPrecision[r, 25],
HoldAllComplete]
Now:
MachineNumberQ[2.2]
ToString[3.14]
False "3.140000000000000124344979"
-
$\begingroup$ Your solution fails when the number entered has the NumberMark after digits, for example
1.5`
. $\endgroup$ Commented Dec 1, 2013 at 19:24 -
$\begingroup$ @Alexey I never thought it would be robust as written. Let me see if I can improve it some. $\endgroup$ Commented Dec 1, 2013 at 20:42
-
1$\begingroup$ Your second solution works in Mathematica 5.2 and 7.0.1 but not in v.8.0.4. Looks like a bug in
$Pre
in v.8.0.4. $\endgroup$ Commented Dec 1, 2013 at 21:07 -
$\begingroup$ @Mr.Wizard: Your first solution also doesn't appear to work with numbers with 18 or more significant figures. For example: if you set the precision in your function equal to say, 50, then evaluate
z = 1.2345678901234567
and thenPrecision[z]
, you get a precision of 50. By contrast, withz = 1.23456789012345678
, you get a precision of 17.0915, which is equal to its native precision. $\endgroup$– theoristCommented Dec 29, 2016 at 23:19 -
$\begingroup$ @theorist This code was designed to work with machine precision numbers only. Numbers entered with additional digits are automatically interpreted as arbitrary precision; I did not wish to override the precision those. If you leave out
&& Precision@ToExpression@s == MachinePrecision
it should force those too. $\endgroup$ Commented Dec 31, 2016 at 18:41
There is a quick-n-dirty solution. Set
$MinPrecision = 100
And then enter numbers something like
x = 1.01`2;
You will be getting warnings as
Precision::precsm: Requested precision 2.` is smaller than $MinPrecision.
Using $MinPrecision instead.
but in this way you if you want to change precision you just change $MinPrecision
value.
In[21]:= x
Out[21]= 1.\
0100000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000
-
$\begingroup$ I don't even get the
Precision::precsm
warning message. However it does not work on machine numbers; the entry form as you rightly noted is critical. +1 for a simple method that may work in a number of applications. $\endgroup$ Commented Feb 10, 2016 at 18:52 -
$\begingroup$ This is 10x easier than the accepted answer. $\endgroup$ Commented May 11, 2021 at 12:45
First time posting, but for any googlers of this issue, the "global" precision of machine precision numbers can be set by:
Unprotect[$MachinePrecision];
$MachinePrecision = 100;
Protect[$MachinePrecision];
-
$\begingroup$ Does this setting affect any evaluations? $\endgroup$ Commented Jun 1, 2017 at 9:27
-
1$\begingroup$ This does not affect
MachinePrecision
(no dollar sign) for example. I cannot imagine that it will do anything to change internals when a number like 3.3 is encountered (Try it:In[20]:= Precision[3.3] Out[20]= MachinePrecision
). On top of which, it could have unpredictable effects which I would not view as a benefit. $\endgroup$ Commented Jun 1, 2017 at 16:04
?$*Precision
. You can do fixed precision calculations withBlock[{$MaxPrecision=..., $MinPrecision=...}, ...]
or set these globally to affect all functions that rely on it $\endgroup$1.0`20
. Also, you should be aware that some matrix decompositions are done in machine precision using LAPACK. $\endgroup$SetPrecision
will take the machine-precision value and extend it with base-2 zeros up to the required precision, which may not be what you want (since zeros in base 2 are not necessarily so in base 10; e.g.SetPrecision[1.9, 20]
gives a result slightly less than 1.9). If you use the annotation, the zeros are taken to be in base 10 instead. Another possible approach is to useRationalize
. $\endgroup$