MATLAB: typy danych

Table of Contents

Typy danych numerycznych

podwójnej precyzji

zakres liczb podwójnej precyzji

dokładność obliczeń

niedokładności

wynik operacji

Pojedynczej precyzji

wynik operacji

konwersje

zakres liczb pojedynczej precyzji

precyzja

Liczby całkowite

Inne typy numeryczne

konwersje typów

Kilka pożytecznych funkcji

Zakresy liczb

Znaki i napisy

parę funkcji

Typy danych numerycznych

  1. double Double-precision arrays
  2. single Single-precision arrays
  3. int8 8-bit signed integer arrays
  4. int16 16-bit signed integer arrays
  5. int32 32-bit signed integer arrays
  6. int64 64-bit signed integer arrays
  7. uint8 8-bit unsigned integer arrays
  8. uint16 16-bit unsigned integer arrays
  9. uint32 32-bit unsigned integer arrays
  10. uint64 64-bit unsigned integer arrays

Podwójnej precyzji

format default
x = 1.1;
class(x) 
ans = 'double'

Jest to typ domyślny. Inne typy trzeba w odpowiedni sposób deklarować

stała zapisana jako 1.1 traktowana jest jako

class(1.1)
ans = 'double'

typu double

zakres liczb podwójnej precyzji

realmax
ans = 1.7977e+308

albo

realmax('double')
ans = 1.7977e+308
realmin
ans = 2.2251e-308

dokładność obliczeń

Sprawa jest dosyć skomplikowana i związana ze zmiennoprzecinkowym sposobem pzechowywania wartości.

Dostępna jest funkcja eps() pokazująca o ile rożni się następna (większa) wartość (jaka jest wartość najmniej znaczącego bitu w tej liczbie)

format default
eps(0)
ans = 4.9407e-324
eps(0.1)
ans = 1.3878e-17
eps(1)
ans = 2.2204e-16
eps(2)
ans = 4.4409e-16
eps(1000)
ans = 1.1369e-13

Jak widać „dostępne” do obliczeń wartości nie są rozłożone równomiernie na osi liczbowej!

eps(1e10)
ans = 1.9073e-06
eps(1e100)
ans = 1.9427e+84
eps(1e300)
ans = 1.4870e+284
eps(2^10)
ans = 2.2737e-13
format hex
eps(0)
ans = 
   0000000000000001
format default

niedokładności

Jaki będzie wynik operacji poniższej operacji?

ponieważ 4/3 to jeden i jedna trzecia, zatem powinien być równy zero, prawda?

format default
e = 1 - 3*(4/3 - 1)
e = 2.2204e-16

Jest to spowodowane tym, że ułamek $\frac{4}{3}$ nie ma dokładnej reprezentacji binarnej.

eps(1)
ans = 2.2204e-16

e równe jest wartości eps(1).

A co będzie teraz?

e = 1 - 10*(11/10 - 1)
e = -8.8818e-16

wynik operacji

Wynik operacji wykonywanej na argumentach różnego typu będzie

  • single — typu single
  • double — typu double
  • int8, int16, int32, int6 — będzie odpowiedniego typu int
  • uint8, uint16, uint32, uint64 — będzie odpowiedniego typu uint
  • char — będzie typu double
  • logical — będzie tylu double

Pojedynczej precyzji

y = single(1.1)
y = 1.1000
whos x y
  Name      Size            Bytes  Class     Attributes

  x         1x1                 8  double              
  y         1x1                 4  single              

(zwracam uwagę na dopisek z informacją o klasie)

x - y
ans = -2.3842e-08

to dosyc dziwne, bo typ wyniku jest „mniejszy” niż typ „największego” argumentu (i nie zależy od kolejnoci wykonywania działań

y - x
ans = 2.3842e-08

wynik operacji

Operacje wykonywane na zmiennych (i stałych) typu single i zmiennych i stałych typu

  • double
  • single
  • char
  • logical

będą miały typ single.

konwersje

Ad = [1 2 0; 2 5 -1; 4 10 -1]
Ad = 3x3    
     1     2     0
     2     5    -1
     4    10    -1

To jest, oczywiście macierz podwójnej precyzji

A = single(Ad)
A = 3x3 single matrix    
     1     2     0
     2     5    -1
     4    10    -1

podobnie jak

A = cast(Ad,'single')
A = 3x3 single matrix    
     1     2     0
     2     5    -1
     4    10    -1

Wszystkie operacje wykonywane na zmiennych typu single będą dawały wynik single.

zakres liczb pojedynczej precyzji

realmax('single')
ans = 3.4028e+38
realmin('single')
ans = 1.1755e-38

precyzja

class(y)
ans = 'single'
eps(y)
ans = 1.1921e-07
eps(single(0))
ans = 1.4013e-45
eps(single(1000))
ans = 6.1035e-05
eps(single(1e20))
ans = 8.7961e+12

Czyli podobnie jak w przypadku double.

Liczby całkowite

MATLAB całkiem nieźle radzi sobie z typem całkowitym, ale, trzeba pamiętać, że

class(1)
ans = 'double'

Funkcja flintmax zwraca informację o największej liczbie całkowitej, która może być zapisana dokładnie w formacie podwójnej precyzji

format long
z = flintmax
z = 
     9.007199254740992e+15
e = eps(z)
e = 
     2
zz = z + e
zz = 
     9.007199254740994e+15
z = z + 1
z = 
     9.007199254740992e+15
(((z+1)+1)+1)
ans = 
     9.007199254740992e+15
1+1+1+1+z
ans = 
     9.007199254740996e+15

Inne typy numeryczne

Deklaruje się podobnie jak single:

a = uint8(5)
a = uint8
   5
aa = uint8(-5)
aa = uint8
   0
intmax("uint8")
ans = uint8
   255
intmin("uint8")
ans = uint8
   0
intmin("int8")
ans = int8
   -128
intmax("int16")
ans = int16
   32767

konwersje typów

  1. cast Convert variable to different data type (rzutowanie)
  2. typecast Convert data type without changing underlying data
class(a)
ans = 'uint8'
a
a = uint8
   5
b = cast(a,"int8")
b = int8
   5
a=uint8(255)
a = uint8
   255
b = cast(a,"int8")
b = int8
   127

To ostatnie jest bardzo nieoczywiste (przynajmniej z punktu widzenia programisty w C). Ale patrz dalej na funkcję typecast().

b = int8(-128)
b = int8
   -128
a = cast(b, "uint8")
a = uint8
   0

Inna forma konwersji to

class(x)
ans = 'double'
class(y)
ans = 'single'
class(a)
ans = 'uint8'
class(b)
ans = 'int8'
b
b = int8
   -128
cast(b, "like", y)
ans = single
  -128

Czyli rzutuj zmienną b na typ zmiennej y.

typecast

class(a)
ans = 'uint8'
class(b)
ans = 'int8'
a = uint8(255)
a = uint8
   255
b = typecast(a,'int8')
b = int8
   -1

Wartość bitowa się nie zmieniła, ale dokonano reinterpretacji danych. 255 to bajt zawierający 8 jedynek, jak tę kombinację bitów potraktować jako wartość int8 to będzie to -1.

format hex
a
a = uint8
   ff
b
b = int8
   ff

I jeszcze taka ciekawostka

format default
X = int8([77 60 43 26])
X = 1x4 int8 row vector    
   77   60   43   26
Y = typecast(X,'single')
Y = 3.5411e-23
format hex
X
X = 1x4 int8 row vector    
   4d   3c   2b   1a
Y
Y = single
   1a2b3c4d

Kilka pożytecznych funkcji

  1. allfinite Determine if all array elements are finite (Since R2022a)
  2. anynan Determine if any array element is NaN (Since R2022a)
  3. isinteger Determine whether input is integer array
  4. isfloat Determine if input is floating-point array
  5. isnumeric Determine whether input is numeric array
  6. isreal Determine whether array uses complex storage
  7. isfinite Determine which array elements are finite
  8. isinf Determine which array elements are infinite
  9. isnan Determine which array elements are NaN
  10. isa() Determine if x is the specified numeric type
  11. whos x Display the data type of x

Format zmiennoprzecinkowy pozwala oprócz wartości numerycznych potrafi przechowywać trzy dodatkowe wartości:

  1. Inf $+\infty$
  2. -Inf $-\infty$
  3. NaN Not a Number
format default
A = 0./[-2 -1 0 1 2]
A = 1x5    
     0     0   NaN     0     0
anynan(A)
ans = logical
   1
isnan(A)
ans = 1x5 logical array    
   0   0   1   0   0
B = [-2 -1 1 2]/0
B = 1x4    
  -Inf  -Inf   Inf   Inf
anynan(B)
ans = logical
   0
isreal(B)
ans = logical
   1
isfinite(B)
ans = 1x4 logical array    
   0   0   0   0
isinf(B)
ans = 1x4 logical array    
   1   1   1   1

Zakresy liczb

  1. eps Floating-point relative accuracy
  2. flintmax Largest consecutive integer in floating-point format
  3. Inf Create array of all Inf values
  4. intmax Largest value of specific integer type
  5. intmin Smallest value of specific integer type
  6. NaN Create array of all NaN values
  7. realmax Largest positive floating-point number
  8. realmin Smallest normalized floating-point number
u = Inf
u = Inf
v = -Inf
v = -Inf
w = NaN
w = NaN
format hex
u
u = 
   7ff0000000000000
v
v = 
   fff0000000000000
w
w = 
   fff8000000000000

Znaki i napisy

Tak przetłumaczyłem z angielskiego characters i strings.

c = 'Ala ma kota'
c = 'Ala ma kota'
c(1)
ans = 'A'
c = ['ala' 'ma' 'kota']
c = 'alamakota'
c(1)
ans = 'a'
C = "Ala ma kota"
C = "Ala ma kota"
C(1)
ans = "Ala ma kota"
whos C
  Name      Size            Bytes  Class     Attributes

  C         1x1               174  string              
C = ["Ala" "ma" "kota"]
C = 1x3 string    
"Ala"        "ma"         "kota"       
whos C
  Name      Size            Bytes  Class     Attributes

  C         1x3               274  string              
C(1)
ans = "Ala"
class(c)
ans = 'char'
class(C)
ans = 'string'
char("Ala")
ans = 'Ala'
z = char(C)
z = 1x4x3 char array
z(:,:,1) =

    'Ala '

z(:,:,2) =

    'ma  '

z(:,:,3) =

    'kota'
z(1)
ans = 'A'
z(1, 1)
ans = 'A'
z(1, 1, 1)
ans = 'A'
z(:, :, 1)
ans = 'Ala '
string('Ala')
ans = "Ala"

Jak widać jst różnica…

parę funkcji

format default

String Arrays

  1. string String array
  2. strings Create string array with no characters
  3. join Combine strings
  4. plus Add numbers, append strings

Character Arrays

  1. char Character array
  2. cellstr Convert to cell array of character vectors
  3. blanks Create character array of blanks
  4. newline Create newline character

Character or String Arrays

  1. compose Format data into multiple strings
  2. sprintf Format data into string or character vector
  3. strcat Concatenate strings horizontally
  4. append Combine strings (Since R2019a)

Convert Input Arguments

  1. convertCharsToStrings Convert character arrays to string arrays, leaving other arrays unaltered
  2. convertStringsToChars Convert string arrays to character arrays, leaving other arrays unaltered
  3. convertContainedStringsToChars Convert string arrays at any level of cell array or structure

Convert Between Numeric and Strings

  1. double Double-precision arrays
  2. string String array
  3. str2double Convert strings to double precision values
  4. num2str Convert numbers to character array
format default
v = str2double("10.5")
v = 10.5000
V = str2double('10.43')
V = 10.4300
class(v)
ans = 'double'
C = num2str(v)
C = '10.5'
C = num2str(123.456789)
C = '123.4568'
C = num2str(123.456789e3)
C = '123456.789'
whos v V C
  Name      Size            Bytes  Class     Attributes

  C         1x10               20  char                
  V         1x1                 8  double              
  v         1x1                 8  double              

Format wywołania funkcji jest bardziej rozbudowany

s = num2str(pi)
s = '3.1416'
s = num2str(pi,3)
s = '3.14'
s = num2str(pi,"%+020.5f zł")
s = '+0000000000003.14159 zł'

format:

image_0.png

Poprzedni