在幕后,C#/ .NET中十进制值类型发生了什么?

如何实现decimal类型?

更新

  • 它是128位值类型(16字节)
  • 1个符号位
  • 尾数为96位(12字节)
  • 指数为8位
  • 剩余的比特(其中23个!)设置为0

谢谢! 我会坚持使用我自己的隐含比例的64位长。

维基百科上的Decimal Floating Point文章,其中包含有关System.Decimal本文的特定链接。

十进制存储在128位中,即使只有102也是必需的。 将十进制视为表示尾数的三个32位整数,然后是表示符号和指数的一个整数是很方便的。 最后一个整数的最高位是符号位(以正常方式,位为负数设置(1))和位16-23(高16位字的低位)包含指数。 其他位必须全部清零(0)。 这种表示forms是decimal.GetBits(十进制)给出的表示,它返回一个4个整数的数组。

如MSDN的Decimal Structure页面所述, url为http://msdn.microsoft.com/en-us/library/system.decimal(VS.80).aspx :

Decimal值的二进制表示由1位符号,96位整数和用于划分96位整数的比例因子组成,并指定它的小数部分。 缩放因子隐式为数字10,从0到28的指数上升。因此,Decimal值的二进制表示forms为(( – 296到296)/ 10(0到28)),其中-296-1等于MinValue,296-1等于MaxValue。

缩放因子还保留十进制数中的任何尾随零。 尾随零不影响算术或比较运算中的十进制数的值。 但是,如果应用了适当的格式字符串,则ToString方法可以显示尾随零。

来自C#语言规范 :

decimal类型是128位数据类型,适用于财务和货币计算。
decimal类型可以表示从1.0×10 -28到大约7.9×10 28的值,具有28-29个有效数字。

decimal类型的有限值集合的forms为(-1) s × c ×10 e ,其中符号s为0或1,系数c由0≤c<2 96给出 ,并且标度e是0≤e≤28。
decimal类型不支持带符号的零,无穷大或NaN。 decimal表示为以10的幂为单位缩放的96位整数。 对于绝对值小于1.0m的小数,该值精确到小数点后28位,但不再进一步。

对于绝对值大于或等于1.0m的小数,该值精确到28或29位。 与floatdouble数据类型相反,十进制小数(如0.1)可以用十进制表示forms表示。 在floatdouble表示中,这些数字通常是无限分数,使得这些表示更容易出现舍入错误。

如果二元运算符的一个操作数是decimal类型,则另一个操作数必须是整数类型或decimal类型。 如果存在整数类型操作数,则在执行操作之前将其转换为decimal

decimal类型值的操作结果是计算精确结果(保留每个运算符定义的比例)然后舍入以适合表示forms的结果。 结果四舍五入到最接近的可表示值,并且当结果等于两个可表示的值时,结果四舍五入到在最低有效数字位置具有偶数的值(这称为“银行家舍入”)。 零结果始终具有0的符号和0的标度。

如果十进制算术运算产生的绝对值小于或等于5×10 -29 ,则运算结果为零。 如果十进制算术运算产生的结果对于decimal格式而言太大,则抛出System.OverflowException

decimal类型具有比浮点类型更高的精度但更小的范围。 因此,从浮点类型到decimal转换可能会产生溢出exception,从decimal到浮点类型的转换可能会导致精度损失。 由于这些原因,浮点类型和decimal之间不存在隐式转换,如果没有显式转换,则不可能在同一表达式中混合浮点和decimal操作数。

来自J.Richter的“CLR via C#”第3版:

通常用于财务计算的128位高精度浮点值,其中不能容忍舍入误差。 在128位中,1位表示值的符号,96位表示值本身,8位表示将96位值除以10的幂(可以是0到28之间的任何值)。 其余位未使用。

decimal关键字表示128位数据类型。

资源

Decimal值的二进制表示由1位符号,96位整数和用于划分96位整数的比例因子组成,并指定它的小数部分。 缩放因子隐式为数字10,从0到28的指数上升。因此,Decimal值的二进制表示forms为(( – 296到296)/ 10(0到28)),其中-296-1等于MinValue,296-1等于MaxValue。

资源

十进制类型只是浮点数的另一种forms – 但与float和double不同,使用的基数为10。

一个简单的解释是http://csharpindepth.com/Articles/General/Decimal.aspx