Bagaimana cara saya mengkonversi nomor float ke seluruh nomor dalam JavaScript?


1110

Saya ingin mengonversi float ke seluruh angka dalam JavaScript. Sebenarnya, saya ingin tahu bagaimana melakukan KEDUA konversi standar: dengan memotong dan membulatkan. Dan efisien, bukan melalui konversi ke string dan parsing.


83
Jika Anda tidak mengetahuinya, semua angka dalam javascript adalah float. Dari spesifikasinya:
beberapa

6
4.3.20 Jenis Nomor: Jenis nomor adalah seperangkat nilai yang mewakili angka. Dalam ECMAScript, himpunan nilai mewakili nilai doubleprecision 64-bit format IEEE 754 termasuk nilai “Not-a-Number” (NaN) khusus, infinity positif, dan infinity negatif.
Beberapa

9
Ya, Javascript tidak memiliki tipe "integer" yang berbeda, tetapi masih jarang harus melakukan konversi ini. Misalnya, dalam aplikasi saya pengguna mengetikkan angka (mungkin termasuk sen). Saya harus memotong sen dan menampilkannya dengan tanda koma. Langkah 1 adalah mengonversi ke int.
mcherm

1
juga berguna: perbandingan kecepatan semua metode jsperf.com/math-floor-vs-math-round-vs-parseint/33
c ..

1
@karl: Jika saya menerima input ke dalam sebuah bidang, saya mungkin dapat mengontrol karakter apa yang saya terima, tapi saya bisa melakukan semua jenis pemrosesan dalam Javascript, bukan hanya menerima input pengguna. Bahkan kemudian saya mungkin menginginkannya untuk hal-hal seperti pasta pendukung.
mcherm

Jawaban:


1609
var intvalue = Math.floor( floatvalue );
var intvalue = Math.ceil( floatvalue ); 
var intvalue = Math.round( floatvalue );

// `Math.trunc` was added in ECMAScript 6
var intvalue = Math.trunc( floatvalue );

Referensi objek matematika


Contohnya

Positif
// value=x        //  x=5          5<x<5.5      5.5<=x<6  

Math.floor(value) //  5            5            5
Math.ceil(value)  //  5            6            6
Math.round(value) //  5            5            6
Math.trunc(value) //  5            5            5
parseInt(value)   //  5            5            5
~~value           //  5            5            5
value | 0         //  5            5            5
value >> 0        //  5            5            5
value >>> 0       //  5            5            5
value - value % 1 //  5            5            5
Negatif
// value=x        // x=-5         -5>x>=-5.5   -5.5>x>-6

Math.floor(value) // -5           -6           -6
Math.ceil(value)  // -5           -5           -5
Math.round(value) // -5           -5           -6
Math.trunc(value) // -5           -5           -5
parseInt(value)   // -5           -5           -5
value | 0         // -5           -5           -5
~~value           // -5           -5           -5
value >> 0        // -5           -5           -5
value >>> 0       // 4294967291   4294967291   4294967291
value - value % 1 // -5           -5           -5
Positif - Angka yang lebih besar
// x = Number.MAX_SAFE_INTEGER/10 // =900719925474099.1

// value=x            x=900719925474099    x=900719925474099.4  x=900719925474099.5

Math.floor(value) //  900719925474099      900719925474099      900719925474099
Math.ceil(value)  //  900719925474099      900719925474100      900719925474100
Math.round(value) //  900719925474099      900719925474099      900719925474100
Math.trunc(value) //  900719925474099      900719925474099      900719925474099
parseInt(value)   //  900719925474099      900719925474099      900719925474099
value | 0         //  858993459            858993459            858993459
~~value           //  858993459            858993459            858993459
value >> 0        //  858993459            858993459            858993459
value >>> 0       //  858993459            858993459            858993459
value - value % 1 //  900719925474099      900719925474099      900719925474099
Negatif - Angka yang lebih besar
// x = Number.MAX_SAFE_INTEGER/10 * -1 // -900719925474099.1

// value = x      // x=-900719925474099   x=-900719925474099.5 x=-900719925474099.6

Math.floor(value) // -900719925474099     -900719925474100     -900719925474100
Math.ceil(value)  // -900719925474099     -900719925474099     -900719925474099
Math.round(value) // -900719925474099     -900719925474099     -900719925474100
Math.trunc(value) // -900719925474099     -900719925474099     -900719925474099
parseInt(value)   // -900719925474099     -900719925474099     -900719925474099
value | 0         // -858993459           -858993459           -858993459
~~value           // -858993459           -858993459           -858993459
value >> 0        // -858993459           -858993459           -858993459
value >>> 0       //  3435973837           3435973837           3435973837
value - value % 1 // -900719925474099     -900719925474099     -900719925474099

82
Seperti disebutkan dalam jawaban lain, truncate negatif-aman dapat dilakukan menggunakan var intValue = ~~floatValue;. Jika notasi terlalu mengaburkan untuk selera Anda, hanya menyembunyikannya dalam suatu fungsi: function toInt(value) { return ~~value; }. (Ini juga mengubah string menjadi bilangan bulat, jika Anda mau melakukannya.)
Keen

4
Akan terbalik jika jawaban ini memiliki contoh input / output.
J. Random Coder

7
Mengenai komentar ~~ membatasi nilai hingga 32 bit integer yang ditandatangani, sedangkan Math.floor / ceil / round dapat menangani hingga 53-bit (Number.MAX_SAFE_INTEGER 9007199254740991). Ini disebutkan dalam jawaban di bawah, tetapi perlu diulang di sini untuk mereka yang membaca komentar ini.
John

2
Baca dari bawah di beberapa tempat: Math.trunc(val);Komentar karena ini adalah jawaban yang diterima
Old Badman Grey

Tidak bekerja dengan presisi yang tepat untuk nilai-nilai seperti2.3 - 2.3 % 1
Lapys

301

Bitwise ATAU operator

Bitwise atau operator dapat digunakan untuk memotong angka floating point dan berfungsi untuk positif maupun negatif:

function float2int (value) {
    return value | 0;
}

Hasil

float2int(3.1) == 3
float2int(-3.1) == -3
float2int(3.9) == 3
float2int(-3.9) == -3

Perbandingan kinerja?

Saya telah membuat tes JSPerf yang membandingkan kinerja antara:

  • Math.floor(val)
  • val | 0 bitwise ATAU
  • ~~val bitwise TIDAK
  • parseInt(val)

yang hanya berfungsi dengan angka positif. Dalam hal ini Anda aman untuk menggunakan operasi bitwise sebaik Math.floorfungsinya.

Tetapi jika Anda membutuhkan kode Anda untuk bekerja dengan positif dan negatif , maka operasi bitwise adalah yang tercepat (ATAU menjadi yang disukai). Tes JSPerf lainnya ini membandingkan hal yang sama di mana cukup jelas bahwa karena tanda tambahan memeriksa Matematika sekarang paling lambat dari empat.

Catatan

Sebagaimana dinyatakan dalam komentar, operator BITWISE beroperasi pada bilangan bulat 32bit yang ditandatangani, oleh karena itu sejumlah besar akan dikonversi, contoh:

1234567890  | 0 => 1234567890
12345678901 | 0 => -539222987

@FabioPoloni: ya super sederhana dan sepertinya operator bitwise adalah yang tercepat. Terutama operator OR selalu yang tercepat yang paling sering dicocokkan dengan operasi NOT dan Math walaupun operasi Math adalah yang paling lambat ketika Anda harus mendukung angka negatif juga, karena itu menambah pemeriksaan tambahan tanda angka.
Robert Koritnik

9
@thefourtheye: Semua operasi bitwise kecuali shift kanan yang tidak ditandatangani, bekerja pada bilangan bulat 32-bit yang telah ditandatangani. Oleh karena itu menggunakan operasi bitwise pada nilai floating point akan mengonversinya menjadi bilangan bulat yang melepas digit setelah titik desimal.
Robert Koritnik

3
Jika Anda hanya membutuhkannya untuk angka positif, Math.floor()lebih cepat (setidaknya menurut saya menjalankan tes JSPerf pertama Anda di Google Chrome, versi 30.0.1599.101), lebih kuat (karena tidak tergantung pada bagaimana angka diwakili dalam bit, yang mungkin berubah dan mungkin merusak solusi bitwise ini), dan yang paling penting, lebih eksplisit.
ma11hew28

8
Perhatikan bahwa operator bitwise beroperasi pada angka 32 bit. Mereka tidak akan bekerja untuk angka yang terlalu besar untuk muat dalam 32 bit.
Kat

2
~~lebih baik karena ini adalah operator unary. 4.2|0+4sama dengan 4tetapi ~~4.2+4sama8
Janus Troelsen

94

Catatan: Anda tidak dapat menggunakan Math.floor()sebagai pengganti truncate, karena Math.floor(-3.1) = -4dan tidak -3!!

Pengganti yang benar untuk truncate adalah:

function truncate(value)
{
    if (value < 0) {
        return Math.ceil(value);
    }

    return Math.floor(value);
}

1
Itu tergantung pada perilaku yang diinginkan untuk angka negatif. Beberapa penggunaan membutuhkan angka negatif untuk memetakan ke nilai yang lebih negatif (-3,5 -> -4) dan beberapa mengharuskan mereka untuk memetakan ke integer yang lebih kecil (-3,5 -> -3). Yang pertama biasanya disebut "lantai". Kata "truncate" sering digunakan untuk menggambarkan perilaku yang baik. Dalam kasus saya, saya hanya akan memberinya angka negatif. Tetapi komentar ini adalah peringatan yang berguna bagi mereka yang Peduli dengan perilaku angka negatif.
mcherm

28
@mcherm: Maka mereka tampaknya tidak memahami istilah "terpotong" dengan benar. Truncate tidak persis seperti namanya: ia memotong digit. Ini tidak pernah (dalam pengertian umum) setara dengan lantai atau langit-langit. en.wikipedia.org/wiki/Truncation
Thanatos

5
Math.trunc(value)ditambahkan dalam ECMAScript 6
4esn0k

2
floorputaran menuju -infinity, truncateputaran menuju nol. ( ceilputaran menuju + tak terhingga).
Peter Cordes

46

Operator bitwise ganda tidak dapat digunakan untuk memotong float. Operasi lain yang Anda sebutkan tersedia melalui Math.floor, Math.ceil, dan Math.round.

> ~~2.5
2
> ~~(-1.4)
-1

Lebih detail dari James Padolsey.


1
Ini mungkin hal yang buruk untuk dilakukan untuk kode produksi (karena tidak jelas) tapi itu persis apa yang saya butuhkan untuk golf kode mesin rendering font saya <canvas>di JS . Terima kasih!
Kragen Javier Sitaker

10
Ini juga dapat dilakukan dengan n | 0.
Jay Douglass

17
Perhatikan bahwa salah satu metode (~~ n atau n | 0) hanya bekerja pada angka hingga 2 ^ 31-1, atau 2147483647. 2147483648 atau lebih tinggi akan menghasilkan hasil yang salah; misalnya, 2147483647 | 0 mengembalikan -2147483648, dan 4294967295 | 0 mengembalikan -1, yang hampir pasti bukan yang Anda inginkan.
Ed Bayiates

40

Untuk memotong:

var intvalue = Math.floor(value);

Untuk putaran:

var intvalue = Math.round(value);

6
Math.floor tidak memotong nilai negatif. Lihat jawaban di atas. Kalau tidak jawaban yang bagus.
oligofren

Jika Anda tertarik dengan kinerja, saya telah meletakkan test case kecil di sini: jsperf.com/dsafdgdfsaf/2 (var | 0 menang di sini).
Simbolik

25

Anda bisa menggunakan metode parseInt tanpa pembulatan. Hati-hati dengan input pengguna karena awalan 0x (hex) dan 0 (oktal).

var intValue = parseInt(floatValue, 10);

1
Ini sebenarnya membantu ketika Anda hanya ingin bagian bilangan bulat dari desimal, tanpa pembulatan ke atas atau ke bawah, itulah yang dilakukan .round, .ceil, dan .floor.
Yehuda Gabriel Himango

1
... bahkan ketika hanya memotong ini tampaknya menjadi metode paling lambat. jsperf.com/float-to-int-conversion-comparison
Robert Koritnik

2
Selalu berikan nilai 2 ke parseInt untuk menentukan basis apa yang Anda harapkan. Jadi, parseInt (floatValue, 10) untuk selalu mendapatkan basis 10.
Tim Tisdall

3
Meskipun ini sudah tua, pertanyaan ini sepertinya merupakan pertanyaan yang sering ditanyakan, jadi saya akan menempatkan ini di sini sebagai peringatan. Jika nilai diwakili menggunakan notasi "e" karena ukurannya, itu hanya akan menghasilkan satu digit, bukan apa yang diharapkan. Sebagai contoh, parseInt(1000000000000000000000, 10);menghasilkan 1, bukan 1 000 000 000 000 000 000 000. Lagi pula, pertanyaannya secara eksplisit tidak ingin " mengkonversi ke string dan parsing ", meskipun itu relatif kecil ...;)
Qantas 94 Heavy

4
@ Qantas94Heavy Alasan untuk perilaku ini, adalah karena parseInt()mengharapkan string bukan angka sebagai parameter pertama. Ketika Anda melewati bilangan bulat ini, itu dikonversi ke 1e21dan kemudian parseIntmem-parsing string 1e21, yang menghasilkan 1.
Olaf Dietsche

18

Pergeseran bit sebesar 0 yang setara dengan pembagian dengan 1

// >> or >>>
2.0 >> 0; // 2
2.0 >>> 0; // 2

4
Catatan kecil: >> 0tampaknya hanya berfungsi untuk bilangan bulat < 2 ^ 31-1 , dan >>> 0untuk bilangan bulat < 2 ^ 32-1 . Ini mengembalikan 0 untuk nilai yang lebih besar
Romuald Brunet

@RomualdBrunet, ya, JavaScript jelas mendefinisikan semua operasi bitwise sebagai operasi pada angka 32 bit. Itu ada dalam spesifikasi.
Alexis Wilke

Ini berfungsi karena Javascript hanya menjalankan operasi bitwise dengan bilangan bulat (ditandatangani) 32bit seperti yang dinyatakan dalam jawaban di atas. Jadi setiap bit-operasi yang tampaknya tidak melakukan apa-apa (seperti pergeseran untuk 0, ATAU dengan 0, DAN dengan 1, ganda TIDAK) masih memerlukan penerjemah Javascript untuk mengkonversi nilai ke int 32bit.
FrankKrumnow

9

Dalam kasus Anda, ketika Anda menginginkan sebuah string pada akhirnya (untuk memasukkan koma), Anda juga dapat menggunakan Number.toFixed()fungsi tersebut, namun ini akan melakukan pembulatan.


7

Ada banyak saran di sini. Bitwise OR tampaknya menjadi yang paling sederhana sejauh ini. Berikut ini adalah solusi pendek lain yang berfungsi dengan angka negatif serta menggunakan operator modulo. Mungkin lebih mudah dipahami daripada bitwise ATAU:

intval = floatval - floatval%1;

Metode ini juga berfungsi dengan angka bernilai tinggi di mana '| 0' atau '~~' atau '>> 0' tidak berfungsi dengan benar:

> n=4294967295;
> n|0
-1
> ~~n
-1
> n>>0
-1
> n-n%1
4294967295

Jika Anda merujuk ke jawaban lain, silakan tambahkan referensi atau buat sketsa idenya.
bertl

5

Untuk memotong :

// Math.trunc() is part of the ES6 spec
Math.trunc( 1.5 );  // returns 1
Math.trunc( -1.5 ); // returns -1
// Math.floor( -1.5 ) would return -2, which is probably not what you wanted

Untuk bulat :

Math.round( 1.5 );  // 2
Math.round( 1.49 ); // 1
Math.round( -1.6 ); // -2
Math.round( -1.3 ); // -1

5

Satu lagi cara yang mungkin - gunakan operasi XOR:

console.log(12.3 ^ 0); // 12
console.log("12.3" ^ 0); // 12
console.log(1.2 + 1.3 ^ 0); // 2
console.log(1.2 + 1.3 * 2 ^ 0); // 3
console.log(-1.2 ^ 0); // -1
console.log(-1.2 + 1 ^ 0); // 0
console.log(-1.2 - 1.3 ^ 0); // -2

Prioritas operasi bitwise kurang dari prioritas operasi matematika, ini berguna. Coba di https://jsfiddle.net/au51uj3r/


2

Jika melihat ke Mathobjek asli dalam JavaScript, Anda mendapatkan sejumlah fungsi untuk bekerja pada angka dan nilai, dll ...

Pada dasarnya apa yang ingin Anda lakukan cukup sederhana dan asli dalam JavaScript ...

Bayangkan Anda memiliki nomor di bawah ini:

const myValue = 56.4534931;

dan sekarang jika Anda ingin membulatkannya ke nomor terdekat, cukup lakukan:

const rounded = Math.floor(myValue);

dan Anda mendapatkan:

56

Jika Anda ingin membulatkannya ke nomor terdekat, cukup lakukan:

const roundedUp = Math.ceil(myValue);

dan Anda mendapatkan:

57

Juga Math.roundhanya membulatkannya ke angka yang lebih tinggi atau lebih rendah tergantung mana yang lebih dekat dengan nomor flot.

Anda juga dapat menggunakan ~~nomor di belakang float, yang akan mengkonversi float menjadi bilangan bulat.

Anda bisa menggunakannya seperti ~~myValue...


Harap berhati-hati dengan ~~karena jika jumlahnya lebih besar dari batas int 32, itu akan mengubah nilai ke nilai batas int 32.
Machado

1

//Convert a float to integer

Math.floor(5.95)
//5

Math.ceil(5.95)
//6

Math.round(5.4)
//5

Math.round(5.5)
//6

Math.trunc(5.5)
//5

//Quick Ways
console.log(5.95| 0)
console.log(~~5.95) 
console.log(5.95 >> 0)
//5


0

Saya hanya ingin menunjukkan bahwa Anda ingin membulatkan uang, dan tidak memotong. Kehilangan uang satu sen lebih kecil kemungkinannya, karena 4.999452 * 100 bulat akan memberi Anda 5, jawaban yang lebih representatif.

Dan di atas itu, jangan lupa tentang pembulatan bankir , yang merupakan cara untuk melawan bias yang sedikit positif yang diberikan pembulatan langsung - aplikasi keuangan Anda mungkin memerlukannya.

Pembulatan Gaussian / bankir dalam JavaScript


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.