我的一个伙伴有这些谜题,这是一个躲避我的人。这是问题,给你一个数字,你想要返回该数字乘以3并除以16舍入为0.应该很容易。抓到了吗?你只能使用! 〜& ^ | +<< >>运营商和他们只是12的组合。
int mult(int x){
//some code here...
return y;
}
我的尝试是:
int hold = x + x + x;
int hold1 = 8;
hold1 = hold1 & hold;
hold1 = hold1 >> 3;
hold = hold >> 4;
hold = hold + hold1;
return hold;
但这似乎不起作用。我想我有丢失的问题,但我似乎无法想出一种拯救它们的方法。另一种观点是好的。只是要添加,你也可以只使用int类型的变量而不使用循环,如果可以使用语句或函数调用。
现在我有号码0xfffffff。它应该返回0x2ffffff,但它返回0x3000000。
答案 0 :(得分:3)
对于这个问题,你需要担心分裂前的丢失位(显然)。
基本上,如果它是负数,那么你想在乘以3后加15.一个简单的if
语句(使用你的运算符)就足够了。
我不打算给你代码,但一步一步看起来像,
x = x*3
获取标志并将其存储在变量blarg中。
有另一个变量hold x + 15;
设置一个if语句,如果x为负数,则使用添加的15,如果不是,则使用常规数字(我们在上面执行的次数为3次)。
然后除以16你已经告诉你知道该怎么做。祝你好运!
答案 1 :(得分:2)
这似乎有效(只要不发生溢出):
((num<<2)+~num+1)>>4
试试这个JavaScript代码,在控制台中运行:
for (var num = -128; num <= 128; ++num) {
var a = Math.floor(num * 3 / 16);
var b = ((num<<2)+~num+1)>>4;
console.log(
"Input:", num,
"Regular math:", a,
"Bit math:", b,
"Equal: ", a===b
);
}
答案 2 :(得分:1)
你可以做的是首先除以4然后再加3次然后再加4。
3*x/16=(x/4+x/4+x/4)/4
有了这个逻辑,程序就可以
main()
{
int x=0xefffffff;
int y;
printf("%x",x);
y=x&(0x80000000);
y=y>>31;
x=(y&(~x+1))+(~y&(x));
x=x>>2;
x=x&(0x3fffffff);
x=x+x+x;
x=x>>2;
x=x&(0x3fffffff);
x=(y&(~x+1))+(~y&(x));
printf("\n%x %d",x,x);
}
AND与0x3fffffff使msb为零。它甚至可以将数字转换为正数。 这使用2的负数补码。使用直接分割方法,负数的位精度会有所损失。所以使用这个工作来转换-ve到+ ve数然后执行除法运算。
答案 3 :(得分:1)
将正整数n
除以16时,得到正整数商k
和余数c < 16
:
(n/16) = k + (c/16).
(或者只是应用欧几里得算法。)问题要求乘以3/16
,所以乘以3
(n/16) * 3 = 3k + (c/16) * 3.
数字k
是一个整数,因此部分3k
仍然是整数。但是,int
算术会向下舍入,因此如果先划分,则第二项可能会失去精度。自c < 16
起,您可以安全地乘以而不会溢出(假设为sizeof(int) >= 7
)。所以算法设计可以
(3n/16) = 3k + (3c/16).
k
只是n/16
向下舍入为0.因此,k
可以通过应用单个AND
操作找到。另外两项操作将提供3k
。操作次数:3。c
操作(缺少的位)找到余数AND
。乘以3再使用两个操作。轮班完成了分工。操作次数:4。总操作次数:8。
上述算法使用移位操作。它可能不适用于否定。但是,假设两个补码,n
的符号存储在符号位中。可以通过应用算法将其删除并重新应用于答案。
n
的符号,只需一个AND
即可。OR
。OR
操作。这使最终的操作次数达到11次。
答案 4 :(得分:1)
请注意,C99标准在6.5.7节中指出,有符号负整数的右移调用实现定义的行为。根据{{1}}由32位组成并且有符号整数映射到算术移位指令的规定,以下代码适用于所有int
输入。一个完全可移植的解决方案也可以满足问题中提出的要求,但我现在想不到一个。
我的基本想法是将数字分成高位和低位以防止中间溢出。首先将高位除以16(这是精确的操作),然后乘以3。首先将低位乘以3,然后除以16.由于算术右移向负无穷大而不是像整数除法那样向零舍入,因此需要对负数的右移应用校正。对于N的右移,如果要移位的数字为负,则需要在移位之前加上2 N -1。
int