How to quadruple an unsigned number using bit-wise and logic operator in C

℡╲_俬逩灬. 提交于 2019-12-19 05:02:01

问题


Goal:

4x ( 4.400000095 ) = 17.60000038
  • Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
  • Max ops: 30
  • Return bit-level equivalent of expression x + x + x + x for
  • floating point argument f.

My code:

unsigned 4x(unsigned uf) {
unsigned expn = (uf >> 23) & 0xFF;
unsigned sign = uf & 0x80000000;
unsigned frac = uf & 0x007FFFFF;
if (expn == 255 || (expn == 0 && frac == 0))  
    return uf;
if (expn) {
    expn << 2;
} else if (frac == 0x7FFFFF) {
    frac >> 2;
    expn << 2;
} else {
    frac <<= 2;
}

return (sign) | (expn << 23) | (frac);

}

As you can guess, my code does not work. Instead of quadrupling the input, the input is doubled. I don't know why since the fraction and exponent are always being right / left shifted by 2 instead of 1. Im working with single precision floating point values in 32 bit machines.


回答1:


Some untested code - leave that for OP. (GTG)

The tricky bit is dealing with sub-normal numbers that when *4 become normal. Also watch for large values that overflow to infinity. If you want to ignore sub-normals, just expn += 2 and check for overflow.

Another approach would expn += 2 for normal numbers. For sub-normals, shift the frac <<= 2 and handle cases that become normal.

Code is about 30 ops.

#include <stdint.h>

float x4(float x) {
  // Use union to access the bits.  Leap-of-faith here (float is 32 bits, endian)
  union {
    float f;
    uint32_t u32;
  } u;
  u.f = x;
  uint32_t expn = (u.u32 >> 23) & 0xFF;
  uint32_t sign = u.u32 & 0x80000000;
  uint32_t frac = u.u32 & 0x007FFFFF;

  // Nan Inf
  if (expn == 255) return u.f;

  if (expn == 0) {
    expn++;  // Bring sub-normal into normal expo range
  } else {
    frac += 0x800000; // restore implied bit
  }

  // *4
  frac <<= 2;

  // normalize - this usually iterates twice, less for sub-normals
  while (frac > 0xFFFFFF) {
    expn++;
    frac >>= 1; // 1's will not be shifted out as 2 LSB are 0 so no later rounding
  }

  // overflow to inf
  if (expn >= 255) {
    expn = 255;
    frac = 0;
  } else if (frac & 0x800000) {
    frac ^= 0x800000; // clear implied bit
  } else {
    // still sub-normal
    expn--;  // should now be 0
  }

  u.u32 = sign | (expn << 23) | frac;
  return u.f;   
}



回答2:


Note that

expn << 2;

does not modify expn. You probably want

expn <<= 2;

Ditto for

frac >> 2;
expn << 2;

However, as @chux pointed out, you only need to increase add 2 to the exponent, not multiply the exponent by 4.



来源:https://stackoverflow.com/questions/35168306/how-to-quadruple-an-unsigned-number-using-bit-wise-and-logic-operator-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!