Javascript integer dan bahagian pecahan. Kaedah untuk membundarkan nombor dalam JavaScript. Pembundaran epsilon mesin

Selalunya pengiraan menghasilkan keputusan yang berada di luar julat yang dikehendaki. Akibatnya, perlu dilaksanakan Pembundaran JavaScript sehingga nilai tertentu.

Kenapa nombor bulat?

JavaScript tidak menyimpan integer kerana nilainya diwakili sebagai nombor titik terapung. Banyak pecahan tidak boleh diwakili sebagai nombor dengan nombor terhingga tempat perpuluhan tertentu, jadi JavaScript boleh menjana hasil seperti berikut:

0.1 * 0.2; > 0.020000000000000004

Dalam amalan, ini tidak akan membuat apa-apa perbezaan, kerana kita bercakap tentang ralat 2 quintillionths. Tetapi ini mungkin menjejaskan keputusan apabila menggunakan nombor yang mewakili nilai mata wang, peratusan atau saiz fail. Oleh itu, anda perlu melakukan atau ke tempat perpuluhan tertentu.

Membundarkan nombor perpuluhan

Untuk "memotong" nombor perpuluhan, gunakan kaedah toFixed() atau toPrecision(). Kedua-duanya mengambil satu hujah, yang menentukan bilangan tempat bererti dan perpuluhan untuk disertakan dalam keputusan:

  • jika toFixed() tidak mempunyai hujah yang ditentukan, nilai lalai ialah 0 , iaitu, tiada tempat perpuluhan; nilai hujah maksimum ialah 20 ;
  • jika tiada hujah diberikan kepada toPrecision(), nombor itu tidak ditukar.

var randNum = 6.25; randNum.toFixed(); > "6" Math.PI.toPrecision(1); > "3" var randNum = 87.335; randNum.toFixed(2); > "87.33" var randNum = 87.337; randNum.toPrecision(3); > "87.3"

Catatan

Kedua-dua toFixed() dan toPrecision mengembalikan perwakilan rentetan bulat bagi hasilnya, bukannya nombor. Ini bermakna penambahan bulat pada randNum akan menghasilkan gabungan rentetan dan bukannya satu nombor:

console.log(randNum + bulat); > "6.256"

Jika anda mahu JavaScript membundarkan nombor kepada perseratus terdekat, gunakan parseFloat() :

var randNum = 6.25; var bulat = parseFloat(randNum.toFixed(1)); console.log(bulat); > 6.3

toFixed() dan toPrecision() juga merupakan kaedah yang berguna untuk memotong sejumlah besar tempat perpuluhan. Ini berguna apabila bekerja dengan nombor yang mewakili unit monetari:

var wholeNum = 1 var dollarsCents = wholeNum.toFixed(2); console.log(dollarsCents); > "1.00"

Ambil perhatian bahawa jika nombor mempunyai lebih banyak digit daripada ketepatan yang ditentukan, toPrecision akan mengeluarkan keputusan dalam format saintifik:

var num = 123.435 num.toPrecision(2); > "1.2e+2"

Bagaimana untuk mengelakkan kesilapan semasa membundarkan perpuluhan

Dalam sesetengah kes toFixed dan toPrecision melaksanakan JavaScript membulatkan 5 ke bawah, dan tidak lebih:

var numTest = 1.005; numTest.toFixed(2); > 1;

Hasil daripada contoh di atas hendaklah 1.01, bukan 1. Jika anda ingin mengelakkan ralat ini, saya cadangkan menggunakan nombor eksponen:

fungsi bulat(nilai, perpuluhan) ( kembalikan Nombor(Math.round(nilai+"e"+perpuluhan)+"e-"+perpuluhan); )

Permohonan:

pusingan(1.005,2); > 1.01

Jika anda memerlukan penyelesaian yang lebih mantap daripada pembundaran, ia boleh didapati di MDN.

Pembundaran dengan epsilon

Kaedah alternatif JavaScript membundarkan kepada persepuluh telah diperkenalkan dalam ES6 ( juga dikenali sebagai JavaScript 2015). « Epsilon mesin" memberikan margin ralat yang munasabah apabila membandingkan dua nombor titik terapung. Tanpa pembundaran, perbandingan mungkin menghasilkan keputusan yang serupa dengan yang berikut:

0.1 + 0.2 === 0.3 > palsu

Math.EPILON boleh digunakan dalam fungsi untuk mendapatkan perbandingan yang sah:

fungsi epsEqu(x, y) ( kembalikan Math.abs(x - y)< Number.EPSILON * Math.max(Math.abs(x), Math.abs(y)); }

Fungsi ini mengambil dua hujah: satu mengandungi pengiraan, yang kedua hasil yang dijangkakan (bulat). Ia mengembalikan perbandingan dua parameter ini:

epsEqu(0.1 + 0.2, 0.3) > benar

Semua pelayar moden menyokong fungsi matematik ES6. Tetapi jika anda perlu menyediakan sokongan dalam pelayar lama, maka anda perlu menggunakan polyfills.

Pemotongan nombor perpuluhan

Semua kaedah yang dibentangkan sebelum ini berfungsi JavaScript membundarkan kepada persepuluh. Untuk memotong nombor positif kepada dua tempat perpuluhan, darabkannya dengan 100, potong semula, dan kemudian bahagikan hasilnya dengan 100:

fungsi truncated(num) ( return Math.trunc(num * 100) / 100; ) truncated(3.1416) > 3.14

Jika anda memerlukan sesuatu yang lebih fleksibel, anda boleh menggunakan operator bitwise:

fungsi dipotong(bilangan, tempat perpuluhan) ( var numPowerConverter = Math.pow(10, decimalPlaces); return ~~(num * numPowerConverter)/numPowerConverter; )

penggunaan:

var randInt = 35.874993; dipenggal(randInt,3); > 35.874

Bundarkan kepada nombor terdekat

Untuk melaksanakan Pembundaran JavaScript kepada integer terdekat, Math.round() digunakan:

Math.round(4.3) > 4 Math.round(4.5) > 5

Perhatikan bahawa " separuh nilai", seperti .5, dibundarkan ke atas.

Bundarkan ke bawah kepada nombor bulat terdekat

Jika anda ingin membundarkan ke bawah, gunakan kaedah Math.floor():

Math.floor(42.23); > 42 Math.floor(36.93); > 36

Pembundaran ke bawah mempunyai satu arah untuk semua nombor, termasuk yang negatif. Ini boleh dibayangkan sebagai bangunan pencakar langit dengan bilangan lantai yang tidak terhingga, termasuk di bawah paras asas ( mewakili nombor negatif). Jika anda berada di dalam lif antara tingkat bawah tanah 2 dan 3 ( yang sepadan dengan nilai -2.5), Math.floor akan membawa anda ke tingkat -3:

Math.floor(-2.5); > -3

Jika anda perlu mengelakkan perkara ini, gunakan pembundaran Matematik JavaScript menggunakan Math.trunc() , disokong dalam semua pelayar moden (kecuali IE/Edge):

Math.trunc(-41.43); > -41

MDN juga menyediakan polyfill tiga baris untuk menyediakan sokongan untuk Math.trunc dalam pelayar lama dan IE/Edge.

Bundarkan kepada nombor bulat terdekat

Jika anda ingin membundarkan nombor perpuluhan ke atas, gunakan Math.ceil . Kaedah ini juga boleh dianggap sebagai lif tak terhingga: Math.ceil sentiasa membawa anda "naik", tidak kira sama ada nombor itu negatif atau positif:

Math.ceil(42.23); > 43 Math.ceil(36.93); > 37 Math.ceil(-36.93); -36

Bundarkan kepada gandaan terdekat

Jika anda perlu membundarkan nilai kepada gandaan terdekat 5, buat fungsi yang membahagikan nombor dengan 5, bulatkan, dan kemudian darabkan hasilnya dengan nilai yang sama:

function roundTo5(num) ( return Math.round(num/5)*5; )

penggunaan:

roundTo5(11); > 10

Jika anda memerlukan JavaScript untuk membundarkan kepada dua digit, anda boleh menghantar kedua-dua benih dan gandaan kepada fungsi:

fungsi roundToMultiple(bilangan, berbilang) ( kembalikan Math.round(bilangan/berbilang)*berbilang; )

Untuk menggunakan fungsi, masukkan nombor yang akan dibundarkan dan berbilang dalam panggilannya:

var initialNumber = 11; var gandaan = 10; roundToMultiple(initialNumber, multiple); > 10;

Untuk membulatkan nilai ke atas atau ke bawah sahaja, gantikan bulat dengan siling atau lantai dalam fungsi.

Julat mengikat

Kadangkala anda perlu mendapatkan nilai untuk x yang mesti berada dalam julat tertentu. Sebagai contoh, kita memerlukan nilai dari 1 hingga 100, tetapi kita mendapat nilai 123. Untuk membetulkannya, anda boleh menggunakan min() ( mengembalikan nombor terkecil) dan maks ( mengembalikan nombor maksimum yang dibenarkan).

penggunaan:

var lowBound = 1; var highBound = 100; var numInput = 123; var diapit = Math.max(lowBound, Math.min(numInput, highBound)); console.log(diapit); > 100;

Anda boleh mencipta fungsi atau sambungan kelas Nombor.

Ini membolehkan anda membetulkan jawapan @MarkElliot supaya ia berfungsi untuk nombor negatif juga:

Var div = Math.trunc(y/x); var rem = y % x;

Ambil perhatian bahawa kaedah Matematik mempunyai kelebihan berbanding operator bitwise yang ia berfungsi dengan nombor yang lebih besar daripada 2 31 .

JavaScript mengira di sebelah kanan jantina nombor negatif dan baki bukan integer, mengikut takrifan matematik untuk nombor tersebut.

FLOOR ditakrifkan sebagai "integer terbesar kurang daripada parameter", oleh itu:

  • nombor positif: FLOOR(X) = bahagian integer X;
  • nombor negatif: FLOOR(X) = bahagian integer X tolak 1 (kerana ia sepatutnya LEBIH KECIL daripada parameter, iaitu lebih negatif!)

REMAINDER ditakrifkan sebagai bahagian "baki" (Aritmetik Euclidean). Apabila dividen bukan integer, faktor biasanya juga bukan integer, iaitu tidak ada baki, tetapi jika faktor dipaksa untuk menjadi integer (dan inilah yang berlaku apabila seseorang cuba mendapatkan baki atau modulus sesuatu nombor titik terapung ), jelas akan ada integer "kiri".

JavaScript mengira segala-galanya seperti yang dijangkakan, jadi pengaturcara mesti berhati-hati untuk bertanya soalan yang betul (dan orang ramai mesti berhati-hati untuk menjawab apa yang ditanya!) Soalan pertama Yarin BUKAN "apakah pembahagian integer bagi X dengan Y", sebaliknya ini: " Bilangan integer kali integer yang diberikan PERGI KE yang lain." Untuk nombor positif, jawapan adalah sama untuk kedua-duanya, tetapi bukan untuk nombor negatif, kerana pembahagian integer (dividen dengan pembahagi) akan menjadi -1 kurang daripada nombor (pembahagi) "berguling" (dividen). Dalam erti kata lain, FLOOR akan mengembalikan jawapan yang betul untuk pembahagian integer bagi nombor negatif, tetapi Yarin tidak bertanya tentang perkara itu!

gammax menjawab dengan betul, kod ini berfungsi mengikut arahan Yarin. Sebaliknya, Samuel salah, dia tidak melakukan matematik yang saya rasa, atau dia akan melihat bahawa ini benar-benar berkesan (juga dia tidak menyatakan pembahagi contohnya, tetapi saya harap ia adalah 3) :

Baki = X% Y = -100% 3 = -1

GoesInto = (X - Baki) / Y = (-100 - -1) / 3 = -99 / 3 = -33

By the way, saya menguji kod pada Firefox 27.0.1, ia berfungsi seperti yang diharapkan dengan nombor positif dan negatif, serta nilai bukan integer, untuk kedua-dua dividen dan pembahagi. Contoh:

100.34 / 3.57: GoesInto = -28, Baki = -0.3800000000000079

Ya, saya perasan bahawa terdapat masalah dengan ketepatan tinggi, tetapi saya tidak mempunyai masa untuk menyemaknya (saya tidak tahu sama ada ia masalah dengan Firefox, Windows 7 atau FPU CPU saya). Walau bagaimanapun, untuk soalan Yarin, yang hanya melibatkan integer, kod gammax berfungsi dengan baik.

Anda boleh menggunakan fungsi parseInt untuk mendapatkan hasil yang dipotong.

ParseInt(a/b)

Untuk mendapatkan baki, gunakan pengendali mod:

parseInt mempunyai beberapa perangkap dengan rentetan untuk mengelak daripada menggunakan parameter radix dengan asas 10

ParseInt("09", 10)

Dalam sesetengah kes, perwakilan rentetan nombor mungkin merupakan notasi saintifik, yang mana parseInt akan menghasilkan hasil yang salah.

ParseInt(100000000000000000000000000000000, 10) // 1e+32

Panggilan ini akan menghasilkan keputusan 1.

Mengira bilangan halaman boleh dilakukan dalam satu langkah: Math.ceil(x/y)

Jika anda hanya berkongsi kuasa dua, anda boleh menggunakan operator bitwise:

Fungsi eksport divideBy2(num) ( return ; ) fungsi eksport divideBy4(num) ( return ; ) fungsi eksport divideBy8(num) ( return ; )

(Yang pertama adalah khusus, yang kedua adalah yang lain)

Ini akan sentiasa dipotong kepada sifar. Tidak pasti sama ada sudah terlambat, tetapi ia berkata di sini:

Fungsi intdiv(dividen, pembahagi) ( pembahagi = pembahagi - pembahagi % 1; jika (pembahagi == 0) buang Ralat baharu("bahagi dengan sifar"); dividen = dividen - dividen % 1; var rem = dividen % pembahagi; pulangan ( baki: rem, hasil bagi: (dividen - rem) / pembahagi ); )

Saya bukan pakar dalam pengendali bitwise, tetapi inilah cara lain untuk mendapatkan integer:

Var num = ~~(a / b);

Ini akan berfungsi dengan baik untuk nombor negatif juga, manakala Math.floor() akan berputar ke arah yang salah.

Ini juga kelihatan betul:

Var num = (a / b) >> 0;

Math.floor(operasi) mengembalikan nilai bulat bagi operasi.

Contoh soalan 1:

Var x = 5; var y = 10.4; var z = Math.floor(x + y); console.log(z);

Konsol:

Contoh soalan 2:

Var x = 14; var y = 5; var z = Math.floor(x%y); console.log(x);

Konsol:

Untuk beberapa nombor y dan beberapa pembahagi x, hitung hasil bahagi dan baki (baki) sebagai:

Var quotient = Math.floor(y/x); baki var = y % x;

Selalunya, pengiraan dalam JavaScript tidak memberikan hasil yang kita inginkan dengan tepat. Sudah tentu, kita boleh melakukan apa sahaja yang kita mahu dengan nombor - bulatkan ke atas atau ke bawah, tetapkan julat, potong nombor yang tidak perlu kepada bilangan tempat perpuluhan tertentu, semuanya bergantung pada apa yang anda mahu lakukan dengan nombor ini pada masa hadapan.

Mengapakah pembundaran perlu?

Salah satu aspek menarik JavaScript ialah ia sebenarnya tidak menyimpan integer, kami bekerja terus dengan nombor titik terapung. Ini, digabungkan dengan fakta bahawa banyak nilai pecahan tidak boleh dinyatakan dalam bilangan tempat perpuluhan terhingga, dalam JavaScript kita boleh mendapatkan hasil seperti ini:

0.1 * 0.2; > 0.020000000000000004 0.3 - 0.1 > 0.19999999999999998
Untuk tujuan praktikal, ketidaktepatan ini tidak penting, dalam kes kami, kami bercakap tentang ralat dalam quintillion bahagian, bagaimanapun, ini mungkin mengecewakan sesetengah pihak. Kami juga boleh mendapatkan hasil yang agak pelik apabila menggunakan nombor yang mewakili mata wang, peratusan atau saiz fail. Untuk membetulkan ketidaktepatan ini, kita hanya perlu dapat membundarkan keputusan, dan sudah cukup untuk menetapkan ketepatan perpuluhan.

Pembundaran nombor mempunyai aplikasi praktikal, kita boleh memanipulasi nombor dalam julat tertentu, contohnya kita mahu membundarkan nilai kepada nombor bulat terdekat dan bukannya bekerja hanya dengan bahagian perpuluhan.

Membundarkan nombor perpuluhan

Untuk memotong nombor perpuluhan, gunakan toFixed atau kaedah toPrecision. Kedua-duanya mengambil satu hujah yang menyatakan, masing-masing, berapa banyak angka bererti (iaitu, jumlah bilangan digit yang digunakan dalam nombor) atau tempat perpuluhan (nombor selepas titik perpuluhan) hasilnya harus termasuk:
  1. Jika argumen tidak ditakrifkan untuk toFixed(), ia akan lalai kepada sifar, yang bermaksud 0 tempat perpuluhan, argumen mempunyai nilai maksimum 20.
  2. Jika tiada hujah diberikan kepada toPrecision, nombor itu dibiarkan tanpa disentuh
biarkan randNum = 6.25; randNum.toFixed(); > "6" Math.PI.toPrecision(1); > "3" randNum = 87.335; randNum.toFixed(2); > "87.33" randNum = 87.337; randNum.toPrecision(3); > "87.3"
Kedua-dua kaedah toFixed() dan toPrecision() mengembalikan perwakilan rentetan hasil, bukan nombor. Ini bermakna apabila menjumlahkan nilai bulat dengan randNum, ia akan menghasilkan gabungan rentetan dan bukannya jumlah nombor:

Biarkan randNum = 6.25; biarkan bulat = randNum.toFixed(); // "6" console.log(randNum + bulat); > "6.256"
Jika anda mahu hasilnya menjadi jenis data berangka, maka anda perlu menggunakan parseFloat:

Biarkan randNum = 6.25; biarkan bulat = parseFloat(randNum.toFixed(1)); console.log(bulat); > 6.3
Sila ambil perhatian bahawa nilai 5 dibundarkan kecuali dalam kes yang jarang berlaku.

Kaedah toFixed() dan toPrecision() berguna kerana ia bukan sahaja boleh memotong bahagian pecahan, tetapi juga menambah tempat perpuluhan, yang sesuai apabila bekerja dengan mata wang:

Biarkan wholeNum = 1 biarkan dollarsCents = wholeNum.toFixed(2); console.log(dollarsCents); > "1.00"
Ambil perhatian bahawa toPrecision akan menghasilkan keputusan dalam notasi saintifik jika bilangan integer lebih besar daripada ketepatan itu sendiri:

Biarkan num = 123.435 num.toPrecision(2); > "1.2e+2"

Cara Mengelakkan Ralat Pembundaran dengan Perpuluhan

Dalam sesetengah kes, toFixed dan toPrecision membulatkan nilai 5 ke bawah dan ke atas:

Biarkan numTest = 1.005; numTest.toFixed(2); > "1.00"
Keputusan pengiraan di atas sepatutnya 1.01, bukan 1. Jika anda ingin mengelakkan ralat yang sama, kita boleh menggunakan penyelesaian yang dicadangkan oleh Jack L Moore, yang menggunakan nombor eksponen untuk pengiraan:

Pusingan fungsi(nilai, perpuluhan) ( kembalikan Nombor(Math.round(value+"e"+decimals)+"e-"+decimals); )
sekarang:

Pusingan(1.005,2); > 1.01
Jika anda mahukan penyelesaian yang lebih mantap daripada yang ditunjukkan di atas, anda boleh pergi ke MDN.

Pembundaran epsilon mesin

Kaedah alternatif untuk membundarkan nombor perpuluhan telah diperkenalkan dalam ES6. Pembundaran epsilon mesin memberikan margin ralat yang munasabah apabila membandingkan dua nombor titik terapung. Tanpa pembundaran, perbandingan mungkin menghasilkan keputusan yang serupa dengan yang berikut:

0.1 + 0.2 === 0.3 > palsu
Kami menggunakan Math.EPILON dalam fungsi kami untuk mendapatkan perbandingan yang sah:

Fungsi epsEqu(x, y) ( kembalikan Math.abs(x - y)< Number.EPSILON * Math.max(Math.abs(x), Math.abs(y)); }
Fungsi ini mengambil dua hujah: yang pertama ialah pengiraan semasa, yang kedua ialah hasil yang dijangkakan. Ia mengembalikan perbandingan kedua-duanya:

EpsEqu(0.1 + 0.2, 0.3) > benar
Semua penyemak imbas moden sudah menyokong fungsi matematik ES6, tetapi jika anda mahukan sokongan dalam pelayar seperti IE 11, gunakan polyfills.

Memotong bahagian pecahan

Semua kaedah yang dibentangkan di atas boleh membundarkan kepada nombor perpuluhan. Untuk hanya memotong nombor kepada dua tempat perpuluhan, anda mesti mendarabkannya dengan 100, dan kemudian membahagikan hasil yang terhasil dengan 100:

Fungsi dipenggal(bilangan) ( kembalikan Math.trunc(bilangan * 100) / 100; ) dipenggal(3.1416) > 3.14
Jika anda ingin menyesuaikan kaedah kepada sebarang bilangan tempat perpuluhan, anda boleh menggunakan penafian berganda bitwise:

Fungsi dipenggal(bilangan, decimalPlaces) ( biarkan numPowerConverter = Math.pow(10, decimalPlaces); return ~~(num * numPowerConverter)/numPowerConverter; )
sekarang:

Biarkan randInt = 35.874993; dipenggal(randInt,3); > 35.874

Bundarkan kepada nombor terdekat

Untuk membundarkan nombor perpuluhan kepada nombor terdekat ke atas atau ke bawah, yang mana kita paling hampir, gunakan Math.round():

Math.round(4.3) > 4 Math.round(4.5) > 5
Sila ambil perhatian bahawa "separuh nilai", 0.5 dibundarkan mengikut peraturan matematik.

Bundarkan ke bawah kepada nombor bulat terdekat

Jika anda ingin sentiasa membundarkan ke bawah, gunakan Math.floor:

Math.floor(42.23); > 42 Math.floor(36.93); > 36
Sila ambil perhatian bahawa pembundaran ke bawah berfungsi untuk semua nombor, termasuk nombor negatif. Bayangkan sebuah bangunan pencakar langit dengan bilangan tingkat yang tidak terhingga, termasuk lantai di tingkat bawah (mewakili nombor negatif). Jika anda berada di dalam lif pada tahap paling rendah antara 2 dan 3 (yang mewakili nilai -2.5), Math.floor akan membawa anda ke -3:

Math.floor(-2.5); > -3
Tetapi jika anda ingin mengelakkan situasi ini, gunakan Math.trunc, disokong dalam semua pelayar moden (kecuali IE/Edge):

Math.trunc(-41.43); > -41
Pada MDN anda akan menemui polyfill yang akan menyediakan sokongan untuk Math.trunc dalam pelayar dan IE/Edge.

Bundarkan kepada nombor bulat terdekat

Sebaliknya, jika anda sentiasa perlu membulatkan, gunakan Math.ceil. Sekali lagi, ingat lif tak terhingga: Math.ceil akan sentiasa "naik", tidak kira sama ada nombornya negatif atau tidak:

Math.ceil(42.23); > 43 Math.ceil(36.93); > 37 Math.ceil(-36.93); > -36

Membundarkan ke atas/bawah kepada nombor yang diperlukan

Jika kita ingin membundarkan kepada gandaan 5 yang terdekat, cara paling mudah ialah mencipta fungsi yang membahagikan nombor dengan 5, membundarkannya dan kemudian mendarabkannya dengan jumlah yang sama:

Function roundTo5(num) ( return Math.round(num/5)*5; )
sekarang:

RoundTo5(11); > 10
Jika anda ingin membundarkan kepada gandaan nilai anda, kami menggunakan fungsi yang lebih umum, menghantar nilai awal dan gandaan:

Fungsi roundToMultiple(bilangan, berbilang) ( return Math.round(bilang/multiple)*multiple; )
sekarang:

Biarkan nombor awal = 11; biarkan gandaan = 10; roundToMultiple(initialNumber, multiple); > 10;

Membetulkan nombor dalam julat

Terdapat banyak kes di mana kita ingin mendapatkan nilai x yang terletak dalam julat. Sebagai contoh, kita mungkin memerlukan nilai antara 1 dan 100, tetapi kita berakhir dengan nilai 123. Untuk membetulkannya, kita boleh menggunakan min (mengembalikan set nombor terkecil) dan maks (mengembalikan yang terbesar daripada mana-mana set daripada nombor). Dalam contoh kami, julat adalah dari 1 hingga 100:

Biarkan lowBound = 1; biarkan highBound = 100; biarkan numInput = 123; biarkan diapit = Math.max(lowBound, Math.min(numInput, highBound)); console.log(diapit); > 100;
Sekali lagi, kita boleh menggunakan semula operasi dan membungkus semuanya dalam fungsi, menggunakan penyelesaian yang dicadangkan oleh Daniel X. Moore:

Number.prototype.clamp = function(min, max) ( return Math.min(Math.max(ini, min), max); );
sekarang:

NumInput.clamp(lowBound, highBound); > 100;

Pembundaran Gaussian

Pembundaran Gaussian, juga dikenali sebagai pembundaran jurubank, melibatkan pembundaran kepada nombor genap terdekat. Kaedah pembundaran ini berfungsi tanpa ralat statistik. Penyelesaian yang lebih baik telah dicadangkan oleh Tim Down:

Fungsi gaussRound(bilangan, Tempat perpuluhan) ( biarkan d = Tempat perpuluhan || 0, m = Math.pow(10, d), n = +(d ? num * m: num).toFixed(8), i = Math.floor (n), f = n - i, e = 1e-8, r = (f > 0.5 - e && f< 0.5 + e) ? ((i % 2 == 0) ? i: i + 1) : Math.round(n); return d ? r / m: r; }
sekarang:

GaussRound(2.5) > 2 gaussRound(3.5) > 4 gaussRound(2.57,1) > 2.6
Perpuluhan dalam CSS:

Memandangkan JavaScript sering digunakan untuk membuat pemetaan kedudukan untuk elemen HTML, anda mungkin tertanya-tanya apa yang akan berlaku jika kami menjana nilai perpuluhan untuk elemen kami:

#box ( lebar: 63.667731993px; )
Berita baiknya ialah pelayar moden akan menghormati nilai perpuluhan dalam model blok, termasuk peratusan atau unit piksel.

Menyusun

Selalunya kita perlu mengisih beberapa elemen, sebagai contoh, kita mempunyai pelbagai rekod permainan, dan ia mesti disusun mengikut urutan menurun pangkat pemain. Malangnya, kaedah sort() standard mempunyai beberapa had yang mengejutkan: ia berfungsi dengan baik dengan perkataan Inggeris biasa, tetapi segera rosak apabila ia menemui nombor, aksara unik atau perkataan huruf besar.

Menyusun mengikut abjad

Nampaknya menyusun tatasusunan mengikut abjad sepatutnya menjadi tugas yang mudah:

Biarkan buah = ["butternut squash", "apricot", "cantaloupe"]; fruit.sort(); > "aprikot", "labu butternut", "cantaloupe"]
Walau bagaimanapun, kami menghadapi masalah sebaik sahaja salah satu elemen adalah huruf besar:

Biarkan buah = ["butternut squash", "apricot", "Cantalope"]; fruit.sort(); > "Cantaloupe", "apricot", "butternut squash"]
Ini kerana, secara lalai, pengisih membandingkan aksara pertama yang diwakili dalam Unicode. Unicode ialah kod unik untuk mana-mana aksara, tanpa mengira platform, tanpa mengira program, tanpa mengira bahasa. Contohnya, jika anda melihat jadual kod, aksara "a" mempunyai nilai U+0061 (dalam perenambelasan 0x61), manakala aksara "C" mempunyai kod U+0043 (0x43), yang datang lebih awal dalam Unicode jadual daripada aksara "a".

Untuk mengisih tatasusunan yang mungkin mengandungi huruf pertama kes bercampur, kita perlu sama ada menukar semua elemen buat sementara waktu kepada huruf kecil, atau mentakrifkan susunan isihan kami menggunakan kaedah localeCompare() dengan beberapa argumen. Sebagai peraturan, untuk kes sedemikian, lebih baik untuk segera membuat fungsi untuk kegunaan berulang:

Fungsi alphaSort(arr) ( arr.sort(function (a, b) ( return a.localeCompare(b, "en", ("sensitivity": "base")); )); ) biarkan buah = ["butternut squash ", "aprikot", "Cantaloupe"]; alphaSort(buah) >
Jika anda mahu tatasusunan disusun mengikut susunan abjad terbalik, cuma tukar kedudukan a dan b dalam fungsi:

Fungsi alphaSort(arr) ( arr.sort(function (a, b) ( return b.localeCompare(a, "en", ("sensitivity": "base")); )); ) biarkan buah = ["butternut squash ", "aprikot", "Cantaloupe"]; alphaSort(buah) > ["Cantaloupe", "butternut squash", "apricot"]
Di sini perlu diperhatikan bahawa localeCompare digunakan dengan argumen, kita juga perlu ingat bahawa ia disokong oleh IE11+, untuk versi lama IE, kita boleh menggunakannya tanpa argumen, dan dalam huruf kecil:

Function caseSort(arr) ( arr.sort(function (a, b) ( return a.toLowerCase().localeCompare(b.toLowerCase()); )); ) biarkan buah = ["butternut squash", "apricot", "Cantaloupe"]; caseSort(buah) > ["apricot", "butternut squash", "Cantaloupe"]

Isihan angka

Semua ini tidak terpakai kepada contoh yang kita bincangkan di atas tentang susunan rekod permainan. Dengan beberapa tatasusunan angka, pengisihan berfungsi dengan baik, tetapi pada satu ketika hasilnya tidak dapat diramalkan:

Biarkan highScores = ; highScores.sort(); >
Masalahnya ialah kaedah sort() melakukan perbandingan leksikografi: yang bermaksud bahawa nombor akan ditukar menjadi rentetan dan perbandingan akan dibuat semula dengan memadankan aksara pertama rentetan itu dalam susunan aksara dalam jadual Unicode . Oleh itu, kami sekali lagi perlu menentukan susunan isihan kami:

Biarkan highScores = ; highScores.sort(function(a,b) ( return a - b; )); >
Sekali lagi, untuk mengisih nombor dalam susunan terbalik, tukar kedudukan a dan b dalam fungsi.

Mengisih struktur seperti JSON

Dan akhirnya, jika kita mempunyai struktur data seperti JSON yang diwakili sebagai tatasusunan rekod permainan:

Mari skor = [ ( "nama": "Daniel", "skor": 21768 ), ( "nama": "Michael", "skor": 33579 ), ( "nama": "Alison", "skor": 38395 ) ];
Dalam ES6+, anda boleh menggunakan fungsi anak panah:

Scores.sort((a, b) => b.skor - a.skor));
Untuk pelayar lama yang tidak mempunyai sokongan ini:

Scores.sort(function(a, b) ( return a.skor - b.skor ));
Seperti yang anda lihat, pengisihan dalam JavaScript adalah perkara yang agak kabur, saya harap contoh ini akan menjadikan hidup lebih mudah entah bagaimana.

Bekerja dengan fungsi kuasa

Eksponen ialah operasi yang pada asalnya ditakrifkan sebagai hasil pendaraban nombor asli dengan sendirinya; punca kuasa dua a ialah nombor yang memberikan a apabila kuasa dua. Kita boleh menggunakan fungsi ini secara berterusan dalam kehidupan seharian dalam pelajaran matematik, termasuk semasa mengira luas, isipadu, atau bahkan dalam pemodelan fizikal.

Dalam JavaScript, fungsi kuasa diwakili sebagai Math.pow(), dan dalam standard ES7 baharu, pengendali eksponen baharu telah diperkenalkan - " * * ".

Eksponensiasi

Untuk menaikkan nombor kepada kuasa ke-n, gunakan fungsi Math.pow(), dengan argumen pertama ialah nombor yang akan dinaikkan kepada kuasa, argumen kedua ialah eksponen:

Math.pow(3,2) > 9
Bentuk tatatanda ini bermaksud 3 kuasa dua, atau 3 × 3, yang membawa kepada hasil 9. Contoh lain boleh diberikan, sudah tentu:

Math.pow(5,3); > 125
Iaitu, 5 kubus, atau 5 × 5 × 5, adalah sama dengan 125.

ECMAScript 7 ialah versi JavaScript yang seterusnya, pada dasarnya, kita boleh menggunakan pengendali eksponensial yang dicadangkan baharu - * *, bentuk tatatanda ini mungkin lebih deskriptif:

3 ** 2 > 9
Pada masa ini, sokongan untuk pengendali ini agak terhad, jadi tidak disyorkan untuk menggunakannya.

Fungsi kuasa boleh berguna dalam pelbagai situasi. Contoh mudah, mengira bilangan saat dalam sejam: Math.pow (60,2).

Akar kuasa dua dan kubus

Math.sqrt() dan Math.cbrt() adalah bertentangan dengan Math.pow(). Seperti yang kita ingat, punca kuasa dua a ialah nombor yang memberikan a apabila kuasa dua.

Math.sqrt(9) > 3
Pada masa yang sama, punca kubus a ialah nombor yang memberikan a apabila dinaikkan kepada kubus.

Math.cbrt(125) > 5
Math.cbrt() baru sahaja diperkenalkan ke dalam spesifikasi JavaScript, dan oleh itu hanya disokong dalam penyemak imbas moden: Chrome 38+, Firefox dan Opera 25+ dan Safari 7.1+. Anda akan perasan bahawa Internet Explorer tiada dalam senarai ini, tetapi anda akan menemui polyfill pada MDN.

Contoh

Sudah tentu, kita boleh menggunakan nilai bukan integer dalam salah satu fungsi ini:

Math.pow(1.25, 2); > 1.5625 Math.cbrt(56.57) > 3.8387991760286138
Sila ambil perhatian bahawa ini juga berfungsi dengan baik apabila menggunakan nilai hujah negatif:

Math.pow(-5,2) > 25 Math.pow(10,-2) > 0.01
Walau bagaimanapun, ini tidak akan berfungsi untuk punca kuasa dua:

Math.sqrt(-9) > NaN
Daripada analisis matematik kita tahu bahawa nombor khayalan merujuk kepada punca kuasa dua nombor negatif. Dan ini mungkin membawa kita kepada teknik lain untuk bekerja dengan nombor kompleks, tetapi itu cerita lain.

Anda boleh menggunakan pecahan dalam Math.pow() untuk mencari punca kuasa dua dan kubus nombor. Punca kuasa dua menggunakan eksponen 0.5:

Math.pow(5, 0.5); // = Math.sqrt(5) = 5 ** (1/2) > 2.23606797749979
Walau bagaimanapun, disebabkan keanehan titik terapung, anda tidak dapat meneka dengan tepat hasil yang betul:

Math.pow(2.23606797749979,2) > 5.000000000000001
Dalam situasi sedemikian, anda perlu mengambil jalan keluar untuk memotong tanda daripada nombor atau pembundaran kepada beberapa nilai.

Sesetengah orang, atas sebab yang tidak diketahui, dalam JavaScript mengelirukan fungsi Math.pow() dengan Math.exp() , iaitu fungsi eksponen untuk nombor secara umum. Nota: Dalam bahasa Inggeris, "exponent" diterjemahkan sebagai "exponent", jadi ini lebih berkemungkinan digunakan untuk penutur bahasa Inggeris, walaupun terdapat nama alternatif untuk exponent, seperti indeks, kuasa.

Pemalar matematik

Bekerja dengan matematik dalam JavaScript menjadi lebih mudah dengan beberapa pemalar terbina dalam. Pemalar ini adalah sifat bagi objek Matematik. Perlu diingat bahawa pemalar ditulis dalam huruf besar, bukan notasi CamelCase.

Math.abs, parseInt, parseFloat

Bekerja dengan nombor dalam JavaScript boleh menjadi lebih rumit daripada yang kelihatan. Nilai yang diperolehi tidak selalunya berada dalam julat yang dijangkakan; kadangkala hasilnya mungkin tidak sama sekali seperti yang kita jangkakan.

Math.abs()

Kaedah Math.abs() mengembalikan nilai mutlak nombor, yang mengingatkan kita tentang fungsi matematik yang serupa untuk modulus nombor.

Biarkan newVal = -57.64; Math.abs(newVal); > 57.64
Math.abs(0) sentiasa mengembalikan sifar, tetapi jika kita meletakkan tanda tolak di hadapan fungsi -Math.abs(NUM) kita akan sentiasa mendapat nilai negatif.

Math.abs(0); > -0

parseInt()

Kami tahu bahawa JavaScript memahami bahawa "15" ialah rentetan, bukan nombor dan, sebagai contoh, apabila menghuraikan sifat CSS menggunakan JavaScript atau menerima nilai daripada tatasusunan yang tidak disediakan, keputusan kami mungkin tidak dapat diramalkan. Kami boleh menerima rentetan yang diwakili sebagai "17px" sebagai input, dan ini bukan perkara luar biasa bagi kami. Persoalannya ialah bagaimana untuk menukar rentetan ini kepada nilai sebenar dan menggunakannya dalam pengiraan selanjutnya.

Sintaks: parseInt(rentetan, radix);

Fungsi parseInt menukar hujah pertama yang dihantar kepadanya kepada jenis rentetan, mentafsirnya dan mengembalikan nilai integer atau NaN. Hasilnya (jika bukan NaN) ialah integer dan merupakan hujah pertama (rentetan), dianggap sebagai nombor dalam radix yang ditentukan. Sebagai contoh, asas 10 menunjukkan penukaran daripada perpuluhan, 8 daripada perlapanan, 16 daripada perenambelasan, dan seterusnya. Jika asasnya lebih besar daripada 10, maka huruf digunakan untuk mewakili nombor yang lebih besar daripada 9. Contohnya, untuk nombor perenambelasan (asas 16), huruf A hingga F digunakan.

Mari lihat contoh bekerja dengan sifat CSS, di mana, secara relatifnya, kita boleh mendapatkan nilai berikut:

Biar elem = document.body; biarkan centerPoint = window.getComputedStyle(elem).transformOrigin; > "454px 2087.19px"
Kita boleh membahagikan nilai dengan ruang:

Biarkan pusat = centerPoint.split(" "); > ["454px", "2087.19px"]
Walau bagaimanapun, setiap elemen masih rentetan, kita boleh menyingkirkannya dengan menggunakan fungsi kami:

Biarkan centerX = parseInt(pusat, 10); > 454 biarkan centerY = parseInt(pusat, 10); >2087
Seperti yang anda lihat, dengan hujah kedua kami menunjukkan sistem nombor yang mana nombor itu akan ditukar; parameter ini adalah pilihan, tetapi disyorkan untuk menggunakannya jika anda tidak tahu rentetan mana yang akan diterima sebagai input.

parseFloat()

Daripada contoh di atas, anda mungkin perasan bahawa parseInt membuang bahagian pecahan. Dalam kes kami, parseFloat boleh berfungsi dengan nombor titik terapung. Sekali lagi, ini boleh berguna apabila menghuraikan CSS dan tugas lain, terutamanya apabila bekerja dengan peratusan titik terapung.

Sintaks: parseFloat(rentetan)

Biarkan FP = "33.33333%"; console.log(parseFloat(FP)); > 33.33333
Ambil perhatian bahawa tiada hujah kedua dalam sintaks parseFloat.

Walaupun kami memahami bahawa parseInt() dan parseFloat() adalah fungsi yang sangat berguna, adalah penting untuk diingat bahawa ia bukan tanpa ralat, jadi adalah perlu untuk menyemak julat nilai yang dijangkakan dan akhirnya menganalisis hasilnya untuk memastikan bahawa nilai yang diperoleh adalah betul.
Hantar tanpa nama


Dalam bahagian pelajaran kita ini kita akan berkenalan dengan objek tersebut Nombor seperti bekas jenis data berangka. Intipati objektifnya yang sebenar akan disentuh secara dangkal hari ini.

Sama seperti objek Tali mengandungi baris teks, objek Nombor mengandungi nombor. Sama seperti rentetan, nombor yang kita cipta secara automatik menjadi contoh objek.

Jenis data nombor

Terdapat dua jenis nombor dalam JavaScript: integer dan titik terapung (tiada pembahagian kepada banyak jenis, seperti dalam bahasa lain integer, panjang, pendek, berganda ). Nombor titik terapung mempunyai bahagian integer dan pecahan yang dipisahkan oleh titik (tanpa mengira tetapan tempat).

Kedua-dua jenis nombor ini bukan jenis bebas dan tidak memerlukan penukaran khas antara mereka sendiri. Jika, sebagai contoh, 32.5 kita akan membiak dengan 0.4 , maka kita serta-merta mendapat integer 13 , bukan pecahan 13.0 , yang perlu ditukar kepada nilai integer (seperti yang sering berlaku dalam bahasa lain).

Mencipta objek Nombor

Seperti rentetan, nombor biasanya dijadikan sebagai objek Nombor, tugasan mudah (tidak seperti rentetan, tiada petikan diperlukan).

var myNum = 21 ;

Tetapi anda juga boleh membuat objek baharu menggunakan pembina:

var myNum = Nombor baharu; myNum = 21 ;

Dalam kebanyakan kes, ini tidak perlu dan bahkan berbahaya. Kami akan melihat contoh yang betul bagi kerja sedemikian dengan objek dalam Bahagian 4.

Perwakilan nombor

Borang eksponen

Nombor boleh diwakili sama ada dalam bentuk biasa atau eksponen, contohnya:

2e6 // tiada ruang!

Ia bermaksud: 2 × 10 6

Jika kita mengeluarkan nombor sedemikian melalui kaedah dokumen tulis(), maka kita mendapat nombor yang dikembangkan dalam perwakilan biasa.

Dokumen. menulis(14e12);

Keputusan:

Sistem nombor asas

Nombor juga boleh diwakili dalam sistem perpuluhan, heksadesimal dan perlapanan.

Keseluruhan nombor dalam bentuk perpuluhan tidak sepatutnya bermula dari awal, kerana sifar ialah awalan untuk sistem bukan perpuluhan. Cuma 0 awalan untuk nilai perlapanan, dan 0x untuk heksadesimal.

Sebagai contoh, 075 ialah perwakilan perlapanan bagi nombor perpuluhan 61 , A 0x75 perwakilan heksadesimal bagi nombor perpuluhan 117 .

Untuk nilai perlapanan, nombor daripada 0 sebelum ini 7 , untuk siri alfanumerik heksadesimal 0123456789ABCDEF. Surat boleh digunakan dalam mana-mana daftar.

Ungkapan aritmetik boleh menggunakan sebarang bentuk nombor, tetapi hasilnya akan sentiasa diwakili sebagai nombor perpuluhan.

Perwakilan nombor dalam sistem lain

Bercakap tentang objek Tali, kami menyentuh kaedah menjalin(), yang menukarkan sebarang objek kepada rentetan. Apabila menukar nombor kepada rentetan, adalah dinasihatkan untuk menentukan sistem nombor sebagai hujah.

Nota

Nombor asal mesti disertakan dalam kurungan

(nombor). menjalin(sistem)

sistem boleh mengambil sebarang nilai dari 2 hingga 36.

(157 ).menjalin(2 ); // perwakilan binari 157, sama (53 ).menjalin(27 ); // perwakilan 27 digit eksotik 53, sama

Tetapi ungkapan yang terhasil ini adalah rentetan. Untuk menjadikannya nombor nyata dalam sistem nombor yang ditentukan, anda memerlukan hasil kaedah tersebut toString(sistem) tukar balik kepada nombor. Ini tidak lagi dilakukan dengan kaedah, tetapi fungsi kernel Nombor (objek). Kita akan bercakap tentang fungsi kernel dalam salah satu pelajaran yang akan datang, tetapi buat masa ini perhatikan sintaks, ia serupa dengan panggilan fungsi:

var a = 1546 ; var b = a. menjalin(2); var c = Nombor(b);

Atau segera, "dua dalam satu":

var a = 1546 ; var b = Nombor(a. menjalin(2 ));

Catatan

Jika nombor asal diberikan kepada pembolehubah, maka ia tidak perlu diletakkan dalam kurungan semasa memanggil kaedah menjalin() .

Sifat objek Nombor

Kami akan menyentuh sifat objek umum pembina dan prototaip dalam pelajaran tentang objek Objek, dan sekarang mari kita beralih kepada sifat khusus objek Nombor.

Sifat-sifat ini hanya untuk bacaan, iaitu, kita tidak boleh mengubahnya.

MAX_VALUE

Bilangan maksimum yang boleh diproses dalam JavaScript.

Mari lihat nombor jenis apa ini:

var e = Nombor . MAX_VALUE dokumen. menulis(e)

Keputusan:

1.7976931348623157e+308

Plus dalam kes ini bukan tanda tambahan, tetapi tahap positif, iaitu 1.7976931348623157 × 10,308

Catatan

Saya biasanya menunjukkan hasil menggunakan skrip bertulis yang sebenarnya. Tetapi terlalu banyak pengiraan pecahan boleh melambatkan pemuatan halaman, dan kebanyakan hasil dalam tutorial ini adalah tulisan tangan, boleh dikatakan.

MIN_VALUE

Dan ini adalah sewajarnya nilai minimum. Mari kita terokainya.

var f = Nombor . MIN_VALUE dokumen. menulis(f)

Keputusan:

Itu dia 5 × 10 -324

Nilai bukan angka yang telah kami temui.

Sifat ini dikembalikan oleh JavaScript apabila operasi berangka entah bagaimana menghasilkan hasil bukan angka.

NEGATIVE_INFINITY, POSITIVE_INFINITY

Pada suatu masa dahulu mereka berfikir seperti ini: "satu rusa, dua rusa, banyak rusa."

JavaScript mengira sedikit lebih "maju": "satu rusa, dua rusa, tiga rusa, ... , 1.7976931348623157 × 10,308 rusa, banyak rusa."

"banyak" transendental ini dinyatakan oleh hartanah POSITIVE_INFINITY.

Apabila proses diterbalikkan, membahagikan unit (“satu rusa”) kepada kepingan kecil, kecil, bahagian terkecil yang dikira ialah 5 × 10 -324 bahagian. Yang kurang pun sudah NEGATIVE_INFINITY.

Kaedah objek Nombor

Nota: Sama seperti kaedah toString(), semua kaedah lain memerlukan nombor asal disertakan dalam kurungan jika ia diwakili secara eksplisit (bukan sebagai pembolehubah).

toExponential()

Mengembalikan rentetan yang mewakili nombor dalam tatatanda saintifik, dengan satu digit sebelum titik perpuluhan.

Sintaks:

nombor. kepadaEksponen(bilangan tanda)

Hujah bilangan tanda menentukan ketepatan pembundaran selepas titik perpuluhan. Jika hujah ditinggalkan, bilangan digit selepas titik perpuluhan adalah sama dengan bilangan digit yang diperlukan untuk mewakili nilai.

Contoh:

var myFullNumber = 4659872156831598853654127 ; dokumen. menulis(myFullNumber.toExponential(4))

Keputusan:

toFixed()

Mengembalikan rentetan yang mewakili nombor titik tetap, dibundarkan kepada bilangan tempat perpuluhan yang dinyatakan dalam hujah.

Sintaks:

nombor. kepadaTetap(bilangan tanda)

Contoh:

var myDecimal1 = 46.59872156831598853654127 ; var myDecimal2 = 46 ; dokumen. menulis(myDecimal1.toFixed(1)) dokumen. menulis("
") dokumen. menulis(myDecimal2.toFixed(3))

Keputusan:

Kaedah ini kadang-kadang sangat berguna. Sebagai contoh, fungsi rumit dari pelajaran lepas kini boleh diwakili seperti ini:

function anyRootPlus(x, y) ( var srcnum = Math . exp(Math. log(x)/y); var hasil = (srcnum). kepadaTetap(3); pulangan hasil; )

Sekarang mari masukkannya ke dalam borang dan ujinya:

Benar, kini integer juga akan mempunyai tiga sifar selepas titik. Tetapi, mengetahui kelakuan nombor dan rentetan, mengetahui cara bekerja dengan pengendali bersyarat dan penukaran jenis, tidaklah begitu sukar untuk membuat "reka bentuk" berangka yang diperlukan.

toLocaleString()

Menukar objek berangka kepada nilai rentetan, dengan mengambil kira tetapan tempat untuk pemisah perpuluhan dan beribu-ribu pemisah. Mata wang negara diambil sebagai asas, oleh itu dalam versi Rusia semua nombor, walaupun integer, dibentangkan dengan dua tempat perpuluhan (kopecks):

var myDrob = 25.327 ; var myMnogo = 25635120 ; var myRoubl = 35 ; /* besarkan untuk melihat koma dengan lebih baik */ dokumen. menulis("

" + myDrob. toLocaleString() + "

" ); dokumen. menulis("

" + myMnogo. toLocaleString() + "

" ); dokumen. menulis("

" + myRoubl. toLocaleString() + "

" );

Keputusan:

toPrecision()

Mengembalikan rentetan yang mewakili nombor dengan jumlah bilangan digit bererti yang ditentukan.

Sintaks:

nombor. toPrecision(kuantitiDigit)

Hujah:

kuantitiDigit bilangan digit dalam baris yang dipaparkan. Jika kuantiti yang ditentukan lebih besar daripada kuantiti dalam nombor asal, sifar perpuluhan dipaparkan.

Dokumen. menulis((354 ).toPrecision(8 ))

Keputusan:

Kaedah toPrecision() Dan toLocaleString() bersama-sama tidak berfungsi, untuk "reka bentuk Rusia" nombor apa-apa ketepatan, anda perlu menulis fungsi anda sendiri. Fungsi bertulis boleh dijadikan kaedah tambahan objek Nombor, kami telah melakukan sesuatu yang serupa dengan objek Tarikh(). Butiran lanjut dalam pelajaran tentang objek Objek.

menjalin()

Nah, kami telah membincangkan kaedah ini secara terperinci pada permulaan pelajaran.

Cipta kaedah anda sendiri

Sekarang kita akan mencipta kaedah yang sama yang akan memaparkan nombor dengan sebarang bilangan tempat perpuluhan dengan ruang antara tempat keseribu dan dengan koma sebagai pemisah perpuluhan.

Untuk melakukan ini, kita memerlukan fungsi yang agak rumit yang akan menukar rentetan dan tatasusunan yang diperoleh daripada contoh objek Nombor.

Mari kita isytiharkan kaedah:

Number.prototype.toRussianString = kepadaRussianString

Sebelum kita mula membina fungsi, mari kita rumuskan tugas.

Mula-mula kita perlu mewakili nombor sebagai rentetan dan mengekstrak bahagian integer, bahagian pecahan dan titik pemisah daripadanya.

Kemudian letakkan ruang yang diperlukan dalam bahagian integer, bulatkan bahagian pecahan kepada bilangan aksara yang boleh ditentukan sebagai hujah kepada fungsi (dan kaedah), dan tukar noktah kepada koma.

Mari kita mulakan fungsi dengan mengisytiharkan pembolehubah yang diperlukan.

fungsi kepadaRussianString(prec) ( /* pembolehubah untuk menukar rentetan */ var a = "" , b = "" , c, d, e;

Melihat ke hadapan, saya akan mengatakan bahawa bahagian perpuluhan, akibat gangguan rentetan kami, kehilangan intipati "pecahan"nya, dan kami perlu bekerja dengannya seperti dengan integer lain. Untuk bekerja dengannya kami akan menggunakan kaedah tersebut toPrecision(), dan hujah fungsi kami (dan pada masa yang sama kaedah kami) menetapkan nilai khusus untuk kaedah tersebut toPrecision(). Parameter minimum kaedah ini adalah satu. Dan fungsi kami juga mungkin memerlukan sifar (apabila membundarkan kepada integer). Dan pada masa yang sama, pembundaran yang betul harus berfungsi walaupun sebelum kita mula "memotong" objek. Oleh itu, dengan serta-merta apabila mengisytiharkan pembolehubah, kami akan memintas perangkap ini:

/* pembolehubah yang menukar contoh objek yang diberikan kepada rentetan */ if (prec == 0 ) var str = this . kepadaTetap(0 ).menjalinmenjalin(10 );

Kami terus mengisytiharkan pembolehubah.

/* pembolehubah untuk nilai pulangan */ var nr1; /* pembolehubah untuk bahagian "letupan" */ var intpart, fractpaft, precpart, divider, dot = str. lastIndexOf("." ); /* kaunter */ var i;

Pembolehubah titik mencari kedudukan titik dalam rentetan nombor yang ditentukan. Pada kedudukan ini kami memotong keseluruhan bahagian ( intpart). Jika nombor itu adalah integer dan tiada titik, kedudukannya akan kurang daripada sifar. Dalam kes ini, pemisah ( pembahagi), dan bahagian pecahan ( bahagian pecahan) mestilah rentetan kosong. Jika tidak, koma diberikan kepada pemisah, dan bahagian pecahan dipotong untuk kerja selanjutnya:

jika (titik< 0 ) { intpart = str; fractpart = "" ; pembahagi = "" ;) lain (intpart = str. subrentetan(0 , titik); bahagian pecahan = str. subrentetan(titik + 1 , str. panjang); pembahagi = "," ;}

Kami bekerja dengan keseluruhan bahagian. Ruang hanya diperlukan jika terdapat lebih daripada 3 aksara:

jika (intpart. panjang > 3 ) {

Sekarang mari kita bermain permainan "solitaire" berikut (semua ini berlaku dalam pernyataan bersyarat):

Mari kita mengimbas kembar tiga dalam susunan terbalik.

Mula-mula, mari kumpulkan mereka menjadi pembolehubah a tanpa sebarang penambahan, hanya untuk mengira panjang subrentetan yang terhasil. Lagipun, jika jumlah bilangan digit tidak boleh dibahagikan dengan 3, maka ekor 1 atau 2 digit kekal di sebelah kiri, dan kini kita boleh menyatakannya sebagai subrentetan dengan menolak panjang subrentetan dengan "tiga" daripada panjang keseluruhan rentetan (pembolehubah c). Dan letakkan ruang yang tidak pecah di hadapannya (yang akan kami keluarkan kemudian). Untuk apa? Oleh kerana kumpulan tiga digit dibaca dalam susunan terbalik, ekor awal ini harus diletakkan di hujung baris. Iaitu, jika kita mempunyai nombor, katakan, 36748521, kita perlu berbaris 521,748 36, meletakkan ruang yang tidak pecah di hadapan setiap kumpulan supaya terdapat pemisah untuk tatasusunan (lagipun, kita perlu membalikkannya kembali, dan ini boleh dilakukan menggunakan kaedah tatasusunan terbalik()).

Dalam arahan terakhir gelung, kami akan menyusun dalam tiga kali ganda dan menulis hasilnya kepada pembolehubah b.

untuk (i=intpart. panjang-3 ; i>=0 ; i-=3 ) /* kumpul kembar tiga */( a = a + intpart. substr(i, 3); /* cari "ekor" kiri */ c = " " + bahagian. substr(0 , intpart. panjang-a. panjang); /* letakkan pemisah dalam kembar tiga */ b = b + " " + bahagian. substr(i, 3);)

Apabila menambah rentetan b+c kita mendapat rentetan yang perlu ditukar menjadi tatasusunan, dan kemudian tatasusunan ini diterbalikkan dan ditukar semula menjadi rentetan (ini semua ditulis kepada pembolehubah d).

D = (b+c). berpecah(" " ).terbalik().menjalin().menggantikan(/,/g, " " );

Tatasusunan ditukar kepada rentetan bersama-sama dengan pembatas koma; kami tidak memerlukannya. Oleh itu, dalam arahan yang sama kami mengeluarkannya menggunakan ungkapan biasa /,/g, Di mana /,/ mencipta ungkapan biasa untuk koma, dan g"bendera", yang menunjukkan bahawa anda perlu menggantikan semua corak ungkapan (hanya meletakkan semua koma) yang muncul dalam baris. Kami menggantikannya dengan ruang tidak pecah yang sama.

(Ungkapan biasa akan dibincangkan secara terperinci dalam bahagian terakhir tutorial.)

Dan sekarang kita perlu membersihkan sesuatu yang lain (di dalam pernyataan bersyarat yang sama jika (intpart.length > 3)).

Hakikatnya ialah sama ada pada permulaan atau pada penghujung baris kami akan ada ruang tambahan yang tidak putus yang terdiri daripada 6 aksara: “&”, “n”, “b”, “s”, “p” dan “ ;”. Oleh itu, mari kita mengosongkan sampah dan menulis hasilnya kepada pembolehubah e:

jika (d. subrentetan(0 , 1 ) == "&" ) e = d. subrentetan(6 , d. panjang-6 ); lain e = d. subrentetan(0 , d. panjang-6 );

Sekarang kita boleh, dengan hati nurani yang bersih, menutup keseluruhan operator bersyarat dan menulis pilihan alternatif untuk nombor pendek yang tidak perlu dibahagikan kepada "tiga".

) else e = intpart;

Jadi pembolehubah e menyimpan bahagian integer nombor, dan kami akan berurusan dengan bahagian perpuluhan.

Perhatian! Apabila kita bekerja dengan bahagian pecahan (yang kini perlu dirawat secara keseluruhan), kita mesti ingat bahawa apabila sebelum == 0 fungsi akan bergelut, jadi mari pasangkannya dengan segera:

jika (prec != 0 ) (

Sekarang anda boleh bekerja dengan tenang. Tetapi terdapat beberapa lagi "batu" yang kini kita akan memintas.

Pertama, jika kita mempunyai bahagian pecahan, andaikan 41 , dan kami menetapkan pembundaran kepada 3 digit, kemudian kaedahnya toPrecision, mengambil bahagian pecahan kita sebagai integer, akan mengeluarkan 41.0 , iaitu, anda perlu mengeluarkan titik itu.

Kedua, jika bahagian pecahan nombor asal lebih daripada 3 digit, maka kaedahnya toPrecision akan mula menghasilkan keputusan dalam bentuk eksponen. Anda juga perlu melawan ini.

Oleh itu, kami akan "membersihkan" hasilnya melalui tiga pembolehubah: precpart, precpart1 Dan precpart2.

Precpart = (Nombor (fractpart). toPrecision(prac)). menjalin(10 )

Sekarang kita "membersihkan":

/* jika terdapat bahagian pecahan */ jika (bahagian pecahan != "") ( /* cari dan hapuskan titik */ precpart1 = precpart. menggantikan(".", "") /* semak untuk melihat sama ada terdapat eksponen di sana, */ var plus = precpart1.lastIndexOf("e"); /* dan jika wujud, */ jika (tambah > 0 ) /* cabut sampai ke akarnya, */ precpart2 = precpart1. subrentetan(0 , tambah); /* jika tidak */ lain /* jangan ubah apa-apa */ precpart2 = precpart1 ) /* jika tiada bahagian pecahan, */ lain /* kemudian kami mengeluarkan sifar dan sekali lagi menyingkirkan titik */ precpart2 = "," +precpart. menggantikan("." , "" )

Oleh kerana kami menunjukkan pada mulanya bahawa jika tiada bahagian pecahan dalam nombor asal, tiada koma, maka dalam kes ini kita perlu meletakkannya semula.

) lain ( /* iaitu, jika prec masih sifar, cuma cetak baris kosong */ precpart2 = "" ; pembahagi = "" ; }

Dan kord terakhir:

Nr1 = e + pembahagi + precpart2; kembalikan nr1; )

Keseluruhan fungsi:

function toRussianString(prec) ( var a = "" , b = "" , c, d, e; if (prec == 0 ) var str = this . kepadaTetap(0 ).menjalin(10 ); else var str = ini . menjalin(10 ); var nr1; var intpart, fractpaft, precpart, divider, dot = str. lastIndexOf("." ); var i; jika (titik< 0 ) { intpart = str; fractpart = "" ; pembahagi = "" ;) lain (intpart = str. subrentetan(0 , titik); bahagian pecahan = str. subrentetan(titik + 1 , str. panjang); pembahagi = "," ;) jika (intpart. panjang> 3 ) ( untuk (i=intpart. panjang-3 ; i>=0 ; i-=3 ) ( a = a + intpart. substr(i, 3); c = " " + bahagian. substr(0 , intpart. panjang-a. panjang); b = b + " " + bahagian. substr(i, 3 );) d = (b+c). berpecah(" " ).terbalik().menjalin().menggantikan(/,/g, " " ); jika (d. subrentetan(0 , 1 ) == "&" ) e = d. subrentetan(6 , d. panjang-6 ); lain e = d. subrentetan(0 , d. panjang-6 ); ) else e = intpart; if (prec != 0 ) ( precpart = (Nombor (fractpart). toPrecision(prac)). menjalin(10) jika (fractpart != "") ( precpart1 = precpart. menggantikan(".", "") var plus = precpart1.lastIndexOf("e"); jika (tambah > 0 ) precpart2 = precpart1. subrentetan(0 , tambah); else precpart2 = precpart1 ) else precpart2 = "," +precpart. menggantikan("." , "" ) ) lain ( precpart2 = "" ; pembahagi = "" ; ) nr1 = e + pembahagi + precpart2; kembalikan nr1; )

Fungsi ini kini boleh dipanggil sebagai kaedah.

Var myNumber = 2569843359.6583521 dokumen. menulis(nombor saya. kepadaRussianString(3 ))

Keputusan:

Anda boleh meletakkan pembina kaedah dan fungsi dalam perpustakaan - iaitu, dalam fail .js yang boleh dipanggil daripada kod halaman web. Semasa anda menulis kaedah untuk objek yang berbeza, anda boleh mengisih kaedah ke dalam fail perpustakaan untuk objek ini dan menggunakan kaedah tambahan.