Akankah komputer mencoba membagi dengan nol?


59

Kita semua tahu 0/0adalah Undefineddan kembali kesalahan jika saya harus memasukkannya ke dalam kalkulator, dan jika saya harus membuat sebuah program (dalam C setidaknya) OS akan menghentikannya ketika saya mencoba untuk membagi dengan nol.

Tetapi yang saya bertanya-tanya adalah apakah komputer bahkan mencoba untuk membaginya dengan nol , atau apakah ia hanya memiliki "perlindungan bawaan", sehingga ketika "melihat" 0/0ia mengembalikan kesalahan bahkan sebelum mencoba menghitungnya?


10
0/0 tidak terdefinisi, nomor lain / 0 adalah jenis kesalahan yang berbeda, Anda tampaknya membingungkan keduanya
edc65

7
Angka apa pun yang dibagi 0 tidak terdefinisi, secara matematis.
ManoDestra

12
@ jwg: "jika memang memiliki nilai itu akan menjadi 1" - belum tentu; ada seluruh cabang matematika yang ditujukan untuk apa nilainya dalam keadaan yang berbeda :)
psmears

11
Untuk memperjelas terminologi di sini, 0/0 disebut bentuk tak tentu sementara x / 0 untuk bukan nol x tidak ditentukan . Perhitungan yang berakhir dengan 0/0 sering dapat dihitung dengan cara yang berbeda untuk memberikan jawaban yang nyata, sedangkan x / 0 pada dasarnya tidak berarti.
Era

9
@ jwg Anda mungkin tertarik pada aturan l'hopital. Jelas ada kasus di mana 0/0 tidak menyiratkan nilai 1.
d0nut

Jawaban:


74

CPU memiliki deteksi bawaan. Sebagian besar arsitektur set instruksi menentukan bahwa CPU akan menjebak ke handler pengecualian untuk integer divide dengan nol (saya tidak berpikir itu peduli jika dividennya nol).

Ada kemungkinan bahwa pemeriksaan untuk nol pembagi terjadi secara paralel dalam perangkat keras bersama dengan upaya untuk melakukan pembagian, namun, deteksi kondisi yang menyinggung secara efektif membatalkan pembagian dan perangkap sebagai gantinya, jadi kami tidak dapat benar-benar mengetahui apakah ada bagian yang dari itu mencoba divisi atau tidak.

(Perangkat keras sering bekerja seperti itu, melakukan banyak hal secara paralel dan kemudian memilih hasil yang sesuai setelah itu karena masing-masing operasi dapat segera memulai alih-alih membuat serial tentang pilihan operasi yang sesuai.)

Mekanisme trap to exception yang sama juga akan digunakan ketika deteksi overflow dihidupkan, yang Anda minta biasanya dengan menggunakan instruksi add / sub / mul yang berbeda (atau tanda pada instruksi tersebut).

Divisi floating point juga telah dibangun dalam deteksi untuk divide oleh nol, tetapi mengembalikan nilai yang berbeda ( IEEE 754 menentukan NaN ) alih-alih menjebak ke handler pengecualian.


Secara hipotesis, jika CPU menghilangkan deteksi apa pun untuk mencoba membaginya dengan nol, masalahnya dapat mencakup:

  • menggantung CPU (mis. dalam inf. loop) - ini mungkin terjadi jika CPU menggunakan algoritma untuk membagi yang berhenti ketika pembilang kurang dari pembagi (dalam nilai absolut). Gantung seperti ini akan dianggap sebagai crash CPU.
  • jawaban sampah (kemungkinan dapat diprediksi), jika CPU menggunakan penghitung untuk mengakhiri pembagian pada jumlah langkah pembagian maksimum yang dimungkinkan (mis. 31 atau 32 pada mesin 32-bit).

51
@Ankush "Sistem crash" sebenarnya bukan sesuatu yang terjadi pada tingkat CPU. Perilaku CPU yang paling mungkin tidak terjebak pada pembagian dengan nol adalah bahwa ia hanya melakukan operasi pembagian, menghasilkan beberapa hasil omong kosong dan terus berjalan. Sama seperti ketika Anda menambahkan dua bilangan bulat yang terjadi melimpah.
Ixrec

6
Untuk floating point, pilihan antara "NaN" dan "trap" biasanya dapat diselesaikan dengan membalik bendera di FPU.
Vatine

10
@Ankush Dalam kasus apa yang dikatakan lxrec tidak jelas: sejauh menyangkut CPU, tidak ada yang namanya crash.
user253751

7
@Ankush Beberapa situasi menyebabkan "sistem crash" tingkat CPU. Dalam kasus tersebut kita berbicara tentang hal-hal seperti shutdown perlindungan termal (overheat protection), triple faults dan situasi serupa. Hampir setiap kerusakan yang Anda temui dalam penggunaan biasa, termasuk opcode yang tidak valid , ditangani dengan menjebak dan memulihkan dengan cara tertentu, atau hanya mengabaikan kesalahan dan melanjutkan eksekusi dalam keadaan yang berpotensi tidak bersih, mungkin telah menetapkan beberapa flag kesalahan.
CVn

8
Jika Anda tidak menjebak pembagian dengan nol, hasilnya adalah, dalam bahasa pemrograman, "Perilaku Tidak Terdefinisi." Ini berarti komputer dapat melakukan apa saja. Ini mungkin, seperti Bergi menyebutkan, memasuki lingkaran kereta dan menggantung. Ini mungkin hanya menghasilkan beberapa seri bit yang tidak ditentukan yang merupakan apa yang terjadi dari implementasi logika pembagian mereka (ingat, komputer tidak "membagi" dalam pengertian matematika. Ia melakukan operasi pada dua angka, yang cukup dekat dengan pembagian yang biasanya kita sebut "divisi" .. lihat juga floating point roundoff).
Cort Ammon

34

Itu tergantung pada bahasa, pada kompiler, pada apakah Anda menggunakan bilangan bulat atau angka floating point, dan sebagainya.

Untuk angka floating point, sebagian besar implementasi menggunakan standar IEEE 754 , di mana pembagian dengan 0 didefinisikan dengan baik. 0/0 memberikan hasil NaN yang jelas (bukan-angka), dan x / 0 untuk x ≠ 0 memberikan + Infinity atau -Infinity, tergantung pada tanda x.

Dalam bahasa seperti C, C ++ dll pembagian dengan nol memanggil perilaku tidak terdefinisi. Jadi menurut definisi bahasa, apa pun bisa terjadi. Terutama hal-hal yang tidak Anda inginkan terjadi. Seperti semuanya bekerja dengan sangat baik ketika Anda menulis kode dan menghancurkan data saat pelanggan Anda menggunakannya. Jadi dari sudut pandang bahasa, jangan lakukan ini . Beberapa bahasa menjamin bahwa aplikasi Anda akan macet; terserah mereka bagaimana ini diterapkan. Untuk bahasa-bahasa tersebut, pembagian dengan nol akan macet.

Banyak prosesor memiliki semacam instruksi "bagi" built-in, yang akan berperilaku berbeda tergantung pada prosesor. Pada prosesor Intel 32bit dan 64 bit, instruksi "bagi" akan membuat aplikasi Anda macet ketika Anda mencoba membagi dengan nol. Prosesor lain mungkin berperilaku berbeda.

Jika kompiler mendeteksi bahwa pembagian dengan nol akan terjadi ketika Anda mengeksekusi beberapa kode, dan kompiler itu baik untuk penggunanya, itu kemungkinan akan memberi Anda peringatan, dan menghasilkan instruksi "bagi" yang sudah ada di dalamnya sehingga perilakunya adalah sama.


22
"Pada prosesor Intel 32bit dan 64 bit, instruksi" bagi "akan membuat aplikasi Anda macet ketika Anda mencoba membagi dengan nol." Kutipan diperlukan. CPU tidak memiliki gagasan tentang aplikasi, mereka menjalankan instruksi dan (jika kami menyertakan MMU) menegakkan batas akses memori (kecuali dalam cincin 0 , atau setara dalam arsitektur non-Intel-x86). Bahwa instruksi adalah bagian dari Aplikasi A daripada Aplikasi B atau Sistem Operasi Komponen C tidak relevan dengan CPU; apakah instruksi dapat berupa Instruksi X atau menggunakan Memory Address Y yang relevan.
CVn

1
Untuk menambahkan komentar ke @ MichaelKjörling: OS memiliki cara untuk memberitahukan aplikasi ini (dan jenis kesalahan lainnya). Di dunia windows itu adalah EXCEPTION_INT_DIVIDE_BY_ZEROnilai EXCEPTION_RECORDyang akan ditangani oleh Strlered Exception Handling Handler Handler yang diinstal (mudah-mudahan)
user45891

1
Terkadang mereka melakukan hal-hal selain menjamin bahwa aplikasi Anda akan macet. Misalnya, banyak bahasa / platform menjamin bahwa mereka akan memberikan pengecualian pada pembagian dengan nol. Anda kemudian dapat menangkap dan menangani pengecualian tersebut tanpa menabrak.
reirab

2
Anda dapat menghapus "mungkin" dalam "Prosesor lain mungkin berperilaku berbeda": Pada Platform PowerPC, divisi hanya menghasilkan hasil nol pada pembagian dengan nol. Yang jauh lebih berguna daripada perilaku panik platform X86.
cmaster

13

Sepertinya Anda bertanya-tanya apa yang akan terjadi jika seseorang membuat CPU yang tidak secara eksplisit memeriksa nol sebelum membaginya. Apa yang akan terjadi tergantung sepenuhnya pada implementasi divisi. Tanpa merinci, satu jenis implementasi akan menghasilkan hasil yang memiliki semua bit ditetapkan, misalnya 65535 pada CPU 16-bit. Yang lain mungkin menutup telepon.


1

Tapi yang saya ingin tahu adalah apakah komputer bahkan mencoba untuk membagi dengan nol, atau apakah itu hanya memiliki "built in protection", sehingga ketika "melihat" 0/0 ia mengembalikan kesalahan bahkan sebelum mencoba untuk menghitungnya?

Karena x/0tidak masuk akal, titik, komputer harus selalu memeriksa pembagian dengan nol. Ada masalah di sini: Programmer ingin menghitung (a+b)/ctanpa harus repot memeriksa apakah perhitungan itu masuk akal. Respons di bawah-the-kap untuk pembagian dengan nol oleh CPU + nomor jenis + sistem operasi + bahasa adalah baik melakukan sesuatu yang agak drastis (misalnya, crash program) atau melakukan sesuatu yang terlalu jinak (misalnya, menciptakan nilai yang membuat tidak ada akal seperti floating point IEEE NaN, angka yang "Bukan Angka").

Dalam pengaturan biasa, seorang programmer diharapkan tahu apakah itu (a+b)/cmasuk akal. Dalam konteks ini, tidak ada alasan untuk memeriksa pembagian dengan nol. Jika pembagian dengan nol tidak terjadi, dan jika bahasa mesin + bahasa implementasi + tipe data + respons sistem operasi untuk membuat program macet, tidak apa-apa. Jika responsnya adalah menciptakan nilai yang pada akhirnya mungkin mencemari setiap angka dalam program, tidak apa-apa juga.

Baik "sesuatu yang drastis" atau "terlalu jinak" adalah hal yang tepat untuk dilakukan di dunia komputasi dengan keandalan tinggi. Respons default itu mungkin membunuh seorang pasien, menabrak pesawat, atau membuat bom meledak di tempat yang salah. Dalam lingkungan keandalan yang tinggi, seorang programmer yang menulis (a+b)/cakan dipilih mati selama tinjauan kode, atau di zaman modern, mungkin dipilih mati secara otomatis oleh alat yang memeriksa konstruksi verboten. Dalam lingkungan ini, programmer itu seharusnya telah menulis sesuatu di sepanjang baris div(add(a,b),c)(dan mungkin beberapa memeriksa status kesalahan). Di bawah kap, fungsi div(dan juga add) fungsi / makro melindungi terhadap pembagian dengan nol (atau meluap dalam kasus add). Apa yang dibutuhkan oleh perlindungan itu sangat spesifik untuk implementasi.


Hanya karena NaN tidak mematuhi aritmatika yang Anda pelajari di sekolah tidak berarti itu tidak masuk akal. Ini mematuhi aritmatika yang berbeda
Caleth

-2

Kami tahu sekarang x/0dan 0/0tidak memiliki jawaban yang jelas. Apa yang terjadi jika Anda tetap mencoba menghitung 0/0?

Pada sistem modern, perhitungan dilewatkan ke MPU dalam CPU dan ditandai sebagai operasi ilegal, kembali NaN.

Pada sistem yang jauh lebih tua, seperti komputer rumah '80 -an yang tidak memiliki divisi on-chip, perhitungan dilakukan oleh perangkat lunak apa pun yang sedang berjalan. Ada beberapa pilihan yang mungkin:

  • Kurangi salinan pembagi yang lebih kecil dan lebih kecil sampai nilainya mencapai nol dan catat salinan yang ukurannya dikurangi
    • Jika memeriksa nol sebelum pengurangan pertama, itu akan keluar dengan cepat dan hasilnya akan 0
    • Jika diasumsikan harus mampu mengurangi setidaknya satu kali, hasilnya akan menjadi 1
  • Hitung logaritma dari kedua angka, kurangi dan naikkan e ke kekuatan hasil. Metode yang sangat tidak efisien dibandingkan dengan metode pengurangan di atas, tetapi secara matematis valid
    • Overflow mungkin terjadi saat mencoba menghitung log(0)dan perangkat lunak akan menggunakan rutinitas penanganan kesalahannya, atau crash
    • Perangkat lunak mungkin berasumsi bahwa semua logaritma dapat dihitung dalam jumlah langkah yang tetap dan mengembalikan nilai yang besar, tetapi salah. Karena kedua logaritma akan sama, perbedaannya adalah 0dan e 0 = 1, memberikan hasil1

Dengan kata lain, itu akan tergantung pada implementasi apa yang akan terjadi dan akan mungkin untuk menulis perangkat lunak yang menghasilkan hasil yang benar dan dapat diprediksi untuk setiap nilai tetapi nilai-nilai yang tampaknya aneh untuk 0/0itu tetap saja, masih konsisten secara internal.


3
Pertanyaan ini adalah tentang membagi dengan nol dalam bilangan bulat, dan tidak ada yang namanya NaNdalam bilangan bulat.
David Hammen

3
Tidak ada CPU yang akan menghitung log dan kurangi untuk menghitung hasil pembagian. Waktu instruksi logaritma adalah beberapa urutan yang lebih besar dari sebuah divisi. Berapa nilai log (0)?
berjalan

1
@ Davidvidam OP tidak pernah menyebut bilangan bulat, dan siapa pun yang mengomentari pertanyaan itu. Bilangan bulat hanya disebutkan dalam jawaban.
CJ Dennis

@wallyk Saya sudah mengatakan dalam jawaban saya bahwa logaritma adalah very inefficientuntuk pembagian. Biaya untuk hitung adalah (penjumlahan = pengurangan) <= perkalian <= pembagian. Jika Anda tidak memiliki MPU yang dapat melakukan pembagian dalam jumlah siklus clock yang sama dengan penambahan (biasanya satu), maka pembagian lebih mahal daripada penambahan dan pengurangan dan biasanya lebih mahal dari perkalian juga.
CJ Dennis
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.