Belajar Tipe Data Primitif pada Java

Tipe data adalah salah satu konsep dasar pemrograman. Sebagai seorang programer, seharusnya menguasai hal ini dengan baik. Untuk mempelajari tipe data, sebaiknya menggunakan bahasa pemrograman yang strongly typed, misalnya Java.

Tidak seperti pada bahasa PHP, Java adalah bahasa pemrograman yang strongly typed. Kita tidak bisa tidak acuh terhadap tipe data. Kita harus mengetahui data seperti apa yang disimpan ke dalam variabel. Misalnya untuk menyimpan umur kita gunakan variabel yang bertipe Integral, karena umur hanya berupa angka bulat tanpa pecahan.

Selain itu, Java juga bersifat statically typed. Maksudnya adalah setiap variabel harus dideklarasikan sebelum digunakan. Java akan mengecek tipe data pada compile-time.

int i = 0;

Tipe data primitif adalah tipe data standar yang tidak diturunkan dari objek manapun. Java memiliki 8 tipe data primitif, yaitu: byte, short, int, long, float, double, boolean, char. Berikut ini adalah pembahasan untuk masing-masing tipe data.

1. boolean. Tipe data boolean adalah tipe data Logical, yang hanya memiliki 2 nilai literal, yaitu true dan false.

boolean nilai = true;

2. char. Tipe data char adalah tipe data Textual, yang merepresentasikan karakter unicode 16-bit. Nilai literalnya harus diapit dengan tanda petik tunggal (‘).

char huruf = 'a';

3. byte. Tipe data byte adalah tipe data Integral 8-bit. Memiliki rentang nilai antara -27 sampai 27 – 1 atau dari -128 sampai 127.

byte angka = 100;

4. short. Tipe data short adalah tipe data Integral 16-bit. Memiliki rentang nilai antara -215 sampai 215 – 1 atau dari -32768 sampai 32768.

short angka = 1000;

5. int. Tipe data int adalah tipe data Integral 32-bit. Memiliki rentang nilai antara -231 sampai 231 – 1 atau dari -2,147,483,648 sampai 2,147,483,647.

int angka = 1000000;

6. long. Tipe data long adalah tipe data Integral 64-bit. Memiliki rentang nilai antara -263 sampai 263 – 1 atau dari -9,223,372,036,854,775,808 sampai 9,223,372,036,854,775,807.
Tipe data Integral (byte, short, int, long) memiliki default nilai literal int, kecuali diberi akhiran L yang berarti bertipe long. Tipe data Integral dapat menggunakan sistem bilangan desimal, oktal, atau heksadesimal.

int desimal = 26; // angka 26 dalam desimal
int oktal = 032; // angka 26 dalam oktal (diberi awalan 0)
int heksa = 0x1a; // angka 26 dalam heksadesimal (diberi awalan 0x)
long angkaBesar = 1000000000000L; // angka desimal bertipe long

7. float. Tipe data float adalah tipe data Floating Point 32-bit. Nilai literalnya mengandung pecahan (dipisahkan dengan tanda titik ‘.’)

float pi = 3.14F;

8. double. Tipe data double adalah tipe data Floating Point 64-bit. Nilai literal default untuk float dan double adalah double, kecuali diberi akhiran F seperti pada contoh nomor 7 di atas.

float pecahan = 7.65F;
double pecahanDouble = 1.2345;

Jika variabel float yang diinisialisasi dengan suatu nilai tanpa akhiran F, akan muncul pesan kesalahan: “possible loss of precision“.

Nilai literal untuk Floating Point juga bisa menggunakan notasi E (10n).

// ketiga variabel di bawah ini memiliki nilai yang sama 123.4
float f1 = 123.4F;
double d1 = 123.4;
double d2 = 1.234E2;

Sebenarnya tipe data primitif sudah memiliki nilai default pada saat dideklarasikan (meskipun tanpa inisialisasi), kecuali untuk variabel lokal. Nilai default untuk masing-masing tipe data adalah sebagai berikut:

Tipe Data   Nilai Default
--------------------------------------------------
boolean     false
char        '\u0000' (merepresentasikan ASCII null)
byte        0
short       0
int         0
long        0L
float       0.0F
double      0.0

Pada variabel lokal, deklarasi tipe data harus disertai dengan inisialisasi. Jika tidak, pastikan untuk memberikan nilai kepada variabel tersebut sebelum digunakan. Mengakses lokal variabel tanpa inisialisasi akan menghasilkan pesan kesalahan pada saat meng-compile (compile-time error).

11. August 2012 by Sibudi
Categories: Java | Tags: , , | 5 comments

Mencari Nilai Maksimum Per Kategori SQL

Salah satu masalah paling umum yang melibatkan query database adalah mencari nilai terbesar/terkecil pada tiap kategori/tipe. Sebagai contoh adalah mencari pencetak gol terbanyak pada masing-masing dari 4 klub teratas sepak bola Liga Inggris berikut ini.

Nama                    Klub           Gol
------------------------------------------
Sergio Agüero           Man City       23
Edin Džeko              Man City       14
Mario Balotelli         Man City       13
Wayne Rooney	        Man United     27
Javier Hernández        Man United     10
Robin Van Persie        Arsenal        30
Emmanuel Adebayor       Tottenham      17
Jermain Defoe           Tottenham      11
Rafael Van der Vaart    Tottenham      11

Berikut ini adalah hasil yang diinginkan.

Nama                    Klub           Gol
------------------------------------------
Robin Van Persie        Arsenal        30
Wayne Rooney	        Man United     27
Sergio Agüero           Man City       23
Emmanuel Adebayor       Tottenham      17

Untuk menghasilkan keluaran seperti di atas, paling tidak kita membutuhkan dua langkah. Mencari jumlah gol yang diinginkan, kemudian tampilkan field lainnya berdasarkan gol yang sudah dicari tadi.

Langkah pertama adalah mencari gol terbanyak pada masing-masing klub tanpa melihat siapa pencetak golnya.

SELECT Klub, MAX(Gol) as maxGol 
FROM `skorer` 
GROUP BY Klub

Klub           maxGol
---------------------
Arsenal        30
Man City       23
Man United     27
Tottenham      17

Hasil bisa berbeda tergantung teknik penyortingan yang digunakan. Pada contoh di atas penyortingan menaik (ascending) berdasarkan field “Klub”.

Langkah kedua adalah menampilkan field sisanya (Nama) dengan cara menggabungkan table hasil query pertama dengan table mula-mula (skorer).

SELECT b.Nama, b.Klub, b.Gol
FROM (
  SELECT Klub, MAX(Gol) AS maxGol
  FROM `skorer` 
  GROUP BY Klub
) AS a
INNER JOIN `skorer` AS b ON 
  a.Klub = b.Klub AND a.maxGol = b.Gol

Nama                    Klub           Gol
------------------------------------------
Sergio Agüero           Man City       23
Wayne Rooney	        Man United     27
Robin Van Persie        Arsenal        30
Emmanuel Adebayor       Tottenham      17

Jika ingin diurutkan sesuai contoh, tinggal tambahkan ORDER BY Gol DESC pada akhir query.

Sebenarnya ada query yang lebih singkat untuk menampilkan hasil seperti di atas, yaitu dengan menggunakan sub-query untuk mencari gol terbanyak pada masing-masing klub.

SELECT * 
FROM `skorer`
WHERE Gol = (
  SELECT MAX(Gol) 
  FROM `skorer` AS a 
  WHERE a.Klub = skorer.Klub
)

03. August 2012 by Sibudi
Categories: SQL | Tags: , , | 3 comments

Complement

Saya menemukan sebuah lowongan menarik, yaitu setiap kandidatnya diharuskan mengerjakan sebuah soal dan jawabannya dikirimkan beserta surat lamaran.

A complement of a number is defined as inversion (if the bit value = 0, change it to 1 and vice-versa) of all bits of the number starting from the leftmost bit that is set to 1.
For example, if N = 5, N is 101 in binary. The complement of N is 010, which is 2 in decimal. Similarly if N = 50, then complement of N is 13
Complete the function getIntegerComplement(). This function takes N as it’s parameter. The function should return the complement of N.

Constraints :
0 ≤ N ≤ 100000.
Sample Test Cases:

Input #00:
50

Output #00:
13

Explanation:
50 in decimal form equals: 110010.
Inverting the bit sequence: 001101. This is 13 in decimal
Input #01:
100

Output #01:
27

Explanation:
The bit sequence for 100 equals 1100100.
Inverting the sequence we get 0011011 which is 27 in decimal.

Tidak ada keterangan harus menggunakan bahasa pemrograman tertentu. Saya coba kerjakan dengan PHP dengan syarat tidak menggunakan fungsi bawaan PHP decbin() atau sebaliknya bindec(). Kita disuruh mencari complement bit dari masukan berupa bilangan desimal.

Pertama kali kita harus mengkonversi bilangan tersebut menjadi bentuk biner (secara visual, karena pada dasarnya komputer hanya mengenal bilangan biner). Konversi dari desimal ke biner dapat dilakukan dengan menyimpan hasil bagi bilangan desimal dengan angka 2 dan menuliskannya secara terbalik dari hasil yang terakhir sampai hasil yang pertama. Kemudian hasilnya diubah satu persatu dari yang semula 0 ke 1 dan sebaliknya.

<?php
while ($input != 0) {

  $sisa[$i] = ~($input % 2) + 2;
  $input = floor($input / 2);
  $i++;
}

Kode di atas untuk memperoleh sisa hasil bagi, sekaligus dicari complement-nya. Namun kenapa harus ditambah 2? Karena komputer hanya mengenal bilangan biner, jadi kita harus menyesuaikan cara berpikir komputer. Kemudian komputer juga menggunakan two’s complement untuk operasi bilangan binernya. Sehingga angka 0 setelah di-complement akan menghasilkan -1 dan angka 1 akan menghasilkan -2. Hal ini tentu saja tidak sesuai harapan. Jadi ditambahkan dengan angka 2 sehinggan 0 -> -1 + 2 = 1 dan 1 -> -2 + 2 = 0.

Penjelasannya adalah sebagai berikut. Misalnya pada komputer 8 bit, angka 0 bagi komputer adalah 0000 0000, jika dibalik menjadi 1111 1111. Bilangan biner 1111 1111 adalah two’s complement dari angka 1. Buktinya angka 1 biner 0000 0001 dibalik menjadi 1111 1110 lalu ditambah 1 = 1111 1111. Jadi pernyataan ~0 akan menghasilkan two’s complement dari 1. Operator tilde (~) hanya berfungsi membalik bit, interpretasi angkanya tetap bergantung kepada komputer.

Tugas selanjutnya adalah mengkonversi lagi bilangan biner ke desimal. Caranya adalah dengan mengalikan tiap-tiap bit (dimulai dari LSB) dengan 2^0, 2^1, dst sampai ke MSB (most-significant bit), kemudian semua hasilnya dijumlahkan. Bilangan biner yang disimpan pada array sisa[] di atas urut dari LSB ke MSB (tidak diminta tampilannya jadi tidak perlu dibalik-balik urutannya).

<?php
foreach($sisa as $key => $value) {

  if ($key == 0) {

    $output = $value * 1;
    continue;
  }

  $output += $value * pangkat($key);
}

echo $output;

Sebenarnya di PHP sudah ada fungsi pangkat, tapi kita buat sendiri aja toh sederhana ini. Sekaligus mengurangi ketergantungan terhadap satu bahasa.

<?php
function pangkat($a) {

  if ($a == 1)
    return 2;

  else
    return 2 * pangkat($a - 1);
}

Fungsi di atas rekursif. Parameternya adalah indeks dari array sisa[], jadi kalau indeks 3 berarti 2 * 2 * 2. Berikut ini ada listing lengkapnya.

<?php
$input = 50;
$output = 0;
$sisa[] = 0;
$i = 0;

if ($input >= 0 && $input <= 100000) {

  if ($input == 0)
    echo 1;

  else {
	
    while ($input != 0) {

      $sisa[$i] = ~($input % 2) + 2;
      $input = floor($input / 2);
      $i++;
    }

    foreach($sisa as $key => $value) {

      if ($key == 0) {

        $output = $value * 1;
        continue;
      }

      $output += $value * pangkat($key);
    }

    echo $output;
  }
}

function pangkat($a) {

  if ($a == 1)
    return 2;

  else
    return 2 * pangkat($a - 1);
}

20. July 2012 by Sibudi
Categories: Off Topic | Tags: , | Leave a comment

Akses Database Menggunakan PDO pada PHP

Sebagian besar programer PHP pasti pernah membuat aplikasi yang harus berinteraksi dengan database. Sampai pada PHP versi 5.1, pilihan yang direkomendasikan adalah menggunakan native drivers seperti Mysql Extensions.

Sayangnya, pada PHP versi 5.4 penggunaan Mysql Extensions mulai ditinggalkan, dan akan dihapus secara keseluruhan pada PHP versi 5.5. Itu artinya, penggunaan fungsi mysql_connect() atau mysql_query(), seperti pada postingan yang lalu, harus diganti. Pilihannya adalah menggunakan Mysqli Extensions atau yang akan dibahas berikut ini, PDO.

PDO (PHP Data Object), yang diperkenalkan sejak PHP versi 5.1, menyediakan antarmuka untuk berinteraksi dengan berbagai jenis database secara seragam. Gampangnya, kita bisa mengakses database MySQL, Firebird, atau IBM dengan syntax yang sama. Namun tidak semua driver otomatis tersedia pada sistem Anda. Untuk memeriksanya kita gunakan:

<?php
print_r(PDO::getAvailableDrivers()); 

Pada artikel ini menggunakan database MySQL, jadi pastikan tulisan berikut ini yang muncul.

Array ( [0] => mysql )

Berikut ini adalah syntax untuk koneksi awal dengan database dan query SELECT MySQL.

<?php
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$pdo->query('SELECT nama FROM tabel_pengguna WHERE id = ' . $_GET['id']);

Kode di atas adalah contoh yang buruk karena data dari pengguna langsung dimasukan ke dalam query SQL tanpa difilter, sehingga rentan disusupi kode dari luar (SQL Injection). Jika dahulu kita biasa menggunakan fungsi mysql_real_escape_string(), sekarang dapat menggunakan PDO statement prepare() dan bindParam().

<?php
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$stmt = $pdo->prepare('SELECT nama FROM tabel_pengguna WHERE id = :id');
$stmt->bindParam(':id', filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT), PDO::PARAM_INT);
$stmt->execute();

Pada baris ke-3, masukan dari pengguna diganti dengan sebuah placeholder. Nama untuk placeholder dimulai dengan tanda titik dua (:). Fungsi filter_input() pada baris ke-4 digunakan untuk memastikan masukan dari luar, dalam hal ini $_GET['id'], benar-benar berupa angka integer. Dengan PDO statement dan bindParam() di atas, kode Anda akan aman dari serangan SQL Injection.

Meskipun kode di atas dapat berjalan dengan baik, namun Anda akan mendapat pesan peringatan (notice):

Only variables should be passed by reference bla.. bla..

Itu terjadi karena parameter kedua dari bindParam() harus berupa variabel. Jadi kode di atas diubah menjadi seperti ini:

<?php
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$stmt = $pdo->prepare('SELECT nama FROM tabel_pengguna WHERE id = :id');

$id = filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();

Untuk contoh berikutnya, akan kita coba query INSERT dan UPDATE.

<?php
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$stmt = $pdo->prepare('INSERT INTO tabel_pengguna (id, nama) VALUES (:id, :nama)');

$id = filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT);
$nama = filter_input(INPUT_GET, 'nama', FILTER_SANITIZE_STRING)
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->bindParam(':nama', $nama, PDO::PARAM_STR);
$stmt->execute();
<?php
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$stmt = $pdo->prepare('UPDATE tabel_pengguna SET nama = :nama WHERE id = :id');

$id = filter_input(INPUT_GET, 'id', FILTER_SANITIZE_NUMBER_INT);
$nama = filter_input(INPUT_GET, 'nama', FILTER_SANITIZE_STRING)
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->bindParam(':nama', $nama, PDO::PARAM_STR);
$stmt->execute();

Cara mencoba kode-kode di atas, langsung ketik saja di address bar. Contoh: localhost/namafile.php?id=10&nama=ronaldo. Jangan lupa isi variabel-variabel $host, $dbname, $user, dan $pass.

14. July 2012 by Sibudi
Categories: PHP | Tags: , , | 1 comment

Menyesuaikan Zona Waktu di MySQL dan PHP

Ketika membuat sebuah aplikasi website, seringkali waktu yang ditunjukkan oleh server tidak sama dengan waktu client. Ini terjadi karena server terletak di zona waktu yang berbeda dengan client. Misalnya server yang berlokasi di USA, jelas berada di zona waktu yang berbeda dengan client di Indonesia.

echo date('d-m-Y H:i:s');

Kode PHP di atas akan menampilkan waktu aktual pada server. Jika dicoba di localhost tentu saja waktunya akan sama seperti komputer lokal, namun hasilnya bisa berbeda jika dicoba pada server web Anda. Agar hasilnya sesuai dengan waktu di komputer kita, tambahkan pengaturan zona waktu.

date_default_timezone_set('Asia/Jakarta');
echo date('d-m-Y H:i:s');

Untuk zona waktu yang lain bisa menyesuaikan.

Namun cara di atas memiliki beberapa kelemahan, terutama pada aplikasi yang menggunakan database. Selain kemungkinan terkena bug Y2K38, MySQL dan PHP memiliki pengaturan zona waktu yang terpisah. Misal kita menjalankan fungsi NOW() pada MySQL, waktu yang ditampilkan tidak sesuai dengan zona waktu kita. Selain itu, aplikasi juga membutuhkan tambahan proses setiap kali mengolah data dari field waktu pada MySQL agar sesuai dengan zona waktu kita.

Agar proses penyesuaian waktu bisa berjalan secara otomatis, kita harus mengetahui berapa selisih waktu client dengan UTC, kemudian beritahukan kepada MySQL. Pertama-tama dengan bantuan class Datetime, kita dapatkan offset (untuk menutupi selisih yang ada) dalam detik, kemudian mudah saja kita konversikan ke dalam menit dan jam.

$sekarang = new DateTime();
$menit = $sekarang -> getOffset() / 60;

Kemudian cari tau apakah offset bernilai positif atau negatif, lalu konversikan saja ke bilangan positif untuk memudahkan penghitungan.

$tanda = ($menit < 0 ? -1 : 1);
$menit = abs($menit);
$jam = floor($menit / 60);
$menit -= $jam * 60;

Gunakan fungsi sprintf untuk memformat string agar bisa diterima MySQL (format yang bisa diterima misalnya: +07:00).

$offset = sprintf('%+d:%02d', $tanda * $jam, $menit);

Terakhir jalankan query SET time_zone setelah mengkoneksikan aplikasi dengan database. Silakan ganti dengan koneksi database yang Anda gunakan.

mysql_connect($server, $username, $password);
mysql_select_db($database);

mysql_query("SET time_zone = '$offset'");

Akhirnya pengaturan zona waktu antara PHP dan MySQL telah sesuai. Berikut ini adalah gabungan kode-kode snippet di atas.

<?php
date_default_timezone_set('Asia/Jakarta');

$sekarang = new DateTime();
$menit = $sekarang -> getOffset() / 60;

$tanda = ($menit < 0 ? -1 : 1);
$menit = abs($menit);
$jam = floor($menit / 60);
$menit -= $jam * 60;

$offset = sprintf('%+d:%02d', $tanda * $jam, $menit);

mysql_connect($server, $username, $password);
mysql_select_db($database);

mysql_query("SET time_zone = '$offset'");

13. July 2012 by Sibudi
Categories: PHP | Tags: , , | 27 comments

← Older posts

Newer posts →