System.Decimal 结构

本文提供了此 API 参考文档的补充说明。

Decimal 类型表示十进制数字范围从正 79,228,162,514,264,337,593,543,950,335 到负 79,228,162,514,264,337,593,543,950,335。 默认值 Decimal 为 0。 值 Decimal 类型适用于需要大量重要整数和小数位数且没有舍入错误的财务计算。 Decimal 类型仍需要舍入,但它最大限度地减少了因舍入而导致的错误。 相反,它会最大程度地减少因舍入而导致的错误。 例如,以下代码生成的结果为 0.9999999999999999999999999999999999999999,而不是 1。

decimal dividend = Decimal.One;
decimal divisor = 3;
// The following displays 0.9999999999999999999999999999 to the console
Console.WriteLine(dividend/divisor * divisor);
let dividend = Decimal.One
let divisor = 3m
// The following displays 0.9999999999999999999999999999 to the console
printfn $"{dividend/divisor * divisor}"
Dim dividend As Decimal = Decimal.One
Dim divisor As Decimal = 3
' The following displays 0.9999999999999999999999999999 to the console
Console.WriteLine(dividend/divisor * divisor)

当除法和乘法的结果传递给 Round 方法时,结果不会丢失精度,如以下代码所示。

decimal dividend = Decimal.One;
decimal divisor = 3;
// The following displays 1.00 to the console
Console.WriteLine(Math.Round(dividend/divisor * divisor, 2));
let dividend = Decimal.One
let divisor = 3m
// The following displays 1.00 to the console
printfn $"{Math.Round(dividend/divisor * divisor, 2)}"
Dim dividend As Decimal = Decimal.One
Dim divisor As Decimal = 3
' The following displays 1.00 to the console
Console.WriteLine(Math.Round(dividend/divisor * divisor, 2))

小数是一个浮点值,它由一个符号、一个数值组成,其中值中的每个数字范围为 0 到 9,以及一个缩放因子,指示浮点的位置,用于分隔数值的整型和小数部分。

在二进制表示形式中,Decimal 的值为 128 位,其中包括一个 96 位整数和一组 32 位标志,这些标志用于表示符号和缩放因子等信息,以指定其小数部分的构成。 因此,一个值的二进制表示形式为 ((-2Decimal 到 296) / 10(0 到 28)),其中 -(296-1) 等于 ,而 2MinValue-1 等于 。 有关值的二进制表示形式 Decimal 和示例的详细信息,请参阅 Decimal(Int32[]) 构造函数和 GetBits 方法。

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

转换注意事项

此类型提供将Decimal值转换为SByteInt16Int32Int64ByteUInt16UInt32UInt64值的方法。 从这些整型类型向 Decimal 的扩大转换不会丢失信息或引发异常。

Decimal 转换为任何整型类型都是缩窄转换,这种转换会将 Decimal 值舍入到最近的接近零的整数值。 某些语言(如 C#)还支持将值转换为DecimalChar值。 如果这些转换的结果不能在目标类型中表示, OverflowException 则会引发异常。

Decimal类型还提供用于将Decimal值与Single值和Double值相互转换的方法。 从 Decimal 转换到 SingleDouble 是一种缩小转换,可能会丢失精度,但不会丢失转换后数值大小的信息。 转换不会引发异常。

SingleDoubleDecimal的转换如果无法表示为OverflowException,则会抛出Decimal异常。

对十进制值执行运算

Decimal 类型支持标准数学运算,例如加法、减法、除法、乘法和一元求反。 还可以通过调用Decimal方法直接处理值的GetBits二进制表示形式。

若要比较两个 Decimal 值,可以使用标准数值比较运算符,也可以调用 CompareToEquals 方法。

还可以调用类的成员 Math 来执行各种数值运算,包括获取数字的绝对值、确定两 Decimal 个值的最大值或最小值、获取数字的符号和舍入数字。

例子

下面的代码示例演示了如何使用 Decimal

/// <summary>
/// Keeping my fortune in Decimals to avoid the round-off errors.
/// </summary>
class PiggyBank {
    protected decimal MyFortune;

    public void AddPenny() {
        MyFortune = Decimal.Add(MyFortune, .01m);
    }

    public decimal Capacity {
        get {
            return Decimal.MaxValue;
        }
    }

    public decimal Dollars {
        get {
            return Decimal.Floor(MyFortune);
        }
    }

    public decimal Cents {
        get {
            return Decimal.Subtract(MyFortune, Decimal.Floor(MyFortune));
        }
    }

    public override string ToString() {
        return MyFortune.ToString("C")+" in piggy bank";
    }
}
/// Keeping my fortune in Decimals to avoid the round-off errors.
type PiggyBank() =
    let mutable myFortune = 0m

    member _.AddPenny() =
        myFortune <- Decimal.Add(myFortune, 0.01m)

    member _.Capacity =
        Decimal.MaxValue

    member _.Dollars =
        Decimal.Floor myFortune

    member _.Cents =
        Decimal.Subtract(myFortune, Decimal.Floor myFortune)

    override _.ToString() =
        $"{myFortune:C} in piggy bank"
' Keeping my fortune in Decimals to avoid the round-off errors.
Class PiggyBank
    Protected MyFortune As Decimal

    Public Sub AddPenny()
        MyFortune = [Decimal].Add(MyFortune, 0.01D)
    End Sub

    Public ReadOnly Property Capacity() As Decimal
        Get
            Return [Decimal].MaxValue
        End Get
    End Property

    Public ReadOnly Property Dollars() As Decimal
        Get
            Return [Decimal].Floor(MyFortune)
        End Get
    End Property

    Public ReadOnly Property Cents() As Decimal
        Get
            Return [Decimal].Subtract(MyFortune, [Decimal].Floor(MyFortune))
        End Get
    End Property

    Public Overrides Function ToString() As String
        Return MyFortune.ToString("C") + " in piggy bank"
    End Function
End Class