比较IEEE浮标,并增加一倍平等
-
09-06-2019 - |
题
什么是最好的方法进行比较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或更早。
这是最好的方式做到这一点,我已经跨越,因为它提供了最强大的比较,即使在面临的浮点错误。
如果你有漂浮点错误你有甚至更多问题比这一点。虽然我想这是个人观点。