Mengapa perbandingan nilai NaN berperilaku berbeda dari semua nilai lainnya? Artinya, semua perbandingan dengan operator ==, <=,> =, <,> di mana satu atau kedua nilai adalah NaN mengembalikan false, bertentangan dengan perilaku semua nilai lainnya.
Saya kira ini menyederhanakan perhitungan numerik dalam beberapa cara, tapi saya tidak bisa menemukan alasan yang dinyatakan secara eksplisit, bahkan dalam Catatan Kuliah tentang Status IEEE 754 oleh Kahan yang membahas keputusan desain lainnya secara rinci.
Perilaku menyimpang ini menyebabkan masalah ketika melakukan pemrosesan data sederhana. Misalnya, ketika menyortir daftar catatan wrt beberapa bidang bernilai nyata dalam program C saya perlu menulis kode tambahan untuk menangani NaN sebagai elemen maksimal, jika tidak, algoritma pengurutan dapat menjadi bingung.
Sunting: Jawaban sejauh ini semuanya berpendapat bahwa tidak ada artinya membandingkan NaNs.
Saya setuju, tetapi itu tidak berarti bahwa jawaban yang benar adalah salah, tetapi itu akan menjadi Bukan-Boolean (NaB), yang untungnya tidak ada.
Jadi pilihan mengembalikan benar atau salah untuk perbandingan dalam pandangan saya sewenang-wenang, dan untuk pemrosesan data umum akan menguntungkan jika mematuhi hukum yang biasa (refleksivitas ==, trikotomi <, ==,>), jangan sampai struktur data yang mengandalkan hukum-hukum ini menjadi bingung.
Jadi saya meminta beberapa keuntungan nyata dari melanggar undang-undang ini, bukan hanya alasan filosofis.
Sunting 2: Saya pikir saya mengerti sekarang mengapa membuat NaN maksimal adalah ide yang buruk, itu akan mengacaukan perhitungan batas atas.
NaN! = NaN mungkin diinginkan untuk menghindari mendeteksi konvergensi dalam satu loop seperti
while (x != oldX) {
oldX = x;
x = better_approximation(x);
}
Namun yang harus lebih baik ditulis dengan membandingkan perbedaan absolut dengan batas kecil. Jadi IMHO ini adalah argumen yang relatif lemah untuk memecahkan refleksivitas di NaN.
sumber
while (fabs(x - oldX) > threshold)
, keluar dari loop jika konvergensi terjadi atau NaN memasuki perhitungan. Deteksi NaN dan obat yang sesuai kemudian akan terjadi di luar loop.Jawaban:
Saya adalah anggota komite IEEE-754, saya akan mencoba sedikit membantu memperjelas hal-hal.
Pertama, bilangan floating-point bukan bilangan real, dan aritmatika floating-point tidak memenuhi aksioma aritmatika nyata. Trikotomi bukan satu-satunya properti aritmatika nyata yang tidak berlaku untuk mengapung, atau bahkan yang paling penting. Sebagai contoh:
Saya bisa melanjutkan. Tidak mungkin untuk menentukan tipe aritmatika ukuran tetap yang memenuhi semua sifat aritmatika nyata yang kita kenal dan sukai. Komite 754 harus memutuskan untuk membengkokkan atau menghancurkan beberapa dari mereka. Ini dipandu oleh beberapa prinsip sederhana:
Mengenai komentar Anda "itu tidak berarti bahwa jawaban yang benar salah", ini salah. Predikat
(y < x)
bertanya apakahy
kurang darix
. Jikay
NaN, maka itu tidak kurang dari nilai floating-pointx
, jadi jawabannya tentu salah.Saya menyebutkan bahwa trikotomi tidak berlaku untuk nilai floating-point. Namun, ada properti serupa yang memang tahan. Klausul 5.11, paragraf 2 dari standar 754-2008:
Sejauh menulis kode tambahan untuk menangani NaN berjalan, biasanya mungkin (walaupun tidak selalu mudah) untuk menyusun kode Anda sedemikian rupa sehingga NaN dapat lolos dengan benar, tetapi hal ini tidak selalu terjadi. Ketika tidak, beberapa kode tambahan mungkin diperlukan, tetapi itu adalah harga kecil untuk membayar kenyamanan yang diakibatkan oleh penutupan aljabar ke aritmatika titik-mengambang.
Tambahan: Banyak komentator berpendapat bahwa akan lebih berguna untuk menjaga refleksivitas kesetaraan dan trikotomi dengan alasan mengadopsi NaN! = NaN tampaknya tidak mempertahankan aksioma yang sudah dikenal. Saya mengaku memiliki simpati untuk sudut pandang ini, jadi saya pikir saya akan meninjau kembali jawaban ini dan memberikan sedikit konteks.
Pemahaman saya dari berbicara dengan Kahan adalah bahwa NaN! = NaN berasal dari dua pertimbangan pragmatis:
Itu
x == y
harus setara denganx - y == 0
bila memungkinkan (di luar menjadi teorema aritmatika nyata, ini membuat implementasi perangkat keras perbandingan lebih hemat ruang, yang paling penting pada saat standar dikembangkan - namun, perhatikan bahwa ini dilanggar untuk x = y = tak terhingga, jadi itu bukan alasan yang bagus; itu bisa dibengkokkan dengan wajar(x - y == 0) or (x and y are both NaN)
).Lebih penting lagi, tidak ada
isnan( )
predikat pada saat itu NaN diformalkan dalam aritmatika 8087; itu perlu untuk menyediakan programmer dengan cara yang mudah dan efisien untuk mendeteksi nilai-nilai NaN yang tidak bergantung pada bahasa pemrograman menyediakan sesuatu sepertiisnan( )
yang bisa memakan waktu bertahun-tahun. Saya akan mengutip tulisan Kahan sendiri tentang masalah ini:Perhatikan bahwa ini juga logika yang mengesampingkan pengembalian sesuatu seperti "Tidak-Boolean". Mungkin pragmatisme ini salah tempat, dan standar seharusnya diperlukan
isnan( )
, tetapi itu akan membuat NaN hampir mustahil untuk digunakan secara efisien dan nyaman selama beberapa tahun sementara dunia menunggu adopsi bahasa pemrograman. Saya tidak yakin itu akan menjadi tradeoff yang masuk akal.Terus terang: hasil NaN == NaN tidak akan berubah sekarang. Lebih baik belajar hidup dengannya daripada mengeluh di internet. Jika Anda ingin berdebat bahwa relasi pesanan yang cocok untuk wadah juga harus ada, saya akan merekomendasikan menganjurkan bahwa bahasa pemrograman favorit Anda menerapkan
totalOrder
predikat standar di IEEE-754 (2008). Fakta bahwa itu belum berbicara tentang validitas perhatian Kahan yang memotivasi keadaan saat ini.sumber
1f/3f == 10000001f/30000002f
? Jika nilai floating-point dianggap sebagai kelas ekivalensi, makaa=b
tidak berarti "Komputasi yang menghasilkana
danb
, jika dilakukan dengan presisi tak terbatas, akan menghasilkan hasil yang identik", melainkan "Apa yang diketahui tentanga
cocok dengan apa yang diketahui tentangb
". Saya ingin tahu apakah Anda tahu ada contoh kode di mana memiliki "Nan! = NaN" membuat hal-hal lebih sederhana daripada yang seharusnya?!(x < 0 || x == 0 || x > 0)
, tetapi itu akan lebih lambat dan lebih baik daripadax != x
.NaN dapat dianggap sebagai keadaan / angka yang tidak ditentukan. mirip dengan konsep 0/0 yang tidak terdefinisi atau sqrt (-3) (dalam sistem bilangan real tempat floating point).
NaN digunakan sebagai semacam placeholder untuk keadaan yang tidak ditentukan ini. Secara matematis, undefined tidak sama dengan undefined. Anda juga tidak dapat mengatakan bahwa nilai yang tidak terdefinisi lebih besar atau kurang dari nilai yang tidak terdefinisi lainnya. Karenanya semua perbandingan menghasilkan false.
Perilaku ini juga menguntungkan dalam kasus di mana Anda membandingkan sqrt (-3) ke sqrt (-2). Mereka berdua akan mengembalikan NaN tetapi mereka tidak setara meskipun mereka mengembalikan nilai yang sama. Karena itu memiliki kesetaraan selalu menghasilkan false ketika berurusan dengan NaN adalah perilaku yang diinginkan.
sumber
!=
Operator mengembalikan nilai true. MemilikiNaN==NaN
danNaN!=NaN
keduanya kembali salah akan memungkinkan kode yang membandingkan x dan y untuk memilih apa yang harus terjadi ketika kedua operan NaN dengan memilih salah satu==
atau!=
.Untuk memasukkan analogi lain. Jika saya memberi Anda dua kotak, dan memberi tahu Anda bahwa keduanya tidak mengandung apel, apakah Anda akan memberi tahu saya bahwa kotak-kotak itu berisi hal yang sama?
NaN tidak mengandung informasi tentang apa itu sesuatu, hanya apa yang bukan. Karena itu elemen-elemen ini tidak pernah bisa dikatakan sama.
sumber
(NaN==Nan)==false
. Apa yang saya tidak mengerti adalah alasan untuk(Nan!=Nan)==true
.Dari artikel wikipedia di NaN , praktik berikut dapat menyebabkan NaN:
Karena tidak ada cara untuk mengetahui operasi mana yang menciptakan NaN, tidak ada cara untuk membandingkannya yang masuk akal.
sumber
Saya tidak tahu alasan desain, tapi ini kutipan dari standar IEEE 754-1985:
"Harus dimungkinkan untuk membandingkan angka floating-point dalam semua format yang didukung, bahkan jika format operan berbeda. Perbandingan tepat dan tidak pernah meluap atau meluap. Empat hubungan yang saling eksklusif dimungkinkan: kurang dari, sama, lebih besar dari, dan tidak berurutan. Kasus terakhir muncul ketika setidaknya satu operan adalah NaN. Setiap NaN akan membandingkan unordered dengan segala sesuatu, termasuk dirinya sendiri. "
sumber
Ini hanya terlihat aneh karena sebagian besar lingkungan pemrograman yang memungkinkan NaNs juga tidak memungkinkan logika bernilai 3. Jika Anda memasukkan logika bernilai 3 ke dalam campuran, itu menjadi konsisten:
Bahkan .NET tidak menyediakan
bool? operator==(double v1, double v2)
operator, sehingga Anda masih terjebak dengan(NaN == NaN) = false
hasil yang konyol .sumber
Saya menduga bahwa NaN (Bukan Angka) berarti persis seperti itu: Ini bukan angka dan dengan demikian membandingkannya tidak terlalu masuk akal.
Ini sedikit seperti aritmatika dalam SQL dengan
null
operan: Semuanya menghasilkannull
.Perbandingan untuk angka floating point membandingkan nilai numerik. Dengan demikian, mereka tidak dapat digunakan untuk nilai non numerik. Oleh karena itu NaN tidak dapat dibandingkan dalam arti numerik.
sumber
FOO
. Untuk menjadi setara NaNif (NaN != NaN) foo();
seharusnya tidak mengeksekusifoo
, tetapi itu.Jawaban yang terlalu sederhana adalah bahwa NaN tidak memiliki nilai numerik, jadi tidak ada yang dapat dibandingkan dengan yang lain.
Anda dapat mempertimbangkan untuk menguji dan mengganti NaN Anda dengan + INF jika Anda ingin mereka bertindak seperti + INF.
sumber
Sementara saya setuju bahwa perbandingan NaN dengan bilangan real mana pun harus dibatalkan, saya pikir hanya ada alasan untuk membandingkan NaN dengan dirinya sendiri. Bagaimana, misalnya apakah seseorang menemukan perbedaan antara pensinyalan NaNs dan NaNs sunyi? Jika kita menganggap sinyal sebagai satu set nilai Boolean (yaitu bit-vektor) orang mungkin bertanya apakah bit-vektor adalah sama atau berbeda dan memesan set yang sesuai. Sebagai contoh, pada decoding eksponen bias maksimum, jika signifikansi dibiarkan bergeser untuk menyelaraskan bit paling signifikan dari signifikansi pada bit paling signifikan dari format biner, nilai negatif akan menjadi NaN yang tenang dan nilai positif akan menjadi NaN pensinyalan. Nol tentu saja dicadangkan untuk tak terhingga dan perbandingannya akan dibatalkan. Penjajaran MSB akan memungkinkan untuk perbandingan sinyal langsung bahkan dari format biner yang berbeda. Oleh karena itu, dua NaN dengan set sinyal yang sama akan sama dan memberikan makna pada kesetaraan.
sumber
Bagi saya, cara termudah untuk menjelaskannya adalah:
Anda tidak dapat membandingkan NaN dengan sesuatu yang lain (bahkan sendiri) karena tidak memiliki nilai. Juga bisa berupa nilai apa saja (kecuali angka).
sumber
Karena matematika adalah bidang di mana angka "hanya ada". Dalam komputasi Anda harus menginisialisasi angka-angka itu dan mempertahankan statusnya sesuai dengan kebutuhan Anda. Di masa lalu itu, inisialisasi memori bekerja dengan cara yang tidak dapat Anda andalkan. Anda tidak pernah bisa membiarkan diri Anda berpikir tentang ini "oh, itu akan diinisialisasi dengan 0xCD sepanjang waktu, algo saya tidak akan rusak" .
Jadi Anda perlu pelarut non-pencampuran yang tepat yang cukup lengket untuk tidak membiarkan algoritma Anda tersedot dan rusak. Algoritma yang baik yang melibatkan angka sebagian besar akan bekerja dengan relasi, dan mereka yang jika () relasi akan dihilangkan.
Ini hanyalah pelumas yang dapat Anda masukkan ke variabel baru saat pembuatan, alih-alih pemrograman acak dari memori komputer. Dan algoritma Anda apa pun itu, tidak akan rusak.
Selanjutnya, ketika Anda masih tiba-tiba menemukan bahwa algoritma Anda menghasilkan NaN, dimungkinkan untuk membersihkannya, melihat ke setiap cabang satu per satu. Sekali lagi, aturan "selalu salah" sangat membantu dalam hal ini.
sumber
Jawaban yang sangat singkat:
Karena berikut ini:
nan / nan = 1
TIDAK boleh ditahan. Kalau tidak,inf/inf
akan menjadi 1.(Oleh karena itu
nan
tidak bisa sama dengannan
. Adapun>
atau<
, jikanan
akan menghormati hubungan pesanan dalam set memuaskan properti Archimedean, kita akan memiliki laginan / nan = 1
pada batas).sumber
inf = inf
daninf / inf = nan
, jadinan = nan
tidak akan mencegahnyanan / nan = nan
.nan / nan = 1
? Pokoknya ... Alasanmu masuk akal jika inf dan nan sama seperti nomor lainnya. Bukan itu masalahnya. Alasan mengapainf/inf
harusnan
(atau bentuk tak tentu dalam matematika) dan tidak1
lebih halus daripada manipulasi aljabar sederhana (lihat teorema De L'Hospital).