Table of Contents

Základy programování v Matlabu - část 4

Ing. Petr Pokorný, Ph.D.

Funkce

Funkce jsou samostatné obecně napsané skripty nebo jejich části, pomocí kterých můžeme rozčleňovat, zpřehledňovat a řídit komplexně psaný kód programu.

Uživatelsky definované funkce

function [vystupy] = jmeno(vstupy)
% popis funkce pro help a doc
vystupy = vstupy;
end

Příklad: Funkce pro výpočet lichoběžníkového pravidla

function I = intlich(x,y)
% I = intlich(x,y)
% vypocte numericky integral lichobeznikovym pravidlem
a = x(1); b = x(end);
fa = y(1); fb = y(end);
N = length(x)-1;
I = (b - a)/N*((fa + fb)/2 + sum(y(2:end-1)));
end

Funkce s volitelným počtem vstupních parametrů

Matlab umožňuje vytvářet funkce s předem neznámým počtem a typem vstupních parametrů. Pro vhodnou organizaci skriptu slouží dvě funkce:
function N = myfcn(varargin)
% N = myfcn(varargin)
% demonstracni funkce pro volitelny pocet vstupnich parametru
N = nargin; % vrati pocet vstupnich parametru
for in = 1:N
disp( varargin{in} ); % postupne zobrazi bunku na pozici in
end
end

In-line a lokálně definované funkce

Další z možností tvorby funkcí jsou:
function main
% main nadrazena funkce
% In-line funkce
fce1 = @(x) x.^2 + 3;
% Volani in-line funkce
a = 50;
b = fce1(a);
% Volani vnorene funkce
c = localFcn(b);
function out = localFcn(in)
% lokalne definovana funkce
out = in + a; % a je dedena promenna
end
end

Hierarchie hledání zdrojového kódu funkce

Při volání funkce Matlab postupně provádí následující kroky:
  1. Je-li funkce volána ve skriptu, nejprve prohledává tento aktivní skript a při výskytu inline nebo vnořené funkce volá její zdrojový kód.
  2. Není-li funkce in-line nebo vnořená, prohledává současný aktivní adresář (Current Folder). Je-li přítomný m-file se jménem totožným s názvem volané funkce, volá jeho zdrojový kód.
  3. Není-li funkce nalezena v bodech 1. a 2., prohledává zadané cesty vyhledávání (způsob prohlížení nebo zadávání vyhledávacích cest viz doc path).

Příklady

Příklad 1 (upravený příklad 3 z části 3)

Napište funkci, pomocí které budete iterativně počítat odmocninu z reálného čísla x s přesností 1e−15. Využijte rekurentní vztah pro daný jako:
Funkci vhodně nazvěte, vstupní parametry volte x - číslo, ze kterého je počítána odmocnina, T - tolerance výpočtu.
K výpočtu odmocniny využijte cyklus while nebo jiný vhodný způsob.
Nápověda k řešení cylku:
  1. Definujte proměnnou TEST rovnou např. 1. Dále definujte proměnnou Y rovnu vstupní hodnotě X.
  2. Využijte while cyklus, který bude probíhat tak dlouho, dokud TEST nesplní podmínku přesnosti (TEST > 1e−15).
  3. Ve while cyklu definujte proměnnou Y0 rovnu hodnotě Y.
  4. Dále přepočítejte hodnotu proměnné Y dle rekurzivního vztahu.
  5. Hodnotu TEST přepočítejte jako absolutní hodnotu rozdílu hodnot Y a Y0.

Příklad 2 (upravený příklad 4 z části 3)

Vytvořte soubor vyhlazeni.m a vyčistěte prostředí (clc, close all, clear all).
Vytvořte vektor X = [1, 1.4, 2, 2.9, 3.5, 4, 5.1, 7, 8.2, 9.1, 9.3, 9.5, 10]. Dále vytvořte vektor Y s hodnotami √(X) + "náhodně generované číslo" s normálním rozdělením s nulovou střední hodnotou a směrodatnou odchylkou 0.1.
Napište funkci, která bude vyhlazovat 2D data Y pomocí průměrování na okolí ±W/2 okolo daného bodu X, kde W je libovolná šířka průměrujícího intervalu (reálné číslo). Vstupní parametry funkce budou data X a Y a šířka okna W.
Volejte funkci pro různé šířky okna a filtrovaná data zobrazte do vhodného grafu.

Příklad 3 (upravený příklad 3 a 4 z části 3 - pokračování)

Vytvořte funkci pro výpočet numerické integrace lichoběžníkovým pravidlem nad daty X a Y a to takovým způsobem, že funkce rozliší, zda byly zadány dva vektory nebo jeden:
  1. Jestliže je na vstupu zadán jeden vektor, předpokládejte, že je to vektor Y s rovnoměrným dělením s rozestupem 1.
  2. Jestliže jsou na vstupu zadány dva vektory, poté předpokládejte, že se jedná o vektory X a Y, ale uvažujte, že dělení X není rovnoměrné a spusťte algoritmus pro adaptivní dělení vektoru X (viz příklad 4 z části 3 - pokračování) s tolerancí .

Příklad 4

Pepík chce vytvořit pomůcku pro svého tatínka, vášnivého turistu, a napsat funkci, pomocí které dokáže určit vesnici nejblíže zadanému bodu. Z mapy odměřil souřadnice pěti vesnic (viz kód níže). Předpokládejme, že se tatínek ke každé vesnici z každého bodu může dostat po přímé čáře.
% tabulka_vesnice = [ id_vesnice X Y ]
tabulka_vesnice = [ 1 125.25 479.52
2 548.73 354.52
3 155.84 486.34
4 486.47 809.13
5 765.14 907.15 ];
Napište samostatnou funkci najdi_vesnici, kde vstupními parametry budou:
Výstupem poté bude index (číslo řádku matice) vesnice, která je nejblíže danému bodu. Pokud bude více vesnic stejně vzdáleno od daného bodu a blíže než ostatní, vypište indexy všech. Využijte např. funkce sqrt, min, find, apod.
Vytvořte poté nový skript a vyčistěte prostředí (clc, close all, clear all). Ve skriptu vytvořte matici se souřadnicemi vesnic (souřadnice můžete volit sami) a zkoušejte volat vytvořenou funkci pro hledání vesnic. Můžete vytvořit přehledný graf vyhledávání.

Příklad 5

Doplňte funkci najdi_vesnici z příkladu 4 ošetřením vstupních dat:
  1. Zajistěte, aby byly zadány oba dva vstupní parametry funkce (if, nargin). Pokud tomu tak není, vypište chybové hlášení (error).
  2. Dále ošetřete, zda-li má matice XY_vesnice dva sloupce (size) a není-li prázdná (isempty) a zda-li vektor XY_bod má dva prvky. Nebude-li tomu tak, opět vypište chybové hlášení (error).
Napadnou-li vás další podmínky, funkci doplňte.

Příklad 6

Napište funkci, která vyhladí průměrujícím filtrem 3D data. Data k vyhlazení nasimulujte jako matici DATA pomocí funkce peaks na gridu {−3:0.1:3}x{−2:0.1:2} s přidáním náhodného šumu s normálním rozdělením se střední hodnotou 0 a směrodatnou odchylkou 0.5 (randn).
Vytvořte funkci filtrace, jejíž vstupní parametry budou matice dat k filtraci (DATA) a rozměr průměrujícího čtvercového okna N. Nejdříve ošetřete, aby N bylo liché číslo. Pokud není, vypište varovnou hlášku (warning), přičtěte +1 a pokračujte ve vyhodnocení.
Filtraci proveďte takovým způsobem, že hodnota (i, j) ve filtrovaném obraze bude odpovídat průměru z hodnot DATA(iM:i + M, jM:j + M), kde M = (N– 1)/2. Ošetřete také okrajové oblasti, kde okno „přesahuje“ mimo obraz. Zde průměrujte z dostupných hodnot, které budou splňovat podmínku oblasti.
Pro filtraci využijte funkce mean ve for-cyklu (mean, for). Můžete také vyzkoušet konvoluci (conv).

Příklad 7

Napište funkci pro výpočet faktoriálu. Porovnejte časy výpočtů vaší funkce s implementovanou funkcí Matlabu factorial pro rostoucí hodnoty argumentů od 5 do 100. Porovnání opakujte 100krát a určete průměrnou dobu výpočtu pro jednotlivé argumenty. Výsledky zobrazte v přehledném grafu. K záznamu času vyzkoušejte různé funkce tic, toc, timeit nebo cputime.