比较IEEE浮点数和双精度数据的最佳方法是什么? 我听说过几种方法,但我想看看社区的想法。

===============>>#1 票数:7 已采纳

我认为最好的方法是比较ULP

bool is_nan(float f)
{
    return (*reinterpret_cast<unsigned __int32*>(&f) & 0x7f800000) == 0x7f800000 && (*reinterpret_cast<unsigned __int32*>(&f) & 0x007fffff) != 0;
}

bool is_finite(float f)
{
    return (*reinterpret_cast<unsigned __int32*>(&f) & 0x7f800000) != 0x7f800000;
}

// if this symbol is defined, NaNs are never equal to anything (as is normal in IEEE floating point)
// if this symbol is not defined, NaNs are hugely different from regular numbers, but might be equal to each other
#define UNEQUAL_NANS 1
// if this symbol is defined, infinites are never equal to finite numbers (as they're unimaginably greater)
// if this symbol is not defined, infinities are 1 ULP away from +/- FLT_MAX
#define INFINITE_INFINITIES 1

// test whether two IEEE floats are within a specified number of representable values of each other
// This depends on the fact that IEEE floats are properly ordered when treated as signed magnitude integers
bool equal_float(float lhs, float rhs, unsigned __int32 max_ulp_difference)
{
#ifdef UNEQUAL_NANS
    if(is_nan(lhs) || is_nan(rhs))
    {
        return false;
    }
#endif
#ifdef INFINITE_INFINITIES
    if((is_finite(lhs) && !is_finite(rhs)) || (!is_finite(lhs) && is_finite(rhs)))
    {
        return false;
    }
#endif
    signed __int32 left(*reinterpret_cast<signed __int32*>(&lhs));
    // transform signed magnitude ints into 2s complement signed ints
    if(left < 0)
    {
        left = 0x80000000 - left;
    }
    signed __int32 right(*reinterpret_cast<signed __int32*>(&rhs));
    // transform signed magnitude ints into 2s complement signed ints
    if(right < 0)
    {
        right = 0x80000000 - right;
    }
    if(static_cast<unsigned __int32>(std::abs(left - right)) <= max_ulp_difference)
    {
        return true;
    }
    return false;
}

类似的技术可用于双打。 诀窍是转换浮点数以便它们被排序(就像整数一样)然后只看它们有多么不同。

我不知道为什么这个该死的东西搞砸了我的下划线。 编辑:哦,也许这只是预览的人工制品。 那没关系。

===============>>#2 票数:3

我正在使用的当前版本是这个

bool is_equals(float A, float B,
               float maxRelativeError, float maxAbsoluteError)
{

  if (fabs(A - B) < maxAbsoluteError)
    return true;

  float relativeError;
  if (fabs(B) > fabs(A))
    relativeError = fabs((A - B) / B);
  else
    relativeError = fabs((A - B) / A);

  if (relativeError <= maxRelativeError)
    return true;

  return false;
}

这似乎通过组合相对和绝对容错来解决大多数问题。 ULP方法更好吗? 如果是这样,为什么?

===============>>#3 票数:1

在数值软件中,您经常要测试两个浮点数是否完全相等。 LAPACK充满了这种情况的例子。 当然,最常见的情况是您要测试浮点数是否等于“零”,“一”,“二”,“一半”。 如果有人感兴趣,我可以选择一些算法并详细介绍。

同样在BLAS中,您经常需要检查浮点数是否恰好为零或一。 例如,例程dgemv可以计算表单的操作

  • y = beta * y + alpha * A * x
  • y = beta * y + alpha * A ^ T * x
  • y = beta * y + alpha * A ^ H * x

因此,如果beta等于1,那么您将获得“加号分配”,而对于Beta等于零则为“简单分配”。 因此,如果您对这些(常见)案例进行特殊处理,您当然可以降低计算成本。

当然,您可以设计BLAS例程,以避免精确比较(例如使用一些标志)。 但是,LAPACK充满了无法实现的示例。

PS:

  • 肯定有很多情况下你不想检查“完全相同”。 对于许多人来说,这甚至可能是他们唯一需要处理的案例。 我只想指出的是,还有其他案例。

  • 虽然LAPACK是用Fortran编写的,但如果你使用其他编程语言编写数字软件,那么逻辑就是一样的。

===============>>#4 票数:1

@DrPizza:我不是性能大师,但我希望定点操作比浮点运算更快(在大多数情况下)。

这取决于你在做什么。 与IEEE浮点数相同的定点类型将慢很多倍(并且要大很多倍)。

适合花车的东西:

3D图形,物理/工程,模拟,气候模拟....

===============>>#5 票数:0

一个int让我表达~10 ^ 9个值(无论范围如何),这对于我关心其中两个相等的任何情况似乎都足够了。 如果这还不够,请使用64位操作系统,并且您有大约10 ^ 19个不同的值。

我实际上达到了这个极限......我试图在时间周期中以ps和时间来处理时间,在模拟中你很容易达到10 ^ 10个周期。 无论我做了什么,我都很快就溢出了64位整数的微弱范围... 10 ^ 19并不像你想象的那么多,现在计算128位计算!

Floats允许我得到数学问题的解决方案,因为值在低端溢出了很多零。 所以你基本上在数字中有一个小数点浮动aronud而没有精度损失(我可以想象浮点数的尾数中允许的值与64位int相比更有限,但是迫切需要th范围! )。

然后将事物转换回整数进行比较等。

烦人,最后我废弃了整个尝试,只依靠花车和<和>来完成工作。 不完美,但适用于设想的用例。

===============>>#6 票数:0

哦,亲爱的领主请不要将浮动位解释为整数,除非您在P6或更早版本上运行。

===============>>#7 票数:0

哦,亲爱的领主请不要将浮动位解释为整数,除非您在P6或更早版本上运行。

即使它导致它通过内存从向量寄存器复制到整数寄存器,即使它停止了管道,它也是我遇到过的最好的方法,因为它提供了最强大的比较,即使面对面也是如此浮点错误。

即这是一个值得付出的代价。

===============>>#8 票数:0

这是我遇到过的最好的方法,因为它提供了最强大的比较,即使面对浮点错误也是如此。

如果您有浮点错误,那么您遇到的问题就更多了。 虽然我猜这取决于个人观点。

===============>>#9 票数:0

这似乎通过组合相对和绝对容错来解决大多数问题。 ULP方法更好吗? 如果是这样,为什么?

ULP是两个浮点数之间“距离”的直接度量。 这意味着它们不需要您想出相对和绝对错误值,也不必确保将这些值“约为正确”。 使用ULP,您可以直接表达您希望数字的接近程度,同样的阈值也适用于小值和大值。

===============>>#10 票数:0

如果您有浮点错误,那么您遇到的问题就更多了。 虽然我猜这取决于个人观点。

即使我们进行数值分析以最大限度地减少误差累积,我们也无法消除它,我们可以留下应该相同的结果(如果我们用实数计算)但不同(因为我们无法用实数计算)。

===============>>#11 票数:0

如果你正在寻找两个花车相同,那么在我看来它们应该完全相同。 如果您遇到浮点舍入问题,也许固定点表示更适合您的问题。

===============>>#12 票数:0

如果你正在寻找两个花车相同,那么在我看来它们应该完全相同。 如果您遇到浮点舍入问题,也许固定点表示更适合您的问题。

也许我们无法承受这种方法会造成的范围或性能的损失。

===============>>#13 票数:0

如果你正在寻找两个花车相同,那么在我看来它们应该完全相同。 如果您遇到浮点舍入问题,也许固定点表示更适合您的问题。

也许我应该更好地解释这个问题。 在C ++中,以下代码:

#include <iostream>

using namespace std;


int main()
{
  float a = 1.0;
  float b = 0.0;

  for(int i=0;i<10;++i)
  {
    b+=0.1;
  }

  if(a != b)
  {
    cout << "Something is wrong" << endl;
  }

  return 1;
}

打印短语“Something is wrong”。 你是说它应该吗?

===============>>#14 票数:0

@DrPizza:我不是性能大师,但我希望定点操作比浮点运算更快(在大多数情况下)。

@Craig H:好的。 我打印它完全没问题。 如果a或b存钱,那么它们应该以固定点表示。 我正在努力想到一个真实世界的例子,这种逻辑应该与浮动联合起来​​。 适合花车的东西:

  • 权重
  • 行列
  • 距离
  • 现实世界的价值观(如来自ADC)

对于所有这些事情,要么你多了数字,只是简单地将结果呈现给用户进行人工解释,或者你做一个比较陈述(即使这样的陈述是,“这件事在这另一件事的0.001之内”)。 像我这样的比较语句只在算法的上下文中有用:“在0.001之内”部分取决于你问的物理问题。 我的0.02。 或者我应该说2/100?

===============>>#15 票数:0

这取决于你在做什么。 与IEEE浮点数相同的定点类型将慢很多倍(并且要大很多倍)。

好吧,但是如果我想要一个无限小的比特分辨率,那么它又回到了原点:==和!=在这样的问题的背景下没有任何意义。

一个int让我表达~10 ^ 9个值(无论范围如何),这对于我关心其中两个相等的任何情况似乎都足够了。 如果这还不够,请使用64位操作系统,并且您有大约10 ^ 19个不同的值。

我可以在int中表示0到10 ^ 200(例如)范围内的值,它只是遭受的位分辨率(分辨率大于1,但同样,没有应用程序也具有这种范围)作为那种决议)。

总而言之,我认为在所有情况下,一个或者代表一个连续的值,在这种情况下!=和==是无关的,或者一个是表示一组固定的值,可以映射到一个int(或另一个固定的 - 精确型)。

  ask by Craig H translate from so

未解决问题?本站智能推荐:

3回复

IEEE-754的浮点数,双精度数和四进制数是否保证精确表示-2,-1,-0、0、1、2?

所有在标题:不IEEE-754 float , double和quad保证确切表示-2 , -1 , -0 , 0 , 1 , 2 ?
4回复

比较Java中的浮点数和双精度数

以下代码分别使用float和double类型的值。 它显示以下输出: 执行后, a和b的值分别为99999.99和99999.9921875但a==b返回true 。 比较表达式a==b返回true ?
4回复

比较最小/最大浮点数(浮点数或双精度数)

如何比较两个不同的浮点数,达到一定的精度。 我知道在任何编程语言中使用浮点数或双精度数时,都会有非常小的误差,但是这可能足以使浮点数a < b比较返回与实际值不同的值。 我正在从UVa在线法官解决一个问题,该问题多次给了我一个错误的答案。 几乎没有浮点数作为输入输入到两位小数位。
6回复

实数 - 如何确定是否需要浮点数或双精度数?

给定一个实际值,我们可以检查float数据类型是否足以存储数字,还是需要double ? 我知道精度因建筑而异。 是否有任何C / C ++函数来确定正确的数据类型?
7回复

将浮点数格式化为2个小数位

我目前正在为客户网站构建销售模块。 到目前为止,我已经获得了可以完美计算的销售价格,但是我遇到的问题是将输出格式化为2个小数位。 我目前在变量中调用它,以便可以将结果数据绑定到列表视图。 谁能告诉我如何将输出格式设置为小数点后两位? 非常感谢!
3回复

Python替换只给定整数的浮点数

我正在读取一个csv文件,并提取一行数据: 当我打印(x)时,我得到了在单元格中找到的正确值或确切值。 例如153.018848 但是当我尝试在下面将x作为变量传递时: 输出将是<node version="0" lon="153"> 。 我当然要值153.
2回复

浮点数和双精度数的精度位数差异

这个问题已经在这里有答案 : 2年前关闭。 浮点数学运算是否损坏? (31个答案) 我得到z的值为16。 当我使用double
2回复

C中浮点数和双精度数之间的精度

我了解有几个与我的主题相同的主题,但是我仍然没有真正理解它,因此我希望有人可以以一种更简单但明确的方式为我解释这一点,而不是粘贴其他主题的链接,谢谢。 这是一个示例代码: 输出: 我的两个问题是: 为什么将整数添加到浮点数最终会作为第二个输出,但是将浮点数更改为d
10回复

C - 浮点数的序列化(浮点数,双精度数)

如何将浮点数转换为字节序列,以便它可以保存在文件中? 这种算法必须快速且高度便携。 它必须允许相反的操作,反序列化。 如果每个值(持久空间)只需要非常微小的多余位,那就太好了。
2回复

在MATLAB中,变量默认是否真的是双精度?

这个问题是我进一步调查后发现的奇怪问题 。 我一直都理解默认情况下MATLAB变量是双精度的。 因此,如果我要进行一些操作,例如声明一个小数点后20位数字的变量: 我希望最后4位数字被忽略,因为浮点相对精度约为10 -16 : 如果我尝试显示小数点后的数字超过16位(使用