4
$\begingroup$

I am running a code on Mathematica (on Mac OS X) that takes high values for some of the variables. In Notebook, I set the global precision using the following code (which is well documented!) at the top of my 'test_script.m' script to get desired precise results:

$PreRead = (# /. 
 s_String /; 
   StringMatchQ[s, NumberString] && 
    Precision@ToExpression@s == MachinePrecision :> s <> "`50." &);

It works fine as long as I am using Notebook. However, when I try to run it using MathematicaScript Kernel using the following command line argument:

./MathematicaScript -script ~/test_script.m

; I am unable to set the precision and the computation gives inaccurate results. Just to make sure, I gave smaller test values to variables and both processes yielded exactly the similar results. This has led me to believe that in MathematicaScript Kernel, the $PreRead command is not effective.

So, Q: How can I set the precision to my desired value in this case; i.e. achieve the same result in terminal as I do in Notebook? Also, why is there a difference when using a Kernel compared to the Notebook.

$\endgroup$
4
$\begingroup$

Per documentation, use $Pre for things that are not entering the world as strings. As is the case for the standalone terminal interface.

$Pre = (# /. 
     n_?NumberQ /; Precision[n] === MachinePrecision :> 
      SetPrecision[Rationalize[Rationalize[n], 0], 50] &);

--- edit ---

After consulting in-office we have something that seems to work better.

Clear[preFunc]
SetAttributes[preFunc, HoldAll]; 
preFunc[n_] := 
 ReleaseHold[
  ReplaceAll[Hold[n], 
   aa_Real /; Precision[aa] === MachinePrecision :> 
    SetPrecision[Rationalize[Rationalize[aa], 0], 50]]]
$Pre = preFunc;

Here is a test.

ee = 3/1.5 + Pi/7
Precision[ee]

(* Out[12]= 2.4487989505128276054946633404685004120281670570536

Out[13]= 50.0879231348 *)

Not perfect, but clearly better.

Possibly this could be done using $PreRead and substring replacement, I'm not sure.

I will say that I think this is an iffy way to go about handling the underlying problem, which is to use high precision on inputs that might be low precision. I would advocate doing that on a per-computation basis when and as needed, using SetPrecision selectively. I have done this sort of thing in the innards of some functions, most notably NSolve.

--- end edit ---

$\endgroup$
  • $\begingroup$ Not the case sadly, both these option have the same effect. That is...none at all. $\endgroup$ – user38671 Mar 17 '16 at 21:39
  • $\begingroup$ (1) Both of what options? (2) If you given an example, the chances of getting an answer that works for you improves considerably. $\endgroup$ – Daniel Lichtblau Mar 17 '16 at 22:19
  • $\begingroup$ Apologies Daniel. Running the script math -batchinput < testScript.m -batchoutput > res.txt with testScript.m being $Pre = (# /. n_?NumberQ /; Precision[n] === MachinePrecision :> SetPrecision[Rationalize[Rationalize[n], 0], 50] &); 3/1.5+Pi/7 Precision[%] results in res.txt 2.4487989505128276 MachinePrecision rather than 2.4487989505128276054946633404685004120281670570536 50.0879 when run through .nb in the GUI. $\endgroup$ – user38671 Mar 17 '16 at 22:36
  • $\begingroup$ Weird. I'll have a look. $\endgroup$ – Daniel Lichtblau Mar 17 '16 at 22:50
  • 1
    $\begingroup$ Okay, I looked, and I may need to retract my response. Clearly this is more difficult than I had realized. The problem is that even with setting HoldXXX attributes, the Set is getting evaluated before the resetting of precision. So this needs more thought and maybe stronger voodoo than I have managed to conjure. Sorry about that. $\endgroup$ – Daniel Lichtblau Mar 18 '16 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.