2

uint8我正在寻找一种从 Python 获取(使用 Python)C 类型整数(即, int8, uint16, int16, uint32, int32, uint64, int64...)的最大值和最小值的方法。

我期待在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 类型整数。当 number 不在预期的时间间隔内时,它应该引发异常。

目前溢出不会引发异常:

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

我看到了这个 SO postMaximum and Minimum values for ints但它有点不同,因为作者正在寻找 Python 整数的最小/最大值......而不是 C 整数(来自 Python)

我还注意到在 python 中检测 C 类型限制(“limits.h”)?但是,即使它非常相关,也不能真正回答我的问题。

4

1 回答 1

5

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

整数具有无限的精度。

翻译成代码:

>>> i = 10 ** 100
>>> i
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
>>> len(str(i))
101
>>> i.bit_length()
333

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

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

代码00.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():
    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} on {:s}\n".format(sys.version, sys.platform))
    main()

备注

  • 代码依赖于这样一个事实,即对于某个整数类型,它的区间(并且限制是区间的端点)是:
    • 有符号 2的补码)[-(2 bit_size - 1 ), 2 bit_size - 1 - 1]
    • 无符号[0, 2 bit_size - 1]
  • 要检查 a 类型的signum,请使用-1 (无符号类型将自动转换为上限(由于环绕算术) )
  • 输出有很多重复项(如下),因为某些类型只是其他类型的“别名”
  • 您的其余任务(创建一个将Python intctypes类型限制进行比较的函数,如果不是则引发异常)是微不足道的,所以我没有实现它
  • 这仅用于演示目的,因此我没有进行任何参数检查

输出

(py35x64_test) e:\Work\Dev\StackOverflow\q052475749>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code00.py
Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] 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)
于 2018-09-24T18:44:07.407 回答