为什么Convert.ToDecimal(Double)轮到15位有效数字?

时间:2013-12-10 13:01:50

标签: c# double decimal

我有一个小数点后有17位数的double,即:

double myDouble = 0.12345678901234567;

如果我将此转换为decimal,请执行以下操作:

decimal myDecimal = Convert.ToDecimal(myDouble);

然后根据myDecimal文档将Convert.ToDecimal的值四舍五入为15位数(即0.0123456789012345)。我的问题是,为什么要进行这种舍入?

据我所知,如果我的原始数字可以准确地表示在基数10中并且我试图将其存储为double,那么我们只能对前15位数有信心。最后两位数将受到舍入误差的影响。但是,这是一个基础10偏见的观点。我可以使用double更准确地表示我的号码,并希望将其转换为decimal,同时尽可能保持准确性。

不应Convert.ToDecimal旨在尽量减少myDouble(double)Convert.ToDecimal(myDouble)之间的差异吗?

4 个答案:

答案 0 :(得分:6)

来自documentation of Double

  

Double值最多可达 15位精度的十进制数,但是a   内部维护最多17位数

因此,由于double值本身最多包含15个小数位,因此将其转换为Decimal将导致Decimal值具有15位有效数字。

答案 1 :(得分:3)

舍入的行为可确保将具有最多十五个有效数字的任何Decimal转换为double并返回Decimal将使原始值保持不变。如果将值四舍五入到十六位而不是十五位,那么这样的保证不仅不能保持16位数的数字,而且甚至不能保持更短的值。例如,与9000.04最接近的Double值约为9000.040000000000873115;四舍五入至十六位数将产生9000.040000000001。

应该使用四舍五入的选择取决于将Decimal值9000.04的最佳double值视为9000.04m,9000.040000000001m,9000.0400000000008731m,还是其他内容。微软可能认为除了9000.04m以外的任何代表都会让人感到困惑。

答案 2 :(得分:2)

以下内容来自相关方法的文档。

http://msdn.microsoft.com/en-us/library/a69w9ca0(v=vs.110).aspx

“此方法返回的十进制值最多包含15位有效数字。如果value参数包含超过15位有效数字,则使用舍入舍入为最接近的数字。

答案 3 :(得分:0)

每个终止二进制小数都可以精确表示为小数,因此有限数的最小可能差值始终为0.您的数字的IEEE 754 64位表示形式正好等于0.1234567890123456634920984242853592149913311004638671875

从二进制浮点到十进制或十进制字符串的每次转换都必须体现一些关于舍入的决定。从理论上讲,它们可以保留所有数字,但这会导致一些非常长的输出,大多数数字的含义都很小。

在Java的Double.toString中使用的一个选项是停在最短的十进制表示,它将转换回原来的双精度。

大多数设置了一些相当随意的限制。 15位有效数字保留最有意义的数字。