Jak przekonwertować liczbę zmiennoprzecinkową na liczbę całkowitą w JavaScript?


1108

Chciałbym przekonwertować liczbę zmiennoprzecinkową na liczbę całkowitą w JavaScript. Właściwie chciałbym wiedzieć, jak ZROBIĆ standardowe konwersje: przez obcinanie i zaokrąglanie. I skutecznie, nie poprzez konwersję na ciąg i parsowanie.


83
Jeśli nie wiesz, wszystkie liczby w javascript są zmiennoprzecinkowe. Ze specyfikacji:
jakieś

6
4.3.20 Typ liczby: Liczba typu jest zbiorem wartości reprezentujących liczby. W ECMAScript zestaw wartości reprezentuje podwójnie precyzyjne wartości 64-bitowego formatu IEEE 754, w tym specjalne wartości „Brak liczby” (NaN), dodatnią nieskończoność i ujemną nieskończoność.
jakieś

9
Tak, JavaScript nie ma wyraźnego typu „liczba całkowita”, ale nadal nie jest rzadkie, aby wykonać tę konwersję. Na przykład w mojej aplikacji użytkownicy wpisywali numer (ewentualnie łącznie z centami). Musiałem obciąć centy i wyświetlać w / przecinki. Krok 1 polegał na konwersji na int.
mcherm

1
przydatne również: porównanie prędkości wszystkich metod jsperf.com/math-floor-vs-math-round-vs-parseint/33
c ..

1
@karl: Jeśli akceptuję dane wejściowe w polu, mogę być w stanie kontrolować, jakie znaki akceptuję, ale mogę wykonywać wszelkiego rodzaju przetwarzanie w Javascript, nie tylko akceptując dane wprowadzane przez użytkownika. Nawet wtedy mógłbym chcieć tego dla takich rzeczy jak obsługa wklejania.
mcherm

Odpowiedzi:


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

Odwołanie do obiektu matematycznego


Przykłady

Pozytywny
// 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
Negatywny
// 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
Pozytywne - większe liczby
// 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
Ujemne - Większe liczby
// 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
Jak wspomniano w innej odpowiedzi, obcinanie ujemne dla bezpieczeństwa można wykonać za pomocą var intValue = ~~floatValue;. Jeżeli zapis jest zbyt zaciemniać do własnych upodobań, po prostu schować go w funkcji: function toInt(value) { return ~~value; }. (To również zamienia ciągi znaków na liczby całkowite, jeśli masz na to
ochotę

4
Głosowałby, gdyby ta odpowiedź miała przykładowe wejście / wyjście.
J. Random Coder

7
W odniesieniu do komentarza ~~ ogranicza wartość do 32-bitowych liczb całkowitych ze znakiem, podczas gdy Math.floor / ceil / round może obsłużyć do 53-bitów (Number.MAX_SAFE_INTEGER 9007199254740991). Wspomniano o tym w odpowiedzi poniżej, ale warto powtórzyć tutaj dla osób czytających te komentarze.
John

2
Czytaj od dołu w kilku miejscach: Math.trunc(val);Skomentuj, ponieważ jest to zaakceptowana odpowiedź
Old Badman Gray,

Nie działa z dokładną dokładnością dla wartości takich jak2.3 - 2.3 % 1
Lapys,

301

Bitowy operator OR

Do obcinania liczb zmiennoprzecinkowych można użyć operatora bitowego lub operatora. Działa to zarówno z dodatnimi, jak i ujemnymi wartościami:

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

Wyniki

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

Porównanie wydajności?

Stworzyłem test JSPerf, który porównuje wydajność między:

  • Math.floor(val)
  • val | 0 bitowe LUB
  • ~~val bitowe NIE
  • parseInt(val)

która działa tylko z liczbami dodatnimi. W takim przypadku możesz bezpiecznie używać operacji bitowych i Math.floorfunkcji.

Ale jeśli potrzebujesz kodu do pracy zarówno z dodatnimi, jak i ujemnymi , wtedy operacja bitowa jest najszybsza (LUB jest preferowana). Ten drugi test JSPerf porównuje to samo, gdzie jest całkiem oczywiste, że ze względu na dodatkowe sprawdzanie znaków Math jest teraz najwolniejszy z czterech.

Uwaga

Jak stwierdzono w komentarzach, operatorzy BITWISE działają na podpisanych 32-bitowych liczbach całkowitych, dlatego duże liczby zostaną przekonwertowane, na przykład:

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

@FabioPoloni: tak, super proste i wydaje się, że operatorzy bitowi są najszybsi. Zwłaszcza operator OR jest zawsze najszybciej dopasowywany przez operacje NOT i operacje matematyczne, chociaż operacje matematyczne są najwolniejsze, gdy trzeba również obsługiwać liczby ujemne, ponieważ dodaje to dodatkowe sprawdzenie znaku liczby.
Robert Koritnik

9
@thefourtheye: Wszystkie operacje bitowe oprócz prawego przesunięcia bez znaku, działają na 32-bitowych liczbach całkowitych ze znakiem. Dlatego użycie operacji bitowych na liczbach zmiennoprzecinkowych przekształci je na liczbę całkowitą usuwającą cyfry po przecinku.
Robert Koritnik

3
Jeśli potrzebujesz go tylko do liczb dodatnich, Math.floor()jest szybszy (przynajmniej według mojego pierwszego testu JSPerf w Google Chrome, wersja 30.0.1599.101), bardziej niezawodny (ponieważ nie zależy od tego, jak liczby są reprezentowane w bitach, co może zmienić i być może złamać to bitowe rozwiązanie), a co najważniejsze, bardziej jednoznacznie.
ma11hew28,

8
Zauważ, że operatory bitowe działają na liczbach 32-bitowych. Nie będą działać dla liczb zbyt dużych, aby zmieściły się w 32 bitach.
Kat

2
~~jest lepszy, ponieważ jest to jednoargumentowy operator. 4.2|0+4równa się, 4ale ~~4.2+4równa8
Janus Troelsen,

94

Uwaga: Nie możesz użyć Math.floor()jako zamiennika obcięcia, ponieważ Math.floor(-3.1) = -4i nie -3!!

Prawidłowym zamiennikiem obcięcia byłoby:

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

    return Math.floor(value);
}

1
To zależy od pożądanego zachowania liczb ujemnych. Niektóre zastosowania wymagają liczb ujemnych, aby zamapować na bardziej ujemne wartości (-3,5 -> -4), a niektóre wymagają mapowania na mniejszą liczbę całkowitą (-3,5 -> -3). Ten pierwszy jest zwykle nazywany „podłogą”. Słowo „obcięcie” jest często używane do opisania każdego z tych zachowań. W moim przypadku zamierzałem podać tylko liczby ujemne. Ale ten komentarz jest użytecznym ostrzeżeniem dla tych, którzy NIE dbają o zachowanie liczb ujemnych.
mcherm

28
@mcherm: Wydaje się, że nie rozumieją poprawnie terminu „obcinaj”. Obcięcie działa dokładnie tak, jak sugeruje jego nazwa: obcina cyfry. Nigdy nie jest (w sensie ogólnym) równoważny podłodze lub sufitowi. en.wikipedia.org/wiki/Truncation
Thanatos

5
Math.trunc(value)dodano w ECMAScript 6
4esn0k

2
floorzaokrągla w kierunku-nieskończoności, truncatezaokrągla w kierunku zera. ( ceilzaokrągla w kierunku + nieskończoność).
Peter Cordes

46

Do obcinania liczb zmiennoprzecinkowych można zastosować podwójny bitowy operator nie będący operatorem. Inne operacje, które wymieniłeś są dostępne Math.floor, Math.ceili Math.round.

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

Więcej szczegółów dzięki uprzejmości Jamesa Padolseya.


1
Jest to prawdopodobnie zła rzecz do zrobienia dla kodu produkcyjnego (ponieważ jest niejasny), ale dokładnie tego potrzebowałem do gry w golfa w moim <canvas>silniku renderującym czcionki w JS . Dziękuję Ci!
Kragen Javier Sitaker

10
Można to również osiągnąć za pomocą n | 0.
Jay Douglass,

17
Zauważ, że każda metoda (~~ n lub n | 0) działa tylko na liczbach do 2 ^ 31-1 lub 2147483647. 2147483648 lub wyższa zwróci niepoprawny wynik; na przykład 2147483647 | 0 zwraca -2147483648, a 4294967295 | 0 zwraca -1, co prawie na pewno nie jest tym, czego chcesz.
Ed Bayiates

40

Do obcinania:

var intvalue = Math.floor(value);

Dla rundy:

var intvalue = Math.round(value);

6
Math.floor nie obcina wartości ujemnych. Zobacz odpowiedź powyżej. W przeciwnym razie fajna odpowiedź.
oligofren

Jeśli interesuje Cię wydajność, umieściłem tutaj mały przypadek testowy: jsperf.com/dsafdgdfsaf/2 (tutaj wygrywa var | 0).
Cybolic

25

Możesz użyć metody parseInt bez zaokrąglania. Uważaj na dane wprowadzane przez użytkownika ze względu na opcje prefiksu 0x (hex) i 0 (octal).

var intValue = parseInt(floatValue, 10);

1
Jest to naprawdę pomocne, gdy chcesz tylko całkowitą część dziesiętną, bez zaokrąglania w górę lub w dół, co robią .round, .ceil i .floor.
Judah Gabriel Himango,

1
... nawet po zwykłym obcięciu wydaje się to najwolniejszą metodą. jsperf.com/float-to-int-conversion-comparison
Robert Koritnik

2
Zawsze przekazuj drugą wartość do parsowania, aby określić, jakiej podstawy się spodziewasz. Zatem parseInt (floatValue, 10), aby zawsze uzyskać bazę 10.
Tim Tisdall

3
Chociaż jest to stare, wydaje się, że pytanie to jest dość często zadawane, dlatego umieszczę to tutaj jako ostrzeżenie. Jeśli wartość byłaby reprezentowana za pomocą notacji „e” ze względu na jej rozmiar, spowoduje to tylko jedną cyfrę, a nie to, co jest oczekiwane. Na przykład, parseInt(1000000000000000000000, 10);wynikiem jest 1, a nie 1 000 000 000 000 000 000 000. W każdym razie pytanie wyraźnie nie chciało „ konwertowania na ciąg i parsowanie ”, choć jest to stosunkowo niewielkie ...;)
Qantas 94 Heavy

4
@ Qantas94Heavy Przyczyną tego zachowania jest to, że parseInt()oczekuje, że łańcuch nie będzie liczbą jako pierwszym parametrem. Gdy przekażesz tę liczbę całkowitą, jest ona konwertowana na, 1e21a następnie parseIntanalizuje ciąg 1e21, co skutkuje 1.
Olaf Dietsche

18

Przesunięcie bitu o 0, co odpowiada podziałowi przez 1

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

4
Mała uwaga: >> 0wydaje się działać tylko dla liczb całkowitych < 2 ^ 31-1 i >>> 0dla liczb całkowitych < 2 ^ 32-1 . Zwraca 0 dla większych wartości
Romuald Brunet

@RomualdBrunet, tak, JavaScript jasno definiuje wszystkie operacje bitowe jako operacje na liczbach 32-bitowych. To jest w specyfikacji.
Alexis Wilke

Działa to, ponieważ JavaScript wykonuje operacje bitowe tylko z 32-bitowymi (podpisanymi) liczbami całkowitymi, jak podano w odpowiedzi powyżej. Tak więc każda operacja bitowa, która wydaje się nic nie robić (jak przesunięcie na 0, LUB z 0, AND z 1, podwójne NIE) nadal wymaga interpretera JavaScript do konwersji wartości na 32-bitową liczbę całkowitą.
FrankKrumnow

9

W twoim przypadku, jeśli chcesz na końcu napis (w celu wstawienia przecinków), możesz również po prostu użyć Number.toFixed()funkcji, jednak spowoduje to zaokrąglenie.


7

Tutaj jest wiele sugestii. Bitowa OR wydaje się zdecydowanie najprostsza. Oto kolejne krótkie rozwiązanie, które działa również z liczbami ujemnymi przy użyciu operatora modulo. Prawdopodobnie jest to łatwiejsze do zrozumienia niż bitowe LUB:

intval = floatval - floatval%1;

Ta metoda działa również z liczbami o wysokiej wartości, w których ani „| 0”, ani „~~”, ani „>> 0” nie działają poprawnie:

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

Jeśli odwołujesz się do innej odpowiedzi, dodaj do niej odniesienie lub krótko naszkicuj jego pomysł.
bertl

5

Aby obciąć :

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

Aby zaokrąglić :

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

5

Jeszcze jeden możliwy sposób - użyj operacji 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

Priorytet operacji bitowych jest mniejszy niż priorytet operacji matematycznych, jest to przydatne. Spróbuj na https://jsfiddle.net/au51uj3r/


2

Jeśli spojrzysz na natywny Mathobiekt w JavaScript, dostaniesz całą masę funkcji do pracy na liczbach i wartościach itp.

Zasadniczo to, co chcesz zrobić, jest dość proste i natywne w JavaScript ...

Wyobraź sobie, że masz numer poniżej:

const myValue = 56.4534931;

a teraz, jeśli chcesz zaokrąglić w dół do najbliższej liczby, po prostu wykonaj:

const rounded = Math.floor(myValue);

i dostajesz:

56

Jeśli chcesz zaokrąglić w górę do najbliższej liczby, po prostu wykonaj:

const roundedUp = Math.ceil(myValue);

i dostajesz:

57

Po Math.roundprostu zaokrąglij go do wyższej lub niższej liczby, zależnie od tego, która z nich jest bliżej liczby flot.

Możesz także użyć liczby ~~spoza liczby zmiennoprzecinkowej, która zamieni liczbę zmiennoprzecinkową na liczbę całkowitą.

Możesz używać go jak ~~myValue...


Zachowaj ostrożność, ~~ponieważ jeśli liczba jest większa niż limit int 32, zmieni wartość na wartość graniczną 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

Chcę tylko zaznaczyć, że pieniężnie chcesz zaokrąglać, a nie obcinać. Posiadanie grosza jest znacznie mniej prawdopodobne, ponieważ 4.999452 * 100 zaokrąglone da 5, bardziej reprezentatywną odpowiedź.

Co więcej, nie zapominaj o zaokrąglaniu przez bankiera , który jest sposobem na przeciwdziałanie lekko pozytywnemu nastawieniu, jakie daje proste zaokrąglanie - Twoja aplikacja finansowa może tego wymagać.

Zaokrąglanie Gaussa / bankiera w JavaScript


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.