Spec-Zone.ru › NumPy 2.0

Типы данных

См. также

Объекты типов данных

Типы массивов и преобразования между типами

NumPy поддерживает гораздо большее разнообразие числовых типов, чем Python. Этот раздел показывает, какие типы доступны, и как изменить тип данных массива.

Числовые типы NumPy являются экземплярами numpy.dtype (объектов типа данных), каждый из которых обладает уникальными характеристиками. После импорта NumPy с помощью import numpy as np вы можете создавать массивы с заданным типом данных, используя скалярные типы из API NumPy верхнего уровня, например numpy.bool, numpy.float32 и т.д.

Эти скалярные типы в качестве аргументов ключевого слова dtype принимают многие функции или методы NumPy. Например:

>>> z = np.arange(3, dtype=np.uint8)
>>> z
array([0, 1, 2], dtype=uint8)

Типы массивов также могут обозначаться символами, например:

>>> np.array([1, 2, 3], dtype='f')
array([1.,  2.,  3.], dtype=float32)
>>> np.array([1, 2, 3], dtype='d')
array([1.,  2.,  3.], dtype=float64)

См. Указание и создание типов данных для получения дополнительной информации об указании и создании объектов типа данных, включая способ указания параметров, таких как порядок байтов.

Для преобразования типа массива используйте метод .astype(). Например:

>>> z.astype(np.float64)                 
array([0.,  1.,  2.])

Обратите внимание, что выше мы могли бы использовать Python-объект float в качестве типа данных вместо numpy.float64. NumPy знает, что int относится к numpy.int_, bool означает numpy.bool, что float — это numpy.float64, а complex — numpy.complex128. Другие типы данных не имеют эквивалентов в Python.

Чтобы определить тип массива, обратитесь к атрибуту dtype:

>>> z.dtype
dtype('uint8')

Объекты dtype также содержат информацию о типе, например, его разрядность и порядок байтов. Тип данных также может быть использован косвенно для запроса свойств типа, например, является ли он целым числом:

>>> d = np.dtype(int64)
>>> d
dtype('int64')

>>> np.issubdtype(d, np.integer)
True

>>> np.issubdtype(d, np.floating)
False

Числовые типы данных

Существует 5 основных числовых типов, представляющих булевы значения (bool), целые числа (int), беззнаковые целые числа (uint) числа с плавающей точкой (float) и complex. Название основного числового типа в сочетании с числом бит определяет конкретный тип. Разрядность — это количество бит, необходимое для представления одного значения в памяти. Например, numpy.float64 — это 64-битный тип данных с плавающей точкой. Некоторые типы, такие как numpy.int_ и numpy.intp, имеют различную разрядность в зависимости от платформы (например, 32-битные и 64-битные архитектуры процессоров). Это следует учитывать при взаимодействии с низкоуровневым кодом (например, C или Fortran), где адресное пространство обрабатывается непосредственно в памяти.

Типы данных для строк и байтов

Помимо числовых типов, NumPy также поддерживает хранение строк Юникода с помощью типа numpy.str_ (U код символа), нуль-терминированных последовательностей байтов с помощью numpy.bytes_ (S код символа) и произвольных последовательностей байтов с помощью numpy.void (V код символа).

Все вышеперечисленные типы являются фиксированной шириной. Они параметризуются шириной в байтах или кодовых точках Юникода, которую должен вместить один элемент данных в массиве. Это означает, что хранение массива последовательностей байтов или строк с помощью этого типа данных требует предварительного знания или вычисления размеров самых длинных текстовых или байтовых последовательностей.

В качестве примера можно создать массив, хранящий слова "hello" и "world!":

>>> np.array(["hello", "world!"])
array(['hello', 'world!'], dtype='<U6')

Здесь тип данных распознается как строка Юникода максимальной длиной в 6 кодовых точек, достаточно для хранения обоих элементов без усечения. Если мы укажем тип данных короче или длиннее, строка либо усекается, либо дополняется нулями, чтобы вписаться в заданную ширину:

>>> np.array(["hello", "world!"], dtype="U5")
array(['hello', 'world'], dtype='<U5')
>>> np.array(["hello", "world!"], dtype="U7")
array(['hello', 'world!'], dtype='<U7')

Мы можем увидеть заполнение нулями немного яснее, если используем тип данных bytes и попросим NumPy вывести байты в буфере массива:

>>> np.array(["hello", "world"], dtype="S7").tobytes()
b'hello\x00\x00world\x00\x00'

Каждый элемент дополняется двумя дополнительными нулевыми байтами. Однако обратите внимание, что NumPy не может отличить преднамеренно сохраненные завершающие нули от заполняющих нулей:

>>> x = [b"hello\0\0", b"world"]
>>> a = np.array(x, dtype="S7")
>>> print(a[0])
b"hello"
>>> a[0] == x[0]
False

Если вам необходимо хранить и восстанавливать любые завершающие нулевые байты, вам нужно использовать неструктурированный тип данных void:

>>> a = np.array(x, dtype="V7")
>>> a
array([b'\x68\x65\x6C\x6C\x6F\x00\x00', b'\x77\x6F\x72\x6C\x64\x00\x00'],
      dtype='|V7')
>>> a[0] == np.void(x[0])
True

Расширенные типы, не перечисленные выше, рассматриваются в разделе Структурированные массивы.

Взаимосвязь между типами данных NumPy и типами данных C

NumPy предоставляет как имена типов с указанным размером в битах, так и имена, основанные на именах типов C. Поскольку определение типов C зависит от платформы, это означает, что предпочтительнее использовать типы с явно указанным размером в битах, чтобы избежать зависящего от платформы поведения в программах, использующих NumPy.

Для упрощения интеграции с кодом C, где более естественно ссылаться на зависящие от платформы типы C, NumPy также предоставляет псевдонимы типов, которые соответствуют типам C для данной платформы. Некоторые типы данных имеют подчеркивание в конце, чтобы избежать путаницы с именами встроенных типов Python, таких как numpy.bool_.

Каноническое имя в Python API

Имя в Python API, подобное C

Фактический тип C

Описание

numpy.bool или numpy.bool_

N/A

bool (определено в stdbool.h)

Логический тип (True или False), хранится как байт.

numpy.int8

numpy.byte

signed char

Определяемый платформой целочисленный тип с 8 битами.

numpy.uint8

numpy.ubyte

unsigned char

Определяемый платформой целочисленный тип с 8 битами без знака.

numpy.int16

numpy.short

short

Определяемый платформой целочисленный тип с 16 битами.

numpy.uint16

numpy.ushort

unsigned short

Определяемый платформой целочисленный тип с 16 битами без знака.

numpy.int32

numpy.intc

int

Определяемый платформой целочисленный тип с 32 битами.

numpy.uint32

numpy.uintc

unsigned int

Определяемый платформой целочисленный тип с 32 битами без знака.

numpy.intp

N/A

ssize_t/Py_ssize_t

Определяемый платформой целочисленный тип размером size_t; используется, например, для размеров.

numpy.uintp

N/A

size_t

Определяемый платформой целочисленный тип, способный хранить максимальный размер выделения памяти.

N/A

'p'

intptr_t

Гарантированно вмещает указатели. Только код символа (Python и C).

N/A

'P'

uintptr_t

Гарантированно вмещает указатели. Только код символа (Python и C).

numpy.int32 или numpy.int64

numpy.long

long

Определяемый платформой целочисленный тип, как минимум с 32 битами.

numpy.uint32 или numpy.uint64

numpy.ulong

unsigned long

Определяемый платформой целочисленный тип, как минимум с 32 битами без знака.

N/A

numpy.longlong

long long

Определяемый платформой целочисленный тип, как минимум с 64 битами.

N/A

numpy.ulonglong

unsigned long long

Определяемый платформой целочисленный тип, как минимум с 64 битами без знака.

numpy.float16

numpy.half

N/A

Число с плавающей точкой половинной точности: бит знака, 5 бит экспоненты, 10 бит мантиссы.

numpy.float32

numpy.single

float

Определяемое платформой число с плавающей точкой одинарной точности: обычно бит знака, 8 бит экспоненты, 23 бит мантиссы.

numpy.float64

numpy.double

double

Определяемое платформой число с плавающей точкой двойной точности: обычно бит знака, 11 бит экспоненты, 52 бит мантиссы.

numpy.float96 или numpy.float128

numpy.longdouble

long double

Определяемое платформой число с плавающей точкой расширенной точности.

numpy.complex64

numpy.csingle

float complex

Комплексное число, представленное двумя числами с плавающей точкой одинарной точности (действительная и мнимая составляющие).

numpy.complex128

numpy.cdouble

double complex

Комплексное число, представленное двумя числами с плавающей точкой двойной точности (действительная и мнимая составляющие).

numpy.complex192 или numpy.complex256

numpy.clongdouble

long double complex

Комплексное число, представленное двумя числами с плавающей точкой расширенной точности (действительная и мнимая составляющие).

Поскольку многие из них имеют зависящие от платформы определения, предоставляется набор псевдонимов с фиксированным размером (см. Псевдонимы с фиксированным размером).

Скаляры массивов

NumPy обычно возвращает элементы массивов как скаляры массивов (скаляр с привязанным типом данных). Скаляры массивов отличаются от скаляров Python, но в большинстве случаев их можно использовать взаимозаменяемо (основное исключение - версии Python старше v2.x, где целочисленные скаляры массивов не могут выступать в качестве индексов для списков и кортежей). Есть некоторые исключения, например, когда код требует очень специфических атрибутов скаляра или когда он специально проверяет, является ли значение скаляром Python. В целом, проблемы легко решаются путем явного преобразования скаляров массивов в скаляры Python, используя соответствующую функцию типа Python (например, int, float, complex, str).

Основное преимущество использования скаляров массивов заключается в том, что они сохраняют тип массива (в Python может не быть соответствующего скалярного типа, например, int16). Поэтому использование скаляров массивов гарантирует идентичное поведение массивов и скаляров, независимо от того, находится ли значение внутри массива или нет. Скаляры NumPy также имеют многие из тех же методов, что и массивы.

Ошибки переполнения

Фиксированный размер числовых типов NumPy может вызывать ошибки переполнения, когда значение требует больше памяти, чем доступно в типе данных. Например, numpy.power вычисляет 100 ** 9 корректно для 64-битных целых чисел, но возвращает -1486618624 (некорректно) для 32-битного целого числа.

>>> np.power(100, 9, dtype=np.int64)
1000000000000000000
>>> np.power(100, 9, dtype=np.int32)
-1486618624

Поведение типов целых чисел NumPy и Python существенно различается при переполнении целых чисел и может сбить с толку пользователей, ожидающих, что целые числа NumPy будут вести себя аналогично целым числам Python int. В отличие от NumPy, размер целых чисел Python int гибкий. Это означает, что целые числа Python могут расширяться, чтобы вместить любое целое число, и не будут переполняться.

NumPy предоставляет numpy.iinfo и numpy.finfo для проверки минимальных или максимальных значений целых и чисел с плавающей точкой NumPy соответственно.

>>> np.iinfo(int) # Bounds of the default integer on this system.
iinfo(min=-9223372036854775808, max=9223372036854775807, dtype=int64)
>>> np.iinfo(np.int32) # Bounds of a 32-bit integer
iinfo(min=-2147483648, max=2147483647, dtype=int32)
>>> np.iinfo(np.int64) # Bounds of a 64-bit integer
iinfo(min=-9223372036854775808, max=9223372036854775807, dtype=int64)

Если 64-битные целые числа всё ещё слишком малы, результат может быть преобразован в число с плавающей точкой. Числа с плавающей точкой предлагают больший, но неточный, диапазон возможных значений.

>>> np.power(100, 100, dtype=np.int64) # Incorrect even with 64-bit int
0
>>> np.power(100, 100, dtype=np.float64)
1e+200

Расширенная точность

Числа с плавающей точкой Python обычно являются 64-битными числами с плавающей точкой, почти эквивалентными numpy.float64. В некоторых необычных ситуациях может быть полезно использовать числа с плавающей точкой с большей точностью. Возможно ли это в numpy зависит от оборудования и среды разработки: конкретно, x86-машины предоставляют аппаратную плавающую точку с точностью 80 бит, и, хотя большинство компиляторов C предоставляют это как свой тип long double, MSVC (стандартный для сборок Windows) делает long double идентичным double (64 бита). NumPy делает доступным тип компилятора long double в виде numpy.longdouble (и np.clongdouble для комплексных чисел). Вы можете узнать, что предоставляет ваш numpy, с помощью np.finfo(np.longdouble).

NumPy не предоставляет тип данных с точностью выше, чем тип C long double; в частности, 128-битный тип данных IEEE с четырёхкратной точностью (тип FORTRAN REAL*16) недоступен.

Для эффективного выравнивания памяти numpy.longdouble обычно хранится с заполнением нулями, либо до 96, либо до 128 бит. Что более эффективно, зависит от оборудования и среды разработки; обычно на 32-битных системах они дополняются до 96 бит, а на 64-битных системах — обычно до 128 бит. np.longdouble дополняется до значения по умолчанию системы; np.float96 и np.float128 предоставляются пользователям, которые хотят определённое заполнение. Несмотря на названия, np.float96 и np.float128 обеспечивают только такую же точность, как и np.longdouble, то есть 80 бит на большинстве x86-машин и 64 бита в стандартных сборках Windows.

Обратите внимание, что даже если numpy.longdouble предлагает большую точность, чем python float, легко потерять эту дополнительную точность, поскольку python часто заставляет значения проходить через float. Например, оператор форматирования % требует, чтобы его аргументы были преобразованы в стандартные типы python, и поэтому сохранить расширенную точность, даже если запрашивается много десятичных знаков, невозможно. Полезно протестировать код со значением 1 + np.finfo(np.longdouble).eps.

© 2005–2024 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/2.0/user/basics.types.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API