Biraz da bilim yapalım : C# vs Fortran?

Sene 2002…

Mersenne asal sayılarına merak salmıştım. Çok hırslıyım…

Kısaca Mersenne asal sayısını açıkayayım…Asal bir p sayısı için (2^p – 1) sayısı da asal olacak şekilde ifade edilebilen asal sayılara Mersenne asal sayıları denir.

Bir Mersenne asal sayısını bulmak çok zor elbette…An itibariyle bilinen en büyük Mersenne asal sayısı için p asal sayısı 43,112,609. Bu sayıyı bulmak zor değil, asal olduğunu kanıtlamak ta zor değil. İşin güç kısmı (2^p – 1) şeklinde ortaya çıkan rakamın asal olup olmadığını ispatlamak. Mesela,

p = 43,112,609 (bilinen en büyük Mersenne asal sayısı için p sayısı) için,

(2^p – 1)  sayısı 12,978,189 basamaklı…

Neyse…Buradaki asıl konumuz Mersenne asal sayılarını hesaplamak değil. Zaten zamanında Fortan ile yazdığım bir program ile ben de bir Mersenne asal sayısı bulmayı ümit ediyordum ama olmamıştı 🙂

Bilgisayarda 2^p şeklide sayıları hesaplamak başlı başına bir iş (en azından ben basit ve etkili yeni bir yol bulamadım). Güç olan ortaya çıkan rakamı bir değişken ile ifade etmenin mümkün olmaması, zira çoğu programlama dili için ifade edilebilen en büyük veri tipleri olan int64 ve long veri tipleri 8 byte yani 64 bit uzunluğunda. Bunun 1 biti işaret için (negatif, pozitif) kullanıldığından dolayı ifade edilebilen en büyük sayı ise,

(2^63 – 1) = 9,223,372,036,854,775,807

oluyor…Hepi topu 19 basamaklı bir sayı…Ama…

2^1000000 (2 üzeri 1 milyon) =

9900656229295898250697923616301903250733624241787567332866396114531
7094833094861030546145512346483914824315070345837238835106589894163
1492742256503157290537231486937723287177549471366423897012584291448
9614716338412188631103792398056007740136270960553070538667179812336
0615921792798327322364303228626065743092569162785820428347720017944
9319005699514097510312526917394308961549314037842917671378079314795
3357424131614194925264632270461031051872671543446326415534732828328
8444762629663913610121194240251006134317165249494592327571772207810
95411635556324285623401399844018872126340393003478382714500
……………………………………………………………………………………………..
……………………………………………………………………………………………..
……………………………………………………………………………………………..
……………………………………………………………………………………………..
……………………………………………………………………………………………..
……………………………………………………………………………………………..
……………………………………………………………………………………………..
………………………………………………………………………………………..
7024935116946829211711138525637113765334871120226768794624446000419
3285578325161724108564501100103657819320446625631458037513586617595
8334510775841705204022698031471290583891295636747619296417826487441
6728558185416641201613362645962693286352259142851442293758641634293
4310148722902497650983290675368921524145707929362596423749143931702
0877311008625357775069148569092075651782488478598420407064596334261
8474625881707313109960216577067715100810998335115465958457461967836
7983172072707268320759175710042820919242022887266774905230187123610
4888403162747109376

Sayının tamamı için burayı tıklayın (2 üzeri 1 milyon – 1)

Toplam 301030 basamaklı bir sayı…Böyle bir sayıyı nasıl bir veri türü ile ifade etmek gerekir? Mevcut veri tipleri ile bu mümkün değil…

Ben de o zamanlar (2002’li yıllarda) Fortran ile çok büyük sayıları ifade etmek için dizileri(array) kullanmıştım. Fortan o zamanlar dinamik dizileri destekliyordu (hala destekliyor, benimki de laf işte). Ve yazdığım program da gayet güzel sonuçlar veriyordu ancak çok yavaştı 🙂 Programın temeli şuna dayanıyor: sayının herbir basamağını dizinin elemanları olarak atıyordum, dolasıyla çok büyük rakamları hesaplamak için küçük rakamları kullanma fırsatım oluyordu. Örnek olarak,

2 üzeri 10’u hesaplamak istiyorsam eğer,

dizinin ilk elemanına 2 sayısını atıyordum ve bu sayıyı 9 defa (dizinin ilk elamanı 2 olduğu için 2^1’i -2 üzeri 1- hesaplamış oluyoruz zaten) 2 ile çarpıyordum. Her çarpma işlemi sırasında elde olursa, bu elde bir sonraki basamağa aktarılıyordu (bir sonraki basamak yoksa oluşturuluyordu, böylece sayının basamakları otomatik olarak arttırılıyordu)

Efendim geçenlerde bu programı C# ile yazayım dedim.

Ve evet yazdım 🙂

Daha sonra da aynı temele dayanan (diziler) bu programları -Fortan, C# versiyonları- hız olarak kıyaslamak istedim. C# ile yazdığım programı iki metot kullanacak şekilde yazdım. İlk metot Array kullanarak sayının hesaplanması, ikincisi ise IList<int> arayüzünün kullanılarak sayının hesaplanması…Yukarıdaki ekran görüntüsünde de görünüyor seçenekler zaten…

Karşılaştırma için verileri tek tek hesapladım ve sonuçları grafik olarak karşılaştırdım. Sonuçlar da aşağıda,

Grafik 1. Normal

Grafik 2. Logaritmik

Bu grafikler 2^p sayısını hesaplamak için programın harcadığı süreleri gösteriyor.  Yatay eksen p sayısını, dikey eksen ise saniye olarak geçen süreyi gösteriyor.

Herbir p sayısı için geçen süreleri 3 defa hesapladım ve 3 sonucun ortalamasını aldım. Hesaplamaların yapıldığı bilgisayarın donanım ve yazılım konfigurasyonu ise şöyle,

Windows Server 2008 Enterprise (32 bit)

Intel Core 2 CPU T5500 1.66 Ghz

4 GB RAM

C#’ta kullanılan IList<>’i IList1 olarak işaretledim çünkü IList<>’in iki farklı türünü kullanmayı planlıyordum (dolayısıyla diğerini de IList2 olarak işaretleyecektim). Burada kullanılan, generic kullanılarak oluşturulan IList<>, yani IList<int>. Kullanmayı planladığım diğer tür ise IList arayüzünden miras alınarak ve bir takım metotları override edilerek ve object veri türlerinin int olarak cast edilmesi sonucu oluşan sınıftı. Böylece casting işleminin ne kadar masraflı olup olmadığını öğrenebilecektim ama zamanım olmadığı için bu metodu implement edemedim. İlerde hem bu metodu implement edeceğim hem de bu karşılaştırmaya Java programlama dili ile yazılmış olan uygulamayı da ekleyeceğim.

Sonuçlar ortada,

C#’ta Array kullanımı IList<int> kullanımından daha az maliyetli…En azından hız açısından iyi sonuçlar veriyor…

Fortran’a gelince…

Evet hala çok hızlı…Matematiksel işlemlerde hala çok güçlü…Çok büyük sayılarda hız farkı daha net ortaya çıkıyor zaten…

And the Oscar goes to…….FORTRAN!

and…

FORTRAN WINS!

, , , ,

One Response to Biraz da bilim yapalım : C# vs Fortran?

  1. @bütün 18 Ağustos 2010 at 11:08 PM #

    thanks…

Bir cevap yazın

Font Resize