1. Pembulatan bilangan real

Seperti yang telah kita diskusikan, ketika bilangan real ditugaskan ke variabel int, itu selalu dibulatkan ke bilangan bulat terdekat yang lebih kecil - bagian pecahan dibuang begitu saja.

Tetapi mudah untuk membayangkan situasi ketika bilangan pecahan perlu dibulatkan ke bilangan bulat terdekat di salah satu arah atau bahkan dibulatkan. Apa yang Anda lakukan dalam kasus ini?

Untuk ini dan untuk banyak situasi serupa, Java memiliki kelas Math, yang memiliki metode round(), ceil(), dan floor().


Math.round()metode

Metode ini Math.round()membulatkan angka ke bilangan bulat terdekat:

long x = Math.round(real_number)

Tapi ada nuansa lain di sini: metode ini mengembalikan longbilangan bulat (bukan int). Karena bilangan real bisa sangat besar, pembuat Java memutuskan untuk menggunakan tipe bilangan bulat terbesar yang tersedia di Java: long.

Oleh karena itu, jika seorang programmer ingin menetapkan hasil ke suatu intvariabel, maka dia harus secara eksplisit menunjukkan kepada kompiler bahwa dia menerima kemungkinan hilangnya data (jika angka yang dihasilkan tidak sesuai dengan suatu inttipe).

int x = (int) Math.round(real_number)

Contoh:

Penyataan Hasil
int x = (int) Math.round(4.1);
4
int x = (int) Math.round(4.5);
5
int x = (int) Math.round(4.9);
5

Math.ceil()metode

Metode ini Math.ceil()membulatkan angka ke atas menjadi bilangan bulat. Berikut ini contohnya:

Penyataan Hasil
int x = (int) Math.ceil(4.1);
5
int x = (int) Math.ceil(4.5);
5
int x = (int) Math.ceil(4.9);
5

Math.floor()metode

Metode ini Math.floor()membulatkan angka ke bawah menjadi bilangan bulat. Berikut ini contohnya:

Penyataan Hasil
int x = (int) Math.floor(4.1);
4
int x = (int) Math.floor(4.5);
4
int x = (int) Math.floor(4.9);
4

Tentu saja, saat membulatkan angka ke bilangan bulat, lebih mudah menggunakan operator tipe cast:(int)

Penyataan Hasil
int x = (int) 4.9
4

Jika Anda kesulitan mengingat nama-nama ini, pelajaran bahasa Inggris singkat akan membantu:

  • Mathberarti matematika
  • Roundberarti bulat
  • Ceilingartinya plafon
  • Floorberarti lantai

2. Bagaimana struktur bilangan floating-point

Jenis doubledapat menyimpan nilai dalam rentang dari hingga . Kisaran nilai yang sangat besar ini (dibandingkan dengan tipe) dijelaskan oleh fakta bahwa tipe (serta ) memiliki struktur internal yang sama sekali berbeda dari tipe bilangan bulat. Secara internal, tipe mengkodekan nilainya sebagai dua angka: yang pertama disebut mantissa , dan yang kedua disebut eksponen .-1.7*10308+1.7*10308intdoublefloatdouble

Katakanlah kita memiliki nomor 123456789dan menyimpannya sebagai doublevariabel. Saat kita melakukannya, angkanya diubah menjadi , dan secara internal tipe menyimpan dua angka — dan . Significand ("bagian penting dari angka" atau mantissa) disorot dengan warna merah, sedangkan eksponen disorot dengan warna biru.1.23456789*108double234567898

Pendekatan ini memungkinkan untuk menyimpan jumlah yang sangat besar dan sangat kecil. Tetapi karena representasi angka dibatasi hingga 8 byte (64 bit) dan beberapa bit digunakan untuk menyimpan eksponen ( serta tanda mantissa dan tanda eksponen), digit maksimum yang tersedia untuk mewakili mantissa adalah 15 .

Ini adalah deskripsi yang sangat disederhanakan tentang bagaimana bilangan real disusun.


3. Kehilangan presisi saat bekerja dengan bilangan real

Saat bekerja dengan bilangan real, ingatlah selalu bahwa bilangan real tidak eksak . Mungkin selalu ada kesalahan pembulatan dan kesalahan konversi saat mengubah dari desimal ke biner. Selain itu, sumber kesalahan yang paling umum adalah hilangnya presisi saat menambahkan/mengurangi angka pada skala yang sangat berbeda.

Fakta terakhir ini sedikit mencengangkan bagi pemrogram pemula.

Jika kita kurangi dari , Kita dapatkan .1/109109109

Mengurangkan angka pada skala yang sangat berbeda Penjelasan
 1000000000.000000000;
-         0.000000001;
 1000000000.000000000;
Angka kedua sangat kecil , yang akan menyebabkan signifikansinya (disorot dengan warna abu-abu) diabaikan. 15 digit signifikan disorot dalam warna oranye.

Apa yang bisa kita katakan, pemrograman tidak sama dengan matematika.


4. Jebakan saat membandingkan bilangan real

Bahaya lain terletak pada menunggu programmer ketika mereka membandingkan bilangan real. Itu muncul saat bekerja dengan bilangan real, karena kesalahan pembulatan dapat terakumulasi. Hasilnya adalah ada situasi ketika bilangan real diharapkan sama, tetapi ternyata tidak. Atau sebaliknya: angkanya diharapkan berbeda, tetapi sama.

Contoh:

Penyataan Penjelasan
double a = 1000000000.0;
double b = 0.000000001;
double c = a - b;
Nilai variabel a akan menjadi 1000000000.0
Nilai variabel c akan menjadi 1000000000.0
(jumlah dalam b variabel terlalu kecil)

Dalam contoh di atas, aand cseharusnya tidak sama, tetapi memang demikian.

Atau mari kita ambil contoh lain:

Penyataan Penjelasan
double a = 1.00000000000000001;
double b = 1.00000000000000002;
Nilai variabel a akan menjadi 1.0
Nilai variabel b akan menjadi1.0

5. Fakta menarik tentangstrictfp

Java memiliki kata kunci khusus (strict floating pointstrictfp ) , yang tidak ditemukan dalam bahasa pemrograman lain . Dan tahukah Anda mengapa Anda membutuhkannya? Itu memperburuk keakuratan operasi dengan angka floating-point. Inilah kisah tentang bagaimana hal itu terjadi:

Pencipta Java:
Kami benar-benar ingin Java menjadi sangat populer dan menjalankan program Java di sebanyak mungkin perangkat. Jadi kami memastikan bahwa spesifikasi mesin Java menyatakan bahwa semua program harus berjalan dengan cara yang sama di semua jenis perangkat!
Pembuat prosesor Intel:
Hai semuanya! Kami telah meningkatkan prosesor kami, dan sekarang semua bilangan real diwakili menggunakan 10-byte, bukan 8-byte di dalam prosesor kami. Lebih banyak byte berarti lebih banyak digit signifikan. Maksudnya itu apa? Itu benar! Sekarang perhitungan ilmiah Anda akan lebih akurat!
Ilmuwan dan semua orang yang terlibat dalam perhitungan ultra-presisi:
Dingin! Bagus sekali. Berita bagus!
Pencipta Java:
Tidak-tidak-tidak, kalian! Kami telah memberi tahu Anda bahwa semua program Java harus berjalan sama di semua perangkat . Kami akan menonaktifkan secara paksa kemampuan untuk menggunakan bilangan real 10-byte di dalam prosesor Intel.
Sekarang semuanya baik-baik saja lagi! Jangan berterima kasih kepada kami.
Ilmuwan dan semua orang yang terlibat dalam perhitungan ultra-presisi:
Apakah Anda benar-benar sudah gila? Cepat kembalikan semuanya seperti semula!
Pencipta Java:
Teman-teman, ini untuk kebaikanmu sendiri! Bayangkan saja: semua program Java berjalan dengan cara yang sama di semua perangkat . Itu sangat keren!
Ilmuwan dan semua orang yang terlibat dalam perhitungan ultra-presisi:
Tidak. Itu tidak keren sama sekali. Cepat kembalikan semuanya seperti semula! Atau tahu di mana kami akan meletakkan Java Anda?
Pencipta Java:
Hmm. Mengapa Anda tidak langsung mengatakannya? Tentu saja, kami akan mengembalikannya.
Kami memulihkan kemampuan Anda untuk menggunakan semua fitur prosesor terbaru.
Omong-omong... Kami juga secara khusus menambahkan strictfpkata kunci ke bahasa. Jika Anda menuliskannya sebelum nama fungsi, maka semua operasi yang melibatkan bilangan real di dalam fungsi tersebut akan sama buruknya di semua perangkat !