비트 OR 0을 사용하여 숫자를 플로어링


193

내 동료가 비트 또는

var a = 13.6 | 0; //a == 13

우리는 그것에 대해 이야기하고 몇 가지 궁금합니다.

  • 어떻게 작동합니까? 우리의 이론은 그러한 연산자를 사용하면 숫자를 정수로 변환하여 소수 부분을 제거한다는 것입니다
  • 그것보다 장점이 Math.floor있습니까? 좀 더 빠를까요? (말장난이 아닙니다)
  • 단점이 있습니까? 경우에 따라 작동하지 않을 수 있습니까? 명료 함은 분명한 것입니다. 우리는 그것을 이해해야했기 때문에이 질문을 작성하고 있습니다.

감사.


6
단점 : 2 ^ 31-1까지만 작동하며 약 20 억 (10 ^ 9)입니다. 최대 숫자 값은 약 10 ^ 308btw입니다.
Šime Vidas

12
예 : 3000000000.1 | 0-1294967296으로 평가됩니다. 따라서이 방법은 돈 계산에 적용 할 수 없습니다 (특히 10을 피하기 위해 100을 곱한 경우).
Šime Vidas

13
@ ŠimeVidas 수레는 돈 계산에 사용해서는 안
조지 Reith는에게

20
이되는 바닥재되지 절단 (0을 향해 라운딩).
Bartłomiej Zalewski

3
@sequence 0.1 + 0.2 == 0.3자바 스크립트 콘솔에서 입력 해보십시오 . 언어가 지원하는 경우 10 진수 유형을 사용해야합니다. 그렇지 않으면 대신 센트를 저장하십시오.
Alex Turpin

답변:


161

어떻게 작동합니까? 우리의 이론은 그러한 연산자를 사용하면 숫자를 정수로 변환하여 소수 부분을 제거한다는 것입니다

부호없는 오른쪽 시프트를 제외한 모든 비트 연산 >>>은 부호있는 32 비트 정수에서 작동합니다. 따라서 비트 연산을 사용하면 부동 소수점을 정수로 변환합니다.

Math.floor를 수행하는 것보다 장점이 있습니까? 좀 더 빠를까요? (말장난이 아닙니다)

http://jsperf.com/or-vs-floor/2가 약간 더 빠른 것 같습니다

단점이 있습니까? 경우에 따라 작동하지 않을 수 있습니까? 명료 함은 분명한 것입니다. 우리는 그것을 이해해야했기 때문에이 질문을 작성하고 있습니다.

  • jsLint를 전달하지 않습니다.
  • 32 비트 부호있는 정수만
  • 홀수 비교 동작 : Math.floor(NaN) === NaN,(NaN | 0) === 0

9
@harold는 실제로 라운드가 아니기 때문에 단순히 잘립니다.
Alex Turpin

5
또 다른 가능한 단점은 인 Math.floor(NaN) === NaN동안 (NaN | 0) === 0. 이러한 차이는 일부 응용 프로그램에서 중요 할 수 있습니다.
Ted Hopp

4
jsperf는 루프 불변 코드 모션으로 인해 크롬의 빈 루프에 대한 성능 정보를 제공합니다. 약간 더 나은 성능 테스트는 다음과 같습니다. jsperf.com/floor-performance/2
Sam Giles

4
이것은 asm.js(내가 처음으로 배운 곳 )의 표준 부분입니다 . 다른 이유없이 Math객체에서 함수를 호출하지 않기 때문에 더 빠릅니다 Math.floor = function(...). 언제든지 에서처럼 바꿀 수있는 함수입니다 .
gman

3
(value | 0) === value값이 실제로 정수이고 정수인지 확인하는 데 사용될 수 있습니다 (Elm 소스 코드 @ dwayne-crooks 링크와 같이). 그리고 foo = foo | 0임의의 값을 정수로 강제 변환하는 데 사용할 수 있습니다 (32 비트 숫자는 잘리고 숫자가 아닌 모든 숫자는 0이 됨).
David Michael Gregg

36

이것은 바닥 이 아니라 절단 입니다. 하워드의 대답은 맞습니다. 그러나 Math.floor음수와 관련하여 정확히 수행 해야하는 것을 추가하고 싶습니다 . 수학적으로, 그것은 바닥입니다.

위에서 설명한 경우 프로그래머는 잘라 내기 또는 소수점을 완전히 자르는 데 더 관심이있었습니다 . 비록 그들이 사용한 구문은 float를 int로 변환한다는 사실을 모호하게합니다.


7
이것은 정답이며, 받아 들여지지 않은 것입니다. Math.floor(8589934591.1)예상 결과 를 생성 하는 추가 8589934591.1 | 0 하지 마십시오 .
Salman A

21

ECMAScript를 6에서의 것과 동일 |0하다 Math.trunc 내가 말을해야 종류의 :

소수를 제거하여 숫자의 정수 부분을 반환합니다. 인수가 양수인지 음수인지에 관계없이 점과 그 뒤에있는 숫자를 자릅니다.

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

6
Math.trunc()2 ^ 31 이상의 숫자로 작동 | 0하지만 그렇지 않은 사실을 제외하고
Nolyurn

10

첫 번째 요점이 맞습니다. 숫자는 정수로 캐스트되므로 10 진수가 제거됩니다. 참고, 그 해주십시오 Math.floor음수에 적용 할 때 따라서 마이너스 무한대에 가까워 다음 정수로 라운드와는 다른 결과를 제공합니다.


5

Javascript는 배정도 64 비트 부동 숫자Number 로 나타냅니다 .

Math.floor 이것을 염두에두고 작동합니다.

비트 단위 연산은 부호 있는 32 비트 정수로 작동합니다 . 32 비트 부호있는 정수는 첫 번째 비트를 음의 부호로 사용하고 다른 31 비트는 숫자입니다. 이 때문에 허용되는 32 비트 부호있는 숫자의 최소 및 최대 수는 각각 -2,147,483,648 및 2147483647 (0x7FFFFFFFF)입니다.

따라서 할 때 | 0본질적으로하는 것은 & 0xFFFFFFFF입니다. 즉, 0x80000000 (2147483648) 이상으로 표시되는 숫자는 음수로 반환됩니다.

예를 들면 다음과 같습니다.

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

또한. 비트 단위 연산은 "바닥"이 아닙니다. 그들은 잘라 그들이 가장 가까운 반올림, 말과 동일하다, 0. 당신이 음수 주위에 이동하면, Math.floor아래로 잠시 비트는 반올림 시작 까지 .

앞에서 말했듯 Math.floor이 64 비트 부동 숫자로 작동하기 때문에 더 안전합니다. 비트 단위 는 빠르지 만 32 비트 부호있는 범위로 제한됩니다.

요약:

  • 에서 작업하는 경우 비트 단위는 동일하게 작동합니다 0 to 2147483647.
  • 에서 작업하는 경우 비트 단위는 1 숫자입니다 -2147483647 to 0.
  • 보다 작 -2147483648거나 큰 숫자의 경우 비트 단위가 완전히 다릅니다 2147483647.

당신이 만약 정말로 성능을 조정할 싶어 모두 사용

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

Math.trunc비트 연산과 같은 작품 을 추가하기 만하면됩니다 . 그래서 당신은 이것을 할 수 있습니다 :

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

5
  • 사양에 따르면 정수로 변환됩니다.

    lnum을 ToInt32 (lval)로 설정하십시오.

  • 성능 : 이것은 전에 jsperf 에서 테스트되었습니다 .

참고 : 사양에 대한 연결 끊김 제거

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.