2011-05-31 93 views
4

假设我有两个浮点数,即xy,它们的值非常接近。查找接近浮点数之间的“离散”差异

在计算机上可以表现出离散数量的浮点数,所以我们可以按升序列举它们:f_1, f_2, f_3, ...。我希望能够找到在此列表中的xy的距离(即它们是1,2,3,...还是分开n不连续的步骤?)

是否有可能只用算术运算做到这一点(+-*/ ),而不是看二进制表示?我主要感兴趣的是如何在x86上工作。

是下面的近似正确的,假定y > xxy都只有几步之遥(比方说,< 100)分开? (可能不是......)

(y-x)/x/eps 

这里eps表示机器epsilon。 (机器epsilon是1.0和下一个最小浮点数之间的差值。)

+0

@ShreevatsaR,这就是为什么我除以'x'(不仅是'eps')。 (y-x)/ x/eps =(y-x)/(x * eps)'。我仍然不确定它是否正确。 – Szabolcs 2011-05-31 14:33:17

+0

啊,好吧,对不起。你的公式可能是对的;让我们想想。 :-)与此同时,您可以阅读[每位计算机科学家应该了解的浮点算术知识](http://cr.yp.to/2005-590/goldberg.pdf)。 – ShreevatsaR 2011-05-31 14:51:57

回答

1

您不必直接检查二进制表示,但您必须依赖它来获得确切的答案,我认为。

首先使用frexp()将x分解为指数exp和尾数。我相信下一个大于x的浮动是x + eps * 2^(exp-1)。 (“-1”是因为frexp返回范围[1/2,  1]中的尾数,而不是[1,  2)。)

如果x和y具有相同的指数,则基本完成。否则,您需要计算每个功率为2的步数,这只是1.0/eps。换句话说,2^n和2 ^(n + 1)之间的步数是1.0/eps。因此,对于y> x,计算从x到下一个幂数有多少个步骤;然后计算需要多少步才能达到2的最大功率小于y;然后计算从那里到达y需要多少步骤。我认为所有这些都很容易用eps表示。

3

浮标被字典顺序,因此:

int steps(float a, float b){ 

    int ai = *(int*)&a; // reinterpret as integer 
    int bi = *(int*)&b; // reinterpret as integer 
    return bi - ai; 
} 

steps(5.0e-1, 5.0000054e-1); // returns 9 

Such a technique比较浮点数时使用。

+1

,只要数字大于0.仍然需要一些逻辑来覆盖负值和0(包括“-0”)。 – 2012-01-16 05:54:54

+0

+1,关于词典排序的有趣观察。但是,如果仅使用浮点算术运算,我仍然很想知道这一点。我在问这个问题时使用的语言不支持将位模式重新解释为不同的类型。 – Szabolcs 2012-01-16 07:19:47

+0

@Szabolcs你在用什么语言?我用C++编写代码,但它应该在C和D中工作。 – Arlen 2012-01-16 07:24:00