Python จัดการ int และ long อย่างไร?


118

มีใครรู้บ้างว่า Python จัดการประเภท int และ long ภายในอย่างไร

  • มันเลือกประเภทที่เหมาะสมแบบไดนามิกหรือไม่?
  • ขีด จำกัด สำหรับ int คืออะไร?
  • ฉันใช้ Python 2.6 แตกต่างจากเวอร์ชันก่อนหน้าหรือไม่

ฉันจะเข้าใจโค้ดด้านล่างได้อย่างไร?

>>> print type(65535)
<type 'int'>
>>> print type(65536*65536)
<type 'long'>

ปรับปรุง:

>>> print type(0x7fffffff)
<type 'int'>
>>> print type(0x80000000)
<type 'long'>

พวกเขาไม่เพียงจับคู่กับประเภท stdc ในการบินที่อยู่ด้านล่างใน CPython หรือไม่?
Aiden Bell

ใช่ฉันคิดว่าพวกเขาทำ ฉันยังสงสัยว่าทุกอย่างถูกจัดสรรบนฮีปดังนั้นเมื่อตัวเลขต้องการความแม่นยำมากขึ้นพวกเขาก็reallocทำได้ถูกต้อง แต่ฉันไม่ค่อยแน่ใจนักดังนั้นฉันจะทิ้งคำตอบให้คนอื่น
zneak

2
คุณยังสามารถบังคับให้ python ใช้ตัวแปรแบบยาวได้ด้วยvar = 666L
qba

8
@Ignacio: ผิด CPython intเป็น C long(ค่าเริ่มต้นคือลงนาม) ... ดู<CPython 2.X source>/Include/intobject.h: โครงสร้างพิมพ์ดีด {PyObject_HEAD long ob_ival; } PyIntObject; ไม่ว่าในกรณีใด ๆ Python 2.x intอนุญาตให้ใช้ตัวเลขติดลบ a C unsignedไม่สามารถรับมือได้
John Machin

PEP 237 กล่าวถึงวิธีการที่ Python มีจุดมุ่งหมายเพื่อทำให้ทุกอย่างดูเหมือนเดิม
Carel

คำตอบ:


124

intและlongเป็น "เอกภาพ" กี่รุ่นสำรอง ก่อนหน้านั้นเป็นไปได้ที่จะล้น int ผ่านทางคณิตศาสตร์

3.x ก้าวไปอีกขั้นโดยการกำจัดระยะยาวทั้งหมดและมีเพียง int

  • Python 2 : sys.maxintมีค่าสูงสุดที่ Python int สามารถเก็บได้
    • บน Python 2.7 64 บิตมีขนาด 24 ไบต์ ตรวจสอบด้วยsys.getsizeof().
  • Python 3 : sys.maxsizeมีขนาดสูงสุดเป็นไบต์ที่ Python int สามารถเป็นได้
    • นี่จะเป็นกิกะไบต์ใน 32 บิตและเอ็กซาไบต์ใน 64 บิต
    • int ขนาดใหญ่ดังกล่าวจะมีค่าใกล้เคียงกับ 8 ของพลังของsys.maxsize.

30
แต่ Python3 เรียกประเภทนี้ว่า 'int' แม้ว่ามันจะทำงานเหมือน "long" ของ 2.x มากกว่าก็ตาม

3
ความคิดเห็นโดย Ted: ดังที่กล่าวไว้ด้านล่างโปรดระวังว่าการแคสต์บางสิ่งเป็น int ที่มีขนาดใหญ่กว่า maxint จะยังคงส่งผลให้ประเภท >>> ยาว (int (sys.maxint + 1)) <type 'long'>
StuartLC

2
sys.maxint จะให้จำนวนเต็ม 64 บิตที่ใหญ่ที่สุด (บนเครื่อง 64 บิตของฉัน) Long อาจใหญ่กว่า 64 บิตได้มากเพียงลอง "sys.maxint << 1000000"
fccoelho

4
ใน python3 คือ sys.maxsize
pylover

3
sys.maxsize ไม่มีส่วนเกี่ยวข้องกับจำนวนเต็ม sys.maxint ของ Python 3 ถูกลบออกเนื่องจากไม่มีขนาดสูงสุดสำหรับจำนวนเต็ม (Python 3 intเหมือนกับ Python 2 long)
asmeurer

19

PEPนี้น่าจะช่วยได้

สิ่งที่สำคัญที่สุดคือคุณไม่ควรต้องกังวลกับมันในเวอร์ชัน python> 2.4


15
คุณต้องกังวลเกี่ยวกับเรื่องนี้หากคุณต้องเรียกใช้ฟังก์ชัน int ใน c ด้วยสิ่งที่ไม่พอดีกับ int (เช่น long) ไม่มีการร่าย long-> int จะช่วยได้ เกิดขึ้นกับฉันเมื่อไม่นานมานี้
Macke

1
@ Macke: ความคิดเห็นนี้ช่วยฉันฉันคิดว่า int จะทำเคล็ดลับและสงสัยว่าทำไมฉันถึงยังได้รับข้อยกเว้นของ Jython
ted

@ Macke จริงแท้แน่นอน ที่ บริษัท ที่ฉันทำงานอยู่ในขณะนี้เรามี Simulator ที่เขียนด้วย Python ซึ่งรับอินพุตของผู้ใช้ผ่านรายการ Tkinter และส่งค่า casted ผ่าน TCP / IP ไปยังไคลเอนต์ (เขียนด้วย C / C ++) ซึ่งเลียนแบบระบบฝังตัว ลองนึกภาพว่าจะเกิดอะไรขึ้นเมื่อคุณใส่ 1000000000000000000000000000 ในรายการที่ใช้ Python ของคุณ ... : P
rbaleksandar

@ แม็คกี้ดีถ้าคุณใส่ใจที่จะอ่าน PEP จริงก็บอกอย่างชัดเจนว่า: C API ยังคงไม่เปลี่ยนแปลง รหัส C ยังคงต้องตระหนักถึงความแตกต่างระหว่าง ints สั้นและยาว (Python 3.0 C API อาจเข้ากันไม่ได้โดยสิ้นเชิง) PyArg_Parse * () API นั้นยอมรับ long ints อยู่แล้วตราบเท่าที่อยู่ในช่วงที่ C ints หรือ longs สามารถแทนได้ดังนั้นฟังก์ชันที่รับ C int หรือ long อาร์กิวเมนต์จะได้รับ ' ไม่ต้องกังวลเกี่ยวกับการจัดการกับ Python longs
cowbert

4

บนเครื่องของฉัน:

>>> print type(1<<30)
<type 'int'>
>>> print type(1<<31)
<type 'long'>
>>> print type(0x7FFFFFFF)
<type 'int'>
>>> print type(0x7FFFFFFF+1)
<type 'long'>

Python ใช้ ints (จำนวนเต็มที่ลงชื่อ 32 บิตฉันไม่รู้ว่าเป็น C ints ภายใต้ประทุนหรือไม่) สำหรับค่าที่พอดีกับ 32 บิต แต่จะเปลี่ยนเป็น longs โดยอัตโนมัติ (บิตจำนวนมากโดยพลการ - เช่น bignums) สำหรับอะไรก็ตาม ที่มีขนาดใหญ่ ฉันคาดเดาว่าสิ่งนี้จะเร่งความเร็วสำหรับค่าที่น้อยลงในขณะที่หลีกเลี่ยงการล้นใด ๆ ด้วยการเปลี่ยนไปใช้ bignums อย่างราบรื่น


4

น่าสนใจ บนกล่อง 64 บิต (i7 Ubuntu) ของฉัน:

>>> print type(0x7FFFFFFF)
<type 'int'>
>>> print type(0x7FFFFFFF+1)
<type 'int'>

เดาว่าเพิ่ม ints ได้ถึง 64 บิตในเครื่องที่ใหญ่กว่า


2
Python ใช้ประเภทจำนวนเต็มขนาดใหญ่ที่มีให้สำหรับเครื่อง ดังนั้นโดยปกติแล้วในเครื่อง 32 บิต int จะมีขนาด 32 บิตในขณะที่เครื่อง 64 บิตจะมีขนาด 64 บิต แต่อาจมีสถาปัตยกรรม 32 บิตที่กำหนดจำนวนเต็ม 64 บิตในกรณีนั้น python จะใช้จำนวนเต็ม 64 บิต
Bakuriu

4

Python 2.7.9 อัตโนมัติส่งเสริมตัวเลข สำหรับกรณีที่ไม่แน่ใจว่าจะใช้ int () หรือ long ()

>>> a = int("123")
>>> type(a)
<type 'int'>
>>> a = int("111111111111111111111111111111111111111111111111111")
>>> type(a)
<type 'long'>

4

Python 2 จะตั้งค่าประเภทโดยอัตโนมัติตามขนาดของค่า สามารถดูคำแนะนำของค่าสูงสุดได้ด้านล่าง

ค่าสูงสุดของ Int เริ่มต้นใน Python 2 คือ 65535 ค่าใดก็ตามที่อยู่ด้านบนจะยาว

ตัวอย่างเช่น:

>> print type(65535)
<type 'int'>
>>> print type(65536*65536)
<type 'long'>

ใน Python 3 ประเภทข้อมูลแบบยาวถูกลบออกและค่าจำนวนเต็มทั้งหมดจะถูกจัดการโดยคลาส Int ขนาดเริ่มต้นของ Int จะขึ้นอยู่กับสถาปัตยกรรม CPU ของคุณ

ตัวอย่างเช่น:

  • ระบบ 32 บิตประเภทข้อมูลเริ่มต้นสำหรับจำนวนเต็มจะเป็น 'Int32'
  • ระบบ 64 บิตประเภทข้อมูลเริ่มต้นสำหรับจำนวนเต็มจะเป็น 'Int64'

ค่าต่ำสุด / สูงสุดของแต่ละประเภทมีอยู่ด้านล่าง:

  • Int8: [-128,127]
  • Int16: [-32768,32767]
  • Int32: [-2147483648,2147483647]
  • Int64: [-9223372036854775808,9223372036854775807]
  • Int128: [-170141183460469231731687303715884105728,170141183460469231731687303715884105727]
  • UInt8: [0,255]
  • UInt16: [0,65535]
  • UInt32: [0,4294967295]
  • UInt64: [0,18446744073709551615]
  • UInt128: [0,340282366920938463463374607431768211455]

หากขนาด Int ของคุณเกินขีด จำกัด ที่กล่าวไว้ข้างต้น python จะเปลี่ยนประเภทโดยอัตโนมัติและจัดสรรหน่วยความจำเพิ่มเติมเพื่อจัดการกับค่าต่ำสุด / สูงสุดที่เพิ่มขึ้นนี้ โดยที่ใน Python 2 จะแปลงเป็น 'long' ตอนนี้ก็แปลงเป็นขนาด Int ถัดไป

ตัวอย่าง: หากคุณใช้ระบบปฏิบัติการ 32 บิตค่าสูงสุดของ Int จะเป็น 2147483647 ตามค่าเริ่มต้น หากกำหนดค่า 2147483648 ขึ้นไปประเภทจะเปลี่ยนเป็น Int64

มีหลายวิธีในการตรวจสอบขนาดของ int และการจัดสรรหน่วยความจำ หมายเหตุ: ใน Python 3 การใช้เมธอด built-in type () จะส่งคืนเสมอ<class 'int'>ไม่ว่าคุณจะใช้ Int ขนาดใดก็ตาม


1

จาก python 3.x ไลบรารีจำนวนเต็มแบบรวมจะฉลาดกว่าเวอร์ชันเก่ากว่า ในกล่อง (i7 Ubuntu) ของฉันฉันได้รับสิ่งต่อไปนี้

>>> type(math.factorial(30))
<class 'int'>

สำหรับรายละเอียดการใช้งานอ้างอิงInclude/longintrepr.h, Objects/longobject.c and Modules/mathmodule.cไฟล์ ไฟล์สุดท้ายคือโมดูลไดนามิก (คอมไพล์เป็นไฟล์ so) รหัสมีความคิดเห็นที่ดีที่จะปฏิบัติตาม


1

เพียงเพื่อดำเนินการต่อกับคำตอบทั้งหมดที่ให้ไว้ที่นี่โดยเฉพาะ @ James Lanes

ขนาดของประเภทจำนวนเต็มสามารถแสดงได้ด้วยสูตรนี้:

ช่วงรวม = (ระบบ 2 ^ บิต)

ขีด จำกัด ล่าง = - (ระบบ 2 ^ บิต) * 0.5 ขีด จำกัด บน = ((ระบบ 2 ^ บิต) * 0.5) - 1


0

มันจัดการพวกเขาเพราะintและlongเป็นคำจำกัดความของคลาสพี่น้อง พวกเขามีวิธีการที่เหมาะสมสำหรับ +, -, *, / ฯลฯ ซึ่งจะให้ผลลัพธ์ของคลาสที่เหมาะสม

ตัวอย่างเช่น

>>> a=1<<30
>>> type(a)
<type 'int'>
>>> b=a*2
>>> type(b)
<type 'long'>

ในกรณีนี้คลาสintจะมี__mul__เมธอด (วิธีที่ใช้ *) ซึ่งสร้างlongผลลัพธ์เมื่อต้องการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.