Za pomocą bitowego lub 0, aby uzyskać liczbę

Mój kolega natknął się na metodę floatowania liczb używając bitowego or:

var a = 13.6 | 0; //a == 13
Rozmawialiśmy o tym i zastanawialiśmy się nad kilkoma rzeczami.
    Jak to działa? Nasza teoria była taka, że używając takiego operatora rzuca liczbę do liczby całkowitej, usuwając w ten sposób część ułamkową
  • czy ma jakąś przewagę nad robieniem Math.floor? Może trochę szybciej? (kalambur nieprzeznaczony)
  • Czy ma jakieś wady? Może w niektórych przypadkach to nie działa? Jasność to oczywiste, ponieważ musieliśmy to rozgryźć, I cóż, piszę to pytanie.
Dzięki.
Author: Alex Turpin, 2011-09-20

6 answers

Jak to działa? Nasza teoria głosiła, że użycie takiego operatora powoduje Liczba do liczby całkowitej, usuwając w ten sposób część ułamkową

Wszystkie operacje bitowe z wyjątkiem unsigned right shift, >>>, działają na podpisanych 32-bitowych liczbach całkowitych. Użycie operacji bitowych przekonwertuje zmiennoprzecinkowy na liczbę całkowitą.

Czy to ma jakąś przewagę nad matematyką.podłoga? Może to trochę szybciej? (kalambur nieprzeznaczony)

Http://jsperf.com/or-vs-floor/2 wydaje się nieco szybciej

Czy ma jakieś wady? Może w niektórych przypadkach to nie działa? Klarowność jest oczywista, ponieważ musieliśmy to rozgryźć i dobrze, Piszę to pytanie.
  • nie przejdzie jsLint.
  • tylko liczby całkowite z podpisem 32-bitowym
  • dziwne zachowanie porównawcze: Math.floor(NaN) === NaN, natomiast (NaN | 0) === 0
 115
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-02 03:32:07

To jest obcinanie w przeciwieństwie do podłogi. Odpowiedź Howarda jest w pewnym sensie poprawna, ale dodam, że Math.floor robi dokładnie to, co powinno w odniesieniu do liczb ujemnych. Matematycznie, tym jest Podłoga.

W opisanym powyżej przypadku programista był bardziej zainteresowany okrojeniem lub całkowitym odcięciem dziesiętnym. Chociaż składnia, której używali, zasłania fakt, że konwertują float na int.

 24
Author: Chad La Guardia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-20 15:54:29

W ECMAScript 6 odpowiednikiem |0 jest Matematyka.trunc , rodzaj powinienem powiedzieć:

Zwraca całkę liczby, usuwając dowolne cyfry ułamkowe. Po prostu obcina kropkę i cyfry za nią, bez względu na to, czy argument jest liczbą dodatnią, czy ujemną.

Math.trunc(13.37)   // 13
Math.trunc(42.84)   // 42
Math.trunc(0.123)   //  0
Math.trunc(-0.123)  // -0
Math.trunc("-1.123")// -1
Math.trunc(NaN)     // NaN
Math.trunc("foo")   // NaN
Math.trunc()        // NaN
 13
Author: zangw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-10 13:44:55

Twój pierwszy punkt jest poprawny. Liczba jest rzucana do liczby całkowitej, a zatem wszelkie cyfry dziesiętne są usuwane. Należy pamiętać, że Math.floor zaokrągla do następnej liczby całkowitej w kierunku minus nieskończoności, a tym samym daje inny wynik w przypadku liczb ujemnych.

 10
Author: Howard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-20 15:51:51
  • Specyfikacja mówi, że jest przekonwertowana na liczbę całkowitą:

    Niech lnum będzie ToInt32 (lval).

  • Wydajność: to zostało przetestowane w jsperf wcześniej.

 5
Author: pimvdb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-20 16:54:52

Javascript reprezentuje Number jako 64-bitowe liczby zmiennoprzecinkowe o podwójnej precyzji.

Math.floor działa z tym w umyśle.

Operacje bitowe działają w 32bitach podpisanych liczbach całkowitych. 32-bitowe liczby całkowite używają pierwszego bitu jako znaku ujemnego, a pozostałe 31 bitów to liczba. Z tego powodu liczba min i max dozwolonych 32-bitowych podpisanych numerów to odpowiednio -2,147,483,648 i 2147483647 (0x7FFFFFFFF).

Więc kiedy robisz | 0, jesteś zasadniczo robi to & 0xFFFFFFFF. Oznacza to, że każda liczba reprezentowana jako 0x80000000 (2147483648) lub większa powróci jako liczba ujemna.

Na przykład:

 // Safe
 (2147483647.5918 & 0xFFFFFFFF) ===  2147483647
 (2147483647      & 0xFFFFFFFF) ===  2147483647
 (200.59082098    & 0xFFFFFFFF) ===  200
 (0X7FFFFFFF      & 0xFFFFFFFF) ===  0X7FFFFFFF

 // Unsafe
 (2147483648      & 0xFFFFFFFF) === -2147483648
 (-2147483649     & 0xFFFFFFFF) ===  2147483647
 (0x80000000      & 0xFFFFFFFF) === -2147483648
 (3000000000.5    & 0xFFFFFFFF) === -1294967296

Również. Operacje bitowe nie "podłoga". Oniobcinają , co jest tym samym, co powiedzenie, zaokrąglają się najbliżej 0. Gdy przejdziesz do liczb ujemnych, Math.floor zaokrągla w dół podczas bitowego zaokrąglania w górę.

Jak już mówiłem, Math.floor jest bezpieczniejsze, ponieważ działa z 64-bitowymi liczbami zmiennymi. Bitowe jest szybsze, tak, ale ograniczone do zakresu 32-bitowego.

Do podsumowania:

  • bitowe działa tak samo, jeśli pracujesz z 0 to 2147483647.
  • bitowe jest 1 Liczba wyłączona, jeśli pracujesz z -2147483647 to 0.
  • bitowy jest zupełnie inny dla liczb mniejszych niż -2147483648 i większych niż 2147483647.

Jeśli naprawdę chcesz poprawić wydajność i użyć obu:

function floor(n) {
    if (n >= 0 && n < 0x80000000) {
      return n & 0xFFFFFFFF;
    }
    if (n > -0x80000000 && n < 0) {
      return (n - 1) & 0xFFFFFFFF;
    }
    return Math.floor(n);
}

Wystarczy dodać Math.trunc działa jak operacje bitowe. Więc możesz to zrobić:

function floor(n) {
    if (n > -0x80000000 && n < 0x80000000) {
      return n & 0xFFFFFFFF;
    }
    return Math.trunc(n);
}
 0
Author: ShortFuse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 15:39:03