Apakah mesin JS diizinkan untuk mengubah bit NaN?

12

Dalam JavaScript, nilai NaN dapat diwakili oleh berbagai macam 64-bit ganda secara internal. Secara khusus, sembarang ganda dengan representasi bitwise berikut:

x111 1111 1111 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx

Ditafsirkan sebagai NaN. Pertanyaan saya adalah: seandainya saya melemparkan dua uint 32-bit ke Nomor JS menggunakan ArrayBuffers, menyebarkannya, lalu melemparkannya kembali ke dua uint 32-bit. Akankah bit yang dipulihkan sama dengan yang asli, atau apakah mesin JS diizinkan untuk mengubah bit NaN sesuka hati? Dengan kata lain, dapatkah nomor JS digunakan untuk menyimpan 64-bit losslesly?

Viktor Maia
sumber
2
Ide menarik
Evert
1
Sebuah tes saya buat. Sepertinya setidaknya Node.js mengubah bit sesuka hati, menyebabkan hilangnya informasi.
MaiaVictor
1
Selain: Tidak setiap pola bit seperti itu mewakili NaN. Jika semua x tetapi setelah yang pertama adalah nol, itu merepresentasikan tak terhingga.
Eric Postpischil

Jawaban:

6

ECMA-262 Edisi ke 9 , Juni 2018, (standar yang dimaksudkan untuk menyesuaikan JavaScript) mengatakan, dalam 6.1.6 "The Number Type":

… 9007199254740990 (yaitu, 2 53 -2) nilai “Not-a-Number” berbeda dari Standar IEEE diwakili dalam ECMAScript sebagai nilai NaN khusus tunggal ... Dalam beberapa implementasi, kode eksternal mungkin dapat mendeteksi perbedaan antara berbagai nilai Not-a-Number, tetapi perilaku tersebut bergantung pada implementasi; ke kode ECMAScript, semua nilai NaN tidak dapat dibedakan satu sama lain.

24.1.17 "NumberToRawBytes (tipe, nilai, isLittleEndian)" mengatakan:

... Jika nilainya NaN, rawBytes dapat diatur untuk implementasi apa pun yang dipilih IEEE 754-2008 format binary64, Not-a-Number encoding. Suatu implementasi harus selalu memilih pengkodean yang sama untuk setiap implementasi nilai NaN yang dapat dibedakan.…

Saya tidak melihat bagian-bagian lain yang menyebutkan NaN yang menerangi pertanyaan ini. Di satu sisi, 24.1.17 secara efektif memberi tahu kita bahwa bit NaN harus dipertahankan ketika mengubah NaN menjadi byte mentah. Namun, tidak ada hal lain yang memberi tahu kami bahwa bit harus disimpan dalam operasi lain. Orang mungkin menyimpulkan bahwa ini adalah maksudnya, karena persyaratan ini dalam 24.1.17 tidak akan berfungsi jika bit dapat diubah secara sewenang-wenang oleh operasi lainnya. Tapi saya tidak akan bergantung pada implementasi JavaScript untuk mengimplementasikan ini sesuai dengan maksud itu.

Eric Postpischil
sumber
1

Saya pernah mengajukan pertanyaan untuk Java, tentang ketergantungan perangkat keras terhadap nilai-nilai NaN, dan diketahui bahwa beberapa CPU akan secara diam-diam mengubah "pensinyalan NaN" menjadi "NaN yang tenang" (mengatur bit NaN yang tenang) (mengatur bit NaN yang tenang) ketika nilai NaN dimuat ke dalam register prosesor. Jadi setidaknya salah satu bit, bit NaN yang tenang, tidak dapat Anda gunakan untuk menyimpan data sewenang-wenang.

Menggunakan bit lain, selama bit NaN yang diam diatur, mungkin aman. Tapi sepertinya masih ada ruang untuk implementasi-ketergantungan di sini, dan karenanya tidak ada jaminan.

Masalah semacam ini adalah mengapa operasi bahasa normal menghindari melakukan apa pun yang tergantung pada nilai internal NaN, dan lebih suka memperlakukan semua NaN sebagai "hanya NaN".

Boann
sumber
0

Standar IEEE-754 asli sengaja meninggalkan bit NaN hingga implementasi. Itu memang memberikan petunjuk, seperti

Anda mungkin memasukkan alamat memori asli tempat NaN dibuat.

Sementara itu, aritmatika memiliki aturan khusus tentang apa yang harus dilakukan dengan NaN, dan itu tidak ada hubungannya dengan bit di bagian bawah. Saya tidak berpikir itu bahkan mengatakan apa yang harus dilakukan ketika menambahkan dua NaN - menjaga bit dari salah satu dari mereka dibandingkan membuat satu set bit. Hanya saja hasilnya pasti masih NaN.

Rick James
sumber