ZetCode

C# Decimal

last modified October 10, 2020

C# Decimal tutorial shows how to perform high-precision calculation in C# with Decimal. C# tutorial is a comprehensive tutorial on C# language.

Decimal

The decimal is a floating decimal point type. Because the decimal type has more precision and a smaller range than both float and double, it is appropriate for financial and monetary calculations. The default value of a Decimal is 0. The Decimal literal uses m or M suffix. Humans are used to representing non-integers in a decimal form, and expect exact results in decimal representations.

Some values cannot be exactly represented in double/float data types. For instance, storing the 0.1 value in double/float (which are binary floating point values) variable we get only an approximation of the value. Similarly, the 1/3 value cannot be represented exactly in decimal floating point type.

Decimals are much slower than a double/float. Decimals also allow the encoding or trailing zeros.

Neither of the types is perfect; generally, decimal types are better suited for financial and monetary calculations, while the double/float types for scientific calculations.

C# floating point numbers

Floating point numbers represent real numbers in computing. Real numbers measure continuous quantities, like weight, height, or speed. In C# we have three floating point types: float, double, and decimal.

C# Alias .NET Type Size Precision Range
float System.Single 4 bytes 7 digits +-1.5 x 10-45 to +-3.4 x 1038
double System.Double 8 bytes 15-16 digits +-5.0 x 10-324 to +-1.7 x 10308
decimal System.Decimal 16 bytes 28-29 decimal places +-1.0 x 10-28 to +-7.9 x 1028

The above table gives the characteristics of the floating point types.

Note: As a rule of thumb, decimal is used for counted values while float/double for measured values.

C# decimal precision

The decimal type is a 128-bit floating point data type; it can have up to 28-29 significant digits.

The following example compares the precision of the float, double, and the decimal types.

Program.cs
using System;

namespace Precision
{
    class Program
    {
        static void Main(string[] args)
        {
            float x = 1f / 3f;
            double y = 1d / 3d;
            decimal z = 1m / 3m;

            Console.WriteLine(x);
            Console.WriteLine(y);
            Console.WriteLine(z);
        }
    }
}

Value 1/3 is an irrational number; it can be represented only as an approximation.

$ dotnet run
0.33333334
0.3333333333333333
0.3333333333333333333333333333

From the example we can see that decimal has more decimal places after the floating point.

C# decimal literal

The D/d suffix is used for double values, the F/f for float values and the M/m decimal values. Floating point values without a suffix are double.

Program.cs
using System;

namespace Floats
{
    class Program
    {
        static void Main(string[] args)
        {
            float n1 = 1.234f;
            double n2 = 1.234;
            decimal n3 = 1.234m;

            Console.WriteLine(n1);
            Console.WriteLine(n2);
            Console.WriteLine(n3);

            Console.WriteLine(n1.GetType());
            Console.WriteLine(n2.GetType());
            Console.WriteLine(n3.GetType());
        }
    }
}

In the example, we use three different literal notations for floating point numbers.

$ dotnet run
1.234
1.234
1.234
System.Single
System.Double
System.Decimal

This is the output.

C# decimal for exact financial or monetary calculations

Finalcial and monetary calculations must be exact.

Program.cs
using System;

namespace ExactCalc
{
    class Program
    {
        static void Main(string[] args)
        {
            double x = 0.1 + 0.1 + 0.1;
            double y = 0.3;

            Console.WriteLine(x);
            Console.WriteLine(y);
            Console.WriteLine(x == y);

            decimal u = 0.1m + 0.1m + 0.1m;
            decimal v = 0.3m;

            Console.WriteLine(u);
            Console.WriteLine(v);
            Console.WriteLine(u == v);
        }
    }
}

This example shows that values 0.1 can be represented exactly in decimal type.

$ dotnet run
0.30000000000000004
0.3
False
0.3
0.3
True

The double value has some small error. It can be ignored in many calculations. For instance, if we are measuring weight or height of people, this kind of error is irrelevant. However, in finalcial calculations it causes problems.

C# decimal System.OverflowException

Unlike in double/float types, trying to increse a decimal value beyond its limit causes System.OverflowException.

Program.cs
using System;

namespace Overflow
{
    class Program
    {
        static void Main(string[] args)
        {
            float maxValue = float.MaxValue;
            float nextValue = maxValue + 1f;

            Console.WriteLine(maxValue.ToString("f"));
            Console.WriteLine(nextValue.ToString("f"));

            decimal maxValue2 = decimal.MaxValue;
            decimal nextValue2 = maxValue2 + 1m;

            Console.WriteLine(maxValue.ToString("m"));
            Console.WriteLine(nextValue.ToString("m"));
        }
    }
}

In the exammple, we add one to the maximal value of a float and a decimal.

$ dotnet run 
340282346638528859811704183484516925440.000
340282346638528859811704183484516925440.000 
Unhandled exception. System.OverflowException: Value was either too large or too 
small for a Decimal.
...

The example throws the System.OverflowException.

C# decimal Parse

The Parse method converts the string representation of a number to its decimal equivalent.

numbers.txt
123.23
213.44
713.54
319.11
199.09

We have this numbers.txt file.

Program.cs
using System;
using System.IO;

namespace SumEx
{
    class Program
    {
        static void Main(string[] args)
        {
            var values = File.ReadAllLines("numbers.txt");

            decimal sum = 0m;

            foreach (var value in values)
            {
                sum += decimal.Parse(value);
            } 

            Console.WriteLine($"The sum is: {sum}");
        }
    }
}

In the example, we read all values from the numbers.txt file.

var values = File.ReadAllLines("numbers.txt");

The ReadAllLines returns a string array. We need to trasform the strings into decimal values.

foreach (var value in values)
{
    sum += decimal.Parse(value);
} 

We go throug the array and parse the strings into decimals with Parse.

$ dotnet run
The sum is: 1568.41

This is the output.

C# decimal built-in methods

The decimal type has some built-in methocs such as Add or Subtract.

Program.cs
using System;

namespace DecimalMethods
{
    class Program
    {
        static void Main(string[] args)
        {
            decimal x = 12m;
            decimal y = 5m;
            decimal z = 12.89m;

            Console.WriteLine(decimal.Remainder(x, y));
            Console.WriteLine(decimal.Add(x, y));
            Console.WriteLine(decimal.Subtract(x, y));
            Console.WriteLine(decimal.Round(z, 1));
        }
    }
}

The example demonstrates the Remainder, Add, Subtract, and Round methods.

$ dotnet run
2
17
7
12.9

This is the output.

In this tutorial we have worked with Decimal data type in C#.

Read C# tutorial or list all C# tutorials.