为什么从双倍到十进制时会丢失数据
本文关键字:数据 十进制 为什么 | 更新日期: 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
可以保存更大的值,因此更准确,那么我如何丢失从double
到decimal
的数据?
这是设计使然。引用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
采取了唯一明智的路线并将它们四舍五入。毕竟,如果您有一个可以精确表示十进制值的类型,则不会希望从不准确的数字开始。
因此,您本身不会丢失数据。事实上,你只是在失去垃圾。你认为是数据的垃圾。
编辑:从评论中澄清我的观点:不同数值数据类型之间的转换可能会导致精度损失。在 double
和 decimal
之间尤其如此,因为这两种类型都能够表示另一种类型无法表示的值。此外,double
和decimal
都有相当具体的用例,这从文档中也很明显(强调我的):
双精度值类型表示双精度 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 (!) 的值差异根本无关紧要。你的温度计在这里给你(让我们慷慨一点)五个准确的数字,你担心之后的十位随机垃圾。只是不要。
我敢肯定,物理学家或其他科学家可能会在这里正确处理测量值及其精度,但我们在学校被教导说,即使给出比测量值更精确的值也是完全胡说八道。计算可能会影响(并降低)该精度。