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;
    }
}

如您所见,我强制使用(双)精度以确保在将两个浮点数相乘时不会丢失精度。

查看 IL 代码,我可以看到两个 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 认为由于我已经在乘以浮点数,它不应该使用双精度乘法而是单精度乘法,这给了我一直在跟踪的错误。

我对吗 ?有没有办法强制这种双精度乘法?

谢谢

4

3 回答 3

3

认为你误解了大会。我相信 FMULP 总是在 80 位寄存器上运行。看到 JIT 在这里做错事,我会感到惊讶。

我建议你用 myDoubleConverter写出算术前后的精确值。这样,您应该更好地了解正在发生的事情。

于 2010-09-29T16:49:02.227 回答
0

您可能想要切换到十进制以获得更好的精度

于 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 的十进制数。Decimal 值类型适用于需要大量有效整数和小数位数且无舍入错误的财务计算。Decimal 类型不会消除舍入的需要。相反,它最大限度地减少了由于四舍五入引起的错误。

如果做不到这一点,请尝试在相乘之前将两边都加倍。float * double 可能会导致双精度,但是由于您的双精度浮点数是伪装的浮点数,与另一个浮点数进行比较,编译器可能会忽略您想要的精度,“知道”两个浮点数不会成为双精度浮点数。

于 2010-09-29T16:47:54.007 回答