1. Membundarkan nombor nyata

Seperti yang telah kita bincangkan, apabila nombor nyata diberikan kepada pembolehubah int, ia sentiasa dibundarkan ke bawah kepada integer terkecil yang terdekat - bahagian pecahan dibuang begitu sahaja.

Tetapi adalah mudah untuk membayangkan situasi apabila nombor pecahan perlu dibundarkan kepada integer terdekat dalam mana-mana arah atau pun dibundarkan ke atas. Apa yang anda lakukan dalam kes ini?

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


Math.round()kaedah

Kaedah Math.round()membundarkan nombor kepada integer terdekat:

long x = Math.round(real_number)

Tetapi terdapat satu lagi nuansa di sini: kaedah ini mengembalikan longinteger (bukan int). Oleh kerana nombor nyata boleh menjadi sangat besar, pencipta Java memutuskan untuk menggunakan jenis integer terbesar Java yang tersedia: long.

Sehubungan itu, jika pengaturcara ingin memberikan hasil kepada intpembolehubah, maka dia mesti menunjukkan secara jelas kepada pengkompil bahawa dia menerima kemungkinan kehilangan data (sekiranya nombor yang terhasil tidak sesuai dengan jenis int).

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

Contoh:

Kenyataan Hasilnya
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()kaedah

Kaedah Math.ceil()membundarkan nombor kepada integer. Berikut adalah contoh:

Kenyataan Hasilnya
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()kaedah

Kaedah Math.floor()membundarkan nombor ke bawah kepada integer. Berikut adalah contoh:

Kenyataan Hasilnya
int x = (int) Math.floor(4.1);
4
int x = (int) Math.floor(4.5);
4
int x = (int) Math.floor(4.9);
4

Sudah tentu, apabila membundarkan nombor ke bawah kepada integer, lebih mudah untuk menggunakan operator cast jenis:(int)

Kenyataan Hasilnya
int x = (int) 4.9
4

Jika anda merasa sukar untuk mengingati nama-nama ini, pelajaran bahasa Inggeris pendek akan membantu:

  • Mathbermaksud matematik
  • Roundbermaksud bulat
  • Ceilingbermaksud siling
  • Floorbermaksud lantai

2. Bagaimana nombor titik terapung distrukturkan

Jenis doubleboleh menyimpan nilai dalam julat dari hingga . Julat besar nilai ini (berbanding dengan jenis) dijelaskan oleh fakta bahawa jenis (serta ) mempunyai struktur dalaman yang sama sekali berbeza daripada jenis integer. Secara dalaman, jenis mengekodkan nilainya sebagai dua nombor: yang pertama dipanggil mantissa , dan yang kedua dipanggil eksponen .-1.7*10308+1.7*10308intdoublefloatdouble

Katakan kita mempunyai nombor 123456789dan menyimpannya sebagai doublepembolehubah. Apabila kita melakukannya, nombor itu ditukar kepada , dan secara dalaman jenis menyimpan dua nombor — dan . Significand ("bahagian penting nombor" atau mantissa) diserlahkan dengan warna merah, manakala eksponen diserlahkan dengan warna biru.1.23456789*108double234567898

Pendekatan ini memungkinkan untuk menyimpan kedua-dua nombor yang sangat besar dan yang sangat kecil. Tetapi kerana perwakilan nombor adalah terhad kepada 8 bait (64 bit) dan beberapa bit digunakan untuk menyimpan eksponen ( serta tanda mantissa dan tanda eksponen), digit maksimum yang tersedia untuk mewakili mantissa ialah 15 .

Ini adalah penerangan yang sangat ringkas tentang cara nombor nyata distrukturkan.


3. Kehilangan ketepatan apabila bekerja dengan nombor nyata

Apabila bekerja dengan nombor nyata, sentiasa ingat bahawa nombor nyata tidak tepat . Mungkin sentiasa ada ralat pembundaran dan ralat penukaran apabila menukar daripada perpuluhan kepada binari. Selain itu, sumber ralat yang paling biasa ialah kehilangan ketepatan apabila menambah/menolak nombor pada skala yang berbeza secara radikal.

Fakta terakhir ini agak mengejutkan untuk pengaturcara baru.

Jika kita tolak daripada , kita dapat .1/109109109

Menolak nombor pada skala yang sangat berbeza Penjelasan
1000000000.000000000;
-         0.000000001;
 1000000000.000000000;
Nombor kedua adalah sangat kecil , yang akan menyebabkan significandnya (diserlahkan dalam warna kelabu) diabaikan. 15 digit bererti diserlahkan dalam oren.

Apa yang boleh kita katakan, pengaturcaraan tidak sama dengan matematik.


4. Perangkap apabila membandingkan nombor nyata

Bahaya lain terletak pada penantian pengaturcara apabila mereka membandingkan nombor nyata. Ia timbul apabila bekerja dengan nombor nyata, kerana ralat pusingan boleh terkumpul. Hasilnya ialah terdapat situasi apabila nombor nyata dijangka sama, tetapi tidak. Atau sebaliknya: nombor dijangka berbeza, tetapi ia adalah sama.

Contoh:

Kenyataan Penjelasan
double a = 1000000000.0;
double b = 0.000000001;
double c = a - b;
Nilai pembolehubah a akan menjadi 1000000000.0
Nilai pembolehubah c akan menjadi 1000000000.0
(nombor dalam b pembolehubah adalah terlalu kecil)

Dalam contoh di atas, adan ctidak sepatutnya sama, tetapi mereka adalah.

Atau mari kita ambil contoh lain:

Kenyataan Penjelasan
double a = 1.00000000000000001;
double b = 1.00000000000000002;
Nilai pembolehubah a akan 1.0
Nilai pembolehubah b akan1.0

5. Fakta menarik tentangstrictfp

Java mempunyai strictfpkata kunci khas ( strict f loating p oint ), yang tidak terdapat dalam bahasa pengaturcaraan lain. Dan adakah anda tahu mengapa anda memerlukannya? Ia memburukkan ketepatan operasi dengan nombor titik terapung. Inilah kisah bagaimana ia berlaku:

Pencipta Java:
Kami benar-benar mahu Java menjadi sangat popular dan menjalankan program Java pada seberapa banyak peranti yang mungkin. Oleh itu, kami memastikan bahawa spesifikasi untuk mesin Java mengatakan bahawa semua program mesti berjalan dengan cara yang sama pada semua jenis peranti!
Pembuat pemproses Intel:
Hei, semua orang! Kami telah menambah baik pemproses kami, dan kini semua nombor nyata diwakili menggunakan 10-bait dan bukannya 8-bait di dalam pemproses kami. Lebih banyak bait bermakna lebih banyak digit bererti. Apakah maksudnya? betul! Kini pengiraan saintifik anda akan menjadi lebih tepat!
Para saintis dan semua orang yang terlibat dalam pengiraan ultra-tepat:
Sejuk! Bagus. Berita baik!
Pencipta Java:
Tidak-tidak-tidak, kamu semua! Kami telah memberitahu anda bahawa semua program Java mesti dijalankan sama pada semua peranti . Kami akan melumpuhkan secara paksa keupayaan untuk menggunakan nombor nyata 10-bait dalam pemproses Intel.
Kini semuanya baik-baik saja! Jangan berterima kasih kepada kami.
Para saintis dan semua orang yang terlibat dalam pengiraan ultra-tepat:
Adakah anda sudah gila sepenuhnya? Cepat dapatkan semuanya kembali seperti sediakala!
Pencipta Java:
Kawan-kawan, ini untuk kebaikan anda sendiri! Bayangkan sahaja: semua program Java berjalan dengan cara yang sama pada semua peranti . Itu sangat keren!
Para saintis dan semua orang yang terlibat dalam pengiraan ultra-tepat:
Tidak. Ia tidak hebat sama sekali. Cepat letak semula segalanya! Atau tahu di mana kami akan meletakkan Java anda?
Pencipta Java:
Hmm. Mengapa anda tidak berkata begitu segera? Sudah tentu, kami akan meletakkannya kembali.
Kami memulihkan keupayaan anda untuk menggunakan semua ciri pemproses terkini.
Ngomong-ngomong... Kami juga menambah strictfpkata kunci pada bahasa tersebut. Jika anda menulisnya sebelum nama fungsi, maka semua operasi yang melibatkan nombor nyata di dalam fungsi itu akan sama buruknya pada semua peranti !