Como o Python gerencia int e long?

118

Alguém sabe como Python gerencia internamente tipos int e long?

  • Ele escolhe o tipo certo dinamicamente?
  • Qual é o limite de um int?
  • Estou usando o Python 2.6. É diferente das versões anteriores?

Como devo entender o código abaixo?

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

Atualizar:

>>> print type(0x7fffffff)
<type 'int'>
>>> print type(0x80000000)
<type 'long'>
luc
fonte
Eles não mapeiam apenas para tipos stdc em tempo real no CPython?
Aiden Bell de
Sim, acho que sim. Eu também suspeito que tudo está alocado na pilha, então quando um número precisa de mais precisão, ele fica reallocbem. Mas não tenho certeza, então vou deixar a resposta para outra pessoa.
zneak de
2
Você também pode forçar o python a usar a variável longa comvar = 666L
qba de
8
@Ignacio: ERRADO Um CPython inté um C long(o padrão é assinado) ... veja <CPython 2.X source>/Include/intobject.h: typedef struct {PyObject_HEAD long ob_ival; } PyIntObject; Em qualquer caso, o Python 2.x intpermite números negativos; um C unsignedsimplesmente não daria certo.
John Machin de
O PEP 237 discute como o Python se destina a fazer tudo parecer o mesmo.
Carel de

Respostas:

124

inte longforam "unificados" algumas versões atrás . Antes disso, era possível estourar um int por meio de operações matemáticas.

3.x avançou ainda mais, eliminando long completamente e tendo apenas int.

  • Python 2 : sys.maxintcontém o valor máximo que um int Python pode conter.
    • Em um Python 2.7 de 64 bits, o tamanho é 24 bytes. Verifique com sys.getsizeof().
  • Python 3 : sys.maxsizecontém o tamanho máximo em bytes que um Python int pode ter.
    • Serão gigabytes em 32 bits e exabytes em 64 bits.
    • Um int tão grande teria um valor semelhante a 8 elevado à potência de sys.maxsize.
Ignacio Vazquez-Abrams
fonte
30
Mas Python3 chama esse tipo de 'int', embora se comporte mais como 'longo' de 2.x.
3
Comentário de Ted: Como mencionado abaixo, tome cuidado, pois lançar algo em int que seja maior que maxint ainda resultará em um tipo longo >>> (int (sys.maxint + 1)) <type 'long'>
StuartLC
2
sys.maxint fornecerá o maior número inteiro de 64 bits (na minha máquina de 64 bits). Um Long pode ser muito maior que 64 bits, tente "sys.maxint << 1000000"
fccoelho
4
Em python3, é sys.maxsize
pylover
3
sys.maxsize não tem nada a ver com inteiros. O sys.maxint do Python 3 foi removido porque não há tamanho máximo para um inteiro (o Python 3 inté igual ao do Python 2 long).
asmeurer
19

Este PEP deve ajudar.

O ponto principal é que você realmente não deveria ter que se preocupar com isso nas versões python> 2.4

mluebke
fonte
15
Você terá que se preocupar com isso se precisar chamar uma função int em c com algo que não cabe em int (ou seja, um long). Nenhuma quantidade de fundição long-> int vai ajudar. Aconteceu comigo recentemente.
Macke,
1
@Macke: Esse comentário me salvou, presumi que int resolveria o problema e estava me perguntando por que ainda estava recebendo uma exceção Jython.
ted
@Macke Absolutamente verdadeiro. Na empresa em que trabalho atualmente, temos um Simulador escrito em Python que recebe a entrada do usuário por meio de entradas do Tkinter e envia os valores convertidos via TCP / IP para um cliente (escrito em C / C ++) que simula um sistema embarcado. Imagine o que acontece quando você insere 100000000000000000000000 em sua entrada baseada em Python ...: P
rbaleksandar
@Mackie bem, se você realmente se preocupou em ler o PEP, ele diz explicitamente: A API C permanece inalterada; O código C ainda precisará estar ciente da diferença entre ints curtos e longos. (Provavelmente, a API C do Python 3.0 será completamente incompatível.) As APIs PyArg_Parse * () já aceitam ints longos, desde que estejam dentro do intervalo representável por C ints ou longs, para que as funções que usam C int ou argumento longo ganhem ' Não preciso me preocupar em lidar com longs Python.
Cowbert
4

Na minha máquina:

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

Python usa ints (inteiros assinados de 32 bits, não sei se são C ints por baixo do capô ou não) para valores que se encaixam em 32 bits, mas muda automaticamente para longs (número arbitrariamente grande de bits - ou seja, bignums) para qualquer coisa maior. Estou supondo que isso acelera as coisas para valores menores, evitando quaisquer transbordamentos com uma transição perfeita para bignums.

MAK
fonte
4

Interessante. Na minha caixa de 64 bits (i7 Ubuntu):

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

Acho que aumenta para ints de 64 bits em uma máquina maior.

Gringo Suave
fonte
2
Python usa o tipo inteiro maior disponível para a máquina. SO geralmente em máquinas de 32 bits terá tamanho de 32 bits, enquanto em máquinas de 64 bits terá tamanho de 64 bits. Mas poderia haver arquiteturas de 32 bits definindo inteiros de 64 bits; nesse caso, o python usaria o inteiro de 64 bits.
Bakuriu
4

O Python 2.7.9 promove números automaticamente. Para um caso em que não se tem certeza de usar int () ou long ().

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

Python 2 definirá automaticamente o tipo com base no tamanho do valor. Um guia de valores máximos pode ser encontrado abaixo.

O valor máximo do Int padrão em Python 2 é 65535, qualquer coisa acima disso será um longo

Por exemplo:

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

No Python 3, o tipo de dados longo foi removido e todos os valores inteiros são tratados pela classe Int. O tamanho padrão do Int dependerá da arquitetura da CPU.

Por exemplo:

  • Sistemas de 32 bits, o tipo de dados padrão para inteiros será 'Int32'
  • Sistemas de 64 bits, o tipo de dados padrão para inteiros será 'Int64'

Os valores mín. / Máx. De cada tipo podem ser encontrados abaixo:

  • 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]

Se o tamanho do seu Int exceder os limites mencionados acima, o python mudará automaticamente o seu tipo e alocará mais memória para lidar com este aumento nos valores mínimo / máximo. Enquanto em Python 2, ele seria convertido em 'longo', agora apenas se converte no próximo tamanho de Int.

Exemplo: se você estiver usando um sistema operacional de 32 bits, o valor máximo de um Int será 2147483647 por padrão. Se um valor de 2147483648 ou mais for atribuído, o tipo será alterado para Int64.

Existem diferentes maneiras de verificar o tamanho do int e sua alocação de memória. Nota: No Python 3, o uso do método interno type () sempre retornará, <class 'int'>não importa o tamanho Int que você esteja usando.

James Lane
fonte
1

No python 3.x, as bibliotecas de inteiros unificados são ainda mais inteligentes do que as versões anteriores. Na minha caixa (i7 Ubuntu), eu tenho o seguinte,

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

Para detalhes de implementação, consulte os Include/longintrepr.h, Objects/longobject.c and Modules/mathmodule.carquivos. O último arquivo é um módulo dinâmico (compilado em um arquivo so). O código é bem comentado a seguir.

Venki
fonte
1

Só para continuar com todas as respostas que foram dadas aqui, especialmente @James Lanes

o tamanho do tipo inteiro pode ser expresso por esta fórmula:

intervalo total = (sistema de 2 ^ bits)

limite inferior = - (sistema de 2 ^ bits) * 0,5 limite superior = ((sistema de 2 ^ bits) * 0,5) - 1

Nader Belal
fonte
0

Ele gerencia-los, porque inte longsão irmãos definições de classe. Eles têm métodos apropriados para +, -, *, /, etc., que produzirão resultados da classe apropriada.

Por exemplo

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

Neste caso, a classe int possui um __mul__método (aquele que implementa *) que cria um longresultado quando necessário.

S.Lott
fonte