#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,我有一些指令要执行..
谢谢你的帮助
答案 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; }