简体   繁体   English

比较双打

[英]Comparing doubles

I'm writing a program that consists of a while loop that reads two doubles and prints them. 我正在编写一个由while循环组成的程序,它读取两个双打并打印它们。 The program also prints what the larger number is and what the smaller number is. 该程序还会打印较大的数字和较小的数字。

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. 如果两个数字相差小于1.0 / 10000000,则下一步是让程序写出“数字几乎相等”。 How would I do this? 我该怎么做?

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.955 digits). 双精度浮点值可以保存一个数字的最重要的十五位数(实际≈15.955位数)。 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. 换句话说,如果它们在彼此的一个缩放的epsilon内,我们希望将它们称为相等。 This is exactly what the second test computes. 这正是第二次测试计算的内容。

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. 您可以选择添加比单个缩放epsilon更多的余地,因为迭代计算会导致更多重要的浮点误差。 To do this, add an error factor to the right hand side of the second test's comparison: 为此,请在第二个测试的比较右侧添加一个错误因子:

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. 我无法为error_factor提供固定值,因为它将取决于计算中出现的错误量。 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. 请记住,仅基于推测添加(任意)错误因素将使您回到软糖因子领域。

Summary 摘要

You can wrap the following test into a(n inline) function: 您可以将以下测试包装到(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;
}

std::abs(a - b) < 0.000001

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

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";
if (a * 1.0000001 > b  &&  a < b*1.0000001)

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

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;

}
}
abs(a - b) < 1.0 / 10000000

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. 如果你想用a和b来扩展测试,你可以尝试测试abs(a / b-1)<e,其中e是你最喜欢的微小数字,比如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. 但是这个条件实际上在a和b中是不对称的,所以可以说a接近b,但b不接近a。 That would be bad. 那会很糟糕。 It's better to do abs(log(a/b)) < e, where e, again, is your favorite tiny number. 做abs(log(a / b))<e更好,其中e再次是你最喜欢的小数字。 But the logarithms present extra computation, not to mention terrifying undergraduates everywhere. 但是对数提供额外的计算,更不用说到处都是可怕的本科生了。

I suggest the following article: new link 我建议以下文章: 新链接
(obsolete link-> Comparing floating point numbers ) (过时的链接 - > 比较浮点数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM