比较两个浮动 #包括 布尔等式(双a,双b,双ε) { if(fabs(a-b)52和2047),eb=(int)(d>>52和2047); 如果(ea==2047&&(c&fm)!=0 | | eb==2047&&(d&fm)!=0)返回false;//NaN 如果(c==d)返回true;//相同-快速检查 如果(ea==0&&eb==0)返回true;/±0或低于正常值 如果((c&sm)!=(d&sm))返回false;//不同的符号 如果(abs(ea-eb)>1)返回false;//b>2*a或a>2*b d>1 | sm; c-=d; 返回c-65536;//不要使用abs(),因为: //有一个可能性c=0x80000000000000,不能转换为正数 } 公共静态布尔零(double a){return(double.double-tolongbits(a)>>52&2047)

比较两个浮动 #包括 布尔等式(双a,双b,双ε) { if(fabs(a-b)52和2047),eb=(int)(d>>52和2047); 如果(ea==2047&&(c&fm)!=0 | | eb==2047&&(d&fm)!=0)返回false;//NaN 如果(c==d)返回true;//相同-快速检查 如果(ea==0&&eb==0)返回true;/±0或低于正常值 如果((c&sm)!=(d&sm))返回false;//不同的符号 如果(abs(ea-eb)>1)返回false;//b>2*a或a>2*b d>1 | sm; c-=d; 返回c-65536;//不要使用abs(),因为: //有一个可能性c=0x80000000000000,不能转换为正数 } 公共静态布尔零(double a){return(double.double-tolongbits(a)>>52&2047),c,comparison,C,Comparison,我尝试了这种方法来比较两个双精度,但我总是遇到问题,因为我不知道如何选择ε,实际上我想比较小的数字(小数点后的6位数字),比如0.000001。我尝试了一些数字,有时我得到0.000001!=0.000001有时0.000001==0.000002 除了和ε比较,还有别的方法吗 我的目的是比较两个double(在我的例子中代表时间)。以毫秒为单位表示时间的变量t是双精度的。它由另一个函数0.000001递增,然后是0.000002等。每次t改变时,我想检查它是否等于另一个类型为double tt

我尝试了这种方法来比较两个双精度,但我总是遇到问题,因为我不知道如何选择
ε
,实际上我想比较小的数字(小数点后的6位数字),比如0.000001。我尝试了一些数字,有时我得到
0.000001!=0.000001
有时
0.000001==0.000002
除了和ε比较,还有别的方法吗

我的目的是比较两个double(在我的例子中代表时间)。以毫秒为单位表示时间的变量t是双精度的。它由另一个函数0.000001递增,然后是0.000002等。每次t改变时,我想检查它是否等于另一个类型为double tt的变量,如果tt==t,我有一些指令要执行..

感谢您的帮助首先:计算布尔值没有意义(使用
请看这里:

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


当然,你也可以比较两个整数,只需将两个浮点数乘以所需的精度,并将它们转换为整数即可。 请确保正确地向上/向下取整。下面是它的外观:

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

请记住,当
float a=+2^(254-127)*1.\uuuuuuuuu22零/uuuuuuuuu1
float b=+2^(254-127)*1.\uuuuuuu23零/uuuuuuuuuu
时,我们期望的是
abs(a-b)
,而不是
a-b=+2^(254-127-23)*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);
}
公共静态布尔相等(双a,双b){
最终长fm=0xFFFFFFFFFL;//分数掩码
最终长sm=0x80000000000000L;//符号掩码
最终长cm=0x80000000000L;//最高有效十进制位掩码
长c=双字节双字节长比特(a),d=双字节双字节长比特(b);
int ea=(int)(c>>52和2047),eb=(int)(d>>52和2047);
如果(ea==2047&&(c&fm)!=0 | | eb==2047&&(d&fm)!=0)返回false;//NaN
如果(c==d)返回true;//相同-快速检查
如果(ea==0&&eb==0)返回true;/±0或低于正常值
如果((c&sm)!=(d&sm))返回false;//不同的符号
如果(abs(ea-eb)>1)返回false;//b>2*a或a>2*b
d>1 | sm;
c-=d;
返回c<65536&&c>-65536;//不要使用abs(),因为:
//有一个可能性c=0x80000000000000,不能转换为正数
}
公共静态布尔零(double a){return(double.double-tolongbits(a)>>52&2047)<3;}
  • 如果其中任何一个数字为NaN,则数字不相等
  • 如果两个数字相同,则表示相等。这是一个快速初始检查
  • 如果两个数字都是+0、-0或次正常值中的任意一个,则数字相等
  • 如果数字有不同的符号,则数字是不相等的。如果两个数字几乎都是0(但不是±0或低于正常值),且符号不同,则这看起来是错误的方法。但是,如果将这些数字与另一个数字相乘,会怎么样?一个结果为负,另一个结果为正。因此,我们严格要求,这是正确的
  • 如果指数相差2或2以上,则数字不相等,因为一个数字至少是另一个数字的2倍
  • 如果指数的差值正好为1,则将其中一个数字的分数正确移位
  • 若两个分数之差很小,则数字相等

“Epsilon”,而不是Epsilon。0.000001和0.000002都不能精确表示为浮点,都是带循环小数的无限二进制分数。此外,fabs(a-b)很容易发生灾难性的取消。如果你不知道这是怎么回事,你至少可以通过使用ε来避免第一个问题,ε可以精确地表示为float,比如0.00000095367431640625,它是2^-20,接近你想要的10^-6。你为什么要首先使用
float
?首选
double
对于其他浮点类型,我们给出了一个非常强的例子。当然,您的问题仍然是
float
s还是
double
s。感谢您的回复,这可能是重复的。当eps=0.000001时,我得到了一个错误的结果(0.000001==0.000002),但是当我使用类似于1/1048576的东西时,结果总是!=(即使我将0.000001与0.000001进行比较):(
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);
}
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; }