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.

mcherm
sumber
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
bayangan bulan
sumber
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
Robert Koritnik
sumber
@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);
}
Jackson
sumber
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.

brad
sumber
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);
Mike
sumber
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);
Graeme Wicksted
sumber
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
Prasanth
sumber
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.

Russell Leggett
sumber
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
Juliane Holzt
sumber
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
Pisau cukur
sumber
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/

Dmitry Kharitonov
sumber
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...

Alireza
sumber
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

pk_code
sumber
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

Gerard ONeill
sumber
0

Jika Anda menggunakan angularjs maka solusi sederhana sebagai berikut Di Binding Template HTML

{{val | number:0}}

itu akan mengubah val menjadi integer

lanjutkan dengan tautan ini docs.angularjs.org/api/ng/filter/number

Jameel Grand
sumber