51 votes

Pourquoi la taille de 2⁶³ est-elle de 36 octets, alors que 2⁶³-1 ne fait que 24 octets?

Tout en Python est un objet. De sorte que la taille d'un int en Python sera plus grande que d'habitude.

>>> sys.getsizeof(int())
24

OK, mais pourquoi faut-il plus de 12 octets pour 2⁶³ comparativement trop 2⁶³ - 1 , et pas seulement un?

>>> sys.getsizeof(2**63)
36
>>> sys.getsizeof(2**62)
24

Je reçois 2⁶³ est une longue et 2⁶³-1 un int, mais pourquoi 12 octets de la différence?

Pas plus intuitif, j'ai essayé quelques autres choses:

>>> a = 2**63
>>> a -= 2**62
>>> sys.getsizeof(a)
36

a sont toujours stockées en tant que long, même si il pourrait être dans un int maintenant. Ce n'est donc pas surprenant. Mais:

>>> a -= (2**63 - 1)
>>> a = 2**63
>>> a -= (2**63 - 1)
>>> a
1L
>>> sys.getsizeof(a)
28

Une nouvelle taille.

>>> a = 2**63
>>> a -= 2**63
>>> a
0L
>>> sys.getsizeof(a)
24

De retour de 24 octets, mais toujours avec une longue.

Dernière chose que j'ai eu:

>>> sys.getsizeof(long())
24

Question:

Comment fonctionne le stockage de la mémoire de travail dans ces scénarios?

Sous-questions:

Pourquoi est-il un écart de 12 octets pour ajouter ce que notre intuition nous dit, c'est juste 1 peu?

Pourquoi sont - int() et long() 24 octets, mais long(1) est déjà 28 octets et int(2⁶²)?

NB: Python 3.X fonctionne un peu différemment, mais pas de manière plus intuitive. Ici, je me suis concentré sur Python 2.7; je n'ai pas tester sur les versions antérieures.

62voto

user4815162342 Points 27348

pourquoi fait-il plus de 12 octets pour 2⁶3 comparé trop 2⁶3 - 1 et pas seulement un?

Sur un LP64 système1, un Python 2 int consiste exactement trois pointeur de la taille des morceaux:

  • le type pointeur
  • nombre de références
  • valeur réelle, un C long int

C'est 24 octets au total. D'autre part, un Python long se compose de:

  • le type pointeur
  • nombre de références
  • nombre de chiffres, un pointeur taille entier
  • inline tableau de la valeur des chiffres, chacun détenant 30 bits de valeur, mais stockés en 32 bits (un des les bits non utilisés est utilisé pour efficace, transporter, emprunter lors de l'addition et de la soustraction)

2**63 nécessite 64 bits pour stocker, il s'adapte en trois 30 bits chiffres. Depuis, chaque chiffre est de 4 octets, l'ensemble de Python long prendra 24+3*4 = 36 octets.

En d'autres termes, la différence vient de l' long d'avoir à stocker séparément la taille du nombre (8 octets supplémentaires) et du fait qu'elle est un peu moins efficace en terme d'espace sur le stockage de la valeur (12 octets pour stocker les chiffres de 2**63). Y compris la taille, la valeur 2**63 en long occupe de 20 octets. En comparant les 8 octets occupés par toute la valeur de la simple int rendements observés de 12 octets différence.

Il est intéressant de noter que Python 3 n'a qu'un seul type entier, appelés int, qui est de largeur variable, et la mise en œuvre de la même manière que Python 2 long.


1

64-bit de Windows en diffère en ce qu'il conserve une 32-bit long int, sans doute à la source de la compatibilité avec un grand corps de vieux code qui utilisait char, short, et long comme "pratique" des alias pour les 8, 16 et 32 bits des valeurs qui s'est passé à travailler sur les deux 16 et 32 bits des systèmes. Pour obtenir une réelle 64 bits de type x86-64 Windows, il faut utiliser __int64 ou (sur les nouvelles versions de compilateur) long long ou int64_t. Depuis Python 2 en interne dépend de Python int inscriptible dans un C long, en divers lieux, sys.maxint reste 2**31-1, même sur une version 64 bits de Windows. Ce caprice est également fixé en Python 3, qui n'a pas de concept exemple maxint.

5voto

CIsForCookies Points 6642

Alors que je n'ai pas à le trouver dans la documentation, voici mon explication.

Python 2 favorise int de long implicitement, lorsque la valeur dépasse la valeur peut être stockée dans int. La taille du nouveau type (long) est la taille par défaut de long, qui est de 32. À partir de maintenant, la taille de votre variable, sera déterminée par sa valeur, qui peut monter et descendre.

from sys import getsizeof as size
a = 1
n = 32

# going up
for i in range(10):
    if not i:
        print 'a = %100s%13s%4s' % (str(a), type(a), size(a))
    else:
        print 'a = %100s%14s%3s' % (str(a), type(a), size(a))
    a <<= n

# going down
for i in range(11):
    print 'a = %100s%14s%3s' % (str(a), type(a), size(a))
    a >>= n


a =                                                                                                    1 <type 'int'>  24
a =                                                                                           4294967296 <type 'long'> 32
a =                                                                                 18446744073709551616 <type 'long'> 36
a =                                                                        79228162514264337593543950336 <type 'long'> 40
a =                                                              340282366920938463463374607431768211456 <type 'long'> 44
a =                                                    1461501637330902918203684832716283019655932542976 <type 'long'> 48
a =                                           6277101735386680763835789423207666416102355444464034512896 <type 'long'> 52
a =                                 26959946667150639794667015087019630673637144422540572481103610249216 <type 'long'> 56
a =                       115792089237316195423570985008687907853269984665640564039457584007913129639936 <type 'long'> 60
a =              497323236409786642155382248146820840100456150797347717440463976893159497012533375533056 <type 'long'> 64
a =    2135987035920910082395021706169552114602704522356652769947041607822219725780640550022962086936576 <type 'long'> 68
a =              497323236409786642155382248146820840100456150797347717440463976893159497012533375533056 <type 'long'> 64
a =                       115792089237316195423570985008687907853269984665640564039457584007913129639936 <type 'long'> 60
a =                                 26959946667150639794667015087019630673637144422540572481103610249216 <type 'long'> 56
a =                                           6277101735386680763835789423207666416102355444464034512896 <type 'long'> 52
a =                                                    1461501637330902918203684832716283019655932542976 <type 'long'> 48
a =                                                              340282366920938463463374607431768211456 <type 'long'> 44
a =                                                                        79228162514264337593543950336 <type 'long'> 40
a =                                                                                 18446744073709551616 <type 'long'> 36
a =                                                                                           4294967296 <type 'long'> 32
a =                                                                                                    1 <type 'long'> 28

Comme vous pouvez le voir, le type de séjours long après qu'il est devenu trop grand pour un int, et la taille initiale était de 32, mais les changements de taille avec la valeur (qui peut être supérieur ou inférieur [ou égal, évidemment] à 32)

Donc, pour répondre à votre question, la taille de base est de 24 int, et 28 long, tandis que l' long a aussi l'espace pour l'enregistrement de grandes valeurs (qui commence comme 4 octets - donc 32 octets pour long, mais peut monter et descendre en fonction de la valeur)

Comme pour le sous-question, la création d'un type unique (avec une taille unique) pour un nouveau numéro est impossible, donc Python a "sous-classes" de long type, qui font face à un éventail de numéros, par conséquent, une fois que vous avez dépassé la limite de votre ancien long vous devez utiliser la plus récente, ce qui représente un nombre beaucoup plus grand de trop, par conséquent, il a quelques octets de plus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X