使用按位运算符比较浮点数

时间:2010-06-23 16:22:39

标签: c floating-point bitwise-operators

如何使用一系列按位运算来比较浮点值?

9 个答案:

答案 0 :(得分:6)

别。只是......不要。使用==或其野性和古怪的neigbors ><。甚至还有疯狂的混合动力车<=>=!这些应该涵盖你所有的浮动比较需求。

更新:没关系,请勿使用==。其他人应该没事。

更新更新:不使用==表示您可能不应使用<=>=。这个故事的寓意是花车很棘手,这就是为什么你绝对不应该对它们进行按位操作。

答案 1 :(得分: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;

然后我们可以通过执行以下操作访问代码中的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);

你可以分配,修改字段或其他任何你需要的东西。

答案 2 :(得分:1)

我不认为在float上使用按位运算符会执行您认为会执行的操作。在此之前,请确保您熟悉IEEE 754标准,该标准管理内部如何表示浮点数。虽然这是一个非常有效的操作,但它很可能不是很有用。

你到底想要完成什么?可能有更好的方法。

答案 3 :(得分:0)

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

你可以轻松地在你的花车上应用任何按位运算符,但你不会获得任何有用的东西,因为这些运算符会以一种如果你想把它们视为浮点数而没有任何意义的方式修改数字。< / p>

两个指数和两个尾数的两个指数有什么样的感觉?我的意思是在实际的浮动操作中..

答案 4 :(得分:0)

浮点布局与平台有很大关系。我记得看到丑陋的黑客只使用整数操作来绘制随机浮点数,但这肯定是可移植。

答案 5 :(得分:0)

在您需要执行此操作的极少数情况下(例如,处理外部浮点格式,例如在PC上操作VAX G格式的数据),通常将浮点数据放入一个相同大小的整数,或者一个char数组(同样,大小合适)。

不要指望这样的代码可以放在便携或干净的地方。在典型情况下,您希望尽可能少地执行此操作,通常只需读取原始数据,创建可能的最接近的本机浮点值,然后使用它。即使在/如果你必须处理这些外国数据时,通常仍应避免以外国格式进行比较。

答案 6 :(得分:0)

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

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

显然,在大多数情况下,使用这种黑客行为是不可移植的,也是不可取的。

答案 7 :(得分:0)

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

让我们假设你的目标根本不能fp,所以你需要从头开始实现它。然后由您来决定如何将数字存储在内存中(您可以同意系统的字节顺序);例如1.23的浮点数作为0xA4709D3F存储在我的机器(LE)上,实际上“正确”的方式是0x3F9D70A4(我们的写作方式比LE更像BE,但没有“正确”的方式......甚至虽然这种方式允许我们直接用specs检查数据,所以如果我写-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可能存在于某个地方......)

答案 8 :(得分:0)

转换为整数类型。然后您可以使用它的所有二进制操作。请注意转换是临时的(类型转换就像一个函数返回值,解释为它具有不同的类型)。

float real_value;
(int)real_value | 3, // this will work
real_value | 3; // This will not work