代码之家  ›  专栏  ›  技术社区  ›  Bram Vanroy

为什么假值(0)的字节数小于真值(1)?

  •  30
  • Bram Vanroy  · 技术社区  · 8 年前

    我在玩弄 sys getsizeof() 并发现 False (或 0 )包含的字节数少于 True (或 1 ).为什么?

    import sys
    
    print("Zero: " + str(sys.getsizeof(0)))
    print("One: " + str(sys.getsizeof(1)))
    print("False: " + str(sys.getsizeof(False)))
    print("True: " + str(sys.getsizeof(True)))
    
    # Prints:
    # Zero: 24
    # One: 28
    # False: 24
    # True: 28
    

    事实上,其他数字(也有一些由多个数字组成)是28字节。

    for n in range(0, 12):
      print(str(n) + ": " + str(sys.getsizeof(n)))
    
    # Prints:
    # 0: 24
    # 1: 28
    # 2: 28
    # 3: 28
    # 4: 28
    # 5: 28
    # 6: 28
    # 7: 28
    # 8: 28
    # 9: 28
    # 10: 28
    # 11: 28
    

    更重要的是: sys.getsizeof(999999999) 也是28字节! sys.getsizeof(9999999999) 但是,是32。

    发生了什么事?我想布尔人 符合事实的 错误的 内部转换为 0 1. 但是为什么零的大小不同于其他较低的整数呢?

    附带问题:这是特定于Python(3)如何表示这些项,还是通常在操作系统中数字是这样表示的?

    1 回复  |  直到 6 年前
        1
  •  32
  •   abarnert    8 年前

    记住Python int 值具有任意大小。这是怎么回事?

    在CPython, 1. int由 PyLong_Object ,它有一个由4字节块组成的数组 2. ,每个存储30位 3. 数字的价值。

    • 0 根本不需要块。
    • 1 - (1<<30)-1 需要1个区块。
    • 1<<30 - (1<<60)-1 需要2块。

    等等

    这有点过于简单化;有关详细信息,请参阅 longintrepr.h 在源中。


    在Python 2中,有两种不同的类型,称为 内景 long 内景 由C 32位有符号整数表示 4. 直接嵌入头中,而不是块数组。A. 长的 就像Python 3 内景

    如果您对 0L ,则, 1L ,以明确要求 长的 值,您将得到与Python 3中相同的结果。但没有 L 后缀,任何32位的文字都会 内景 ,并且只有太大的文本才能 长的 s 5. (这意味着 (1<<31)-1 是一个 内景 但是 1<<31 是2块 长的 .)


    1、在不同的实现中,这可能不是真的。IIRC,Jython的功能与CPython大致相同,但IronPython使用C#“bignum”实现。

    2、为什么是30位而不是32位?主要是因为 pow ** 如果可以假设两个“数字”中的位数可以除以 10

    3、使用C "struct hack" .技术上,a Py_LongObject 是28字节,但没有人分配 Py\u LongObject ;它们将malloc 24、28、32、36等字节转换为 Py_LongObject *

    事实上,一条巨蟒 内景 是C 长的 ,只是为了让事情变得混乱。因此,C API充满了以下内容 PyInt_FromLong 其中 长的 表示“32位int”和 PyLong_FromSize_t 其中 长的 表示“bignum”。

    Python 2的早期版本。x未集成 内景 长的 很好,但希望没有人再担心这些了。

    推荐文章