3

我目前正在处理中进行一些数值传热计算,这需要互补误差函数(erfc)的良好近似。传热方程之一由 exp(s^2) 和 erfc(s) 的乘积组成,这意味着(对于较大的 s 值)一个非常大的数字乘以一个非常小的数字。因此,erfc 的精度需要相当高。否则大量 s 的计算将不稳定。

由于 Processing not 的数学函数(例如 sqrt()、exp() 和 pow())不能采用双精度数,所以我使用浮点数,这给我在 s 的大值时带来了稳定性问题。我的意思是大值。4 到 5。例如,4.5 的 erfc 应该是 1.97*10^(-10)。

...现在是问题。

1) 是否有可能在处理的数学函数(例如平方根、exp 和幂)中使用双精度来更精确地表示互补误差函数值?

2) 据我所知,Python 也使用浮点数——而不是双精度数——这意味着(至少在我看来)Processing 和 Python 应该得到相同的互补误差函数结果。然而,这种情况并非如此。Python 对误差函数的逼近比 Processing 更精确。怎么会这样?

下面显示了互补误差函数近似的 Python 和处理版本。

Python:

from math import sqrt
from math import pi
from math import exp

n=1000 #number of intervals
b=float(1) #integration end
h=b/n #Interval width

leftRiemann=0
for s in range(0, n):
  leftRiemann=leftRiemann+h*2/sqrt(pi)*exp(-((s*h)**2))

rightRiemann=0
for s in range(1, n+1):
  rightRiemann=rightRiemann+h*2/sqrt(pi)*exp(-((s*h)**2))

trapez=0.5*leftRiemann+0.5*rightRiemann

centrePoint=0
for s in range(1, n+1):
  centrePoint = centrePoint+h*2/sqrt(pi)*exp(-((h*(s-0.5))**2))

erfc=1 - (1.0/3*trapez+2.0/3*centrePoint)
print erfc

加工:

void setup() {
  int n = 1000;
  float b = 1;
  float h = b/n;

  float leftRiemann = 0;
  for(int s=0; s<n; s++) {
    leftRiemann = leftRiemann + h*2/sqrt(PI)*exp(-pow(s*h, 2));
  }

  float rightRiemann = 0;
  for(int s=1; s<=n; s++) {
    rightRiemann = rightRiemann + h*2/sqrt(PI)*exp(-pow(s*h, 2));
  }

  float trapez = 0.5*leftRiemann + 0.5*rightRiemann;

  float centrePoint = 0;
  for(int s=1; s<=n; s++) {
    centrePoint = centrePoint + h*2/sqrt(PI)*exp(-pow(h*(s-0.5), 2));
  }

  float erfc = 1 - (trapez/3 + 2*centrePoint/3);
  println(erfc);
}

Python:erfc(1) = 0.15729920705

处理:erfc(1) = 0.15729982

表值:erfc(1) = 0.157299

4

1 回答 1

1

好的,现在我想通了。正如@Veedrac 所写,Python 对浮点数使用双精度,这是计算偏差的原因。为了克服处理中的这个问题,如果使用 Java 数学类中的数学函数,则可以在数学函数中使用双精度数。

因此,不要使用默认的 sqrt() 函数(或任何其他数学函数),而是通过import java.lang.Math.*;在代码开头键入来导入 java 数学类。在处理类型中使用函数,例如Math.sqrt(Math.PI),而不是sqrt(PI).

于 2013-09-21T18:51:31.643 回答