Dalam JavaScript , bagaimana saya mendapatkan:
- Berapa kali integer yang diberikan masuk ke integer lain?
- Pengingat?
Dalam JavaScript , bagaimana saya mendapatkan:
Untuk beberapa nomor y
dan beberapa pembagi x
menghitung hasil bagi ( quotient
) dan sisanya ( remainder
) sebagai:
var quotient = Math.floor(y/x);
var remainder = y % x;
3.5 % 2
mengevaluasi menjadi 1,5. Pastikan untuk menangani (parseInt, floor, dll.) Seperti yang diperlukanfloor
dan%
bersama - sama tidak konsisten dengan cara itu. Baik gunakantrunc
alih-alihfloor
(dengan demikian mengizinkan sisa negatif) atau gunakan pengurangan untuk mendapatkan sisanya (rem = y - div * x
).rem
pula, Anda bisa mendapatkan hasil bagidiv
lebih cepat tanpa lantai:(y - rem) / x
. 2. Ngomong-ngomong operasi modulo oleh definisi yang direkomendasikan Donald Knuth (tanda-cocok-divisor, bukan sisanya yaitu modulus Euclidean, atau JavaScript tanda-cocok-dividen) adalah apa yang bisa kita kode dalam JavaScript sebagaifunction mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }
.Saya bukan ahli dalam operator bitwise, tapi inilah cara lain untuk mendapatkan seluruh nomor:
Ini akan bekerja dengan baik untuk angka negatif juga, sementara
Math.floor()
akan membulatkan arah yang salah.Ini tampaknya benar juga:
sumber
a/b | 0
~~int
,int | 0
danint >> 0
tidak mengubah argumen awal, tetapi menjadikan interpreter pass sebagai bagian integral dari operator.floor
hampir tidak berputar ke arah yang salah, diberi nama - hanya saja bukan arah yang umumnya orang inginkan!a = 12447132275286670000; b = 128
Math.floor(a/b)
->97243220900677100
dan~~(a/b)
->-1231452688
.~~(5/2) --> 2
seperti halnya(5/2)>>0 --> 2
, tapi~~(5/2) + 1 --> 3
, sementara~~(5/2)>>0 + 1 --> 1
.~~
adalah pilihan yang baik karena diutamakan lebih tepat.Saya melakukan beberapa tes kecepatan di Firefox.
Di atas didasarkan pada 10 juta percobaan untuk masing-masing.
Kesimpulan: Gunakan
(a/b>>0)
(atau(~~(a/b))
atau(a/b|0)
) untuk mencapai efisiensi sekitar 20%. Juga perlu diingat bahwa mereka semua tidak konsisten denganMath.floor
, kapana/b<0 && a%b!=0
.sumber
Math.floor
dan siapa-tahu-berapa-banyak fungsi API lainnya, atau belajar tentang~
operator (bitwise-not) dan bagaimana operasi bitwise bekerja di JS dan kemudian memahami efek double tilde?Math.floor
lebih mengerti . Dan kalaupun tidak, yang ini bisa di-googleable.ES6 memperkenalkan
Math.trunc
metode baru . Ini memungkinkan untuk memperbaiki jawaban @ MarkElliot untuk membuatnya berfungsi untuk angka negatif juga:Perhatikan bahwa
Math
metode memiliki keunggulan dibandingkan operator bitwise yang mereka gunakan dengan angka di atas 2 31 .sumber
18014398509481984 == 18014398509481985
,.~~(x/y)
. Perlu mendukung jumlah yang lebih besar hingga 54 bit yang ditandatangani? GunakanMath.trunc
jika Anda memilikinya, atauMath.floor
sebaliknya (koreksi untuk angka negatif). Perlu mendukung jumlah yang lebih besar lagi? Gunakan beberapa perpustakaan angka besar.divmod
, Anda dapat menerapkannya seperti:function divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; }
sumber
Math.trunc
:). Saya memeriksa dengan 100,3; -100,3; 100, -3 dan -100, -3. Tentu saja, banyak waktu telah berlalu sejak komentar Anda dan banyak hal berubah.Saya biasanya menggunakan:
Ini mungkin bukan yang paling elegan, tetapi berhasil.
sumber
Anda dapat menggunakan fungsi ini
parseInt
untuk mendapatkan hasil yang terpotong.Untuk mendapatkan sisanya, gunakan mod operator:
parseInt memiliki beberapa perangkap dengan string, untuk menghindari penggunaan parameter radix dengan basis 10
Dalam beberapa kasus representasi string nomor dapat menjadi notasi ilmiah, dalam hal ini, parseInt akan menghasilkan hasil yang salah.
Panggilan ini akan menghasilkan 1 sebagai hasilnya.
sumber
parseInt
harus dihindari bila memungkinkan. Berikut ini peringatan Douglas Crockford: "Jika karakter pertama dari string adalah 0, maka string tersebut dievaluasi dalam basis 8, bukan basis 10. Dalam basis 8, 8 dan 9 bukan digit, jadi parseInt (" 08 ") dan parseInt ("09") menghasilkan 0 sebagai hasilnya. Kesalahan ini menyebabkan masalah dalam program yang menguraikan tanggal dan waktu. Untungnya, parseInt dapat mengambil parameter radix, sehingga parseInt ("08", 10) menghasilkan 8. Saya sarankan Anda selalu berikan parameter radix. " archive.oreilly.com/pub/a/javascript/excerpts/…parseInt
harus dihindari; Hanya saja ada beberapa gotcha yang harus diperhatikan. Anda harus menyadari hal-hal ini dan bersiap untuk mengatasinya.parseInt
dengan argumen nomor.parseInt
seharusnya mengurai string sebagian-numerik, bukan angka terpotong.JavaScript menghitung dengan tepat lantai bilangan negatif dan sisa bilangan non-integer, mengikuti definisi matematika untuknya.
LANTAI didefinisikan sebagai "bilangan bulat terbesar yang lebih kecil dari parameter", dengan demikian:
REMAINDER didefinisikan sebagai "sisa" dari suatu divisi (Euclidean arithmetic). Ketika dividen bukan bilangan bulat, hasil bagi biasanya juga bukan bilangan bulat, yaitu, tidak ada sisa, tetapi jika hasil bagi dipaksa menjadi bilangan bulat (dan itulah yang terjadi ketika seseorang mencoba untuk mendapatkan sisa atau modulus dari suatu angka floating-point), akan ada "sisa" non-integer, jelas.
JavaScript memang menghitung semuanya seperti yang diharapkan, sehingga programmer harus berhati-hati untuk mengajukan pertanyaan yang tepat (dan orang-orang harus berhati-hati untuk menjawab apa yang ditanyakan!) Pertanyaan pertama Yarin bukanlah "apa pembagian bilangan X dengan Y", tapi, sebagai gantinya, "SELURUH berapa kali bilangan bulat yang diberikan PERGI ke yang lain". Untuk bilangan positif, jawabannya adalah sama untuk keduanya, tetapi tidak untuk bilangan negatif, karena pembagian bilangan bulat (dividen dengan pembagi) akan -1 lebih kecil daripada kali angka (pembagi) "masuk ke" yang lain (dividen). Dengan kata lain, FLOOR akan mengembalikan jawaban yang benar untuk pembagian bilangan bulat dari angka negatif, tetapi Yarin tidak menanyakan itu!
gammax menjawab dengan benar, kode itu berfungsi seperti yang diminta oleh Yarin. Di sisi lain, Samuel salah, dia tidak menghitung, kurasa, atau dia akan melihat bahwa itu berhasil (juga, dia tidak mengatakan apa yang menjadi pembagi dari teladannya, tetapi saya berharap itu adalah 3):
Sisa = X% Y = -100% 3 = -1
GoesInto = (X - Sisa) / Y = (-100 - -1) / 3 = -99 / 3 = -33
By the way, saya menguji kode pada Firefox 27.0.1, itu berfungsi seperti yang diharapkan, dengan angka positif dan negatif dan juga dengan nilai-nilai non-integer, baik untuk dividen dan pembagi. Contoh:
-100.34 / 3.57: GoesInto = -28, Sisa = -0.380000000000000079
Ya, saya perhatikan, ada masalah presisi di sana, tapi saya tidak punya waktu untuk memeriksanya (saya tidak tahu apakah itu masalah dengan Firefox, Windows 7 atau dengan FPU CPU saya). Namun untuk pertanyaan Yarin, yang hanya melibatkan bilangan bulat, kode gammax berfungsi dengan baik.
sumber
Math.floor(operation)
mengembalikan nilai pembulatan operasi.Contoh 1 st pertanyaan:
Menghibur:
Contoh 2 nd pertanyaan:
Menghibur:
sumber
Menghitung jumlah halaman dapat dilakukan dalam satu langkah: Math.ceil (x / y)
sumber
Komentar Alex Moore-Niemi sebagai jawaban:
Untuk Rubyist di sini dari Google dalam pencarian
divmod
, Anda dapat mengimplementasikannya seperti:Hasil:
sumber
divmod
menggunakan pembagian lantai (Math.floor
), yang berbeda dari divisi terpotong (Math.trunc
) ketika angka negatif terlibat. Ini adalah kasus untuk paket NPMdivmod
, Rubydivmod
, SWI-Prologdivmod
dan mungkin banyak implementasi lainnya juga.divmod
ada karena ia melakukan dua kali lebih cepat dari komputasi dua operasi secara terpisah. Menyediakan fungsi seperti itu tanpa manfaat kinerja ini mungkin membingungkan.Jika Anda hanya membagi dengan kekuatan dua, Anda dapat menggunakan operator bitwise:
(Yang pertama adalah hasil bagi, yang kedua sisanya)
sumber
function divideByPowerOf2(num, exponent) { return [num >> exponent, num & ((1 << exponent) - 1)]; }
,.Anda dapat menggunakan ternary untuk memutuskan bagaimana menangani nilai integer positif dan negatif juga.
Jika angkanya positif, semuanya baik-baik saja. Jika angkanya negatif, itu akan menambah 1 karena cara Math.floor menangani negatif.
sumber
Ini akan selalu terpotong menuju nol. Tidak yakin apakah sudah terlambat, tapi begini saja:
sumber
Jika Anda perlu menghitung sisanya untuk bilangan bulat yang sangat besar, yang runtime JS tidak dapat wakili seperti itu (bilangan bulat lebih besar dari 2 ^ 32 diwakili sebagai float dan karena itu kehilangan presisi), Anda perlu melakukan beberapa trik.
Ini sangat penting untuk memeriksa banyak kasus digit cek yang ada dalam banyak contoh kehidupan sehari-hari kita (nomor rekening bank, kartu kredit, ...)
Pertama-tama Anda memerlukan nomor Anda sebagai string (jika tidak, Anda telah kehilangan presisi dan sisanya tidak masuk akal).
Anda sekarang harus memisahkan string Anda menjadi bagian-bagian yang lebih kecil, cukup kecil sehingga rangkaian sisa dan seutas tali dapat muat dalam 9 digit.
Persiapkan ekspresi reguler untuk memisahkan string
Misalnya, jika
digits
7, regexp adalahIni cocok dengan nonempty substring dengan panjang maksimum 7, yang diikuti (
(?=...)
adalah lookahead positif) oleh sejumlah karakter yang kelipatan dari 7. The 'g' adalah untuk membuat ekspresi dijalankan melalui semua string, tidak berhenti pada pertandingan pertama.Sekarang konversikan setiap bagian menjadi bilangan bulat, dan hitung sisanya dengan
reduce
(menambahkan kembali sisa sebelumnya - atau 0 - dikalikan dengan kekuatan 10 yang benar):Ini akan berfungsi karena algoritme sisa "pengurangan":
yang memungkinkan untuk mengganti 'bagian awal' dari representasi desimal dari angka dengan sisanya, tanpa mempengaruhi sisa akhir.
Kode akhir akan terlihat seperti:
sumber