C# .net十进制值1m和1.0000m之间是否存在实际差异?

C# .net十进制值1m和1.0000m之间是否存在实际差异?,c#,.net,decimal,C#,.net,Decimal,.net十进制值1m和1.0000m之间是否存在实际差异 内部存储器不同: 1m : 0x00000001 0x00000000 0x00000000 0x00000000 1.0000m : 0x000186a0 0x00000000 0x00000000 0x00050000 但是,是否存在BCL中的方法会使用“有效数字”知识的情况 我问这个问题是因为我正在研究一种压缩磁盘存储或网络传输的十进制值所需空间的方法,并且正在考虑在存储该值之前对其进行“规范化”,以提高其可压缩性。但是

.net十进制值1m和1.0000m之间是否存在实际差异

内部存储器不同:

1m      : 0x00000001 0x00000000 0x00000000 0x00000000
1.0000m : 0x000186a0 0x00000000 0x00000000 0x00050000
但是,是否存在BCL中的方法会使用“有效数字”知识的情况


我问这个问题是因为我正在研究一种压缩磁盘存储或网络传输的十进制值所需空间的方法,并且正在考虑在存储该值之前对其进行“规范化”,以提高其可压缩性。但是,我想知道它是否有可能导致后续问题。我猜这应该没问题,但这只是因为我没有看到任何方法或属性公开值的精度。有人知道其他情况吗?

我能想到的唯一原因是调用`ToString返回源代码中的精确文本表示

Console.WriteLine(1m); // 1
Console.WriteLine(1.000m); // 1.000

编码差异的原因是因为Decimal数据类型将数字存储为一个整数(96位整数),带有一个用于形成除数以获得小数的刻度。价值本质上是

integer / 10^scale
在内部,十进制类型表示为4 Int32,有关详细信息,请参阅的文档。总之,GetBits返回一个4 Int32的数组,其中每个元素表示十进制编码的后续部分

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.0000m被编码为十进制时,实际表示为
10000/10^4
,而1m被表示为
1/10^0
,数学上相同的值只是编码不同而已

如果您对十进制类型使用本机.NET运算符,并且不亲自操作/比较位/字节,则应该是安全的


您还将注意到,字符串转换还将考虑此二进制表示形式,并生成不同的字符串,因此如果您依赖字符串表示形式,则在这种情况下需要小心。

十进制类型跟踪比例,因为它在算术中很重要。如果你手工对两个数字进行长乘法,例如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


如果有人试图做精度算术,跟踪数值和结果的精度和比例是很重要的,因为它告诉你一些关于结果精度的信息(请注意,精度与准确度不同:用刻度为1/10英寸的尺子测量某事物,你对测量结果的最好评价是,不管你在小数点右边放了多少个尾随零,它最多精确到1/10英寸。另一种说法是这样说的您的测量值最精确,在规定值的+/-5/100范围内。

-1:“ToString”怎么可能了解源代码吗?很有趣。我必须考虑一下我是否关心。@Chaos:胡说八道。找一个更好的解释,但不是那个。你知道.NET中存储源代码信息的任何其他功能吗?不是元数据,而是源代码的实际信息。@John,@Chaos,原因是什么十进制数据类型实际上存储为带除数(小数位数)的整数。因此,当数字1.000m被编码为十进制数据类型时,它被存储为1000,小数位数为3,数字1被存储为小数位数为0的1。我认为每个人都被语义细节绊倒了,@chaosption的意思是,它存储输入源代码时的数字表示,w这是真的。小挑剔:不是字节1,2,3,而是(4字节四重奏)。或者你可以说前12个字节包含整数值。@Matt Brunell,你完全正确!谢谢你,我相应地更正了答案。不幸的是,
十进制
跟踪精度的方式无法可靠地维护有关所涉及数字精度的任何信息。按数字除法非2^n*5^n形式的将产生最大可表示位数,无论这些数字是否表示任何实际精度,并且没有任何迹象表明减法何时会导致灾难性的取消。