1

数値範囲を同じ長さのセグメントに分割する必要があります。しかし、どちらの方法がより正確かは判断できません。例えば:

double r1 = 100.0, r2 = 1000.0, r = r2 - r1;
int n = 30;
double[] position = new double[n];
for (int i = 0; i < n; i++)
{
    position[i] = r1 + (double)i / n * r;
    // position[i] = r1 + i * r / n;
}

(double)int1 / int2 * doubleまたはについてint1 * double / int2です。どちらの方法がより正確ですか? どの方法を使用すればよいですか?

アップデート

次のコードは違いを示します。

double r1 = 1000.0, r2 = 100000.0, r = r2 - r1;
int n = 300;
double[] position = new double[n];
for (int i = 0; i < n; i++)
{
    double v1 = r1 + (double)i / n * r;
    double v2 = position[i] = r1 + i * r / n;
    if (v1 != v2)
    {
        Console.WriteLine(v2 - v1);
    }
}
4

3 に答える 3

1

免責事項:例として挙げるすべての数値は正確ではありませんが、舞台裏で起こっていることの原則を示しています。

2 つのケースを調べてみましょう。

(1)int1 = 1000, int2= 3, double = 3.0 最初の方法は次のようになります: (1000.0 / 3) * 3 == 333.33333 * 3.0 == 999.999...
2番目の方法は(1000 * 3.0) / 3 == 3000 / 3 == 1000
このシナリオでは - 2 番目の方法の方が正確です。

(2) int1 = 2, int2 = 2, double = Double.MAX_VALUE
1 つ目は生成されます(2.0 / 2) * Double.MAX_VALUE == 1 * Double.MAX_VALUE == Double.MAX_VALUE
が、2 つ目は生成されます(2 * Double.MAX_VALUE) / 2- (Java では) が生成されますInfinity。オーバーフローする可能性があるのか​​、それとも常に無限大なのか、二重標準がこのケースについて何を言っているのかわかりませんが、明確に問題。
したがって、この場合、最初の方法の方が正確です。

integers がlongs またはdoubleisである場合、事態はより複雑になる可能性がfloatあります。s で表すことができない長い値があるdoubleためです。この場合、大きな値に対して精度が失われる可能性がdoubleあり、いずれにせよ、大きなdouble値は精度が低くなります。 .

結論: どちらが優れているかはドメイン固有です。場合によっては、最初の方法の方が良い場合もあれば、最初の方法の方が良い場合もあります。int1int2、およびの値に大きく依存しますdouble
ただし、知る限り、倍精度演算の一般的な経験則は、計算をできるだけ小さく保つことです(巨大な数を作成してから元に戻すのではなく、できるだけ小さく保ちます)。この問題は、有効桁数の損失として知られています。

于 2012-09-06T18:34:51.127 に答える
1

いずれにせよ、コンパイラまたは JIT プロセスは効率のために操作を並べ替える可能性があるため、どちらも特に高速ではありません。

于 2012-09-05T13:00:41.590 に答える
0

たぶん私はあなたの要件を誤解していますが、ループ内で除算/乗算を行うのはなぜですか? 多分これは同じ結果を得るでしょう:

decimal r1 = 100.0m, r2 = 1000.0m, r = r2 - r1;
int n = 30;
decimal[] position = new double[n];

decimal diff = r / n;
decimal current = r1;

for (int i = 0; i < n; i++)
{
    position[i] = current;
    current += diff;
}
于 2012-09-05T13:06:24.110 に答える