我想比较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");
}
还是有更好的方法。
答案 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:此参数指定要比较的第二个值