如何在C语言中使用逐位and逻辑运算符实现无符号数的四倍

如何在C语言中使用逐位and逻辑运算符实现无符号数的四倍,c,floating-point,precision,unsigned,C,Floating Point,Precision,Unsigned,目标: 合法运算:任何整数/无符号运算,包括| |、&&。也如果 最多运行时间:30 返回表达式x+x+x+x的位级等效项 浮点参数f。 我的代码: 4x ( 4.400000095 ) = 17.60000038 } 您可以猜到,我的代码不起作用。输入不是翻两番,而是翻倍。我不知道为什么,因为分数和指数总是右移/左移2而不是1。我在32位机器中使用单精度浮点值。注意 unsigned 4x(unsigned uf) { unsigned expn = (uf >> 23) &am

目标:

合法运算:任何整数/无符号运算,包括| |、&&。也如果 最多运行时间:30 返回表达式x+x+x+x的位级等效项 浮点参数f。 我的代码:

4x ( 4.400000095 ) = 17.60000038
}

您可以猜到,我的代码不起作用。输入不是翻两番,而是翻倍。我不知道为什么,因为分数和指数总是右移/左移2而不是1。我在32位机器中使用单精度浮点值。

注意

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);
同上

expn <<= 2;

然而,正如@chux所指出的,您只需要将指数增加2,而不是将指数乘以4。

一些未经测试的代码-将其留给OP.GTG

棘手的一点是当*4变为正常值时,如何处理次正常值。还要注意溢出到无穷大的大值。如果要忽略次法线,只需expn+=2并检查溢出


另一种方法是expn+=2表示正常数。对于次法线,将分形从次法线移到接近无穷大的位置,代码只需将指数增加2。您无法以这种方式操作浮点数。另外,4x不是合法的函数名。两条注释都表明您有两个基本选项。第一个是包含无符号和浮点值的并集,这将允许您通过对无符号表示进行操作来避免违反严格别名的精神。下一个是声明指向浮点地址的未签名指针的技术违规。如果你被允许使用工会,那就是最好的选择;你的例子说你想要4.4*4=17.6,给或取一些分数;您的评论建议您使用x*x*x*x又名x**4,其中**是从Fortran借用的伪求幂运算符。你是说x+x+x+x吗?请清楚你想要什么-矛盾的信息使你很难给出一个好的答案。
expn <<= 2;
frac >> 2;
expn << 2;
#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;   
}