Belajar Bahasa C sharp/Bab IV
Mengenal Data dan Tipe Data
suntingOke deh, sebelum melangkah lebih jauh, lebih baik kita belajar terlebih dahulu mengenai apa sih tipe data itu. Data, adalah bentuk jamak dari Datum, yang berarti "to give" atau "to grant". Secara literal, Datum berarti sebongkah informasi. Secara istilah, data dapat disamakan dengan informasi yang diperoleh dari eksperimen atau survei yang digunakan sebagai dasar pengambilan konklusi. Dalam ilmu komputer, data merujuk kepada informasi yang dapat diproses oleh komputer, yang dapat berupa angka-angka, teks, gambar, suara, video, dan lain sebagainya yang dapat disimpan di dalam memori komputer.
Sementara itu, menurut Wikipedia, tipe data atau data type dalam bahasa pemrograman merujuk kepada definisi sekumpulan nilai dan operasi apa saja yang diizinkan terhadap nilai-nilai tersebut.
Whew! Berat nggak definisinya? Oke, seiring dengan waktu kita akan belajar bahwa sebenarnya tipe data itu nggak seberat definisinya—he-he!
Bilangan Bulat (Integer)
suntingBilangan bulat atau Integer (disebut juga sebagai int di dalam C#) hampir ditemukan di semua tipe program. Oleh karena itu, adalah penting bagi seorang programmer untuk mengetahui secara pasti apa itu integer, dan di mana letak kekuatan dan kekurangannya. Sebagai contoh, berapa sih bilangan yang dapat ditampung di dalam tipe data integer? Untuk menjawabnya, kita bisa menulis sebuah program C# yang menunjukkan jawabannya:
using System;
class Program0201
{
static void Main()
{
int x = 2;
Console.Title = "Program0201 (x=2)";
Console.WriteLine(x);
Console.WriteLine(x *= x);
Console.WriteLine(x *= x);
Console.WriteLine(x *= x);
Console.WriteLine(x *= x);
Console.WriteLine(x *= x);
Console.WriteLine(x *= x);
Console.WriteLine(x *= x);
Console.WriteLine(x *= x);
Console.WriteLine(x *= x);
Console.ReadKey();
}
}
Whew, kalau dilihat, kode sumber di atas adalah banyak yang sama. Untuk sementara, kita dapat melakukan copy-paste saja dulu deh, meski di dalam C# ada metode yang jauh lebih efisien (nanti juga akan dibahas). Oke, apa yang akan dikerjakan oleh program di atas? Program di atas akan mendeklarasikan sebuah variabel dengan nama x
dan tipe data int
, dan kita memberinya nilai 2. Dalam statemen-statemen selanjutnya akan melakukan perkalian dengan bilangan sebelumnya, dan hasilnya pun akan ditampilkan, karena di sana telah terdapat metode WriteLine()
. Nah, saat dijalankan, program tersebut akan menghasilkan tampilan seperti berikut:
Nah lho! Awalnya programnya benar menghasilkan nilai-nilai 2, 4, 16, 256, 65536, tapi habis itu, kok malah hasilnya 0? Apakah ada yang salah? Misterius, bukan? Kenapa cuma lima nilai saja yang dapat dihitung, sementara nilai keenam menghasilkan 0. Karena nilai x pada statemen keenam adalah 0, maka nilai selanjutnya adalah 0 juga, karena bagaimanapun juga 0 dikalikan dengan 0 selalu menghasilkan nilai 0!.
Nah, yang jadi pertanyaan "Kenapa 65536 dikalikan 65536 sama dengan 0?". Lalu, coba kita modifikasi nilai x=2
di dalam program di atas dengan menggunakan nilai baru x=3
, kenapa juga hasilnya negatif?
Meski nilai-nilai hasil di atas terlihat sangatlah salah, nilai-nilai tersebut tidaklah dikeluarkan oleh komputer secara acak, akibat "kegilaan". Meskipun sangatlah mengejutkan, nilai-nilai tersebut sangatlah bisa ditebak. Oleh karenanya, untuk menghindari kebingungan kita akibat adanya nilai-nilai seperti itu di dalam program "beneran" buatan kita, maka kita harus tahu bagaimana variabel dengan jenis-jenis berbeda disimpan dan dimanipulasi di dalam komputer.
Binary Digit
suntingDalam komputer digital, semua informasi dikodekan sebagai sekumpulan 'bit', sebuah kata yang berarti binary digit (digit biner). Sebuah bit adalah bentuk paling sederhana dari informasi yang disimpan di dalam komputer digital. Lebih jauh lagi, dalam perangkat keras komputer, sebuah bit merujuk kepada keberadaan tegangan listrik dan ketiadaannya. Akan tetapi, bagi manusia, kita bisa menyimbolkan nilai dari sebuah bit sebagai 0 atau 1. Saat bit tertentu bernilai 0 atau 1, maka 0 dan 1 tersebut kadang-kadang disebut sebagai keadaan dari bit tersebut atau bit state.
Sebuah bit mampu menampung dua keadaan, dan oleh karena itu bit tersebut akan mampu membedakan antara dua buah kemungkinan yang sangat jauh berbeda: Ya atau tidak. Benar atau salah. Hidup atau Mati. Halal atau Haram. Semuanya tergantung bagaimana bit tersebut digunakan. Dua buah bit akan memunculkan empat buah keadaan yang berbeda: 00, 01, 10, dan 11. Tiga buah bit dapat meningkatkan keadaan menjadi delapan buah keadaan: 000, 001, 010, 011, 100, 101, 110, dan 111. Setiap tambahan bit, akan mengakibatkan keadaan menjadi dua kali lipat lebih banyak. Untuk sebuah kumpulan bit, jumlah keadaan pun dapat dirumuskan menjadi:
2 pangkat bit
Komputer pribadi dengan prosesor Intel Pentium (Pentium, Pentium MMX, Pentium Pro, Pentium II, Pentium III, dan Pentium 4) dan keluarganya yang kompatibel seperti AMD K6 dan Athlon disebut sebagai komputer 32-bit karena memang mereka bekerja dengan menggunakan potongan-potongan data berukuran 32 bit. Sementara itu komputer dengan prosesor Intel Core, Intel Core 2, Intel Xeon, Intel Itanium, AMD Athlon 64, AMD Phenom, AMD Opteron dan Intel Itanium 2 disebut sebagai komputer 64-bit, karena memang mereka bekerja dengan menggunakan susunan 64-bit untuk satuan prosesnya. Beberapa komputer generasi awal hanya dapat menangani 8 bit sekali jalan, dan kemudian 8 bit kini disebut sebagai 1 byte. Satuan byte masih sering kita temukan di dalam komputer-komputer generasi terbaru: di dalam memori, hard disk, USB flash drive, dan ukuran berkas komputer semuanya diukur dalam satuan byte.
Seiring dengan 0 dan 1 digabungkan menjadi satu, mereka pun akhirnya mulai terlihat seperti susunan angka, dan memang hal tersebutlah yang terjadi. Seperti halnya ketika kita menulis angka desimal sebagai kombinasi dari digit-digit desimal dari 0 hingga 9, kita juga bisa menulis angka biner dengan menggunakan kombinasi dari digit biner, yakni 0 dan 1.
Bilangan Bulat Bertanda
suntingBahasa C# menggunakan 32 bit (atau setara dengan 4 byte) untuk merepresentasikan sebuah variabel bertipe data int. Sebuah variabel bertipe data int dapat menyimpan nilai positif dan negatif, sehingga definisi formal untuk int (dalam C# Language Specification) adalah 32-bit signed integer (bilangan bulat bertanda 32-bit); kata "signed
" berarti bahwa salah satu dari bit-bit tersebut menandakan apakah sebuah angka yang dimaksud adalah negatif atau positif. Karena int memiliki 32 bit, maka ia dapat menyimpan hingga 2 pangkat 32 nilai yang berbeda (tepatnya 4.294.967.296) Nilai-nilai tersebut dapat dibagi hampir sama rata antara bilangan positif dan negatif. Mengapa saya katakan "hampir sama rata", karena memang di sana jumlah nilai positif lebih sedikit dibandingkan dengan nilai negatif, dan hal tersebut dikarenakan salah satu dari kombinasi-kombinasi bit haruslah mampu merepresentasikan 0. Nilai 0 desimal jika direpresentasikan dalam tipe data int sama dengan 32 buah angka 0 yang disusun seperti :
0000-0000-0000-0000-0000-0000-0000-0000
Lho, kenapa ada tanda stripnya? Itu hanyalah untuk memudahkan kita untuk membacanya, karenanya saya membaginya ke dalam kelompok bit berjumlah 4 digit. Dari angka 0, kita dapat memulai penghitungan hingga angka-angka positif lainnya:
0000-0000-0000-0000-0000-0000-0000-0001 ekuivalen dengan 1 desimal 0000-0000-0000-0000-0000-0000-0000-0010 ekuivalen dengan 2 desimal 0000-0000-0000-0000-0000-0000-0000-0011 ekuivalen dengan 3 desimal 0000-0000-0000-0000-0000-0000-0000-0100 ekuivalen dengan 4 desimal 0000-0000-0000-0000-0000-0000-0000-0101 ekuivalen dengan 5 desimal 0000-0000-0000-0000-0000-0000-0000-0110 ekuivalen dengan 6 desimal 0000-0000-0000-0000-0000-0000-0000-0111 ekuivalen dengan 7 desimal 0000-0000-0000-0000-0000-0000-0000-1000 ekuivalen dengan 8 desimal
dan seterusnya, dan seterusnya. Setiap angka-angka biner tersebut merupakan angka sebelumnya ditambah dengan 1. Menambah sebuah angka biner sama saja seperti menambah angka desimal: kita dapat memulainya dari digit paling kanan, dan bekerja hingga ke kiri. Di dalam bilangan biner, 0 ditambah 0 sama dengan 0, 0 ditambah 1 sama dengan 1, dam 1 ditambah 1 sama dengan 10. Coba Anda tuliskan di kertas, kira-kira berapa nilai biner untuk 9 hingga 16?
Seperti yang telah kita ketahui, bahwa setiap bilangan desimal yang merepresentasikan nilai pangkat 10 (seperti halnya 10/sepuluh, 100/seratus, 1000/seribu, 10000/sepuluh ribu, atau bahkan 10000000000/satu miliar) terdiri atas 1 yang diikuti dengan satu nol/0 atau banyak nol. Bilangan biner juga sama: bilangan biner yang merepresentasikan nilai dari pangkat 2 ditulis sebagai sebuah bit 1 yang diikuti dengan satu nol hingga banyak nol. Sebagai contoh:
0000-0000-0000-0000-0000-0001-0000-0000
sama dengan 256 atau 28 dan
0000-0000-0000-0001-0000-0000-0000-0000
sama dengan 65.536 atau 216.
Fakta apa yang bisa kita ambil dari kejadian di atas? Ya, kita bisa mengubah bilangan biner menjadi bilangan desimal dengan mudah. Setiap digit di dalam bilangan biner akan merepresentasikan pangkat 2. Sebuah bilangan biner dengan lima buah bit bernilai 1 seperti di bawah ini:
0000-0000-0000-0001-0000-0010-0000-1101
adalah hasil penjumlahan dari lima buah bilangan biner dasar pada tempat di mana setiap bit bernilai 1:
0000-0000-0000-0000-0000-0000-0000-0001 atau 20 atau 1 0000-0000-0000-0000-0000-0000-0000-0100 atau 22 atau 4 0000-0000-0000-0000-0000-0000-0000-1000 atau 23 atau 8 0000-0000-0000-0000-0000-0010-0000-0000 atau 29 atau 512 0000-0000-0000-0001-0000-0000-0000-0000 atau 216 atau 65536
Maka totalnya adalah 1 + 4 + 8 + 512 + 65536 = 66061 dalam bilangan desimal.
Saat kita terus mengubah semua digit dalam susunan angka 32-bit, maka kita pada akhirnya akan mendapatkan:
0111-1111-1111-1111-1111-1111-1111-1111
atau setara dengan 2.147.483.647.
Oke kita berhenti sejenak di sini terlebih dahulu. Di dalam contoh di atas, kita melihat mengapa sih semua bit pertama dari angka 32-bit tersebut masih merupakan angka 0? Sebenarnya apa yang kita lakukan adalah mencari nilai kombinasi dari 31 bit lainnya. Dan kita menemukan ada 231 atau 2.147.483.648 kombinasi, yang merepresentasikan angka desimal dari 0 hingga 2.147.483.647. Dengan 31 bit, kita tidak dapat menghitung semua angka hingga 2.147.483.648 karena kita membutuhkan sebuah kombinasi bit yang merepresentasikan angka 0. Jadi, angka 2.147.483.647 merupakan angka positif tertinggi yang bisa dicapai dengan menggunakan 32-bit bilangan bulat bertanda (32-bit signed integer). Bilangan tersebut setara dengan 231-1.
Bit yang terletak pada sisi paling kiri, lazim dikenal dengan high bit, atau most significant bit (MSB), dan saat membicarakan bilangan bulat bertanda (signed integer), bit yang terletak pada sisi paling kiri juga disebut sebagai bit penanda. Setiap angka dengan bit penanda 1 adalah negatif, sementara setiap angka dengan bit penanda 0 adalah positif. Cara yang dapat digunakan untuk merepresentasikan bilangan bulat negatif di dalam komputer digital modern disebut juga dengan komplemen dua, yang merujuk pada teknik yang digunakan untuk mengubah antara bilangan positif dan negatif. Coba perhatikan daftar angka berikut ini, yang merupakan susunan bilangan bulat negatif dengan panjang 32-bit:
1000-0000-0000-0000-0000-0000-0000-0000 sama dengan -2.147.483.648 1000-0000-0000-0000-0000-0000-0000-0001 sama dengan -2.147.483.647 1000-0000-0000-0000-0000-0000-0000-0010 sama dengan -2.147.483.646 1000-0000-0000-0000-0000-0000-0000-0011 sama dengan -2.147.483.645
Sebelumnya, saya pernah menyebutkan mengenai cara bagaimana menaikkan angka biner. Jika kita menambahkan 1 pada setiap biner ke dalam angka-angka di atas, kita akan memperoleh nilai yang lain. Tidak ada perbedaan di dalam peraturan penjumlahan hanya karena salah satu angka tersebut dianggap negatif. Coba, teruskan hingga menyentuh angka 0:
1111-1111-1111-1111-1111-1111-1111-1100 sama dengan -4 1111-1111-1111-1111-1111-1111-1111-1101 sama dengan –3 1111-1111-1111-1111-1111-1111-1111-1110 sama dengan –2 1111-1111-1111-1111-1111-1111-1111-1111 sama dengan –1
Sekarang, jika kita tambahkan satu bilangan 1 lagi untuk mencapai nilai 0, maka kita akan menjadikan bilangan tersebut bilangan 33-bit:
1-0000-0000-0000-0000-0000-0000-0000-0000
Akan tetapi, kita sedang berurusan dengan angka 32-bit di sini, dan bit yang ke-33 pun dapat diabaikan. Menambahkan 1 dengan -1 akan menghasilkan bilangan berikut:
0000-0000-0000-0000-0000-0000-0000-0000
Atau merupakan angka 0, tempat kita mulai.
Saat berurusan dengan komplemen dua dalam bilangan bulat bertanda, kita akan melakukan negasi (yakni pengubahan sebuah angka dari bilangan positif menjadi bilangan negatif dan sebaliknya) dalam dua langkah. Langkah pertama adalah kita memutar semua bit yang ada, yang bisa dilakukan dengan menjadikan semua bit bernilai 1 menjadi bit bernilai 0, dan semua bit bernilai 0 menjadi bit bernilai 1. Jika sudah, selanjutnya kita menambahkan angka 1 di depannya. Oke, sekarang jelas kan, bahwa sebuah bilangan bulat 32-bit bertanda dapat memiliki jangkauan dari -2.147.483.648 hingga 2.147.483.647. Beberapa perhitungan (seperti halnya bilangan 65.536 dikalikan dengan bilangan 65.536 seperti di dalam program0201 kita di atas), akan menghasilkan sebuah nilai di luar daya tampungnya, yakni 4.294.967.296, yang jika dikonversikan ke dalam bilangan binernya memiliki 33 bit:
1-0000-0000-0000-0000-0000-0000-0000-0000
Akan tetapi, karena hanya 32-bit saja jatah yang tersedia untuk menyimpan hasilnya, hanya 32-bit terendah lah yang dipertahankan. Bilangan 1 yang terletak di kiri yang merupakan bit yang paling signifikan akan diabaikan dan dibuang, sehingga hasil akhirnya adalah 0. Sehingga, saat berurusan dengan bilangan bulat berukuran 32-bit, nilai 232 pun akan bernilai 0.
Sekilas, representasi 32-bit tersebut seolah-olah menjadi sebuah lingkaran setan. Saat kita menambahkan 1 kepada nilai biner -1, dan mempertahankan hanya 32-bit bit terbawah, maka kita akan mendapatkan 0. Hal tersebut normal saja. Akan tetapi, berikut adalah nilai dalam bilangan biner dari 2.147.483.647:
0111-1111-1111-1111-1111-1111-1111-1111
dan, saat menambahkan 1 ke dalam nilai tersebut, hasilnya adalah:
1000-0000-0000-0000-0000-0000-0000-0000
atau sama dengan -2.147.483.648. Dengan kata lain, kode di bawah ini:
int A = 2147483647;
Console.WriteLine(A + 1);
Akan menampilkan hasil:
–2147483648
Dalam versi Program0201 yang kita modifikasi dengan mengubah nilai x menjadi 3, saat nilai 43.046.721 dikalikan dengan dirinya akan menghasilkan sebuah bilangan negatif. Lho kok bisa? Kita cari tahu yuk! Representasi biner dari bilangan 43.046.721 adalah:
0000-0010-1001-0000-1101-0111-0100-0001
Normalnya, jika kita mengalikan bilangan tersebut dengan dirinya sendiri akan menghasilkan 1.853.020.188.851.841, atau jika direpresentasikan dalam bilangan biner, hasilnya adalah:
0110-1001-0101-0100-1111-1110-0010-0001-1110-0011-1110-1000-0001
Akan tetapi, karena saat itu nilai X direpresentasikan di dalam bilangan bulat 32-bit, maka hanya 32-bit bit terendah sajalah yang akan dianggap dalam perhitungan tersebut:
1110-0010-0001-1110-0011-1110-1000-0001
Kalau kita lihat, bit tertingginya adalah 1, yang berarti bahwa bit tersebut adalah bilangan negatif. Untuk mencari berapa sih nilainya, balikkan saja semua bitnya menjadi:
0001-1101-1110-0001-1100-0001-0111-1110
Lalu, tambahkan 1:
0001-1101-1110-0001-1100-0001-0111-1111
Dan hasilnya adalah 501.334.399, yang berarti hasil perkalian dari 43.046.721 dengan dirinya sendiri akan dipotong menjadi 32-bit, yakni -501.334.399. Coba lihat, berapa hasilnya? Sama tidak?
Overflow dan Underflow
suntingKok, ada anomali ya? Katanya komputer barang yang canggih, tapi kenapa ya? Sebelumnya saya pernah katakan bahwa komputer adalah barang yang bego, yang tidak akan bergerak tanpa ada instruksi! Komputer, hanya bisa kita anggap sebagai budak saja lah. Lalu kenapa terjadi anomali, karena di sana terjadi apa yang disebut dengan overflow dan underflow. Nah lho apa lagi tuh? Kejadian overflow akan terjadi saat nilai sebuah bilangan bulat melebihi nilai positif maksimumnya, sementara underflow akan terjadi saat nilai sebuah bilangan bulat kurang dari nilai negatif minimumnya. Tapi, para programmer seringnya menggunakan kata "overflow" saja untuk menjelaskan kedua fenomena tersebut. Program-program C# pada dasarnya mengizinkan adanya overflow, karena C# dapat melakukan penjumlahan, pengurangan perkalian, dan pembagian terhadap bilangan bulat tanpa adanya kekhawatiran apakah nantinya hasilnya dapat ditampung pada ruangan 32-bit atau tidak. Mengabaikan overflow dalam melakukan perhitungan aritmetika terhadap bilangan bulat adalah sebuah cara yang paling efisien dan paling cepat dilakukan oleh komputer. Komputer, namanya saja budak bego, akan terus saja meneruskan perhitungan tersebut tanpa harus berhenti sejenak untuk mengecek apakah terjadi overflow atau tidak.
Meskipun beberapa program aplikasi mungkin dapat mengambil keuntungan dari overflow bilangan bulat, dalam banyak kasus, overflow menjadi sebuah masalah dan dianggap menjadi sebuah bug di dalam kode kita. Sebagai contoh, program sebuah bank yang menerima uang hingga miliaran rupiah, adalah sebuah program yang tidak menerima overflow, karena ketika seorang nasabah memiliki hutang 2.147.483.647 rupiah dalam saldo, lalu ada bunga 1 rupiah, maka saldonya akan berubah menjadi 2.147.483.648, yang berarti hal tersebut berubah menjadi keuntungan buat si penghutang tersebut. Siapa penjahatnya? Bukannya teller atau kasir, tapi overflow lah yang jadi penjahatnya.
Teknik pertama melibatkan kompiler C# itu sendiri. Kita dapat menginstruksikan kompiler C# untuk membuat kode yang mampu melakukan pengecekan terhadap overflow terhadap bilangan bulat. Ini merupakan contoh dari opsi kompiler. Untuk mengilustrasikannya, marilah kita kembali ke contoh program Program0201.cs.
Jika kita menggunakan Microsoft Visual Studio atau Microsoft Visual C# Express Edition, bukalah jendela properti Program0201 dengan cara mengklik kanan pada proyek yang bersangkutan lalu memilih menu Properties. Pada Project Properties yang keluar selanjutnya, bukalah tab Build. Di sana ada sebuah tombol Advanced, dan tekanlah tombol tersebut untuk memunculkan Advanced Build Settings seperti yang terlihat pada gambar berikut. Centanglah checkbox Check for arithmetic overflow/underflow. Lalu tekan OK untuk menutup kotak dialog tersebut.
Lakukan kompilasi, dan jalankan programnya. Saat program Program0201 berjalan, program tersebut akan menampilkan lima buah baris pertama, sebelum akhirnya akan memunculkan sebuah eksepsi.
Kita juga sebenarnya bisa melakukan pengecekan terhadap overflow pada ekspresi-ekspresi secara individual di dalam kode sumber dengan menggunakan operator checked. Statemen berikut:
B = checked(5 * A);
akan mengeluarkan sebuah eksepsi, meskipun kita telah membuang tanda centang pada opsi Check for arithmetic overflow/underflow, jika memang di dalam ekspresi tersebut akan menghasilkan sebuah nilai yang berada di luar jangkauan. Lawan dari operator checked
adalah unchecked
, sehingga ekspresi di atas diubah menjadi seperti:
B = unchecked(5 * A);
sehingga ekspresi tersebut tidak akan mengeluarkan eksepsi, meski opsi Check for arithmetic overflow/underflow kita telah centang.
Kita juga bisa menggunakan operator checked
dan unchecked
dalam sebuah blok kode (yang diapit oleh tanda kurung keriting {
dan }
). Perhatikan contoh berikut:
checked
{
A += 1000000;
B = B * A;
}
Setiap statemen yang berada di dalam blok tersebut yang nantinya akan menghasilkan overflow dalam operasi aritmetika akan mengeluarkan eksepsi. Operator unchecked juga bisa digunakan sebagai lawan dari checked
.
Pilihan ketiga adalah dengan menggunakan pilihan kompiler C# (csc.exe) dengan tambahan switch /checked+
untuk mengaktifkan proses pengecekan atau /checked-
untuk menonaktifkan proses pengecekan.
csc.exe Program0201.cs /checked+
(perintah ini sama saja dengan opsi Check for arithmetic overflow/underflow dalam SharpDevelop atau IDE lainnya.)
Jadi, kita punya banyak pilihan. Kita juga bisa mengizinkan kalkulasi aritmetika untuk terus maju tanpa memperhatikan kemunculan overflow (yang mungkin akan menyebabkan kesalahan di dalam hasilnya), atau kita bisa menghentikan kalkulasi seperti ini untuk menyebabkan sebuah eksepsi. Untuk saat ini, memang tidak ada pilihan lagi, karena memang eksepsi bisa menghentikan proses eksekusi program. (sebenarnya ada sebuah cara tentang bagaimana sebuah program dapat mendeteksi kapan eksepsi dapat dimunculkan dan dapat kembali ke dalam proses eksekusi saat program selesai melakukan eksekusi. Tapi saat ini kita belajar ini dulu saja ya).
Mungkin, kita berkata "ah lebih baik gunakan opsi /checked+
saja lah, biar nantinya program yang saya buat nggak akan muncul overflow, toh overflow akan mematikan program saya!" Jujur saja, saya menentang hal tersebut! Mengaktifkan pengecekan overflow untuk semua operasi aritmetika dapat menurunkan performa dan kecepatan program yang kita buat. Oke, yang saya tentang adalah ketika kita membuat program untuk didistribusikan ke pengguna, kita mengaktifkan opsi pengecekan overflow, tapi saat kita mengembangkan program kita, ya nggak apa-apa lah! Toh yang menggunakan program, kita-kita juga. Saran saya, gunakan saja operator checked
dan unchecked pada statemen dan ekspresi yang mungkin akan membuat eksepsi overflow, daripada menggunakan opsi /checked+
atau /checked-
, sebelum kita belajar mengenai penangan eksepsi secara lebih elegan!
Bilangan Bulat Bertanda
suntingWhew! Mungkin yang ada di dalam pikiran kita, kenapa sih saya menggunakan int melulu seolah-olah C# hanya mendukung int
? Oke deh. Saya kembali ke jalan lagi. Tipe data int
memang merupakan tipe data yang paling populer, akan tetapi sebenarnya, C# mendukung keberadaan tipe data lainnya lho.
Anggap kita sedang menangani data populasi manusia di Indonesia. Pasti, tidak ada penduduk yang dianggap negatif oleh komputer, sehingga kenapa juga kita menggunakan signed integer? Lagian, kita juga nggak bakal menggunakan setengah nilai dari total nilai yang disediakan oleh signed integer (berarti semiliar data, wow! Padahal Indonesia kan cuma 250 juta jiwa doang). Lalu, apa dong yang bisa digunakan? Kita bisa menggunakan unsigned integer (bilangan bulat tidak bertanda), ketimbang kita menggunakan bilangan signed integer (bilangan bulat bertanda).
Bahasa C# mendukung tipe data bilangan bulat tidak bertanda berukuran 32-bit, yang disebut dengan uint
. Cara bacanya: "you int". Kita bisa mendeklarasikan uint sebagaimana kita mendeklarasikan int
, dengan cara:
uint A;
Bilangan bulat tak bertanda tidak memiliki bit penanda (sign bit). Bit yang paling kiri (most significant bit) akan dianggap sama seperti halnya bit yang lain. Seperti halnya int
, uint
juga dimulai dari 0:
0000-0000-0000-0000-0000-0000-0000-0000
Dan terus menerus naik hingga nilai maksimum dari int
:
0111-1111-1111-1111-1111-1111-1111-1111 atau setara dengan 2.147.483.647
Akan tetapi, tidak seperti int
, uint
akan terus menerus mendapatkan nilai positif:
1000-0000-0000-0000-0000-0000-0000-0000 atau setara dengan 2.147.483.648
Hingga nilai maksimum positifnya:
1111-1111-1111-1111-1111-1111-1111-1111 atau setara dengan 4.294.967.295
sehingga, tipe data uint dapat menyimpan nilai dari 0 hingga 4.294.967.295 (232-1). Sebuah tipe data uint
saat ini mampu menangani data populasi orang Indonesia, dan mungkin semua negara di dunia. Akan tetapi, saat harus menghadapi jumlah populasi seluruh manusia di Bumi, uint pun takluk!
Sama seperti tipe data int, uint juga dapat terkena "kutukan" overflow dan underflow. Perhatikan contoh di bawah ini:
uint A = 4294967295;
A += 1;
Variabel A akan menghasilkan nilai 0 jika pengecekan overflow terhadap integer tidak dilakukan, atau bernilai 1 saat pengecekan overflow dilakukan.
Bilangan bulat kurang dari 32-bit
suntingKita juga bisa menggunakan bilangan bulat yang lebih kecil daripada 32-bit. Jika bilangan bulat 64-bit dinamakan dengan long
(yang berarti panjang dalam bahasa Inggris), maka lawan dari long
adalah short
. Untuk bilangan short
tidak bertanda, digunakanlah tipe data ushort
. Panjangnya berapa sih si short
ini? Dalam C#, short
memiliki panjang hingga 16-bit, sehingga mampu menampung nilai dari 0 hingga 65536. Tipe data short bertanda memiliki jangkauan dari -32768 hingga 32767, sementara tipe data ushort
memiliki jangkauan dari 0 hingga 65536.
Selain short
dan ushort
, C# juga memiliki sebuah tipe data lagi yang digunakan untuk menyimpan bilangan bulat dengan panjang 8-bit, sehingga totalnya mampu menampung 256 buah angka. Seperti halnya bilangan bulat lainnya, tipe data ini juga terbagi atas dua buah jenis, yakni bertanda (sbyte
) dan tidak bertanda (byte
). Tipe data sbyte
dapat memiliki nilai dari -127 hingga 128, sementara byte dapat memiliki nilai dari 0 hingga 255.
Tipe-tipe data seperti int
, long
, dan short
semuanya merupakan tipe data bilangan bulat bertanda; sementara uint
, ulong
, dan ushort
merupakan tipe data bilangan bulat tak bertanda. Kita bisa membedakan antara keduanya dengan melihat keberadaan huruf "u
" di sana. Akan tetapi, untuk bilangan bulat 8-bit, penamaannya dibalik: byte
merupakan tipe data bilangan bulat tidak bertanda, sementara sbyte
merupakan bilangan bulat bertanda.
Beberapa pertimbangan
suntingSecara umum, meski jika sebuah variabel tertentu hanya digunakan untuk menyimpan bilangan bulat dengan nilai kurang dari 32767, kita lantas nggak harus menggunakan short ketimbang int. Prosesor 32-bit modern saat ini dapat menangani nilai 32-bit dengan lebih mudah dan efisien jika dibandingkan dengan 16-bit.
Rumus umum yang bisa digunakan untuk menulis variabel bilangan bulat adalah “saat membutuhkan bilangan bulat, mulailah dari int.” Tipe data int mungkin menjadi pilihan terbaik untuk sebagian besar kebutuhan terhadap bilangan bulat yang kita butuhkan. Jika memang kita membutuhkan nilai yang lebih besar lagi, maka gunakanlah long.
Tipe data Integer dan .NET Framework
suntingPada Modul 2, saya menyebutkan bagaimana caranya untuk mengakses dokumentasi yang terdapat di dalam .NET Framework. Jika kita telusuri ruang nama System di dalam dokumentasi .NET Framework, kita akan menemukan sebuah struktur dengan nama Int32. Nama "int
" dalam C# sebenarnya merupakan alias (singkatan atau nama lain yang lebih pendek) bagi struktur System.Int32
yang terdapat di dalam .NET Framework. Tujuh tipe data bilangan bulat lainnya juga merupakan alias untuk struktur-struktur lainnya. Ketimbang kita menggunakan sebuah variabel dengan menggunakan bahasa C#:
kita juga bisa mendeklarasikannya dengan menggunakan nama struktur .NET:
System.Int32 A;
Kedua statemen di atas adalah 100% sama! Atau, bahkan jika kita telah menggunakan direktif:
using System;
pada bagian atas kode kita, kita bahkan menyingkat pendeklarasian bilangan bulat bertanda berukuran 32-bit dengan menggunakan statemen:
Int32 A;
Dan sekarang, ketimbang kita mengatakan bahwa kita mendeklarasikan sebuah variabel dengan tipe data int
, atau kita membuat objek dengan tipe data int
, kita juga bisa menyebut hal tersebut sebagai pembuatan sebuah kejadian (instance) dari struktur System.Int32
. Whew! Apa lagi tuh? Tapi, jika Anda bertanya kepada para programmer bahasa berorientasi objek, mereka akan menjawab pilihan ketiga, ketimbang pilihan pertama dan kedua.