Python int 到二进制字符串?
Posted
技术标签:
【中文标题】Python int 到二进制字符串?【英文标题】:Python int to binary string? 【发布时间】:2010-10-16 12:55:24 【问题描述】:在 Python 中是否有任何固定的 Python 方法可以将 Integer(或 Long)转换为二进制字符串?
Google 上有无数的 dec2bin() 函数...但我希望我可以使用内置函数/库。
【问题讨论】:
反之,纯字符串处理算法见this。 【参考方案1】:Python 的字符串格式方法可以采用格式规范。
>>> "0:b".format(37)
'100101'
Format spec docs for Python 2
Format spec docs for Python 3
【讨论】:
str.format()
仅仅格式化一个值是多余的。直接去format()
function:format(n, 'b')
。无需解析占位符并将其与参数匹配,直接进行值格式化操作本身。如果您需要将格式化结果放在更长的字符串中(例如,将其用作模板),请仅使用 str.format()
。
@mike:或者使用格式化规范。将带前导 0
的位数添加到格式化字符串:format(10, '016b')
格式化为带前导零的 16 位。
通常使用 4/8/... 位表示:":08b".format(37)
f"37:b" 在 Python3.7 或更高版本中。
这里有一个负数问题。 @nate 没有明确指定在这种情况下所需的输出是什么,但纯粹是二进制数,不存在负号。所以最高位一般用于负号。假设我们使用 8 位整数,-37 将是0b10100101
。但是对于无符号整数,该值将是 165。所以它不是这么简单。答案应该反映这一点。【参考方案2】:
如果您正在寻找 bin()
等同于 hex()
,它是在 python 2.6 中添加的。
例子:
>>> bin(10)
'0b1010'
【讨论】:
还要注意,str(bin(i))[2:]
(1000000ops 为 0.369s)比 "0:b".format(i)
(1000000ops 为 0.721s)更快
@mVChr 如果有人将数字转换为 ASCII 二进制表示,我真的希望速度无关紧要。
@mVChr: str.format()
无论如何都是错误的工具,你应该改用format(i, 'b')
。考虑到这也为您提供了填充和对齐选项; format(i, '016b')
格式化为 16 位零填充二进制数。要对bin()
执行相同操作,您必须添加str.zfill()
调用:bin(i)[2:].zfill(16)
(无需调用str()
!)。 format()
的可读性和灵活性(bin()
的动态格式化要困难得多)是很好的权衡,除非必须,否则不要优化性能,然后再优化可维护性。
[2:] 是什么意思?
当然,使用 python 3.6+ 你现在可以使用f"37:b"
。【参考方案3】:
Python 实际上确实为此内置了一些功能,可以执行诸如'0:b'.format(42)
之类的操作,这将为您提供42
的位模式(在字符串中),或者101010
.
就更一般的理念而言,没有任何语言或库会为其用户群提供他们想要的一切。如果您在一个不能完全提供您需要的环境中工作,那么您应该在开发时收集 sn-ps 代码,以确保您永远不必重复编写相同的东西。比如伪代码:
define intToBinString, receiving intVal:
if intVal is equal to zero:
return "0"
set strVal to ""
while intVal is greater than zero:
if intVal is odd:
prefix "1" to strVal
else:
prefix "0" to strVal
divide intVal by two, rounding down
return strVal
它将根据十进制值构造您的二进制字符串。请记住,这是一种通用的伪代码,它可能不是最最有效的方法,但对于您似乎提出的迭代,它不会有太大的不同。它实际上只是作为如何完成的指南。
总体思路是使用以下代码(按优先顺序):
语言或内置库。 具有合适许可证的第三方库。 您自己的收藏。 您需要编写一些新内容(并保存在您自己的收藏中以备日后使用)。【讨论】:
这个答案有一些很好的建议。太糟糕了,代码太慢了。你提出了一个 O(N^2) 算法,而 O(N) 可以。有问题的部分在s = "1" + s
和s = "0" + s
行中。每个都制作了一个不必要的 s 副本。您应该在返回之前反转字符串。
@Andreas,我建议是使用'0:b'.format(42)
,slow 方法只是一个通用的示例,它可能是也可能不是 O( n^2) 取决于使用的实际语言。它只是看起来像 Python,因为 Python 是一种理想的伪代码语言,所以我将对其进行更改以使其清楚。
实际上,当s
是字符串类型时,s = "1" + s
不是 O(N),这将是一种非常深奥的语言。也许是一种所有字符串都向后存储的语言,或者每个字符都是链表中的一个节点?对于任何典型的语言,字符串基本上是一个字符数组。在这种情况下,为字符串添加前缀需要制作副本,否则您将如何将字符放在其他字符之前?
我可以很容易地设想一个字符串类型,它由一块内存组成,其中字符串在该块内是右对齐的,并且它的起始字符有一个偏移量。要为字符添加前缀,您只需减少偏移量并将字符存储在那里。是的,这会是深奥的,但对我来说,用一些伪代码争论可能的现实世界问题是没有意义的,尤其是,因为你不太可能有超过几十位/迭代。如果您的数据量很小,即使是备受诟病的冒泡排序也足够了 :-) 无论如何,我会添加关于效率的说明。
当然,如果效率很重要,您可能不会选择 Python。尽管如此,根据我的经验,经常发生这样的情况,即使用 O(N²) 算法简单编写并使用小数据集进行测试的代码很快就会用于更大的数据集,因为“它似乎有效”。然后突然之间你的代码需要几个小时才能运行,而修复后可能只需要几秒钟。 O(N²) 算法是阴险的,因为它们似乎可以工作一段时间,但是当您的数据扩展时,它们就不行了,到那时编写它们的人已经退出了,没有人知道为什么事情会永远持续下去。【参考方案4】:
如果你想要一个没有 0b 前缀的文本表示,你可以使用这个:
get_bin = lambda x: format(x, 'b')
print(get_bin(3))
>>> '11'
print(get_bin(-3))
>>> '-11'
当你想要一个 n 位表示时:
get_bin = lambda x, n: format(x, 'b').zfill(n)
>>> get_bin(12, 32)
'00000000000000000000000000001100'
>>> get_bin(-12, 32)
'-00000000000000000000000000001100'
或者,如果您更喜欢函数:
def get_bin(x, n=0):
"""
Get the binary representation of x.
Parameters
----------
x : int
n : int
Minimum number of digits. If x needs less digits in binary, the rest
is filled with zeros.
Returns
-------
str
"""
return format(x, 'b').zfill(n)
【讨论】:
或者只使用format(integer, 'b')
。 bin()
是一个调试工具,专门用于生成 Python 二进制整数文字语法,format()
旨在生成特定格式。
@MartijnPieters 非常感谢您提及它。我已经调整了我的解决方案。你怎么知道bin()
是一个旨在生成 Python 二进制整数文字语法的调试工具?我在文档中找不到。
来自文档:结果是一个有效的 Python 表达式。它的目的是生成 Python 表达式,而不是生成最终用户表示。这同样适用于oct()
和hex()
。
更多替代方案:如果要使宽度动态化,则可以使用 str.zfill()
而不是 str.format()
或 format()
与动态第二个参数:'0:01b'.format(x, n)
或 format(b, '0b'.format(n))
。
@MartijnPieters 哇,非常感谢您的意见!我不知道这是可能的格式。但是,我认为我目前对zfill
的回答比动态的第二个参数更容易阅读和理解,所以我会保留它。【参考方案5】:
作为参考:
def toBinary(n):
return ''.join(str(1 & int(n) >> i) for i in range(64)[::-1])
该函数可以转换一个最大为18446744073709551615
的正整数,表示为字符串'1111111111111111111111111111111111111111111111111111111111111111'
。
可以修改它以提供更大的整数,尽管它可能不如"0:b".format()
或bin()
方便。
【讨论】:
@GarethDavidson 这是哪个版本?在谷歌搜索时,明确说明这一点可能会有更大的用途。 我认为是 2.7 版。我怀疑它是否适用于 3.x【参考方案6】:这适用于 python 3,它保留前导零!
print(format(0, '08b'))
【讨论】:
我很欣赏这个简单的答案。 非常感谢。可惜这个答案太落后了。 太棒了!这就是我要找的。span> 【参考方案7】:我很惊讶没有提到使用 Python 3.6 及更高版本支持的格式化字符串来完成此任务的好方法。 TLDR:
>>> number = 1
>>> f'0bnumber:08b'
'0b00000001'
更长的故事
这是 Python 3.6 提供的格式化字符串的功能:
>>> x, y, z = 1, 2, 3
>>> f'x y 2*z'
'1 2 6'
您也可以请求二进制文件:
>>> f'z:b'
'11'
指定宽度:
>>> f'z:8b'
' 11'
请求零填充:
f'z:08b'
'00000011'
并添加通用前缀来表示二进制数:
>>> f'0bz:08b'
'0b00000011'
您也可以让 Python 为您添加前缀,但我不喜欢上面的版本,因为您必须考虑前缀的宽度:
>>> f'z:#010b'
'0b00000011'
更多信息可在Formatted string literals 和Format Specification Mini-Language 的官方文档中找到。
【讨论】:
添加下划线:f'0bz:09_b'
=> '0b0000_0011'
字节序呢?可以换吗?
这超出了这个问题的范围。最重要的第一个是如何在位置系统中写入数字的规范方式,而不管系统字节顺序如何,这只是一个实现细节。您可以执行f'z:08b'[::-1]
来实现最低有效字节优先排序,但是恕我直言,在大多数情况下这只会引起混淆......【参考方案8】:
一个简单的方法是使用字符串格式,见page。
>> "0:b".format(10)
'1010'
如果你想要一个固定长度的二进制字符串,你可以使用这个:
>> "0:fill8b".format(10, fill='0')
'00001010'
如果需要补码,则可以使用以下行:
'0:fillwidthb'.format((x + 2**n) % 2**n, fill='0', width=n)
其中 n 是二进制字符串的宽度。
【讨论】:
【参考方案9】:带有 lambda 的单线:
>>> binary = lambda n: '' if n==0 else binary(n/2) + str(n%2)
测试:
>>> binary(5)
'101'
编辑:
然后:(
t1 = time()
for i in range(1000000):
binary(i)
t2 = time()
print(t2 - t1)
# 6.57236599922
对比
t1 = time()
for i in range(1000000):
'0:b'.format(i)
t2 = time()
print(t2 - t1)
# 0.68017411232
【讨论】:
虽然返回 '' 为 0。 0 的正常表示不是“0”吗? 如果你想看到那个 0 :),你可以将''
替换为 '0'
,但它会为任何数字添加前导 0。【参考方案10】:
由于前面的答案大多使用 format(), 这是一个 f-string 实现。
integer = 7
bit_count = 5
print(f'integer:0bit_countb')
输出:
00111
为方便起见,这里是格式化字符串文字的 python 文档链接:https://docs.python.org/3/reference/lexical_analysis.html#f-strings。
【讨论】:
【参考方案11】:备选方案总结:
n=42
assert "-101010" == format(-n, 'b')
assert "-101010" == "0:b".format(-n)
assert "-101010" == (lambda x: x >= 0 and str(bin(x))[2:] or "-" + str(bin(x))[3:])(-n)
assert "0b101010" == bin(n)
assert "101010" == bin(n)[2:] # But this won't work for negative numbers.
贡献者包括John Fouhy、Tung Nguyen、mVChr、Martin Thoma。和 Martijn Pieters。
【讨论】:
str.format()
只是格式化一个值是多余的。直接进入format()
函数:format(n, 'b')
。无需解析占位符并将其与参数匹配。【参考方案12】:
>>> format(123, 'b')
'1111011'
【讨论】:
【参考方案13】:你可以这样做:
bin(10)[2:]
或:
f = str(bin(10))
c = []
c.append("".join(map(int, f[2:])))
print c
【讨论】:
bin(n).replace("0b", "")【参考方案14】:对于我们这些需要将有符号整数(范围 -2**(digits-1) 到 2**(digits-1)-1)转换为 2 的补码二进制字符串的人来说,这个方法有效:
def int2bin(integer, digits):
if integer >= 0:
return bin(integer)[2:].zfill(digits)
else:
return bin(2**digits + integer)[2:]
这会产生:
>>> int2bin(10, 8)
'00001010'
>>> int2bin(-10, 8)
'11110110'
>>> int2bin(-128, 8)
'10000000'
>>> int2bin(127, 8)
'01111111'
【讨论】:
【参考方案15】:使用 numpy pack/unpackbits,它们是你最好的朋友。
Examples
--------
>>> a = np.array([[2], [7], [23]], dtype=np.uint8)
>>> a
array([[ 2],
[ 7],
[23]], dtype=uint8)
>>> b = np.unpackbits(a, axis=1)
>>> b
array([[0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 1, 1, 1],
[0, 0, 0, 1, 0, 1, 1, 1]], dtype=uint8)
【讨论】:
问题是关于 string 表示。尽管如此,这恰好是我在没有先通过字符串的情况下寻找的! :) doco 表示:将uint8
数组的元素解包为二进制值输出数组。对于高达 255 的值非常有用。【参考方案16】:
接受的答案没有解决负数,我将对此进行介绍。 除了上面的答案,您还可以只使用bin 和hex 函数。而在相反的方向,使用二进制表示法:
>>> bin(37)
'0b100101'
>>> 0b100101
37
但是对于负数,事情变得有点复杂。该问题未指定您要如何处理负数。
Python 只是添加了一个负号,所以 -37 的结果是这样的:
>>> bin(-37)
'-0b100101'
在计算机/硬件二进制数据中,不存在负号。我们只有 1 和 0。因此,如果您正在读取或生成要由其他软件/硬件处理的二进制数据流,您首先需要知道所使用的符号。
一个符号是sign-magnitude notation,其中第一位代表负号,其余的是实际值。在这种情况下,-37 将是 0b1100101
,而 37 将是 0b0100101
。这看起来像 python 产生的,但只是在前面添加一个 0 或 1 来表示正数/负数。
比较常见的是Two's complement notation,看起来比较复杂,结果和python的字符串格式化有很大区别。您可以阅读链接中的详细信息,但对于 8 位有符号整数,-37 将是 0b11011011
,37 将是 0b00100101
。
Python 没有简单的方法来生成这些二进制表示。您可以使用numpy 将二进制补码值转换为 python 整数:
>>> import numpy as np
>>> np.int8(0b11011011)
-37
>>> np.uint8(0b11011011)
219
>>> np.uint8(0b00100101)
37
>>> np.int8(0b00100101)
37
但我不知道用内置函数做相反的简单方法。 bitstring package 可以提供帮助。
>>> from bitstring import BitArray
>>> arr = BitArray(int=-37, length=8)
>>> arr.uint
219
>>> arr.int
-37
>>> arr.bin
'11011011'
>>> BitArray(bin='11011011').int
-37
>>> BitArray(bin='11011011').uint
219
【讨论】:
【参考方案17】:Python 3.6 添加了一种新的字符串格式化方法,称为格式化字符串文字或“f-strings”。 示例:
name = 'Bob'
number = 42
f"Hello, name, your number is number:>08b"
输出将是“你好,鲍勃,你的号码是 00001010!”
可以在此处找到有关此问题的讨论 - Here
【讨论】:
【参考方案18】:除非我误解了二进制字符串的含义,否则我认为您要查找的模块是struct
【讨论】:
New location.【参考方案19】:通过使用位运算符,使用另一种算法的另一种解决方案。
def int2bin(val):
res=''
while val>0:
res += str(val&1)
val=val>>1 # val=val/2
return res[::-1] # reverse the string
一个更快的版本,无需反转字符串。
def int2bin(val):
res=''
while val>0:
res = chr((val&1) + 0x30) + res
val=val>>1
return res
【讨论】:
第二个版本肯定不会更快,因为您最终会得到类似 O(N^2) 算法而不是 O(N) 的算法。我见过这样的事情会杀死一个应用程序(性能方面),因为开发人员认为最后做一个额外的传递比在第一个循环中做一些额外的事情要慢。修复后,运行时间从几天缩短到几秒。【参考方案20】:def binary(decimal) :
otherBase = ""
while decimal != 0 :
otherBase = str(decimal % 2) + otherBase
decimal //= 2
return otherBase
print binary(10)
输出:
1010
【讨论】:
【参考方案21】:这是我刚刚实现的代码。这不是方法,但您可以将其用作即用型函数!
def inttobinary(number):
if number == 0:
return str(0)
result =""
while (number != 0):
remainder = number%2
number = number/2
result += str(remainder)
return result[::-1] # to invert the string
【讨论】:
【参考方案22】:n=input()
print(bin(n).replace("0b", ""))
【讨论】:
【参考方案23】:numpy.binary_repr(num, width=None)
以上文档链接中的示例:
>>> np.binary_repr(3) '11' >>> np.binary_repr(-3) '-11' >>> np.binary_repr(3, width=4) '0011'
当输入数为负数且指定宽度时,返回二进制补码:
>>> np.binary_repr(-3, width=3) '101' >>> np.binary_repr(-3, width=5) '11101'
【讨论】:
【参考方案24】:有点类似的解决方案
def to_bin(dec):
flag = True
bin_str = ''
while flag:
remainder = dec % 2
quotient = dec / 2
if quotient == 0:
flag = False
bin_str += str(remainder)
dec = quotient
bin_str = bin_str[::-1] # reverse the string
return bin_str
【讨论】:
【参考方案25】:这里是使用 divmod() 函数的简单解决方案,它返回提醒和不带分数的除法结果。
def dectobin(number):
bin = ''
while (number >= 1):
number, rem = divmod(number, 2)
bin = bin + str(rem)
return bin
【讨论】:
需要调试。调用dectobin(10)
得到 '0101'【参考方案26】:
这是另一种使用常规数学的方法,没有循环,只有递归。 (普通情况 0 不返回任何内容)。
def toBin(num):
if num == 0:
return ""
return toBin(num//2) + str(num%2)
print ([(toBin(i)) for i in range(10)])
['', '1', '10', '11', '100', '101', '110', '111', '1000', '1001']
【讨论】:
奇怪的是0
返回''
,应该是'0'
...【参考方案27】:
具有 DEC、BIN、HEX 的所有必要功能的计算器: (使用 Python 3.5 制作和测试)
您可以更改输入的测试编号并获取转换后的编号。
# CONVERTER: DEC / BIN / HEX
def dec2bin(d):
# dec -> bin
b = bin(d)
return b
def dec2hex(d):
# dec -> hex
h = hex(d)
return h
def bin2dec(b):
# bin -> dec
bin_numb="0:b".format(b)
d = eval(bin_numb)
return d,bin_numb
def bin2hex(b):
# bin -> hex
h = hex(b)
return h
def hex2dec(h):
# hex -> dec
d = int(h)
return d
def hex2bin(h):
# hex -> bin
b = bin(h)
return b
## TESTING NUMBERS
numb_dec = 99
numb_bin = 0b0111
numb_hex = 0xFF
## CALCULATIONS
res_dec2bin = dec2bin(numb_dec)
res_dec2hex = dec2hex(numb_dec)
res_bin2dec,bin_numb = bin2dec(numb_bin)
res_bin2hex = bin2hex(numb_bin)
res_hex2dec = hex2dec(numb_hex)
res_hex2bin = hex2bin(numb_hex)
## PRINTING
print('------- DECIMAL to BIN / HEX -------\n')
print('decimal:',numb_dec,'\nbin: ',res_dec2bin,'\nhex: ',res_dec2hex,'\n')
print('------- BINARY to DEC / HEX -------\n')
print('binary: ',bin_numb,'\ndec: ',numb_bin,'\nhex: ',res_bin2hex,'\n')
print('----- HEXADECIMAL to BIN / HEX -----\n')
print('hexadec:',hex(numb_hex),'\nbin: ',res_hex2bin,'\ndec: ',res_hex2dec,'\n')
【讨论】:
【参考方案28】:计算二进制数:
print("Binary is 0:>08b".format(16))
计算一个数字的十六进制数:
print("Hexa Decimal is 0:>0x".format(15))
计算所有二进制数到 16::
for i in range(17):
print("0:>2: binary is 0:>08b".format(i))
计算 Hexa 十进制数到 17
for i in range(17):
print("0:>2: Hexa Decimal is 0:>0x".format(i))
##as 2 digit is enogh for hexa decimal representation of a number
【讨论】:
【参考方案29】:try:
while True:
p = ""
a = input()
while a != 0:
l = a % 2
b = a - l
a = b / 2
p = str(l) + p
print(p)
except:
print ("write 1 number")
【讨论】:
可能想对您在那里所做的事情添加一些解释。【参考方案30】:我找到了一种使用矩阵运算将十进制转换为二进制的方法。
import numpy as np
E_mat = np.tile(E,[1,M])
M_order = pow(2,(M-1-np.array(range(M)))).T
bindata = np.remainder(np.floor(E_mat /M_order).astype(np.int),2)
E
是输入十进制数据,M
是二进制命令。 bindata
为输出二进制数据,格式为1×M二进制矩阵。
【讨论】:
以上是关于Python int 到二进制字符串?的主要内容,如果未能解决你的问题,请参考以下文章