比较两位小数

时间:2015-06-09 08:59:26

标签: c# comparison decimal

我想比较c#中的两个小数,但有一些误差。任何人都可以指出以下代码的问题。请注意,我对6个小数位感兴趣,之后我可以忽略这些值。

var valOne = decimal.Round(valueOne, 6);
var valTwo = decimal.Round(valueTwo, 6);
var difference = Math.Abs(valOne - valTwo);
if (difference > 0.0000001m) {
   Console.WriteLine("Values are different");
}
else {
    Console.WriteLine("Values are equal");
}

还是有更好的方法。

7 个答案:

答案 0 :(得分:4)

如果要将值四舍五入到小数点后6位,那么您的epsilon值太小。两个值可以不同的最小量是0.000001。

例如:

var valOne = Decimal.Round(1.1234560M, 6);    // Gives 1.123456
var valTwo = Decimal.Round(1.1234569M, 6);    // Gives 1.123457

if (Math.Abs(valOne - valTwo) >= 0.000001M)
{
    Console.WriteLine("Values differ");
}
else
{
    Console.WriteLine("Values are the same");
}

答案 1 :(得分:1)

以下适用于我:

tblRamos

以上将显示“diff”。

如果更改为var valueOne = 1.1234563M; var valueTwo = 1.1234567M; var diff = Math.Abs(valueOne - valueTwo); //Console.WriteLine(diff); if(diff > 0.0000003M) { Console.WriteLine("diff"); } else { Console.WriteLine("equal"); } ,差异将小于阈值,因此它将显示“相等”。

然后,您可以根据自己的需要var valueOne = 1.1234565M;Round

编辑: @tangokhi刚刚注意到你的答案!你是对的..忽略我的回复。

答案 2 :(得分:1)

此答案基于此处获得最高评价的答案:Floating point comparison functions for C#

在某些情况下,应避免进行直接比较,如here所示。基本上是因为小数可以相等,但实际上在代码中不等于

float a = 0.15 + 0.15
float b = 0.1 + 0.2
if (a == b) { ... } // can be false!
if (a >= b) { ... } // can also be false!

您必须指定要比较数字的接近程度。链接上给出的答案称其为“ Epsilon”,但他们没有详细说明这是位值,范围还是仅仅是给定数字的增量。

以下功能中的“ Epsilon”将数字进行比较,以使其在给定的差异度之内。例如,如果您想使用上面的示例并使其恢复为真,则您希望在0.1之内进行比较,而不是在0.01之内进行比较,就像默认情况下将0.30与0.3比较时所做的那样。

    public static bool nearlyEqual(double a, double b, double epsilon)
    {
        double absA = Math.Abs(a);
        double absB = Math.Abs(b);
        double diff = Math.Abs(a - b);

        if (a == b)
        { 
            // shortcut, handles infinities
            return true;
        }
        else if (a == 0 || b == 0 || diff < Double.Epsilon)
        {
            // a or b is zero or both are extremely close to it
            // relative error is less meaningful here
            return diff < epsilon;
        }
        else
        { 
            // use relative error
            return diff / (absA + absB) < epsilon;
        }
    }

假设您有一个包含项ID和浮点十进制(双精度)数字的项字典,就像一堆纬度...

 Dictionary<int, double> cityLatPoints = new Dictionary<int, double>();

您想知道纬度是否在这些点之一附近...这是您的处理方式:

double epsilon = 0.000005;
List<int> possLatCityIds = new List<int>();  // stores your matching IDs for later
double dblLat = 39.59833333;  // hard-coded value here, but could come from anywhere

// Possible Latitudes
foreach (KeyValuePair<int, double> kvp in cityLatPoints)
{
    if (nearlyEqual(kvp.Value, dblLat, epsilon))
    {
        //Values are the same or similar
        possLatCityIds.Add(kvp.Key);  // ID gets added to the list
    }
}

对于给出的示例,它看起来像这样:

decimal valOne = decimal.Round(valueOne, 6);
decimal valTwo = decimal.Round(valueTwo, 6);
double dblOne = Convert.ToDouble(valOne);
double dblTwo = Convert.ToDouble(valTwo);
double epsilon = 0.0000001;

if (nearlyEqual(dblOne, dblTwo, epsilon))
{
    Console.WriteLine("Values are equal");
}
else
{
    Console.WriteLine("Values are different");
}

答案 3 :(得分:0)

修正拼写错误“var valTwo = decimal.Roung(valueTwo,6);”它应该是decimal.Round(....

您还可以使用Decimal.Equals(dec1,dec2)或Decimal.Compare(dec1,dec2)来比较小数

答案 4 :(得分:0)

你可以做一个功能并做这样的事情

public static bool Check(decimal first, decimal second, decimal margin) 
{ 
    return Math.Abs(first - second) <= margin; 
}

它将返回true或false,具体取决于值是否小于或等于

答案 5 :(得分:0)

我想如果我不使用Round那么这个解决方案很好。

var valOne = 1.1234560M; // Decimal.Round(1.1234560M, 6);  Don't round.
var valTwo = 1.1234569M; // Decimal.Round(1.1234569M, 6);  Don't round

if (Math.Abs(valOne - valTwo) >= 0.000001M) // Six digits after decimal in epsilon
{
    Console.WriteLine("Values differ");
}
else
{
    Console.WriteLine("Values are the same");
}

如上所述,对于六位小数,两位小数可以不同的最小量是0.000001M。可以安全地忽略任何小于此的东西。我认为这个解决方案很好,但如果有人认为我错过了什么,我感谢你的帮助。

全部谢谢

答案 6 :(得分:0)

此方法用于比较两个指定的十进制值。 语法:public static int Compare (decimal a1, decimal a2);

参数: a1:此参数指定要比较的第一个值。 a2:此参数指定要比较的第二个值