Numpy dtype view - PullRequest
       1

Numpy dtype view

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

Я следую учебному пособию, показанному ниже, в разделе Виды Dtype:

https://scipy -cookbook.readthedocs.io / items / ViewsVsCopies.html

Я воспроизвел это ниже:

import numpy as np

b = np.arange(10, dtype='int16')
b
#array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int16)
v3 = b.view('int32')
v3 += 1
b
#array([1, 1, 3, 3, 5, 5, 7, 7, 9, 9], dtype=int16)
v4 = b.view('int8')
v4
#array([1, 0, 1, 0, 3, 0, 3, 0, 5, 0, 5, 0, 7, 0, 7, 0, 9, 0, 9, 0], dtype=int8)

Меня больше всего смущает вопрос, почему v3 выглядит как?

array([ 65536, 196610, 327684, 458758, 589832], dtype=int32)

Несмотря на то, что при просмотре v3 все равно равен b при просмотреas ('int16'), как подтверждает следующий код:

v3.view('int16')
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int16)

Меня также немного смущает значение b после выражения сложения v3 + = 1:

array([1, 1, 3, 3, 5, 5, 7, 7, 9, 9], dtype=int16)

Здесь (1, dtype = 'int32') добавляется в v3, что, в свою очередь, добавляет его в b.

Будет ли такое представление, выражения dtype всегда обновляют просматриваемый массив, в данном случае b?

Поскольку dtype ('int32') в два раза больше, он будет иметь удвоенную длину значений 'int16' и перезаписывает два из них за раз, его шаг также будет вдвое большебольшой и поэтому он берет каждую вторую цифру в b.

Правильно ли это истолковано?

Почему каждая цифравозвращается дважды, а не просто возвращает усеченный b?

array([1, 3, 5, 7, 9], dtype=int16)

1 Ответ

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

Это связано с тем, как хранится массив.В непрерывном (важном!) Порядке фактический блок памяти b выглядит как

[0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0...]

, где каждое число представляет byte в памяти.Блок памяти можно просмотреть как любой dtype.При просмотре как int16 два byte с образуют число, и результат становится

[00 10 20 30 40 50 60 70...]

при просмотре как int32, четыре byte с образуют число, а результат становится

[0010 2030 4050...]

современные ПК используют little-endian для хранения номера.Это означает, например, что int32(1234) следует интерпретировать как 1*256^0 + 2*256^1 + 3*256^2 + 4*256^3, а int16(56) следует интерпретировать как 5*256^0 + 6*256^1.По этой причине 0010 становится 65536, 2030 становится 196610 и т. Д.

При добавлении одного к представлению int32, поскольку представление int32 технически совместно использует тот же блок памяти сМассив int16 (представление всегда разделяет блок памяти с массивом view-ed), также будет изменен массив int16.Добавление int32 one означает добавление 1000 (то есть добавление единицы к крайнему левому числу в xxxx), что соответствует члену 256^0 в каждом четном номере позиции:

int32 view: [1010 3030 5050 7070]
int16 view: [10 10 30 30 50 50 70 70]

Следовательно, представление int16 преобразуется в [1 1 3 3 5 5 7 7...].

BTW:

  • Литерал 1 не имеет dtype.Это может быть напечатано long (то есть int32), когда numpy не может выбрать лучший тип.Но когда вы делаете что-то вроде a += 1, число будет набираться dtype из a

  • Numpy поддерживает массив big-endian (то есть int32(1234) выше становится 4321 в памяти).В этом случае результат изменения представления будет совершенно другим

  • Numpy также поддерживает массив, который фактически хранится в обратном направлении (то есть [int16(10), int16(20), int16(30), int16(40)] на самом деле [4 0 3 0 2 0 1 0] в памяти).Это также будет иметь эффект

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

Ваши идеи о том, что «просмотр» как отличающийся dtype не должен изменять значение случайным образом, относятся кcast (т. е. astype).Приведение возвращает новую копию с тем же значением, но с другим dtype.Из-за разницы в размерах dtype приведение не может совместно использовать память с исходным массивом, и оно более или менее неэффективно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...