JavaScript'te bir kayan nokta numarasını tam sayıya nasıl dönüştürebilirim?


1110

JavaScript'te bir şamandırayı tam sayıya dönüştürmek istiyorum. Aslında, standart dönüşümlerin her ikisini de nasıl yapacağımı bilmek istiyorum: keserek ve yuvarlayarak. Ve verimli bir şekilde, bir dizeye dönüştürme ve ayrıştırma yoluyla değil.


83
Eğer bilmiyorsan, javascript içindeki tüm sayılar yüzer. Spesifikasyondan:
bazı 2

6
4.3.20 Sayı Türü: Sayı türü sayıları temsil eden bir değerler kümesidir. ECMAScript'te, değerler kümesi özel "Sayı Değil" (NaN) değerleri, pozitif sonsuzluk ve negatif sonsuzluk dahil olmak üzere çift duyarlıklı 64 bit format IEEE 754 değerlerini temsil eder.
bazı

9
Evet, Javascript'in farklı bir "tamsayı" türü yoktur, ancak bu dönüşümü yapmak hala nadir değildir. Örneğin, benim uygulamada kullanıcılar bir sayı (muhtemelen sent dahil) yazdı. Ben sent kesilmiş ve virgül w / görüntülemek zorunda kaldı. Adım 1 int dönüştürmek oldu.
mcherm

1
ayrıca yararlı: tüm yöntemlerin hız karşılaştırması jsperf.com/math-floor-vs-math-round-vs-parseint/33
c ..

1
@karl: Bir alana girdi kabul edersem, hangi karakterleri kabul ettiğimi kontrol edebilirim, ancak Javascript'te sadece kullanıcı girişini kabul etmeden her türlü işlemi yapabilirim. O zaman bile macunu desteklemek gibi şeyler için isteyebilirim.
mcherm

Yanıtlar:


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 );

Matematik nesne başvurusu


Örnekler

Pozitif
// 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
Olumsuz
// 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
Pozitif - Daha büyük sayılar
// 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 - Büyük sayılar
// 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
Başka bir cevapta belirtildiği gibi, negatif-güvenli bir kesme kullanılarak yapılabilir var intValue = ~~floatValue;. Notasyonu senin zevke gizleyebilir çok ise, sadece bir işlevde gizlemek: function toInt(value) { return ~~value; }. (Eğer bunu önemsiyorsanız, bu aynı zamanda dizeleri tamsayılara dönüştürür.)
Keen

4
Bu cevabın örnek girdi / çıktısı olup olmadığını değerlendirir.
J. Random Coder

7
Yorum ile ilgili ~~ değeri 32 bit işaretli tamsayılarla sınırlarken, Math.floor / ceil / round 53-bit'e kadar işleyebilir (Number.MAX_SAFE_INTEGER 9007199254740991). Bu, aşağıdaki cevapta belirtilmiştir, ancak bu yorumları okuyanlar için burada tekrar etmeye değer.
John

2
Aşağıdan birkaç yerde okuyun: Math.trunc(val);Yorum çünkü bu kabul edilen cevaptır
Old Badman Gray

Gibi değerler için kesin bir hassasiyetle çalışmaz2.3 - 2.3 % 1
Lapys

301

Bitsel VEYA operatör

Bir bitsel veya operatör kayan nokta rakamlarını kısaltmak için kullanılabilir ve pozitifler ve negatifler için çalışır:

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

Sonuçlar

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

Performans karşılaştırması?

Arasında performansı karşılaştıran bir JSPerf testi oluşturdum :

  • Math.floor(val)
  • val | 0 bitsel VEYA
  • ~~val bitsel DEĞİL
  • parseInt(val)

sadece pozitif sayılarla çalışır. Bu durumda, Math.floorfonksiyonun yanı sıra bitsel işlemleri de kullanabilirsiniz .

Ancak , negatiflerin yanı sıra pozitiflerle çalışmak için kodunuza ihtiyacınız varsa , en hızlı şekilde bitsel işlem (VEYA tercih edilen yöntemdir). Bu diğer JSPerf testi , Math'ın ek işaret kontrolü nedeniyle şimdi dördün en yavaş olduğu oldukça açık olanı karşılaştırıyor .

Not

Yorumlarda belirtildiği gibi, BITWISE operatörleri imzalı 32 bit tamsayılarda çalışır, bu nedenle büyük sayılar dönüştürülür, örnek:

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

@FabioPoloni: evet süper basit ve bitsel operatörler en hızlı gibi görünüyor. Özellikle OR operatörü her zaman NOT ve Matematik işlemleri tarafından en hızlı eşleştirilir, ancak negatif sayıları da desteklemeniz gerektiğinde Matematik işlemleri en yavaştır, çünkü ek bir sayı işareti kontrolü ekler.
Robert Koritnik

9
@thefourtheye: İmzasız sağ kaydırma hariç tüm bitsel işlemler, işaretli 32 bit tamsayılar üzerinde çalışır. Bu nedenle, kayan nokta değerlerinde bitsel işlemler kullanmak, bunları ondalık noktadan sonra basamakları sıyırmak için bir tamsayıya dönüştürür.
Robert Koritnik

3
Sadece pozitif sayılar için ihtiyacınız varsa Math.floor(), daha hızlıdır (en azından Google Chrome'da ilk JSPerf testinizi çalıştırmamıza göre , sürüm 30.0.1599.101), daha sağlamdır (çünkü sayıların bit cinsinden nasıl temsil edildiğine bağlı değildir, ve bu bitsel çözümü değiştirebilir ve bozabilir) ve en önemlisi daha açıktır.
ma11hew28

8
Bitsel operatörlerin 32 bit sayılarla çalıştığını unutmayın. 32 bite sığmayacak kadar büyük sayılar için çalışmazlar.
Kat

2
~~daha iyi çünkü tek bir operatör. 4.2|0+4eşittir 4ama ~~4.2+4eşittir8
Janus Troelsen

94

Not: Math.floor()Kesmek için yedek olarak kullanamazsınız , çünkü Math.floor(-3.1) = -4değil -3!

Kesme için doğru değiştirme:

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

    return Math.floor(value);
}

1
Bu, negatif sayılar için istenen davranışa bağlıdır. Bazı kullanımlar daha negatif değere (-3.5 -> -4) eşlemek için negatif sayılara, bazıları ise daha küçük tamsayıya (-3.5 -> -3) eşlemelerini gerektirir. İlkine normalde "zemin" denir. "Kesme" kelimesi genellikle her iki davranışı tanımlamak için kullanılır. Benim durumumda, sadece negatif sayıları besleyecektim. Ancak bu yorum, negatif sayı davranışını önemseyenler için yararlı bir uyarıdır.
mcherm

28
@mcherm: O zaman "kısalt" terimini doğru anlamıyorlar. Truncate tam olarak isminden de anlaşılacağı gibi rakamları kısaltır. Asla (genel anlamda) zemine veya tavana eşdeğer değildir. tr.wikipedia.org/wiki/Truncation
Thanatos

5
Math.trunc(value)ECMAScript 6
4esn0k

2
floorsonsuzluğa truncateyuvarlar, sıfıra yuvarlar. ( ceil+ sonsuza doğru yuvarlar).
Peter Cordes

46

Şamandıraları kısaltmak için çift bitsel olmayan bir operatör kullanılabilir. Bahsettiğiniz diğer işlemler mevcut aracılığıyla vardır Math.floor, Math.ceilve Math.round.

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

Daha fazla detay James Padolsey'in izniyle.


1
Bu muhtemelen (o belirsiz olduğundan) üretim kodu için yapmak kötü bir şeydir ama ben kod golf için tam olarak ihtiyaç duyduğumuz benim <canvas>JS yazı tipi oluşturma motorunu . Teşekkür ederim!
Kragen Javier Sitaker

10
Bu aynı zamanda n | 0.
Jay Douglass

17
Her iki yöntemin (~~ n veya n | 0) yalnızca 2 ^ 31-1 veya 2147483647'ye kadar olan sayılar üzerinde çalıştığını unutmayın. 2147483648 veya daha yüksek bir değer yanlış sonuç döndürür; örneğin, 2147483647 | 0, -2147483648 ve 4294967295 | 0, -1 değerini döndürür, bu da kesinlikle istediğiniz gibi değildir.
Ed Bayiates


25

Yuvarlama olmadan parseInt yöntemini kullanabilirsiniz . 0x (onaltılık) ve 0 (sekizli) önek seçenekleri nedeniyle kullanıcı girişine dikkat edin.

var intValue = parseInt(floatValue, 10);

1
Bu aslında, ondalık sayının tamsayı kısmını yukarı veya aşağı yuvarlamadan istediğinizde yararlıdır.
Judah Gabriel Himango

1
... basitçe keserken bile bu en yavaş yöntem gibi görünüyor. jsperf.com/float-to-int-conversion-comparison
Robert Koritnik

2
Beklediğiniz tabanı belirlemek için her zaman 2. değeri parseInt öğesine iletin. Yani, parseInt (floatValue, 10) her zaman taban 10'u elde eder.
Tim Tisdall

3
Bu eski olmasına rağmen, bu soru oldukça sık sorulan bir soru gibi görünüyor, bu yüzden buraya bir uyarı olarak koyacağım. Değer, boyutu nedeniyle "e" gösterimi kullanılarak temsil edilecekse, beklendiği gibi değil, yalnızca bir rakamla sonuçlanır. Örneğin, parseInt(1000000000000000000000, 10);1 değil, 1 000 000 000 000 000 000 000 000 ile sonuçlanır. Her neyse, soru açıkça " bir dizeye dönüştürme ve ayrıştırma " istemiyordu , ancak bu nispeten küçük ...;)
Qantas 94 Heavy

4
@ Qantas94Heavy Bu davranışın nedeni , ilk parametre olarak bir sayı değil bir dizeparseInt() beklemesidir . Bu tamsayı geçtiğinizde, bu dönüştürülür ve daha sonra dize ayrıştırır , sonuçları . 1e21parseInt1e211
Olaf Dietsche

18

1'e bölünmeye eşdeğer olan 0 ile bit kaydırma

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

4
Küçük not: >> 0sadece < 2 ^ 31-1>>> 0 tamsayıları ve < 2 ^ 32-1 tamsayıları için çalışıyor gibi görünüyor . Bu, daha büyük değerler için 0 değerini döndürür
Romuald Brunet

@RomualdBrunet, evet, JavaScript tüm bitsel işlemleri 32 bit sayılarla çalışıyor olarak açıkça tanımlar. Bu özelliklerde.
Alexis Wilke

Bu, Javascript'in yukarıdaki cevapta belirtildiği gibi sadece 32bit (imzalı) tamsayılarla bitsel işlem yaptığı gibi çalışır. Bu yüzden hiçbir şey yapmıyor gibi görünen herhangi bir bit işleminin (değeri 0, VEYA 0 ile, ve 1, çift NOT ile değil) değeri 32bit int'e dönüştürmek için Javascript yorumlayıcıya ihtiyacı vardır.
FrankKrumnow

9

Sizin durumunuzda, sonunda bir virgül kullanmak istediğinizde (virgül eklemek için), sadece Number.toFixed()işlevi kullanabilirsiniz , ancak bu yuvarlama gerçekleştirecektir.


7

Burada birçok öneri var. Bitsel VEYA açık ara en basit gibi görünüyor. Modulo operatörünü kullanarak da negatif sayılarla çalışan başka bir kısa çözüm. Anlamak muhtemelen bitsel VEYA'dan daha kolaydır:

intval = floatval - floatval%1;

Bu yöntem aynı zamanda '| 0' veya '~~' veya '>> 0'ın doğru çalışmadığı yüksek değer sayılarıyla da çalışır:

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

Başka bir cevaba atıfta bulunursanız, lütfen ona bir referans ekleyin veya fikrini kısaca çizin.
bertl

5

To kesmek :

// 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

To turda :

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

5

Olası bir yol daha - XOR işlemini kullanın:

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

Bitsel işlemlerin önceliği matematik işlemlerinin önceliğinden daha azdır, yararlıdır. Https://jsfiddle.net/au51uj3r/ adresinde deneyin


2

MathJavaScript'te yerel nesneye bakarsanız , sayılar ve değerler vb. Üzerinde çalışmak için tüm işlevleri alırsınız ...

Temel olarak JavaScript'te yapmak istediğiniz şey oldukça basit ve yerel ...

Aşağıdaki numaraya sahip olduğunuzu düşünün:

const myValue = 56.4534931;

ve şimdi en yakın sayıya yuvarlamak istiyorsanız, yapmanız yeterli:

const rounded = Math.floor(myValue);

ve elde edersiniz:

56

En yakın sayıya yuvarlamak istiyorsanız, yapmanız gerekenler:

const roundedUp = Math.ceil(myValue);

ve elde edersiniz:

57

Ayrıca Math.round, daha yüksek veya daha düşük sayıya yuvarlamak, hangisinin flot numarasına daha yakın olduğuna bağlıdır.

Ayrıca ~~, bir float'ı tam sayıya dönüştürecek olan float numarasının arkasında da kullanabilirsiniz .

Gibi kullanabilirsiniz ~~myValue...


Dikkatli olun ~~çünkü sayı int 32 sınırından büyükse, değeri int 32 sınır değerine değiştirecektir.
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



Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.