如何使用C中位方式和逻辑运算符来翻两番一个无符号数 [英] How to quadruple an unsigned number using bit-wise and logic operator in C
问题描述
目标:
4倍(4.400000095)= 17.60000038
- 法律OPS:任意整数/无符号运算含。 ||,&安培;&放;.此外,如果,而
- 最大OPS:30
- 返回位水平相当于前$的对$ pssion X + X + X + X为
- 浮点参数F。
块引用>我的code:
符号4X(无符号UF){
无符号EXPN =(UF>> 23)及0xFF的;
无符号的符号= UF&安培; 0x80000000的;
无符号压裂= UF&安培; 0x007FFFFF;
如果(EXPN == || 255(EXPN == 0安培;&安培;压裂== 0))
返回UF;
如果(EXPN){
EXPN<< 2;
}否则如果(压裂== 0x7FFFFF){
压裂>> 2;
EXPN<< 2;
}其他{
压裂&所述;&下; = 2;
}返回(标志)| (EXPN<< 23)| (压裂);}
正如您可以猜到,我的code不起作用。代替四倍的输入,所述输入被加倍。我不知道为什么,因为小数和指数总是被左/右按2,而不是1进出口单precision浮点值的工作在32位机器移位。
解决方案一些未经检验的code - 留到OP。 (GTG)
棘手位处理分普通号,当* 4趋于正常。同时还要注意这个溢出到无穷大的值。如果你想忽略子法线,只是
EXPN + = 2
和检查溢出。另一种方法是
。EXPN + = 2
正常的数字。对于子法线,移压裂<< = 2
和处理案件趋于正常。code为约30欢声笑语。
的#include< stdint.h>浮X4(浮X){
//使用union来访问位。跨越式的信仰在这里(浮点为32位,尾数)
工会{
浮F;
uint32_t的U32;
} U;
u.f = X;
uint32_t的EXPN =(u.u32>> 23)及0xFF的;
uint32_t的签名= u.u32&安培; 0x80000000的;
uint32_t的压裂= u.u32&安培; 0x007FFFFF; //楠天道酬勤
如果(EXPN == 255)返回u.f; 如果(EXPN == 0){
EXPN ++; //把分一般为正常范围世博会
}其他{
压裂+ =从0x800000; //恢复隐含位
} // * 4
压裂&所述;&下; = 2; //规范化 - 这通常两次迭代,少子法线
而(压裂> 0XFFFFFF){
EXPN ++;
压裂>> = 1; // 1的将不被移出为2 LSB是0,因此最迟四舍五入
} //溢出INF
如果(EXPN> = 255){
EXPN = 255;
压裂= 0;
}否则如果(压裂&安培;从0x800000){
压裂^ =从0x800000; //明确隐含位
}其他{
//仍低于正常
expn--; //现在应该0
} u.u32等号(=)| (EXPN<< 23)|压裂;
返回u.f;
}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.
解决方案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 thefrac <<= 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; }
这篇关于如何使用C中位方式和逻辑运算符来翻两番一个无符号数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!