8
$\begingroup$

Some of my symbolic computations involve many large numbers, e.g.:

37894580188800000000000000000000000000000000000000

As the computation is symbolic, I'd like to leave the numbers in exact form, holding off the numerical conversion until the end.

This, however, makes the presentation of intermediate results unwieldy (especially if the expression contains a lot of large numbers). It would be nice if there were a function that caused an output to display all its over-threshold exact numbers in scientific notation, while keeping them exact internally. For instance in the case of the above, it would be:

3.78945801888 x 10^49

Wolfram's documentation says "The Wolfram Language provides flexible mechanisms for full typeset formatting of numbers of any magnitude and precision", but I've not been able to find a function that does this.

EDIT: Thanks kglr and Carl! Here's how your functions work on one of my test cases (too long to put into the comments):

test = (BesselJ[-(3/4), (307792869430417000000000000000000 Mrest)/
     56948374077008069066071] BesselY[-(1/4), (
     307792869430417000000000000000000 Mrest)/
     56948374077008069066071] + 
   BesselJ[3/4, (307792869430417000000000000000000 Mrest)/
     56948374077008069066071] BesselY[1/4, (
     307792869430417000000000000000000 Mrest)/
     56948374077008069066071]) (Quantity[-((
    2053373 Sqrt[73/18913] Mrest^3 \[Pi]^(3/2))/
    218400036542934750122025461419177208453231459616518446904000000000\
00), 1/("Kilograms")^3])

enter image description here kglr (these approaches give nice compactness, and have the convenience of only needing to be applied once) (the results from the two are identical):

$Post = N
test
$Post=.
(*OR*)
$PrePrint = 
  If[Precision[#] == \[Infinity], N[#], N[#, Precision[#]]] &;
test
$PrePrint =.

enter image description here

Carl (this function is useful if I want to keep track of the individual numbers):

inexactForm[test]

enter image description here

$\endgroup$
2

3 Answers 3

6
$\begingroup$

You can try $Post or $PrePrint:

$Post

num = 37894580188800000000000000000000000000000000000000;

$Post = N; (* apply `N` to every output expression *)

num

3.78945801888`*^49

Precision[num]

Reset

$Post = .

num

37894580188800000000000000000000000000000000000000

$PrePrint

Apply N to every expression before it is printed -- "Show exact quantities by their numerical value:"

$PrePrint = Replace[#, 
  x_?NumericQ :> If[Precision[x] == ∞, N[x], N[x, Precision[x]]], All] &;

num
foo[{num, bar[10`20], 2`2}]

enter image description here

$\endgroup$
9
  • $\begingroup$ I like this (+1) but I think you will want to make the $PrePrint example more general, so that it applies all formats of output; as written the output must be a bare Integer. $\endgroup$
    – Mr.Wizard
    Commented Dec 31, 2019 at 0:47
  • $\begingroup$ @Mr.Wizard, thank you for the upvote. Added another example. $\endgroup$
    – kglr
    Commented Dec 31, 2019 at 2:10
  • $\begingroup$ $Post = N is a simple, elegant solution. It would be nice if it left the Bessel orders as exacts, but I'm basically happy with it. $\endgroup$
    – theorist
    Commented Dec 31, 2019 at 3:16
  • $\begingroup$ Perhaps I wasn't clear. Consider {num, 10`20} and {num, 10`20, 2`2} for example; shouldn't these give something like {3.78946*10^49, 10.000000000000000000, 2.0} instead? $\endgroup$
    – Mr.Wizard
    Commented Dec 31, 2019 at 6:30
  • 1
    $\begingroup$ Yes, I understand that -- that's why I was surprised you were showing a backtick as appearing in an Output cell (designated in yellow in your answer). When I copied the output of your code into the addendum to my question, I don't get a backtick (and I also don't get the same no. of displayed digits). I believe what's going on is that you copied the output of your \$PrePrint code directly into your MSE post (as I did)--but, rather than doing the same for the output of your \$Post code, you first copied its output into an Input cell, and then copied from the Input cell into your post. $\endgroup$
    – theorist
    Commented Dec 31, 2019 at 21:32
4
$\begingroup$

You can create wrapper function to do this:

MakeBoxes[inexactForm[e_], StandardForm] ^:= Internal`InheritedBlock[{Integer},
    Unprotect[Integer];
    MakeBoxes[i_Integer, StandardForm] ^:= With[{n=N@i}, MakeBoxes[n, StandardForm]];
    MakeBoxes[e, StandardForm]
]

Then:

inexactForm[
    a[
        37894580188800000000000000000000000000000000000000,
        37894580188800000000000000000000000000000000000000
    ]
]

a[3.78946*10^49,3.78946*10^49]

$\endgroup$
3
$\begingroup$

You could just modify the display Format of specific functions/patterns:

Unprotect[BesselJ, BesselY];
Format[BesselJ[n_, z_ /; Precision[z] == ∞]] := BesselJ[n, N[z]]
Format[BesselY[n_, z_ /; Precision[z] == ∞]] := BesselY[n, N[z]]
Protect[BesselJ, BesselY];

then we get a more legible display without modifying any variables:

test

(*    (BesselJ[-(3/4), 5.40477*10^9 Mrest] BesselY[-(1/4), 5.40477*10^9 Mrest] + 
       BesselJ[3/4, 5.40477*10^9 Mrest] BesselY[1/4, 5.40477*10^9 Mrest]) (Quantity[...])    *)
$\endgroup$
2
  • 1
    $\begingroup$ Consider MakeBoxes; no need to Unprotect and you can combine definitions: MakeBoxes[(h : BesselJ | BesselY)[n_, z_ /; Precision[z] == ∞], fmt_] := ToBoxes @ h[n, N[z]] $\endgroup$
    – Mr.Wizard
    Commented Jan 1, 2020 at 5:15
  • $\begingroup$ @Mr.Wizard yes that's a possibility. I try to keep my code agnostic about boxes, seeing them as a low-level mechanism that may not age well. $\endgroup$
    – Roman
    Commented Jan 1, 2020 at 9:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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