是否有一种有效的方法可以删除C ++ / Python中数字的第一位,假设您不知道该数字的大小或数据类型有多大?
我知道在Python中我可以通过获取bin(n),将字符串截断1,然后将其重新编译为int来实现,但我很好奇是否有更“数学”的方法来执行此操作。
e.g。说数字是6,二进制是110。切第一位,它变为10或2。
答案 0 :(得分:2)
有一点麻烦,一次删除一点,直到只留下最高位:
def upper_bit(x):
while x & (x - 1):
x &= x - 1
return x
现在你可以将它用作面具:
def mask_off(x, mask):
return x & ~mask
>>> mask_off(6, upper_bit(6))
2
请注意,这仅适用于正数,因为Python内联具有无限的性质。
答案 1 :(得分:1)
查看110
(小数点后6位)
最重要的位是100
(4位小数) // - 请注意,这总是2的幂
创建一个掩码:比MSB少一个011
(3个十进制)
使用按位屏蔽最高位 - 和110 & 011
= 10
(2位小数)
计算MSB(最高有效位)已经在这里和其他地方经常处理
答案 2 :(得分:1)
好吧,您可以创建一个循环,在该循环中您可以在每次迭代中将某个变量(比如x)加倍,然后检查此变量是否大于您的数字。如果是,则将其除以2并减去您的数字。例如,如果您的号码是11:
- 第一次迭代:x = 1< 11,所以继续
- 第二次迭代:x = 2< 11,所以继续
- 第三次迭代:x = 4< 11,所以继续
- 第四次迭代:x = 8< 11,所以继续
-fifth iteration:x = 16> 11,因此将x除以2:x = 8。然后从你的号码中减去8并得到答案:
11-8 = 3。
答案 3 :(得分:1)
如果您使用支持__builtin_clz
的C编译器,并且您将自己限制为__builtin_clz
支持的类型,则可以执行以下操作:
unsigned int chopWithBuiltin(unsigned int x) {
//get number of leading redundant sign bits,
//which is one less than the position of the MSB
int msb_idx = __builtin_clz(x);
//now make a mask that is all the bits below the MSB
int mask = UINT_MAX >> (msb_idx+1);
return x & mask;
}
这使用__builtin_clz
,希望在汇编时快速映射到某个东西而不是循环来检测MSB。
对于负数,您可以使用__builtin_clrsb
构建类似的内容,但它会变得复杂。
答案 4 :(得分:0)
在Python中,我会做其中一个:
def chop_msb(i):
return i >> 1 & i
print chop_msb(6)
> 2
print chop_msb(12)
> 4
print chop_msb(32)
> 0
def chop_msb2(i):
return 2**(i.bit_length()-1) ^ i
print chop_msb2(6)
> 2
print chop_msb2(12)
> 4
print chop_msb2(32)
> 0
说明:
这与@ Glenn的解决方案完全相同,但它可以更有效地计算遮罩。
这会将i
的MSB与i
进行异或。通过计算2到(i
- 1的位长度)来计算MSB(在这种情况下)。
XOR返回在第一个值或第二个值中设置的所有位,但不在两者中。这意味着在这种情况下基本上将MSB设置为0:
6: 110 XOR 100 = 010 = 2
12: 1100 XOR 1000 = 0100 = 4
32: 100000 XOR 100000 = 000000 = 0
答案 5 :(得分:0)
首先在n的以2为底的对数中通过log2(n)对数找到二进制数的长度
n = 6
l = int(log(n, 2)) + 1
由于您的数字为6,即二进制数110
,因此请找到MSB 100
(十进制为4)。
mask = 2**(l-1) #msb will always be 2^(length-1)
现在只需使用XOR运算符删除MSB
res = n^mask
一行中的代码为
n = 2**int(log(n,2)) ^ n