在区间(-1,1)上用Python绘制函数1/x和-1/x^2

1 投票
1 回答
3056 浏览
提问于 2025-04-18 00:42

请看看我的代码,帮帮我。
我正在写一段代码,用来近似一个函数的导数。为了直观地检查我的近似值和真实导数有多接近,我把它们一起画出来。

我的问题是,当函数在零点没有定义的时候,比如1/x,它的导数是'1/x^2'。

提前谢谢你们的帮助。

# -*- coding: utf-8 -*-
from pylab import *
import math
def Derivative(f,x, Tol = 10e-5, Max = 20):
try:
    k = 2
    D_old = (f(x+2.0**(-k))-f(x-2.0**-k))/(2.0**(1-k))
    k = 3
    D_new = (f(x+2.0**(-k))-f(x-2.0**-k))/(2.0**(1-k))

    E_old = abs(D_new - D_old)

    while True:
        D_old = D_new 

        k+=1

        D_new = (f(x+2.0**(-k))-f(x-2.0**-k))/(2.0**(1-k))
        E_new = abs(D_old - D_new)

        if E_new < Tol or E_new >= E_old or k >= Max:
            return D_old

except:
    return nan
def Fa(x):
     return math.sin(2*math.pi*x)
def Fap(x):
     return 2*math.pi*math.cos(2*math.pi*x)
def Fb(x):
    return x**2
def Fbp(x):
    return 2*x
def Fc(x):
    return 1.0/x
def Fcp(x):
    if abs(x)<0.01:
    return 0
    else:
        return -1.0/x**2
def Fd(x):
    return abs(x)
def Fdp(x):
    return 1 #since it's x/sqrt(x**2)

# Plot of Derivative Fa
xx = arange(-1, 1, 0.01)              # A Numpy vector of x-values
yy = [Derivative(Fa, x) for x in xx]  # Vector of f’ approximations
plot(xx, yy, 'r--', linewidth = 5)      # solid red line of width 5

yy2 = [Fap(x) for x in xx]
plot(xx, yy2, 'b--', linewidth = 2)     # solid blue line of width 2

# Plot of Derivative Fb

yy = [Derivative(Fb, x) for x in xx]  # Vector of f’ approximations
plot(xx, yy, 'g^', linewidth = 5)      # solid green line of width 5

yy2 = [Fbp(x) for x in xx]
plot(xx, yy2, 'y^', linewidth = 2)     # solid yellow line of width 2

1 个回答

1

"1/x" 是一个无限的函数,你不能画出一个在零点没有定义的函数。你只能用一个断开的坐标轴来表示这个函数。

关于断开坐标轴的做法,你可以参考评论区的 wwii 的建议,或者查看这个 教程,它是关于 matplotlib 的。

这个教程展示了如何仅用两个子图来实现你想要的效果。

下面是示例代码:

"""
Broken axis example, where the y-axis will have a portion cut out.
"""
import matplotlib.pylab as plt
import numpy as np


# 30 points between 0 0.2] originally made using np.random.rand(30)*.2
pts = np.array([ 0.015,  0.166,  0.133,  0.159,  0.041,  0.024,  0.195,
    0.039, 0.161,  0.018,  0.143,  0.056,  0.125,  0.096,  0.094, 0.051,
    0.043,  0.021,  0.138,  0.075,  0.109,  0.195,  0.05 , 0.074, 0.079,
    0.155,  0.02 ,  0.01 ,  0.061,  0.008])

# Now let's make two outlier points which are far away from everything. 
pts[[3,14]] += .8

# If we were to simply plot pts, we'd lose most of the interesting
# details due to the outliers. So let's 'break' or 'cut-out' the y-axis
# into two portions - use the top (ax) for the outliers, and the bottom
# (ax2) for the details of the majority of our data
f,(ax,ax2) = plt.subplots(2,1,sharex=True)

# plot the same data on both axes
ax.plot(pts)
ax2.plot(pts)

# zoom-in / limit the view to different portions of the data
ax.set_ylim(.78,1.) # outliers only
ax2.set_ylim(0,.22) # most of the data

# hide the spines between ax and ax2
ax.spines['bottom'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax.xaxis.tick_top()
ax.tick_params(labeltop='off') # don't put tick labels at the top
ax2.xaxis.tick_bottom()

# This looks pretty good, and was fairly painless, but you can get that
# cut-out diagonal lines look with just a bit more work. The important
# thing to know here is that in axes coordinates, which are always
# between 0-1, spine endpoints are at these locations (0,0), (0,1),
# (1,0), and (1,1).  Thus, we just need to put the diagonals in the
# appropriate corners of each of our axes, and so long as we use the
# right transform and disable clipping.

d = .015 # how big to make the diagonal lines in axes coordinates
# arguments to pass plot, just so we don't keep repeating them
kwargs = dict(transform=ax.transAxes, color='k', clip_on=False)
ax.plot((-d,+d),(-d,+d), **kwargs)      # top-left diagonal
ax.plot((1-d,1+d),(-d,+d), **kwargs)    # top-right diagonal

kwargs.update(transform=ax2.transAxes)  # switch to the bottom axes
ax2.plot((-d,+d),(1-d,1+d), **kwargs)   # bottom-left diagonal
ax2.plot((1-d,1+d),(1-d,1+d), **kwargs) # bottom-right diagonal

# What's cool about this is that now if we vary the distance between
# ax and ax2 via f.subplots_adjust(hspace=...) or plt.subplot_tool(),
# the diagonal lines will move accordingly, and stay right at the tips
# of the spines they are 'breaking'

plt.show()

撰写回答