C# 中的浮点数和双精度

发布于 2024-09-25 14:15:25 字数 777 浏览 3 评论 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] 

然而, 乘法,给我我一直在跟踪的错误。

我说得对吗? 有什么办法强制这种双精度乘法吗?

谢谢

Having a bit of a problem here on a matrix multiplication code.
I seem to lose precision on large matrices multiplications (my code runs fine on small matrices).

My loop is the following :

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

As you can see, I force a (double) precision to make sure I don't lose precision when multiplying my two floats.

Looking at IL code, I can see two conv.r8 which make me think that IL code has this float-to-double precision conversion in it.

However, when running it and having a look at the disassembly (x86 machine), I see the following :

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] 

It makes me think that JIT has thought that since I'm already multiplying floats, it shouldn't use double precision multiplication but single precision multiplication, giving me the errors I've been tracking.

Am I right ?
Is there any way to force this double precision multiplication ?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

街角迷惘 2024-10-02 14:15:25

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

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

I think you're misinterpreting the assembly. I believe that FMULP always operates on the 80-bit registers. I would be surprised to see the JIT doing the wrong thing here.

I suggest you use my DoubleConverter to write out the precise values before and after the arithmetic. That way you should get a better idea of what's going on.

念﹏祤嫣 2024-10-02 14:15:25

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

You might want to switch to decimal for better precision

浅紫色的梦幻 2024-10-02 14:15:25

首先,有什么原因不能使用十进制吗?小数保持任何数字所需的精度,并且不存在浮点数所具有的烦人的“尾数的最接近的二进制表示”问题,该问题可能导致 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 可能会产生双精度数,但由于您的双精度数是与另一个浮点数进行比较的变相浮点数,因此编译器可能会忽略您所需的精度,“知道”两个浮点数不会产生双精度数。

First, is there any reason you can't use decimal? Decimals maintain the necessary precision of any number, and don't have the annoying "nearest binary representation of the mantissa" problems floats have that can result in x-y = z +- .0000000000...0000001 errors.

From MSDN:

The Decimal value type represents
decimal numbers ranging from positive
79,228,162,514,264,337,593,543,950,335
to negative
79,228,162,514,264,337,593,543,950,335.
The Decimal value type is appropriate
for financial calculations requiring
large numbers of significant integral
and fractional digits and no round-off
errors. The Decimal type does not
eliminate the need for rounding.
Rather, it minimizes errors due to
rounding.

Failing this, try casting both sides to double before multiplying. float * double may result in a double, but as your double is a float in disguise being compared to another float, the compiler may be ignoring your desired precision, "knowing" that two floats won't make a double.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文