pgfplot 呈现锯齿状多项式

pgfplot 呈现锯齿状多项式

无论使用smooth还是增加sample点数,我都会得到这个 9 次多项式的非常锯齿状的图。

有想法吗?

\documentclass{standalone}

\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usetikzlibrary{fpu}

\begin{document}
\begin{tikzpicture}[scale=.55]
\begin{axis}[
xlabel={$x$}, ylabel={$y$}
,restrict y to domain=-10^9:10^9
,axis lines=middle
,samples=2000,
%,grid
,thick
,domain=0:4
,xtick={0,1,2,3,4}
,ytick={0,9}
,xmin=0
,xmax=4.5
,ymin=-1
,ymax=1.8
,xlabel shift={1in}
,y tick label style={yshift={5pt}}
%,legend pos=outer north east
]
\addplot+[black,no marks,smooth]{1.5*x + 3.83333*x^2 - 15.0104*x^3 + 22.7454*x^4 - 19.2028*x^5 +
 9.37731*x^6 - 2.5978*x^7 + 0.377315*x^8 - 0.0222801*x^9};
\end{axis}
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案1

正如评论的那样约翰·科米洛,这里的问题在于精度——添加样本不会有帮助。

我的建议是将多项式拆分为二阶部分项;这样可以避免有问题的高次幂(如x^9)。我编写了一个小型 SymPy 来执行此操作,结果您的多项式等同于:

-0.0222801*x*(x - 4.04307547777127)*(x + 0.193642687986076)*(x**2 - 7.81990533113625*x + 15.3415387466162)*(x**2 - 4.09164256641596*x + 4.41554633036612)*(x**2 - 1.1740869290557*x + 1.26942721414423)

通常情况下,这是一个计算性能更好的函数。你可以看到:

\documentclass[border=10pt]{standalone}

\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usetikzlibrary{fpu}

\begin{document}
\begin{tikzpicture}[scale=.55]
\begin{axis}[
xlabel={$x$}, ylabel={$y$}
,restrict y to domain=-10^9:10^9
,axis lines=middle
,samples=200,
%,grid
,thick
,domain=0:4
,xtick={0,1,2,3,4}
,ytick={0,9}
,xmin=0
,xmax=4.5
,ymin=-1
,ymax=1.8
,xlabel shift={1in}
,y tick label style={yshift={5pt}}
%,legend pos=outer north east
]
% \addplot+[black,no marks,]{1.5*x + 3.83333*x^2 - 15.0104*x^3 + 22.7454*x^4 - 19.2028*x^5 +
 % 9.37731*x^6 - 2.5978*x^7 + 0.377315*x^8 - 0.0222801*x^9};
\addplot+[red,no marks,]{-0.0222801*x*(x - 4.04307547777127)*(x + 0.193642687986076)
    *(x*x - 7.81990533113625*x + 15.3415387466162)
    *(x*x - 4.09164256641596*x + 4.41554633036612)
    *(x*x - 1.1740869290557*x + 1.26942721414423)};
\end{axis}
\end{tikzpicture}
\end{document}

输出图

(如果您愿意,我可以分享 Python 代码 --- 但这只是一个技巧,可能这里的每个人都可以编写一些更优雅的东西)。

SymPi 代码用于获取多项式的二阶项形式

(根据请求,这里是 python 代码);请注意,我留下了公式的 mathjax 代码,因为 PNG 真的很小……

import sys
import os
# BEWARE only for command line interactive usage
from math import *
import scipy as sp
import numpy as np
import matplotlib.pyplot as plt
sys.path.append("/home/romano/lib/python")
import sympy as sym
from sympy import init_printing
init_printing()
sym.__version__
'1.1.1'
x, y, z = sym.symbols("x y z")

在此处输入多项式

Y=1.5*x + 3.83333*x**2 - 15.0104*x**3 + 22.7454*x**4 - 19.2028*x**5 +9.37731*x**6 - 2.5978*x**7 + 0.377315*x**8 - 0.0222801*x**9
P=sym.Poly(Y); P

$$\operatorname{Poly}{\left( - 0.0222801 x^{9} + 0.377315 x^{8} - 2.5978 x^{7} + 9.37731 x^{6} - 19.2028 x^{5} + 22.7454 x^{4} - 15.0104 x^{3} + 3.83333 x^{2} + 1.5 x, x, domain=\mathbb{R} \right)}$$

在此处输入图片描述

求多项式的根

rs=sym.polys.polyroots.roots(P, multiple=True); rs

$$\left [ -0.193642687986076, \quad 0, \quad 4.04307547777127, \quad 0.587043464527849 - 0.961668958061643 i, \quad 0.587043464527849 + 0.961668958061643 i, \quad 2.04582128320798 - 0.479751610251982 i, \quad 2.04582128320798 + 0.479751610251982 i, \quad 3.90995266556812 - 0.23196745382247 i, \quad 3.90995266556812 + 0.23196745382247 i\right ]$$

在此处输入图片描述

获得 sos(二阶段)形式的肮脏黑客。它依赖于根的顺序是固定的这一事实,我不确定这是否正确:复共轭项必须一个接一个地出现。

tot=1
skip = False
for r in rs:
    rr = complex(r)
    if rr.imag==0:
        term = (x-rr)
        tot = tot*term
    else:
        if skip==False: #first complex root 
            skip=True
            a = rr.real
            b = rr.imag
            term = (x*x-2*a*x+(a*a+b*b))
            tot = term * tot
        else:
            skip=False
tot

$$x \left(x - 4.04307547777127\right) \left(x + 0.193642687986076\right) \left(x^{2} - 7.81990533113625 x + 15.3415387466162\right) \left(x^{2} - 4.09164256641596 x + 4.41554633036612\right) \left(x^{2} - 1.1740869290557 x + 1.26942721414423\right)$$

在此处输入图片描述

f=sym.LC(P); print(f); print (f*tot)
-0.0222801000000000
-0.0222801*x*(x - 4.04307547777127)*(x + 0.193642687986076)*(x**2 - 7.81990533113625*x + 15.3415387466162)*(x**2 - 4.09164256641596*x + 4.41554633036612)*(x**2 - 1.1740869290557*x + 1.26942721414423)

检查两件事是否相同……你永远不知道

Z=sym.expand(f*tot); Z

$$- 0.0222801 x^{9} + 0.377315 x^{8} - 2.5978 x^{7} + 9.37731 x^{6} - 19.2028 x^{5} + 22.7454 x^{4} - 15.0104 x^{3} + 3.83333 x^{2} + 1.5 x$$

在此处输入图片描述

Y

$$- 0.0222801 x^{9} + 0.377315 x^{8} - 2.5978 x^{7} + 9.37731 x^{6} - 19.2028 x^{5} + 22.7454 x^{4} - 15.0104 x^{3} + 3.83333 x^{2} + 1.5 x$$

在此处输入图片描述

相关内容