比较两位小数
Comparing two decimals
我想在 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");
}
或者有没有更好的方法
修正错别字 "var valTwo = decimal.Roung(valueTwo, 6);" 应该是 decimal.Round(....
您还可以使用 Decimal.Equals(dec1, dec2) 或 Decimal.Compare(dec1, dec2)
来比较十进制
你可以做一个函数,做这样的事情
public static bool Check(decimal first, decimal second, decimal margin)
{
return Math.Abs(first - second) <= margin;
}
它会 return 真或假取决于值是否更小或相等
如果您将值四舍五入到小数点后 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");
}
我想如果我不使用 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。小于此的任何内容都可以安全地忽略。我认为这个解决方案很好,但如果有人认为我遗漏了什么,我感谢你的帮助。
谢谢大家
以下对我有用:
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");
}
以上会显示"diff"。
如果改成var valueOne = 1.1234565M;
,差值会小于阈值,所以会显示"equal"。
然后你可以Round
或Truncate
,这取决于你的需要。
编辑:
@tangokhi 刚刚注意到你的回答!你是对的..忽略我的回复。
此答案基于此处投票最高的答案: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!
您必须指定要比较数字的接近程度。 link 给出的答案作为 "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");
}
此方法用于比较两个指定的 Decimal 值。
语法:public static int Compare (decimal a1, decimal a2);
参数:
a1:This 参数指定要比较的第一个值。
a2:This 参数指定要比较的第二个值
我想在 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");
}
或者有没有更好的方法
修正错别字 "var valTwo = decimal.Roung(valueTwo, 6);" 应该是 decimal.Round(....
您还可以使用 Decimal.Equals(dec1, dec2) 或 Decimal.Compare(dec1, dec2)
来比较十进制你可以做一个函数,做这样的事情
public static bool Check(decimal first, decimal second, decimal margin)
{
return Math.Abs(first - second) <= margin;
}
它会 return 真或假取决于值是否更小或相等
如果您将值四舍五入到小数点后 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");
}
我想如果我不使用 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。小于此的任何内容都可以安全地忽略。我认为这个解决方案很好,但如果有人认为我遗漏了什么,我感谢你的帮助。
谢谢大家
以下对我有用:
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");
}
以上会显示"diff"。
如果改成var valueOne = 1.1234565M;
,差值会小于阈值,所以会显示"equal"。
然后你可以Round
或Truncate
,这取决于你的需要。
编辑: @tangokhi 刚刚注意到你的回答!你是对的..忽略我的回复。
此答案基于此处投票最高的答案: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!
您必须指定要比较数字的接近程度。 link 给出的答案作为 "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");
}
此方法用于比较两个指定的 Decimal 值。
语法:public static int Compare (decimal a1, decimal a2);
参数: a1:This 参数指定要比较的第一个值。 a2:This 参数指定要比较的第二个值