2. Tipe Data, Literal, dan
Variabel
Mengapa
Tipe Data Penting
Tipe data sangat
penting dalam C# karena semua operasi diperiksa oleh kompiler tentang
kompatibilitas tipenya. Operasi yang ilegal tidak dapat dikompilasi. Hal ini
mendukung kehandalan dalam pencegahan error. Untuk mendukung kehandalan
pemrograman, semua variabel, ekspresi, dan nilai harus memiliki sebuah tipe
data. Tipe data suatu variabel menentukan operasi apa saja yang diijinkan untuk
diterapkan pada nilai variabel. Operasi yang dapat diterapkan pada suatu tipe
bisa jadi tidak dapat diterapkan pada tipe data lain.
Tipe
Data Dalam C#
C# memuat dua
kategori umum dari tipe data built-in: tipe nilai dan tipe referensi. Perbedaan
antara dua tipe itu adalah apa yang dimuat oleh suatu variabel. Untuk tipe
nilai, variabel dapat menampung suatu nilai, seperti 3.1416 atau 212. Untuk
tipe referensi, variabel dapat memuat sebuah referensi ke suatu nilai. Tipe
referensi yang paling umum dipakai adalah kelas, dan diskusi tentang kelas dan
tipe referensi akan dilakukan secara detil pada buku ini. Yang dibahas pada bab
ini hanya tipe nilai.
Tipe
|
Arti
|
bool
|
Merepresentasikan
nilai true/false
|
byte
|
Integer
tak-bertanda 8-bit
|
char
|
Karakter
|
decimal
|
Nilai numerik
untuk perhitungan keuangan
|
double
|
Titik
mengambang kepresisian ganda
|
float
|
Titik
mengambang kepresisian tunggal
|
int
|
Integer
|
long
|
Long integer
|
sbyte
|
Integer
bertanda 8-bit
|
short
|
Integer short
|
uint
|
Integer tak-bertanda
|
ulong
|
Long
tak-bertanda
|
ushort
|
Short
tak-bertanda
|
Tabel 2.1 Tipe-tipe nilai dalam C#
Dalam C#,
terdapat 13 tipe nilai seperti ditampilkan pada Tabel 2.1. Secara kolektif,
tipe nilai disebut pula dengan tipe sederhana atau tipe primitif. Disebut
dengan tipe sederhana karena hanya memuat satu nilai.
Integer
C#
mendefinisikan sembilan tiga integer: char,
byte, sbyte, short, ushort, int, uint, long, dan ulong. Tetapi, tipe char
secara umum dipakai untuk merepresentasikan karakter, dan akan didiskusikan
nanti pada akhir bab ini. Delapan tipe integer lainnya dipakai untuk
perhitungan numerik. Lebar-bidang dan rentang dari delapan tipe integer
tersebut ditampilkan di sini:
Seperti
ditunjukkan pada tabel, C# mendefinisikan versi bertanda dan tak-bertanda dari
berbagai tipe integer. Perbedaan antara integer bertanda dan tak-bertanda
adalah bagaiman bit paling signifikan (MSB, most significant bit)
diinterpretasikan. Jika integer bertanda dispesifikasi, maka kompiler C# akan
menghasilkan kode yang mengasumsikan bahwa bit paling signifikan dari suatu
integer dipakai sebagai flag. Jika tanda flag adalah 0, maka angka tersebut
positif; jika flag adalah 1, maka angka tersebut negatif. Angka negatif
direpresentasikan menggunakan pendekatan komplemen dua. Dengan metode ini,
semua bit dalam angka negatif dibalik, kemudian ditambahkan 1.
Integer bertanda
penting untuk banyak algoritma, tetapi hanya memiliki magnitudo setengah dari
versi integer tak-bertanda. Sebagai contoh, sebuah short, di sini adalah 32,767:
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
Untuk nilai
tak-bertanda, jika bit paling signifikan ditetapkan 1, maka angka tersebut akan
diinterpretasikan sebagai -1 (dalam format komplemen dua). Namun, jika Anda
mendeklarasikannya sebagai ushort,
maka ketika bit paling signifikan ditetapkan 1, angka tersebut akan menjadi
65,535.
Yang paling umum
dipakai dari tipe integer adalah int.
Variabel bertipe int seringkali
dipakai untuk mengendalikan loop, untuk mengindeks array, dan untuk kepentingan
matematika. Ketika Anda membutuhkan sebuah integer yang memiliki rentang nilai
lebih dari int, maka Anda mempunyai
banyak opsi. Jika nilai yang ingin disimpan adalah tak-bertanda, maka Anda bisa
memakai uint. Untuk nilai bertanda
yang besar, gunakan long. Untuk
nilai tak-bertanda yang besar, gunakan ulong.
Sebagai contoh, berikut adalah sebuah program yang menghitung jarak dari Bumi ke
Matahari, dalam inci. Karena nilai ini terlalu besar, program menggunakan
variabel long untuk menampungnya.
// Menghitung jarak dari
Bumi ke Matahari dalam inci.
using System;
class Inci
{
static
void Main() {
long
inci;
long
mile;
mile = 93000000; // 93,000,000 mile ke
matahari
// 5,280 kaki dalam satu mile, 12 inci
dalam satu kaki.
inci = mile * 5280 * 12;
Console.WriteLine("Jarak ke matahari : " +
inci + " inci.");
}
}
Berikut adalah
keluaran program:
Jarak ke matahari : 5892480000000 inci.
Jelaslah, hasil
yang diperoleh tidak mungkin ditampung oleh variabel bertipe int atau uint.
Tipe integer
terkecil adalah byte dan sbyte. Tipe byte merupakan nilai tak-bertanda dalam rentang 0 dan 255. Variabel
bertipe byte berguna ketika bekerja
dengan data biner, seperti aliran byte yang dihasilkan oleh divais tertentu.
Untuk integer kecil tak-bertanda, gunakan sbyte. Berikut disajikan contoh penggunaan variabel
bertipe byte untuk mengendalikan
sebuah loop for yang menghasilkan
penjumlahan angka 0 sampai 100.
// Menggunakan byte.
using System;
class Menggunakan_byte {
static
void Main() {
byte
x;
int
jum;
jum = 0;
for
(x = 1; x <= 100; x++)
jum = jum + x;
Console.WriteLine("Penjumlahan dari 0-100 adalah " +
jum);
}
}
Keluaran program
ditampilkan di sini:
Penjumlahan dari 0-100 adalah 5050
Karena loop for hanya dijalankan dari 0 sampai 100,
yang berada dalam rentang suatu byte, maka tidak diperlukan variabel bertipe
yang lebih besar untuk mengendalikannya.
Ketika Anda
memerlukan sebuah integer yang lebih besar dari byte atau sbyte, tetapi
lebih kecil dari int atau uint, Anda bisa menggunakan short atau ushort.
Tipe
Titik-Mengambang
Tipe
titik-mengambang (floating-point)
dapat merepresentasikan angka dengan komponen fraksional. Ada dua jenis tipe
titik-mengambang, float dan double, yang merepresentasikan angka
kepresisian tunggal dan kepresisian ganda. Tipe float berlebar 32 bit dan memiliki rentang berkisar 1.5E-45 sampai
3.4E+38. Tipe double berlebar 64 bit
dan memiliki rentang berkisar 5E-324 sampai 1.7E308.
Dari keduanya, double adalah yang paling umum
digunakan. Alasannya adalah bahwa banyak fungsi matematika dalam pustaka kelas
C# (yang merupakan pustaka Framework .NET) menggunakan nilai-nilai double. Sebagai contoh, metode Sqrt() (yang didefinisikan oleh kelas System.Math) menghasilkan nilai balik
bertipe double, yang merupakan akar
kuadrat dari argumen bertipe double.
Berikut disajikan Sqrt() yang
dipakai untuk menghitung radius suatu lingkaran bila diberikan luas lingkaran.
// Menemukan radius dari
luas suatu lingkaran.
using System;
class FindRadius {
static
void Main() {
Double
r;
Double
luas;
luas = 10.0;
r = Math.Sqrt(luas
/ 3.1416);
Console.WriteLine("Radius
adalah " + r);
}
}
Keluaran program
ditampilkan di sini:
Radius adalah 1.78412203012729
Seperti
disebutkan sebelumnya, Sqrt() adalah
anggota dari kelas Math. Perhatikan
bagaimana Sqrt() dipanggil; diawali
dengan nama Math. Sama dengan Console yang mengawali WriteLine().
Program berikut
mendemonstrasikan beberapa fungsi trigonometrik C#, yang juga merupakan bagian
dari pustaka matematika C#. Semua fungsi tersebut diterapkan pada data double. Program menampilkan sinus,
kosinus, dan tangent untuk sudut (dalam radian) dari 0.1 sampai 1.0.
// Mendemonstrasikan
Math.Sin(), Math.Cos(), dan Math.Tan().
using System;
class Trigonometri {
static
void Main() {
Double
theta; // sudut dalam radian
for
(theta = 0.1; theta <= 1.0; theta = theta + 0.1) {
Console.WriteLine("Sinus
dari " + theta + " adalah
" +
Math.Sin(theta));
Console.WriteLine("Kosinus
dari " + theta + " adalah
" +
Math.Cos(theta));
Console.WriteLine("Tangent
dari " + theta + " adalah
" +
Math.Tan(theta));
Console.WriteLine();
}
}
}
Berikut adalah
keluaran program:
Sinus dari 0.1 adalah 0.0998334166468282
Kosinus dari 0.1 adalah 0.995004165278026
Tangent dari 0.1 adalah 0.100334672085451
Sinus dari 0.2 adalah 0.198669330795061
Kosinus dari 0.2 adalah 0.980066577841242
Tangent dari 0.2 adalah 0.202710035508673
Sinus dari 0.3 adalah 0.29552020666134
Kosinus dari 0.3 adalah 0.955336489125606
Tangent dari 0.3 adalah 0.309336249609623
Sinus dari 0.4 adalah 0.389418342308651
Kosinus dari 0.4 adalah 0.921060994002885
Tangent dari 0.4 adalah 0.422793218738162
Sinus dari 0.5 adalah 0.479425538604203
Kosinus dari 0.5 adalah 0.877582561890373
Tangent dari 0.5 adalah 0.54630248984379
Sinus dari 0.6 adalah 0.564642473395035
Kosinus dari 0.6 adalah 0.825335614909678
Tangent dari 0.6 adalah 0.684136808341692
Sinus dari 0.7 adalah 0.644217687237691
Kosinus dari 0.7 adalah 0.764842187284489
Tangent dari 0.7 adalah 0.842288380463079
Sinus dari 0.8 adalah 0.717356090899523
Kosinus dari 0.8 adalah 0.696706709347166
Tangent dari 0.8 adalah 1.02963855705036
Sinus dari 0.9 adalah 0.783326909627483
Kosinus dari 0.9 adalah 0.621609968270665
Tangent dari 0.9 adalah 1.26015821755034
Sinus dari 1 adalah 0.841470984807896
Kosinus dari 1 adalah 0.54030230586814
Tangent dari 1 adalah 1.5574077246549
Untuk menghitung
sinus, kosinus, dan tangent, gunakan metode-metode pustaka standar Math.Sine(), Math.Cos(), dan Math.Tan().
Seperti Math.Sqrt(), semua metode
trigonometrik dipanggil dengan sebuah argumen double dan menghasilkan nilai balik bertipe double. Sudut harus dalam radian.
Tipe
Desimal
Yang paling
menarik dari tipe data numerik dalam C# adalah tipe decimal, yang dimaksudkan untuk digunakan dalam kalkulasi moneter.
Tipe decimal menggunakan 128 bit
untuk merepresentasikan nilai di dalam rentang 1E-28 sampai 7.9E+28. Seperti
Anda ketahui, aritmatika titik-mengambang sangat rentan terhadap berbagai error
pembulatan ketika diterapkan pada nilai desimal. Tipe decimal mengeliminasi error tersebut dan dapat secara akurat
merepresentasikan sampai dengan 28 posisi desimal. Kemampuan ini dipakai untuk
merepresentasikan nilai desimal tanpa error pembulatan sehingga cocok untuk
komputasi yang melibatkan uang.
Berikut
disajikan suatu program yang menggunakan tipe decimal dalam kalkulasi finansial. Program ini menghitung harga
yang telah didiskon dari harga awal dan persentase diskon.
// Menggunakan tipe decimal
untuk menghitung diskon.
using System;
class GunakanDecimal {
static
void Main() {
decimal
harga;
decimal
diskon;
decimal
harga_diskon;
// menghitung harga setelah diskon.
harga = 19000.95m;
diskon = 0.15m; // persen diskon adalah
15%
harga_diskon = harga - (harga *
diskon);
Console.WriteLine("Harga Setelah Diskon: Rp." +
harga_diskon);
}
}
Keluaran program
ditunjukkan di sini:
Harga Setelah Diskon: Rp.16150.8075
Di dalam
program, perhatikan bahwa konstanta desimal diikuti dengan sufiks m. Ini perlu karena tanpa sufiks, nilai
ini akan diinterpretasikan sebagai konstanta titik-mengambang standar, yang
tidak kompatibel dengan tipe data decimal.
Anda dapat menugaskan sebuah nilai integer, seperti 10, kepada variabel decimal tanpa menggunakan sufiks m. (Diskusi detil tentang konstanta
numerik diberikan di akhir bab).
Berikut adalah
contoh lain yang menggunakan tipe decimal.
Program ini menghitung nilai masa depan dari sebuah investasi yang memiliki
laju bunga tetap pada suatu periode (beberapa tahun).
/*
Menggunakan tipe decimal
untuk menghitung
nilai masa depan dari suatu
investasi.
*/
using System;
class NilaiMasaDepan {
static
void Main() {
decimal
investasi;
decimal
laju_bunga;
int
tahun, i;
investasi = 1000.0M;
laju_bunga = 0.07M;
tahun = 10;
Console.WriteLine("Investasi awal: Rp." + investasi);
Console.WriteLine("Laju bunga: " + laju_bunga);
Console.WriteLine("Selama " + tahun + " tahun");
for
(i = 0; i < tahun; i++)
investasi = investasi + (investasi
* laju_bunga);
Console.WriteLine("Nilai masa depan adalah Rp." +
investasi);
}
}
Keluaran program
ditampilkan di sini:
Investasi awal: Rp.1000.0
Laju bunga: 0.07
Selama 10 tahun
Nilai masa depan adalah Rp.1967.151357289565322490000
Perhatikan bahwa
hasil yang didapatkan akurat dengan 21 dijit di belakang titik desimal, mungkin
lebih dari yang Anda perlukan.
Karakter
Dalam C#,
karakter bukan suatu kuantitas 8-bit seperti di dalam banyak bahasa pemrograman
lainnya, seperti C++. C# menggunakan tipe karakter 16-bit yang dikenal dengan
Unicode. Unicode mendefinisikan himpunan karakter yang cukup besar dalam
merepresentasikan karakter dalam semua bahasa manusia. Meskipun banyak bahasa
seperti, Indonesia, English, dan French menggunakan alfabet yang relatif
sedikit, beberapa bahasa, seperti Chinese, menggunakan himpunan karakter yang
tidak bida direpresentasikan hanya dengan 8 bit. Untuk mengatasi situasi ini,
dalam C#, diberikan tipe char yang
merupakan sebuah tipe tak-bertanda 16-bit dengan rentang 0 sampai 65,535.
Himpunan karakter ASCII 8-bit standar adalah subhimpunan dari Unicode dengan
rentang 0 sampai 127. Jadi, karakter-karakter ASCII masih merupakan karaker C#
yang valid.
Variabel
karakter dapat ditugasi sebuah nilai dengan mengapit karakter dengan dua kutip
tunggal. Sebagai contoh, hal ini menugaskan X kepada variabel ch:
char ch;
ch = 'X';
Anda dapat
menampilkan nilai char menggunakan
statemen WriteLine(). Sebagai
contoh, baris ini menampilkan nilai di dalam ch:
Console.WriteLine("Ini adalah
ch: " + ch);
Meskipun char didefinisikan oleh C# sebagai
sebuah tipe integer, tipe ini tidak dapat dengan bebas dicampur dengan integer
pada semua kasus. Ini karena tidak adanya konversi tipe otomatis dari integer
menjadi char. Sebagai contoh,
fragmen berikut adalah tak-valid:
char ch;
ch = 88; // error, tak-valid
Alasannya adalah
bahwa 88 adalah sebuah nilai integer, dan nilai itu tidak secara otomatis
dikonversi menjadi sebuah char. Jika
Anda mencoba mengkompilasi kode ini, Anda akan mendapatkan pesan error. Untuk
membuat penugasan ini menjadi legal, Anda perlu menerapkan cast, yang akan didiskusikan nanti pada bab ini.
Tipe
bool
Tipe bool merepresentasikan nilai true/false. C# mendefinisikan nilai true
dan false menggunakan katakunci
reservasi true dan false. Jadi, sebuah variabel atau
ekspresi bertipe bool akan bernilai
salah satu dari dua nilai tersebut. Di samping itu, tidak ada konversi yang
didefinisikan antara bool dan nilai
integer. Misalnya, 1 tidak dikonversi menjadi true, dan 0 tidak dikonversi menjadi false.
Berikut adalah
sebuah program yang mendemonstrasikan tipe bool:
// Menggunakan nilai bool.
using System;
class DemoBool
{
static
void Main() {
bool
b;
b = false;
Console.WriteLine("b adalah " + b);
b = true;
Console.WriteLine("b adalah " + b);
// Nilai bool dapat mengendalikan
statemen if.
if
(b) Console.WriteLine("Ini dieksekusi.");
b = false;
if
(b) Console.WriteLine("Ini tidak dieksekusi.");
// Keluaran dari operator relasional
adalah nilai bool.
Console.WriteLine("10 > 9 adalah " + (10 > 9));
}
}
Keluaran program
ditampilkan di sini:
b adalah False
b adalah True
Ini dieksekusi.
10 > 9 adalah True
Ada tiga hal
menarik yang perlu diperhatikan. Pertama, seperti Anda lihat, ketika suatu
nilai bool ditampilkan dengan WriteLine(), “True” atau “False”
ditampilkan. Kedua, nilai suatu variabel bool
dapat dipakai untuk mengendalikan statemen if.
Tidak diperlukan statemen if seperti
ini:
if(b == true) ...
Ketiga, keluaran
dari suatu operator relasional, seperti <, adalah sebuah nilai bool.
Ini mengapa ekspresi 10>9 menampilkan nilai “True”. Di samping itu,
sepasang kurung untuk mengapit ekspresi 10>9 diperlukan karena operator +
mempunyai derajat keutamaan yang lebih dari >.
Beberapa
opsi Keluaran
Sampai di titik
ini, ketika data ditampilkan menggunakan statemen WriteLine(), keluarannya ditampilkan menggunakan format default.
Tetapi, Framework .NET mendefinisikan mekanisme pemformatan yang memberikan
Anda kendali untuk bagaimana data ditampilkan. Meskipun I/O terformat dirangkum
secara detil dalam buku ini, adalah hal yang bermanfaat untuk mengenalkan
beberapa opsi pemformatan. Dengan opsi ini, Anda akan mampu menetapkan
bagaimana tampilan keluaran menggunakan statemen WriteLine().
Ketika
menampilkan runtun data, Anda dapat memisahkan setiap bagian data dengan tanda
plus, seperti ditampilkan di sini:
Console.WriteLine("Anda
memesan " + 2 + " item
harga Rp." + 3 + " masing-masing.");
Meskipun cukup
nyaman, penampilan informasi numerik dengan cara ini tidak memberikan Anda
kendali dalam bagaimana menampilkan informasi. Sebagai contoh, untuk nilai
titik-mengambang, Anda tidak dapat mengendalikan jumlah desimal yang akan
ditampilkan. Perhatikan statemen berikut:
Console.WriteLine("Berikut adalah 10/3: " +
10.0/3.0);
menghasilkan
keluaran ini:
Berikut adalah 10/3: 3.33333333333333
Meskipun ini
baik untuk beberapa tujuan, menampilkan begitu banyak desimal di belakang titik
desimal bisa jadi tidak cocok untuk tujuan tertentu. Sebagai contoh, dalam
kalkulasi finansial, Anda biasanya hanya ingin menampilkan dua titik desimal di
belakang titik desimal.
Untuk
mengendalikan bagaimana data numerik diformat, Anda perlu menggunakan format
kedua dari metode WriteLine(),
seperti ditunjukkan di sini, yang membolehkan Anda untuk memformat informasi:
WriteLine(“string format”, arg0,
arg1, ... , argN);
Dalam versi ini,
argumen pada WriteLine() dipisahkan
dengan koma dan bukan tanda +. string format memuat dua item: reguler, karakter
yang akan ditampilkan, dan penspesifikasi format. Penspesifikasi format
memiliki bentuk umum:
{argnum, width: fmt}
Di sini, argnum menspesifikasi
jumlah argumen (mulai dari nol) yang akan ditampilkan. Lebar bidang minimum
dispesifikasi oleh width, dan format dispesifikasi oleh fmt. width dan fmt bersifat opsional.
Selama eksekusi,
ketika sebuah penspesifikasi format dijumpai di dalam string format, argumen
terkait, yang dispesifikasi oleh argnum, diganti dan ditampilkan. Jadi, posisi dari spesifikasi
format di dalam string format menentukan dimana data akan ditampilkan. Oleh
karena itu, dalam bentuk sederhananya, penspesifikasi format mengindikasikan
argumen mana yang akan ditampilkan. Sebagai contoh, {0} mengindikasikan arg0, {1}
mengindikasikan arg1, dan seterusnya.
Dimulai dari
contoh sederhana. Statemen
Console.WriteLine("Pebruari
mempunyai {0} atau {1} hari.", 28, 29);
menghasilkan
keluaran berikut:
Pebruari mempunyai 28 atau 29 hari.
Seperti yang
Anda lihat, nilai 28 menggantikan {0}, dan 29 menggantikan {1}. Jadi,
penspesifikasi format mengidentifikasi lokasi dimana argumen berurutan, dalam
kasus ini 28 dan 29, ditampilkan di dalam string. Di samping itu, perhatikan
nilai-nilai yang dipisahkan dengan koma, bukan dengan tanda +.
Berikut adalah
variasi dari statemen sebelumnya yang menspesifikasi lebar bidang minimum:
Console.WriteLine("Pebruari
mempunyai {0,10} atau {1,5} hari.", 28, 29);
menghasilkan
keluaran berikut:
Pebruari mempunyai 28
atau 29 hari.
Seperti yang
Anda lihat, spasi ditambahkan untuk mengisi bidang yang tidak dipakai.
Argumen yang
berkaitan dengan perintah format tidak harus konstanta. Sebagai contoh, program
ini menampilkan tabel kuadrat dan kubik, yang menggunakan perintah format dalam
menampilkan nilai.
// Menggunakan perintah
format.
using System;
class OpsiPenampilan {
static
void Main()
{
int
i;
Console.WriteLine("Nilai\tKuadrat\tKubik");
for
(i = 1; i < 10; i++)
Console.WriteLine("{0}\t{1}\t{2}", i, i * i, i * i * i);
}
}
Keluaran
ditampilkan di sini:
Nilai Kuadrat Kubik
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
Cara termudah
menspesifikasi suatu format adalah menyediakan sebuah template yang akan
digunakan WriteLine(). Untuk
melakukannya, tunjukkan contoh format yang Anda inginkan menggunakan tanda #
untuk menandai posisi dijit. Anda juga dapat menspesifikasi titik desimal dan
koma. Sebagai contoh, berikut adalah cara yang lebih baik dalam menampilkan 10
dibagi dengan 3:
Console.WriteLine("Berikut adalah 10/3: {0:#.##}", 10.0/3.0);
Keluaran dari
statemen di atas adalah
Berikut adalah 10/3: 3.33
Pada contoh
tersebut, template yang dipakai adalah #.##, yang memberitahukan WriteLine() untuk menampilkan dua dijit
di belakang titik desimal. Penting dipahami bahwa WriteLine() dapat menampilkan lebih dari satu dijit di depan titik
desimal, jika diperlukan.
Berikut adalah
satu contoh lain. Statemen
Console.WriteLine("{0:###,###.##}", 123456.56);
menghasilkan
keluaran ini:
123,456.56
Jika Anda ingin
menampilkan nilai moneter, gunakan penspesifikasi format C. Sebagai contoh,
decimal uang;
uang = 12323.09m;
Console.WriteLine("Uang saat ini adalah {0:C}", uang);
Keluarannya
adalah (format dalam dollar Amerika):
Uang saat ini adalah $12,323.09
Format C dapat pula dipakai untuk memperbaiki
keluaran dari program diskon harga yang telah diberikan sebelumnya:
// Menggunakan format C
untuk menampilkan dollar dan cent.
using System;
class GunakanDecimal2
{
static
void Main() {
decimal
harga;
decimal
diskon;
decimal
harga_diskon;
// Menghitung harga diskon.
harga = 19.95m;
diskon = 0.15m; // persen diskon 15%
harga_diskon = harga - (harga *
diskon);
Console.WriteLine("Harga setelah diskon: {0:C}",
harga_diskon);
}
}
Berikut adalah
keluaran program:
Harga setelah diskon: $16.96
Literal
Dalam C#,
literal berarti nilai tetap yang direpresentasikan dalam format bacaan manusia.
Sebagai contoh, angka 100 adalah sebuah literal. Literal dan kegunaannya telah
digunakan dalam suatu format pada beberapa contoh program sebelumnya. Sekarang
saatnya membahasnya secara formal.
Literal C# dapat
berupa sembarang tipe sederhana. Cara setiap literal direpresentasikan
bergantung pada tipenya. Seperti dijelaskan sebelumnya, literal string diapit
dengan dua tanda kutip tunggal. Misalnya, ‘a’ dan ‘%’ keduanya adalah literal
string.
Literal integer
dispesifikasi sebagai angka tanpa komponen pecahan. Sebagai contoh, 10 dan -100
keduanya adalah literal integer. Literal titik-mengambang memerlukan titik
desimal yang diikuti dengan komponen pecahan. Sebagai contoh, 11.123 adalah
literal titik-mengambang. C# juga membolehkan Anda untuk menggunakan notasi
saintifik bagi angka titik-mengambang.
Dalam C#,
literal memiliki tipe. Pertanyaannya adalah tipe apakah literal numerik?
Sebagai contoh, apakah tipe dari 12, 123987, atau 0.23? Untungnya, C#
menspesifikasi beberapa aturan sederhana yang bisa menjawab pertanyaan ini.
Pertama, untuk
literal integer, tipe literal adalah tipe integer terkecil yang bisa
menampungnya, dimulai dari int.
Jadi, sebuah literal integer adalah bertipe int, uint, long, atau ulong, bergantung pada nilainya. Kedua, literal titik-mengambang
adalah bertipe double.
Jika tipe
default C# bukanlah yang Anda inginkan untuk sebuah literal, Anda bisa
menspesifikasi secara eksplisit tipenya dengan mencantumkan sufiks. Untuk
menspesifikasi sebuah literal long,
tempelkan l atau L. Sebagai
contoh, 12 adalah sebuah int, tetapi
12L adalah sebuah long. Untuk
menspesifikasi sebuah integer tak-bertanda, tempelkan u atau U. Jadi, 100
adalah sebuah int, tetapi 100U
adalah uint. Untuk menspesifikasi
integer long tak-bertanda, gunakan ul atau UL. Sebagai contoh, 984375UL bertipe ulong.
Untuk
menspesifikasi literal float,
tempelkan F atau f pada nilai. Sebagai contoh, 10.19F
adalah bertipe float. Meskipun
berlebihan, Anda dapat menspesifikasi literal double dengan menempelkan D
atau d. (Seperti disebutkan
sebelumnya, literal titik-mengambang secara default adalah double).
Untuk
menspesifikasi literal decimal,
nilai terkait diikuti dengan m atau M. Sebagai contoh, 9.9M adalah sebuah
literal decimal.
Literal
Heksadesimal
Seperti yang Anda
ketahui, dalam pemrograman kadangkala lebih mudah untuk menggunakan sistem
bilangan berbasis 16 menggantikan basis 10. Sistem bilangan basis 16 disebut
dengan heksadesimal dan menggunakan dijit 0 sampai 9 dan huruf A sampai F (yang
mewakili nilai 10, 11, 12, 13, 14, dan 15). Sebagai contoh, bilangan
heksadesimal 10 adalah 16 dalam desimal. Karena frekuensi penggunaan angka
heksadesimal yang sangat tinggi, C# membolehkan Anda untuk menspesifikasi
literal integer dalam format heksadesimal. Literal heksadesimal harus diawali
dengan 0x. Berikut adalah dua contoh literal heksadesimal:
hitung = 0xFF; // 255 dalam desimal
tambah = 0x1a; // 26 dalam desimal
Runtun
Escape
Literal karakter
yang diapit dengan dua kutip tunggal berlaku pada hampir semua karakter,
kecuali bebera karakter, seperti carriage return. Selain itu, untuk beberapa
karakter tertentu, kutip tunggal dan kutip ganda, memiliki makna spesial dalam
C#, sehingga Anda tidak dapat menggunakannya secara langsung. Karena dua alasan
ini, C# menyediakan beberapa runtun escape
spesial, yang kadangkala dikenal pula sebagai konstanta karakter backslash, yang ditampilkan pada Tabel
2.2.
Sebagai contoh,
statemen berikut menugasi ch dengan
karakter tab:
ch = '\t';
Contoh
selanjutnya menugaskan sebuah kutip tunggal pada ch:
ch = '\'';
Runtun escape
|
Deskripsi
|
\a
|
Alert (bell)
|
\b
|
Backspace
|
\f
|
Form feed
|
\n
|
New line
(garis baru)
|
\r
|
Carriage
return
|
\t
|
Tab horisontal
|
\v
|
Tab vertikal
|
\0
|
Null
|
\’
|
Kutip tunggal
|
\”
|
Kutip ganda
|
\\
|
Backslash
|
Tabel 2.2 Runtun escape
Literal
String
C# mendukung
satu lagi tipe literal: literal string. Literal string adalah himpunan karakter
yang diapit oleh dua kutip ganda. Sebagai contoh,
“Ini adalah literal string”
adalah sebuah
literal string. Anda telah melihat banyak literal string pada statemen
WriteLine() pada beberapa program terdahulu. Di samping karakter normal,
literal string dapat pula memuat satu atau lebih runtun escape. Sebagai contoh, perhatikan program berikut, yang
menggunakan runtun escape \n dan \t.
// Demonstrasi runtun escape
dalam string.
using System;
class DemoString
{
static
void Main() {
Console.WriteLine("Baris Satu\nBaris Dua\nBaris Tiga");
Console.WriteLine("Satu\tDua\tTiga");
Console.WriteLine("Empat\tLima\tEnam");
// Menampilkan kutip
Console.WriteLine("\"Kenapa?\", Dia berujar.");
}
}
Keluaran program
adalah:
Baris Satu
Baris Dua
Baris Tiga
Satu Dua Tiga
Empat Lima Enam
"Kenapa?", Dia berujar.
Perhatikan
bagaimana runtun escape \n dipakai
untuk menghasilkan baris baru. Anda tidak perlu menggunakan beberapa statemen WriteLine() untuk mendapatkan keluaran
banyak baris baru. Anda hanya perlu menyisipkan \n di dalam string panjang pada titik dimana Anda ingin baris baru
diperlukan. Selain itu, perhatikan juga bagaimana tanda kutip ganda dihasilkan
di dalam suatu string.
Selain format
literal string yang baru saja dijelaskan, Anda juga dapat menspesifikasi
literal string verbatim. Literal string verbatim diawali dengan @, yang diikuti
oleh sebuah string yang dikutip. Jadi, Anda dapat menyertakan baris-baru, tab,
dan lainnya, tetapi Anda tidak perlu menggunakan runtun escape. Satu-satunya
pengecualian adalah bahwa untuk mendapatkan kutip ganda (“), Anda harus
menggunakan dua kutip ganda secara berurutan (“”). Berikut adalah sebuah
program yang mendemonstrasikan literal string verbatim:
// Demonstrasi literal
string verbatim.
using System;
class Verbatim {
static
void Main() {
Console.WriteLine(@"Ini
adalah literal
string verbatim yang
ditempatkan pada beberapa
baris.
");
Console.WriteLine(@"Berikut
adalah keluaran yang ditab:
1 2
3 4
5 6
7 8
");
Console.WriteLine(@"Programer
berkata, ""Saya suka C#.""");
}
}
Keluaran program
adalah:
Ini adalah literal
string verbatim yang
ditempatkan pada beberapa baris.
Berikut adalah keluaran yang ditab:
1 2 3 4
5 6 7 8
Programer berkata, "Saya suka C#."
Hal penting yang
perlu diperhatikan dalam program tersebut adalah bahwa literal string verbatim
ditampilkan persis sama dengan apa yang dituliskan di dalam program.
Keuntungan
literal string verbatim adalah bahwa Anda dapat menentukan keluaran di dalam
program Anda yang sama persis dengan apa tertampil pada layar. Namun, pada
kasus string baris-jamak, identasi (pengaturan posisi) akan mengaburkan
kemudahan pembacaan program. Karena alasan ini, semua program pada buku ini
membatasi penggunaan literal string. Yang perlu Anda ingat adalah bahwa literal
string verbatim bisa berguna pada banyak situasi pemformatan.
Satu hal
terakhir: Jangan bingung dalam membedakan string dengan karakter. Literal
karakter, seperti ‘X’, merepresentasikan huruf bertipe char. Literal string yang hanya memuat satu huruf, seperti “X”,
tetap sebuah string.
Lebih
Dekat Dengan Variabel
Variabel
dideklarasikan menggunakan format statemen berikut:
tipe nama-var;
dimana tipe adalah tipe
data variabel dan nama-var adalah namanya. Anda dapat mendeklarasikan sebuah variabel
bertipe sembarang (yang valid). Adalah hal penting untuk memahami bahwa
kapabilitas suatu variabel ditentukan oleh tipenya. Sebagai contoh, variabel
bertipe bool tidak dapat dipakai
untuk menyimpan nilai titik-mengambang. Selain itu, tipe suatu variabel tidak
bisa diubah setelah pendeklarasiannya. Variabel bertipe int tidak bisa diubah menjadi bertipe char, misalnya.
Semua variabel
dalam C# harus dideklarasikan sebelum digunakan. Sebagai aturan umum, hal ini
diperlukan karena kompiler harus mengetahui tipe data sebuah variabel sebelum
kompiler mengkompilasi sembarang statemen yang menggunakan variabel tersebut.
Hal ini juga memampukan kompiler untuk melakukan pemeriksaan tipe.
C#
mendefinisikan beberapa jenis variabel. Jenis variabel yang dipakai sejauh ini
adalah variabel lokal karena dideklarasikan di dalam sebuah metode.
Menginisialisasi
Variabel
Salah satu cara untuk
memberikan nilai kepada sebuah variabel adalah melalui statemen penugasan,
seperti yang Anda telah lakukan sebelumnya. Cara lainnya adalah dengan
memberikan nilai awal ketika variabel tersebut dideklarasikan. Untuk
melakukannya, nama variabel diikuti dengan tanda sama dengan dan nilai yang
akan ditugaskan. Bentuk umum inisialisasi variabel ditampilkan di sini:
tipe nama-var = nilai;
Di sini, nilai adalah nilai
yang akan diberikan kepada variabel ketika variabel itu diciptakan. nilai harus
kompatibel dengan tipe yang dispesifikasi. Berikut diberikan beberapa contoh
inisialisasi variabel:
int hitung = 10; // memberikan hitung nilai awal 10
char ch = 'X'; // menginisialisasi ch dengan huruf X
float f = 1.2F; // f diinisialisasi dengan 1.2
Ketika
mendeklarasikan dua atau lebih variabel bertipe sama yang dipisahkan dengan
koma, Anda dapat memberikannya nilai awal. Sebagai contoh,
int a, b = 8, c = 19, d; // b dan c mempunyai nilai awal
Pada kasus ini, hanya
b dan c yang diinisialisasi.
Inisialisasi
Dinamis
Meskipun
contoh-contoh sebelumnya hanya menggunakan konstanta sebagai penginisialisasi,
C# membolehkan variabel diinisialisasi secara dinamis, menggunakan sembarang
ekspresi valid di titik dimana variabel tersebut dideklarasikan. Sebagai
contoh, berikut adalah sebuah program pendek yang menghitung sisi miring dari
sebuah segitiga, bila diberikan dua sisi lainnya.
// Demonstrasi inisialisasi
dinamis.
using System;
class InisialDinamis {
static
void Main() {
// Panjang kedua sisi.
double
s1 = 4.0;
double
s2 = 5.0;
// Secara dinamis menginisialisasi
sisi_miring.
double
sisi_miring = Math.Sqrt((s1 * s1) + (s2 * s2));
Console.Write("Sisi miring suatu segitiga dengan kedua
disi " +
s1 + " dan " +
s2 + " adalah ");
Console.WriteLine("{0:#.###}.", sisi_miring);
}
}
Berikut adalah
keluaran program:
Sisi miring suatu segitiga dengan kedua disi 4 dan 5 adalah
6.403.
Di sini, tiga
variabel lokal, yaitu s1, s2, dan sisi_miring, dideklarasikan. Dua variabel pertama, s1 dan s2, diinisialisasi dengan konstanta. Namun, sisi_miring diinisialisasi secara dinamis dengan panjang sisi
miring suatu segitiga. Perhatikan bahwa inisialisasi melibatkan pemanggilan Math.Sqrt(). Seperti yang telah
dijelaskan, Anda dapat menggunakan sembarang ekspresi yang valid di titik
inisialisasi. Karena pemanggilan terhadap Math.Sqrt()
valid di titik tersebut, ia dapat dipakai di dalam inisialisasi sisi_miring.
Variabel
Bertipe Implisit
Seperti yang
telah dijelaskan, dalam C# semua variabel harus dideklarasikan. Normalnya,
deklarasi mencakup tipe variabel, seperti int
atau bool, diikuti dengan nama
variabel. Namun, sejak C# 3.0, menjadi memungkinkan bagi kompiler dalam
menentukan tipe suatu variabel lokal berdasarkan nilai yang dipakai untuk
menginisialisasinya. Hal ini dikenal dengan variabel bertipe implisit.
Variabel bertipe
implisit dideklarasikan menggunakan katakunci var, dan harus diinisialisasi. Kompiler menggunakan tipe
penginisialisasi dalam menentukan tipe variabel. Berikut adalah sebuah
contohnya:
var e =
2.7183;
Karena e diinisialisasi dengan literal
titik-mengambang (secara default, double),
maka tipe dari e adalah double. Jika e dideklarasikan seperti ini:
var e =
2.7183F;
maka e bertipe float.
Program berikut
mendeklarasikan tipe variabel yang dideklarasikan secara implisit.
// Demonstrasi tipe variabel
secara implisit.
using System;
class VariabelBertipeImplisit {
static
void Main() {
// Berikut adalah variabel bertipe
implisit.
// Keduanya bertipe double karena ekspresi
// penginisialisasi bertipe double.
var
s1 = 4.0;
var
s2 = 5.0;
// Sekarang, sisi_miring bertipe implisit.
Tipenya double
// karena tipe nilai balik dari Sqrt()
adalah double.
var
sisi_miring = Math.Sqrt( (s1 * s1) + (s2 * s2) );
Console.Write("Sisi miring dari suatu segitiga dengan
kedua sisi " +
s1 + " dan " + s2 + " adalah ");
Console.WriteLine("{0:#.###}.",
sisi_miring);
// Statemen berikut tidak akan dikompilasi
karena
// s1 adalah sebuah double dan tidak dapat
ditugasi nilai decimal.
// s1 = 12.2M; // Error!
}
}
Keluaran program
sama dengan sebelumnya. Hal penting yang perlu ditekankan di sini adalah bahwa
suatu variabel bertipe implisit tidak bisa diubah semena-mena. Perhatikan
komentar ini di dalam program:
// s1 = 12.2M; // Error!
Penugasan ini
tak valid karena s1 bertipe double. Jadi, ia tidak bisa ditugasi
sebuah nilai decimal. Satu-satunya
perbedaan antara variabel bertipe implisit dan variabel yang ditipe secara
eksplisit adalah bagaimana tipe ditentukan. Begitu tipe telah ditentukan,
variabel telah memiliki tipe, dan tipe ini tetap selama variabel itu eksis.
Jadi, tipe dari s1 tidak dapat
diubah selama ekskusi program.
Satu hal
terakhir: Hanya boleh satu variabel bertipe implisit yang dapat dideklarasikan
pada satu waktu. Oleh karena itu, deklarasi berikut:
var s1 =
4.0, s2 = 5.0; // Error!
adalah salah dan
tidak bisa dikompilasi karena mencoba untuk mendeklarasikan s1 dan s2 pada waktu yang bersamaan.
Skop
dan Usia Variabel
Sejauh ini,
semua variabel yang dipakai dideklarasikan di awal metode Main(). Namun, C# membolehkan variabel lokal dideklarasikan di
dalam sembarang blok. Blok diawali dengan kurung kurawal buka dan diakhiri
dengan kurung kurawal tutup. Blok mendefinisikan skop. Jadi, setiap kali Anda
memulai blok baru, itu artinya Anda menciptakan skop baru. Skop menentukan
visibilitas nama-nama yang dikenali oleh bagian-bagian program Anda tanpa
memerlukan kualifikasi. Skop juga menentukan usia variabel lokal.
Skop yang paling
penting dalam C# adalah yang didefinisikan oleh suatu kelas dan yang
didefinisikan oleh suatu metode. Diskusi tentang skop kelas (dan variabel yang
dideklarasikan di dalamnya) dilakukan nanti pada buku ini. Untuk sekarang,
hanya skop yang didefinisikan oleh metode yang akan dibahas.
Skop yang didefinisikan
oleh metode diawali dengan kurung kurawal buka dan diakhiri dengan kurung
kurawal tutunp. Namun, jika metode tersebut mempunyai parameter, parameter
tersebut juga disertakan di dalam skop yang didefinisikan oleh metode.
Sebagai aturan
umum, variabel lokal yang dideklarasikan di dalam sebuah skop tidak dikenali
oleh kode yang didefinisikan di luar skop tersebut. Jadi, ketika Anda
mendeklarasikan sebuah variabel di dalam suatu skop, maka Anda melindunginya
dari akses atau modifikasi dari luar skop. Aturan skop merupakan fondasi bagi
enkapsulasi.
Skop dapat
dibuat bersarang. Ketika ini terjadi, skop sebelar luar mengapit skop sebelah
dalam. Ini berarti bahwa variabel lokal yang dideklarasikan di dalam skop luar
dapat dikenali oleh kode di dalam skop sebelah dalam. Tetapi tidak sebaliknya.
Variabel lokal yang dideklarasikan di dalam skop sebelah dalam tidak dikenali
oleh kode di luarnya (meski berada di dalam skop sebelah luar).
// Demonstrasi skop blok.
using System;
class DemoSkop {
static
void Main() {
int
x; // dikenali oleh semua kode di dalam Main()
x = 10;
if
(x == 10)
{ // mulai skop baru
int y = 20; // hanya dikenali di dalam blok ini
// x dan y keduanya dikenali di
sini.
Console.WriteLine("x
dan y: " + x + " " + y);
x = y * 2;
}
// y = 100; // Error! y tidak dikenali
di sini.
// x masih dikenali di sini.
Console.WriteLine("x adalah " + x);
}
}
Keluaran program
ditampilkan di sini:
x dan y: 10 20
x adalah 40
Seperti
diindikasikan pada komentar, variabel x
dideklarasikan di awal skop Main()
dan dapat diakses (dikenali) oleh semua kode di dalam Main(). Di dalam blok if, y dideklarasikan. Karena blok
mendefinisikan skop, y hanya
dikenali oleh kode di dalam blok tersebut. Ini mengapa di luar blok tersebut,
baris y = 100; tidak dikenali. Jika
Anda menghapus simbol komentar //, maka error kompilasi akan terjadi karena y tidak di kenali di luar bloknya. Di
dalam blok if, x dapat dipakai karena kode di dalam blok tersebut memiliki akses
terhadap variabel tersebut.
Di dalam suatu
blok, variabel dapat dideklarasikan dimanapun, tetapi hanya bisa diakses
setelah titik pendeklarasiannya. Jadi, jika Anda mendefinisikan sebuah variabel
di awal metode, maka variabel itu dapat diakses oleh semua kode di dalam metode
tersebut. Sebaliknya, jika Anda mendeklarasikan variabel di akhir suatu blok,
maka ia hanya menjadi variabel sia-sia, karena tidak ada kode yang dapat
mengaksesnya.
Jika suatu
deklarasi variabel melibatkan penginisialisasi, maka variabel tersebut akan
diinisialiasi-ulang setiap kali blok yang memuatnya dimasuki program. Sebagai
contoh, perhatikan program ini:
// Demonstrasi usia suatu
variabel.
using System;
class VarInitDemo {
static
void Main() {
int
x;
for(x
= 0; x < 3; x++) {
int
y = -1; // y diinisialisasi setiap kali blok dimasuki
Console.WriteLine("y adalah: " + y); // selalu
menampilkan -1
y = 100;
Console.WriteLine("y sekarang menjadi: " + y);
}
}
}
Berikut adalah
keluaran program:
y adalah: -1
y sekarang menjadi: 100
y adalah: -1
y sekarang menjadi: 100
y adalah: -1
y sekarang menjadi: 100
Seperti yang
dapat Anda lihat, y selalu
diinisialisasi-ulang dengan -1 setiap kali loop for dimasuki program. Meskipun y ditugasi nilai 100, nilai ini akan
hilang.
Ada satu hal
aneh dalam aturan skop C# yang bisa mengejutkan Anda: Meskipun blok bisa dibuat
bersarang, tidak ada variabel yang dideklarasikan di dalam skop sebelah dalam
yang dapat memiliki nama sama dengan variabel yang dideklarasikan oleh skop
sebelah luar. Sebagai contoh, program berikut, yang mencoba mendeklarasikan dua
variabel terpisah dengan nama sama, tidak akan berhasil dikompilasi.
/*
Program ini mencoba
mendeklarasikan sebuah variabel
di dalam skop sebelah dalam
dengan nama sama dengan
variabel yang didefinisikan
di dalam skop sebelah luar.
*** Program ini tak akan
bisa dikompilasi. ***
*/
using System;
class VariabelBersarang {
static
void Main() {
int
hitung;
for
(hitung = 0; hitung < 10; hitung = hitung + 1)
{
Console.WriteLine("Ini
adalah hitung: " + hitung);
int hitung; // ilegal!!!
for (hitung = 0; hitung < 2; hitung++)
Console.WriteLine("Program
ini bermasalah!");
}
}
}
Jika Anda
memiliki latar belakang pemrograman C/C++, maka Anda mengetahui tidak ada
batasan nama seperti ini. Jadi, dalam C/C++ deklarasi hitung di dalam blok loop
for sebelah dalam seutuhnya valid.
Namun, dalam C/C++, deklarasi semacam itu akan menyembunyikan variabel sebelah
luar. Perancang C# merasa bahwa jenis penyembunyian nama seperti ini dapat
dengan mudah menyebabkan error pemrograman dan tidak mengijinkan penggunaannya.
Konversi
Tipe dan Casting
Dalam
pemrograman, adalah hal umum dijumpai untuk mengubah satu tipe variabel menjadi
tipe lain. Sebagai contoh, Anda bisa jadi ingin menugaskan nilai int menjadi kepada sebuah variabel float, seperti ditunjukkan di sini:
int i;
float f;
i = 10;
f = i; // menugaskan int ke suatu float
Ketika beberapa
tipe kompatibel dicampur di dalam suatu penugasan, nilai dari sisi sebelah
kanan operator penugasan secara otomatis dikonversi menjadi tipe dari sisi
sebelah kiri. Jadi, pada fragmen tersebut, nilai di dalam i dikonversi menjadi float
dan kemudian ditugaskan kepada f.
Namun, karena aturan pemeriksaan-tipe C#, tidak semua tipe kompatibel, dan
jadi, tidak semua konversi secara implisit diijinkan. Sebagai contoh, bool dan int tidak kompatibel. Untungnya, masih dimungkinkan terjadinya
konversi antara tipe-tipe tak-kompatibel menggunakan cast. Sebuah cast melakukan konversi eksplisit. Konversi tipe
otomatis dan operasi cast didisikusikan di sini.
Konversi
Otomatis
Ketika suatu
tipe data ditugaskan kepada variabel bertipe lain, konversi tipe otomatis akan
terjadi secara otomatis jika
·
Kedua tipe kompatibel.
·
Tipe tujuan memiliki rentang lebih
besar dari tipe sumber.
Ketika kedua
kondisi ini dipenuhi, konversi melebar akan terjadi. Sebagai contoh, tipe int selalu cukup besar untuk menampung
nilai bertipe byte, dan kedua int dan byte merupakan tipe integer yang kompatibel, jadi konversi implisit
bisa diterapkan.
Untuk konversi
melebar, tipe-tipe numerik, termasuk tipe integer dan tipe titik-mengambang,
adalah kompatibel satu sama lain. Sebagai contoh, program berikut valid karena
konversi long menjadi double merupakan suatu konversi melebar
yang secara otomatis dilakukan.
// Demonstrasi konversi
implisit dari long ke double.
using System;
class LtoD {
static
void Main() {
long
L;
double
D;
L = 100123285L;
D = L;
Console.WriteLine("L dan D: " + L + " " +
D);
}
}
Meskipun
konversi implisit dari long menjadi double bisa dilakukan, konversi
implisit dari double menjadi long tidak bisa dilakukan karena bukan
merupakan konversi melebar. Jadi, versi berikut dari program sebelumnya menjadi
tak-valid:
// *** Program ini tidak
bisa dikompilasi. ***
using System;
class LtoD {
static
void Main() {
long
L;
double
D;
D = 100123285.0;
L = D; // Ilegal!!!
Console.WriteLine("L dan D: " + L + " " +
D);
}
}
Selain
pembatasan yang telah dijelaskan, konversi implisit antara decimal dan float atau double tidak bisa dilakukan, atau dari
tipe numerik menjadi char atau double. Di samping itu, char dan bool tidak kompatibel satu sama lain.
Operasi
Cast Atas Tipe Tak-Kompatibel
Meskipun
konversi tipe implisit cukup membantu, operasi itu tidak bisa memenuhi semua
kebutuhan pemrograman karena hanya bisa diterapkan pada konversi melebar di
antara tipe-tipe kompatibel. Untuk kasus selain itu, Anda harus menerapkan cast.
Sebuah cast adalah instruksi kepada kompiler untuk mengkonversi keluaran suatu
ekspresi menjadi tipe yang diinginkan. Jadi, kompiler meminta dilakukan
konversi tipe secara eksplisit. Operasi cast mempunyai bentuk umum:
(tipe-target) ekspresi
Di sini, tipe-target menspesifikasi
tipe yang diinginkan. Sebagai contoh, diberikan
double x, y;
Jika Anda ingin
tipe konversi x/y menjadi int,
Anda dapat menuliskan
(int) (x / y)
Di sini,
meskipun x dan y bertipe double,
operasi cast mengkonversi keluaran ekspresi menjadi int. Sepasang kurung yang mengapit x/y diperlukan. Karena jika kurung tidak digunakan, operasi cast
hanya akan diterapkan pada x dan
bukan pada keluaran pembagian. Operasi cast diperlukan di sini karena konversi
implisit dari double menjadi int tidak bisa dilakukan.
Ketika operasi
cast melibatkan konversi menyempit, informasi bisa hilang. Sebagai contoh,
ketika operasi cast dilakukan terhadap long
menjadi int, informasi bisa hilang
jika nilai dari long lebih besar
dari rentang sebuah int karena
bit-bit signifikan akan terhapus. Ketika suatu nilai titik-mengambang dicast
menjadi tipe integer, komponen pecahan akan hilang akibat pemotongan. Sebagai
contoh, jika nilai 1.23 ditugaskan kepada sebuah integer, nilai yang dihasilkan
adalah 1. Komponen pecahan 0.23 akan hilang.
Program berikut
mendemonstrasikan beberapa konversi tipe yang memerlukan operasi cast. Program
ini juga menunjukkan beberapa situasi dimana operasi cast dapat menyebabkan
data hilang.
// Demonstrasi operasi cast.
using System;
class DemoCast {
static void Main() {
double x, y;
byte b;
int i;
char ch;
uint u;
short s;
long l;
x = 10.0;
y = 3.0;
// Cast double
menjadi int, komponen pecahan hilang.
i = (int) (x / y);
Console.WriteLine("Keluaran integer dari x / y: " +
i);
Console.WriteLine();
// Cast int menjadi
byte, tidak ada data hilang.
i = 255;
b = (byte) i;
Console.WriteLine("b setelah penugasan 255: " + b +
" -- tidak data hilang.");
// Cast int menjadi
byte, data hilang.
i = 257;
b = (byte) i;
Console.WriteLine("b setelah penugasan 257: " + b +
" -- data hilang.");
Console.WriteLine();
// Cast uint
menjadi short, tidak ada data hilang.
u = 32000;
s = (short) u;
Console.WriteLine("s setelah penugasan 32000: " + s +
" -- tidak ada data hilang.");
// Cast uint
menjadi short, data hilang.
u = 64000;
s = (short) u;
Console.WriteLine("s setelah penugasan 64000: " + s +
" -- data hilang.");
Console.WriteLine();
// Cast long
menjadi uint, tidak ada data hilang.
l = 64000;
u = (uint)l;
Console.WriteLine("u setelah penugasan 64000: " + u +
" -- tidak ada data hilang.");
// Cast dari long
menjadi uint, data hilang.
l = -12;
u = (uint)l;
Console.WriteLine("u setelah penugasan -12: " + u +
" -- data hilang.");
Console.WriteLine();
// Cast int menjadi
char.
b = 88; // kode
ASCII untuk X
ch = (char)b;
Console.WriteLine("ch setelah penugasan 88: " + ch);
}
}
Keluaran program
ditampilkan di sini:
Keluaran
integer dari x / y: 3
b
setelah penugasan 255: 255 -- tidak data hilang.
b
setelah penugasan 257: 1 -- data hilang.
s
setelah penugasan 32000: 32000 -- tidak ada data hilang.
s
setelah penugasan 64000: -1536 -- data hilang.
u
setelah penugasan 64000: 64000 -- tidak ada data hilang.
u
setelah penugasan -12: 4294967284 -- data hilang.
ch
setelah penugasan 88: X
Akan diperiksa
setiap penugasan. Operasi cast terhadap (x/y)
menjadi int menghasilkan pemotongan
komponen pecahan (fraksional), dan informasi hilang.
Tidak ada
informasi yang hilang terjadi ketika b
ditugasi nilai 255 karena sebuah byte
dapat menampung nilai 255. Namun, ketika percobaan dilakukan untuk menugasi b dengan nilai 257, informasi hilang
terjadi karena 257 melebihi rentang suatu byte.
Pada kedua kasus, operasi cast dibutuhkan karena konversi implisit dari int menjadi byte tidak bisa dilakukan.
Ketika variabel short, s, ditugasi nilai 32,000 melalui variabel uint, u, tidak ada data
yang hilang karena sebuah short
dapat menampung nilai 32,000. Namun, dalam penugasan selanjutnya, u mempunyai nilai 64,000, yang berada
di luar rentang sebuah short, dan
data menjadi hilang. Pada kedua kasus, operasi cast diperlakukan karena
konversi implisit dari uint menjadi short tidak bisa dilakukan.
Selanjutnya, u ditugasi nilai 64,000 melalui
variabel long, l. Pada kasus ini,
tidak ada data yang hilang karena 64,000 masih berada di dalam rentang sebuah uint.
Namun, ketika nilai -12 ditugaskan kepada u, data menjadi hilang karena sebuah uint tidak bisa menampung nilai negatif. Pada kedua kasus, operasi
cast diperlukan karena konversi implisit dari long menjadi uint tidak
bisa dilakukan.
Konversi
Tipe Dalam Ekspresi
Selain terjadi
di dalam penugasan, konversi tipe juga terjadi di dalam ekspresi. Di dalam
suatu ekspresi, Anda dapat dengan bebas mencampur dua atau lebih berbagai tipe
data berbeda sepanjang kompatibel satu sama lain. Sebagai contoh, Anda dapat mencampur
short dan long di dalam sebuah ekspresi karena keduanya adalah tipe numerik. Ketika
berbagai tipe data dicampur di dalam sebuah ekspresi, maka dikonversi menjadi
tipe yang sama melalui basis operasi-demi-operasi.
Konversi
dilakukan melalui aturan promosi tipe C#. Berikut adalah algoritma promosi tipe
C#:
IF satu operand
adalah decimal, THEN operand lain
dipromosikan menjadi decimal (kecuali jika salah satu operand bertipe float atau double, pada kasus itu akan terjadi error).
ELSEIF satu
operand bertipe double, maka operand
kedua dipromosikan menjadi double.
ELSEIF satu
operand bertipe float, maka operand
kedua dipromosikan menjadi float.
ELSEIF satu
operand bertipe ulong, maka operand
kedua dipromosikan menjadi ulong
(kecuali jika operand kedua bertipe sbyte,
short, int, atau long, pada
kasus tersebut akan terjadi error).
ELSEIF satu
operand bertipe long, maka operand
kedua dipromosikan menjadi long.
ELSEIF satu
operand bertipe uint dan operand
kedua bertipe sbyte, short, atau, int, maka kedua operand dikonversi
menjadi long.
ELSEIF satu
operand bertipe uint, maka operand
kedua dipromosikan menjadi uint.
ELSE kedua
operand dipromosikan menjadi int.
Adalah hal
penting untuk dipahami bahwa promosi tipe hanya diterapkan pada nilai di dalam
ekspresi yang sedang dievaluasi. Sebagai contoh, jika nilai dari sebuah
variabel bertipe byte dipromosikan
menjadi int di dalam suatu ekspresi,
maka di luar ekspresi variabel tersebut masih sebuah byte. Promosi tipe hanya mempengaruhi evaluasi atas suatu ekspresi.
Promosi tipe
dapat mengarah ke hasil yang tidak diinginkan. Sebagai contoh, ketika suatu
operasi aritmatika melibatkan dua nilai byte,
runtun berikut terjadi. Pertama, operand byte
dipromosikan menjadi int, memberikan
hasil int. Jadi, keluaran sebuah
ekspresi yang melibatkan dua nilai byte
akan menghasilkan sebuah int. Ini
mungkin bukan apa yang Anda bayangkan. Perhatikan program berikut.
// Kejutan Promosi tipe!
using System;
class PromDemo
{
static
void Main()
{
byte
b;
b = 10;
b = (byte)(b * b); // cast diperlukan!!
Console.WriteLine("b: " + b);
}
}
Di luar dugaan
Anda, operasi cast terhadap byte diperlukan ketika menugaskan b * b kembali kepada b!. Alasannya adalah karena di dalam b * b, nilai b dipromosikan menjadi int
ketika ekspresi tersebut dievaluasi. Jadi, b
* b menghasilkan nilai int, yang
tidak bisa ditugaskan ke variabel byte
tanpa operasi cast.
Situasi yang
sama terjadi pada char. Sebagai
contoh, dalam fragmen berikut, operasi cast terhadap char diperlukan karena promosi atas ch1 dan ch2 menjadi int di dalam ekspresi
char ch1 = 'a',
ch2 = 'b';
ch1 = (char)
(ch1 + ch2);
Tanpa adanya
operasi cast, hasil penjumlahan ch1
dan ch2 akan bertipe int, yang tidak bisa ditugaskan kepada
variabel char.
Menggunakan
Cast Dalam Ekspresi
Operasi cast
dapat diterapkan pada bagian spesifik dari sebuah ekspresi panjang. Ini
memberikan Anda kendali atas konversi tipe yang terjadi di dalam sebuah
ekspresi yang sedang dievaluasi. Sebagai contoh, perhatikan program berikut.
Program tersebut menampilkan beberapa akar kuadrat atas angka dari 1 sampai 10.
Program juga menampilkan bagian bulat dan bagian pecahan dari setiap hasil,
secara terpisah. Untuk melakukannya, program menggunakan operasi cast dalam
mengkonversi hasil dari Math.Sqrt()
menjadi int.
// Menggunakan cast di dalam
sebuah ekspresi.
using System;
class CastExpr {
static
void Main() {
double
n;
for(n
= 1.0; n <= 10; n++) {
Console.WriteLine("Akar kuadrat atas {0} adalah {1}",
n, Math.Sqrt(n));
Console.WriteLine("Bagian angka bulat: {0}",
(int)Math.Sqrt(n));
Console.WriteLine("Bagian pecahan: {0}",
Math.Sqrt(n) - (int)Math.Sqrt(n));
Console.WriteLine();
}
}
}
Berikut adalah
keluaran program:
Akar kuadrat atas 1 adalah 1
Bagian angka bulat: 1
Bagian pecahan: 0
Akar kuadrat atas 2 adalah 1.4142135623731
Bagian angka bulat: 1
Bagian pecahan: 0.414213562373095
Akar kuadrat atas 3 adalah 1.73205080756888
Bagian angka bulat: 1
Bagian pecahan: 0.732050807568877
Akar kuadrat atas 4 adalah 2
Bagian angka bulat: 2
Bagian pecahan: 0
Akar kuadrat atas 5 adalah 2.23606797749979
Bagian angka bulat: 2
Bagian pecahan: 0.23606797749979
Akar kuadrat atas 6 adalah 2.44948974278318
Bagian angka bulat: 2
Bagian pecahan: 0.449489742783178
Akar kuadrat atas 7 adalah 2.64575131106459
Bagian angka bulat: 2
Bagian pecahan: 0.645751311064591
Akar kuadrat atas 8 adalah 2.82842712474619
Bagian angka bulat: 2
Bagian pecahan: 0.82842712474619
Akar kuadrat atas 9 adalah 3
Bagian angka bulat: 3
Bagian pecahan: 0
Akar kuadrat atas 10 adalah 3.16227766016838
Bagian angka bulat: 3
Bagian pecahan: 0.16227766016838
nice information min
ReplyDeleteIsolasi hp double tape
yuhuu....bermanfaat gan
ReplyDeletePemotong simcard