Kalıcı değişkenler
MATLAB'de kalıcı değişken tanımlarken kullanabileceğiniz bir anahtar sözcük var: persistent
. Yaratılan değişkenin siz fonksiyondan çıksanız bile hafızada korunmasını sağlıyor. C'deki static
anahtar sözcüğü gibi düşünebilirsiniz. Örneğin bir koşan ortalama (running averager) fonksiyonu yazalım:
function ortalama = kosanOrtalama(x) persistent n; persistent toplam; if x == 'sifirla' % Kalıcı değişkenleri ilklendir n = 0; toplam = 0; ortalama = 0; else % Yeni veri geldi n = n + 1; toplam = toplam + x; ortalama = toplam / n; % Ortalamayı güncelle. end
Üstteki fonksiyonda n
ve toplam
değişkenlerini kalıcı olarak yarattık. Fonksiyonu 'sifirla'
parametresi ile çağırdığımızda değerleri ilklendirecek. Eğer sayı verirsek ise o sayıyı kullanarak ortalamayı güncelleyecek.
kosanOrtalama('sifirla') ans = 0 >> kosanOrtalama(10) ans = 10 >> kosanOrtalama(5) ans = 7.5000
Şu sıralar yazdığım kodda veri üstünde bir model için olabilirlik değeri hesaplıyorum ve bunu yeni veriler geldikçe veya döngüde ilerlerken güncelleyerek yapıyorum. Bu durumda güncellediğim değerleri fonksiyondan alıp sonra yine vermek yerine persistent
ile kalıcı yaratmak işimi bir hayli hızlandırdı.
Bilgisayarla görüde popüler olan aktif görü (active vision) alanı da bu biçimde değişkenler için biçilmiş kaftan. Çünkü orada da yeni veri geldikçe güncellenen sonuçlar mevcut.
Kaynak: CITS1005 dersi
Güncelleme: Barış'ın katkılarıyla kodun daha anlaşılır ve hızlı çalışan sürümü şöyle:
function ortalama = kosanOrtalama(x) persistent n; persistent toplam; if isempty(n) n = 0; toplam = 0; end n = n + 1; toplam = toplam + x; ortalama = toplam / n; % Ortalamayi güncelle. end
Sıfırlamak için de clear kosanOrtalama;
yazmak gerekiyor.
2 yorum
Bu persistent cok kuvvetli bir arac, nedense birsuru kisi farkinda degil. Insanlarin farkina varmasi yonunde guzel bir adim olmus sagolasin :) Gerci MATLAB kullanan cogu insan MATLAB hakkinda birsuru seyin farkinda degil :) Genelde bu tip problemleri cozmek icin insanlarin ilk aklina gelen `global` kullanmak. Global kullanmanin neden kotu oldugunu ogrenmeyi meraklilara birakiyorum.
Soyle olsa daha iyi olur diyecegim bir kac husus var.
Bu hususlardan en onemsiz gordugum heralde `x == 'sifirla'` ifadesi. `==` ile string karsilastirmasi yapmak pek verimli degil. strcmp() kullanmak daha hizli islem, cunku strcmp() stringin uzunlugu, degiskenin tipleri gibi baska parametreleri test edip erkenden sonuc donebiliyor. Genelde persistent kullanan fonksiyonlar defalarca cagirilmak uzere yazildiklari icin, boylesi bir fonksiyonun icerisinde strcmp() kullanmak daha faydali olacaktir. Yoksa `==` operatoru kullanmak bence daha okunabilir, cok cagirilmayacak yerlerde `==` kullanilabilir.
Ufak bi test yaptim bir strcmp() kullanarak bir de `==` kullanarak kodu 100000 kere kosturdum, sirasiyla sonuclar 1 ve 1.25 sn idi. %25 artis bana fazla gorundu.
Bir diger mevzu ise if-else kullanimi. if-else kullanmak kodu anlamayi guclestiriyor. if kullanmadan kod yazmayi savunanlardanim. Ilk bakista sacma gorunse de if kullanimindan kacinmaya calisinca anliyorsunuz ki gercekten kafanizi ve kodunuzu karistiran birsey bu if. Hic kullanmayin demiyorum, kullanin ama hobi olarak kullanin :P Burada if kullanimindan niye kacinmanin gerektigi ve nasil guzel koda, guzel mimariye sevkettigine dair guzel bir video var: http://goo.gl/cebgO
Simdi madem birseyi elestiriyorum yerine yenisini koyayim. persistent degisikenleri ilklendirmenin en kabul gormus ve yaygin yolu:
if isempty(x)
x = 0;
end
seklinde. Ortak kabul gormus kullanimlari kullanmak da isi kolaylastirir, zaten cogulukla kabul gormelerinin nedeni bircok acidan iyi olmalaridir, ve zamanla sinanmislardir. Fonksiyonu su bicime donusturelim:
function ortalama = kosanOrtalama(x)
persistent n;
persistent toplam;
if isempty(n)
n = 0;
toplam = 0;
end
n = n + 1;
toplam = toplam + x;
ortalama = toplam / n; % Ortalamayi güncelle.
end
bence bu hali oncekinden guzel oldu. Peki ya kodumuzun icerisinde tekrar sifirdan kosan ortalama hesaplamamiz gerekecekse, yani fonksiyonun durumunu sifirlamamiz gerekecekse? Cozum basit:
clear kosanOrtalama;
ifadesi fonksiyona ait tum bilgileri siliyor.
Aslinda biraz kararsiz oldugum bi mevzu daha var, MATLAB'in kod indentasyonunu sevmiyorum. Bakinca hangi fonksiyon nerede basliyor nerede bitiyor belli olmuyor, okumayi zorlastiriyor. O yuzden fonksiyonlarin `end` ile bitirlip, kodun icinin bir adim iceri sokulmasindan yanayim. `end` ile bitirmek su an hatirlayamadigim baska bir hatayi da onluyor.
Tahmin ettigimden de uzun yorum oldu, belki konuk yazar olarak agirlanmaliydim. Hem degisik trip olurdu.
@Barış:
strcmp
kullanacaktım (MATLAB öneriyor zaten böyle kullanmayın, yavaş olur diye) amapersistent
'a odaklanınca öyle kaldı. Şimdi çok iyi oldu, eline sağlık! Şu girintileme işi de gözümden kaçmış. Ben de fonksiyon sonlarınaend
koyuyorum artık ve kodları hep girintileyerek yazıyorum normalde. Bu örneği, kalıcı değişkenleri anlatmak için bulmuştum. Güncelledik, şahane oldu. Tekrardan eline sağlık!