Jump to page: 1 2
Thread overview
ulong değişkene en büyük değeri atama
Apr 02, 2012
zafer
Jul 27, 2012
Salih Dinçer
Jul 27, 2012
Salih Dinçer
Jul 27, 2012
Salih Dinçer
Jul 28, 2012
Salih Dinçer
Jul 28, 2012
Salih Dinçer
Jul 28, 2012
Salih Dinçer
Jul 28, 2012
Salih Dinçer
Jul 28, 2012
Salih Dinçer
April 02, 2012

Merhaba, aşağıdaki kodda derleme zamanında şu hatayı alıyorum, yanlış olan nedir?

Alıntı:

>

signed integer overflow

Örnek kodlar;

module main;

import std.stdio;

void main()
{
   /*
   int.max : 2147483647            uint.max: 4294967295
   long.max : 9223372036854775807  ulong.max: 18446744073709551615
   */

   uint uintTest1 = uint.max;        // Tamam
   uint uintTest2 = 4_294_967_295;  // Tamam

   long longTest1 = long.max;                      // Tamam
   long longTest2 = 9_223_372_036_854_775_807;     // Tamam

   ulong ulongTest1 = ulong.max;                   // Tamam
   ulong ulongTest2 = 18446744073709551615;        // Hata -> signed integer overflow


   writefln("intTest1 : %s,  intTest2: %s", uintTest1, uintTest2);
   writefln("longTest1 : %s,  longTest2: %s", longTest1, longTest2);

   /*
   writefln("int.max : %s, uint.max: %s", int.max, uint.max);
   writefln("long.max : %s, ulong.max: %s", long.max, ulong.max);
   */
}

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

April 02, 2012

Bu benim hatam. Şurada "Tamsayı değerlerin türleri" başlığı altındaki bilgi eksik:

http://ddili.org/ders/d/hazir_degerler.html

Şurada yazanlara bakılırsa benim "... ona da sığmıyorsa ulong'dur" yazdığım kural yok:

http://dlang.org/lex.html#IntegerLiteral

Orada "Decimal Literal Types" tablosunda görüldüğü gibi, onlu yazılan sabit değer küçükse int, büyükse long. Otomatik olarak ulong kabul edilebilmesi için ya sonunda U (veya u) olmalı, ya da onlu olarak yazılmamamış olmalı (örneğin 0xFFFF_FFFF_FFFF_FFFF):

   ulong ulongTest2 = 18446744073709551615U; // şimdi tamam

Ali

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

July 27, 2012

Az önce bir kaç deneme (aşağıda sadece ikisi nakledildi) yaptım ve neticede 'assert()''in düzgün veri alamadığını ve dikkatli olmamız gerektiğini farkettim. Alt çizgiler ile de alakası yok arkadaşlar...:)

Çünkü o şekilde de "failure" vermiyor ki, denedim. İlki olması gerektiği gibi doğru çalışyor (hata atıyor); o yüzden satırı gizledim. Ama diğerinde sorun var gibi, ne dersin? Dener misiniz...

uint.max.writeln; // 4_294_967_295
//assert(uint.max > (2_999_999_999 * 2)); // Assertion failure
5999999998.writeln(" uint.max'dan büyüktür!");
writeln(2_999_999_999 * 2); // Doğru hesap ediyor...

assert(uint.max > (999_999_999 * 22)); // (!)
21999999978.writeln(" uint.max'dan büyüktür!");
writeln(999999999 * 22); // Herhangi birinde L olmaz ise yanlış hesap ediyor!

Bu kod normal bir şekilde çalışır çünkü 2. 'assert()''de yanlış hesap ediliyor...
Alıntı (acehreli:1333377449):

>
>     ulong ulongTest2 = 18446744073709551615U; // şimdi tamam
> ```

>
Hocam, L ile birlikte U harfi de olması gerekmiyor muydu? Çünkü D.ershane'de şöyle yazılmış:

Alıntı:
>
> Değerin büyüklüğünden bağımsız olarak, eğer değerin sonunda bir U karakteri varsa, işaretsiz bir türdür. Örnek: 10U'nun türü uint'tir. Küçük harf u da kullanılabilir.
>
> L ve U karakterleri birlikte ve sıralarının önemi olmadan da kullanılabilirler. Örneğin 7UL'nin ve 8LU'nun ikisinin de türleri ulong'dur.
>

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

Alıntı:

>
> uint.max.writeln; // 4_294_967_295
> //assert(uint.max > (2_999_999_999 * 2)); // Assertion failure
> 5999999998.writeln(" uint.max'dan büyüktür!");
> writeln(2_999_999_999 * 2); // Doğru hesap ediyor...
> ```

Peki hocam yukarıdaki ilk örnekte neden kırpılma olmuyor? Öyle ya, 2 ile çarpılma sonucu uint.max'ı geçen bir değer!

Alıntı (acehreli):
> Evet, eğer kırpılma olmasın diye açıkça long istiyorsak L yazmalıyız.
>
> Bu kurallar çok karışık olabiliyorlar. D'ye kızamıyoruz çünkü diğer yaygın sistem dilleri olan C ve C++'tan olduğu gibi aktarılmıştır.
Kızmak mümkün mü, D'ye gönül vermiş insanlarız! En azından gülü seven dikenine katlanır hesabı...:)

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

Yok gözden kaçırmadım, sanırım anlamamışım ve hala anlayamıyorum!

Bir - iki saat vakit lüften, anlayacağım...:)

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

July 27, 2012

Öncelikle, böyle önemli uyarıların için tekrar teşekkürler.

Alıntı (Salih Dinçer):

>

'assert()''in düzgün veri alamadığını

Mutlaka bir açıklaması vardır. ;) Hem assert'in veri alması demek de doğru değil. Onun tek yaptığı, verilen ifadeyi işletmek.

Alıntı:

>

dikkatli olmamız gerektiğini farkettim.

Her zaman! Hem de nasıl! :)

Alıntı:

>

Alt çizgiler ile de alakası yok arkadaşlar...:)

Zaten olmaması gerekiyor. Alt çizginin değere etkisi olursa derleyici hatasıdır.

Alıntı:

>

//assert(uint.max > (2_999_999_999 * 2)); // Assertion failure

Tamsayı işlemlerine bakmadan önce o işlemin hangi türde işletildiğinden emin olmamız gerekir. Şuradaki "Aritmetik dönüşümler" başlığına bakacağım:

http://ddili.org/ders/d/tur_donusumleri.html

Bir de şuradaki hazır değerlerin türlerine:

http://ddili.org/ders/d/hazir_degerler.html

2'nin türü int; o kolay. 2_999_999_999'un türü ise "int'e sığmadığı ve onlu olarak yazıldığı" için long.

long * int ifadesinin sonucunun türü "Aritmetik dönüşümler" başlığındaki 4.2 maddesi gereğince long.

şimdi 'uint > long' ifadesinin türüne bakalım. O da 4.3 maddesi gereğince long. Yani uint.max'a karşılık gelen long değer ile 2_999_999_999 * 2'ye karşılık gelen long değeri karşılaştırıyoruz. Bakalım:

   writeln(typeid(2_999_999_999 * 2));
   writefln("%x", cast(long)uint.max);
   writefln("%x", 2_999_999_999 * 2);

Çıktısı:

'long
ffffffff
165a0bbfe
'

Evet, söylediklerime uyuyor. Herşey doğru işlemiş.

Alıntı:

>

assert(uint.max > (999_999_999 * 22)); // (!)

Şimdi ona bakalım: çarpma işleminin solunda ve sağında int var. O yüzden işlem int üzerinden yapılıyor. Sonuç yine int ama bu sefer int'e sığmadığı için kırpılıyor. Ondan sonra > işlemi iki taraf da uint türünde olacak biçimde işletiliyor. (4.4 maddesi).

Alıntı:

>

writeln(999999999 * 22); // Herhangi birinde L olmaz ise yanlış hesap ediyor!

Evet, eğer kırpılma olmasın diye açıkça long istiyorsak L yazmalıyız.

Bu kurallar çok karışık olabiliyorlar. D'ye kızamıyoruz çünkü diğer yaygın sistem dilleri olan C ve C++'tan olduğu gibi aktarılmıştır.

Ali

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

July 27, 2012

Alıntı (Salih Dinçer):

>

yukarıdaki ilk örnekte neden kırpılma olmuyor? Öyle ya, 2 ile çarpılma sonucu uint.max'ı geçen bir değer!

Gözden kaçırmış olmalısın; yukarıdan kopyalıyorum:

Alıntı (acehreli):

>

2'nin türü int; o kolay. 2_999_999_999'un türü ise "int'e sığmadığı ve onlu olarak yazıldığı" için long.

long * int ifadesinin sonucunun türü "Aritmetik dönüşümler" başlığındaki 4.2 maddesi gereğince long.

şimdi 'uint > long' ifadesinin türüne bakalım. O da 4.3 maddesi gereğince long. Yani uint.max'a karşılık gelen long değer ile 2_999_999_999 * 2'ye karşılık gelen long değeri karşılaştırıyoruz.

Ali

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

July 27, 2012

Alıntı (Salih Dinçer):

>

ilk örnekte neden kırpılma olmuyor? Öyle ya, 2 ile çarpılma sonucu uint.max'ı geçen bir değer!

Bir de şunu hatırlatayım: Doğal olarak, kırpılma kavramı için hem değer hem de tür önemlidir. uint.max'ı geçtiğini bildiğimiz değerin türü long olduğu için kırpılma olmuyor.

Ali

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

July 28, 2012

Aradan neredeyse 24 saat geçecek ve ben hala anlayamıyorum...:)

Yani sorunu ve çözümünü anlamaktayım. Ama 'uint'.max'ı geçen bir değerin bir yerde çalışıp bir yerde çalışmaması bana ilginç geliyor. Tamam, 'long' türü olduğu için kırpılmama hadisesi olabilir. Peki aşağıdaki kodda bütün bu değerleri (hatta farkını) aritmetik olarak ve alt alta hizalayarak göstermişken, bunu nasıl açıklayabiliriz?

 uint.max.writeln("<-- bu uint.max'dır");
 long.max.writeln("<-- bu long.max'dır ve aradaki fark = ", long.max-uint.max);

 long hes = 2_999_999_999L * 2L;
 hes.writeln("<-- bunu büyük gören gizlenmiş assert(), hemen aşağıdadır!");
 //assert(uint.max > (2_999_999_999 * 2)); // Assertion failure

 hes = 999_999_999L * 22L;
 hes.writeln("<-- bunu küçük(!) gören çalışmayan assert(), hemen aşağıdadır!");
 assert(uint.max > (999_999_999 * 22)); // (!)

Bir de hes'leri yanlış hesaplayalım. Yani L harfini koymadığımızı farz edelim. İkisi (son iki satır) şu şekilde ekrana sonuç yazdırmaktadır:

'4294967295<-- bu uint.max'dır
9223372036854775807<-- bu long.max'dır ve aradaki fark = 9223372032559808512
5999999998<-- bunu büyük gören gizlenmiş assert(), hemen aşağıdadır!
525163498<-- bunu küçük(!) gören çalışmayan assert(), hemen aşağıdadır!
'
Burada küçük(!) şekilde ifade ettiğim gerçekten de küçük ama aritmetik işlem sırasında birine L koymanız "5_999_999_998" değerinden 1 basamak daha büyük bir değer çıkmasını ve dolayısıyla 'assert()''ün çalışmasına sebep oluyor!

Pekiiii...:)

Asıl soru geliyor: 'uint'.max ile 'long'.max arasında bir değer (sınır) mı var ki hes, ilk hesaplandığında 'uint'.max'dan büyük olabilir ve 'assert()' ile çalışabiliyorken ikincisinde n'oluyorda kırpılıyor? Aslında ne olduğunu biliyoruz! Çünkü değer, "525_163_498" (kırpılan!) değil de "21_999_999_978" hesaplanması gerektiği ve 'x'.max'ı da taşırdığını anlıyorum...

'x'.max mı? Evet...:)

Henüz tespit etmedim ama belki 1 bit fazlasıdır(?) bir 'x'.max var! Çünkü bu "4_294_967_295", bir 'uint'.max değeridir ve bu da "5_999_999_998" 'uint'.max'ı geçmekte (fark = 1_705_032_703) olan ve ilk 'assert()''ü sorunsuzca tetikleyebilen bir değerdir...

Şimdiiii...:)

Bomba soru geliyor: Madem 'uint'.max'ı geçen bir türden (bunun 'long' olduğu söyleniyor) bahsediyoruz, öyleyse 'long'.max değerine kadar hiç bir kırpılma işlemi olmaması gerekmez miydi? Öyle ya, hesap ortada:

'9_223_372_036_854_775_807

  •      21_999_999_978
    

--------------------------'
Farkı hiç hesaplamıyorum bile...:)

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

July 28, 2012

Tamam...:)

Olay çözülmüştür! Anladığımı aktarayım...

Sabit bir değer kullanıyorsanız ve türü ifade eden harf kullanmıyorsanız (türü belli olan bir değişken üzerinde hesap yapmıyorsanız), derleyici bu sayıların türünü otomatik belirliyor. Bunu, yapılan hesaplamalar işaretli olabileceğinden, otomatik belirlenen değerler sırasıyla şu şekilde (işaretli türler ile) sorgulanıyor:

  • 'byte.max'ı geçti mi?' <-- Bunda yanılmışım, böyle bir şey yok!
  • 'short.max'ı geçti mi?' <--- Bunda da, çünkü olay bundan sonra sorgulanıyormuş...:)
  • 'int'.max'ı geçti mi?
  • 'long'.max'ı geçti mi?
    (Geçmediyse, o halde değeri, en son sorgudan 'false' dönen tür ile işaretle!)

Bunu 'int'.max ile örnekleyelim:

 writeln((int.max + 1) * 10);    // Çıktısı: 0
 writeln((int.max + 1L) * 10);   // Çıktısı: 21474836480 (örnekteki gibi)
 writeln((int.max + 1) * 10L);   // Çıktısı: -21474836480 (?)
 writeln((int.max + 1L) * 10L);  // Çıktısı: 21474836480 (örnekteki gibi)
 // Örnek:
 write(2147483648 * 10, ": 10'u bunun 1 fazlasıyla çarptım-->", int.max);
 writeln("(int.max)\nİşte bu yüzden derleyici değere long.max işareti koydu!");

Çıktısı:
'0
21474836480
-21474836480
21474836480
21474836480: 10'u bunun 1 fazlasıyla çarptım-->2147483647(int.max)
İşte bu yüzden derleyici değere long.max işareti koydu! >>----|
v-------------------------------------------------------------|'
Çünkü 'int'.max değerinden 1 fazlaydı (sabit değer olarak!) ve sanki yanında gizli bir L varmış gibi düşünmemiz gerekiyor. İşte bu yüzden sihirli sayılar ile çalışıyorken eğer sayı 'int'.max değerini geçmediyse ve yanında L belirteçini kunllamadıysanız sayı, (DİKKAT) açımasızca kırpılacaktır...:)

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

« First   ‹ Prev
1 2