0

How to do comparisons of float values using series of bitwise operations?

4

9 回答 9

5

Don't. Just... don't. Use ==, or its wild and wacky neigbors > and <. There's even the crazy hybrids, <= and >=! These should cover all of your float-comparison needs.

Update: Never mind, don't use ==. The others should be fine.

Update update: Not using == means you probably shouldn't use <= or >=, either. The moral of the story is that floats are tricksy, which is why you absolutely, definitely shouldn't be trying bitwise operations on them.

于 2010-06-23T16:25:53.923 回答
2

在某些情况下,按位操作浮点数实际上是有意义的。例如,如果您尝试对具有较低位精度或较大位精度的硬件进行建模。在这些情况下,您将需要访问浮点数上的位。正如 bta 所说,您首先应该知道的是 IEEE 754 标准,以便您知道您正在操作哪些位。

然后您可以使用诸如 ShinTakezou 之类的解决方案,但我会建议一些更复杂的解决方案。

假设我们想要单精度。

首先我们声明一个具有不同浮点字段的结构:

typedef struct s_float{
    int sign : 1;
    int exponent : 8;
    int mantissa : 23;
}my_float_struct;

然后我们这样声明一个联合:

union u_float{
    float the_float;
    my_float_struct the_structure;
}my_float;

然后我们可以通过执行以下操作访问代码中的浮点数:

my_float.the_float = <float number>;

位字段的使用例如如下:

printf("%f is %d.%d.%d\n",my_float.the_float,my_float.the_structure.sign,my_float.the_structure.exponent,my_float.the_structure.mantissa);

而且您可以分配、修改字段或您需要的任何其他内容。

于 2011-10-25T10:28:55.343 回答
1

我不认为在 a 上使用按位运算符float会做你认为它会做的事情。在此之前,请确保您熟悉IEEE 754标准,该标准控制浮点数在内部的表示方式。虽然这是一个完全有效的操作,但它很可能不是很有用。

你到底想完成什么?可能有更好的方法来做到这一点。

于 2010-06-23T16:30:57.360 回答
0

float数字表示的域不适合它们的位实现和操作。

您可以轻松地在您的浮点数上应用任何按位运算符,但您不会获得任何有用的信息,因为如果您想将它们视为浮点数,这些运算符将以一种根本没有任何意义的方式修改数字。

对两个指数进行与运算或对两个尾数进行异或运算会有什么意义?我的意思是在实际的浮动操作中..

于 2010-06-23T16:27:57.977 回答
0

浮点布局强烈依赖于平台。我记得看到丑陋的黑客只使用整数运算来绘制随机浮点数,但这绝对是不可移植的。

于 2010-06-23T16:28:09.113 回答
0

Convert to integral type. Then You can use all the binary operations with it. Beware that conversion is temporary (type conversion is like a function returning value interpreted as if it had different type).

float real_value;
(int)real_value | 3, // this will work
real_value | 3; // This will not work
于 2011-10-27T12:38:47.597 回答
0

如果您仔细阅读有关 fp 编号的 IEEE 规范,那么您就处于起步阶段。下一步是在软件中实现硬件已经完成的工作,如果 cpu 支持 fp 否则你必须在软件中从头开始实现 fp 操作(根据 IEEE)......两者都完全可行(这是一个必须要做的)如果需要 IEEE 754,则在将 IEEE 用于 cpus 或 fp 协处理器之前执行此操作)。

让我们假设您的目标根本无法 fp,因此您需要从头开始实现它。然后由您决定如何将数字存储在内存中(您可以同意系统的字节顺序);例如,1.23 的浮点数在我的机器(LE)上作为 0xA4709D3F 存储到 mem 中,实际上“正确”的方式是 0x3F9D70A4(我们的写作方式更像是 BE 而不是 LE,但没有“正确”的方式......即使这种方式允许我们直接使用规格检查数据,所以如果我写 -1.23,我会得到 0xBF9D70A4,很明显符号位被提升到 1)

但是由于我们要从头开始实现它,我们可以通过这种方式将数字写入内存:

unsigned char p[4];
p[0] = 0x3f; p[1] = 0x9d; p[2] = 0x70; p[3] = 0xa4;

然后是困难的部分......就像这样:

bool is_positive(float_t *p)
{
  return ! (p[0] & 0x80); // or alike
}

假设我们的 proc 无法处理 32 位(或更多)整数,我们在内存中工作。当然,我选择了更简单的操作......!其他的比较难,但是从 IEEE 754 的描述开始,做一些推理,你就可以实现你想要的。如您所见,这并不容易......当没有浮点单元时,您可以在某个地方找到实现对 fp 数进行操作的库,但现在我找不到任何库(示例可能是 Amiga mathieeedoubbas.library,但我认为你找不到这个的来源,无论如何它可以直接在 m68k asm 中......;只是说软件 impl 可能存在于某处......)

于 2010-06-23T18:09:08.620 回答
0

在极少数需要这样做的情况下(例如,处理外来浮点格式,例如在 PC 上处理 VAX G 格式的数据),您通常通过将浮点数据放入整数相同的大小,或者放入一个 char 数组(同样,大小正确)。

不要指望这样的代码接近可移植或干净。在典型情况下,您希望尽可能少地这样做,通常只是读入原始数据,创建可能最接近的本机浮点值,然后使用它。即使/如果您必须处理此类外来数据,通常仍应避免使用外来格式进行比较等操作。

于 2010-06-23T16:33:25.323 回答
0

下面的链接中有一个很好的描述,它使用该技巧为浮点数创建高度优化的排序函数。

http://www.stereopsis.com/radix.html

显然,在大多数情况下,使用这种 hack 是不可移植且不可取的。

于 2010-06-23T16:54:27.970 回答