İmzasız numaralar neden uygulanır?


12

Mikroişlemci sistemlerin neden imzasız sayılar kullandığını anlayamıyorum. Sanırım maliyet koşullu dalların sayısının iki katı, çünkü .etc'den daha büyük, imzalı olandan farklı bir algoritmaya ihtiyaç duyuyor, hala imzasız sayıların önemli bir avantajı olduğu herhangi bir algoritma var mı?

sorum kısmen bir derleyici tarafından desteklenmediği gibi neden talimat setinde olmaları gerektiğidir?


27
Temel olarak imzasız sayılar standarttır, işaretli negatif sayılar sağlamak için uygulanır.
Pieter B

37
Dünyadaki verilerin çoğu sayısal değildir. Sayısal olmayan veriler, imzasız türler kullanılarak kolayca değiştirilebilir. Java'nın imzasız sayısal türlere sahip olmaması bir başarısızlıktır, bu da sayısal olmayan verileri (örneğin sıkıştırma vb.) İşlemek zorunda olan şeylerde çok fazla hataya neden olur.
Erik Eidt

6
@jtw Erik, negatif piksel rengi veya negatif karakter diye bir şey olmadığını söylüyor. Bunun için imzalı tamsayıları kullanmak israf olacaktır, adres alanının yarısından vazgeçersiniz.
Martin Maat

26
Burada yalnız olup olmadığımdan emin değilim, ancak uygulamaları geliştirirken imzalı tamsayılara ihtiyacım olması şaşırtıcı derecede nadir . Neredeyse her zaman ihtiyacım olan şey (imzasız) doğal bir sayı (genellikle pozitif bir boyut) veya imzalı bir kayan nokta sayısıdır. İstisnalar para birimi gibi şeylerdir, ancak bunlar çok nadirdir; bana göre, imzasız tamsayılar norm ve imzalı tamsayılar istisnadır!
Thomas

11
Bir CPU bakış açısından, hemen hemen tüm sayılar imzasızdır. Birkaç talimat bitleri imzalı (.eg aritmetik-sağ kaydırma) olarak yorumlayabilir, ancak gerçekten ikisinin tamamlayıcısı , CPU'nun imzalı tamsayıları imzasız tamsayı olarak görmesini sağlar, yani CPU tarafından her ikisini de desteklemek için hiçbir (veya çok az) özel devre gerekmez .
Cornstalks

Yanıtlar:


39

İmzasız sayılar, bir bit dizisinin bir yorumudur. Aynı zamanda, CPU ve dahili olarak en basit ve en çok kullanılan yorumdur çünkü adresler ve op kodları basitçe bitlerdir. Bellek / Yığın adresleme ve aritmetik, mikroişlemci, kuyu, işlemenin temelleridir. Soyutlama piramidini yukarı doğru hareket ettirirken, bitlerin sık sık başka bir yorumu bir karakterdir (ASCII, Unicode, EBCDIC). Sonra IEEE Kayan nokta, grafikler için RGBA vb. Gibi başka yorumlar da var. Bunların hiçbiri basit işaretli sayılar değildir (IEEE FP basit değildir ve bunları kullanan aritmetik çok karmaşıktır).

Ayrıca, imzasız aritmetik ile diğerlerini uygulamak oldukça doğrudur (en verimli değilse). Bunun tersi doğru değil.


3
EBCDIC'in sadece bir "I" si vardır.
Ruslan

4
@Ruslan - ama oluyor telaffuz o ikisi var gibi. <g>
Pete Becker

5
@PeteBecker hayır değil. EBCDIC eb -see-dick olarak telaffuz edilir .
Mike Nakis

19

Karşılaştırma işlemleri için donanım maliyetinin büyük kısmı çıkarma işlemidir. Karşılaştırma ile kullanılan çıkarımın çıktısı esasen üç durum bitidir:

  • tüm bitlerin sıfır olup olmadığı (yani eşit koşul),
  • sonucun işaret biti
  • çıkarma işleminin taşıma biti (yani 32 bitlik bir bilgisayarda 33. yüksek dereceli bit)

Çıkarma işleminden sonra bu üç bitin test edilmesinin uygun kombinasyonu ile, tüm imzalı ilişkisel işlemleri ve tüm imzasız ilişkisel işlemleri belirleyebiliriz (bu bitler ayrıca taşmanın nasıl tespit edildiği, imzalı ve imzasız olduğu şeklindedir). Aynı temel ALU donanımı, istenen ilişkisel karşılaştırmaya göre farklılık gösteren bu üç durum bitinin son kontrolüne kadar tüm bu karşılaştırmaları uygulamak için (çıkarma talimatından bahsetmemek üzere) paylaşılabilir. Yani, fazladan bir donanım değil.

Tek gerçek maliyet, talimat yoğunluğu marjinal olarak azaltabilecek talimat seti mimarisinde ek karşılaştırma modlarının kodlanması gereksinimidir. Yine de, donanımın belirli bir dil tarafından kullanılmayan birçok talimatı olması oldukça normaldir.


1
İmzasız sayıların karşılaştırılması çıkarma gerektirmez. soldan sağa bitsel karşılaştırma ile elde edilebilir.
Jonathan Rosenne

10
@JonathanRosenne Ama işlemciler bunu böyle uygulamıyor. Aksine, 2'li bir tamamlayıcı işlemcinin ALU'sunda çıkarma (taşıma / ödünç alma ile veya taşıma olmadan) uygulamaması neredeyse düşünülemez. Hemen ardından bir tasarımcı hakkında düşünmek, bu gerekli ALU'yu aynı taşla karşılaştırmak için başka bir kuşu öldürmek için kullanmaktır. Daha sonra karşılaştırma, sonucun kayıt dosyasına geri yazılmadığı bir çıkarma olur.
Iwillnotexist Idonotexist

4
+1: bu, sorulan soruya doğru cevaptır. Özetleme: imzalı olmayan işlemleri uygulamak zaten imzayı uyguladığınızda neredeyse ücretsizdir .
Periata Breatta

10
@PeriataBreatta Ayrıca başka bir şekilde çalışır. Modern CPU'lardaki işaretli ve işaretsiz sayılar neredeyse aynıdır, bu da OP'nin tanımadığı ana noktadır. Karşılaştırma talimatları bile imzalı ve imzasız için aynıdır - bu, ikisinin tamamlayıcısının imzalı tamsayı savaşlarını kazanmasının nedenlerinden biridir :)
Luaan

3
@svidgen> diğer cevapların söylediği gibi, bunun tersini yapar. Birincil kaygı, temelde her şey için kullanılan işaretsiz sayılardır (bellek adresi, io / bağlantı noktaları, karakter gösterimleri,…). İmzalı numaralar, imzasız olduktan sonra ucuza gelir ve nadir görülen durumlarda istenirse kullanışlı olur.
spektrumlar

14

Çünkü, her zaman >= 0 olan bir şeyi saymanız gerekirse , imzalı tam sayıları kullanarak sayma alanınızı gereksiz yere yarıya indirirsiniz.

Veritabanı tablolarınıza koyabileceğiniz otomatik olarak artırılmış INT PK'yi düşünün. Bilgisayarda biçimlendirilmiş bir sayıda kayıtları o kadar, orada masa depolar YARI tamsayı imzalanmış olabilir YOK parası ile aynı alan boyutu için.

Veya bir RGBa renginin sekizlileri. Bu doğal olarak pozitif sayı kavramını negatif bir sayı olarak saymaya garip bir şekilde başlamak istemiyoruz. İşaretli bir sayı ya zihinsel modeli kıracak ya da alanımızı yarıya indirecektir. İşaretsiz bir tam sayı yalnızca kavramla eşleşmez, aynı zamanda iki katı çözünürlük sağlar.

Donanım açısından, imzasız tamsayılar basittir. Muhtemelen matematiği gerçekleştirmek için en kolay bit yapısıdır. Ve şüphesiz, bir derleyicideki tamsayı tiplerini (hatta kayan nokta!) Simüle ederek donanımı basitleştirebiliriz. Yani, neden hem imzasız olan ve imzalı tamsayı uygulanan donanım?

Performans ...

İşaretli tam sayıları donanıma uygulamak, yazılımda olduğundan daha etkilidir. Donanımdan, tek bir komutta her iki tamsayı türünde matematik yapması istenebilir. Ve bu çok iyi , çünkü donanım bitleri aşağı yukarı paralel olarak topluyor. Bunu yazılımda simüle etmeye çalışırsanız, "simüle etmeyi" seçtiğiniz tamsayı türü şüphesiz birçok talimat gerektirir ve fark edilir şekilde daha yavaş olur.


2
Bu çizgiler boyunca, dizi sınırları kontrolü yaparken kendinize bir işlem kaydedebilirsiniz. İmzasız bir tamsayı kullanırsanız, yalnızca sağlanan dizinin dizi boyutundan küçük olup olmadığını kontrol etmeniz gerekir (negatif olamaz).
riwalk

2
@ dan04 Kesinlikle olabilir ... Ama, 0 veya 1'den başlayarak otomatik olarak artan bir int kullanıyorsanız, bu oldukça yaygın bir uygulamadır, mevcut sayılarınızın yarısının kullanılmasını engellediniz. Ve makul bir şekilde -2 ^ 31 (ya da her neyse) olarak saymaya başlayabilseniz de, kimlik alanınızın ortasında potansiyel bir "kenar" durumunuz olacaktır.
svidgen

1
Alanınızı ikiye bölmek zayıf bir argüman. Şansınız, uygulamanız 2 milyardan fazla, 4 milyardan fazla gerektiriyorsa.
corsiKa

1
@corsiKa: bu nedenle, 4'ten fazla gerektiriyorsa, muhtemelen 8, sonra 16 vb. gerektirir. Nerede bitiyor?
whatsisname

1
@whatsisname genellikle 8, 16, 32 veya 64 bitlik tamsayı türlerini kullanırsınız. İmzasız olduğunu söylemek daha iyidir çünkü imzalı bir bayttaki 31 bitlik pozitif tamsayı alanının sınırlı aralığı yerine 32 bitin hepsini alırsınız , çoğu durumda önemli değildir.
corsiKa

9

Sorunuz iki bölümden oluşmaktadır:

  1. İmzasız tam sayıların amacı nedir?

  2. İmzasız tam sayılar sorun çıkarmaya değer mi?

1. İşaretsiz tam sayıların amacı nedir?

İmzasız sayılar, oldukça basit bir şekilde, negatif değerlerin anlamsız olduğu bir miktarlar sınıfını temsil eder. Elbette, "kaç elmam var?" Sorusunun cevabını söyleyebilirsiniz. birisine biraz elma borcunuz varsa negatif bir sayı olabilir, ama "ne kadar belleğim var?" sorusuna ne dersiniz? - negatif miktarda belleğe sahip olamazsınız. Dolayısıyla, imzasız tamsayılar bu miktarları temsil etmek için çok uygundur ve işaretli tamsayıların yapabileceğinden iki kat artı değer gösterebilme avantajına sahiptirler. Örneğin, 16-bit işaretli bir tamsayı ile temsil edebileceğiniz maksimum değer 32767, 16-bit işaretsiz bir tamsayı ile 65535'tir.

2. İmzasız tam sayılar sorun çıkarmaya değer mi?

İmzasız tam sayılar gerçekten herhangi bir sorunu temsil etmez, bu yüzden evet, buna değer. Görüyorsunuz, fazladan bir "algoritma" seti gerektirmezler; bunları uygulamak için gereken devre, imzalı tamsayıların uygulanması için gereken devrenin bir alt kümesidir.

CPU'da işaretli tamsayılar için bir çarpan ve işaretsizler için farklı bir çarpan yoktur; işlemin niteliğine bağlı olarak biraz farklı bir şekilde çalışan sadece bir çarpanı vardır. İmzalı çarpmayı desteklemek imzasız olandan biraz daha fazla devre gerektirir, ancak yine de desteklenmesi gerektiğinden, imzasız çarpma pratik olarak ücretsiz olarak gelir, pakete dahil edilir.

Toplama ve çıkarma için, devrede hiçbir fark yoktur. Eğer sözde ikisinin tamsayıların tamsayı temsilini okursanız , tamsayıların doğasından bağımsız olarak bu işlemlerin tam olarak aynı şekilde gerçekleştirilebileceği kadar akıllıca tasarlanmış olduğunu göreceksiniz.

Karşılaştırma da aynı şekilde çalışır, çünkü sonucu çıkartmak ve atmaktan başka bir şey değildir, tek fark, CPU'nun ayarladığı farklı CPU bayraklarına bakarak çalışan koşullu dal (atlama) talimatlarındadır. önceki (karşılaştırma) komut. Bu cevapta: /programming//a/9617990/773113 Intel x86 mimarisinde nasıl çalıştıklarına dair bir açıklama bulabilirsiniz. Olan şey, koşullu atlama talimatının imzalı veya imzasız olarak gösterilmesinin hangi bayrakları incelediğine bağlı olmasıdır.


1
sorum tüm bunları varsaydı, algoritma ile i kural daha küçük için kural vb farklı anlamına geliyordu. Gördüğüm maliyet çok fazla talimat alıyor. Üst düzey programlar verileri bit kalıpları olarak görmek istiyorsa, bu bir derleyici tarafından kolayca uygulanabilir
jtw

3
@jtw - ama önemli olan nokta, bu ekstra talimatların aslında imzalı sayılar için gereken talimatlara çok benzemesidir ve onlar için gerekli olan devrenin neredeyse tamamı paylaşılabilir . Her iki tipin uygulanmasının ekstra maliyeti neredeyse sıfırdır.
Periata Breatta

1
Evet, soruma cevap veriyor, ekstra şube talimatlarını eklemek küçük bir maliyetle geliyor ve pratikte genellikle yararlı oluyorlar
jtw

1
"İmzasız işlemler, bölme ve çarpma söz konusu olduğunda ekstra işlem gerektiriyor" diye düşünüyorum. İmzasız değerlerle çarpma ve bölme daha kolaydır. İmzalı işlenenlerle başa çıkmak için ekstra işlem gerekir.
Cody Gray

@CodyGray Birisinin bunu söylemek için geleceğini biliyordum. Haklısın tabi ki. Başlangıçta kısaca uğruna atladığım ifademin arkasındaki sebep budur: imzalı sürümler çok faydalı olduğu için bir CPU muhtemelen sadece imzasız çarpma ve bölme sunamazdı. Nitekim, imzalı çarpma ve bölme şarttır; imzasız isteğe bağlıdır. Bu nedenle, imzasız da teklif edilecekse , bu biraz daha fazla devre gerektirdiği görülebilir.
Mike Nakis

7

Mikroişlemciler doğal olarak imzasızdır. İşaretli sayılar, tersi değil, uygulanan şeydir.

Bilgisayarlar işaretli sayılar olmadan iyi çalışabilirler ve iyi çalışırlar, ancak biz, negatif sayılara ihtiyaç duyan insanlar, dolayısıyla imzalar icat edildi.


4
Birçok mikroişlemcinin çeşitli işlemler için hem imzalı hem de imzasız talimatları vardır.
whatsisname

1
@whatsisname: Tersi: birçok mikroişlemcinin yalnızca imzasız talimatları vardır. Bir kaç imzalı talimat var. Bunun nedeni, 2s-tamamlayıcı aritmetik ile, bit değerinin hava durumuna bakılmaksızın veya imzasız olduğuna ve kişinin nasıl okuduğuna bakılmaksızın aynı olması nedeniyle, bir yorumlama meselesidir - bu nedenle derleyici özelliği olarak uygulamak daha kolaydır. Genellikle sadece programcıların derleyici kullanmadığını kabul eden eski mikroların montaj kodunu okunabilir yapmak için süslü imzalı talimatları vardır.
slebetman

3

Çünkü depolama için kolayca kullanılabilecek bir bit daha var ve negatif sayılar için endişelenmenize gerek yok. Bundan daha fazlası yok.

Şimdi, bu ekstra bitin nerede olacağına dair bir örneğe ihtiyacınız varsa, bakarsanız bulunacak çok şey var.

En sevdiğim örnek Satranç motorlarındaki bitboardlardan geliyor. Bir satranç tahtasında 64 kareler vardır, bu nedenle unsigned longhareket üretimi etrafında dönen çeşitli algoritmalar için mükemmel bir depolama sağlar. İkili işlemlere (vardiya işlemlerinin yanı sıra !!) ihtiyacınız olduğu düşünüldüğünde, MSB ayarlanmışsa hangi özel şeylerin gerçekleşeceği konusunda endişelenmemenizin neden daha kolay olduğunu görmek kolaydır. İmzalı uzun ile yapılabilir, ancak imzasız kullanmak çok daha kolaydır.


3

Saf bir matematik geçmişine sahip olmak, ilgilenen herkes için biraz daha matematiksel bir yaklaşımdır.

8 bit imzalı ve imzasız bir tamsayı ile başlarsak, temel olarak toplama ve çarpma söz konusu olduğunda, tamsayı modulo 256 tamsayılarıdır, 2'nin tamamlayıcısı negatif tamsayıları temsil etmek için kullanılması şartıyla (ve her modern işlemcinin yaptığı gibi) .

İşlerin farklı olduğu yerlerde iki yer vardır: biri karşılaştırma işlemidir. Bir anlamda, modulo 256 tam sayıları en iyi bir sayı çemberi olarak kabul edilir (modulo 12 tamsayıları eski moda bir analog saat yüzeyinde yaptığı gibi). Sayısal karşılaştırmaları (x <y) anlamlı kılmak için, hangi sayıların diğerlerinden daha az olduğuna karar vermemiz gerekiyordu. Matematikçinin bakış açısından, modulo 256 tamsayılarını bir şekilde tüm tamsayılar kümesine gömmek istiyoruz. İkili gösterimi tamamen sıfır olan 8 bit tamsayısının 0 tamsayısına eşlenmesi yapılması gereken en açık şeydir. Daha sonra başkalarını eşlemeye devam edebiliriz, böylece '0 + 1' (bir kaydı sıfırlama sonucu, diyelim balta ve 'inc ax' aracılığıyla birer birer artırılır) tamsayı 1'e gider ve bu şekilde devam eder. Aynısını -1 ile yapabiliriz, örneğin '0-1' ile -1 tamsayısını ve '0-1-1' eşleme -2 tamsayısına. Bu yerleştirmenin bir işlev olduğundan emin olmalıyız, bu nedenle tek bir 8 bitlik tamsayıyı iki tamsayı ile eşleştiremeyiz. Bu şekilde, tüm sayıları bir tamsayılar kümesine eşlersek, 0, 0'dan küçük ve 0'dan küçük tamsayılarla birlikte orada olacak demektir. Bunu 8 bit tamsayı ile yapmanın temelde 255 yolu vardır (buna göre 0'dan -255'e kadar istediğiniz minimum değere). Daha sonra '0 <y - x' cinsinden 'x <y' tanımlayabilirsiniz.

Donanım desteğinin mantıklı olduğu iki yaygın kullanım durumu vardır: biri sıfırdan büyük tamsayı 0'dan büyük ve biri yaklaşık 50/50 bölünmüş 0'dır. Diğer tüm olasılıklar, sayıları ekstra bir ve alt 'operasyonlardan önce ve bu ihtiyaç modern yazılımda açık bir örnek düşünemediğimden çok nadirdir (çünkü sadece 16 bit gibi daha büyük bir mantisle çalışabilirsiniz).

Diğer bir konu, 8 bitlik bir tamsayıyı 16 bitlik tamsayılar alanına eşlemektir. -1 -1'e gider mi? 0xFF'in -1'i temsil etmesi isteniyorsa, istediğiniz şey budur. Bu durumda, işaret genişletme yapılması mantıklıdır, böylece 0xFF 0xFFFF'ye gider. Öte yandan, 0xFF 255'i temsil ediyorsa, 0xFFFF yerine 255, dolayısıyla 0x00FF ile eşlenmesini istersiniz.

Bu, 'shift' ve 'aritmetik shift' işlemleri arasındaki farktır.

Bununla birlikte, sonuçta, yazılımdaki int'lerin tamsayılar değil, ikili ifadeler olduğu ve sadece bazılarının temsil edilebileceği gerçeği ortaya çıkmaktadır. Donanım tasarlanırken, donanımda yerel olarak yapılacak seçimler yapılmalıdır. 2'nin tamamlayıcısı ile toplama ve çarpma işlemleri aynı olduğundan, negatif tamsayıları bu şekilde temsil etmek mantıklıdır. O zaman sadece ikili gösterimlerinizin hangi tamsayıları temsil etmesi gerektiğine bağlı olan bir işlem meselesidir.


Matematiksel yaklaşımı seviyorum, ancak sadece belirli bir daha büyük boyuta yükseltmeyi düşünmek yerine, sonsuz uzunlukta bir ikili sayılardaki işlemler açısından genellemenin daha iyi olduğunu düşünüyorum. En sağdaki k basamağı 0 olan ve sonucun en sağdaki k basamağı 1 olan herhangi bir sayıdan 1 çıkarın ve biri sonsuz sayıda bitle matematik yapmışsa her bitin 1 olacağını indüksiyonla kanıtlayabilir. math, bir sayının alt bitleri hariç tümünü yok sayar.
supercat

2

Mevcut imzalı tamsayılarla bir CPU tasarımına imzasız tamsayı ekleme uygulama maliyetini inceleyelim.

Tipik bir CPU aşağıdaki aritmetik talimatlara ihtiyaç duyar:

  • EKLE (iki değer ekler ve işlem taşarsa bir bayrak ayarlar)
  • SUB (bir değeri diğerinden çıkarır ve çeşitli bayraklar ayarlar - bunları aşağıda tartışacağız)
  • CMP (esasen 'SUB ve sonucu at, sadece bayrakları tut')
  • LSH (sola kaydırma, taşma üzerine bir bayrak ayarlama)
  • RSH (sağa kaydırma, 1 dışarı kaydırılmışsa bir bayrak ayarla)
  • Yukarıdaki talimatların hepsinin bayraklardan taşıma / borç almayı ele alan varyantları, böylece CPU kayıtlarından daha büyük türlerde çalışmak için talimatları uygun bir şekilde zincirlemenizi sağlar.
  • MUL (çarpma, bayrakları ayarlama vb. - evrensel olarak kullanılamaz)
  • DIV (böl, bayrak ayarla vb. - birçok CPU mimarisinde bu eksiklik var)
  • Daha küçük bir tamsayı türünden (örn. 16 bit) daha büyük bir tamsayı türüne (örneğin 32 bit) geçin. İşaretli tamsayılar için buna genellikle MOVSX denir (işaret uzatmalı hareket).

Ayrıca mantıksal talimatlara ihtiyaç duyar:

  • Sıfırdaki şube
  • Şube daha büyük
  • Daha az şube
  • Taşma üzerinde şube
  • Yukarıdakilerin hepsinin olumsuzlanmış versiyonları

Yukarıdaki dalları işaretli tamsayı karşılaştırmalarında gerçekleştirmek için en kolay yol, SUB komutunun aşağıdaki bayrakları ayarlamasını sağlamaktır:

  • Sıfır. Çıkarmanın sıfır değerine neden olup olmadığını ayarlayın.
  • Taşma. Çıkarma işleminin en önemli bitten bir değer ödünç alıp almadığını ayarlayın.
  • İşaret. Sonucun işaret bitine ayarlayın.

Daha sonra aritmetik dallar aşağıdaki gibi uygulanır:

  • Sıfırdaki dal: sıfır bayrağı ayarlanmışsa
  • Daha az dal: işaret bayrağı taşma bayrağından farklıysa
  • Daha büyük dal: işaret bayrağı taşma bayrağına eşitse ve sıfır bayrağı açıksa.

Bunların olumsuzlukları, bunların nasıl uygulandığından açıkça gelmelidir.

Böylece mevcut tasarımınız imzalı tamsayıların hepsini zaten uygulamaktadır. Şimdi işaretsiz tam sayılar eklemek için ne yapmamız gerektiğini ele alalım:

  • EKLE - EKLE'nin uygulanması aynıdır.
  • SUB - fazladan bir bayrak eklememiz gerekir: taşıma bayrağı, kaydın en önemli biti dışında bir değer ödünç alındığında ayarlanır.
  • CMP - değişmez
  • LSH - değişmez
  • RSH - işaretli değerler için doğru kaydırma, en önemli bitin değerini korur. İmzasız değerler için bunun yerine sıfıra ayarlamalıyız.
  • MUL - çıktı boyutu girişi ile aynı ise, hiçbir özel işlem (x86 gereklidir yapar özel işlem var, ama sadece bir kayıt çifti içine çıkışı olduğundan, ancak bu tesisin aslında oldukça nadiren kullanıldığını not, bu yüzden olacağını imzasız türlerden daha işlemci dışında bırakmak için daha açık bir aday)
  • DIV - değişiklik gerekmez
  • Daha küçük tipten daha büyük tipe geçin - MOVZX eklemeniz gerekir, sıfır uzatma ile hareket ettirin. MOVZX'in uygulanması son derece basittir.
  • Sıfırdaki dal - değişmedi
  • Şube daha az - bayrak kümesi taşıma zaman atlar.
  • Şube daha büyük - eğer bayrak ve sıfır her ikisi de açık ise atlar.

Her durumda, değişikliklerin çok basit olduğunu ve sadece devrenin küçük bir bölümünü açıp kapatarak veya bir parçası olarak hesaplanması gereken bir değerle kontrol edilebilecek yeni bir bayrak kaydı ekleyerek gerçekleştirilebileceğini unutmayın. zaten talimatın uygulanması.

Bu nedenle, imzasız talimatlar eklemenin maliyeti çok düşüktür . Neden yapılması gerektiğine ilişkin olarak , bellek adreslerinin (ve dizilerdeki ofsetlerin) doğal olarak imzasız değerler olduğunu unutmayın. Programlar bellek adreslerini işlemek için çok zaman harcadığından, bunları doğru şekilde işleyen bir türe sahip olmak programların yazılmasını kolaylaştırır.


teşekkür ederim, bu sorumu cevaplıyor, maliyeti küçük ve talimatlar sık ​​sık faydalı
jtw

1
Çoklu hassasiyetli aritmetik yaparken imzasız çift boyutlu çarpma önemlidir ve RSA şifrelemesi gerçekleştirirken genel olarak 2 kattan daha iyi bir hız artışı için muhtemelen iyidir. Ayrıca, imzalı ve imzasız davalarda bölme farklıdır, ancak imzasız dava daha kolay ve bölünme birkaç talimat eklemenin çok fazla zarar vermeyecek kadar nadir ve yavaş olduğundan, yapılacak en basit şey sadece imzasız bölünmeyi uygulamak olacaktır. ve ardından bazı işaret işleme mantığıyla sarın.
supercat

2

İmzasız sayılar büyük ölçüde bir sargı cebir halkasına ihtiyaç duyulan durumları ele almak için mevcuttur (16 bitlik imzasız tip için, uyumlu mod 65536 tamsayıların halkası olacaktır). Bir değer alın, modülden daha az bir miktar ekleyin ve iki değer arasındaki fark eklenen miktar olacaktır. Gerçek dünyadaki bir örnek olarak, bir yardımcı sayaç bir ayın başında 9995'i okuyor ve biri 23 birim kullanıyorsa, ayın sonunda 0018'i okuyacaktır. Bir cebirsel halka tipi kullanırken, taşma ile başa çıkmak için özel bir şey yapmaya gerek yoktur. 9995'i 0018'den çıkarmak, tam olarak kullanılan birimlerin sayısı olan 0023'ü verecektir.

C'nin ilk uygulandığı makine olan PDP-11'de, imzasız tamsayı türleri yoktu, ancak işaretli türler, 65535 ile 0 arasında değil, 32767 ve -32768 arasında sarılmış modüler aritmetik için kullanılabilir. platformlar her şeyi temiz bir şekilde sarmadı; uygulamaların PDP-11'de kullanılan ikinin tamamlayıcı tam sayılarını taklit etmesini istemek yerine, dil bunun yerine çoğunlukla cebirsel halkalar gibi davranması gereken imzasız türler ekledi ve taşma durumunda işaretli tamsayı türlerinin başka şekillerde davranmasına izin verdi.

C'nin ilk günlerinde, 32767'yi (ortak INT_MAX) aşabilen ancak 65535'i (ortak UINT_MAX) aşabilecek birçok miktar vardı. Böylece, bu miktarları tutmak için imzasız tiplerin kullanılması yaygınlaşmıştır (örneğin, size_t). Ne yazık ki, dilde, cebirsel halkalar gibi davranması gereken türlere karşı ekstra bir pozitif aralığı olan sayılar gibi davranması gereken türleri ayırt etmek için hiçbir şey yoktur. Bunun yerine, dil "int" den daha küçük türleri sayılar gibi davranırken, tam boyutlu türler cebirsel halkalar gibi davranır. Sonuç olarak, aşağıdaki gibi çağrı fonksiyonu:

uint32_t mul(uint16_t a, uint16_t b) { return a*b; }

(65535, 65535) intile 16 bit (yani dönüş 1) olan sistemlerde tanımlı bir davranış int, 33 bit veya daha büyük (0xFFFE0001 dönüşü) farklı bir davranış ve "int" in herhangi bir yerde olduğu sistemlerde Tanımsız Davranış olacaktır. arasında [ gcc'nin genellikle INT_MAX + 1u ve UINT_MAX arasındaki sonuçlarla aritmetik olarak doğru sonuçlar vereceğini, ancak bazen bu tür değerlerle başarısız olan yukarıdaki işlev için kod üreteceğini unutmayın!]. Çok yardımcı değil.

Yine de, sürekli olarak sayı gibi veya cebirsel bir halka gibi sürekli davranan türlerin eksikliği, cebirsel halka türlerinin bazı programlama türleri için neredeyse vazgeçilmez olduğu gerçeğini değiştirmez.

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.