什么是最好的方法进行比较IEEE浮标,并增加一倍的平等?我有听说过几种方法,但我想看看什么是社会的思想。

有帮助吗?

解决方案

最好的方法我想是比较 ULPs.

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;
}

一个类似的技术可以用于增加一倍。诀窍是将浮因此,他们命令(如整数)和然后只是看看如何不同。

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

其他提示

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

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;
}

这似乎照顾的大多数问题通过合并相对和绝对错误的容忍。是行不当劳动行为的办法更好?如果是这样,为什么?

@DrPizza:我没有性能大师,但是我希望的固定点行动要快于浮点运算(在多数情况下)。

它不取决于你是什么做它们。一个定点的类型具有相同的范围如IEEE浮动将许多许多倍慢(而且很多时候更大)。

事情适用于浮:

3D图形的、物理学/工程、模拟、气候模拟。...

在数值软件,你常常想要测试是否两个浮点数 到底 平等。特点是可扩展性。是全面的实例这样的情况。肯定的是,最常见的情况是你想要测试是否浮点数等于"零","One","Two","半"。如果任何人感兴趣的是我可以挑选一些算法和更为详细的说明。

还在布拉斯你经常要检查是否是一个浮点的数量正是零或一个。例如,程序dgemv可以计算操作的形式

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

因此,如果测试等于一个你有一个"加分配"和用于测试等于零"简单分配".所以你一定可以切的计算成本,如果你给这些(公共)情况下的一种特殊的治疗。

当然,你可以设计的布拉斯程序,在这样一种方式,可以避免确切的比较(例如使用一些标志)。然而,特点是可扩展性。是充分的例子,这是不可能的。

P.S.:

  • 当然,还有许多情况下,你不想检查"完全平等"。对于许多人来说,这甚至可能是唯一的情况下,他们曾经拥有来处理。所有我想指出的是,还有其他的情况。

  • 虽然特点是可扩展性。是写在Fortran的逻辑是相同的,如果您使用的是其他的编程语言为数字的软件。

哦亲爱的上帝,请不要解释的浮位作为整数,除非你上运行的P6或更早。

甚至如果这会导致到复制自矢量注册为整寄存器通过存储器,即使它摊的管道,这是最好的方式做到这一点,我已经跨越,因为它提供了最强大的比较,即使在面临的浮点错误。

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

这似乎照顾的大多数问题通过合并相对和绝对错误的容忍。是行不当劳动行为的办法更好?如果是这样,为什么?

ULPs是一种直接测量的"距离"之间的两个浮点数。这意味着他们不需要你来想像的相对和绝对错误的价值观,也不必以确保获得这些价值"有关权利"。与ULPs,你可以直接表达你想要的数字,而同一阈值工作以及对于小价值观作为为大家。

如果你有漂浮点错误你有甚至更多问题比这一点。虽然我想这是个人观点。

甚至如果我们的数字分析,以尽量减少累积的错误,我们不能消除它,我们可以留下结果应该是相同的(如果我们计算与雷亚尔)而有所不同(因为我们无法计算与雷亚尔).

如果你是在寻找两个浮标是平等的,那么他们应该是同等的。如果你正面临着一个浮点四舍五入的问题,也许是一个固定点表示将满足你的问题好。

如果你是在寻找两个浮标是平等的,那么他们应该是同等的。如果你正面临着一个浮点四舍五入的问题,也许是一个固定点表示将满足你的问题好。

也许我们无法负担得起的损失的范围或性能,这种做法会造成。

@DrPizza:我没有性能大师,但是我希望的固定点行动要快于浮点运算(在多数情况下)。

@克雷格*H:肯定的。我完全没关系,与它打印那。如果一个或b储存的钱然后他们应该代表在固定点。我在努力想的一个真实世界的例子,在那里这样的逻辑应该是盟军向浮动。事情适用于浮:

  • 重量
  • 队伍
  • 距离
  • 现实世界中的价值(如自ADC)

所有这些事情,无论你多了,然后数字和简明的结果的用户人的解释,或者你让一个比较声明(甚至如果这种说法是,"这件事是在0.001这一其他的事情").比较像我这样的声明只是有用的上下文中的算法:该"内0.001"的一部分取决于什么 物理 问题你要求.我的0.02.或者我应该说2/100秒?

它不取决于你是什么 这样做与他们。一个定点的类型 与同一范围内作为一个IEEE浮 将是许多许多倍慢(和 大许多倍).

好吧,但是如果我想要一个无穷小点解决然后又回到我最初的观点:==并!= 没有任何意义的背景下这样的问题。

Int让我表示,~10^9值(不论的范围内),这似乎是足够的任何情况下,我会关心他们两个是平等的。如果这还不够,使用64位的操作系统和你已经有了约10^19个不同的价值观。

我可以表达价值观的范围在0到10^200(例如)在诠释,它仅仅是位的决议,遭受(决议将大于1,但是,再说一次,不应有这样的范围,以及这样的分辨率)。

总之,我认为在所有情况下,一个是代表一个连续体的价值观,在这种情况下!= 和==是毫不相关,或一个是代表一个固定的价值观,这可以映射到一个int(或另一个固定的精度的类型)。

Int让我表示,~10^9值 (不论的范围)似乎 喜欢足的任何情况下我 会关心他们两个是 平等。如果这还不够,使用 64位的操作系统和你已经有了约10^19 不同的价值观。

我实际上打击,限制了...我只是想玩弄时间在ps和时间,在时钟周期中的模拟,你很容易地击中10^10个周期。无论我做什么我很快溢出的小范围的64位整数...10^19个是不是你以为是,给我128位计算,现在!

浮允许我得到一个解决方案的数学问题,因为值溢出,有很多零低端。所以基本上你有一个小数点浮aronud的数目没有损失的精确度(我可能会喜欢的更有限的不同的数值,允许在尾数的浮子相比,有64位int,但迫切需要的个范围!).

然后事情转换回来整数比较等。

讨厌,并在结束我报废的整个企图,只是依赖和浮 < 并>获得所做的工作。不完美,但可以作为使用情况的设想。

如果你是在寻找两个浮标是平等的,那么他们应该是同等的。如果你正面临着一个浮点四舍五入的问题,也许是一个固定点表示将满足你的问题好。

也许我应该解释的问题更好。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;
}

印短语"的东西是错误的"。你是说,它应该吗?

哦亲爱的上帝,请不要解释的浮位作为整数,除非你上运行的P6或更早。

这是最好的方式做到这一点,我已经跨越,因为它提供了最强大的比较,即使在面临的浮点错误。

如果你有漂浮点错误你有甚至更多问题比这一点。虽然我想这是个人观点。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top