Bu sayfadaki yazılar
Sayfanın metni
Sayfa 21
Faktöriyel de Alalım
Geçen sayı söz verdiğim gibi, örneklerle uğraşmaya devam ediyoruz. Bu sefer de faktöriyel alma işlemiyle uğraşalım azıcık. Çoğunuz biliyorsunuz faktöriyel alma işlemi bu şekilde tanımlanmıştır:
(k-2)x...x2x1
Ünlem işareti “faktöriyel” olarak okunur ve faktöriyel alma işlemini temsil eder. Örneğin “5 faktöriyel”i hesaplarsak:
değerini elde ederiz. Buradan sadece tam sayıların faktöriyelleri bulunabilmiş gibi görünüyor, ama matematikçiler 0 ile 1 arasındaki sayıların faktöriyelini hesaplamak için de bir polinom bulmuşlar. Bu sayede (mesela) 4.6'nın faktöriyelini rahatlıkla hesaplayabiliriz: Tabii ki ilk olarak 0.6'nın faktöriyelini hesaplayabilmeliyiz. Bunu (yeterince yaklaşmak için) 8. dereceden bir polinom olarak yazdığımızda şu katsayıları elde ederiz:
al — 1 al- -.577191652 a2- -,897056937 ad - ,918206B57 a5 - -,756704078 a6 — 482199394 -.193527818 a8 — 035868343
Program 2'ye bir göz atarsanız 0 ile 1 arasındaki sayıların faktöriyelini hesaplayan makine dili rutinini görebilirsiniz.
POLINOM — LDA #<KATSAYI LDY #>KATSAYI JMP POLİNOM
$E059
KATSAYI .BYT 8 .FLP .035868343 .FPL -.193527818 .FLP .482199394 .FLP -.756704078
.FLP .FLP
918206857 -.897056937 .FLP ,988206891 .FLP -.57719652 .FLP
Program-2: 0 ile 1 arasındaki sayıların faktöriyelini hesaplayan program.
USR fonksiyonunun 828'i göstermesini de sağladıktan sonra
PRINT USR(X) komutuyla X sayısının faktöriyelini görebilirsiniz. Örneğin:
- -
0.951350564 0.886227246
Ve tüm sayıların faktöriyelini hesaplamak istersek kısa bir BASIC program makine dili rutinimize eşlik edebilir. Program 3'de bu işi yapacak olan BASIC programını görebi- lirsiniz. Programda farkedeceğiniz gibi, USR(X) fonksiyonunu her türlü değer ata- malarında (Y— Yx USR(X) gibi) kullanabi- lirsiniz. 10 INPUT "ARGUMAN"; X 20 TF X<0 OR X>33 THEN 10 30 IF X-0 THEN Y-İ: GOTO 70 40 Y-X: IF X<1 THEN Y-USR(X): GOTO 70 50 X-X-1: TF X>1 THEN Y-Y*XŞ GOTO 50
60 IF THEN Y-Y*USR(X) 70 PRİNT "FAKTOÖRİYEL -"; Y
Program-3: Program-2'yi kullanarak, tüm sayıların faktöriyelinin alınmasını sağlayan BASIC programı.
BASIC programın 20. satırı, negatif ve 30'dan büyük sayıların faktöriyelini almaya çalışmamızı engelliyor. Faktöriyel işlemi, tanım olarak sadece sıfır ve üstü için geçerlidir. 30'un üstündeki sayıların faktöriyeli, bilgisayarınızın hesaplayabileceğinden (1E38) daha büyük bir sonuç vereceğinden, program hata verecektir. Sıfır faktöriyel 1 olarak tanımlandığından, 30. satırla bu kontrolü yapıyoruz. 50. satır ise programın beynini oluşturuyor. Sayı 0 ile bir arasında bir değere ulaşana kadar Y ile çarpılıp bir eksiltiliyor. Son olarak, sayının artan kısmı birden küçükse USR(X) ile Y'yi çarpıyoruz. Y'nin değeri 70. satırda ekrana yazılıyor. Programı birkaç örnek değer için çalıştırırsak:
0 - | - | 15 — 1.32934087 2 - 2 3 - 6 05 — ,886227246
7.35 = 102087.3151 Aslında tüm faktöriyel alma rutinini makine dili kullanarak yazabiliriz. Bunun için sadece deminki BASIC programının makine dili eşdeğerini yazmamız gerekecektir. Tablo 3'te bu makine dili programının akış şemasını görebilirsiniz. Kendinizi denemeniz için bu programı yazma kısmını size bırakıyorum. Eğer sonuçlarınızı bana yollarsanız, ben de sizin konuyu ne kadar takip edebilmiş olduğunuzu anlayabileceğim. İlk sayı sonra kaç arkadaşımızın bu programı yapabilmiş olduklarını ve genel hataların (çalıştıramayanlar da bana yazsın demek oluyor bu) neler olduğunu açıklayacağım. Tabii ki böyle bir şeyi yapmam için bana yazmanız gerekiyor. Nedense sizlerle bir iletişim ağı kurmayı pek başaramadım. Bu sebeple de konuları hâlâ körü körüne seçip “Umarım birilerinin işine yarıyordur” demek zorunda kalıyorum. Yanlış anlamayın, “Su Şişesi”yle rekabet gibi bir amacım yok, Yalnızca sizin burada anlatılanlardan ne kadar yararlanabildiğinizi anlamak istiyorum.
SON
SON
Neyse, bu ayki vaazımı da verdiğime göre yazıyı bitirebilirim. Gelecek ay garip garip konularda buluşmak üzere hoşça kalın.
Klavyeyle gezinmek için ← ve → tuşları.
Sayfa 20
100 Y - A(N) 110 FOR IT - N-1 130 NEXT Y
Tablo-2: n. dereceden polinomun belirli bir X için değerini hesaplayan program.
n(n+1)/2 çarpma ve n toplama gerektirirken, Horner metoduyla n çarpma ve n toplama yapmak yeterli olmaktadır. Bu işlemi yapacak bir program yazmanın ne kadar basit olduğunu Tablo 2'de yer alan programdan da görebilirsiniz. Bu program n. dereceden bir polinomun belirli bir x için alacağı değer hesaplar ve sonucu y'de bırakır. A(k) dizisi de a0'dan an'e kadar olan katsayıları tutar. Bu anlattığım teori, fonksiyonların çoğunun bilgisayarlar tarafından hesaplanabilmesini mümkün kılar. BASIC yorumlayıcısı da n. dereceden polinom hesaplayıcı bir rutin sayesinde SIN, COS gibi fonksiyonları hesaplayabilir.
Polinom Değeri Hesaplama
Demin bahsettiğim rutin $E059 adresinde yer alır ve şu değerleri ister: FAC: x'in değerini tutar. Y, A: polinom değer tablosu. A — düşük değerlikli, Y— yüksek değerlikli. Polinom değeri tablosu, şu şekilde hazırlanmış olmalıdır.
polinom derecesi n n. derecenin katsayı değeri (n-1). derecenin katsayı değeri
1. derecenin katsayı değeri 0. derecenin katsayı değeri
Buradaki polinom derecesi tek baytlık işaretsiz bir sayıdır. n. derecenin katsayısı dediğimiz şey de x^n'li terimin katsayısıdır. Bu katsayı değerleri hep 5'er baytlık kesirli sayılar olarak saklanırlar. Artık bu bilgilerimizden yararlanarak polinom değerlerini hesaplayan bir rutin yazabiliriz rahatlıkla. Normal bir Assembler ile çalışırken kesirli sayıların datalarını belleğe geçirmek zordur. En kötü ihtimalle, bir değişkene bu kesirli sayıyı atayıp, bir monitör programı aracılığıyla
Böylece bu değişkenin datalarını kağıda yazıp, .BYT a,b,c,d,e şeklinde girebiliriz. Ama ASSEMBLER/MONITOR:64 kesirli sayıları doğrudan doğruya kaynak (source) listesine eklemenize izin veriyor. Bu iş için de .FLP komutunu kullanıyoruz. Assembler her .FLP gördüğü yerden sonra gelen sayıları otomatik olarak beşer baytlık kesirli sayı datasına çeviriyor. Neyse, sözü fazla uzatmadan bilgilerimizi ortaya koyalım ve şu polinomun lim:
Program 1'e bakarsanız bu hesabı yapan makine dili programını görebilirsiniz.
*-828 ;$033C, yani
kaset buffer POLINOM - $E059 LDA #<KATSAYI LDY #>KATSAYI JMP POLINOM 3 KATSAYI .BYT 4 .FLP 0.5 3A(4) .FPL -2.3 şA(3) .FLP 8.2 .FLP 2.5 şA(1) .FLP 0.7 şA(0)
) Program-1: Basit bir polinomun değerini hesaplayan program.
Rutinin tek yaptığı iş, katsayı adresini polinom hesaplayan ROM rutinine iletmek.
USR( ) Fonksiyonu
Peki bu POL(x) fonksiyonunu nasıl kullanacağız? SYS komutunu kullanmamız olanaksız. X değerini rutine nasıl ileteceğiz ki? Bize gereken, SIN( ), COS( ) gibi bir fonksiyon. Neyse ki BASIC yorumlayıcısı bunu da düşünmüş. Her türlü amaca hizmet etmek için USR( ) (USeR defined: kullanıcı tarafından tanımlanmış) adlı bir fonksiyon yaratmışlar. Bu fonksiyonu istediğiniz gibi tanımlayabilirsiniz. Sadece yorumlayıcıya fonksiyonun yerini bildirmemiz gerekli. Bu fonksiyonun yerini, her zaman yaptığımız gibi düşük-yüksek değerlikli bayt formatında 785/786 ($0311/$0312) adreslerine yerleştirmeliyiz:
POKE 785,828AND255:POKET86,828/256
Artık POL( ) fonksiyonumuz tanımlanmıştır. Şu komutu girerek bir test yapalım:
PRINT USR(1)
Sonuç olarak 9.6'yı ekranda görebilirsiniz. Bakalım doğru olmuş mu:
y=0.742.548.2-2.34
Daha fazla kontrolle uğraşmak isterseniz bir de şu döngüyü kurun:
FOR 1--5 TO 5:PRINT USR():NEXT
193.2 397.1 169.6 54,9 9.6 28.1 60.4 122.7 243.2
Eğer bir BASIC programında polinomlarla uğraşacaksanız ve aynı polinomu sık sık kullanıyorsanız, bu metod size kesin bir üstünlük sağlayacaktır. Tek başına kullanılsaydı 12.5 ms süren bu rutin çoğu BASIC fonksiyonundan hızlı çalışmaktadır. USR( ) fonksiyonunun yediği zamanı da hesaba katarsak 50 ms'ye çıkan bu süre gene de çok iyidir (isterseniz BASIC programla aynı işlemi yapmayı deneyin bakalım). Polinom derecesi arttıkça ve formül karmaşıklaştıkça rutin biraz daha yavaşlayacak, fakat hiçbir zaman BASIC'in o akıllara durgunluk veren yavaşlığına düşmeyecektir. Program 1'deki örnekte de iyice pekiştirdiğimiz gibi, katsayılar x'in en yüksek üslü değerinden başlar ve x olmayan terime doğru gider. Eğer bu sırayı doğru vermezseniz doğru sonuç alamazsınız. x=1'de yaptığınız kontrol de bu hatayı ortaya çıkarmaz. En iyisi x=1 ve x=0 vererek polinomları kontrol etmektir. Eklemem gereken bir şey daha var: Eğer herhangi bir terim formülde yoksa (y=1+4x gibi) bu terimin katsayısını sıfır alarak listeye eklemelisiniz.