比较双打

时间:2010-10-24 20:18:31

标签: c++

我正在编写一个由while循环组成的程序,该循环读取两个双打并打印它们。该程序还会打印较大的数字和较小的数字。

这是我到目前为止的代码。

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" ;

    }
}

如果两个数字相差小于1.0 / 10000000,则下一步是让程序写出“数字几乎相等”。我该怎么做?

8 个答案:

答案 0 :(得分:24)

以下是我如何测试平等,没有“软糖因素”:

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";

<强>解释

第一个测试是一个简单的比较。当然,我们都知道,比较双精度值可能会导致它们被认为是不相等的,即使它们在逻辑上是等价的。

双精度浮点值可以保存数字的最重要的十五位数(实际为≈15.955个数字)。因此,如果(大约)它们的前十五个数字匹配,我们想要调用两个值相等。换句话说,如果它们在彼此的一个缩放的epsilon内,我们希望将它们称为相等。这正是第二次测试计算的内容。

由于迭代计算导致更重要的浮点误差蔓延,您可以选择添加比单个缩放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";

我无法为error_factor提供固定值,因为它取决于计算中出现的错误数量。但是,通过一些测试,您应该能够找到适合您应用的合理值。请记住,仅根据推测添加(任意)错误因素会使您回到软糖因子区域。

<强>摘要

您可以将以下测试包装到(n内联)函数中:

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;
}

答案 1 :(得分:11)

std::abs(a - b) < 0.000001

当然,用你认为“差不多”的东西替换常数。

答案 2 :(得分:4)

只测试它们是否相差少于该数量:)

if ( std::abs(a - b) < 1.0 / 10000000 )
  cout << "The numbers are almost equal.\n";

答案 3 :(得分:2)

if (a * 1.0000001 > b  &&  a < b*1.0000001)

您可以添加错误值(1.0 / 10000000.0),但通常最好使用乘数,因此比较的精确度相同。

答案 4 :(得分:1)

abs(a - b) < 1.0 / 10000000

答案 5 :(得分:1)

如果你想用a和b来扩展测试,你可以尝试测试abs(a / b-1)&lt; e,其中e是你最喜欢的微小数字,比如0.001。但是这个条件实际上在a和b中是不对称的,所以可以说a接近b,但b不接近a。那会很糟糕。最好做abs(log(a / b))&lt; e,再次,e是你最喜欢的小号码。但是对数提供了额外的计算,更不用说到处都是可怕的本科生了。

答案 6 :(得分:1)

我建议使用以下文章:new link
(过时的链接 - &gt; Comparing floating point numbers

答案 7 :(得分:1)

我也在读这本书,因为我们没有达到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;

}
}