Thread overview
Dizi değerleri neden bozuk?
Apr 28, 2011
erdem
Apr 28, 2011
erdem
Apr 28, 2011
erdem
Apr 28, 2011
erdem
April 28, 2011

Hımm. Programı çalıştırmadan ve cevaba bakmadan rastgele fikirler..

import std.stdio, std.random;

void main () {
   double[5] dizi;

   foreach(ref eleman; dizi) {
       eleman = uniform(5, 15);
   }

   foreach(i; 0 .. dizi.length) {
       writeln(dizi[i]);
   }
}

Örneğin bu program çalışıyor. Burada foreach ile ilgili bir hata yok sanırım. Çünkü dershanede bu şekilde örnekler vardı.

   foreach (sayaç, eleman; dizi) {
       writeln(sayaç, ": ", eleman);
   }

Sabit genişlikli bir diziyi bir işleve parametre olarak geçtiğimizde ya da döndürdüğümüzde tüm elemanlar kopyalanıyordu. Ama böyle bir durum da gözükmüyor.

'i''nin ilklendirme değeri ne olabilir. Eğer sayaç olarak kullanılacaksa arttırılması gerekmez mi. Ben 'i''yi hataya yakın buluyorum. Ve ilklendirme değeri geçersiz bir değerse hatalı sonuç elde edebiliriz diye düşünüyorum.

Birazdan programı çalıştırıp deneyeceğim merak etmeye başladım! :-D

Programı çalıştırdıktan sonra 'i 've 'eleman''ın türleri farklı. Birisi 'double' birisi 'int'.

Programı şu şekilde düzelttikten sonra çalışıyor:

import std.stdio;

void main()
{
   double[5] dizi;
   int ortaDeğer = 3;

   foreach (int i, ref eleman; dizi) {
       eleman = cast(double) (i - ortaDeğer);

   }

   writeln(dizi);
}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 28, 2011

yanıta bakmadan ve bilmeden serbest atış yapıyorum.
Tahmin:

eleman dizi[indis] demek. uint değerinde indis. indis - olunca eksi değer alamadığından en yüksek değerden başlıyor.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 28, 2011
import std.stdio;

void main()
{
   double[5] dizi;

   int ortaDeğer = 3;

   foreach(int i; 0 .. dizi.length) {
       dizi[i] = i - ortaDeğer;
   }

   writeln(dizi);
}

Bu programda da belli oluyor. Orada 'i''nin başına 'int' koymayınca hemen hemen aynı sonucu veriyor :)

Ama ben yazsam böyle yazardım herhalde.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 28, 2011

Bir de Can'ın da bahsettiği gibi eğer 'uint' işaretsiz bir değer kullanırsak. Örneğin yukarıdaki 'ortadeğer' ve 'i''yi işaretsiz olarak tanımlarsak bir taşma olduğu için 'cast(double)' ile de kurtaramıyoruz :)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 28, 2011

Alıntı:

>

Bir de Can'ın da bahsettiği gibi eğer uint işaretsiz bir değer kullanırsak. Örneğin yukarıdaki ortadeğer ve i'yi işaretsiz olarak tanımlarsak bir taşma olduğu için cast(double) ile de kurtaramıyoruz

Ben sadece nedeni açıkladım. Çözümü söylemedim. uint türünde olduğu için hata olduğuhnu söyledim.

söylediklerimi daha ayrıntılı yazarsam:

Ben dizinin aralık(daha doğrusu indis) olarak uint aldığını uint ile - gibi işaretin gerekli olduğu bir işlem yapıldığı için hata olduğunu söyledim. foreach doğal olarak indisin değerinde değişken tutuyor ve hata oluşuyor dedim. Aslında hata denmesininde doğru olmadığını çünkü işaretsiz türlerin doğal davranışının değişkene sığmadığında değişken.max tan tekrar başladığını söyledim.

Önceden değişken türleri ile sık sık hata yaptığım için artık böyle sorunları koda bakar bakmaz görüyorum :-)

Soruda kodun doğru çalışması için ne yapılmasını sormadığı için nasıl yapılacağını söylemedim(Yarın sınavım var koda hiç bir işlem yapmadım. Derlediğimde zaten her şey belli idi. - değer değişkene sığmamış. uint.max yazdırılmış. Yeterince ip ucu vardı :-P ).

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 28, 2011

Sadece daha açık görülsün diye yazdım. Burada değer eksi bir sayı alınca (işaretsiz sayıların sadece pozitif değerler tutabileceğini biliyoruz) sanırım taşma oluyor ve geçersiz bir değer 'başkabirSayı''ya atanıyor.

   uint ortaDeğer = 3;

   uint başkabirDeğer;

   double başkabirSayi = başkabirDeğer - ortaDeğer;

   writeln(başkabirSayi);

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 28, 2011

Evet bende aynı şeyi demek istemiştim taşma sözcüğü aklıma gelmedi. Sağol.
Alıntı (erdem):

>

işaretsiz olarak tanımlarsak bir taşma olduğu için cast(double) ile de kurtaramıyoruz

Ayrıca bende açıkça görülsün diye yazıyorum yoksa dediklerimin bilindiğini biliyorum.

Eğer işlem yaptığımız sayının mutlak değeri, değişkenin alabileceği değer aralığından(Dikkat: değişken maksimum değeri demedim!) fazla değilse ve kullandığımız değişkenlerin türünü(daha doğrusu aralığını) biliyor isek taşmaları kurtarabiliriz.

Örn:

void main()
{
   uint değer = -3;

   writeln(değer);

   int ideğer=değer;

   writeln(ideğer);


}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 28, 2011

Bu sorun D.learn forumunda gösterildi. Aşağıdaki soruyu oradan uyarladım.

Aşağıdaki program dizinin 5 elemanına değerler atıyor. foreach'in sayaç olanağından yararlanıldığı için i 0'dan 4'e kadar değerler alır. Sonuçta elemanların şöyle olmaları bekleniyor:

'[ -3, -2, -1, 0, 1 ]'

import std.stdio;

void main()
{
   double[5] dizi;

   int ortaDeğer = 3;

   foreach (i, ref eleman; dizi) {
       eleman = i - ortaDeğer;
   }

   writeln(dizi);
}

Ama eleman değerleri öyle olmuyor. Neden?

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

April 28, 2011

Evet, sorun foreach sayacının size_t türünde olması. Ortamına göre değişebiliyor: 32 bit ortamda uint, 64 bit ortamda ulong. Ama sorun bit sayısında değil, sayacın işaretsiz (unsigned) bir tür olmasında.

C'den gelen kurallar gereği, işaretsiz türlerin bulunduğu işlemlerin türü de işaretsizdir. Yani aslında 'i - ortaDeğer' işleminin sonucu işaretsizdir. Alttan taşarsa işaretsiz türün büyük bir değerini edinir.

Dizi elemanı double olduğu için de o büyük değer aynen korunuyor.

Bence foreach sayacının türünü Erdem'in gösterdiği gibi açıkça int yazmak iyi bir çözüm.

İşin başka kötü tarafı, dizinin türü baştan int olsa bu hatayı hiç farkedemiyoruz; çünkü işaretsiz sonucumuz o zaman int'e otomatik olarak dönüşüyor ve ikiye tümleyen aritmetiği nedeniyle doğru int değerini üretiyor. Sonuçta da yıllardır bu hatayla doğru olarak işlemekte olan program, dizi türü double yapılınca birden bire bozuluyor. :-/

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]