Forum: Ders Arası RSS
Diziler Problem-1
Sayfa:  1  2  sonraki 
Kadir Can #1
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Diziler Problem-1
import std.cstream;
 
void main()
{
    dout.writefln("How many number do you need?");
    int number;
    int counter=0;
    din.readf(&number);
    real[ ] numbers;
    while(counter<number){
        dout.writefln("Enter the number, please!");
        din.readf(&numbers[counter]);
        counter++;
    }
    counter=0;
    numbers.sort;
    while(counter<number){
        dout.writefln(numbers[counter]);
        counter++;
    }
    counter=0;
    numbers.reverse;
    while(counter<number){
        dout.writefln(numbers[counter]);
        counter++;
    }
}
Arkadaşlar bu kodu yazdım.Çalıştırıyorum(Komut isteminden.).Kaç sayı gireceğimi yazıyorum.Sonra şöyle bir hata alıyorum ve program çöküyor.
core.exception.RangeError@arrays(12) Range violation
Ne yapabilirim?
canalpay (Moderatör) #2
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
import std.cstream;
 
void main()
{
    dout.writefln("How many number do you need?");
    int number;
    int counter=0;
    din.readf(&number);
    real[] numbers;
    numbers.length=number; ///Burayı ekledim.
    while(counter<number){
        dout.writefln("Enter the number, please!");
        din.readf(&numbers[counter]);
        counter++;
    }
    counter=0;
    numbers.sort;
    while(counter<number){
        dout.writefln(numbers[counter]);
        counter++;
    }
    counter=0;
    numbers.reverse;
    while(counter<number){
        dout.writefln(numbers[counter]);
        counter++;
    }
}
canalpay (Moderatör) #3
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Nedenini şöyle açıklayayım:

Dinamik diziler eleman sayısı çalıştırma sırasında değiştirilebilen dizilerdir. Ancak ilk tanımlandığında kaç tane elemanı olacağını söyleyemediğimiz için başlangıçta sıfır tane elemanı var. Sizin yazdığınız şu kodda:
        din.readf(&numbers[counter]); //counter değeri 0. Yani ilk elemana erişmeye çalışıyor. 
kodda sıfır uzunluktaki bir dizinin ilk elemanına erişmeye çalışıyor. Dizide ilk eleman olmadığı için çalışma anında hata veriyor ve hata mesajında şu oluyor :
core.exception.RangeError@arrays(12) Range violation

Bu da aralık ihlali demek. Yani program aman abi bende bilmemkaçtane eleman var sen bilmemkaçtane+1.elemana erişmeye çalışıyorsun. O eleman yok ki. Bak aralıkları ihlal ediyorsun diye hata veriyor.

Parantez içindeki sayıda hata hangi satırda onu gösteriyor.
Kadir Can #4
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #2
Teşekkürler.
canalpay (Moderatör) #5
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Önemli değil. Sanırım pek açıklayıcı yazamamışım. İstersen en baştan yazayım yada anlayamadığın yer varsa orayı anlatayım.
Kadir Can #6
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Teşekkürler,anladım.Zaten sorunun cevabını incelediğimde o satırı gördüm.Mantık hatası yapmışım.Tekrar anlatmanıza gerek yok.Tekrar teşekkürler.
canalpay (Moderatör) #7
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Tamam. Bu arada o kodu şu şekilde de yazabilirdik:

import std.cstream;
 
void main()
{
    dout.writefln("How many number do you need?");
    int number;
    int counter=0;
    din.readf(&number);
    real[] numbers;
    int copy;
    while(counter<number){
        dout.writefln("Enter the number, please!");
        din.readf(&copy);
        numbers~=copy;
        counter++;
    }
    counter=0;
    numbers.sort;
    while(counter<number){
        dout.writefln(numbers[counter]);
        counter++;
    }
    counter=0;
    numbers.reverse;
    while(counter<number){
        dout.writefln(numbers[counter]);
        counter++;
    }
}

Oradaki numbers~=copy; kodu derleyici arka planda şu şekilde derler: (Ali Bey demişti :-) )

numbers.length=numbers.length+1;
numbers[numbers.length-1] = copy;

Tabi her ~= kodu her defasında bellekte yeni alan açmak için uğraşacağı için daha yavaş çalışır. Eğer dizinin uzunluğu bu örnekteki gibi belirli ise ~= şeklinde yazmak daha çok yavaşlatır. Gerek yoktur.
acehreli (Moderatör) #8
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
canalpay:
numbers.length=numbers.length+1;
numbers[numbers.length-1] = copy;

Tabi her ~= kodu her defasında bellekte yeni alan açmak için uğraşacağı için daha yavaş çalışır. Eğer dizinin uzunluğu bu örnekteki gibi belirli ise ~= şeklinde yazmak daha çok yavaşlatır. Gerek yoktur.

Daha yavaş olduğu doğru. Ama bu yavaşlık amortized constant denen türdendir. Dizinin uzunluğu ne kadar büyükse, bu şekilde yeni yer ayırmaların etkisi gittikçe küçülür.

Çünkü dizi perde arkasında 1 adet değil, akıllıca hep o andaki uzunluğunun belirli bir oranı kadar yer ayırır. Örneğin %50'si kadar ayırı... Dizi ne kadar büyümüşse, o büyüklüğün yarısı kadar eleman için tek yer ayrılır.

Böylece eleman sayısı başına yer ayırma (ve gereken kopyalanmaların) adedi çok küçüktür.

Evet ~= daha yavaştır ama bu yavaşlık algoritma karmaşıklığı kadar etkili değildir.

Ali
canalpay (Moderatör) #9
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Çünkü dizi perde arkasında 1 adet değil, akıllıca hep o andaki uzunluğunun belirli bir oranı kadar yer ayırır. Örneğin %50'si kadar ayırı... Dizi ne kadar büyümüşse, o büyüklüğün yarısı kadar eleman için tek yer ayrılır.

Ben hatırladığım kadarıyla D böyle bir şey yapmıyor. Hep bir fazlası kadar yer ayırıyor. Daha fazlası değil. Sizde bunu söylemiştiniz. Sanırım bu kod parçasında iki tane aynı değeri ekrana yazdırırsa benim dediğim doğru oluyordur ? :

import std.cstream;
import std.random;
void main()
{
    dout.writefln("How many number do you need?");
    int counter=0;
 
    real[] numbers;
    int copy;
    int a = uniform(2000,200000);
    for(int b=0;a>b;b++) {
        numbers~=b;
        counter++;
        
 
    }
 
        dout.writefln(a);
        dout.writefln(numbers.length);
  
}
acehreli (Moderatör) #10
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
canalpay:
Hep bir fazlası kadar yer ayırıyor

Karışık yazmışım. :) Eleman sayısı ile kapasite farklı kavramlar.

Evet, dizinin eleman sayısı hep bir artıyor; ama perde arkasında, ileride olabilecek eklemeler için bir kapasite de bulunuyor. Yani gerekenden fazla bellek ayrılmış, sonraki eklemeler için bekliyor.

Bunu bir programla deneyebiliriz ... diyecektim ki, std.array modülünde zaten capacity işlevi varmış. :)

import std.stdio;
import std.array;
 
void bilgiVer(int[] dizi)
{
    writeln("uzunluk: ", dizi.length, " kapasite: ", dizi.capacity);
}
 
void main()
{
    int[] dizi;
 
    foreach (i; 0 .. 100) {
        dizi.bilgiVer();
        dizi ~= i;
    }
}

Ek not: Eğer ilk parametresi dizi olan bir işlev yazarsanız, o işlevi sanki dizi üyesi gibi kullanabilirsiniz. Yukarıdaki dizi.capacity ve dizi.bilgiVer() yazımları o kurala uygun olarak çalışıyor.

Çıktısı şöyle:

uzunluk: 0 kapasite: 0
uzunluk: 1 kapasite: 3
uzunluk: 2 kapasite: 3
uzunluk: 3 kapasite: 3
uzunluk: 4 kapasite: 7
uzunluk: 5 kapasite: 7
uzunluk: 6 kapasite: 7
uzunluk: 7 kapasite: 7
uzunluk: 8 kapasite: 15
uzunluk: 9 kapasite: 15
uzunluk: 10 kapasite: 15
uzunluk: 11 kapasite: 15
uzunluk: 12 kapasite: 15
uzunluk: 13 kapasite: 15
...

Kapasitenin her arttığı nokta, bellekten yeni bellek ayrıldığını gösteriyor. Örneğin 3'ten 4'e geçerken 7 elemanlık yer ayrılmış.

Başka bir gözlem, dmd yer ayırırken %50 arttırmıyor ve şu formülü kullanıyor: İlk ayırdığında 3, ama sonra (dizi.length * 2) + 1

Ali
canalpay (Moderatör) #11
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Evet çok akıllıymış. Ayrıca hep (dizi.length * 2) + 1 formülünü uygulamıyor. Yoksa zaten ileride gereksiz bellek
hatasına  yada bellek kullanımına yol açardı herhalde. Derleyici gerçekten mantıklı.


import std.stdio;
import std.array;
 
void bilgiVer(int[] dizi)
{
    writeln("uzunluk: ", dizi.length, " kapasite: ", dizi.capacity);
}
 
void main()
{
    int[] dizi;
 
    foreach (i; 0 .. 3153919) {
        if (i>3153917-10)
        dizi.bilgiVer();
        dizi ~= i;
    }
}
acehreli (Moderatör) #12
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Haklısın. Ben de yalnızca kapasitenin değiştiği noktalara bakmaya karar verdim:

import std.stdio;
import std.array;
 
int belkiBilgiVer(int[] dizi, int eskiKapasite)
{
    if (dizi.capacity > eskiKapasite) {
        writeln("uzunluk: ", dizi.length,
                " kapasite: ", dizi.capacity,
                " oran: ", cast(double)dizi.capacity / eskiKapasite);
    }
 
    return dizi.capacity;
}
 
void main()
{
    int[] dizi;
    int eskiKapasite = int.min;
 
    foreach (i; 0 .. 3_153_919) {
        eskiKapasite = dizi.belkiBilgiVer(eskiKapasite);
        dizi ~= i;
    }
}

Kapasite artma oranı gittikçe düşüyor; ama aralarda ani zıplamalar da var:

uzunluk: 1 kapasite: 3 oran: inf
uzunluk: 4 kapasite: 7 oran: 2.33333
uzunluk: 8 kapasite: 15 oran: 2.14286
uzunluk: 16 kapasite: 31 oran: 2.06667
uzunluk: 32 kapasite: 63 oran: 2.03226
uzunluk: 64 kapasite: 127 oran: 2.01587
uzunluk: 128 kapasite: 255 oran: 2.00787
uzunluk: 256 kapasite: 509 oran: 1.99608
uzunluk: 512 kapasite: 1021 oran: 2.00589
uzunluk: 1022 kapasite: 2045 oran: 2.00294
uzunluk: 2046 kapasite: 3069 oran: 1.50073
uzunluk: 3070 kapasite: 4093 oran: 1.33366
uzunluk: 4094 kapasite: 5117 oran: 1.25018
uzunluk: 5118 kapasite: 6141 oran: 1.20012
uzunluk: 6142 kapasite: 7165 oran: 1.16675
uzunluk: 7166 kapasite: 8189 oran: 1.14292
uzunluk: 8190 kapasite: 9213 oran: 1.12505
uzunluk: 9214 kapasite: 10237 oran: 1.11115
uzunluk: 10238 kapasite: 11261 oran: 1.10003
uzunluk: 11262 kapasite: 12285 oran: 1.09093
uzunluk: 12286 kapasite: 13309 oran: 1.08335
uzunluk: 13310 kapasite: 14333 oran: 1.07694
...
uzunluk: 1154046 kapasite: 1155069 oran: 1.00089
uzunluk: 1155070 kapasite: 3153917 oran: 2.7305         <-- burada
uzunluk: 3153918 kapasite: 3154941 oran: 1.00032
...
uzunluk: 4742142 kapasite: 4743165 oran: 1.00022
uzunluk: 4743166 kapasite: 12333053 oran: 2.60017       <-- burada
uzunluk: 12333054 kapasite: 12334077 oran: 1.00008
...
(başka da var)

Garip... :)

dmd bu işi sanki src/dmd/root/array.c dosyasındaki Array::reserve() işlevinde yapıyor ama orada böyle zıplamalı bir hesap görmüyorum.

Ali
acehreli (Moderatör) #13
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Böyle sohbetler çok yararlı oluyor. Kadir Can'ın sorusu dmd'nin bir hatasını ortaya çıkartmış oldu.

Şu 'bug report'u açtım:

  http://d.puremagic.com/issues/show_bug.cgi?id=4412

Ali
Kadir Can #14
Üye Haz 2010 tarihinden beri · 413 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Faydalı olabildiysem gerçekten mutlu olurum.Peki neden?

Çünkü bu D dili yeni bir dil.Haliyle içinde bug denen hatalar vardır ve bu hataların erken farkedilmesi önemlidir.

Ayrıca burda sayın Ali Bey dersler ne kadar öncelerde fazla ilgi görmedilerse de ders yazmaya devam etti.Özellikle Ali Bey'e teşekkür ederim.Ve tabi ki canalpay'ı da unutmamak gerekir.
canalpay (Moderatör) #15
Kullanıcı başlığı: Can Alpay Çiftçi
Üye Tem 2009 tarihinden beri · 1133 mesaj · Konum: İzmir
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Ve tabi ki canalpay'ı da unutmamak gerekir.
Teşekkürler.

Ali Bey zaten bir sürü bug buldu. Herhalde bug bulmaya çok uğraşsa en çok bug bulan kişi ünvanı alır :-) (Bir gün bende bug bulacağım :-D )

Ama bulunan bu son bug pek önemli değil bence. Bazı durumlarda programın daha hızlı çalışmasını bile sağlayabilir :-D Ancak derleyici yazılırken böyle olunması düşünülmediği için bug kapsamındadır herhalde.
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Sayfa:  1  2  sonraki 
Forum: Ders Arası RSS
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-18, 00:34:43 (UTC -08:00)