decimal (C# Reference)
The decimal keyword indicates a 128-bit data type. Compared to floating-point types, the decimal type has more precision and a smaller range, which makes it appropriate for financial and monetary calculations. The approximate range and precision for the decimal type are shown in the following table.
Type | Approximate Range | Precision | .NET Framework type |
|---|---|---|---|
decimal | (-7.9 x 1028 to 7.9 x 1028) / (100 to 28) | 28-29 significant digits |
The integral types are implicitly converted to decimal and the result evaluates to decimal. Therefore you can initialize a decimal variable using an integer literal, without the suffix, as follows:
decimal myMoney = 300;
There is no implicit conversion between floating-point types and the decimal type; therefore, a cast must be used to convert between these two types. For example:
decimal myMoney = 99.9m; double x = (double)myMoney; myMoney = (decimal)x;
You can also mix decimal and numeric integral types in the same expression. However, mixing decimal and floating-point types without a cast causes a compilation error.
For more information about implicit numeric conversions, see Implicit Numeric Conversions Table (C# Reference).
For more information about explicit numeric conversions, see Explicit Numeric Conversions Table (C# Reference).
You can format the results by using the String.Format method, or through the Console.Write method, which calls String.Format(). The currency format is specified by using the standard currency format string "C" or "c," as shown in the second example later in this article. For more information about the String.Format method, see String.Format.
In this example, a decimal and an int are mixed in the same expression. The result evaluates to the decimal type.
The following example uses a statement that tries to add the double and decimal variables:
double x = 9; Console.WriteLine(d + x); // Error
The result is the following error:
Operator '+' cannot be applied to operands of type 'double' and 'decimal'
In this example, the output is formatted by using the currency format string. Notice that x is rounded because the decimal places exceed $0.99. The variable y, which represents the maximum exact digits, is displayed exactly in the correct format.
public class TestDecimalFormat { static void Main() { decimal x = 0.999m; decimal y = 9999999999999999999999999999m; Console.WriteLine("My amount = {0:C}", x); Console.WriteLine("Your amount = {0:C}", y); } } /* Output: My amount = $1.00 Your amount = $9,999,999,999,999,999,999,999,999,999.00 */
For more information, see the C# Language Specification. The language specification is the definitive source for C# syntax and usage.
using System; using System.Globalization;
using System.Runtime;
using System.Runtime.Serialization;
using System.Security;
// currency value types:
namespace Currency
{
[Serializable]
public struct CAD : IComparable, IFormattable, IConvertible, ISerializable, IComparable<CAD>, IEquatable<CAD>
{
/* constructors... */
/* properties */
public long WholeNumbers
{
get;
}
public long DigitsAfterDecimal
{
get;
}
// other properties and fields...
/* operators */
public static CAD operator +(CAD cad1, CAD cad2);
public static CAD operator +(CAD cad, USD usd);
public static CAD operator +(CAD cad, decimal m);
public static CAD operator +(CAD cad, double d);
public static CAD operator +(CAD cad, float f);
public static CAD operator +(CAD cad, object o);
// other operators...
/* other methods... */
}
[Serializable]
public struct USD : IComparable, IFormattable, IConvertible, ISerializable, IComparable<USD>, IEquatable<USD>
{
/* constructors... */
/* properties */
public long WholeNumbers
{
get;
}
public long DigitsAfterDecimal
{
get;
}
// other properties and fields...
/* operators... */
/* other methods... */
}
/* other structs of currency value types... */
}
- 1/5/2012
- Nevin Janzen
- 3/5/2012
- Nevin Janzen
EDIT:
See below for ideas for currency value types you can create yourself.
[tfl - 22 01 12] Hi - and thanks for your post. Community content is not the appropriate place for technical support queries. Instead,
you should visit the Technet Forums at http://forums.microsoft.com/technet, where such posts are welcomed and where you stand a much
better chance of getting your query resolved. Sorry if that's not the answer you wanted to hear.
- 12/7/2011
- C Tierney
- 1/24/2012
- Thomas Lee
* "A zero result always has a sign of 0 and a scale of 0." (paragraph 4.1.7)
* "For decimal, the default value is 0.0m." (paragraph 4.1.2)
* "Any scale apparent in the literal is preserved unless the value is rounded or the value is zero (in which latter case the sign and scale will be 0)." (paragraph 2.4.4.3)
I does not look like these specifications are met with the current implementation of Visual C# and .NET. Here is one example:
decimal a;
a = 0.0m;
Console.WriteLine(a); // outputs 0.0
a = default(decimal);
Console.WriteLine(a); // outputs 0
a = new decimal();
Console.WriteLine(a); // outputs 0
Why are there zeros with different scales, and why is the default value not 0.0m?
Another example is:
decimal x = 2.3000m;
decimal y = -2.3000m;
decimal b = x + y;
Console.WriteLine(b); // outputs 0.0000
The result b has a positive scale (trailing zeros after the decimal point).
/JeppeSN
Edit by SJ at MSFT: Thanks for pointing this out. I have forwarded the issue to the developers for resolution. I'll keep an eye on it to see what happens.
- 9/15/2011
- JeppeSN1
- 9/28/2011
- SJ_at_MSFT