Decimal
This type accurately stores numeric data. In some C# programs (like those with financial data) rounding errors are harmful—decimal helps.
Decimal
stores large and small numbers with many digits after the decimal place. We access methods like decimal.Ceiling
and Floor
.
Decimal
values require 16 bytes. The decimal type is a value type—it requires more memory than most other value types used commonly in C#.
GC.GetTotalMemory
method is used to determine memory usage.sizeof
(decimal), we see that it returns the integer 16.using System; const int _count = 1000000; // One million decimals long bytes1 = GC.GetTotalMemory(true); // Part 1: allocate an array of decimal values. // ... Assign an element to make the allocation not optimized out. decimal[] array = new decimal[_count]; long bytes2 = GC.GetTotalMemory(true); array[1] = 0.1M; // Part 2: compute the memory usage of the decimal type. long difference = bytes2 - bytes1; double per = (double)difference / _count; Console.WriteLine("Program used: {0:0.0} MB", (double)difference / (1024 * 1024)); Console.WriteLine("Each decimal element required: {0:0.0} bytes", per);Program used: 15.3 MB Each decimal element required: 16.0 bytes
Decimal
is a value type. It can be manipulated with the standard numeric operators in the C# language. These include the plus, minus, multiply and divide operators.
Console
.using System; decimal d = 1.0M; // Test decimal. if (d == 1.0M) { Console.WriteLine(d); } decimal y = 0.5M; // Add decimal. y += d; Console.WriteLine(y); // Subtract and multiply decimal. y -= (d * 2); Console.WriteLine(y);1.0 1.5 -0.5
If you want to know the maximum or minimum value, access the MaxValue
and MinValue
constants. You can also use the One, Zero, and MinusOne
constants.
using System; Console.WriteLine(decimal.MaxValue); Console.WriteLine(decimal.MinValue); Console.WriteLine(decimal.One); Console.WriteLine(decimal.Zero); Console.WriteLine(decimal.MinusOne);79228162514264337593543950335 -79228162514264337593543950335 1 0 -1
Floor
, Ceiling
When using decimal, you should call methods available on the decimal class
instead of those in the Math class
for accuracy reasons.
Ceiling
is the integer above the number and the floor is the integer below the number.using System; Console.WriteLine(decimal.Ceiling(1.1M)); Console.WriteLine(decimal.Floor(1.1M));2 1
To improve the clarity of decimal manipulations, you can use the Add, Multiply, Subtract and Divide methods. Each of these methods receives two arguments.
using System; Console.WriteLine(decimal.Add(1.1M, 1.3M)); // Add Console.WriteLine(decimal.Multiply(5.0M, 2.0M)); // Five times two Console.WriteLine(decimal.Subtract(2.0M, 1.0M)); // Two minus one Console.WriteLine(decimal.Divide(10M, 2M)); // Ten divided by two2.4 10.00 1.0 5
When doing important computations with money, you may want to get the remainder of a division. The remainder is the part left over after the division completes.
Remainder()
method. We show that the remainder of 2 divided by 1.5 is 0.5.using System; // Remainder of 2 divided by 1.5 is 0.5 Console.WriteLine(decimal.Remainder(2.0M, 1.5M));0.5
This method erases all the numbers after the decimal place. It doesn't take into consideration whether the number would be rounded up or rounded down.
int
), but has different behavior on values that cannot be represented with int
.using System; // Truncate removes the digits after the decimal place. Console.WriteLine(decimal.Truncate(4.55M));4
Negate makes positive decimals negative, and makes negative decimals positive. You could duplicate this functionality by multiplying by negative one.
using System; // Makes positive numbers negative, and negative numbers positive. Console.WriteLine(decimal.Negate(1.5M)); Console.WriteLine(decimal.Negate(-1.5M));-1.5 1.5
MidpointRounding
The decimal.Round
method by default rounds down or up to the specified decimal place. You can specify the MidpointRounding
to further define the required behavior.
ToEven
value means that when a number needs to be rounded, it is always rounded to the nearest even number.AwayFromZero
value means that numbers are rounded up for positive numbers and down for negative numbers.using System; // Round to one decimal place. Console.WriteLine(decimal.Round(1.59M, 1)); // Demonstrate MidpointRounding enumeration. Console.WriteLine(decimal.Round(2.5M, 0, MidpointRounding.ToEven)); Console.WriteLine(decimal.Round(2.5M, 0, MidpointRounding.AwayFromZero));1.6 2 3
Parse
, TryParse
The decimal.Parse
method will throw an exception if you feed it an incorrectly-formatted value. TryParse
will handle errors by returning a false value.
Parse
if you expect all input will be correct, and TryParse
if you expect errors to be common.using System; // Use Parse on arguments that are always correct. decimal value = decimal.Parse("100.01"); Console.WriteLine(value); // Use TryParse when errors are expected. decimal value2; if (decimal.TryParse("perl", out value2)) { Console.WriteLine("Not reached"); }100.01
It is sometimes wasteful to store many decimals. You can use the "To" methods on the decimal type to convert to smaller memory representations of the number.
using System; const decimal input = 5; // Convert this decimal into other compatible types. Console.WriteLine(decimal.ToByte(input)); Console.WriteLine(decimal.ToDouble(input)); Console.WriteLine(decimal.ToInt16(input)); Console.WriteLine(decimal.ToInt32(input)); Console.WriteLine(decimal.ToInt64(input)); Console.WriteLine(decimal.ToSByte(input)); Console.WriteLine(decimal.ToSingle(input)); Console.WriteLine(decimal.ToUInt16(input)); Console.WriteLine(decimal.ToUInt32(input)); Console.WriteLine(decimal.ToUInt64(input));5 5 5 5 5 5 5 5 5 5
FromOACurrency
, ToOACurrency
Decimal
provides FromOACurrency
and ToOACurrency
. FromOACurrency
receives an OA value and converts it into a decimal.
ToOACurrency
takes a decimal and converts it into an OA value. OA values are a Microsoft-specific encoding.The decimal type is a powerful and accurate representation for number data in memory. It is valuable for representing important quantities like amounts of money.