แปลงเป็นเลขฐานสองและเก็บค่าศูนย์นำหน้าใน Python


154

ฉันพยายามแปลงจำนวนเต็มเป็นไบนารีโดยใช้ฟังก์ชัน bin () ใน Python อย่างไรก็ตามมันจะลบค่าศูนย์นำหน้าซึ่งฉันต้องการจริง ๆ เสมอดังนั้นผลลัพธ์จะเป็น 8 บิตเสมอ:

ตัวอย่าง:

bin(1) -> 0b1

# What I would like:
bin(1) -> 0b00000001

มีวิธีทำเช่นนี้หรือไม่?


ดูเพิ่มเติม: Python int กับไบนารี? โดยเฉพาะคำตอบของฉันด้วยการเป็นตัวแทนบิต ไม่เหมือนกัน แต่ผมมาถึงคำถามนี้ค้นหาคำตอบของฉัน ...
มาร์ติน Thoma

คำตอบ:


220

ใช้format()ฟังก์ชั่น :

>>> format(14, '#010b')
'0b00001110'

format()ฟังก์ชั่นเพียงแค่รูปแบบการป้อนข้อมูลต่อไปนี้รูปแบบจำเพาะมินิภาษา #ทำให้รูปแบบรวมถึง0bคำนำหน้าและ010ขนาดรูปแบบการส่งออกให้พอดีกับความกว้าง 10 ตัวอักษรที่มี0ช่องว่างภายใน; 2 ตัวอักษรสำหรับ0bคำนำหน้าส่วนอีก 8 ตัวสำหรับเลขฐานสอง

นี่คือตัวเลือกที่กะทัดรัดและตรงที่สุด

หากคุณใส่ผลลัพธ์ในสตริงที่มีขนาดใหญ่ขึ้นให้ใช้สตริงที่จัดรูปแบบตามตัวอักษร (3.6+) หรือใช้str.format()และใส่อาร์กิวเมนต์ที่สองสำหรับformat()ฟังก์ชันหลังเครื่องหมายโคลอนของตัวยึดตำแหน่ง{:..}:

>>> value = 14
>>> f'The produced output, in binary, is: {value:#010b}'
'The produced output, in binary, is: 0b00001110'
>>> 'The produced output, in binary, is: {:#010b}'.format(value)
'The produced output, in binary, is: 0b00001110'

ตามที่เกิดขึ้นแม้เพียงแค่จัดรูปแบบค่าเดียว (ดังนั้นโดยไม่ต้องใส่ผลลัพธ์ในสตริงที่มีขนาดใหญ่กว่า) การใช้สตริงตัวอักษรที่จัดรูปแบบจะเร็วกว่าการใช้format():

>>> import timeit
>>> timeit.timeit("f_(v, '#010b')", "v = 14; f_ = format")  # use a local for performance
0.40298633499332936
>>> timeit.timeit("f'{v:#010b}'", "v = 14")
0.2850222919951193

แต่ฉันจะใช้มันเฉพาะในกรณีที่การแสดงในวงแคบเป็นเรื่องที่ควรformat(...)สื่อสาร

หากคุณไม่ต้องการ0bคำนำหน้าให้ปล่อย#และปรับความยาวของฟิลด์:

>>> format(14, '08b')
'00001110'

3
การจัดรูปแบบนี้มีประโยชน์กับฉันจริงๆ ฉันได้เริ่มต้นเรียนรู้การจัดการบิตและฉันก็ทำรูปแบบบิตสำหรับตัวเลขใน Python พบสิ่งนี้ ขอบคุณ.
kratostoical

ใช้งานได้ดี สามารถรับบิตขนาดใหญ่แม้ว่า format(192,'08b')+'.'+format(0,'08b')+'.'+format(2,'08b')+'.'+format(33,'08b') 11000000.00000000.00000010.00100001
เสียง

@ tjt263: นั่นเป็นเหตุผลที่ฉันระบุไว้อย่างชัดเจนว่าหากคุณใส่ผลลัพธ์ในสตริงที่ใหญ่กว่าให้ใช้สตริงที่จัดรูปแบบตามตัวอักษร (3.6+) หรือใช้str.format()และใส่อาร์กิวเมนต์ที่สองสำหรับฟังก์ชั่น format () หลังเครื่องหมายโคลอนของตัวยึดตำแหน่ง{:..}:
Martijn Pieters

1
@ tjt263: f"{192:08b}.{0:08b}.{2:08b}.{33:08b}"เช่นการใช้งาน
Martijn Pieters

ดีมาก. ฉันไม่เคยรู้เลยว่านั่นคือสิ่งที่คุณต้องการจากคำอธิบายเพียงอย่างเดียว แต่ตอนนี้ฉันเห็นตัวอย่างของคุณแล้วฉันอาจจะไม่มีวันลืม ไชโย
เสียง

115
>>> '{:08b}'.format(1)
'00000001'

โปรดดู: ข้อกำหนดคุณสมบัติรูปแบบมินิภาษา


หมายเหตุสำหรับ Python 2.6 หรือเก่ากว่าคุณไม่สามารถละเว้นตัวระบุอาร์กิวเมนต์ตำแหน่งได้:ดังนั้นควรใช้

>>> '{0:08b}'.format(1)
'00000001'      

3
ไม่จำเป็นต้องใช้str.format()ที่นี่เมื่อformat()จะทำ คุณไม่มี0bคำนำหน้า
Martijn Pieters

2
@MartijnPieters str.formatมีความยืดหยุ่นมากกว่าformat()เพราะจะช่วยให้คุณทำหลายตัวแปรพร้อมกัน ฉันลืมไปตลอดว่าformatฟังก์ชั่นยังมีอยู่ เป็นที่ยอมรับกันอย่างสมบูรณ์ว่าเพียงพอในกรณีนี้
Mark Ransom

1
@MarkRansom: แน่นอนเมื่อคุณเป็นเพียงการใช้str.format()มีเพียงหนึ่ง{}องค์ประกอบที่ไม่มีข้อความอื่น ๆ คุณจะไม่ได้ใช้สตริง templating คุณจะจัดรูปแบบหนึ่งค่า format()ในกรณีใช้เพียง :-)
Martijn Pieters


9

คุณสามารถใช้การจัดรูปแบบสตริงมินิภาษา:

def binary(num, pre='0b', length=8, spacer=0):
    return '{0}{{:{1}>{2}}}'.format(pre, spacer, length).format(bin(num)[2:])

การสาธิต:

print binary(1)

เอาท์พุท:

'0b00000001'

แก้ไข: อิงตามแนวคิด @Martijn Pieters

def binary(num, length=8):
    return format(num, '#0{}b'.format(length + 2))

2
ภาษาการจัดรูปแบบเดียวกันสามารถใช้เพื่อรวมคำนำหน้าสำหรับคุณ #ใช้ นอกจากนี้ยังมีformat()ซึ่งช่วยให้คุณไม่ต้องทำแม่แบบสตริงเต็ม
Martijn Pieters

2

เมื่อใช้ Python >= 3.6วิธีที่สะอาดที่สุดคือใช้f-stringsพร้อมการจัดรูปแบบสตริง :

>>> var = 23
>>> f"{var:#010b}"
'0b00010111'

คำอธิบาย:

  • var ตัวแปรที่จะจัดรูปแบบ
  • : ทุกอย่างหลังจากนี้เป็นตัวระบุรูปแบบ
  • #ใช้แบบฟอร์มทางเลือก (เพิ่ม0bคำนำหน้า)
  • 0 แผ่นกับศูนย์
  • 10แผ่นความยาวรวมออก 10 (รวมถึง 2 ตัวอักษรสำหรับ0b)
  • b ใช้การเป็นตัวแทนไบนารีสำหรับจำนวน

ไม่มีก็ไม่สะอาด, ไม่เว้นแต่คุณจะทำมากขึ้นด้วยสตริงมากกว่าเพียงแค่ตัวยึดเดียว มิฉะนั้นformat(var, "#010b")สื่อสารเจตนาดีกว่ามาก มันเป็นตัวเลือกที่เร็วที่สุด แต่คุณก็รู้แล้วว่าถูกต้องเพราะฉันครอบคลุมทุกสิ่งที่คุณโพสต์ไว้ในคำตอบ
Martijn Pieters

1

บางครั้งคุณแค่ต้องการซับง่าย ๆ :

binary = ''.join(['{0:08b}'.format(ord(x)) for x in input])

Python 3


1
โปรดทราบว่า[ ]ไม่จำเป็นต้องมี - join()ยอมรับนิพจน์ตัวสร้าง ''.join('{0:08b}'.format(ord(x)) for x in input)
Christoph Burschka

@ChristophBurschka ทราบว่าเนื่องจากstr.join()ต้องทำการผ่านสองครั้งเครื่องกำเนิดสัญญาณจะถูกแปลงเป็นรายการแรกก่อนเข้าร่วม สิ่งนี้ต้องใช้เวลาอย่างมากในการทำงานและทำดีกว่าที่นี่จริง ๆเพื่อส่งผ่านรายการความเข้าใจมากกว่านิพจน์ตัวสร้าง มันเป็นสิ่งหนึ่งถ้าพวกเขายกเว้นกฎ
Martijn Pieters

-1

คุณสามารถใช้สิ่งนี้

("{:0%db}"%length).format(num)

2
โปรดใช้บล็อครหัสเป็นอย่างน้อยสำหรับข้อมูลโค้ดของคุณ และถ้าคุณต้องการให้มันเป็นคำตอบที่ดีจริงๆให้เพิ่มความคิดเห็นเกี่ยวกับสาเหตุที่การแก้ปัญหานี้แก้คำถาม OP
β.εηοιτ.βε

คุณไม่จำเป็นต้องใช้รูปแบบการจัดรูปแบบสตริงอื่นเพื่อเพิ่มความกว้างของตัวแปร เพียงเพิ่มตัวยึดตำแหน่งอื่น:"{:0{l}b}".format(num, l=length)
Martijn Pieters

-1

คุณสามารถใช้วิธีการสตริง rjust ของไวยากรณ์หลาม: string.rjust (ความยาว, fillchar) fillchar เป็นตัวเลือก

และสำหรับคำถามของคุณคุณเขียนเช่นนี้

'0b'+ '1'.rjust(8,'0)

ดังนั้นมันจะเป็น '0b00000001'


มีข้อผิดพลาดทางไวยากรณ์ แต่ที่สำคัญกว่านั้นมันไม่ได้ตอบคำถามเลยซึ่งเกี่ยวกับการแปลงเป็นการintแทนแบบไบนารีที่เป็นข้อความ intคุณไม่ได้เริ่มต้นด้วย
Thierry Lathuille

-3

คุณสามารถใช้ zfill:

print str(1).zfill(2) 
print str(10).zfill(2) 
print str(100).zfill(2)

พิมพ์:

01
10
100

ฉันชอบโซลูชันนี้เนื่องจากช่วยได้ไม่เพียง แต่เมื่อแสดงผลตัวเลข แต่เมื่อคุณจำเป็นต้องกำหนดให้กับตัวแปร ... เช่น - x = str (datetime.date.today (). เดือน) .zfill (2) จะ ส่งคืน x เป็น '02' สำหรับเดือน feb


1
ปัญหากับ zfill มันคือการปฏิบัติต่อสตริงไบนารีเช่นสตริงและเพิ่มศูนย์ก่อนที่ตัวบ่งชี้ 'b' ไบนารี ... เช่น bin(14) ให้ '0b1110' 'และ bin(14).zfill(8) ให้' 000b1110 '' ไม่ใช่ `'0b00001110' 'ซึ่งเป็นสิ่งที่ต้องการ
Shaun
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.