Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Riemann和对于相等的正面积和负面积不会产生零_Python_Matplotlib_Integral_Calculus - Fatal编程技术网

Python Riemann和对于相等的正面积和负面积不会产生零

Python Riemann和对于相等的正面积和负面积不会产生零,python,matplotlib,integral,calculus,Python,Matplotlib,Integral,Calculus,我编写了一个程序,用一个黎曼和来近似一个积分,并用Python中的matplotlib来绘制它。对于x轴上下面积相等的函数,结果面积应为零,但我的程序输出的数值非常小 下面的代码将奇数函数f(x)=x^3从-1绘制到1,因此面积应为零。相反,我的代码将其近似为1.68065561477562 e^-15 这是什么原因造成的?是delta_x、x还是y中的舍入误差?我知道我可以将值舍入为零,但我想知道是否还有其他问题或方法可以解决这个问题 我曾尝试将Decimal.Decimal类用于delta_

我编写了一个程序,用一个黎曼和来近似一个积分,并用Python中的matplotlib来绘制它。对于x轴上下面积相等的函数,结果面积应为零,但我的程序输出的数值非常小

下面的代码将奇数函数f(x)=x^3从-1绘制到1,因此面积应为零。相反,我的代码将其近似为1.68065561477562 e^-15

这是什么原因造成的?是delta_x、x还是y中的舍入误差?我知道我可以将值舍入为零,但我想知道是否还有其他问题或方法可以解决这个问题

我曾尝试将Decimal.Decimal类用于delta_x,但得到的数字更小

Python代码:

import matplotlib.pyplot as plt
import numpy as np

# Approximates and graphs integral using Riemann Sum


# example function: f(x) = x^3
def f_x(x):
    return x**3

# integration range from a to b with n rectangles
a, b, n = -1, 1, 1000

# calculate delta x, list of x-values, list of y-values, and approximate area under curve
delta_x = (b - a) / n

x = np.arange(a, b+delta_x, delta_x)

y = [f_x(i) for i in x]

area = sum(y) * delta_x

# graph using matplotlib
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y)
ax.bar(x, y, delta_x, alpha=.5)
plt.title('a={}, b={}, n={}'.format(a, b, n))
plt.xlabel('A = {}'.format(area))
plt.show()

你的代码对我来说似乎是有效的。它对由
f_x
返回的
y
求和,并通过将
delta_x
添加到
arange
的第二个参数中,解释了只有1000个子区间的近似误差。不幸的是,我认为舍入错误在这里起作用。

您的代码对我来说似乎是有效的。它对由
f_x
返回的
y
求和,并通过将
delta_x
添加到
arange
的第二个参数中,解释了只有1000个子区间的近似误差。不幸的是,我认为舍入误差在这里起作用。

是的,这只是因为浮点不准确

对于构造分区,可能更合适,因为可能包括也可能不包括端点,这取决于使用非整数步长时端点的舍入方式

来自文档:

使用非整数步长(如0.1)时,结果通常不一致。对于这些情况,最好使用linspace


是的,这只是因为浮点不准确

对于构造分区,可能更合适,因为可能包括也可能不包括端点,这取决于使用非整数步长时端点的舍入方式

来自文档:

使用非整数步长(如0.1)时,结果通常不一致。对于这些情况,最好使用linspace


你需要知道你所计算的不是原始意义上的黎曼积分。您将间隔划分为
n
个存储单元,然后将其相加为
n+1
个存储单元(此处
n=1000
len(x)==1001
)。因此,结果可能接近你的预期,但这肯定不是一个好办法

使用将间隔划分为
n
bin,然后对这些
n
bin的值求和。您可以选择是计算左黎曼和、右黎曼和,还是可能取中点

import numpy as np

def f_x(x):
    return x**3

# integration range from a to b with n rectangles
a, b, n = -1, 1, 1000

delta_x = (b - a) / float(n)

x_left = np.arange(a, b, delta_x)
x_right = np.arange(a+delta_x, b+delta_x, delta_x)
x_mid = np.arange(a+delta_x/2., b+delta_x/2., delta_x)

print len(x_left),  len(x_right), len(x_mid)          ### 1000 1000 1000


area_left = f_x(x_left).sum() * delta_x
area_right = f_x(x_right).sum() * delta_x
area_mid = f_x(x_mid).sum() * delta_x

print area_left     # -0.002
print area_right    #  0.002
print area_mid      # 1.81898940355e-15
虽然中点和已经给出了一个很好的结果,但对于对称函数,最好选择
n
偶数,并取左右和的平均值

print 0.5*(area_right+area_left)   # 1.76204537072e-15
这同样接近于0

现在值得注意的是,
numpy.arange
本身会产生一些错误。更好的选择是使用
numpy.linspace

x_left = np.linspace(a, b-delta_x, n)
x_right = np.linspace(a+delta_x, b, n)
x_mid = np.linspace(a+delta_x/2., b-delta_x/2., n)
屈服

print area_left     # -0.002
print area_right    #  0.002
print area_mid      # 8.52651282912e-17
print 0.5*(area_right+area_left)   # 5.68121938382e-17
5.68121938382e-17
非常接近于0。它不完全为0的原因确实是

著名的例子是
0.1+0.2-0.3

结果是
5.5e-17
而不是0。这表明该简单操作引入了与黎曼积分相同的1e-17阶误差

您需要知道,您正在计算的不是原始意义上的黎曼积分。您将间隔划分为
n
个存储单元,然后将其相加为
n+1
个存储单元(此处
n=1000
len(x)==1001
)。因此,结果可能接近你的预期,但这肯定不是一个好办法

使用将间隔划分为
n
bin,然后对这些
n
bin的值求和。您可以选择是计算左黎曼和、右黎曼和,还是可能取中点

import numpy as np

def f_x(x):
    return x**3

# integration range from a to b with n rectangles
a, b, n = -1, 1, 1000

delta_x = (b - a) / float(n)

x_left = np.arange(a, b, delta_x)
x_right = np.arange(a+delta_x, b+delta_x, delta_x)
x_mid = np.arange(a+delta_x/2., b+delta_x/2., delta_x)

print len(x_left),  len(x_right), len(x_mid)          ### 1000 1000 1000


area_left = f_x(x_left).sum() * delta_x
area_right = f_x(x_right).sum() * delta_x
area_mid = f_x(x_mid).sum() * delta_x

print area_left     # -0.002
print area_right    #  0.002
print area_mid      # 1.81898940355e-15
虽然中点和已经给出了一个很好的结果,但对于对称函数,最好选择
n
偶数,并取左右和的平均值

print 0.5*(area_right+area_left)   # 1.76204537072e-15
这同样接近于0

现在值得注意的是,
numpy.arange
本身会产生一些错误。更好的选择是使用
numpy.linspace

x_left = np.linspace(a, b-delta_x, n)
x_right = np.linspace(a+delta_x, b, n)
x_mid = np.linspace(a+delta_x/2., b-delta_x/2., n)
屈服

print area_left     # -0.002
print area_right    #  0.002
print area_mid      # 8.52651282912e-17
print 0.5*(area_right+area_left)   # 5.68121938382e-17
5.68121938382e-17
非常接近于0。它不完全为0的原因确实是

著名的例子是
0.1+0.2-0.3

结果是
5.5e-17
而不是0。这表明该简单操作引入了与黎曼积分相同的1e-17阶误差

这在原则上是正确的,尽管问题中的代码有另一个比这里讨论的准确性更严重的缺陷。请看我的答案。这在原则上是正确的,尽管问题中的代码有另一个比这里讨论的准确性更严重的缺陷。看我的答案。是的,有趣的是,如果你只使用奇数个子区间,那么将左黎曼和从
-1
1+delta\ux
相当于对
-1-delta\ux/2
1+delta\ux/2
的区间使用中点近似,因此保持对称。是的,有趣的是,如果只使用奇数个子区间,那么将
-1
上的左黎曼和取到
1+delta_x
相当于对
-1-delta_x/2
1+delta_x/2
上的区间使用中点近似,因此保持对称。