Underscore: _.isNumber(NaN) mengembalikan nilai true

Dibuat pada 15 Des 2011  ·  38Komentar  ·  Sumber: jashkenas/underscore

Karena NaN adalah singkatan dari "Not a Number", pemeriksaan isNumber dalam kasus ini sepertinya akan mengembalikan false. Saya perhatikan dari diskusi lain bahwa ini sebenarnya disengaja. Mungkin dokumentasi harus mencerminkan fakta ini secara eksplisit.

enhancement fixed

Komentar yang paling membantu

Ok jadi saya mulai dengan masalah sederhana. Saya memiliki input berupa string, angka, dan mungkin NaN. Saya punya solusi sederhana dalam JavaScript dasar menggunakan parseInt dan isFinite untuk menguji apakah parse int berhasil. Sederhana tetapi tidak sepenuhnya bersih atau menggambarkan tujuan saya sendiri. Jadi, saya memutuskan untuk menggunakan perpustakaan goto saya yang benar-benar luar biasa untuk melakukan tugas-tugas semacam ini. Saya menemukan fungsi pada pemeriksaan awal yang mengatakan itu membutuhkan nilai dan memberi tahu Anda jika itu adalah angka, yang menurut definisi umum saya adalah apa yang saya pikir saya inginkan.

Pertama, dengan ini dapatkah Anda melihat bagaimana menambahkan baris ke dokumentasi akan membantu pengguna perpustakaan mendapatkan fungsi yang tepat untuk pekerjaan pertama kali? Kedua, saya minta lagi contoh di mana ini bermakna.

Sepertinya Anda tahu semua yang perlu diketahui tentang bahasa tersebut. Jadi, daripada menyemburkan kembali tembakan buta dalam solusi gelap yang dapat diberikan oleh saudara laki-laki kelas 8 saya kepada saya, mungkin akan lebih baik jika Anda dapat menggunakan sebagian dari sekolah penguasaan itu kepada kita semua melalui dokumentasi yang luar biasa. Terima kasih atas waktu Anda.

Semua 38 komentar

Anda benar, itu disengaja. Dan saya rasa itu tidak perlu dinyatakan secara eksplisit. Siapa pun yang pernah bekerja dengan IEEE 754 float sebelumnya mungkin tahu bahwa NaN hanyalah nilai floating point lainnya.

Terkait: diskusi di #321

Maksud saya bertanya adalah, ketika saya melakukan tugas web umum, fungsi bernama isNumber sepertinya merupakan cara yang baik untuk memeriksa apakah nilai yang ditemukan menjawab definisi umum pengguna "apakah ini angka?".

Selain itu, menurut saya nilai NaN diperkenalkan di tempat pertama untuk membantu mengidentifikasi nilai yang merusak komputasi. Dalam semangat spesifikasi sepertinya jawaban yang benar ketika Anda mengajukan pertanyaan "apakah ini angka?" sebenarnya adalah "Bukan Angka". Jika Anda dapat menyebutkan contoh umum di mana Anda ingin jawabannya benar untuk pertanyaan ini, saya akan tutup mulut sekarang :)

Anda mencari isFinite , yang seharusnya sudah diketahui oleh orang yang mengetahui JS.

Ok jadi saya mulai dengan masalah sederhana. Saya memiliki input berupa string, angka, dan mungkin NaN. Saya punya solusi sederhana dalam JavaScript dasar menggunakan parseInt dan isFinite untuk menguji apakah parse int berhasil. Sederhana tetapi tidak sepenuhnya bersih atau menggambarkan tujuan saya sendiri. Jadi, saya memutuskan untuk menggunakan perpustakaan goto saya yang benar-benar luar biasa untuk melakukan tugas-tugas semacam ini. Saya menemukan fungsi pada pemeriksaan awal yang mengatakan itu membutuhkan nilai dan memberi tahu Anda jika itu adalah angka, yang menurut definisi umum saya adalah apa yang saya pikir saya inginkan.

Pertama, dengan ini dapatkah Anda melihat bagaimana menambahkan baris ke dokumentasi akan membantu pengguna perpustakaan mendapatkan fungsi yang tepat untuk pekerjaan pertama kali? Kedua, saya minta lagi contoh di mana ini bermakna.

Sepertinya Anda tahu semua yang perlu diketahui tentang bahasa tersebut. Jadi, daripada menyemburkan kembali tembakan buta dalam solusi gelap yang dapat diberikan oleh saudara laki-laki kelas 8 saya kepada saya, mungkin akan lebih baik jika Anda dapat menggunakan sebagian dari sekolah penguasaan itu kepada kita semua melalui dokumentasi yang luar biasa. Terima kasih atas waktu Anda.

Saya tertarik dengan pendapat @jashkenas . Saya tidak bermaksud untuk terdengar menghina atau merendahkan. Aku tahu aku terkadang seperti itu. Saya pikir itu adalah fakta bahwa saya mencoba mengarahkan percakapan ke arah yang lebih baik menunjukkan masalah dengan memberikan jawaban sederhana ini dan melihat bagaimana mereka gagal menyelesaikan masalah di mata Anda.

Pertama, dengan ini dapatkah Anda melihat bagaimana menambahkan baris ke dokumentasi akan membantu pengguna perpustakaan mendapatkan fungsi yang tepat untuk pekerjaan pertama kali?

Mungkin, tentu.

Kedua, saya minta lagi contoh di mana ini bermakna.

Menguji [[Kelas]] == "Nomor"? Itu harus jelas, itu cocok dengan angka. Mungkin itu bukan bilangan asli atau bilangan bulat atau bilangan terbatas atau bilangan real atau bilangan rasional atau himpunan bagian apa pun yang Anda harapkan, tetapi semuanya pasti bilangan.

Semua yang dikatakan, ada kalanya menambahkan terlalu banyak bulu dalam dokumentasi bisa berbahaya. Tapi kurasa ini bukan salah satunya. Ini berpotensi membantu pengembang yang mungkin, dalam keadaan mereka saat ini, memiliki interpretasi yang bertentangan tentang konsep abstrak angka. Seperti dalam kasus Anda, di mana Anda telah menetapkan model mental dari himpunan yang ingin Anda uji, dan kemudian menemukan fungsi yang _muncul_ untuk melakukan pengujian itu. +1 , meskipun saya masih tertarik dengan apa yang dipikirkan @jashkenas .

Ya -- sama sekali tidak jelas apakah _.isNumber akan mengembalikan true atau false ketika diteruskan NaN . Saya pasti tidak akan ingat tanpa mencobanya. Menambahkan catatan ke dokumentasi di komit di atas. Terima kasih.

Terima kasih teman-teman. Senang mengetahui bahwa orang lain mungkin tidak mengalami masalah yang sama.

Ini jelas tampak seperti kasus di mana semantik harus mengalahkan fakta teknis. Ya, NaN mungkin Angka menurut beberapa spesifikasi. Tapi jika saya menanyakan sesuatu pertanyaan "Apakah Anda nomor?" dan dikatakan "Saya Bukan Angka" maka saya harus mempercayainya. Bukan Angka – NaN – secara definitif bukan Angka... dan isNumber harus mengembalikan false.

Menempatkan Gotcha di dokumen - alih-alih memperbaiki hal-hal yang masuk akal bagi manusia - hanya menghasilkan lebih sedikit waktu untuk pengkodean dan lebih banyak waktu untuk mengintip dokumentasi yang menggaruk-garuk kepala Anda.

Bisakah ini dipertimbangkan kembali?

@contentfree : NaN adalah anggota float. Setiap angka di JS adalah float. Saya pikir itu membuat NaN sebagai angka yang mereka dapatkan. NaN tidak berarti "Saya bukan angka". Ini adalah representasi numerik dari non-angka. Kasus ditutup dalam buku saya. Gunakan isFinite jika Anda ingin menguji angka yang bukan NaN / Infinity / -Infinity .

Bukan untuk mengalahkan kuda mati tapi...

Mengapa tidak lakukan saja?
obj instanceOf Number

Menurut saya jika ada cara yang lebih mudah dibaca untuk melakukan tindakan yang diperlukan yang sudah ada dalam spesifikasi javascript, saya akan melakukannya dengan cara itu tanpa menggunakan perpustakaan dengan perpustakaan yang tidak diketahui (kecuali saya membuang waktu untuk menyelidiki).

Saya memilih bahwa jika kita tidak akan memperbaiki ini menjadi benar secara semantik, kita harus menghapus overhead dan sakit kepala yang tidak berguna dari perpustakaan.

Operator instanceof hanya akan bekerja untuk objek, bukan primitif: new Number(5) instanceof Number == true; 5 instanceof Number == false . Ini juga tidak akan berfungsi di seluruh bingkai di browser. Pengecekan [[Class]] melalui Object::toString secara umum diterima sebagai metode pemeriksaan tipe yang paling dapat diandalkan dalam JavaScript.

+1 untuk membuat perpustakaan lebih berguna dan dalam hal yang sama mendidik pengguna yang baru mengenal JavaScript.

Saran:
_.isNumber(objek, [isFinite]);

Ini akan memungkinkan penambahan sederhana dari true ke implementasi Anda saat ini ketika ditangkap oleh gotcha ini sambil belajar bahwa isFinite mungkin adalah apa yang Anda cari sejak awal.

2c saya

@nickl- Ide yang menarik, tapi...mengapa tidak menggunakan isFinite ?

Atau, karena _.isNaN sudah ada, _.isFinite berpotensi ditambahkan untuk simetri:

_.isFinite = function (value) {
  return value > -1 / 0 && value < 1 / 0;
};

@kitcambridge

Satu-satunya masalah yang saya perkirakan dengan itu adalah bahwa string akan lulus sebagai "0x0", "0xF", "2", dll. Jadi apa pun yang terjadi, itu harus dikombinasikan dengan _.isNumber atau yang setara:

_.isFinite = function (obj) {
  return obj > -1/0 && obj < 1/0 && _.isNumber(obj);
};

Dapat mencukur lima karakter dengan menggunakan val === +val untuk pengujian angka:

_.isFinite = function (obj) {
  return obj > -1/0 && obj < 1/0 && obj === +obj;
};

@octatone Tentu, saya pikir itu adil ... secara teknis, string itu _are_ terbatas, karena dapat digunakan dalam perbandingan numerik (penerjemah harus memaksanya ke angka), tetapi proposal Anda lebih konsisten dengan fungsi pemeriksaan tipe Garis Bawah yang ada.

Bagaimana dengan _,isValidNumber yang sejalan dengan _.isValidDate yang ada dan tidak membingungkan argumen isFinite?

@nickl-

NaN dan Infinity _adalah_ nomor yang valid. Saya pikir penamaan fungsi ini isValidNumber akan membingungkan tujuannya atau maksud Anda mengganti nama isNumber menjadi isValidNumber?

NaN dan Infinity _adalah_ nomor yang valid. Saya pikir penamaan fungsi ini isValidNumber akan membingungkan tujuannya.

Saya setuju.

Saya tidak mengatakan ganti nama ...

Saya juga terkejut mengetahui bahwa _.isNumber(NaN) === true .

Saya pikir saya cenderung setuju dengan @contentfree https://github.com/jashkenas/underscore/issues/406#issuecomment -4144992 . Dalam rekayasa perangkat lunak kami bahkan memiliki prinsip untuk kasus khusus ini: Prinsip Kekaguman Terkecil . ;-)

Dan setelah melihat ini banyak orang bingung tentang hal itu, saya pikir masuk akal untuk mendapatkan fungsi untuk melakukan apa yang diharapkan oleh manusia non-hard-core-js-coders ketika mereka melihat namanya.

Hanya 2 kecilku…™

_.isNaN juga membingungkan. Dalam dokumen:

Catatan: ini tidak sama dengan fungsi isNaN asli, yang juga akan mengembalikan true untuk banyak nilai bukan angka lainnya, seperti undefined.

dalam arti normal undefined memang Bukan-A-Number.

Saya memilih konstruktif semantik, isNumber == Not a number lol. Saya percaya, Jika Anda perlu merinci tentang memeriksa nilai floating point, maka lakukan dengan cara lain?

Saya memilih konstruktif semantik,

Tidak, itu adalah angka dengan [[Class]] seperti -Infinity , Infinity , & Object(2) . Itu salah satu hal yang dipelajari para pengembang, seperti fungsi juga objek. Kemungkinan Anda ingin melakukan beberapa bentuk validasi pada nomor Anda yang berada di luar cakupan metode ini. Misalnya lebih besar dari -1 , kurang dari Math.pow(2,32) , atau bilangan bulat. Dalam kasus -Infinity , Infinity atau NaN Saya menggunakan _.isFinite sebagai validator. Demikian pula _.isDate tidak memvalidasi jika objek tanggal mewakili tanggal yang valid.

Bagaimana dengan memperbarui dokumentasi dengan "lihat juga: isFinite" dan "lihat juga: «metode enumerasi esai untuk menentukan apakah sesuatu adalah nilai numerik yang benar-benar dapat Anda gunakan»"

@michaelficarra Saya tahu bahwa dalam spesifikasi NaN sangat banyak tipe numerik. Tetapi apakah itu yang dipikirkan seorang programmer ketika mereka bertanya apakah ini angka?

Apa yang sebagian besar dari kita ingin ketahui, sebagian besar waktu adalah, dapatkah saya menggunakan ini untuk aritmatika dasar. Jadi, Anda harus pergi isNumber(x) && isFinite(x). Dan tidak apa-apa kurasa. Tapi itu masalah besar bagi programmer baru dan tidak bisa dibaca dengan baik.

Dari sudut pandang bahasa Inggris yang ketat, Not a Number (NaN) yang mengembalikan true dari tes yang disebut isNumber tidak masuk akal sama sekali. Bukankah ini lebih baik bernama isNumeric atau isNumericType?

Saya tidak ragu bahwa ini akan menambah bug dan membuang banyak waktu, setidaknya pertama kali orang menentang ini.

Jadi, Anda harus pergi isNumber(x) && isFinite(x).

Saya baru-baru ini menyelaraskan implementasi _.isFinite untuk mengikuti ES6 Number.isFinite .
Ini memastikan nilainya adalah bilangan primitif, terbatas, & harus menangani kasus umum ini.

Tidak perlu mengubah perilaku _.isNumber yang sejajar dengan metode pemeriksaan [[Class]] .

Dari sudut pandang bahasa Inggris yang ketat, Not a Number (NaN) yang mengembalikan true dari tes yang disebut isNumber tidak masuk akal sama sekali. Bukankah ini lebih baik bernama isNumeric atau isNumericType?

Lihat komentar saya tentang validasi, _.isNumber , dan _.isDate .

@jdalton Anda benar tentang perilaku yang konstan dengan _.isDate. Dan kalian melakukan pekerjaan yang hebat dengan garis bawah, jadi saya pikir keputusan benar-benar jatuh ke tangan Anda.

Tapi sepertinya sangat kontra intuitif sehingga sesuatu yang disebut bukan angka adalah angka.

@Walms 100% setuju. Saya pikir dalam hal ini, programmer dan intuisi harus mengesampingkan "kebenaran" mutlak dari pernyataan yang diberikan NaN adalah _secara teknis_ numerik.

Tapi sepertinya sangat kontra intuitif sehingga sesuatu yang disebut bukan angka adalah angka.

Dalam konteks itu apakah ada kontra yang lebih intuitif daripada _.isNumber mengembalikan true untuk objek angka, Object(2) yang merupakan tipe object ?

Ini adalah metode [[Class]] . Mungkin itu perlu dibuat lebih jelas dalam dokumentasi.

Saya sudah mengusulkan alternatif yang layak yaitu dengan membuat _.isFinite follow ES6 Number.isFinite . Jika Anda ingin is-number gunakan typeof x == 'number' . Jika Anda ingin validasi bahwa nilainya bukan NaN , Infinity , atau -Infinity , semua [[Class]] dari Number , lalu _.isFinite adalah cara yang tepat.

Lihat ke underscore-contrib untuk metode angka berbutir lebih halus. Ini memiliki _.isNumeric , _.isInteger , _.isZero , _.isEven , _.isOdd , _.isFloat , _.isNegative , & _.isPositive .

@jdalton Saya pikir Anda dua komentar terakhir benar-benar membantu menjelaskan mengapa saya pikir ini membingungkan.

Awalnya saya tidak melihat bahwa _.isNumber diberi konteks oleh fakta bahwa itu diawali oleh is, artinya itu adalah pemeriksaan tipe. Dengan konteks ini Anda sepenuhnya benar, tidak masuk akal jika _.isNumber mengembalikan false untuk NaN.

Tetapi kemudian garis bawah-contrib dan isFinite tampaknya melanggar konteks ini. Seperti yang mereka mulai dengan, namun melihat nilai daripada jenis. Dan di sinilah saya pikir kebingungannya adalah tidak ada cara yang jelas untuk menentukan konteks dari nama fungsi.

Semua ini mengatakan saya tidak melihat cara untuk memperbaikinya.

Saya pikir masalahnya di sini adalah ada beberapa hal tentang Angka yang tidak intuitif. Namun, mereka berperilaku dengan cara yang konsisten. Dimungkinkan untuk membuat _.isNumber lebih intuitif dalam kasus ini dengan membuatnya kurang konsisten, yang pada akhirnya akan membuatnya kurang intuitif dalam kasus lain.

Berikut adalah beberapa contoh konkret:

# If you add two Numbers together you always get another Number back
# This function should always return true no matter what you pass it
closedUnderAddition = (a, b) -> !isNumber(a) || !isNumber(b) || isNumber(a + b)

closedUnderAddition(1,1) == true
closedUnderAddition(Number.MAX_INT,2**970) == true # false if isNumber checks finiteness

# If you divide two Numbers you always get another Number back
closedUnderDivision = (a, b) -> !isNumber(a) || !isNumber(b) || isNumber(a / b)

closedUnderDivision(1, 2) == true
closedUnderDivision(1, 0) == true # false if isNumber checks finiteness
closedUnderDivision(0, 0) == true # false if isNumber checks finiteness or NaN-ness

# Anything you cast to a Number is a Number
castsToNumber = (x) -> isNumber(Number(x))

castsToNumber(1) == true
castsToNumber(Infinity) == true # false if isNumber checks finiteness
castsToNumber("bees") == true # false if isNumber checks finiteness or NaN-ness
castsToNumber("3") == true

Seperti yang dikatakan michaelficarra:

NaN tidak berarti "Saya bukan angka". Ini adalah representasi numerik dari non-angka.

Atau, dengan kata lain, ada "angka" dan Angka. NaN mungkin bukan "angka" tetapi itu benar-benar Angka bersama dengan Infinity, -Tak terhingga dan hal-hal konyol seperti -0. Meskipun liar dan berbulu, definisi Angka ditentukan dengan baik dan berperilaku secara konsisten.

"angka" di sisi lain adalah konsep yang didefinisikan dengan buruk, tergantung pada siapa Anda berbicara, dapat mencakup salah satu atau tidak sama sekali di atas , dan mungkin string numerik, bools, tengah malam dan segala macam hal. Tidak apa-apa, tetapi tidak akan pernah ada solusi yang sesuai dengan definisi semua orang.

Saya pikir karena alasan itu pada dasarnya ini adalah masalah dokumentasi.

Juga apakah "angka" berhenti terlihat seperti kata untuk orang lain?

Poin bagus, @lembut. Saya memilih konsistensi daripada intuisi, karena yang pertama adalah ukuran objektif sedangkan kita tidak akan semua setuju tentang apa yang intuitif (seperti yang ditunjukkan oleh utas ini).

Hanya saja, jangan memperlakukan NaN sebagai "Bukan Angka". NaN adalah nilai khusus.

Hanya saja, jangan memperlakukan NaN sebagai "Bukan Angka". NaN adalah nilai khusus.

Ya tapi itu disebut "Bukan Angka".
Bagi saya itu seperti ini
var _false = "benar";
Ya, Anda dapat mengetahui bahwa _false benar, tetapi membingungkan tanpa alasan yang jelas.

@Walms Itu nama yang buruk tapi itu bukan salah JS. Kita mungkin menyalahkan orang yang menamakannya sebagai "NaN". http://en.wikipedia.org/wiki/NaN

Aargh, saya berharap _.isNumber(NaN) akan mengembalikan false ... beberapa menggaruk kepala yang serius di sini sampai saya menyadari inilah alasannya.

if (isNaN(Number(value))) {
  alert('Number required.');
}

@pspi Setuju. Membuat _.isNumber() berperilaku benar dalam arti _semantic_ berarti saya tidak akan pernah benar-benar menggunakannya. ._isFinite() tampaknya merupakan fungsi yang bekerja seperti yang saya harapkan.

Dan tentu saja, satu hari setelah memposting ini, saya menemukan bahwa _.isFinite('1') adalah true , meskipun argumennya bukan angka.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

clouddueling picture clouddueling  ·  3Komentar

Francefire picture Francefire  ·  5Komentar

markvr picture markvr  ·  3Komentar

afranioce picture afranioce  ·  8Komentar

jezen picture jezen  ·  8Komentar