İmzalı ve İmzasız Tam Sayılar


395

İmzalı ve imzasız bir tamsayı arasındaki farkın doğru olduğunu söylemek doğru mudur?

  1. İmzasız daha büyük bir pozitif değere sahip olabilir ve negatif bir değere sahip olamaz.
  2. İmzasız, ön biti değerin bir parçası olarak kullanırken, imzalı sürüm sayının pozitif veya negatif olup olmadığını belirlemek için en soldaki biti kullanır.
  3. imzalı tamsayılar hem pozitif hem de negatif sayılar içerebilir.

Başka fark var mı?


6
Çünkü 0 ne olumlu ne de olumsuz olduğunu , terimini kullanmak çok daha uygun olmayan negatif bir değer yerine pozitif bir değer işaretsiz tamsayılar için.
Daniel

Yanıtlar:


344

İmzasız daha büyük bir pozitif değere sahip olabilir ve negatif bir değere sahip olamaz.

Evet.

İmzasız, ön biti değerin bir parçası olarak kullanırken, imzalı sürüm sayının pozitif veya negatif olup olmadığını belirlemek için en soldaki biti kullanır.

İşaretli tam sayıları temsil etmenin farklı yolları vardır. Görselleştirmenin en kolayı, en soldaki biti bir işaret ( işaret ve büyüklük ) olarak kullanmaktır, ancak daha yaygın olanı ikisinin tamamlayıcısıdır . Her ikisi de çoğu modern mikroişlemcide kullanılmaktadır - kayan nokta işaret ve büyüklük kullanırken, tamsayı aritmetiği ikinin tamamlayıcısını kullanır.

imzalı tamsayılar hem pozitif hem de negatif sayılar içerebilir.

Evet


Bunun tam olarak bu metin olup olmadığından emin değilim ama başka bir bağlantı buldum. PDF'nin 9. sayfasına gidin (aslında kitabın 38. sayfasıdır) ve Veri Temsili (Bölüm 1.3) bölümünü görebilirsiniz. Yukarıda söylenen her şeyin açıklamasına sahiptir. lms.uop.edu.jo/lms/pluginfile.php/2420/mod_resource/content/1/…
WeirdElfB0y

92

X86'da donanım düzeyinde farklılıklara gireceğim. Bir derleyici yazmıyorsanız veya montaj dilini kullanmıyorsanız, bu çoğunlukla önemsizdir. Ama bilmek güzel.

İlk olarak, x86, ikisinin işaretli sayıların tamamlayıcı temsili için yerel desteğe sahiptir . Diğer gösterimleri kullanabilirsiniz, ancak bu daha fazla talimat gerektirir ve genellikle işlemci süresi kaybı olur.

"Yerel destek" ile ne demek istiyorum? Temel olarak, imzasız sayılar için kullandığınız bir dizi talimat ve imzalı sayılar için kullandığınız başka bir takım vardır. İmzasız numaralar, imzalı numaralarla aynı kayıtlara oturabilir ve gerçekten de imzalı ve imzasız talimatları işlemciyi endişelendirmeden karıştırabilirsiniz. Bir numaranın imzalanıp imzalanmadığını izlemek derleyiciye (veya montaj programlayıcısına) bağlıdır ve uygun talimatları kullanın.

İlk olarak, ikinin tamamlayıcı sayıları toplama ve çıkartmanın imzasız sayılarla aynı olduğu özelliğine sahiptir. Sayıların pozitif veya negatif olması fark etmez. (Sadece devam edin ve So ADDve SUBbir kaygı olmadan sayılar.)

Karşılaştırmalar söz konusu olduğunda farklar ortaya çıkmaya başlar. x86'nın bunları ayırt etmenin basit bir yolu vardır: yukarıda / aşağıda imzasız bir karşılaştırma ve imzalı bir karşılaştırmayı gösteren büyük / küçük. (Örneğin JAE, "Üstte veya eşitse zıpla" anlamına gelir ve imzasızdır.)

İmzalı ve imzasız tamsayılarla ilgilenmek için iki set çarpma ve bölme talimatı vardır.

Son olarak: örneğin taşma olup olmadığını kontrol etmek istiyorsanız, imzalı ve imzasız numaralar için bunu farklı şekilde yaparsınız.


İmzasız ve imzalı sayılarla ne demek istiyorsun, sormak istediğim şey imzasız int a = 2 ve imzalı int b = 2 yazdığımda, hem imzalı hem de imzasız, bir sayı imzalı veya imzasız mı? negatif işaretinin olup olmadığına mı bağlıyız? Bu bir süredir beni rahatsız ediyor.
Suraj Jain

@SurajJain imzalı ve imzasız tiplere atıfta bulunur. Onlar olup olmadığını göstermek mümkün değişken veya ifade negatif bir değer sahip olması.
Artelius

Aşağıdaki şüphem var, soruyu sordum, henüz tatmin edici bir cevap yok, buraya bir göz atın, stackoverflow.com/questions/41399092/…
Suraj Jain

62

Sadece imzalı ve imzasız olduğunu sordu. İnsanların buna neden fazladan şeyler eklediğini bilmiyorum. Size cevabı söyleyeyim.

  1. İmzasız: Yalnızca negatif olmayan değerlerden oluşur, yani 0 ila 255.

  2. İmzalı: Hem negatif hem de pozitif değerlerden oluşur, ancak farklı biçimlerde

    • 0 ile +127 arasında
    • -1 ila -128

Ve bu açıklama 8-bit sayı sistemi ile ilgilidir.


17

Tamlık için sadece birkaç nokta:

  • bu cevap sadece tamsayı temsillerini tartışmaktadır. Kayan nokta için başka cevaplar olabilir;

  • negatif bir sayının gösterimi değişebilir. Bugün kullanılan en yaygın (bugüne kadar - neredeyse evrenseldir) ikisinin tamamlayıcısıdır . Diğer temsiller arasında kişinin tamamlayıcı (oldukça nadir) ve imzalı büyüklüğü (kaybolan nadiren - muhtemelen sadece müze parçalarında kullanılır) sayıyı mutlak değeri temsil eden kalan bitlerle bir işaret göstergesi olarak kullanır.

  • İkisinin tamamlayıcısı kullanıldığında, değişken pozitif sayılardan daha geniş bir negatif sayı aralığını (birer birer) temsil edebilir. Bunun nedeni, sıfırın 'pozitif' sayılara dahil edilmesidir (çünkü işaret biti sıfır için ayarlanmadığından), ancak negatif sayıların değil. Bu, en küçük negatif sayının mutlak değerinin temsil edilemeyeceği anlamına gelir.

  • tamamlayıcı veya işaretli büyüklüğünü kullanırken sıfırın pozitif veya negatif bir sayı olarak temsil edilmesini sağlayabilirsiniz (bu, bu gösterimlerin tipik olarak kullanılmamasının birkaç nedeninden biridir).


Eğer imzasız int a = -2 ve imzalı int b = -2 yazarsanız, temel temsil aynı olur, imzasız numara negatif bir değer vermenin iyi olmadığını biliyorum, ama yine de verirsem, ne olacak temel temsil?
Suraj Jain

1
Küçük eleyip sıkma: IEEE kayan noktasında işaret ve büyüklük kullanılır, bu yüzden aslında oldukça yaygındır. :-)
alastair

14

Sınıfta öğrendiklerini göre, imzalanan tamsayılar hem pozitif temsil edebilir ve işaretsiz tamsayı iken, negatif sayılar sadece negatif olmayan.

Örneğin, 8 bitlik bir sayıya bakarak :

işaretsiz değerler 0için255

imzalı değerler -128-127


11

2. nokta hariç her şey doğrudur. İmzalı girişler için birçok farklı gösterim vardır, bazı uygulamalar ilkini kullanır, diğerleri sonuncuyu kullanır, ancak diğerleri tamamen farklı bir şey kullanır. Tüm bunlar birlikte çalıştığınız platforma bağlıdır.


Bu küçük endian ve big endian mıydı?
vIceBerg

küçük ve büyük endian, platformdaki baytların sırası ile ilgilidir. Büyük endian 0x7F 0xFE 0xFF yaparken küçük endian 0xFF 0xFE 0x7F yapabilir.
Jasper Bekkers

10

Başka bir fark, farklı boyutlarda tamsayılar arasında dönüştürme yaptığınızdır.

Örneğin, bir bayt akışından (sadelik için 16 bit) bir tamsayıyı işaretsiz değerlerle çıkarıyorsanız, şunları yapabilirsiniz:

i = ((int) b[j]) << 8 | b[j+1]

(büyük olasılıkla 2. baytı kullanmalıdır, ancak derleyicinin doğru şeyi yapacağını tahmin ediyorum)

İmzalı değerlerle, işaret uzantısı hakkında endişelenmeniz ve şunları yapmanız gerekir:

i = (((int) b[i]) & 0xFF) << 8 | ((int) b[i+1]) & 0xFF

5

Genel olarak bu doğru. Farklılıkları neden aradığınız hakkında daha fazla bir şey bilmeden, imzalı ve imzasız arasındaki diğer hiçbir farklıcı düşünemiyorum.


4

Başkalarının söylediklerinin üstünde ve üstünde, C'de, işaretsiz bir tamsayıyı aşamazsınız; davranış, modül aritmetiği olarak tanımlanır. İşaretli bir tamsayı taşabilir ve teorik olarak (mevcut ana akım sistemlerde pratikte olmasa da) taşma bir hatayı tetikleyebilir (belki de sıfır hatayla bölünmeye benzer).


1
İmzalı tamsayı taşmasının tanımsız davranışı tetiklediğini ve modern derleyicilerin bunu tespit etme ve programınızı beklenmedik ancak teknik olarak meşru yollarla değiştirmek için istismar ettiklerini, çünkü tanımlanmamış davranışın gerçekleşmeyeceğini varsaymalarına izin verildiğini unutmayın. Bu, şimdi 7 yıl öncesine göre çok daha fazla sorun.
Jonathan Leffler

4
  1. Evet, işaretsiz tam sayı büyük değer saklayabilir.
  2. Hayır, pozitif ve negatif değerleri göstermenin farklı yolları vardır.
  3. Evet, işaretli tam sayı hem pozitif hem de negatif değerler içerebilir.

4

(ikinci soruya cevap olarak) Sadece bir işaret biti kullanarak (2'nin tamamlayıcısı değil), -0 ile sonuçlanabilir. Çok hoş değil.


Sadece bu cevaba eklemek için, temel olarak bu her iki sayının da temel 2 olduğu 10 == 00 anlamına gelir.

4

C işaretli tamsayılar sayıları temsil eder. Eğer ave btürleri tamsayı imzalanmış bir değişkenlerdir, standart bir derleyici ifadesi yapmanız gerektiğinden asla a+=biçine mağazayı akendi değerlerinin aritmetik toplamından daha başka bir şey. Aritmetik toplamı uymaz olsaydı, emin olmak için aişlemci, belki oraya koymak mümkün olmayabilir, ancak standart truncate için derleyici gerektirmediğine veya değeri kaydırmak veya aşan değerler ise bu konuda başka bir şey yapmak türleri için sınırlar. Standart gerektirmezken, C uygulamalarının aritmetik taşmaları işaretli değerlerle yakalamasına izin verildiğini unutmayın.

C'deki işaretsiz tamsayılar, daha büyük tiplere dönüştürme veya bunlarla yapılan işlemleri içeren senaryolar haricinde, ikisinin bir miktar gücü olan uyumlu tam sayıların soyut cebir halkaları gibi davranırlar. Herhangi bir boyuttaki bir tamsayıyı 32-bit işaretsiz tipe dönüştürmek, 4.294.967.296 tamsayı moduna uygun olan şeylere karşılık gelen elemanı verecektir. 3'ün 2'den çıkarılmasının nedeni 4,294,967,295'in, 4,294,967,295'e uygun bir şeye 3'e uygun bir şey eklemenin 2'ye uygun bir şey vermesidir.

Soyut cebirsel halka tipleri genellikle elverişli şeylerdir; maalesef C, bir türün halka olarak davranıp davranmayacağı konusunda belirleyici faktör olarak imzayı kullanır. Daha kötüsü, işaretsiz değerler, daha büyük türlere dönüştürüldüğünde halka üyeleri yerine sayı olarak kabul edilir ve intüzerlerine herhangi bir aritmetik gerçekleştirildiğinde sayılara dönüştürülmekten daha küçük işaretsiz değerler olarak kabul edilir . Eğer vbir uint32_teşit ise 4,294,967,294, o zaman v*=v;yapmalıdır v=4. Ne yazık ki, int64 bit ise, o zaman ne v*=v;yapabileceğini söylemek mümkün değil.

Standart olduğu gibi, bir kişinin cebirsel halkalarla ilişkili davranışı istediği durumlarda işaretsiz türler ve sayıları temsil etmek istediği zaman imzalı türler kullanmanızı öneririm. C'nin ayrımları olduğu gibi çizmesi talihsiz bir durum, ama onlar oldukları şey.


3

İmzasız tamsayıların sizi belirli bir tuzakta yakalaması, imzalı tamsayılardan çok daha olasıdır. Tuzak, yukarıdaki 1 ve 3 doğru olsa da, her iki tamsayı tipine de "tutabileceği" sınırların dışında bir değer atanabilmesi ve sessizce dönüştürülmesinden kaynaklanmaktadır.

unsigned int ui = -1;
signed int si = -1;

if (ui < 0) {
    printf("unsigned < 0\n");
}
if (si < 0) {
    printf("signed < 0\n");
}
if (ui == si) {
    printf("%d == %d\n", ui, si);
    printf("%ud == %ud\n", ui, si);
}

Bunu çalıştırdığınızda, her iki değer de -1'e atanmış ve farklı şekilde bildirilmiş olsa bile aşağıdaki çıktıyı alırsınız.

signed < 0
-1 == -1
4294967295d == 4294967295d

0

İmzalı ve imzasız bir değer arasındaki C'deki tek garantili fark, imzalı değerin negatif, 0 veya pozitif olabileceği, imzasız bir ise sadece 0 veya pozitif olabileceğidir. Sorun, C, türlerin biçimini tanımlamamasıdır (bu nedenle , tam sayılarınızın ikinin tamamlayıcısında olduğunu bilmiyorsunuz ). Açıkça belirttiğiniz ilk iki nokta yanlıştır.


0

Gömülü Sistemlerde programlama yaparken imzasız Tam Sayılar kullanmalısınız. Döngülerde, imzalı tamsayılara ihtiyaç olmadığında, imzasız tamsayıların kullanılması, bu tür sistemlerin tasarımı için gerekli olan güvenli tasarrufu sağlayacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.