关于C#:转换double到decimal不完全正确


Convert Double --> Decimal not exactly

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
What is the difference between Decimal, Float and Double in C#?

帮助我。

我正在用C语言开发一个应用程序。我正在努力:

1
2
3
4
DateTime dtm1 = new DateTime(2012, 11, 15, 11, 3, 0);
DateTime dtm2 = new DateTime(2012, 11, 15, 11, 3, 20);
TimeSpan timespan3 = dtm2 - dtm1;
decimal _Hour = Convert.ToDecimal(timespan3.TotalHours);

当这样做时,输出如下:

1
 _Hour = 0.00555555555555556M

而这并不完全正确,当使用是一种类型的双倍它的输出:

1
2
3
 double _Hour = timespan3.TotalHours;

 output: 0.0055555555555555549

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public decimal tinhDienTichHinhThang(decimal D1, decimal D2, decimal H)
        {
            //tính t?ng 2 ?áy
            decimal tong2Day = D1 + D2;
            //c?ng vào nhan chi?u cao :))
            tong2Day = tong2Day * H;

            //return di?n tích
            return tong2Day / 2;
        }


DateTime dtm1 = new DateTime(2012, 11, 15, 11, 3, 0);
DateTime dtm2 = new DateTime(2012, 11, 15, 11, 3, 20);
TimeSpan timespan3 = dtm2 - dtm1;

///progress
///cal1: _Hour
///cal2: decimal D1 = 0.25
///cal3: decimal D2 = 5
///cal4: decimal D3 = 0.9

decimal test1 = (decimal test1 = Math.Round((D1 + tinhDienTichHinhThang(D2, 0, Convert.ToDecimal(timespan3.TotalHours))) * D3, 3, MidpointRounding.AwayFromZero);

输出:测试1=0.237

如果计算手册:

1
test1 =  Math.Round((0.25 + ((5+0)*timespan3.TotalHours/2))*0.9, 3, MidpointRounding.AwayFromZero);

输出:TEST1=0.238(精确:0.2375)

注:计算Win XP,然后精确到:0.2375但是计算赢7然后不准确。

请向我解释一下为什么要这样解决这个问题?


双精度是浮点值。它们的精度仍然限制在64位,但是它们有一个值和一个指数,这个值被提升到(基本上是科学记数法)这就是为什么它们的范围大于整数或长整数,但是由于这个扩展的范围,它们无法表示该范围内的所有可能值。

小数的位数比双精度数多,所以在转换值时,您只会看到双精度数比小数精度低的副作用。


1
2
3
4
5
decimal test1 = (0.25M + 5M * Convert.ToDecimal(timespan3.TotalHours) / 2M) * 0.9M;

decimal test2 = (decimal)((0.25 + 5 * timespan3.TotalHours / 2) * 0.9);

double test3 = (0.25 + 5 * timespan3.TotalHours / 2) * 0.9;

当执行这样的操作时,它们的输出与下面的不一样。你能指导解决这个问题是不是?


我不知道你有什么问题。但是,如果您对十进制和double中的不同值有问题,那是由设计造成的。默认情况下带浮点的数字不精确。

更新:(在答案中回答您的问题)

因此,你在回答问题时,第一句和第二句陈述不同:

原因

1
5M * Convert.ToDecimal(timespan3.TotalHours)/ 2M

计算采用十进制,但第二:

1
5 * timespan3.TotalHours / 2

计算是双倍的(因为TimeSpan3.TotalHours是双倍的)。这意味着结果可能与第一条语句不同。但是在计算和时,您将它强制转换为十进制,它隐式地将值转换为十进制,这样可以更改值。

在第三个语句中,也有整数值计算,但double是浮点类型,所以它的值可以不同于第二个语句,后者是定点类型decimal。