I got stuck in a problem with pgfmath module.
When trying to calculate the following functions values the result that gets printed out is always zero. I guess the problem is an underflow of pgfmaths co-domain, and the mathematical engine cuts off the small values.
This is an minimal example of what i was trying to explain in the introduction:
\documentclass[tikz]{standalone}
\usepackage[fleqn]{amsmath}
% physical constants:
\pgfmathdeclarefunction{m0}{0}{%
\pgfmathparse{4*pi*1e-7}%
}
\pgfmathdeclarefunction{K}{0}{%
\pgfmathparse{m0*pi/4}%
}
\pgfmathdeclarefunction{c1}{0}{% c1 = K/1.45
\pgfmathparse{K/1.45}%
}
\pgfmathdeclarefunction{c2}{1}{% c2(gamma) = c1/gamma^2
\pgfmathparse{c1/(#1)^2}%
}
\pgfmathdeclarefunction{c3}{2}{% c3(gamma,lambda)
\pgfmathparse{K/((#1)*((#2)+0.45))}%
}
\pgfmathdeclarefunction{DL_rel}{2}{% DL_rel(lambda, gamma)
\pgfmathparse{(2*sqrt((580*#1+261)*#2^3)+40*#1+18)/(29*#2^3-20*#1-9)}%
}
% the problematic pgfmath-function
\pgfmathdeclarefunction{N1}{5}{% N1(soluition, Lmin, gamma, lambda, d1)
\pgfmathsetmacro\numa{(DL_rel(#4,#3)*#2)/2+#2}%
\pgfmathsetmacro\numb{sqrt(\numa^2-c1*c3(#3,#4))/(4*c2(#3)^2)}%
\pgfmathsetmacro\denom{2*c1*#5}%
\pgfmathparse{(#1 -1) ?%
(sqrt((\numa + \numb)/\denom))%
:%
(sqrt((\numa - \numb)/\denom))%
}%
}
\begin{document}
This is the equation im trying to solve:
\begin{equation} \label{eq:N1}
N_{1_{1,2}} =\sqrt{
\frac{\frac{\Delta L}{2} +L_{min} \pm \sqrt{\left(\frac{\Delta L}{2} + L_{min}\right)^2 - \frac{c_1 c_3}{4\cdot c_2^2}\cdot \Delta L^2}}
{2\cdot c_1 d_1}
}
\end{equation}
This should print out its solution:
\begin{equation*}
N_{1_{1,2}} =
\left\{ \begin{array}{l}
\pgfmathparse{N1(1, 4e-4, 1.2, 0.466, 0.115)}\pgfmathresult\\
\pgfmathparse{N1(2, 4e-4, 1.2, 0.466, 0.115)}\pgfmathresult
\end{array}\right.
\end{equation*}
\end{document}
It took me already way to long to get so far and it would be very frustrating for me to stop here, and get all the math done in a different application.
Maybe someone out there has a solution to my problem.
Anyway i want use this post to say thank you! this has been a wonderful place to learn Latex so far, good job everybody!
Best Answer
update to re-insist on numerical instability
Here is from the log output, using
gamma=1.2
,lambda=0.466
andLmin=4e-6
, which were the values from the original OP. Similar, but differing result are observed withgamma=1.2
,lambda=0.44
.Note: I have set constant
K
to value1
to skip the computations withPi
. This modifies the result here as the rounding float operations are not exactly the same.Source code to generate the above.
I have also tested with Maple. Again setting
K
to1
.The results are of the same type but with both coincidences and differences.
update to comment an intriguing numerical curiosity/instability
First version of OP asked for
N1(1, 4e-6, 1.2, 0.466, 0.115)
, which is treated below. Turns out apparently that the\numb
in that case is zero. But depending on the float precision it may be found or not to be zero. The\numa
being only about1e-5
the precision of final result may be drastically reduced by small but non zero\numb
.I compared
xint
withmaple
and obtained similar results (differ only in last digit) for16
,20
,24
digits of precision (takes time to use maple, more testing on the way). ForPi
, I did my tests inxint
starting with94
decimals and multiplying first by1.0
to reduce to stated\xintDigits
. Thus I ran the code below withOn the Maple side,
Pi
is treated as a symbol until the finalevalf
.Here is how the results look like on the
xint
side with higher and higher float precision:(this is for the solution with
\numa+\numb
). Notice how the result with16
digits is much better than the one with20
digits!!!!!!! and it is even quite better than the one for24
digits! (but not as good as28
digits). This is due to the fact that at16
digits, both xint and maple find\numb
to be zero, but about3e-15
at20
digits which induces a big error in the sum, as\numa
is about1e-5
.With
92
digits of precision one finds\numb
about3e-51
numerically. It the exact value is zero, this means that it spoils the digits of the result after about46
of them...With
92
digits of precision, Maple finds\numb
to beAnd
xint
obtains3.1622776601683793319988935444327185337195551393252168268575048527925944386392382213442481084e-51
you can see it matches up to the end.;-)
As the returned values decrease with increasing precision perhaps I can trust the exact one is zero (I have not done the algebra). If the exact value is really zero, adding or subtracting the above to something which is
0.000010117182975...
will corrupt it after about 46 significant digits, destroying the 92 digits float evaluations to get it...Very surprising ! (but do read quoted block above)
This should be taken into account when comparing with any other math engine: the formula is numerically instable due to possible catastrophic cancellation in a subtraction.
original answer
Here is an approach using another math engine. It knows only square root, but this is enough here. Note that in the given example
\numb
turns out to be exactly zero.In this example, the two solutions are the same, as the
\numb
vanishes ...Notice that the solutions are computed expandably. That matters to some (fools...).
If you want more precision start with: