0

ここで行列乗算コードに少し問題があります。大きな行列の乗算では精度が低下するようです(私のコードは小さな行列で正常に実行されます)。

私のループは次のとおりです:

for (int j = 0; j < columns; j++)
{
    float[] column = otherMatrix.Column(j);
    for (int i = 0; i < rows; i++)
    {
        double s = 0;
        for (int k = 0; k < size; k++)
            s += this[i,k] * ((double) column[k]);
        result[i, j] = (float)s;
    }
}

ご覧のとおり、2つの浮動小数点数を乗算するときに精度が失われないように、(倍精度)精度を強制します。

ILコードを見ると、2つのconv.r8があり、ILコードにはこの浮動小数点から倍精度への変換が含まれていると思います。

ただし、それを実行して逆アセンブル(x86マシン)を見ると、次のように表示されます。

0000024e  fld         dword ptr [edx+eax*4+8] 
00000252  fmulp       st(1),st 
00000254  fadd        qword ptr [ebp-64h] 
00000257  fstp        qword ptr [ebp-20h] 

JITは、すでにfloatを乗算しているので、倍精度乗算ではなく単精度乗算を使用する必要があると考えており、追跡しているエラーが発生していると思います。

私は正しいですか?この倍精度乗算を強制する方法はありますか?

ありがとう

4

3 に答える 3

3

アセンブリを誤って解釈していると思います。FMULPは常に80ビットレジスタで動作すると思います。ここでJITが間違ったことをしているのを見て驚かれることでしょう。

算術の前後の正確なDoubleConverter値を書き出すためにmyを使用することをお勧めします。そうすれば、何が起こっているのかをよりよく理解できるはずです。

于 2010-09-29T16:49:02.227 に答える
0

精度を上げるために10進数に切り替えることをお勧めします

于 2010-09-29T16:41:12.840 に答える
0

まず、小数が使えない理由はありますか?小数は任意の数の必要な精度を維持し、浮動小数点数がxy = z +-.0000000000...0000001エラーを引き起こす可能性のある厄介な「仮数の最も近いバイナリ表現」の問題を抱えていません。

MSDNから:

Decimal値タイプは、正の79,228,162,514,264,337,593,543,950,335から負の79,228,162,514,264,337,593,543,950,335までの範囲の10進数を表します。10進値タイプは、多数の重要な整数および小数桁を必要とし、丸め誤差がない財務計算に適しています。Decimalタイプは、丸めの必要性を排除しません。むしろ、丸めによるエラーを最小限に抑えます。

これに失敗した場合は、乗算する前に両側を2倍にキャストしてみてください。float * doubleはdoubleになる可能性がありますが、doubleは別のfloatと比較される偽装のfloatであるため、コンパイラは2つのfloatがdoubleにならないことを「認識」して、目的の精度を無視している可能性があります。

于 2010-09-29T16:47:54.007 に答える