C++ 比较双打
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4010240/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Comparing doubles
提问by Capkutay
I'm writing a program that consists of a while loop that reads two doubles and prints them. The program also prints what the larger number is and what the smaller number is.
我正在编写一个程序,它由一个 while 循环组成,该循环读取两个双精度并打印它们。该程序还打印较大的数字和较小的数字。
this is the code i have so far.
这是我到目前为止的代码。
int main()
{
// VARIABLE DECLARATIONS
double a;
double b;
while (a,b != '|') //WHILE A & B DO NOT EQUAL '|'
{
cin >>a >>b;
cout << a << b << "\n" ;
if (a<b) //IF A<B: SMALLER VALUE IS A
cout << "The smaller value is:" << a << endl
<< "The larger value is:" << b << endl ;
else if (b<a) //ELSE IF B<A
cout << "The smaller value is:" << b << endl
<< "The larger value is:" << a << endl ;
else if (b==a)
cout << "The two numbers you entered are equal." << "\n" ;
}
}
The next step is having the program write out "the numbers are almost equal" if the two numbers differ by less than 1.0/10000000. How would I do this?
下一步是让程序写出“数字几乎相等”,如果两个数字相差小于 1.0/10000000。我该怎么做?
回答by Michael Goldshteyn
Here is how I would test for equality, without a "fudge factor":
这是我如何测试平等,没有“捏造因素”:
if (
// Test 1: Very cheap, but can result in false negatives
a==b ||
// Test 2: More expensive, but comprehensive
std::abs(a-b)<std::abs(std::min(a,b))*std::numeric_limits<double>::epsilon())
std::cout << "The numbers are equal\n";
Explanation
解释
The first test is a simple comparison. Of course we all know that comparing double precision values can result in them being deemed unequal, even when they are logically equivalent.
第一个测试是一个简单的比较。当然,我们都知道比较双精度值会导致它们被视为不相等,即使它们在逻辑上是相等的。
A double precision floating point value can hold the most significant fifteen digits of a number (actually ≈15.955digits). Therefore, we want to call two values equal if (approximately) their first fifteen digits match. To phrase this another way, we want to call them equal if they are within one scaled epsilon of each other. This is exactly what the second test computes.
双精度浮点值可以容纳一个数字的最高 15 位数字(实际上≈15.955位数字)。因此,如果(大约)前 15 位数字匹配,我们希望两个值相等。换句话说,如果它们在彼此的一个缩放 epsilon 之内,我们想称它们为相等。这正是第二个测试计算的内容。
You can choose to add more leeway than a single scaled epsilon, due to more significant floating point errors creeping in as a result of iterative computation. To do this, add an error factor to the right hand side of the second test's comparison:
您可以选择添加比单个缩放 epsilon 更大的余量,因为迭代计算会导致更显着的浮点错误。为此,请在第二个测试比较的右侧添加一个误差因子:
double error_factor=2.0;
if (a==b ||
std::abs(a-b)<std::abs(std::min(a,b))*std::numeric_limits<double>::epsilon()*
error_factor)
std::cout << "The numbers are equal\n";
I cannot give you a fixed value for the error_factor
, since it will depend on the amount of error that creeps into your computations. However, with some testing you should be able to find a reasonable value that suits your application. Do keep in mind that adding an (arbitrary) error factor based on speculation alone will put you right back into fudge factor territory.
我不能给你一个固定的值error_factor
,因为它取决于你计算中的错误量。但是,通过一些测试,您应该能够找到适合您应用的合理值。请记住,仅根据推测添加(任意)误差因子将使您重新回到捏造因子领域。
Summary
概括
You can wrap the following test into a(n inline) function:
您可以将以下测试包装到 (n inline) 函数中:
inline bool logically_equal(double a, double b, double error_factor=1.0)
{
return a==b ||
std::abs(a-b)<std::abs(std::min(a,b))*std::numeric_limits<double>::epsilon()*
error_factor;
}
回答by Billy ONeal
std::abs(a - b) < 0.000001
std::abs(a - b) < 0.000001
Of course, replace the constant with whatever you consider "almost".
当然,将常量替换为您认为“几乎”的任何内容。
回答by Peter Alexander
Just test if they differ by less than that amount :)
只需测试它们的差异是否小于该数量:)
if ( std::abs(a - b) < 1.0 / 10000000 )
cout << "The numbers are almost equal.\n";
回答by winwaed
if (a * 1.0000001 > b && a < b*1.0000001)
You can add an error value (your 1.0 / 10000000.0 ) but it is generally better to use a multiplier, so the comparison is to the same level of accuracy.
您可以添加一个错误值(您的 1.0 / 10000000.0 ),但通常最好使用乘数,因此比较的精度水平相同。
回答by Tomek
I suggest the following article: new link
(obsolete link->Comparing floating point numbers)
回答by user4030933
I'm also reading the book, since we didn't get to std::abs, i did something like that:
我也在读这本书,因为我们没有进入 std::abs,我做了这样的事情:
int main()
{
double i1,i2;
while(cin>> i1 >> i2){
if (i1<i2) {
if ((i2-i1)<=0.0000001) cout << "Almost equal!"<<endl;
else cout << "the smaller value is: "<< i1 << " the larger value is: " << i2 <<endl;
}
if (i1>i2) {
if ((i1-i2)<=0.0000001) cout << "Almost equal!"<<endl;
else cout << "the smaller value is: "<< i2 << " the larger value is: " << i1 <<endl;
}
else if (i1==i2) cout << "the value : "<< i1 << " And the value : " << i2 << " are equal!"<<endl;
}
}
回答by Josephine
If you want the test to scale with a and b, you could try testing abs(a/b-1) < e, where e is your favorite tiny number, like 0.001. But this condition is actually asymmetrical in a and b, so it can work out to say a is close to b, but b is not close to a. That would be bad. It's better to do abs(log(a/b)) < e, where e, again, is your favorite tiny number. But the logarithms present extra computation, not to mention terrifying undergraduates everywhere.
如果您希望测试使用 a 和 b 进行缩放,您可以尝试测试 abs(a/b-1) < e,其中 e 是您最喜欢的小数,例如 0.001。但是这个条件实际上在 a 和 b 中是不对称的,所以可以说 a 接近 b,但 b 不接近 a。那会很糟糕。最好是 abs(log(a/b)) < e,其中 e 再次是您最喜欢的小数。但是对数带来了额外的计算,更不用说到处都是可怕的本科生了。
回答by Klark
abs(a - b) < 1.0 / 10000000