在差异小数双号在C#中的结果转换 [英] Conversion of a decimal to double number in C# results in a difference

查看:110
本文介绍了在差异小数双号在C#中的结果转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题的总结:

有关一些十进制值,当我们转换类型从十进制翻一番,一小部分被添加到结果

For some decimal values, when we convert the type from decimal to double, a small fraction is added to the result.

是什么使得它更糟糕的是,可以有转换时产生不同的双值的两个平等的十进制值。

What makes it worse, is that there can be two "equal" decimal values that result in different double values when converted.

code样品:<​​/ P>

Code sample:

decimal dcm = 8224055000.0000000000m;  // dcm = 8224055000
double dbl = Convert.ToDouble(dcm);    // dbl = 8224055000.000001

decimal dcm2 = Convert.ToDecimal(dbl); // dcm2 = 8224055000
double dbl2 = Convert.ToDouble(dcm2);  // dbl2 = 8224055000.0

decimal deltaDcm = dcm2 - dcm;         // deltaDcm = 0
double deltaDbl = dbl2 - dbl;          // deltaDbl = -0.00000095367431640625

看注释中的结果。结果从调试器的手表复制。
产生这种效果的数字具有十进制数字比数据类型的限制少得多,因此它不能成为一个溢出(我想!)。

Look at the results in the comments. Results are copied from debugger's watch. The numbers that produce this effect have far less decimal digits than the limit of the data types, so it can't be an overflow (I guess!).

是什么使得它更有趣的是,可以有两个等于十进制值(code样品中不同,请参阅DCM和DCM2,用deltaDcm等于零)造成的不同的转换时,双精度值。 (在codeDBL和DBL2,它有一个非零deltaDbl)

What makes it much more interesting is that there can be two equal decimal values (in the code sample above, see "dcm" and "dcm2", with "deltaDcm" equal to zero) resulting in different double values when converted. (In the code, "dbl" and "dbl2", which have a non-zero "deltaDbl")

我想它应该是在这两个数据类型与差异中的数字的按位重新presentation,但无法弄清楚什么!我需要知道怎样做才能使转换我需要它的方式。 (如DCM2​​ - > DBL2)

I guess it should be something related to difference in the bitwise representation of the numbers in the two data types, but can't figure out what! And I need to know what to do to make the conversion the way I need it to be. (like dcm2 -> dbl2)

推荐答案

有趣 - 虽然我一般不信任写出漂浮时,你感兴趣的确切结果点值的正常方式。

Interesting - although I generally don't trust normal ways of writing out floating point values when you're interested in the exact results.

下面是一个稍微简单的演示,使用 DoubleConverter.cs 这是我以前使用过几次。

Here's a slightly simpler demonstration, using DoubleConverter.cs which I've used a few times before.

using System;

class Test
{
    static void Main()
    {
        decimal dcm1 = 8224055000.0000000000m;
        decimal dcm2 = 8224055000m;
        double dbl1 = (double) dcm1;
        double dbl2 = (double) dcm2;

        Console.WriteLine(DoubleConverter.ToExactString(dbl1));
        Console.WriteLine(DoubleConverter.ToExactString(dbl2));
    }
}

结果:

8224055000.00000095367431640625
8224055000

现在的问题是,为什么原来的值(8224055000.0000000000),它是一个整数 - ,准确地重新presentable为双击 - 与额外的数据结束了。我强烈怀疑这是由于在算法怪癖用于从转换成十进制双击,但它是不幸的。

Now the question is why the original value (8224055000.0000000000) which is an integer - and exactly representable as a double - ends up with extra data in. I strongly suspect it's due to quirks in the algorithm used to convert from decimal to double, but it's unfortunate.

这也违反了C#规范的6.2.1:

It also violates section 6.2.1 of the C# spec:

有关从十进制转换为浮动或双,十进制值舍入到
  最近的双重或浮点值。尽管这种转换可能会失去precision,它不会导致
  一个异常被抛出。

For a conversion from decimal to float or double, the decimal value is rounded to the nearest double or float value. While this conversion may lose precision, it never causes an exception to be thrown.

最接近双重价值显然是刚刚8224055000 ...所以这是一个错误海事组织。这不是一个我期望得到固定的任何时间很快,虽然。 (它给的方式在.NET 4.0b1相同的结果。)

The "nearest double value" is clearly just 8224055000... so this is a bug IMO. It's not one I'd expect to get fixed any time soon though. (It gives the same results in .NET 4.0b1 by the way.)

要避免的错误,你可能想先正常化的十进制值,有效地删除小数点后多余的0。这是有点棘手,因为它涉及到96位的整数运算 - 在.NET 4.0 的BigInteger 类可能更容易,但是这可能不是一个选择

To avoid the bug, you probably want to normalize the decimal value first, effectively "removing" the extra 0s after the decimal point. This is somewhat tricky as it involves 96-bit integer arithmetic - the .NET 4.0 BigInteger class may well make it easier, but that may not be an option for you.

这篇关于在差异小数双号在C#中的结果转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆