6.4. Dtype-uri

Tipul elementelor unui ndarray este dtype-ul său. Dtype-ul decide trei lucruri deodată: câți octeți ocupă fiecare element, cum sunt interpretați octeții și ce interval de valori poate stoca tabloul. Alegerea dtype-ului potrivit este cea mai importantă decizie care afectează utilizarea memoriei RAM pe cameră.

6.4.1. Dtype-urile acceptate

numpy pe cameră acceptă un set restrâns de dtype-uri:

dtype

octeți

interval

uint8

1

0 până la 255

int8

1

-128 până la 127

uint16

2

0 până la 65.535

int16

2

-32.768 până la 32.767

float

4

IEEE 754 precizie simplă

bool

1

True / False

Nu există int32 sau int64, iar versiunea ulab de la OpenMV nu activează dtype-ul opțional complex.

Alegeți tipul care se potrivește cu hardware-ul care a produs datele. O probă de la un ADC pe 8 biți cere uint8; o probă de la un ADC pe 12 biți încape în uint16; un pixel de luminanță de la o cameră în tonuri de gri încape în uint8 – economisind de patru ori RAM-ul pe care l-ar costa dtype-ul implicit float.

6.4.2. Dtype-ul implicit

Dtype-ul implicit al fiecărui constructor de pe Crearea tablourilor este float. Acesta este rareori ceea ce dorește aplicația când prelucrează date de la senzori. Transmiteți dtype= în mod explicit ori de câte ori lățimea naturală este mai mică:

sensor = np.array(samples, dtype=np.uint16)

Re-împachetarea unui tablou de numere întregi fără un argument dtype= copiază și convertește în float, ceea ce costă atât timp, cât și RAM. Când performanța contează, specificați dtype-ul.

6.4.3. Dtype-ul unui tablou existent

dtype citește dtype-ul tabloului sub forma codului de tip întreg pe care tabloul îl poartă intern:

a = np.array([1, 2, 3], dtype=np.uint8)
print(a.dtype)            # 66 (the integer value of ``'B'``)

Numerele întregi ale codurilor de tip corespund constantelor expuse pe modulul numpynumpy.uint8, numpy.int8, numpy.uint16, numpy.int16, numpy.float, numpy.bool – astfel încât compararea dtype-ului cu constanta din modul este modul în care un script ramifică în funcție de ceea ce conține un tablou:

if a.dtype == np.uint8:
    ...  # uint8 branch

6.4.4. Reguli de promovare a tipului

Două tablouri de dtype-uri diferite pot fi operanzi ai aceluiași operator. numpy alege tipul rezultatului conform unui tabel scurt:

stânga

dreapta

rezultat

uint8

int8

int16

uint8

int16

int16

uint8

uint16

uint16

int8

int16

int16

int8

uint16

uint16

uint16

int16

float

oricare

float

float

Rândul uint16 / int16 promovează direct la float deoarece numpy pe cameră nu are dtype de număr întreg pe 32 de biți.

Când un operator binar are un scalar Python pe una dintre laturi, scalarul este convertit într-un tablou cu un singur element de cel mai mic dtype potrivit: 123 devine un tablou uint8, -1000 devine int16, un float Python devine float.

6.4.5. Depășirea numerelor întregi se ciclează

Operațiile pe două tablouri de același dtype întreg păstrează acel dtype, chiar și când rezultatul depășește. Transportul este abandonat în tăcere:

a = np.array([200, 200], dtype=np.uint8)
b = np.array([100, 100], dtype=np.uint8)
print(a + b)

Ieșire:

array([44, 44], dtype=uint8)

Rezultatul este 300 mod 256 == 44. Când un rezultat intermediar are nevoie de un interval mai mare decât permite dtype-ul de intrare, faceți mai întâi conversia:

c = np.array(a, dtype=np.uint16) + b
# array([300, 300], dtype=uint16)

Această regulă se aplică fiecărui operator pe numere întregi – +, -, *, //, %, &, |, ^. Tablourile float nu depășesc niciodată (în schimb promovează la infinit), așa că trucul conversiei este necesar doar în cazul numerelor întregi.