为什么Convert.ToDecimal(Double)轮到15位有效数字?
我有一个小数点后的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)
之间的差异?
从Double的文档 :
Double值最多包含15个十进制数字的精度 ,但内部最多保留17位数
因此,由于double值本身最多有15个小数位,将其转换为Decimal将导致Decimal值具有15位有效数字。
舍入的行为保证将具有最多十五个有效数字的任何Decimal
转换为double
并返回到Decimal
将使原始值保持不变。 如果将数值四舍五入到十六位而不是十五位,那么这样的保证不仅不能保持16位数的数字,而且甚至不能保持更短的数值 。 例如,最接近9000.04的Double
值约为9000.040000000000873115; 四舍五入到十六位数将产生9000.040000000001。
四舍五入的选择应该取决于是否将double
值9000.04的最佳Decimal
值视为9000.04m,9000.040000000001m,9000.0400000000008731m,或者其他可能。 微软可能认为除了9000.04m以外的任何表示都会令人困惑。
以下内容来自相关方法的文档。
http://msdn.microsoft.com/en-us/library/a69w9ca0(v=vs.110).aspx
“此方法返回的十进制值最多包含15位有效数字。如果value参数包含超过15位有效数字,则使用舍入舍入为最接近的数字。
每个终止二进制小数都可以精确表示为小数,因此有限数的最小可能差值始终为0. IEEE 754 64位表示的数字正好等于0.1234567890123456634920984242853592149913311004638671875
从二进制浮点到十进制或十进制字符串的每次转换都必须体现一些关于舍入的决定。 从理论上讲,它们可以保留所有数字,但这会导致一些非常长的输出,大多数数字没有什么意义。
在Java的Double.toString中使用的一个选项是停在最短的十进制表示,它将转换回原始的double。
大多数设置了一些相当随意的限 15位有效数字保留最有意义的数字。