How to properly compare decimal values in C#?

C#ComparisonFloating Point

C# Problem Overview


I come from a background in C++, and I know that you cannot accurately compare floats for equality. For C#, I simply assumed the same policy applies to decimal values, or any floating point value in general.

Basically, I have two decimal values and if they are NOT equal to each other, I need to perform some action. e.g.:

decimal value1, value2;
// Assume value1 and value2 are set somewhere to valid values.
if( value1 != value2 )
{
    // Do something
}

If this doesn't work as expected, I'm willing to accept a solution that does an equality comparison with a margin of error, say like .00001 or something like that. What would be the recommended solution to this problem?

C# Solutions


Solution 1 - C#

Your code will work as expected. C# decimals are optimized to be very accurate at representing base 10 numbers, so if that's what you're comparing (money, ...), everything should be fine.

Here's a very clear explanation about the accuracy of decimals by Jon Skeet:

> https://stackoverflow.com/questions/618535/what-is-the-difference-between-decimal-float-and-double-in-c/618596#618596

Solution 2 - C#

I was investigating something similar, but with a precision instead of a margin of error and ended up writing some extensions for Float. This can easily be adapted for any type though. I've got a complicated series of comparisons and this makes it nice and readable.

/// <summary>
/// A set of extensions to allow the convenient comparison of float values based on a given precision.
/// </summary>
public static class FloatingPointExtensions
{
	/// <summary>
	/// Determines if the float value is less than or equal to the float parameter according to the defined precision.
	/// </summary>
	/// <param name="float1">The float1.</param>
	/// <param name="float2">The float2.</param>
	/// <param name="precision">The precision.  The number of digits after the decimal that will be considered when comparing.</param>
	/// <returns></returns>
	public static bool LessThan(this float float1, float float2, int precision)
	{
		return (System.Math.Round(float1 - float2, precision) < 0);
	}

	/// <summary>
	/// Determines if the float value is less than or equal to the float parameter according to the defined precision.
	/// </summary>
	/// <param name="float1">The float1.</param>
	/// <param name="float2">The float2.</param>
	/// <param name="precision">The precision.  The number of digits after the decimal that will be considered when comparing.</param>
	/// <returns></returns>
	public static bool LessThanOrEqualTo(this float float1, float float2, int precision)
	{
		return (System.Math.Round(float1 - float2, precision) <= 0);
	}

	/// <summary>
	/// Determines if the float value is greater than (>) the float parameter according to the defined precision.
	/// </summary>
	/// <param name="float1">The float1.</param>
	/// <param name="float2">The float2.</param>
	/// <param name="precision">The precision.  The number of digits after the decimal that will be considered when comparing.</param>
	/// <returns></returns>
	public static bool GreaterThan(this float float1, float float2, int precision)
	{
		return (System.Math.Round(float1 - float2, precision) > 0);
	}

	/// <summary>
	/// Determines if the float value is greater than or equal to (>=) the float parameter according to the defined precision.
	/// </summary>
	/// <param name="float1">The float1.</param>
	/// <param name="float2">The float2.</param>
	/// <param name="precision">The precision.  The number of digits after the decimal that will be considered when comparing.</param>
	/// <returns></returns>
	public static bool GreaterThanOrEqualTo(this float float1, float float2, int precision)
	{
		return (System.Math.Round(float1 - float2, precision) >= 0);
	}

	/// <summary>
	/// Determines if the float value is equal to (==) the float parameter according to the defined precision.
	/// </summary>
	/// <param name="float1">The float1.</param>
	/// <param name="float2">The float2.</param>
	/// <param name="precision">The precision.  The number of digits after the decimal that will be considered when comparing.</param>
	/// <returns></returns>
	public static bool AlmostEquals(this float float1, float float2, int precision)
	{
		return (System.Math.Round(float1 - float2, precision) == 0);
	} 
}

Solution 3 - C#

I agree with the other answers, but I run into a problem where one "authentic" server-side decimal gets compared with one coming from JSON/browser (and must have been a float at some point).

I ended up with this code to round to 2 digits after the decimal point, which was precise enough in my case:

if (Decimal.Round(serverTotalPrice, 2) != Decimal.Round(request.TotalPrice, 2)) {
    throw new ArgumentException("The submitted Total Price is not valid");
}

Solution 4 - C#

I think this will solve your problem.

Basically there is a decimal.compare method.

EDIT: This may be the better method:

Decimal.Equals

EDIT2: If you can compare directly as suggested above, that may be more efficient. I will leave this as it may be of interest.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionvoid.pointerView Question on Stackoverflow
Solution 1 - C#fretjeView Answer on Stackoverflow
Solution 2 - C#KimView Answer on Stackoverflow
Solution 3 - C#EkusView Answer on Stackoverflow
Solution 4 - C#nycdanView Answer on Stackoverflow