Yang mana kasus ketika tipe data 'uint' dan 'pendek' lebih cocok daripada standar int (32)?


24

Saya memahami perbedaan dalam kapasitas dan nilai-nilai yang dapat mereka wakili, tetapi sepertinya orang selalu menggunakan Int32terlepas dari apakah itu sesuai atau tidak. Tidak seorang pun tampaknya menggunakan versi yang tidak ditandatangani ( uint) meskipun banyak waktu yang cocok karena menggambarkan nilai yang tidak boleh negatif (mungkin untuk mewakili ID dari catatan basis data). Juga, tidak ada yang tampaknya menggunakan short/Int16terlepas dari kapasitas nilai yang diperlukan.

Secara objektif, apakah ada kasus-kasus di mana lebih baik digunakan uintatau short/Int16dan jika ya, yang mana?


13
Popularitas tidak selalu merupakan metrik yang layak untuk mengevaluasi keputusan desain perangkat lunak. Hanya karena suatu latihan populer tidak berarti bahwa itu adalah praktik yang sesuai untuk aplikasi khusus Anda, atau bahkan itu adalah praktik yang baik.
Robert Harvey


1
Jawaban singkatnya, saya pikir, adalah bahwa para programmer telah terbiasa dengan semantik yang ditandatangani dan cenderung untuk menganggapnya, bahkan ketika berhadapan dengan tipe yang tidak ditandatangani (dan dengan demikian semantik yang tidak ditandatangani). Kebanyakan orang menganggap itu masalah programmer yang malas atau tidak berpendidikan, tetapi programmer yang dimaksud mungkin sebenarnya sangat berpendidikan dan sangat berhati-hati dan ingin menghindari perangkap yang halus. Jika Anda suka, lihat soundsoftware.ac.uk/c-pitfall-unsigned dan anteru.net/2010/05/17/736 .
Theodoros Chatzigiannakis

Dalam nomor yang tidak ditandatangani, tandanya lebih nulldari positif atau negatif. Jika Anda menganggapnya sebagai sesuatu yang tidak pernah bisa negatif atau selalu positif, Anda akan terkejut (dan sering marah) pada hasilnya karena itu tidak benar-benar bekerja seperti itu, terutama jika dibandingkan dengan atau dikurangi dengan / dari nilai yang ditandatangani.
Adam D. Ruppe

1
Dalam pengalaman saya banyak programmer, yang pernah diprogram dalam bahasa C cenderung peduli byte, masih hari ini, dari memori GB dan ruang penyimpanan.
user1451111

Jawaban:


25

Saya menduga Anda mengacu pada perspektif yang diwarnai oleh pengalaman Anda sendiri di mana Anda belum bekerja di sekitar orang-orang yang menggunakan tipe integral dengan benar. Ini mungkin kejadian biasa, tetapi sudah menjadi pengalaman saya bahwa orang-orang juga menggunakannya dengan benar.

Manfaatnya adalah ruang memori dan waktu cpu, mungkin juga ruang IO tergantung pada apakah jenisnya pernah dikirim melalui kabel atau ke disk. Jenis yang tidak ditandatangani memberi Anda pemeriksaan kompiler untuk memastikan Anda tidak akan melakukan operasi tertentu yang tidak mungkin, ditambah memperluas rentang yang tersedia sambil mempertahankan ukuran yang lebih kecil untuk kinerja yang lebih tinggi di mana mungkin diperlukan.

Penggunaan yang benar adalah seperti yang Anda harapkan - kapan pun Anda tahu pasti Anda dapat menggunakannya secara permanen (jangan membatasi tanpa kepastian atau Anda akan menyesal nanti).

  • Jika Anda mencoba untuk mewakili sesuatu yang tidak pernah bisa menjadi negatif ( public uint NumberOfPeople) gunakan tipe yang tidak ditandatangani.
  • Jika Anda mencoba untuk mewakili sesuatu yang tidak pernah bisa lebih dari 255 ( public byte DamagedToothCount), gunakan byte.
  • Jika Anda mencoba untuk mewakili sesuatu yang secara wajar bisa lebih besar dari 255, tetapi tidak pernah dalam jumlah ribuan , gunakan short ( public short JimmyHoffasBankBalance).
  • Jika Anda mencoba merepresentasikan sesuatu yang bisa ratusan ribu, bahkan jutaan, tetapi tidak mungkin mencapai miliaran, gunakan int ( public int HoursSinceUnixEpoch).
  • Jika Anda tahu pasti angka ini mungkin memiliki nilai besar tanpa batas atau Anda pikir itu mungkin memiliki miliaran, tetapi Anda tidak yakin berapa miliar, lama adalah taruhan terbaik Anda. Jika lama tidak cukup besar Anda memiliki masalah yang menarik dan harus mulai melihat angka presisi yang sewenang-wenang ( public long MyReallyGreatAppsUserCountThisIsNotWishfulThinkingAtAll).

Alasan ini dapat digunakan di seluruh dalam memilih antara ukuran yang ditanda tangani, tidak ditandatangani, dan beragam jenis, hanya berpikir tentang kebenaran logis dari data yang Anda wakili dalam kenyataan.


11
+1, meskipun saya harus memperjelas bahwa "nomor" telepon bukan angka, tetapi serangkaian digit dan pemformatan opsional. Anda tampaknya menyadari hal ini, tetapi kami tidak ingin memberikan contoh yang buruk, bukan? Juga, secara sewenang-wenang membatasi rentang nilai tertentu adalah antipattern jangka pendek - di intmana - mana kecuali Anda tahu fakta bahwa domain masalah sebenarnya membatasi nilai - tidak ada bank yang ingin membatasi akun dengan keras hingga 33 ribu pound (dan memikirkan kesenangannya) ketika itu meluap ...!).
Amon

3
New Life Goal: Over-draft yang cukup besar yang meremehkan tipe integral dari rekening bank saya.
recursion.ninja

11
Ada alasan bagus untuk tidak menggunakan jenis yang tidak ditandatangani di tempat-tempat tertentu, misalnya, ketika aritmatika dicampur antara yang ditandatangani dan yang tidak ditandatangani. Lihat Apa praktik terbaik terkait int yang tidak ditandatangani? .

19
Saya tidak setuju dengan alasan di sini. Jenis unsigned sering merupakan kesalahan karena pengurangan dan perbandingan menjadi tidak terduga jika Anda terbiasa int (mereka bekerja secara konsisten tetapi tidak "selalu positif"). Saya akan menghindarinya kecuali jika Anda memiliki alasan yang sangat spesifik untuk menggunakannya. Juga, mengapa ukuran penting untuk byte vs pendek vs int? Anda sering kali bahkan tidak menghemat ruang, karena struct akan membalut anggota atau array ke penyelarasan tertentu. Saya akan menggunakan byte hanya jika ukuran benar-benar penting (tidak mungkin terutama untuk kode C # yang pernah saya lihat) atau jika Anda secara khusus ingin sampul di 255 untuk sesuatu.
Adam D. Ruppe

4
"manfaatnya adalah ruang memori dan waktu cpu" ... Saya tidak melihat adanya kasus di mana tipe kecil akan benar-benar menghemat waktu CPU. Operasi integer tidak pernah menjadi lebih cepat daripada yang ada pada tipe berukuran mesin , yaitu sejauh menyangkut CPU Anda mungkin juga menggunakan long. Penghematan memori tentu saja secara tidak langsung dapat menghemat waktu dengan meningkatkan efisiensi cache-line dan sebagainya, tetapi OTOH masalah penyelarasan dengan tipe kecil dapat secara tidak langsung menghabiskan waktu.
leftaroundabout

16

Tentu, ada beberapa kasus di mana lebih baik menggunakan uintatau shortatau Int16. Ketika Anda tahu bahwa rentang data Anda akan cocok dengan batasan tipe variabel itu, maka boleh saja menggunakan tipe itu.

Dalam lingkungan yang terbatas ingatan atau ketika berhadapan dengan sejumlah besar objek, masuk akal untuk menggunakan variabel ukuran terkecil. Misalnya, ada perbedaan ukuran yang signifikan untuk satu juta elemen array ints vs. shorts.

Seringkali, itu tidak terjadi dalam kode aktual karena satu atau lebih alasan berikut:

  • Kendala data tidak diketahui sebelumnya
  • Ada kemungkinan bahwa kendala data tidak solid atau diketahui kemungkinan akan berubah
  • Ada harapan untuk menggunakan kembali fungsi dengan rentang data yang lebih luas
  • Pengembang tidak meluangkan waktu untuk memikirkan kendala
  • Penghematan memori tidak signifikan untuk dibenarkan menggunakan tipe variabel yang lebih kecil

Ada banyak alasan yang lebih mungkin, tetapi mereka sampai pada ini: Waktu yang terlibat dalam memutuskan dan menggunakan tipe variabel yang berbeda tidak memberikan manfaat yang cukup untuk membenarkan melakukannya.


8

Dalam C, dalam konteks yang tidak melibatkan promosi bilangan bulat , nilai yang tidak ditandai ditetapkan untuk berperilaku sebagai anggota dari cincin aljabar abstrak "pembungkus" (jadi untuk X dan Y, XY akan menghasilkan nilai unik yang, ketika ditambahkan ke Y, akan menghasilkan X ), ketika tipe integer yang ditandatangani ditentukan sebagai berperilaku seperti integer ketika perhitungan berada dalam kisaran tertentu, dan diizinkan untuk melakukan apa saja ketika perhitungan melampaui itu. Namun, semantik numerik dalam C # benar-benar berbeda. Ketika dalam konteks numerik yang dicentang, kedua tipe yang ditandatangani dan tidak bertanda berperilaku seperti bilangan bulat asalkan komputasi tetap berada dalam jangkauan, dan melempar OverflowExceptionketika tidak; dalam konteks yang tidak dicentang, keduanya berperilaku seperti cincin aljabar.

Satu-satunya waktu yang secara umum bermanfaat untuk menggunakan tipe data yang lebih kecil dari pada Int32saat diperlukan untuk mengemas atau membongkar barang untuk penyimpanan atau transportasi yang ringkas. Jika seseorang perlu menyimpan setengah miliar angka positif, dan mereka semua akan berada dalam kisaran 0 hingga 100, menggunakan masing-masing satu byte daripada empat akan menghemat 1,5 gigabytes penyimpanan. Itu penghematan besar. Jika sepotong kode perlu menyimpan total beberapa ratus nilai, bagaimanapun, membuat masing-masing satu byte daripada empat akan menghemat sekitar 600 byte. Mungkin tidak layak untuk diganggu.

Berkenaan dengan jenis yang tidak ditandatangani, satu-satunya waktu mereka benar-benar berguna adalah ketika melakukan pertukaran informasi, atau ketika membagi angka menjadi beberapa bagian. Jika, misalnya, seseorang perlu melakukan matematika pada bilangan bulat 96-bit, kemungkinan akan lebih mudah untuk melakukan perhitungan pada kelompok tiga bilangan bulat 32 bit yang tidak ditandatangani, daripada pada kelompok bilangan bulat yang ditandatangani. Kalau tidak, tidak ada banyak situasi di mana kisaran nilai 32- atau 64-bit yang ditandatangani tidak memadai, tetapi ukuran yang sama dari nilai yang tidak ditandatangani akan cukup.


4

Biasanya merupakan ide yang buruk untuk menggunakan tipe yang tidak ditandatangani karena mereka meluap dengan cara yang tidak menyenangkan. x = 5-6tiba-tiba bom waktu dalam kode Anda. Sementara itu manfaat dari tipe-tipe yang tidak ditandatangani mendidih menjadi satu ketelitian ekstra, dan jika bit itu sepadan untuk Anda, Anda hampir pasti akan menggunakan tipe yang lebih besar sebagai gantinya.

Ada kasus penggunaan di mana jenis yang lebih kecil bisa masuk akal, tetapi kecuali jika Anda khawatir tentang penggunaan memori atau perlu mengemas data untuk efisiensi pengiriman atau cache atau beberapa masalah lain, biasanya hal itu tidak ada gunanya menggunakan jenis yang lebih kecil. . Selain itu, pada banyak arsitektur, sebenarnya lebih lambat untuk menggunakan jenis ini sehingga mereka dapat benar-benar mengenakan biaya yang kecil.


3
Dalam C, limpahan yang ditandatangani bahkan lebih buruk daripada limpahan yang tidak ditandai (karena itu adalah perilaku yang tidak terdefinisi, sementara lign yang ditandai ditentukan untuk berguling seperti odometer). OTOH, masuk / underflow jauh lebih jarang dalam praktik daripada underflow yang tidak ditandatangani.
Kevin

Benar, tetapi limpahan yang ditandatangani biasanya lebih jelas dan dapat diprediksi.
Jack Aidley

Secara umum saya setuju, tetapi Anda perlu menyadari, misalnya, bahwa kompiler modern dapat mengoptimalkan i+1>ike 1jika iditandatangani, bersama dengan sejumlah perilaku jahat lainnya. Overflow yang tidak ditandatangani dapat menyebabkan bug di kasing sudut. Overflow yang ditandatangani dapat membuat seluruh program Anda tidak berarti .
Kevin

@JackAidley Saya cukup yakin apa yang Anda katakan tidak masuk akal, karena 5-6 menghasilkan pola bit yang sama, tidak peduli apakah itu ditandatangani atau tidak.
Ingo

@ Ingo: seberapa sering Anda melihat pola bit? Yang penting adalah artinya dari pola bit bukan bit mana yang hidup atau mati.
Jack Aidley

2

Sering dilupakan dan mungkin bersinggungan dengan pertanyaan Anda, ketika berhadapan secara khusus dengan tipe .NET, adalah Kepatuhan CLS . Tidak semua jenis tersedia untuk semua bahasa yang dibangun di .NET Framework.

Jika Anda menulis kode untuk dikonsumsi oleh bahasa selain C # dan ingin agar kode tersebut dijamin untuk beroperasi dengan sebanyak mungkin. NET bahasa, maka Anda harus membatasi penggunaan jenis Anda ke bahasa yang sesuai dengan CLS.

Misalnya, versi awal VB.NET (7.0 dan 7.1) tidak mendukung bilangan bulat yang tidak ditandatangani ( UInteger):

http://msdn.microsoft.com/en-us/library/aa903459(v=vs.71).aspx

Bilangan bulat yang tidak ditandatangani tidak sesuai dengan CLS dan karenanya harus digunakan dengan hati-hati jika Anda tidak yakin siapa pengguna perpustakaan kelas Anda.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.