Mathematica Asked on March 12, 2021
Consider the function
f[a_] := NIntegrate[Sqrt[a + Log[x]], {x, 1, 10}, WorkingPrecision -> 30]
.
With this definition, I cannot call f[0.1]
(for example) without Mathematica throwing an error, since "0.1" is interpreted automatically as a machine number with MachinePrecision
(about 16), whereas the integration requires 30 digits of precision.
But when I enter 0.1
, of course I really mean 1/10
. One solution is to enter f[1/10]
, but this is very inconvenient to do every time, especially because my real functions involve many parameters with long strings of decimal numbers. What’s the best way around this issue? Ideally, I’d like Mathematica to interpret 0.1
as 1/10
automatically, as mentioned in the title.
EDIT
To clarify, I would like any decimal number input be treated as the exact mathematical number with the same name. For example, 0.###
should become ###/1000
. As pointed out in the comments, Rationalize
converts 0.33333333
to 1/3
, which I would consider a problem for my case. I would like Mathematica to treat decimal number input as exact numbers without rounding to any finite precision, nor assuming that I intended a "close" but different rational number.
Another option would be to change the function definition:
f[a_] := NIntegrate[Sqrt[Rationalize[a] + Log[x]], {x, 1, 10}, WorkingPrecision -> 30]
or
f[a_] := NIntegrate[Sqrt[SetPrecision[a, [Infinity]] + Log[x]], {x, 1, 10}, WorkingPrecision -> 30]
But this too would be quite inconvenient to do for every function I use. I also worry about the fact that SetPrecision[0.1, [Infinity]]
does not give 1/10
. So all this makes me wonder what the "right" method is.
Clear["Global`*"]
Since f
makes use of a numeric technique, the argument a
should be restricted to being numeric. Set the precision of a
to at least the WorkingPrecision
used in NIntegrate
.
f[a_?NumericQ, wp : _Integer : 30] := Module[{ap = SetPrecision[a,
Max[wp, Precision[a]]]},
NIntegrate[Sqrt[ap + Log[x]], {x, 1, 10}, WorkingPrecision -> wp]]
f[1/10]
(* 11.3397714471112499234083518037 *)
f[0.1]
(* 11.3397714471112499447483664367 *)
f[0.1, 20]
(* 11.339771447111249944 *)
Answered by Bob Hanlon on March 12, 2021
Exact conversion to the underlying IEEE-754 machine-precision number can be done with SetPrecision[x,∞]
:
x = 1/3 // N
(* 0.333333 *)
SetPrecision[x, ∞]
(* 6004799503160661/18014398509481984 *)
So you see that $1/3$ is represented internally as $6,004,799,503,160,661times2^{-54}$.
Answered by Roman on March 12, 2021
Here's a $PreRead
approach:
$PreRead = # /.
s_String /; StringMatchQ[s, NumberString] :>
With[{pos = StringPosition[s, "."]},
RowBox[{StringDrop[s, First[pos]], "/",
10^(StringLength[s] - pos[[1, 1]])}]
/; Length[pos] === 1] &;
(* new Input cell *)
0.231 + 27 Exp[10.856 x]
(* 231/1000 + 27 E^(1357 x/125) *)
(* new Input cell *)
$PreRead =. (* reset *)
%% // N
(* 0.231 + 27. 2.71828^(10.856 x) *)
Gratuitous remark: I never use $PreRead
(anymore). I think the way it can mess with the input is a potential headache and, in this case, I'd rather put up with the inconvenience of typing 10856/1000
.
Answered by Michael E2 on March 12, 2021
This will do what you're after:
rd = With[{t = RealDigits[#][[1]]},,FromDigits[t]/10^Length@t] &;
E.g.:
rd[0.12345675785894491727276262524416723451]
12345675785894491727276262524416723451/100000000000000000000000000000000000000
Compare:
Rationalize[0.12345675785894491727276262524416723451, 0]
2986272931814910240/24188817069267814669
Specifying precision as part of the input can address this:
Rationalize[0.12345675785894491727276262524416723451`100, 0]
12345675785894491727276262524416723451/100000000000000000000000000000000000000
I suppose a simple wrapper could be used to automate the conversion when calling your functions.
Answered by ciao on March 12, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP