Isi kandungan:
Video: Unit conversion: gallons to quarts, pints, and cups | Pre-Algebra | Khan Academy 2024
Percayalah atau tidak, komputer - bahkan yang paling berkuasa - mempunyai batasan tertentu apabila membuat pengiraan matematik. Keterbatasan ini biasanya tidak penting, tetapi kadang kala mereka menyelinap dan menggigit anda. Inilah perkara yang anda perlu berhati-hati ketika melakukan matematik di Jawa.
Integer overflow
Masalah asas dengan jenis integer adalah bahawa mereka mempunyai saiz tetap. Akibatnya, terdapat had saiz saiz yang boleh disimpan dalam pembolehubah jenis
pendek
,
int
, atau
panjang
. Walaupun
panjang
pembolehubah boleh memegang nombor-nombor yang besar, lambat laun anda akan mencari nombor yang terlalu besar agar sesuai dengan pemboleh ubah
panjang
.
Baiklah, pertimbangkan contoh ini (diakui tersusun):
int a = 1000000000; Sistem
. keluar. cetak (a);
a + = 1000000000; Sistem
. keluar. cetak (a);
a + = 1000000000; Sistem
. keluar. cetak (a);
a + = 1000000000; Sistem
. keluar. cetak (a);
Di sini anda mengharapkan nilai
untuk mendapatkan lebih besar selepas setiap penambahan. Tetapi inilah output yang dipaparkan:
1000000000
2000000000
-1294967296
-294967296
Penambahan pertama sepertinya berfungsi, tetapi selepas itu, angka itu menjadi negatif! Itu kerana nilai telah mencapai had saiz
int
jenis data. Malangnya, Java tidak memberitahu anda bahawa ralat ini telah berlaku. Ia hanya menyemarakkan pembolehubah
int
penuh dengan bit yang boleh, membuang apa sahaja yang tidak sesuai, dan berharap anda tidak perasan. Kerana cara
int
menyimpan nilai negatif, nilai positif yang besar tiba-tiba menjadi nilai negatif yang besar.
Moral cerita adalah bahawa jika anda bekerja dengan integer besar, anda harus menggunakan
panjang
daripada
int
, kerana
panjang
boleh menyimpan lebih banyak nombor daripada
int
. Jika program anda berurusan dengan nombor yang cukup besar untuk menjadi masalah untuk
panjang
, pertimbangkan untuk menggunakan jenis terapung sebaliknya. Jenis terapung boleh mengendalikan nilai yang lebih besar daripada
panjang
, dan mereka memberitahu anda apabila anda melebihi kapasiti mereka.
Keadaan mengambang terapung
Nombor terapung mempunyai masalah sendiri. Sebagai permulaan, nombor terapung disimpan dengan menggunakan sistem nombor binari (asas 2), tetapi manusia bekerja dengan nombor dalam sistem nombor perpuluhan (asas 10). Malangnya, angka yang tepat untuk menukar antara kedua-dua sistem ini kadang-kadang mustahil. Itu kerana di mana-mana bilangan asas, pecahan tertentu tidak boleh diwakili dengan tepat.
Satu contoh: Base 10 tidak mempunyai cara untuk mewakili pecahan 1/3. Anda boleh menganggarkannya sebagai 0. 3333333, tetapi akhirnya anda mencapai had berapa digit yang boleh anda simpan, jadi anda perlu berhenti. Dalam asas 2, ia berlaku bahawa salah satu pecahan yang anda tidak dapat mewakili dengan tepat ialah nilai perpuluhan 1/10. Dengan kata lain, pemboleh ubah
float
atau
ganda
tidak dapat mewakili
0 dengan tepat. 1
.
Cuba jalankan kod ini:
float x = 0. 1f;
NumberFormat nf = NumberFormat. getNumberInstance ();
nf. setMinimumFractionDigits (10); Sistem
. keluar. println (format nf (x));
Output yang terhasil ialah:
0. 1000000015
Walaupun
0. 1000000015
adalah tutup hingga
0. 1
, tidak tepat.
Dalam kebanyakan kes, matematik titik terapung Jawa cukup dekat untuk tidak menjadi masalah. Margin kesilapan sangat kecil. Jika anda menggunakan Java untuk mengukur saiz rumah anda, anda memerlukan mikroskop elektron untuk melihat ralat. Jika anda menulis aplikasi yang berurusan dengan transaksi kewangan, bagaimanapun, pembulatan biasa kadang-kadang boleh membesarkan kesilapan untuk menjadikannya penting. Anda boleh mengenakan cukai jualan terlalu banyak atau terlalu kecil. Dan dalam kes-kes yang teruk, invois anda mungkin sebenarnya mempunyai ralat tambahan tambahan.
Jenis integer disimpan dalam binari juga, tentu saja. Tetapi bilangan bulat tidak tertakluk kepada kesilapan yang sama jenis jenis terapung adalah kerana integer tidak mewakili pecahan sama sekali - jadi anda tidak perlu bimbang tentang jenis kesalahan ini untuk jenis
integer
.
Divisyen oleh sifar
Menurut kaedah asas matematik, anda tidak dapat membahagikan nombor dengan sifar. Alasannya adalah mudah: Divisyen adalah kebalikan dari pendaraban - yang bermaksud bahawa jika
a * b = c
, ia juga benar bahawa
a = c / b
. Sekiranya anda membenarkan
b
menjadi sifar, pembahagian tidak bermakna, kerana mana-mana bilangan kali sifar adalah sifar. Oleh itu, kedua-dua
a
dan
c
juga perlu menjadi sifar. Ringkasnya, ahli matematik menyelesaikan masalah dilema ini berabad-abad yang lalu dengan mengatakan bahawa pembahagian oleh sifar itu tidak dibenarkan.
Jadi apa yang berlaku jika anda lakukan cuba membahagikan nombor dengan sifar dalam program Java? Jawapannya bergantung kepada sama ada anda membahagi bilangan bulat atau nombor terapung. Sekiranya anda membahagi bilangan bulat, pernyataan yang mencuba pembahagian dengan sifar mencetuskan apa yang disebut pengecualian, yang merupakan cara yang tidak sopan untuk melancarkan program.
Terdapat cara untuk memintas pengecualian ini untuk membolehkan program anda diteruskan yang tidak anda ketahui di sini. Sementara itu, mana-mana program yang anda tulis yang mencuba pembahagian integer dengan kemalangan sifar.
Jika anda cuba untuk membahagikan jenis floating-point dengan sifar, hasilnya tidak begitu mendadak. Sebaliknya, Java menyerah kepada hasil terapung salah satu nilai istimewa yang disenaraikan dalam jadual di bawah. Perenggan berikut menerangkan bagaimana nilai-nilai khas ini ditentukan:
- Jika anda membahagikan nombor dengan sifar, dan tanda kedua-dua nombor adalah sama, hasilnya adalah infiniti positif.
0. 0
dibahagikan dengan0. 0
adalah infiniti positif, seperti-34. 0
dibahagikan dengan-0. 0
. - Jika anda membahagikan nombor dengan sifar, dan tanda-tanda nombor adalah berbeza, hasilnya adalah tak sah negatif.
-40. 0
dibahagikan dengan0. 0
adalah tak terhingga negatif, seperti34. 0
dibahagikan dengan0. 0
. - Jika anda membahagi sifar dengan sifar, hasilnya bukan nombor (NaN), tanpa mengira tanda-tanda.
Terus | Maksud |
POSITIVE_INFINITY
|
Takrif positif |
NEGATIVE_INFINITY
|
Infiniti negatif |
NaN
|
Nisbah terapung boleh positif atau negatif. Java menganggap nol positif dan negatif sama secara numerik. |
Jika anda mencuba untuk mencetak nilai terapung yang mempunyai salah satu nilai istimewa ini, Java menukar nilai kepada rentetan yang sesuai. Katakan bahawa anda melaksanakan pernyataan berikut:
double x = Math. sqrt (-50); // Tidak ada nombor
double y = x;
jika (x == y)
System. keluar. println ("x sama dengan y");
Output konsol yang terhasil ialah
Infinity
Jika
i
-50. 0
, konsol akan memaparkan
-Infinity
, dan jika
i
adalah sifar, konsol akan memaparkan
NaN
.
Perenggan berikut menerangkan beberapa bit akhir yang aneh:
NaN
-
tidak sama dengan dirinya sendiri, yang mungkin mempunyai beberapa kesan aneh. Sebagai contoh:
double x = Math. sqrt (-50); // Tidak ada nombor
double y = x;
jika (x == y)
System. keluar. println ("x sama dengan y");
Hendaklah menganggap, demi argumen, bahawa
jika
menguji sama ada pembolehubah
x
bersamaan dengan pembolehubah
y
. Oleh kerana ujian ini segera mengikuti pernyataan tugasan yang memberikan nilai
x
ke
y
, anda dengan selamat boleh menganggap bahawa
x
sama dengan
y
betul kan?
Salah. Kerana
x
NaN
,
y
juga
NaN
.
NaN
tidak dianggap sama dengan nilai lain, termasuk
NaN
lain. Oleh itu, perbandingan dalam pernyataan
jika
gagal.
Satu lagi akibat yang pelik: Anda tidak boleh mengandaikan bahawa nombor tolak itu sendiri selalu sifar. Pertimbangkan pernyataan ini:
- double z = x - x; // tidak semestinya sifar
Tidakkah pernyataan ini selalu ditetapkan
z
ke sifar? Tidak jika
x
adalah
NaN
. Dalam kes itu, bukan nombor tolak bukan nombor yang masih bukan nombor.
Satu lagi kekasaran: Mana-mana operasi matematik yang melibatkan hasil infiniti sama ada infiniti lain atau
- NaN
. Infinity + 5, sebagai contoh, masih sama dengan infiniti, jadi panggilan Buzz Lightyear "Ke infiniti dan seterusnya! "Hanya tidak akan berlaku. Tetapi infinity minus infinity memberikan anda …
NaN.