-1

使用 C#,知道为什么以下方法返回57.999999999999993(而不是58)吗?

double Test_Null_Coalescing_Operator()
{
    double? x = 0.58;
    return ((x ?? 0) * 100);
}

//returns 57.999999999999993 (instead of 58)
4

4 回答 4

3

假设 double 是 IEEE 754 64 位二进制浮点,0.58 不能精确表示。最接近的是 0.57999999999999996003197111349436454474925994873046875。After multiplying by 100, the rounding error on rounding up to 58 would be 3.99680288865056354552507400512695312500E-15, which is slightly bigger than the rounding error on rounding down to 57.99999999999999289457264239899814128875732421875, 3.10862446895043831318616867065429687500E-15

如果你表示的是长度等物理量,测量误差将完全使舍入误差相形见绌,小于 10 15的一部分。

有一些特殊情况,例如一些财务计算,短终止小数的精确表示很重要。对于那些,您通常应该使用十进制类型,而不是双精度。

于 2018-10-10T03:54:32.063 回答
1

舍入误差。0.58 不作为双精度存在。

于 2018-10-10T03:44:17.220 回答
0

@Felipe Deveza 已经提到了原因。如果你想得到正好 0.58,你可以使用Math.Round()

于 2018-10-10T04:41:27.873 回答
0

答案和链接的副本解释了原因,我只想强调一个经验法则。只要数字的十进制表示是相关的,就使用decimal类型。和类型很快floatdouble因为它们由 CPU 直接支持,但只有在十进制表示不重要时才使用它们(例如渲染、多媒体处理等)。

在许多语言中decimal(或用于相同目的的类似十进制浮点类型)称为货币,这表明您应该将其用于财务计算。实际上,这也是C# 中m后缀的decimal来源(var x = 0.58m)。

于 2018-10-10T05:23:11.983 回答