Python-翻转二进制文件1';s和0';它在一个字符串中

Python-翻转二进制文件1';s和0';它在一个字符串中,python,Python,我尝试以字符串形式获取一个二进制数,并翻转1和0,也就是说,将字符串中的所有1更改为0,将所有0更改为1。我是Python新手,已经绞尽脑汁想了好几个小时了,现在想弄明白它 >>> ''.join('1' if x == '0' else '0' for x in '1000110') '0111001' c中b的a是一个生成器表达式,它根据不同的序列生成一系列项。在本例中,原始序列是字符(因为您可以在Python中迭代字符串,从而获得组成该字符串的字符),而新序列是一组翻转

我尝试以字符串形式获取一个二进制数,并翻转1和0,也就是说,将字符串中的所有1更改为0,将所有0更改为1。我是Python新手,已经绞尽脑汁想了好几个小时了,现在想弄明白它

>>> ''.join('1' if x == '0' else '0' for x in '1000110')
'0111001'
c中b的
a是一个生成器表达式,它根据不同的序列生成一系列项。在本例中,原始序列是字符(因为您可以在Python中迭代字符串,从而获得组成该字符串的字符),而新序列是一组翻转了0和1的字符

'1'如果x='0'否则'0'
非常简单-它给出了
1
0
中不是
x
的那一个。我们对原始字符集中的每个这样的
x
执行此操作,然后将它们全部连接在一起(在每个项目之间有一个空字符串
'
,也称为“无”),从而得到一个最终字符串,它是原始字符的所有相反字符的组合。

将所有1替换为2,然后将0替换为1,最后将2替换为0

"10011".replace("1", "2").replace("0", "1").replace("2", "0")

Amber的回答虽然很好,但可能不是最清楚的,因此这里有一个超级基本的迭代示例:

b_string = "1100101"
ib_string = ""

for bit in b_string:
  if bit == "1":
    ib_string += "0"
  else:
    ib_string += "1"

print ib_string
这可以通过更好的方式来实现……替换、理解,但这只是一个例子


一旦你理解了这个问题的基础,我会从这个问题的其他答案中学习。这种方法既慢又痛苦。正如Muhammad Alkarouri所指出的那样,为了获得最佳的性能,
string.translate
/
maketrans
组合是一个不错的选择。它的背后是理解力。我的代码在很大程度上是最慢的。

沿着琥珀色的线条,但使用ASCII算法(没有特殊原因)。这显然不是针对生产代码的

''.join(chr(97 - ord(c)) for c in my_bit_string)

48和49分别是“0”和“1”的ASCII(和Unicode)值。为字符提供数值,反之亦然。

另一种方法是使用和


使用字典应该非常简单

>>> flip={"1":"0","0":"1"}
>>> s="100011"
>>> import sys
>>> for i in s:
...   sys.stdout.write(flip[i])
...
011100
如果速度很重要: 您已经有了表示二进制字符串的十进制整数,那么位操作稍微快一点

bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]
如果您只获得二进制字符串,则使用@Amy给出的
str.replace
方法:

s.replace('1', '2').replace('0', '1').replace('2', '0')
我测试了这里提出的各种方法和位操作方法,包括:

测试结果 给定十进制数的位操作
int

bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]

1000000 loops, best of 3: 0.647 usec per loop
bin((int(s, 2) ^ (2**(len(s)+1) - 1)))[3:]

1000000 loops, best of 3: 0.922 usec per loop
s.replace('1', '2').replace('0', '1').replace('2', '0')

1000000 loops, best of 3: 0.619 usec per loop
s.translate(str.maketrans('10', '01'))

1000000 loops, best of 3: 1.16 usec per loop
flip = {'1':'0', '0':'1'}; ''.join(flip[b] for b in s)

100000 loops, best of 3: 2.78 usec per loop
''.join('1' if b == '0' else '0' for b in s)

100000 loops, best of 3: 2.82 usec per loop
给定二进制字符串的位操作:

bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]

1000000 loops, best of 3: 0.647 usec per loop
bin((int(s, 2) ^ (2**(len(s)+1) - 1)))[3:]

1000000 loops, best of 3: 0.922 usec per loop
s.replace('1', '2').replace('0', '1').replace('2', '0')

1000000 loops, best of 3: 0.619 usec per loop
s.translate(str.maketrans('10', '01'))

1000000 loops, best of 3: 1.16 usec per loop
flip = {'1':'0', '0':'1'}; ''.join(flip[b] for b in s)

100000 loops, best of 3: 2.78 usec per loop
''.join('1' if b == '0' else '0' for b in s)

100000 loops, best of 3: 2.82 usec per loop
顺序
str.replace

bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]

1000000 loops, best of 3: 0.647 usec per loop
bin((int(s, 2) ^ (2**(len(s)+1) - 1)))[3:]

1000000 loops, best of 3: 0.922 usec per loop
s.replace('1', '2').replace('0', '1').replace('2', '0')

1000000 loops, best of 3: 0.619 usec per loop
s.translate(str.maketrans('10', '01'))

1000000 loops, best of 3: 1.16 usec per loop
flip = {'1':'0', '0':'1'}; ''.join(flip[b] for b in s)

100000 loops, best of 3: 2.78 usec per loop
''.join('1' if b == '0' else '0' for b in s)

100000 loops, best of 3: 2.82 usec per loop
str.maketrans

bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]

1000000 loops, best of 3: 0.647 usec per loop
bin((int(s, 2) ^ (2**(len(s)+1) - 1)))[3:]

1000000 loops, best of 3: 0.922 usec per loop
s.replace('1', '2').replace('0', '1').replace('2', '0')

1000000 loops, best of 3: 0.619 usec per loop
s.translate(str.maketrans('10', '01'))

1000000 loops, best of 3: 1.16 usec per loop
flip = {'1':'0', '0':'1'}; ''.join(flip[b] for b in s)

100000 loops, best of 3: 2.78 usec per loop
''.join('1' if b == '0' else '0' for b in s)

100000 loops, best of 3: 2.82 usec per loop
''。使用字典映射加入

bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]

1000000 loops, best of 3: 0.647 usec per loop
bin((int(s, 2) ^ (2**(len(s)+1) - 1)))[3:]

1000000 loops, best of 3: 0.922 usec per loop
s.replace('1', '2').replace('0', '1').replace('2', '0')

1000000 loops, best of 3: 0.619 usec per loop
s.translate(str.maketrans('10', '01'))

1000000 loops, best of 3: 1.16 usec per loop
flip = {'1':'0', '0':'1'}; ''.join(flip[b] for b in s)

100000 loops, best of 3: 2.78 usec per loop
''.join('1' if b == '0' else '0' for b in s)

100000 loops, best of 3: 2.82 usec per loop
''。使用条件加入

bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]

1000000 loops, best of 3: 0.647 usec per loop
bin((int(s, 2) ^ (2**(len(s)+1) - 1)))[3:]

1000000 loops, best of 3: 0.922 usec per loop
s.replace('1', '2').replace('0', '1').replace('2', '0')

1000000 loops, best of 3: 0.619 usec per loop
s.translate(str.maketrans('10', '01'))

1000000 loops, best of 3: 1.16 usec per loop
flip = {'1':'0', '0':'1'}; ''.join(flip[b] for b in s)

100000 loops, best of 3: 2.78 usec per loop
''.join('1' if b == '0' else '0' for b in s)

100000 loops, best of 3: 2.82 usec per loop

您已经标记了这个问题的答案,但我还没有看到我更喜欢的方法。我在这里假设你有一个已知长度的二进制数,在我给出的例子中是8位

如果您可以仅以数字开头,则可以执行以下操作:

myNumber = 0b10010011
myNumberInverted = myNumber ^ 0b11111111
^
运算符执行按位异或运算

如果确实必须从字符串开始,则可以先转换为整数,然后执行此操作

myString = '10010011'
myNumber = int(myString, 2)
myNumberInverted = myNumber ^ 0b11111111

自从这个问题被回答后,有些事情已经改变了。希望我的更新对某人有用

翻译方法对我来说是最快的。完整的测试代码如下

感谢您之前的贡献,让我能够测试这一点

# System & Software
# core i7 4790k @ ~ 4.6 GHz   32 GB RAM   Samsung Evo NVME
# Visual Studio 2019 16.3.6

# I do not understand Will's bit manipulation code
# worst times shown in comments
# ordered by speed on my system

import timeit # required to use timeit
import string # Required to call maketrans function.

# https://www.afternerd.com/blog/timeit-multiple-lines/
# if you are trying to time slightly longer pieces of code than a single line
# timeit wants a string


# the syntax  b_string.translate(maketrans("10", "01"))
# presented by Muhammad Alkarouri does not appear to be valid anymore
# i suspect this is due to changes within python versions
a1_bit_flip = """\
a1 = 0b1101010001101111 # accepts the binary input but will store it as an int
a1_bin = bin(a1)[2:]
# creates a string of the binary form of the integer minus the first 2 characters
flip_bin_a1 = a1_bin.translate(str.maketrans("10","01"))"""

trans_time = timeit.timeit(a1_bit_flip, number=100000) # time 100k iterations
print('translate time')
print(trans_time / 100000)
# determine average time of a single iteration ~ 0.6282 us
print('\n')



a2_bit_flip = """\
a2 = 0b1101010001101111
a2_bin = bin(a2)[2:]
a2_bin.replace('1', '2').replace('0', '1').replace('2', '0')"""

replace_time = timeit.timeit(a2_bit_flip, number=100000) # time 100k iterations
print('replace time')
print(replace_time / 100000)
# determine average time of a single iteration ~ 0.7557 us
print('\n')



a3_bit_flip = """\
a3 = 0b1101010001101111
a3_bin = bin(a3)[2:]
bin((int(a3_bin, 2) ^ (2**(len(a3_bin)+1) - 1)))[3:]"""
# I do not understand this line (Will)

bin_bit_time = timeit.timeit(a3_bit_flip, number=100000)
# time 100k iterations
print('bin_bit time')
print(bin_bit_time / 100000)
# determine average time of a single iteration ~ 1.14 us
print('\n')



a4_bit_flip = """\
a4 = 0b1101010001101111
a4_bin = bin(a4)[2:]
bin((i ^ (2 ** (i.bit_length()+1) - 1)))[3:]"""
# I do not understand this line (Will)

int_bit_time = timeit.timeit(a3_bit_flip, number=100000) # time 100k iterations
print('int_bit time')
print(int_bit_time / 100000)
# determine average time of a single iteration ~ 1.14 us
print('\n')



join_bit_flip = """\
a0 = 0b1101010001101111 # accepts the binary input but will store it as an int
a0_bin = bin(a0)[2:]
# creates a string of the binary form of the integer minus the first 2 characters
flip_a0 = "".join('1' if x == '0' else '0' for x in a0_bin)""" # (Amber)

join_time = timeit.timeit(join_bit_flip, number=100000) # time 100k iterations
print('join time')
print(join_time / 100000)
# determine average time of a single iteration ~ 14.511 us
print('\n')

聪明。我喜欢理解力+1为了使其过于巧妙,您可以选择将
if
表达式替换为
'01'[x=='0']
。我还是喜欢你的答案,但我想提一下。我想避免鼓励人们对字符串使用
+=
,而不是
join()
——这不仅是
join()
,更像Pythonic,而且对于一般用法来说也是更有效的方法。尽早灌输这是一个好习惯。使用Python一段时间后,对于
循环,人们往往会发现列表理解比
更清晰。我个人更喜欢这种理解,它对我来说更有意义。一般来说,不要猜测时间。在本例中,
timeit'。join('1'如果x='0'或者'0'对于b_字符串中的x)
在我的机器上给出5.3微秒,而
timeit b_字符串.translate(maketrans(“10”,“01”))
给出979纳秒。您可能想链接到比Python 2.3稍新的文档-可能根本没有注意到我链接到了这样的旧文档,谢谢。为了完全正确,您(正确地)使用了以下方法:不是Amber链接到的不推荐使用的字符串函数。您已经标记了对此的答案,但是你可能想看看
struct.pack
unpack
wrack(v)来销毁;根据你的目标(在我打高尔夫球的情况下,这可能是一个很好的答案,干杯。在我的笔记本电脑上,位操作解决方案比顺序解决方案快。
s=“0101010101010010101000010111010110110110”
%timeit-bin((int(s,2)^(2**(len(s)+1))[3:]
1000000个循环,每个循环3:495ns的最佳值
%timeit s.replace('1','2')。replace('0','1')。replace('2','0')
1000000个循环,每个循环3:690ns的最佳值