Python中C类型整数的最大值和最小值

4
我正在寻找一种使用Python获取C类型整数(即uint8int8uint16int16uint32int32uint64int64等)的最大和最小值的方法。
我原以为可以在ctypes模块中找到。
In [1]: import ctypes
In [2]: ctypes.c_uint8(256)
Out[2]: c_ubyte(0)
In [3]: ctypes.c_uint8(-1)
Out[3]: c_ubyte(255)

但是我找不到它。

Julia在这方面有很好的特性:

julia> typemax(UInt8)
0xff

julia> typemin(UInt8)
0x00

julia> typemin(Int8)
-128

julia> typemax(Int8)
127

我很确定Python有类似的东西。

理想情况下,我甚至正在寻找一种方法来确保给定的Python整数(被称为无界)可以安全地转换为给定大小的C类型整数。 当数字不在预期间隔内时,它应该引发异常。

目前,溢出不会引发异常:

In [4]: ctypes.c_uint8(256)
Out[4]: c_ubyte(0)

我看到了这篇SO帖子Maximum and Minimum values for ints,但是作者正在寻找Python整数的最小值和最大值...而不是C整数(来自Python)。
我还注意到了Detecting C types limits ("limits.h") in python?,尽管与我的问题相关,但它并没有真正回答我的问题。
1个回答

9
根据[Python.Docs]: Numeric Types - int, float, complex

整数具有无限精度。

翻译成代码:
>>> i = 10 ** 100
>>> i
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
>>> len(str(i))
101
>>> i.bit_length()
333

另一方面,每种 C 类型都有固定的大小(取决于平台/架构),如 [CPPReference]: Fundamental types 中清楚地显示。

由于 [Python.Docs]: ctypes - A foreign function library for Python 没有提及类型限制(请注意,那里有一些未记录的内容),让我们手动找出它们。

code00.py:

#!/usr/bin/env python3

import sys
from ctypes import c_int8, c_uint8, c_byte, c_ubyte, c_int16, c_uint16, \
    c_int32, c_uint32, c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong, \
    c_int64, c_uint64, \
    sizeof


def limits(c_int_type):
    signed = c_int_type(-1).value < c_int_type(0).value
    bit_size = sizeof(c_int_type) * 8
    signed_limit = 2 ** (bit_size - 1)
    return (-signed_limit, signed_limit - 1) if signed else (0, 2 * signed_limit - 1)


def main(*argv):
    test_types = (
        c_int8,
        c_uint8,
        c_byte,
        c_ubyte,
        c_int16,
        c_uint16,
        c_int32,
        c_uint32,
        c_int,
        c_uint,
        c_long,
        c_ulong,
        c_longlong,
        c_ulonglong,
        c_int64,
        c_uint64,
    )
    for test_type in test_types:
        print("{:s} limits: ({:d}, {:d})".format(test_type.__name__, *limits(test_type)))


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.")
    sys.exit(rc)

  • 代码依赖于某个整数类型的区间(以及区间端点的极限):

    • 有符号 (2's complement): [-(2 bit_size - 1), 2 bit_size - 1 - 1]

    • 无符号: [0, 2 bit_size - 1]

  • 要检查类型的符号,使用-1(由于wrap around arithmetic,它将自动转换为上限,对于unsigned类型)

  • 输出中有很多重复项,因为一些类型只是其他类型的“别名”

  • 你的任务剩下的部分(创建一个函数,将Python intCTypes类型极限进行比较,并在不匹配时引发异常)很简单,所以我没有实现它

  • 这仅用于演示目的,因此我没有进行任何参数检查

输出:

  • Win:

    • Python pc064 (064bit):

      [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q052475749]> "e:\Work\Dev\VEnvs\py_pc064_03.09_test0\Scripts\python.exe" ./code00.py
      Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] 064bit on win32
      
      c_byte limits: (-128, 127)
      c_ubyte limits: (0, 255)
      c_byte limits: (-128, 127)
      c_ubyte limits: (0, 255)
      c_short limits: (-32768, 32767)
      c_ushort limits: (0, 65535)
      c_long limits: (-2147483648, 2147483647)
      c_ulong limits: (0, 4294967295)
      c_long limits: (-2147483648, 2147483647)
      c_ulong limits: (0, 4294967295)
      c_long limits: (-2147483648, 2147483647)
      c_ulong limits: (0, 4294967295)
      c_longlong limits: (-9223372036854775808, 9223372036854775807)
      c_ulonglong limits: (0, 18446744073709551615)
      c_longlong limits: (-9223372036854775808, 9223372036854775807)
      c_ulonglong limits: (0, 18446744073709551615)
      
      完成。
      
    • Python pc032 (032bit):

      [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q052475749]> "e:\Work\Dev\VEnvs\py_pc032_03.10_test0\Scripts\python.exe" ./code00.py
      Python 3.10.1 (tags/v3.10.1:2cd268a, Dec  6 2021, 18:54:59) [MSC v.1929 32 bit (Intel)] 032bit on win32
      
      c_byte limits: (-128, 127)
      c_ubyte limits: (0, 255)
      c_byte limits: (-128, 127)
      c_ubyte limits: (0, 255)
      c_short limits: (-32768, 32767)
      c_ushort limits: (0, 65535)
      c_long limits: (-2147483648, 2147483647)
      c_ulong limits: (0, 4294967295)
      c_long limits: (-2147483648, 2147483647)
      c_ulong limits: (0, 4294967295)
      c_long limits: (-2147483648, 2147483647)
      c_ulong limits: (0, 4294967295)
      c_longlong limits: (-9223372036854775808, 9223372036854775807)
      c_ulonglong limits: (0, 18446744073709551615)
      c_longlong limits: (-9223372036854775808, 9223372036854775807)
      c_ulonglong limits: (0, 18446744073709551615)
      
      完成。
      
  • Nix (Linux - WSL2) - Python pc064:

    (qaic-env) [cfati@cfati-5510-0:/mnt/e/Work/Dev/StackOverflow/q052475749]> python ./code00.py
    Python 3.8.10 (default, Mar 15 2022, 12:22:08) [GCC 9.4.0] 064bit on linux
    c_byte limits: (-128, 127) c_ubyte limits: (0, 255) c_byte limits: (-128, 127) c_ubyte limits: (0, 255) c_short limits: (-32768, 32767) c_ushort limits: (

    (或多或少相关):


@CristiFati 给出了很好的答案。我想知道这些限制函数是否应该直接添加到 Python ctypes 源代码中(或者将 max/min 属性添加到 ctypes.c_ 类型中)。使用 https://pastebin.com/cvm95m1x 也可以很容易地将其转换为 C 类型整数并引发异常,但也许这应该成为 Python 核心的一部分。你有什么看法? - scls
ctypes.c_types中添加一个issigned属性也可能是一个有趣的想法。 - scls
你(或者我)可以向Python提交一个补丁(我以前做过,有些被接受了,有些被拒绝了)。关于异常抛出,我认为这不会成为问题,因为在C中,一个值会被截断/静默转换以适应类型大小(当然还要有适当的编译器警告)。是的,我想这两个东西都可能很有用,但大多数需要在这个级别上工作的人也知道如何做。而且代码非常简短。我不确定如何指向他们这个问题,如果他们发现有用的东西,他们可以得到它。 - CristiFati
但也许它已经存在(而我不知道),或者在更新的版本中,或者有一个功能请求。必须检查一下。谢谢!顺便说一句:我认为 ctype_convert 应该返回 c_n - CristiFati
感谢@wjandrea的编辑。然而,在我所有的答案中(至少是5年前的答案),有一件事是不变的,那就是URL格式。我并不是说这是最好的格式(有些人可能喜欢它,而另一些人可能讨厌它),但这是我认为适合的(至少目前是这样)。因此,我撤销了更改。对于造成的麻烦和不便,我表示抱歉,没有冒犯之意。 - CristiFati
@CristiFati NP,我不会介意的。是的,我也觉得这种格式很难阅读。首先,模块子标题没有增加任何内容(即“int,float,complex”中,“float和complex”并不相关,“Python外部函数库”是一种描述,但假定任何阅读您答案的人都知道ctypes是什么)。其次,提到链接目标对我来说完全有意义,但在括号中将其放在最前面会影响流程,放在后面更容易阅读,即Numeric Types [Python 3 docs]Fundamental types [CPPReference]ctypes [Python 3 docs] - wjandrea

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接