Integer Bertanda dan Tidak Ditandatangani

395

Apakah saya benar mengatakan bahwa perbedaan antara bilangan bulat yang ditandatangani dan tidak ditandatangani adalah:

  1. Unsigned dapat memiliki nilai positif yang lebih besar, dan tidak ada nilai negatif.
  2. Unsigned menggunakan bit terkemuka sebagai bagian dari nilai, sedangkan versi yang ditandatangani menggunakan bit paling kiri untuk mengidentifikasi apakah angka positif atau negatif.
  3. bilangan bulat yang ditandatangani dapat menampung angka positif dan negatif.

Adakah perbedaan lain?

Shimmy Weitzhandler
sumber
6
Karena 0 tidak positif atau negatif , lebih tepat untuk menggunakan istilah nilai non-negatif daripada nilai positif untuk bilangan bulat tidak bertanda.
Daniel

Jawaban:

344

Unsigned dapat memiliki nilai positif yang lebih besar, dan tidak ada nilai negatif.

Iya.

Unsigned menggunakan bit terkemuka sebagai bagian dari nilai, sedangkan versi yang ditandatangani menggunakan bit paling kiri untuk mengidentifikasi apakah angka positif atau negatif.

Ada berbagai cara untuk mewakili bilangan bulat yang ditandatangani. Yang paling mudah untuk divisualisasikan adalah dengan menggunakan bit paling kiri sebagai bendera ( tanda dan besarnya ), tetapi yang lebih umum adalah pelengkap dua . Keduanya digunakan di sebagian besar mikroprosesor modern - floating point menggunakan tanda dan besarnya, sedangkan aritmatika integer menggunakan komplemen dua itu.

bilangan bulat yang ditandatangani dapat menampung angka positif dan negatif.

Iya

Greg
sumber
Saya tidak yakin apakah ini teks yang tepat, tetapi saya menemukan tautan lain. Pergi ke halaman ke-9 dari PDF (itu sebenarnya halaman ke-38 buku) dan Anda dapat melihat bagian yang disebut Representasi Data (Bagian 1.3). Ini memiliki penjelasan tentang semua hal yang disebutkan di atas. lms.uop.edu.jo/lms/pluginfile.php/2420/mod_resource/content/1/…
WeirdElfB0y
92

Saya akan membahas perbedaan pada tingkat perangkat keras, pada x86. Ini sebagian besar tidak relevan kecuali Anda sedang menulis kompiler atau menggunakan bahasa assembly. Tapi itu menyenangkan untuk diketahui.

Pertama, x86 memiliki dukungan asli untuk representasi komplemen dua angka yang ditandatangani. Anda dapat menggunakan representasi lain tetapi ini akan membutuhkan lebih banyak instruksi dan umumnya membuang-buang waktu prosesor.

Apa yang saya maksud dengan "dukungan asli"? Pada dasarnya saya maksudkan bahwa ada satu set instruksi yang Anda gunakan untuk nomor yang tidak ditandatangani dan satu set yang Anda gunakan untuk nomor yang ditandatangani. Nomor yang tidak ditandai dapat duduk di register yang sama dengan nomor yang ditandatangani, dan memang Anda dapat mencampur instruksi yang ditandatangani dan yang tidak ditandatangani tanpa mengkhawatirkan prosesor. Terserah kompiler (atau programmer perakitan) untuk melacak apakah suatu nomor ditandatangani atau tidak, dan gunakan instruksi yang sesuai.

Pertama, angka komplemen dua memiliki properti yang penambahan dan pengurangannya sama dengan nomor yang tidak ditandatangani. Tidak ada bedanya apakah angkanya positif atau negatif. (Jadi, Anda hanya melanjutkan dan ADDdan SUBnomor Anda tanpa khawatir.)

Perbedaan mulai terlihat ketika datang ke perbandingan. x86 memiliki cara sederhana untuk membedakannya: di atas / di bawah ini menunjukkan perbandingan yang tidak ditandatangani dan lebih besar / kurang dari yang menunjukkan perbandingan yang ditandatangani. (Misalnya JAEberarti "Lompat jika di atas atau sama" dan tidak ditandatangani.)

Ada juga dua set instruksi perkalian dan pembagian untuk menangani bilangan bulat yang ditandatangani dan tidak ditandatangani.

Terakhir: jika Anda ingin memeriksa, katakanlah, melimpah, Anda akan melakukannya secara berbeda untuk nomor yang ditandatangani dan tidak ditandatangani.

Artelius
sumber
Apa yang Anda maksud dengan angka yang tidak ditandatangani dan ditandatangani, yang ingin saya tanyakan adalah jika saya menulis unsigned int a = 2 dan ditandatangani int b = 2, sehingga keduanya ditandatangani atau tidak, apakah nomor yang ditandatangani atau tidak ditandatangani tergantung pada jenisnya. kita menugaskannya, atau tergantung pada apakah itu memiliki tanda negatif atau tidak? Ini telah menggangguku untuk sementara waktu.
Suraj Jain
@SurajJain menandatangani dan tidak bertanda merujuk pada jenis. Mereka menunjukkan apakah mungkin variabel atau ekspresi memiliki nilai negatif.
Artelius
Saya memiliki keraguan berikut, saya telah mengajukan pertanyaan, belum ada jawaban yang memuaskan, lihat di sini, stackoverflow.com/questions/41399092/…
Suraj Jain
62

Dia hanya bertanya tentang ditandatangani dan tidak ditandatangani. Tidak tahu mengapa orang menambahkan hal-hal tambahan dalam hal ini. Biarkan saya memberi tahu Anda jawabannya.

  1. Unsigned: Ini hanya terdiri dari nilai-nilai non-negatif yaitu 0 hingga 255.

  2. Ditandatangani: Terdiri dari nilai-nilai negatif dan positif tetapi dalam berbagai format seperti

    • 0 hingga +127
    • -1 hingga -128

Dan penjelasan ini adalah tentang sistem angka 8-bit.

Ashish Kumar
sumber
17

Hanya beberapa poin untuk kelengkapan:

  • jawaban ini hanya membahas representasi bilangan bulat. Mungkin ada jawaban lain untuk floating point;

  • representasi dari angka negatif dapat bervariasi. Yang paling umum (sejauh ini - hampir universal saat ini) yang digunakan saat ini adalah pelengkap dua . Representasi lain termasuk komplemen seseorang (sangat langka) dan magnitudo yang ditandatangani (sangat jarang - mungkin hanya digunakan pada karya museum) yang hanya menggunakan bit tinggi sebagai indikator tanda dengan bit tetap mewakili nilai absolut dari nomor tersebut.

  • Ketika menggunakan komplemen dua, variabel dapat mewakili rentang yang lebih besar (per satu) dari angka negatif daripada angka positif. Ini karena nol termasuk dalam angka 'positif' (karena bit tanda tidak disetel untuk nol), tetapi bukan angka negatif. Ini berarti bahwa nilai absolut dari angka negatif terkecil tidak dapat direpresentasikan.

  • ketika menggunakan komplemen atau besaran yang ditandatangani, Anda dapat memiliki angka nol sebagai angka positif atau negatif (yang merupakan salah satu dari beberapa alasan mengapa representasi ini biasanya tidak digunakan).

Michael Burr
sumber
Jika saya menulis unsigned int a = -2, dan menandatangani int b = -2, apakah representasi yang mendasari sama, saya tahu itu tidak baik untuk memiliki nomor unsigned yang diberi nilai negatif, tetapi tetap jika saya berikan, apa yang akan menjadi representasi yang mendasarinya?
Suraj Jain
1
Minor niggle: tanda dan besarnya digunakan di IEEE floating point, jadi sebenarnya cukup umum. :-)
alastair
14

Menurut apa yang kami pelajari di kelas, bilangan bulat yang ditandatangani dapat mewakili angka positif dan negatif, sedangkan bilangan bulat yang tidak ditandatangani hanya non-negatif.

Misalnya, melihat angka 8-bit :

nilai yang tidak ditandatangani0 ke255

nilai yang ditandatangani berkisar dari -128hingga127

Ying Xiong
sumber
11

Semuanya kecuali poin 2 sudah benar. Ada banyak notasi berbeda untuk ints yang ditandatangani, beberapa implementasi menggunakan yang pertama, yang lain menggunakan yang terakhir dan yang lain menggunakan sesuatu yang sama sekali berbeda. Itu semua tergantung pada platform yang Anda gunakan.

Jasper Bekkers
sumber
Apakah itu hal kecil-endian dan big-endian?
vIceBerg
little vs big endian berkaitan dengan urutan byte pada platform. Little endian mungkin melakukan 0xFF 0xFE 0x7F sementara big endian akan melakukan 0x7F 0xFE 0xFF.
Jasper Bekkers
10

Perbedaan lainnya adalah ketika Anda mengonversi bilangan bulat dengan ukuran berbeda.

Misalnya, jika Anda mengekstrak integer dari aliran byte (katakanlah 16 bit untuk kesederhanaan), dengan nilai yang tidak ditandatangani, Anda bisa melakukan:

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

(mungkin harus melemparkan 2 nd byte, tapi aku menebak compiler akan melakukan hal yang benar)

Dengan nilai yang ditandatangani, Anda harus khawatir tentang ekstensi tanda dan lakukan:

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

Secara umum itu benar. Tanpa mengetahui lebih banyak tentang mengapa Anda mencari perbedaan, saya tidak bisa memikirkan pembeda lain antara ditandatangani dan tidak ditandatangani.

toddk
sumber
4

Di atas dan di atas yang dikatakan orang lain, di C, Anda tidak bisa melimpahi integer yang tidak ditandatangani; perilaku didefinisikan sebagai modulus aritmatika. Anda dapat melimpahi integer yang ditandatangani dan, secara teori (meskipun tidak dalam praktiknya pada sistem arus utama), overflow dapat memicu kesalahan (mungkin mirip dengan pembagian dengan kesalahan nol).

Jonathan Leffler
sumber
1
Perhatikan bahwa integer overflow yang ditandatangani tidak memicu perilaku tidak terdefinisi, dan kompiler modern sangat agresif dalam menemukan ini dan mengeksploitasinya untuk memodifikasi program Anda dengan cara yang tidak terduga tetapi secara teknis sah karena mereka boleh berasumsi bahwa perilaku tidak terdefinisi tidak akan terjadi - secara kasar. Ini jauh lebih dari masalah sekarang daripada 7 tahun yang lalu.
Jonathan Leffler
4
  1. Ya, bilangan bulat tak bertanda dapat menyimpan nilai besar.
  2. Tidak, ada berbagai cara untuk menunjukkan nilai positif dan negatif.
  3. Ya, integer yang ditandatangani dapat berisi nilai positif dan negatif.
Bhavesh
sumber
4

(sebagai jawaban untuk pertanyaan kedua) Dengan hanya menggunakan bit tanda (dan bukan komplemen 2's), Anda dapat berakhir dengan -0. Tidak terlalu cantik.

Ryan Rodemoyer
sumber
Hanya untuk menambah jawaban ini, pada dasarnya itu berarti bahwa 10 == 00 di mana kedua angka tersebut adalah basis 2.
4

Bilangan bulat yang ditandatangani di C mewakili angka. Jika adan bmerupakan variabel dari tipe integer yang ditandatangani, standar tidak akan pernah mengharuskan kompiler membuat ekspresi a+=bmenyimpan menjadi aapa pun selain jumlah aritmatika dari nilai masing-masing. Yang pasti, jika jumlah aritmatika tidak cocok a, prosesor mungkin tidak dapat meletakkannya di sana, tetapi standar tidak akan meminta kompiler memotong atau membungkus nilai, atau melakukan hal lain untuk masalah ini jika nilai melebihi batas untuk tipenya. Perhatikan bahwa meskipun standar tidak memerlukannya, implementasi C diizinkan untuk menjebak aliran aritmatika dengan nilai yang ditandatangani.

Bilangan bulat tak bertanda di C berperilaku sebagai cincin aljabar abstrak bilangan bulat yang merupakan modul kongruen dengan kekuatan dua, kecuali dalam skenario yang melibatkan konversi ke, atau operasi dengan, tipe yang lebih besar. Mengubah bilangan bulat dari ukuran apa pun menjadi tipe 32-bit yang tidak ditandatangani akan menghasilkan anggota yang sesuai dengan hal-hal yang kongruen dengan bilangan bulat itu mod 4.294.967.296. Alasan mengurangi 3 dari 2 menghasilkan 4.294.967.295 adalah bahwa menambahkan sesuatu yang kongruen ke 3 ke sesuatu yang kongruen ke 4.294.967.295 akan menghasilkan sesuatu yang kongruen dengan 2.

Jenis cincin aljabar abstrak seringkali merupakan hal yang mudah untuk dimiliki; Sayangnya, C menggunakan signness sebagai faktor penentu apakah suatu tipe harus berperilaku sebagai cincin. Lebih buruk lagi, nilai-nilai yang tidak ditandatangani diperlakukan sebagai angka daripada anggota dering ketika dikonversi ke tipe yang lebih besar, dan nilai yang tidak ditandatangani lebih kecil daripada intdikonversi ke angka ketika ada aritmatika dilakukan pada mereka. Jika vadalah uint32_tyang sama 4,294,967,294, maka v*=v;harus membuat v=4. Sayangnya, jika int64 bit, maka tidak ada yang tahu apa yang v*=v;bisa dilakukan.

Mengingat standar seperti itu, saya akan menyarankan menggunakan tipe yang tidak ditandai dalam situasi di mana seseorang ingin perilaku yang terkait dengan cincin aljabar, dan tipe yang ditandatangani ketika seseorang ingin mewakili angka. Sangat disayangkan bahwa C menarik perbedaan seperti itu, tetapi mereka adalah apa adanya.

supercat
sumber
3

Bilangan bulat tak bertanda jauh lebih mungkin menangkap Anda dalam perangkap tertentu daripada bilangan bulat yang ditandatangani. Perangkap berasal dari fakta bahwa sementara 1 & 3 di atas benar, kedua jenis bilangan bulat dapat diberi nilai di luar batas dari apa yang dapat "ditahan" dan itu akan dikonversi secara diam-diam.

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);
}

Ketika Anda menjalankan ini, Anda akan mendapatkan output berikut meskipun kedua nilai ditugaskan ke -1 dan dinyatakan berbeda.

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

Satu-satunya perbedaan yang dijamin antara nilai yang ditandatangani dan yang tidak ditandatangani dalam C adalah bahwa nilai yang ditandatangani bisa negatif, 0 atau positif, sedangkan yang tidak ditandatangani hanya bisa 0 atau positif. Masalahnya adalah bahwa C tidak mendefinisikan format tipe (jadi Anda tidak tahu bahwa integer Anda ada dalam komplemen dua). Sebenarnya dua poin pertama yang Anda sebutkan salah.

Lebih jelas
sumber
0

Anda harus menggunakan Integer yang tidak ditandatangani saat pemrograman pada Sistem Tertanam. Dalam loop, ketika tidak perlu untuk bilangan bulat yang ditandatangani, menggunakan bilangan bulat yang tidak ditandatangani akan menghemat yang diperlukan untuk merancang sistem tersebut.

Fahad Naeem
sumber