Thread overview
12 Tamsayılar Ve Aritmetik İşlemler
Feb 17, 2022
Salih Dincer
Feb 17, 2022
Ali Çehreli
Feb 18, 2022
Ali Çehreli
Feb 19, 2022
Ali Çehreli
Feb 19, 2022
Salih Dincer
February 17, 2022

Herkese iyi akşamlar dilerim (Türkiye için akşam vakti :) ). Benim sorum, şimdi sorarken farkettim, biraz saçma olacak ama, uint türünde taşma yapılması ile ilgili. Normalde hesap makinesinden ( uint.max - (sayı_1 - sayı_2) ) = 9 sonucunu alıyorum. Yani buna: ( 4 294 967 295 - 4 294 967 286 ) = 9 . Ama derleyici 10 gösteriyor. Buradan şuna varıyorum uint.min = 0 değerini alacağı için derleyici 0 'ı da dahil ediyor. Ama bu hesaba göre de (9 + 0 ) = 9 eder yine 10 etmez. Derleyici ne için bana 10 sonucunu veriyor? Bunu merak ediyorum.

import std.stdio;

void main ( ) {
uint sayı_1 = 10;
uint sayı_2 = 20;
writeln("Sorun! uint eksi değer tutamaz: ");
writeln("( sayı_1 - sayı_2 ) = ", (sayı_1 - sayı_2));
writeln("( sayı_2 - sayı_1 ) = ", (sayı_2 - sayı_1));
}
/* Çıktısı ->
* Sorun! uint eksi değer tutamaz:
* ( sayı_1 - sayı_2 ) = 4294967286
* ( sayı_2 - sayı_1 ) = 10
*/

Bir daha deneyeyim diye main işlevinin içinde sadece şunu çalıştırdım: writeln((uint.min) - 10); dersem uint.max 'ı veriyor. İşte bu sonucu tekrar alınca " acaba saçma bir soru mu soruyorum?" Dedim.

February 17, 2022

On Thursday, 17 February 2022 at 17:06:29 UTC, İsmail Emre ARIKAN wrote:

>

Herkese iyi akşamlar dilerim (Türkiye için akşam vakti :) ). Benim sorum, şimdi sorarken farkettim, biraz saçma olacak ama, uint türünde taşma yapılması ile ilgili. Normalde hesap makinesinden ( uint.max - (sayı_1 - sayı_2) ) = 9 sonucunu alıyorum. Yani buna: ( 4 294 967 295 - 4 294 967 286 ) = 9 . Ama derleyici 10 gösteriyor. Buradan şuna varıyorum uint.min = 0 değerini alacağı için derleyici 0 'ı da dahil ediyor. Ama bu hesaba göre de (9 + 0 ) = 9 eder yine 10 etmez. Derleyici ne için bana 10 sonucunu veriyor?

Ben 10 sonucunu almadım, işte kanıtı:

uint sayı_1 = 10, sayı_2 = 20;
uint sonucu = sayı_1 - sayı_2;

sonucu.writefln!"%b: %d"(sonucu);

foreach(n; 1 .. 9) { // 9. satır döngü dışında...
  uint x = sonucu + n;
  n.writeln(". satır=> sonucu++;");
  x.writefln!"%b: %d"(x);
}

9.writeln(". satır=> sonucu++;");
uint.max.writefln!"%b: %d"(uint.max);

writeln("9 == ", uint.max - sonucu);
uint testOK = uint.max - sonucu;

assert(testOK == 9);
February 17, 2022
On 2/17/22 09:06, İsmail Emre ARIKAN wrote:

>   Bir daha deneyeyim diye main işlevinin içinde sadece şunu çalıştırdım:
> writeln((uint.min) - 10); dersem uint.max 'ı veriyor. İşte bu sonucu
> tekrar alınca " acaba saçma bir soru mu soruyorum?" Dedim.

Bu konular çok karışık olabiliyor. Şu anda İngilizce forumda C++ için yazılmış olsa da bizimle de ilgili olan "The Usual Arithmetic Confusions" diye bir konu var ("conversions"ı esprili olarak "confusions"a çevirmişler):

  https://forum.dlang.org/thread/ubqnsvildaxtkhrdwjuj@forum.dlang.org

Yani bu otomatik tür dönüşümlerinin gariplikleri bitmez. :)

Aşağıdaki program benim anlayışıma uyuyor. 'uint.min - 1' değerinden başlayarak yazdırıyoruz. 'uint.min - 1'in değeri uint.max' ile aynı oluyor:

import std.stdio;

void main ( ) {
  writeln(uint.max);
  writeln("-----------");
  foreach (i; 1 .. 10) {
    writeln(uint.min - i);
  }
}

Benim mantığıma şöyle uyuyor: 0'dan bir eksiltince 0xffff_ffff oluyor; o da uint.max zaten.

Ali

February 18, 2022
On Thursday, 17 February 2022 at 23:10:10 UTC, Ali Çehreli wrote:
> Bu konular çok karışık olabiliyor. Şu anda İngilizce forumda C++ için yazılmış olsa da bizimle de ilgili olan "The Usual Arithmetic Confusions" diye bir konu var ("conversions"ı esprili olarak "confusions"a çevirmişler):
>
>   https://forum.dlang.org/thread/ubqnsvildaxtkhrdwjuj@forum.dlang.org
>
> Yani bu otomatik tür dönüşümlerinin gariplikleri bitmez. :)
 Bunu bilmiyordum hocam. :)
>
> Aşağıdaki program benim anlayışıma uyuyor. 'uint.min - 1' değerinden başlayarak yazdırıyoruz. 'uint.min - 1'in değeri uint.max' ile aynı oluyor:
>
> import std.stdio;
>
> void main ( ) {
>   writeln(uint.max);
>   writeln("-----------");
>   foreach (i; 1 .. 10) {
>     writeln(uint.min - i);
>   }
> }
>
> Benim mantığıma şöyle uyuyor: 0'dan bir eksiltince 0xffff_ffff oluyor; o da uint.max zaten.
>
> Ali

 Ali hocam yazdığınız program sayesinde tüm ara işlemleri görebiliyorum ve saydım: tam 9 tane sayı var. Sağolun.
/*
"4294967295
-----------

4294967295
4294967294
4294967293
4294967292
4294967291
4294967290
4294967289
4294967288
4294967287"
*/
February 18, 2022
On 2/18/22 07:37, İsmail Emre ARIKAN wrote:

>> Yani bu otomatik tür dönüşümlerinin gariplikleri bitmez. :)
>   Bunu bilmiyordum hocam. :)

Tamsayı terfileri (integer promotions) ve otomatik dönüşümler C++ ve D'ye C'den geçmiştir. Hep kafa karışıklıklarına ve hatalara yol açarlar.

Aşağıdaki programın çıktısını çalıştırmadan yanıtlamaya çalışın:

import std.stdio;

void main() {
  int[10] dizi;
  writeln(-11 + dizi.length);
}

dizi'nin uzunluğu 10 olduğuna göre, -11'e 10 eklersem herhalde -1 yazılır. Yazılmaz! :)

Burada, şurada anlatılan kurallardan biri uygulanıyor:


http://ddili.org/ders/d/tur_donusumleri.html#ix_tur_donusumleri.terfi,%20tamsay%C4%B1

(Kitabın ileri bir noktasında olsa da oradaki hem int terfileri hem de aritmetik dönüşümler önemlidir.)

Eğer 64 bitlik bir ortamdaysanız, uygulanan kural, oradakilerin en sonuncusudur:

  4. Hiçbirisi değilse işaretli tür işaretsiz türe dönüştürülür

Dizilerin .length niteliği size_t'dir. size_t, 64 bitlik ortamda ulong'dur. -11 int'tir, int işaretli türdür; o yüzden -11 önce ulong'a dönüştürülür, kocaman bir değer olur ve o değerden 10 çıkartılır.

Bu saatten sonra yapacak bir şey yok. İşin kötüsü, bu dönüşümlerden daha iyisi de bulunamıyor. Kurallar başka türlü olsaymış başka saçmalıklar oluşurmuş. Yani, bunlar işin doğasında var.

Ali

February 19, 2022
On Friday, 18 February 2022 at 16:35:03 UTC, Ali Çehreli wrote:
> On 2/18/22 07:37, İsmail Emre ARIKAN wrote:
>
> >> Yani bu otomatik tür dönüşümlerinin gariplikleri bitmez. :)
> >   Bunu bilmiyordum hocam. :)
>
> Tamsayı terfileri (integer promotions) ve otomatik dönüşümler C++ ve D'ye C'den geçmiştir. Hep kafa karışıklıklarına ve hatalara yol açarlar.
>
> Aşağıdaki programın çıktısını çalıştırmadan yanıtlamaya çalışın:
>
> import std.stdio;
>
> void main() {
>   int[10] dizi;
>   writeln(-11 + dizi.length);
> }
>
> dizi'nin uzunluğu 10 olduğuna göre, -11'e 10 eklersem herhalde -1 yazılır. Yazılmaz! :)
>
> Burada, şurada anlatılan kurallardan biri uygulanıyor:
>
>
> http://ddili.org/ders/d/tur_donusumleri.html#ix_tur_donusumleri.terfi,%20tamsay%C4%B1
>
> (Kitabın ileri bir noktasında olsa da oradaki hem int terfileri hem de aritmetik dönüşümler önemlidir.)
>
> Eğer 64 bitlik bir ortamdaysanız, uygulanan kural, oradakilerin en sonuncusudur:
>
>   4. Hiçbirisi değilse işaretli tür işaretsiz türe dönüştürülür
>
> Dizilerin .length niteliği size_t'dir. size_t, 64 bitlik ortamda ulong'dur. -11 int'tir, int işaretli türdür; o yüzden -11 önce ulong'a dönüştürülür, kocaman bir değer olur ve o değerden 10 çıkartılır.
>
> Bu saatten sonra yapacak bir şey yok. İşin kötüsü, bu dönüşümlerden daha iyisi de bulunamıyor. Kurallar başka türlü olsaymış başka saçmalıklar oluşurmuş. Yani, bunlar işin doğasında var.
>
> Ali

    Haklısınız Ali hocam. Biz düşünmeden kararsız tür dönüşümlü işlemleri derleyiciye yollayınca dmd 'nin yaptıklarına bakınca aslında DMD 'nin ne kadar akıllı tasarlandığını anladım. Bu işlemler biz insanlar arasında da var bir örnek olarak: Az evvel ailemin kendi arasında konuşurlarken " Üç ceviz kırıldı dördüncüde kırıldı." demeleri ilgimi çekti. Bu kelimeyi hafızam anlamaya çalışırken " üç tane kırılmayan ceviz vardı ya hepsi dört defalık denemenin sonucunda kırıldılar ya da sonuncusu dördüncü denemede kırıldı sonucuna varıyor. Daha sonra sonuç olarak cevizlerin kırılması ve galiba kabuklarının sert olduğu ya da onları kırma yöntemini son denemede bulduğu sonucuna ulaşıyor. " İşte, insanlar konuşmalarında bunu çok dert etmezken insanların tasarladığı bir derleyici bunu yapıyor. Bu söylediğiniz konu da bana bu nedenle de ilginç geldi.


February 19, 2022
> " Üç ceviz kırıldı dördüncüde kırıldı."

 Az evvel ailemin neden bu konuyu konuştuğunu ortadaki sapı kırık ceviz kıracağını görünce anladım. Olayı onlardan öğrendim; meğerse komşu ceviz kırarken ceviz kıracağının sapı kırılınca çöpe atmak istemiş. Ailem de onarabileceğini düşünerek almışlar. Demek ki ceviz kıracağı üç ceviz kırabildi; dördüncüyü kırarken kendisinin sapı kırıldı. :)) .


February 19, 2022
On 2/19/22 02:29, İsmail Emre ARIKAN wrote:

> sapı kırık ceviz kıracağını görünce anladım.

Güzel. :)

Ben de kitapta bilgisayar dilinin konuşma diline benzediğini ama konuşma dilinden daha katı olmak zorunda olduğunu yazmıştım.

Ali

February 19, 2022
On Saturday, 19 February 2022 at 15:12:50 UTC, Ali Çehreli wrote:
> On 2/19/22 02:29, İsmail Emre ARIKAN wrote:
>
> > sapı kırık ceviz kıracağını görünce anladım.
>
> Güzel. :)
>
> Ben de kitapta bilgisayar dilinin konuşma diline benzediğini ama konuşma dilinden daha katı olmak zorunda olduğunu yazmıştım.
>
> Ali

Katılığı gevşetmek ve dili daha insancıl hale getirmek elimizde 😀