使用位算术从二进制 int 获取绝对值

Posted

技术标签:

【中文标题】使用位算术从二进制 int 获取绝对值【英文标题】:Getting absolute value from a binary int using bit arithmetics 【发布时间】:2016-02-05 23:40:58 【问题描述】:
flt32 flt32_abs (flt32 x) 
    int mask=x>>31;

    printMask(mask,32);
    puts("Original");
    printMask(x,32);

    x=x^mask;

    puts("after XOR"); 
    printMask(x,32);

    x=x-mask;

    puts("after x-mask");
    printMask(x,32);
    return x;

这是我的代码,在值 -32 上调用函数返回 .125。我很困惑,因为这是一个非常直接的 abs on bits 公式,但我似乎遗漏了一些东西。有任何想法吗?

【问题讨论】:

flt32 是某种非标准的浮点格式,位移是有效的吗?另见***.com/q/1723575/2564301 Jongware,偶尔,我也在下面的答案中链接到该问题。加入您的flt32 类型问题。 【参考方案1】:

flt32 是浮点类型还是 fixed point 数字类型?

我怀疑它是一种定点算术类型,而您没有正确使用它。让我解释一下。

顾名思义,定点数使用固定位置的十进制数字;这意味着它使用固定位数的小数部分。事实上,它是一个缩放的整数。

我猜您使用的flt32 类型使用整个部分的最高有效24 位和小数部分的最低有效8 位; 32 位表示的实数值是与整数相同的 32 位表示的值除以 256(即 28)。

例如,32 位数字0x00000020 被解释为整数为32。作为小数部分使用8位的定点数,其值为0.125=32/256)。

您发布的代码是正确的,但您没有正确使用它。

使用8 十进制数字编码为定点数的数字-320xFFFFE000,它是-8192 (=-32*256) 的整数表示。该算法正确生成8192,即0x00002000=32*256);当它被解释为定点时,这也是32

如果您将-32 传递给函数而不注意将其编码为定点,它会正确地将其转换为32 并返回此值。但是32 (0x00000020) 被解释为定点时是0.125 (=1/8=32/256)(我假设函数printMask() 是这样做的)。

如何正确测试代码?

您可能有一个从整数创建定点数的函数。使用它来获取-32 的正确表示并将该值传递给flt32_abs() 函数。

如果你没有这样的功能,写起来很容易。只需将整数与256 相乘(或者更好,将其左移 8 位)即可:

function int_to_fx32(int x)

    return x << 8;

定点库通常使用宏进行此类转换,因为它们生成的代码更快。用宏表示,如下所示:

#define int_to_fx32(x) ((x) << 8)

现在你进行测试:

fx32 negative = int_to_fx32(-32);
fx32 positive = fx32_abs(negative);
// This should print 32
printMask(positive, 32);

// This should print 8192
printf("%d", positive);
// This should print -8192
printf("%d", negative);

// This should print 0.125
printMask(32, 32);

【讨论】:

【参考方案2】:
int flt32_abs (int x) 
^^^            ^^^
    int mask=x>>31;
    x=x^mask;
    x=x-mask;
    return x;

我已经能够通过将float 更改为int 来解决此问题并获得 32 的结果,否则代码将无法构建并出现错误:

错误:'float'和'int'类型的无效操作数到二进制'operator>>'

有关为何 C++ 中不允许对浮点数进行二进制操作的解释,请参阅

How to perform a bitwise operation on floating point numbers

我想问问更有经验的开发者,为什么代码还要为 OP 构建?我猜是宽松的编译器设置?

【讨论】:

此代码假定 int 是 32 位 2 的补码。常见,但未由 C 定义。 注意:int mask=x&gt;&gt;31; --> 实现定义的行为。 “实现定义行为的一个例子是当有符号整数右移时高位的传播”C11 §3.4.1 投反对票的是你吗?我要删除答案吗?在阅读上面的答案之前,我对“定点”一无所知,因为遗憾的是它没有在学校教授。 您何时收到 DV? 不确定,几个小时前我昨天第一次登录时就已经存在了。

以上是关于使用位算术从二进制 int 获取绝对值的主要内容,如果未能解决你的问题,请参考以下文章

二进制的原码反码补码

java中byte的范围计算

负数二进制在32位int表示

有符号数的范围

如何使用位操作在java中获取数字的绝对值

取 CGFloat 的绝对值