为什么从双倍到十进制时会丢失数据

本文关键字:数据 十进制 为什么 | 更新日期: 2023-09-27 18:37:00

>我有以下代码无法更改...

 public static decimal Convert(decimal value, Measurement currentMeasurement, Measurement targetMeasurement,  bool roundResult = true)
 {
     double result = Convert(System.Convert.ToDouble(value), currentMeasurement, targetMeasurement, roundResult);
     return System.Convert.ToDecimal(result);
 }

现在result作为-23.333333333333336返回,但是一旦转换为decimal,它就会变得-23.3333333333333M

我认为decimal可以保存更大的值,因此更准确,那么我如何丢失从doubledecimal的数据?

为什么从双倍到十进制时会丢失数据

这是设计使然。引用Convert.ToDecimal的文档:

此方法返回的十进制值最多包含 15 位有效数字。如果 value 参数包含超过 15 个 有效数字,它使用四舍五入到最接近。这 下面的示例说明了 Convert.ToDecimal(Double) 方法如何 使用舍入到最接近返回一个 15 的十进制值 有效数字。

Console.WriteLine(Convert.ToDecimal(123456789012345500.12D));  // Displays 123456789012346000
Console.WriteLine(Convert.ToDecimal(123456789012346500.12D));  // Displays 123456789012346000
Console.WriteLine(Convert.ToDecimal(10030.12345678905D));      // Displays 10030.123456789 
Console.WriteLine(Convert.ToDecimal(10030.12345678915D));      // Displays 10030.1234567892

这样做的原因主要是double无论如何只能保证 15 位十进制的精度。在它们之后显示的所有内容(转换为字符串,它是 17 位数字,因为这是double内部使用的,并且因为这是从字符串中准确重建每个可能的double值可能需要的数字)不能保证是所表示的确切值的一部分。因此,Convert采取了唯一明智的路线并将它们四舍五入。毕竟,如果您有一个可以精确表示十进制值的类型,则不会希望从不准确的数字开始。

因此,您本身不会丢失数据。事实上,你只是在失去垃圾。你认为是数据的垃圾。

编辑:从评论中澄清我的观点:不同数值数据类型之间的转换可能会导致精度损失。在 doubledecimal 之间尤其如此,因为这两种类型都能够表示另一种类型无法表示的值。此外,doubledecimal都有相当具体的用例,这从文档中也很明显(强调我的):

精度值类型表示双精度 64 位数字 值范围从负 1.79769313486232e308 到正 1.79769313486232e308,以及正零或负零、正无穷大、负无穷大,而不是数字 (NaN)。是的 旨在表示非常大的值(例如 行星或星系之间的距离)或极小( 物质的分子量(以千克为单位),这通常是 不精确(例如从地球到另一个太阳系的距离)。 双型符合IEC 60559:1989(IEEE 754)标准 用于二进制浮点运算。

十进制值类型表示十进制数,范围从 正 79,228,162,514,264,337,593,543,950,335 至负 79,228,162,514,264,337,593,543,950,335。 十进制值类型为 适用于需要大量 有效的整数和小数,没有舍入误差。 十进制类型不会消除舍入的需要。相反,它 最大限度地减少由于舍入引起的错误。

这基本上意味着,对于不会变得不合理的大并且您需要准确的十进制表示的数量,您应该使用decimal(以这种方式编写时听起来相当明显)。在实践中,这通常意味着财务计算,正如文档已经指出的那样。

另一方面,在绝大多数其他情况下,double是正确的选择,通常不会作为默认选择受到伤害(像Lua和JavaScript这样的语言很好,double是唯一的数字数据类型)。

在您的特定情况下,由于您在评论中提到这些是温度读数,因此非常、非常、非常简单:只需始终使用double即可。你有温度读数。维基百科建议高度专业化的温度计达到10-3°C左右的精度。这基本上意味着您在这里担心的大约 10−13 (!) 的值差异根本无关紧要。你的温度计在这里给你(让我们慷慨一点)五个准确的数字,你担心之后的十位随机垃圾。只是不要。

我敢肯定,物理学家或其他科学家可能会在这里正确处理测量值及其精度,但我们在学校被教导说,即使给出比测量值更精确的值也是完全胡说八道。计算可能会影响(并降低)该精度。