.net的十进制值1m和0000m之间有什么实际的区别吗?
内部存储不同:
1m : 0x00000001 0x00000000 0x00000000 0x00000000
1.0000m : 0x000186a0 0x00000000 0x00000000 0x00050000
但是,是否存在一种情况,即"有效数字"的知识将被BCL中的方法使用?
我问这个问题是因为我正在研究一种压缩磁盘存储或网络传输所需的十进制值的空间的方法,并且我正在考虑在存储它之前"规范化"值以提高它的可压缩性。但是,我想知道这是否有可能引起问题。我猜它应该没问题,但只是因为我没有看到任何暴露值精度的方法或属性。有人知道吗?
编码差异的原因是Decimal数据类型将数字存储为整数(96位整数),并使用用于形成除数以获得小数的比例。该值本质上是
integer / 10^scale
内部Decimal类型表示为4 Int32,请参阅Decimal文档。GetBits获取更多细节。总之,GetBits返回一个包含4个int32的数组,其中每个元素表示Decimal编码
的后面部分。Element 0,1,2 - Represent the low, middle and high 32 bits on the 96 bit integer
Element 3 - Bits 0-15 Unused
Bits 16-23 exponent which is the power of 10 to divide the integer by
Bits 24-30 Unused
Bit 31 the sign where 0 is positive and 1 is negative
因此,在您的示例中,非常简单地说,当1.000 m被编码为十进制时,实际表示为10000 / 10^4
,而1m在数学上表示为1 / 10^0
,相同的值只是编码不同。
如果您使用本机。net操作符进行十进制类型,并且不自己操作/比较位/字节,则应该是安全的。
您还会注意到字符串转换也会考虑这种二进制表示并产生不同的字符串,因此如果您依赖于字符串表示,则需要小心。
decimal
类型跟踪比例,因为它在算术中很重要。如果你用手做两个数的长乘法—例如,3.14 * 5.00 —结果有6位精度, 比例为4。
要进行乘法运算,忽略小数点(目前)并将这两个数字视为整数。
3.14
* 5.00
------
0000 -- 0 * 314 (0 in the one's place)
00000 -- 0 * 314 (0 in the 10's place)
157000 -- 5 * 314 (5 in the 100's place)
------
157000
给出了未缩放的结果。现在,计算表达式中小数点右侧的位数总数(即4),并将小数点向左插入4位:
15.7000
该结果虽然值与15.7相等,但比值15.7更精确。15.7000的精度为6位,比例为4;15.7的精度为3位,刻度为1。
如果想做精密运算,重要的是要跟踪你的价值观和结果的精度和等级,因为它告诉你一些关于你的结果的精度精度(注意,不是"一样的准确性:用一把尺子衡量的东西毕业差不多一英寸,你能说的最好结果的测量,不管有多少尾随零你把右边的小数点是准确的,在最好的情况下,差不多一英寸。另一种说法是,你的测量结果是准确的,最多在规定值的+/- 5/100以内。
我能想到的唯一原因是调用' ToString返回源代码中的确切文本表示。
Console.WriteLine(1m); // 1
Console.WriteLine(1.000m); // 1.000