我尝试使用蒙特卡洛积分来近似给定图形下的区域来计算其面积。为此,我需要计算出的y_min和y_max是准确的。因此,作为示例,我将使用从0到pi的sin(x)
图表。要找到y_min和y_max,我有以下功能:
def y_range(f, x_min, x_max, n=100):
# Step size
h = float((x_max - x_min)) / n
# Calculate y for n points between x_min and x_max
y = [f(x * h) for x in range(0, n + 1)]
# Get minimum and maximum y
y_max = max(y)
y_min = min(y)
return y_min, y_max
打印y_min和y_max给出:
y_max = 1.0
y_min = -3.21624529935e-16
我知道y_min应该等于0.0,那么如何纠正这种不准确性?
答案 0 :(得分:1)
根本问题是,对于任何max
,min + 100*h
无法导出h
。有几个潜在的原因,但最简单的原因就是它们之间的步数不能被100
整除。
如何更好地完成它取决于你想要多么谨慎。您需要的两件事就是在两个值之间进行插值(而不是基于起点和步骤),并以精确的方式执行插值。
以下代码将产生可靠的结果:
def interp_at_step(a, b, i, n):
# separate calculation of alpha and beta to avoid catastrophic cancellation
alpha = (n-i)/n
beta = i/n
return a*alpha + b*beta
def y_range(f, x_min, x_max, n=100):
# Calculate y for n points between x_min and x_max
y = [f(interp_at_step(x_min, x_max, x, n)) for x in range(0, n + 1)]
# Get minimum and maximum y
y_max = max(y)
y_min = min(y)
return y_min, y_max
当然,正如Denys所说,pi无法准确表现出来。因此,这将减轻插值的误差,但不一定来自操作数本身。
答案 1 :(得分:0)
pi是不合理的,所以你必须接受它只能以一定的精度表示,无论你使用哪种表示。如果您正在使用float,那么精度将按照id product
------ ---------
155535 OTC
155535 COM
155536 OTC
155537 COM
155538 UNKNOWN
的顺序排列here。最简单的方法是使用10**(-16)
将结果四舍五入到15位小数。如果您需要比15位十进制数更好的精度,您可能会考虑其他类型来表示变量,例如十进制
答案 2 :(得分:-1)
当精度如此重要时,我不会使用float
。我建议你看看decimal.Decimal
。假设您将x_min
和x_max
更改为十进制,则只需在第3行删除float
。
This帖子可能有助于解释不准确的来源: