比较两个花车

时间:2011-05-13 08:24:16

标签: c comparison

#include <stdbool.h>

bool Equality(double a, double b, double epsilon)
{
  if (fabs(a-b) < epsilon) return true;
  return false;
}

我尝试过这种方法来比较两个双打,但我总是遇到问题,因为我不知道如何选择epsilon,实际上我想比较小数字(小数点后6位数) 0.000001 。我尝试了一些数字,有时我会0.000001 != 0.000001,有时会0.000001 == 0.000002 除了与epsilon比较之外还有其他方法吗?

我的目的是比较两个双打(代表我的情况下的时间)。表示以毫秒为单位的时间的变量t是double。每次t改变时,它会增加另一个函数0.000001然后0.000002等。我想检查它是否等于double tt类型的另一个变量,如果tt == t,我有一些指令要执行..
谢谢你的帮助

4 个答案:

答案 0 :(得分:16)

请看这里:http://floating-point-gui.de/errors/comparison/

  

由于舍入错误,大多数浮点数最终都会出现   稍微不精确。只要这种不精确度保持很小,它就可以   通常被忽略。 然而,这也意味着预期的数字   相等(例如,当通过不同的正确计算相同的结果时)   方法)经常略有不同,简单的相等测试失败

当然还有What Every Computer Scientist Should Know About Floating-Point Arithmetic

答案 1 :(得分:3)

首先:计算布尔值(使用<运算符)并将其包装在另一个布尔值中没有意义。就这样写:

bool Equality(float a, float b, float epsilon)
{
  return fabs(a - b) < epsilon;
}

其次,你的epsilon本身可能没有很好地表示为float,因此看起来不像你期望的那样。尝试使用2的负幂,例如1/1048576。

答案 2 :(得分:1)

或者,您可以比较两个整数。只需将您的两个浮点数乘以所需的精度,然后将它们转换为整数。 务必正确地向上/向下舍入。这是它的样子:

BOOL floatcmp(float float1, float float2, unsigned int precision){
   int int1, int2;

   if (float1 > 0)
      int1 = (int)(float1 * precision + .5);
   else
      int1 = (int)(float1 * precision - .5);

   if (float2 > 0)
      int2 = (int)(float2 * precision + .5);
   else
      int2 = (int)(float2 * precision - .5);

   return (int1 == int2);
}

答案 3 :(得分:0)

我编写并测试了这段代码。它似乎有效。

public static boolean equal(double a, double b) {
    final long fm = 0xFFFFFFFFFFFFFL;       // fraction mask
    final long sm = 0x8000000000000000L;    // sign mask
    final long cm = 0x8000000000000L;       // most significant decimal bit mask
    long c = Double.doubleToLongBits(a), d = Double.doubleToLongBits(b);        
    int ea = (int) (c >> 52 & 2047), eb = (int) (d >> 52 & 2047);
    if (ea == 2047 && (c & fm) != 0 || eb == 2047 && (d & fm) != 0) return false;   // NaN 
    if (c == d) return true;                            // identical - fast check
    if (ea == 0 && eb == 0) return true;                // ±0 or subnormals
    if ((c & sm) != (d & sm)) return false;             // different signs
    if (abs(ea - eb) > 1) return false;                 // b > 2*a or a > 2*b
    d <<= 12; c <<= 12;
    if (ea < eb) c = c >> 1 | sm;
    else if (ea > eb) d = d >> 1 | sm;
    c -= d;
    return c < 65536 && c > -65536;     // don't use abs(), because:
    // There is a posibility c=0x8000000000000000 which cannot be converted to positive
}
public static boolean zero(double a) { return (Double.doubleToLongBits(a) >> 52 & 2047) < 3; }
  • 如果任何数字是NaN,则数字不相等。
  • 如果2个数字相同,则相等。这是一个快速的初步检查。
  • 如果两个数字都是+ 0,-0或次正常,则数字相等。
  • 如果数字有不同的符号,则数字不相等。如果两个数字几乎为0(但不是±0或次正规)且具有不同的符号,则这看起来是错误的方法。但是如果你把这些数字乘以另一个呢?一个结果是负面的而另一个是积极的。所以我们很严格,这是对的。
  • 如果指数差异为2或更多,则数字不相等,因为一个数字至少是另一个数字的2倍。
  • 如果指数恰好为1,则从其中一个数字正确移位分数。
  • 如果2个分数的差异很小,则数字相等。