Mengapa negatif nol penting?

64

Saya bingung mengapa kita peduli dengan representasi yang berbeda untuk nol positif dan negatif.

Samar-samar saya ingat membaca klaim bahwa memiliki representasi nol negatif sangat penting dalam pemrograman yang melibatkan bilangan kompleks. Saya tidak pernah memiliki kesempatan untuk menulis kode yang melibatkan bilangan kompleks, jadi saya sedikit bingung mengapa ini bisa terjadi.

Artikel Wikipedia tentang konsep ini tidak terlalu membantu; itu hanya membuat klaim samar tentang nol ditandatangani membuat operasi matematika tertentu lebih sederhana di floating point, jika saya mengerti dengan benar. Jawaban ini mencantumkan beberapa fungsi yang berperilaku berbeda, dan mungkin sesuatu dapat disimpulkan dari contoh jika Anda terbiasa dengan bagaimana mereka dapat digunakan. (Meskipun, contoh khusus dari akar kuadrat kompleks tampak salah datar, karena kedua angka tersebut secara matematis setara, kecuali saya memiliki kesalahpahaman.) Tetapi saya tidak dapat menemukan pernyataan yang jelas tentang jenis masalah yang akan Anda hadapi jika tidak ada. Semakin banyak sumber daya matematis yang dapat saya temukan menyatakan bahwa tidak ada yang membedakan antara keduanya dari perspektif matematika, dan artikel Wikipedia tampaknya menyarankan bahwa ini jarang terlihat di luar komputasi selain dari menggambarkan batas.

Jadi mengapa nol negatif bernilai dalam komputasi? Saya yakin saya hanya melewatkan sesuatu.

jpmc26
sumber
6
Nol negatif dapat menandakan underflow dalam angka floating point IEEE, tetapi lebih dari itu, penggunaannya tampaknya kontroversial dan tidak jelas. Jika saya menebak, saya akan mengatakan bahwa nol negatif diwakili dalam IEEE floating point karena ... yah, Anda bisa. Untuk perjalanan yang bahkan lebih menarik, lihat informasi tentang sinyal titik mengambang yang memberi NaN.
Robert Harvey
1
Jika contoh khusus adalah "1 / 0,0" / "1 / -0,0", 0 adalah potongan cabang untuk 1 / x dan batasnya tergantung pada apakah Anda mendekatinya dari bawah atau atas.
Vatine
@Vatine Tidak, contoh khusus adalah sqrt(-1+0i) = idan sqrt(-1-0i) = -i, meskipun berpakaian dengan sintaks yang tepat untuk beberapa bahasa pemrograman, saya percaya. Saya akan mengedit agar lebih jelas.
jpmc26
3
Saya mencari Programmer , Stack Overflow , Ilmu Komputer , Matematika , dan Teknik . Satu-satunya pertanyaan yang dapat saya temukan adalah Penggunaan untuk nilai titik nol mengambang negatif? . Ini tidak mungkin hanya kedua kalinya ini muncul!
Saya benar-benar terkejut bahwa bilangan kompleks belum muncul sama sekali dalam jawaban, terutama mengingat contoh akar kuadrat yang saya tunjukkan.
jpmc26

Jawaban:

69

Anda harus ingat bahwa dalam FPU arithmetics, 0 tidak harus berarti nol, tetapi juga nilainya terlalu kecil untuk diwakili menggunakan tipe data yang diberikan, misalnya

a = -1 / 1000000000000000000.0

a terlalu kecil untuk diwakili dengan benar oleh float (32 bit), sehingga "dibulatkan" menjadi -0.

Sekarang, katakanlah perhitungan kita berlanjut:

b = 1 / a

Karena a adalah float, itu akan menghasilkan -infinity yang cukup jauh dari jawaban yang benar -100000000000000000000.0.0

Sekarang mari kita hitung b jika tidak ada -0 (jadi a dibulatkan menjadi +0):

b = 1 / +0
b = +infinity

Hasilnya salah lagi karena pembulatan, tetapi sekarang "lebih salah" - tidak hanya secara numerik, tetapi yang lebih penting karena tanda yang berbeda (hasil perhitungan adalah + tak terhingga, hasil yang benar adalah -100000000000000000000.0.0).

Anda masih bisa mengatakan bahwa itu tidak masalah karena keduanya salah. Yang penting adalah bahwa ada banyak aplikasi numerik di mana hasil paling penting dari perhitungan adalah tanda - misalnya ketika memutuskan apakah akan belok kiri atau kanan di perempatan dengan menggunakan beberapa algoritma pembelajaran mesin, Anda dapat mengartikan nilai positif => belokan kiri, nilai negatif => belok kanan, "besaran" sebenarnya dari nilai tersebut hanyalah "koefisien kepercayaan".

qbd
sumber
Apakah Anda punya ide apakah tanda underflow mungkin sangat penting dalam perhitungan angka imajiner / kompleks?
jpmc26
@ qbd: Apakah Anda tahu aplikasi numerik itu? Saya akan mengatakan bahwa program yang memicu dan menggunakan +infdan -infdalam operasi normal disadap.
Björn Lindqvist
@ BjörnLindqvist Jika Anda ingin aplikasi yang konkret dan dapat diunduh - maka saya tidak tahu. Saya tidak berpikir itu pasti buggy - bukannya float / double Anda bisa menggunakan sesuatu seperti BigDecimal dengan ketepatan tak terbatas. Tetapi apakah itu layak ketika program akan memberikan hasil yang persis sama dengan yang dengan float / double, tetapi dengan kinerja yang jauh lebih buruk?
qbd
Anda menulis "aplikasi numerik di mana hasil paling penting dari perhitungan adalah tanda" Saya bisa percaya itu, tapi saya tidak percaya ada aplikasi yang ditulis dengan baik yang mengandalkan -0 dan pada nilai yang sedang +infdan -inf. Jika program Anda menyebabkan floating point underflow, itu adalah bug dan apa yang terjadi sesudahnya tidak begitu menarik, imho. Kami masih kehilangan contoh praktis di mana -0 berguna.
Björn Lindqvist
1
@ BjörnLindqvist Sebagian besar x265 dilakukan dalam perakitan, bergantung pada detailnya yang tidak jelas (yang bergantung pada arsitektur CPU) yang hanya diketahui oleh sedikit orang atas nama kinerja. Apakah itu salah? Mengandalkan standar 30 tahun yang diterapkan secara luas (yang akan tetap ada) untuk satu fitur sederhana, yang dipahami dengan baik atas nama kinerja, tiba-tiba tidak tampak terlalu buruk.
qbd
8

Pertama, bagaimana Anda membuat -0? Ada dua cara: (1) melakukan operasi floating-point di mana hasil matematika negatif, tetapi sangat dekat dengan nol sehingga dibulatkan menjadi nol dan bukan ke angka bukan nol. Perhitungan itu akan memberikan -0. (B) Operasi tertentu yang melibatkan nol: Kalikan nol positif dengan angka negatif, atau bagi nol positif dengan angka negatif, atau negasikan nol positif.

Memiliki nol negatif menyederhanakan multiplikasi dan pembagian sedikit, tanda x * y atau x / y selalu merupakan tanda x, eksklusif atau tanda y. Tanpa nol negatif, harus ada beberapa pemeriksaan tambahan untuk mengganti -0 dengan +0.

Ada beberapa situasi yang sangat langka di mana itu berguna. Anda dapat memeriksa apakah hasil dari perkalian atau pembagian secara matematis lebih besar dari atau kurang dari nol, bahkan jika ada underflow (selama Anda tahu hasilnya bukan nol matematika). Saya tidak ingat pernah memiliki kode tertulis di mana itu membuat perbedaan.

Mengoptimalkan kompiler membenci -0. Misalnya, Anda tidak dapat mengganti x + 0,0 dengan x, karena hasilnya tidak boleh x jika x adalah -0,0. Anda tidak dapat mengganti x * 0,0 dengan 0,0, karena hasilnya harus -0,0 jika x <0 atau x adalah -0,0.

gnasher729
sumber
7
Saya berharap IEEE-754 memasukkan empat nol: "tepat", positif sangat kecil, sangat kecil negatif, dan tidak ditandatangani (yang terakhir adalah perbedaan antara nilai-nilai yang tidak bisa dibedakan). Melakukan hal itu akan membuat banyak aksioma floating-point bekerja - di antaranya, x + 0,0 equiv x-0,0 equiv x, xy equiv x + (- 1,0) * y, dan 1,0 / x equiv -1,0 / (- 1,0 * x) [jika x positif nol, keduanya akan pos-inf; jika neg-nol, keduanya neg-inf; jika tepat atau tidak ditandatangani, keduanya NaN].
supercat
Saya bisa mendapatkan nol negatif dengan melewati -5dan 5masuk fmod(). Ini cukup mengganggu untuk kasus penggunaan saya.
Aaron Franke
6

C # Double yang sesuai dengan IEEE 754

    double a = 3.0;
    double b = 0.0;
    double c = -0.0;

    Console.WriteLine(a / b);
    Console.WriteLine(a / c);

cetakan:

Infinity
-Infinity

sebenarnya untuk menjelaskan sedikit ...

Double d = -0.0; 

Ini berarti sesuatu yang jauh lebih dekat dengan d = The Limit of x as x approaches 0-atau The Limit of x as x approaches 0 from the negatives.


Untuk menanggapi komentar Philipp ...

Pada dasarnya nol negatif berarti underflow.

Ada sedikit penggunaan praktis untuk nol negatif jika ...

misalnya, kode ini (lagi C #):

double a = -0.0;
double b = 0.0;

Console.WriteLine(a.Equals(b));
Console.WriteLine(a==b);
Console.WriteLine(Math.Sign(a));

menghasilkan hasil ini:

True
True
0

Untuk menjelaskan secara informal, Semua nilai khusus yang dapat dimiliki oleh floating point IEEE 754 (infinity positif, infinity negatif, NAN, -0.0) tidak memiliki arti dalam arti praktis. Mereka tidak dapat mewakili nilai fisik apa pun, atau nilai apa pun yang masuk akal dalam perhitungan "dunia nyata". Apa yang mereka maksud adalah pada dasarnya ini:

  • infinity positif berarti luapan di ujung positif yang dapat ditunjukkan oleh titik apung
  • infinity negatif berarti luapan di ujung positif yang dapat ditunjukkan oleh titik apung
  • negatif nol berarti aliran bawah dan operan memiliki tanda yang berlawanan
  • positif nol dapat berarti aliran bawah dan operan memiliki tanda yang sama
  • NAN berarti perhitungan Anda tidak terdefinisi, seperti sqrt(-7), atau tidak memiliki batas suka 0/0atau sukaPositiveInfinity/PositiveInfinity
AK_
sumber
7
Ya, tetapi mengapa ini penting? Bisakah Anda memberikan contoh praktis, dunia nyata di mana perbedaan itu penting?
Philipp
5

Pertanyaan tentang bagaimana ini berhubungan dengan perhitungan bilangan kompleks benar-benar menjadi inti mengapa kedua +0 dan -0 ada di floating-point. Jika Anda mempelajari Analisis Kompleks sama sekali, Anda dengan cepat menemukan bahwa fungsi kontinu dari Kompleks ke Kompleks biasanya tidak dapat diperlakukan sebagai 'bernilai tunggal' kecuali jika seseorang mengadopsi 'fiksi sopan' bahwa output membentuk apa yang dikenal sebagai 'permukaan Riemann'. Sebagai contoh, logaritma kompleks memberikan setiap input tanpa batas banyak output; ketika Anda 'menghubungkannya' untuk membentuk output yang berkelanjutan, Anda akan berakhir dengan semua bagian nyata yang membentuk permukaan 'pembuka botol tak terbatas' di sekitar titik asal. Kurva kontinu yang melintasi sumbu nyata 'ke bawah dari sisi positif-imajiner' dan kurva lain yang 'membungkus kutub' dan melintasi sumbu nyata '

Sekarang menerapkannya ke program numerik yang menghitung menggunakan floating-point kompleks. Tindakan yang diambil setelah perhitungan yang diberikan mungkin sangat berbeda tergantung pada 'lembar' program mana yang saat ini 'aktif', dan tanda hasil perhitungan terakhir mungkin memberi tahu Anda 'lembar' mana. Sekarang anggaplah hasilnya nol? Ingat, di sini 'nol' benar-benar berarti 'terlalu kecil untuk diwakili dengan benar'. Tetapi jika perhitungan dapat mengatur untuk - menyimpan tanda - (yaitu ingat yang 'lembar') ketika hasilnya nol, maka kode dapat memeriksa tanda dan melakukan tindakan yang tepat bahkan dalam situasi ini.

PJM
sumber
1

Alasannya lebih sederhana dari biasanya

Tentu saja ada banyak peretasan yang terlihat sangat bagus dan bermanfaat (seperti pembulatan ke -0.0atau +0.0tetapi anggap kita memiliki representasi int yang ditandatangani dengan tanda minus / plus di awal (saya tahu itu diselesaikan dengan kode biner U2 dalam bilangan bulat biasanya tetapi menganggap representasi ganda yang kurang kompleks):

0 111 = 7
^ sign

Bagaimana jika ada angka negatif?

1 111 = -7

Oke, sesederhana itu. Jadi mari kita wakili 0:

0 000 = 0

Itu baik juga. Tapi bagaimana dengan itu 1 000? Apakah harus nomor terlarang? Lebih baik tidak.

Jadi mari kita asumsikan ada dua jenis nol:

0 000 = +0
1 000 = -0

Nah, itu akan menyederhanakan perhitungan kami dan secara tidak sengaja memberikan beberapa fitur tambahan pembulatan. Jadi +0dan -0datang dari hanya masalah representasi biner.

Dawid Pura
sumber
6
Jika saya membaca ini dengan benar, Anda pada dasarnya hanya mengatakan orang mendefinisikan atau menerapkan standar tidak ingin repot melarangnya. Saya tidak berpikir alasan ini mendukung fakta bahwa komplemen 2's menggunakan representasi "nol negatif" untuk angka yang sama sekali berbeda dan tidak memiliki representasi nol negatif. Lihat artikel Wikipedia yang saya tautkan.
jpmc26
1
@ jpmc26 Saya pikir sebenarnya ada beberapa kebenaran untuk itu, dalam arti tidak melarang itu berarti tidak memerlukan implementasi untuk memiliki kasus khusus. Karena, setiap angka memiliki bit tanda dan dapat dinegasikan dengan beralih bit tanda. Bahkan NaN ditandatangani, dan implementasi dapat (tetapi tidak diharuskan) memilih tanda yang sesuai saat menghasilkan NaN. Jika nol negatif tidak ada, setiap perhitungan yang menghasilkan 0 perlu melakukan kerja ekstra untuk memperbaiki bit tanda, dll.
hobbs
4
@ jpmc26 (yaitu dalam setiap penggandaan dua angka lainnya, tanda hasilnya adalah xor dari tanda multiplicand, dan besarnya adalah produk dari dua magnitude. Dalam kehidupan nyata ini bekerja untuk -1 * 0 = - 0. Tetapi jika nol dengan bit tanda dibalik adalah beberapa nilai bukan nol khusus, setiap produk yang dapat menghasilkan 0 harus memeriksa dan memastikan tidak menghasilkan nilai khusus itu secara tidak sengaja.)
hobbs