![问题](https://linux22.com/image/386490/%E9%97%AE%E9%A2%98.png)
下列宏定义\f[#1]
及其导数\fp[#1]
。
\def\f[#1]{((#1)*(#1-1)*(#1-2)*(#1-3)*(#1-5)/10+1.5)}
\edef\fp[#1]{Derive(1,\f[#1])}
问题
我想定义一个可重复使用的宏\g{<contant>}{<variable-x>}
。不幸的是, 这是否意味着at\fp[0.8]
的值始终等于零?df/dx
x=0.8
df[0.8]/dx
\documentclass[pstricks]{standalone}
\usepackage{pstricks-add,pst-eucl}
\def\f[#1]{(#1)*(#1-1)*(#1-2)*(#1-3)*(#1-5)/10+1.5}
\def\fDerivation#1#2{
/x #1 def /F (Derive(1,#2)) tx@AlgToPs begin AlgToPs end cvx def
x F}
\def\g#1#2{(\fDerivation{#1}{\f[#2]})*(#2-#1)+\f[#1]} % y = f'(x0)*(x-x0) +f(x0)
\begin{document}
\begin{pspicture}[showgrid,algebraic](0,-2)(3,3)
\psplot[linecolor=blue]{0}{2}{\f[x]}
\psplot{0}{2}{\g{2}{x}}
\pstInterFF{\f[x]}{\g{2}{x}}{5}{A} % <------- this is important part!
\end{pspicture}
\end{document}
答案1
这是在 的帮助下polexpr
。
\documentclass{article}
\usepackage{pstricks-add,pst-eucl}
\usepackage{polexpr}
\poldef f(x):=x(x-1)(x-2)(x-3)(x-5)/10+1.5;
\PolReduceCoeffs{f}
\PolDiff{f}{f'}
\PolReduceCoeffs{f'}
\let\PolToExprOneTerm\PolToExprOneTermStyleB
\edef\f{\PolToExpr{f}}% uses x (\PolToExprVar default)
% \show\f % style "B" puts denominators on the right
% > \f=macro:
% ->x^5/10-11*x^4/10+41*x^3/10-61*x^2/10+3*x+3/2.
% first try:
% \def\g#1#2{\PolEval{f'}\At{#1}*(#2-#1) +
% \PolEval{f}\At{#1}} % y = f'(x0)*(x-x0) +f(x0)
% but this is bad:
% \edef\test{\g{.8}{x}}
% \show\test
% uses xintfrac internal notation, which are no good for pstricks
% malax things to get output syntax understandable by external world
% (I should make it easier)
\newcommand\g[2]{\PolDecToString{\xintREZ{\PolEval{f'}\At{#1}}}*(#2-#1) +
\PolDecToString{\xintREZ{\PolEval{f}\At{#1}}}} % y = f'(x0)*(x-x0) +f(x0)
% \edef\test{\g{.8}{x}}
% \show\test % -0.936*(x-.8) + 1.677408
% \xintverbosetrue
% \poldef k(x) := f(x) - (\g{1.4}{x}); don't forget parentheses here!
% \typeout{\PolToExpr{k}, \PolEval{k}\At{1.4}}% ok, evaluates to zero
% \PolToSturm{k}{k}
% \PolSturmIsolateZeros{k}
% \PolEnsureIntervalLengths{k}{-10}
% Package xintexpr Info: (on line 40)
% Variable "kL_3" globally defined with value 32629939266/1[-10].
\begin{document}
\begin{pspicture}[showgrid,algebraic](0,-2)(6,4)
\psplot[linecolor=blue]{0}{5.18}{\f}
\psplot[linecolor=red]{0}{6}{\g{2}{x}}
\pstInterFF{\f}{\g{2}{x}}{5}{A} % <------- this is important part!
% This is ok
\psplot[linecolor=black]{0}{6}{\g{1.5}{x}}
\pstInterFF{\f}{\g{1.5}{x}}{5}{C}
\pstInterFF{\f}{\g{1.5}{x}}{3}{D}
\psplot[linecolor=black]{0}{6}{\g{1.4}{x}}
\pstInterFF{\f}{\g{1.4}{x}}{5}{C1}
\pstInterFF{\f}{\g{1.4}{x}}{3.2629939266}{D1}% we have to input almost exact abscissa !!
\psplot[linecolor=black]{0}{6}{\g{1.3}{x}}
\pstInterFF{\f}{\g{1.3}{x}}{5}{C2}
\pstInterFF{\f}{\g{1.3}{x}}{3}{D2}
\psplot[linecolor=black]{0}{6}{\g{1.2}{x}}
\pstInterFF{\f}{\g{1.2}{x}}{5}{C3}
\pstInterFF{\f}{\g{1.2}{x}}{3.7}{D3}% we have to input very close abscissa !!
\psplot[linecolor=black]{0}{6}{\g{1.1}{x}}
\pstInterFF{\f}{\g{1.1}{x}}{5}{C4}
\pstInterFF{\f}{\g{1.1}{x}}{3.9}{D4}% we have to input very close abscissa !!
% \psplot[linecolor=green]{0}{6}{\g{0.8}{x}}
% \pstInterFF{\f}{\g{0.8}{x}}{5}{E}% no
% (I get errors on ghostscript side)
%\psplot[linecolor=cyan]{0}{6}{\g{3}{x}}
%\pstInterFF{\f}{\g{3}{x}}{4.8}{B}% fails to find it!
\end{pspicture}
\end{document}
备注:例如,我在使用 ghostscript 时遇到了一些问题
Running `Ps2pdf' on `testpstricks' with ``ps2pdf testpstricks.ps''
DEBUG: FC_WEIGHT didn't match
但更糟糕的是,当\pstInterFF
找不到点时。但我不太了解 Ghostscript。
我的经验是,\pstInterFF
有时无法预测到附近的根。对于 D1,我给出了我最好的视觉估计,精度为 1 位小数,但它找不到,所以我polexpr
首先通过精度为 10 位小数来计算。
由于分数的内部符号,使用polexpr
它并不总是可以立即与外部世界对话。没有在输出上使用它,但是确实在输出上使用它,所以我不得不将这个输出包装到一些额外的例程中。xintfrac
A/B[N]
\PolToExpr
\PolEval
仍然在polexpr
我已经确定了切线与曲线在另一点再次相切相交的所有点。
事实证明,这样的点恰好有 3 对,总共 6 个点,其中 2 个点距离非常非常近,肉眼根本无法区分。
\documentclass[pstricks, preview]{standalone}
\usepackage{pstricks-add,pst-eucl}
\usepackage{polexpr}
\poldef f(x):=x(x-1)(x-2)(x-3)(x-5)/10+1.5;
\PolReduceCoeffs{f}
\PolDiff{f}{f'}
\PolDiff{f'}{f''}
\PolDiff{f''}{f3}
\PolDiff{f3}{f4}
\PolDiff{f4}{f5}
% \xintverbosetrue
\poldef Delta(x) := subs(subs(subs(subs(
18*a*b*c*d-4b^3d+b^2c^2-4a*c^3-27a^2d^2,
d=f''(x)/2), c=f3(x)/6), b=f4(x)/24), a=f5(x)/120);
\PolReduceCoeffs{Delta}% coefficients are not automatically reduced to
% smallest terms, let's do it. (but any way the Sturm chain polynomials
% automatically are made integer coefficients with no common factor)
\PolToSturm{Delta}{DeltaSturm}
\PolSturmIsolateZeros{DeltaSturm}
\PolEnsureIntervalLengths{DeltaSturm}{-20}
\let\PolToExprOneTerm\PolToExprOneTermStyleB
\newcommand\f{}
\edef\f{\PolToExpr{f}}% uses x (\PolToExprVar default)
% \show\f % style "B" puts denominators on the right
% > \f=macro:
% ->x^5/10-11*x^4/10+41*x^3/10-61*x^2/10+3*x+3/2.
% malax things to get output syntax understandable by external world
% (I should make it easier)
\newcommand\g[2]{\PolDecToString{\xintREZ{\PolEval{f'}\At{#1}}}*(#2-#1) +
\PolDecToString{\xintREZ{\PolEval{f}\At{#1}}}} % y = f'(x0)*(x-x0) +f(x0)
% \edef\test{\g{.8}{x}}
% \show\test % -0.936*(x-.8) + 1.677408
\begin{document}
\begin{preview}
\PolPrintIntervals{DeltaSturm} % (or use \xintverbosetrue and check in log)
% 1 0.38196601125010515179...
% 2 0.69722436226800535344...
% 3 0.89706136340735988338...
% 4 2.61803398874989484820...
% 5 4.30277563773199464655...
% 6 4.30293863659264011661...
\end{preview}
\begin{pspicture}[showgrid,algebraic](0,-2)(6,4)
\psplot[linecolor=blue]{0}{5.18}{\f}
% 3 0.89706136340735988338...
\psplot[linecolor=red]{0}{6}{\g{\PolSturmIsolatedZeroLeft{DeltaSturm}{3}}{x}}
\end{pspicture}
\begin{pspicture}[showgrid,algebraic](0,-2)(6,4)
\psplot[linecolor=blue]{0}{5.18}{\f}
% 2 0.69722436226800535344...
\psplot[linecolor=green]{0}{6}{\g{\PolSturmIsolatedZeroLeft{DeltaSturm}{2}}{x}}
\end{pspicture}
\begin{pspicture}[showgrid,algebraic](0,-2)(6,4)
\psplot[linecolor=blue]{0}{5.18}{\f}
% 1 0.38196601125010515179...
\psplot[linecolor=magenta]{0}{6}{\g{\PolSturmIsolatedZeroLeft{DeltaSturm}{1}}{x}}
\end{pspicture}
\end{document}
前两个并不相同(红色和绿色切线不是同一条直线)。希望我没有犯下一些愚蠢的错误,在建立计算Delta(x_0)
3 次多项式的判别式的公式(f(x) - f(x_0) - f'(x_0)(x-x_0))/(x-x_0)^2
时,该公式恰好在 处的切线有另一个切点时消失x_0
。它似乎在视觉上起作用,两个点几乎重合,这很有趣。
当然有了这样的任意精度软件polexpr
我们才不会被愚弄!
更新关于计算具有双切线的点的 6 次多项式,嵌套subs(subs(...
是为了进行轻微优化,a, b, c, d
只对 进行一次求值,但这里a, b, c, d
不是用数值而是“多项式”替换,因此嵌套的收益subs
几乎为零(当人们知道内部工作原理时)。无论如何,首先将 3 次多项式的判别式定义为函数,然后在语法中使用它,\poldef
这样更清楚。xintexpr
\poldef
% polexpr allows only to define one-variable polynomials (currently)
% but we only need this as a "function" (i.e. a complicated nested
% usages of xintfrac macros):
\xintdeffunc Delta3(a, b, c, d) := 18a*b*c*d-27a^2d^2-4a*c^3-4b^3d+b^2c^2;
% and we can then use this "function" with arguments being
% _polynomials_, to create a genuine _polynomial_
\poldef Delta(x) := Delta3(f5(x)/120, f4(x)/24, f3(x)/6, f''(x)/2);
% or, and we could as well have written 18*(f5(x)/120)*(f4(x)/24)*....
% but this would be barely readable, so we use the nested "subs" for clarity
% \poldef Delta(x) := subs(subs(subs(subs(
% 18a*b*c*d-27a^2d^2-4a*c^3-4b^3d+b^2c^2;
% d=f''(x)/2), c=f3(x)/6), b=f4(x)/24), a=f5(x)/120);
\PolReduceCoeffs{Delta}
% \let\PolToExprOneTerm\PolToExprOneTermStyleB
% \typeout{HERE IT IS: \PolToExpr{Delta}}
6 次多项式正是这样的:
-x^6/50+33*x^5/125-3223*x^4/2500+1796*x^3/625-7457*x^2/2500+1741*x/1250-579/2500
(顺便说一下,手工完成所有这些计算并不难)
答案2
\documentclass{minimal}
\usepackage{pstricks-add}
\def\f[#1]{(#1)*(#1-1)*(#1-2)*(#1-3)*(#1-5)/10+1.5}
\def\fDerivation#1#2{
/x #1 def /F (Derive(1,#2)) tx@AlgToPs begin AlgToPs end cvx def
x F}
\begin{document}
\begin{pspicture}[showgrid](0,-2)(3,3)
\psplot[algebraic,linecolor=blue]{0}{2}{\f[x]}
\psplot[algebraic]{0}{2}{Derive(1,\f[x])}
\psdot[dotscale=2,linecolor=red](!\fDerivation{0.8}{\f[x]})
\end{pspicture}
\end{document}
选择:
\documentclass{minimal}
\usepackage{pst-calculate,pstricks-add}
\def\f[#1]{(#1)*(#1-1)*(#1-2)*(#1-3)*(#1-5)/10+1.5}
\def\fDerivation#1#2{
/x #1 def /F (Derive(1,#2)) tx@AlgToPs begin AlgToPs end cvx def
x F /M exch def pop}
\begin{document}
\begin{pspicture}[showgrid](0,-2)(3,3)
\psplot[algebraic,linecolor=blue]{0}{2}{\f[x]}
\psplot[algebraic]{0}{2}{Derive(1,\f[x])}
\psplot[linecolor=red,algebraic]{0}{3}[\fDerivation{0.8}{\f[x]}]{%
M*(x-0.8)+\pscalculate{\f[0.8]}}
\end{pspicture}
\end{document}