Максимальное и минимальное значение целых чисел типов C из Python - PullRequest
0 голосов
/ 24 сентября 2018

Я ищу способ получить (используя Python) максимальное и минимальное значения целых чисел типов C (т. Е. uint8, int8, uint16, int16, uint32, int32, uint64, int64 ...) из Python.

Я ожидал найти это в ctypes module

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> 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 Максимальное и минимальное значения дляints , но немного по-другому, поскольку автор ищет минимальное / максимальное значение целого числа Python ... не целое число C (из Python)

Я также заметил Определение ограничений типов C ("limit.h") в python? но, даже если он довольно связан, он не отвечает на мой вопрос.

1 Ответ

0 голосов
/ 24 сентября 2018

Согласно: [Python 3.Docs]: числовые типы - int, float, complex :

Целые числа имеют неограниченную точность.

Переведено в код:

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

С другой стороны, каждый тип C имеет фиксированный размер (в зависимости от платформы / архитектуры), как четко показано на [CppReference]: Фундаментальные типы .

Начиная с [Python 3.Docs]: ctypes - Библиотека сторонних функций для Python ничего не упоминает об ограничениях типов ( обратите внимание, что некоторые вещи здесь не документированы ), давайте выясним это вручную.

code.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 дополнение) : <strong><em>[-(2 <sup>bit_size - 1</sup>), 2 <sup>bit_size - 1</sup> - 1]</em></strong>
    • без знака : <strong><em>[0, 2 <sup>bit_size</sup> - 1]</em></strong>
  • Для проверки типа signum , используйте -1 (который будет автоматически преобразован в верхний предел (из-за обтекание арифметики ) с помощью unsigned types)
  • Есть много дубликатов выходных данных (ниже), потому что некоторые типы просто "псевдонимы" для других
  • Остальная часть вашей задачи (создание функции, которая сравнивает Python int до пределов ctypes и вызывает исключение, если это не так) тривиально, поэтому я не реализовал его
  • Это только для демонстрации цели, поэтому я не проверял аргументы

Вывод :

(py35x64_test) e:\Work\Dev\StackOverflow\q052475749>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code.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)
...