3

私は現在、Processing でいくつかの数値熱伝達計算を行っています。これには、相補誤差関数 (erfc) の適切な近似値が必要です。熱伝達方程式の 1 つは、exp(s^2) と erfc(s) の積で構成されます。これは、(s の値が大きい場合) 非常に大きな数に非常に小さな数を掛けることを意味します。このため、erfc の精度はかなり高くする必要があります。そうしないと、多数の s の計算が不安定になります。

Processing の数学関数 (sqrt()、exp()、pow() など) は double を使用できないため、float を使用していますが、s の値が大きい場合に安定性の問題が発生します。大きな値とは、約を意味します。例として、4.5 の erfc は 1.97*10^(-10) になります。

...そして質問へ。

1) 補完誤差関数値のより正確な表現を得るために、処理の数学関数 (平方根、指数、累乗など) で double を使用することは何とか可能ですか?

2) 私が知る限り、Python も float を使用しており、double ではありません。つまり、(少なくとも私の考えでは) Processing と Python は、補完的なエラー関数に対して同じ結果を取得する必要があります。しかし、そうではありません。Python は、Processing よりも正確な誤差関数の近似を行っています。どうすればいいの?

相補誤差関数近似の 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は浮動小数点数に倍精度を使用しており、これが計算偏差の理由です。Processing でこの問題を解決するために、Java 数学クラスの数学関数が使用されている場合、数学関数で double を使用することができます。

したがって、デフォルトの sqrt() 関数 (またはその他の数学関数) を使用する代わりにimport java.lang.Math.*;、コードの先頭に入力して Java 数学クラスをインポートします。Math.sqrt(Math.PI)の代わりに、たとえば型の処理で関数を使用するにはsqrt(PI)

于 2013-09-21T18:51:31.643 に答える