乘以5/8并注意溢出

时间:2012-09-26 18:30:47

标签: c overflow bit-manipulation

我真的很接近终于打破了这个东西,但我仍然不知道如何看待溢出。

int multFiveEighths(int x) {

    int y=((x<<2)+x);
    int f=((y>>3)+1);
    int z=(y>>3);



    return f + ((~!(x>>31&1)+1) & (z+~f+1));

我乘以5/8,并使用条件按位来说: 如果符号位为1(数字为负),请使用f,否则为z。

其中一部分是包含溢出行为,如C表达式(x * 5/8)

那么如何包含溢出行为? 我只能使用这些操作: 〜&amp; ^ | +&lt;&lt; &GT;&GT; 没有循环,没有铸造,没有声明功能。 我很亲密,很痛苦。

修改

我必须实现向零舍入。

4 个答案:

答案 0 :(得分:2)

int x = num >> 3; // divide by 8 (only defined for positive values)

x = x << 2 + x;   // multiply by 5; no overflow yet since 5/8 is less than one

int y = num & 7;  // the bits we shifted out

y = y << 2 + y;   // multiply by 5; no overflow

return (x + (y >> 3)); // the two pieces

ADDENDUM,为零负向:

int s = -((num >> 31) & 1); // sign bit as -1 or 0

int n = (num ^ s) - s; // twos complement if negative

int x = n >> 3; // divide by 8

x = (x << 2) + x;   // multiply by 5; no overflow yet since 5/8 is less than one

int y = n & 7;  // the bits we shifted out

y = (y << 2) + y;   // multiply by 5; no overflow

return (s ^ (x + (y >> 3))) - s; // the two pieces and complemented back

答案 1 :(得分:1)

我希望这是你在寻找的东西:

int multFiveEights(int x) {

  int isneg = (x>>31);

  // Negative x
  int nx = -x;

  int value = ( (~!!(isneg)+1) &  nx ) + ( (~!(isneg)+1) & x );

  /* Now its positive */
  value = (value<<2) + value;
  value = value & ((-1)>>1); // This mask should produce the desired overflow behavior
  value = (value>>3);

  value = ( (~!!(isneg)+1) & (-value)) + ( (~!(isneg)+1) & (value));

  return value;
}

这个想法非常简单:

  1. 将参数转换为正数
  2. 在乘法后将最高有效位掩码为0(这应该实现溢出行为)
  3. 划分
  4. 恢复正确的标志
  5. 当然,如果超过最小数字,则从-1开始。 顺便说一下,我可以自由地使用-运算符,因为它的行为可以使用您允许的运算符来实现,但我发现它更容易阅读。

答案 2 :(得分:0)

我相信这段代码应该涵盖溢出要求。

请注意这样的代码在现实世界中没有用处。

#include <stdint.h>

uint32_t mult_five_eights (uint32_t num)
{
  num = (num << 2) + num; // multiply by 5
  return num >> 3;        // divide by 8
}

修改

演示溢出的演示程序。它从最大可能的int开始,然后继续溢出。请注意,整数溢出只能为 unsigned 整数定义良好。

#include <stdint.h>
#include <limits.h>
#include <stdio.h>

uint32_t mult_five_eights (uint32_t num)
{
  num = (num << 2) + num; // multiply by 5
  return num >> 3;        // divide by 8
}


int main()
{
  uint32_t i;

  for(i=UINT_MAX/5-10; i<UINT_MAX/5+10; i++)
  {
    uint32_t x = i*5/8;
    uint32_t y = mult_five_eights(i);

    printf("%u %u %u ", i, x, y);

    if(x != y)
    {
      printf("error this should never happen");
    }
    printf("\n");

  }

  return 0;
}

答案 3 :(得分:0)

int five_eights(int val)
{
int ret, car;

car = ((val&7)+((val&1) <<2)) & 5;
car = (car | (car >>2)) &1;

ret = ((val+1) >>1) + ((val+4) >>3) ;

return ret-car;
}
显然,以上可以进一步压缩/缩小;额外的变量是为了清晰起见。

请注意避免左移,因此无法溢出。