简体   繁体   English

C#中的浮点数和双精度

[英]Float and double precision in c#

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. 如您所见,我强制执行(double)精度以确保两个浮点数相乘时不会失去精度。

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. 查看IL代码,我可以看到两个conv.r8,它们使​​我认为IL代码中具有浮点到双精度转换。

However, when running it and having a look at the disassembly (x86 machine), I see the following : 但是,在运行它并查看反汇编(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] 

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. 这让我觉得JIT一直认为,由于我已经在乘以浮点数,因此它不应该使用双精度乘法,而应该使用单精度乘法,这给了我一直在跟踪的错误。

Am I right ? 我对吗 ? Is there any way to force this double precision multiplication ? 有什么办法可以强制这种双精度乘法吗?

Thanks 谢谢

I think you're misinterpreting the assembly. 认为您在误解大会。 I believe that FMULP always operates on the 80-bit registers. 我相信FMULP始终在80位寄存器上运行。 I would be surprised to see the JIT doing the wrong thing here. 看到JIT在这里做错了事,我会感到惊讶。

I suggest you use my DoubleConverter to write out the precise values before and after the arithmetic. 我建议您使用我的DoubleConverter在算术前后写出精确的值。 That way you should get a better idea of what's going on. 这样,您应该对发生的事情有更好的了解。

您可能需要切换到十进制以提高精度

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 xy = z +- .0000000000...0000001 errors. 小数保持任何数字的必要精度,并且没有令人讨厌的“浮点数的最近二进制表示”问题,浮点数会导致xy = z +-.0000000000 ... 0000001错误。

From MSDN: 从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. 十进制值类型表示十进制数,范围从正数79,228,162,514,264,337,593,543,950,335到负数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. float * double可能会导致加倍,但是由于double是与另一个float相比变相的float,因此编译器可能会忽略您所需的精度,“知道”两个float不会成为double。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM