0

私はついにこのことを壊そうとしていますが、それでもこれのオーバーフローを監視する方法がわかりません。

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)のようなオーバーフロー動作を含めることです。

では、オーバーフロー動作を含めるにはどうすればよいですか?私はこれらの操作のみを使用できます:!〜&^ | + << >>ループ、キャスト、関数の宣言はありません。私はとても近くにいるので痛いです。

編集

ゼロに向けた丸めを実装する必要があります。

4

4 に答える 4

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

補遺、負の場合はゼロに向かって丸めます:

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
于 2012-09-26T19:51:58.927 に答える
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. 正しい符号を復元する

もちろん、最小数を超えると、-1 から始まります。ちなみに、-許可された演算子で動作を実装できるので、演算子を自由に使用できましたが、読みやすいと思います。

于 2012-09-26T20:35:01.527 に答える
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;
}

明らかに、上記はさらに圧縮/縮小することができます。追加の変数は明確にするためのものです。

左シフトが回避されるため、オーバーフローが発生しないことに注意してください。

于 2012-09-26T20:18:49.250 に答える
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 より下で始まり、オーバーフローを超えて続きます。整数オーバーフローは、符号なし整数に対してのみ明確に定義されていることに注意してください。

#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;
}
于 2012-09-26T19:34:10.170 に答える