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 |
|---|---|---|
|
1 |
0 până la 255 |
|
1 |
-128 până la 127 |
|
2 |
0 până la 65.535 |
|
2 |
-32.768 până la 32.767 |
|
4 |
IEEE 754 precizie simplă |
|
1 |
|
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 numpy – numpy.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 |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
oricare |
|
|
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.