如何在python中获取整数的符号位?

时间:2017-07-12 13:23:54

标签: python

我希望能够在python中访问数字的符号位。我可以在C中执行n >> 31之类的操作,因为int表示为32位。

我不能使用条件运算符和> <

4 个答案:

答案 0 :(得分:6)

在python 3中,整数没有固定的大小,并且没有使用内部CPU表示法表示(它允许处理非常大的数字而没有麻烦)。

所以最好的方法是

signbit = 1 if n < 0 else 0

signbit = int(n < 0)

编辑:如果你不能使用<>(这是可笑的,但也是如此)你可以使用a-b如果a大于{{b将为正的事实1}},所以你可以做到

abs(a-b) == a-b

不使用<>(至少在文字中,因为abs使用它,您可以信任我)

答案 1 :(得分:2)

我认为在Python中并没有真正的符号位概念。就程序员而言,int只是具有特定行为的类型。您无法访问低级别表示。即使bin(-3)返回“否定”二进制表示形式:'-0b11'

但是,如果两个整数没有比较,有很多方法可以获得符号或更大的符号。以下方法滥用浮点数学以避免比较。

def sign(a):
    try:
        return (1 - int(a / (a**2)**0.5)) // 2
    except ZeroDivisionError:
        return 0

def return_bigger(a, b):
    s = sign(b - a)
    return a * s + b * (1 - s)


assert sign(-33) == 1
assert sign(33) == 0    

assert return_bigger(10, 15) == 15
assert return_bigger(25, 3) == 25
assert return_bigger(42, 42) == 42
  • (a**2)**0.5可以替换为abs但我在内部打赌这是通过比较来实现的。
  • 如果您不关心0或相等的整数(或者可能存在其他可怕的数学解决方法),则不需要try / except
  • 最后,我想指出,我完全不知道为什么有人会想要实现类似的东西,除了它的地狱。

答案 2 :(得分:2)

为什么右移符号位以产生1或0在Python中不起作用的原因是,从概念上讲,负整数的位表示用无限数 1 填充左边的位(就像非负数被视为填充有无限数量的 0 位一样)。但是操作n >> 31确实有效(假设n在带符号的32位数字范围内),因为它放置了符号位(或者,如果您愿意,可以使用左填充之一)位)的最低位。您只需要去除其余的左填充位,就可以使用按位操作来完成此操作,如下所示:

n >> 31 & 1

或者您可以利用所有一位表示-1的事实,并简单地对结果求反:

-(n >> 31)

或者,除了最低的32个 1 位以外,您还可以在进行移位之前将其切掉,如下所示:

(n & 0xffffffff) >> 31

所有这些都是在假设您使用的数字适合带符号的32位int的情况下进行的。如果n可能需要用64位表示,则移位63位而不是31位;如果它只有16位数字,则移位15位就足够了(并且,如果使用(n & 0xffffffff) >> 31变体,请调整f的数量)

在机器代码级别,求和/求反和移位可能比使用比较更有效率。前者只是一些机器指令,而后者通常会简化为分支。分支不仅需要更多的机器指令,而且还会对现代CPU的流水线乱序执行产生不良影响。 Python的执行与机器代码的执行之间存在一定距离,因此,要说出任何有关Python的性能影响的信息都比较困难。它可能取决于上下文(就像在机器代码中一样),因此通常也很难进行测试。 (注意:我对CPython或一般情况下在Python中如何执行低级执行了解不多。对于执行此操作的人,这可能并不难回答。)

如果您不知道n有多大(在Python中,不需要整数就可以容纳任何特定位数),则可以使用bit_length()进行查找。这将适用于任何大小的整数:

-(n >> n.bit_length())

bit_length()操作可能会归结为一条机器指令,或者实际上可能需要一个循环来查找结果,具体取决于实现和底层机器体系结构,在后一种情况下,这应该是比使用常量要昂贵得多

最后的评论:实际上,n >> 31不能保证像您在C语言中一样工作,因为C语言对>>是否进行逻辑右移(例如您)没有定义假设)或算术右移(就像Python一样)。在某些语言中,例如Java,您可以使用>>>运算符保证逻辑右移,而使用>>保证算术右移。

答案 3 :(得分:0)

这个怎么样?

def is_negative(num, places):
    return not long(num * 10**places) & 0xFFFFFFFF == long(num * 10**places)

效率不高,但未使用&lt;或者&gt;绝对限制你的怪异。请注意,零将评估为正数。