[JS] 정수 나눗셈 - 몫 구하기

skyepodium·2022년 3월 26일
0
post-thumbnail

수정

not not 의 연산 가능한 최대값은 정수형 범위 2147483647 입니다. 넘으면 음수가 됩니다.

// 1. 정수 범위
const n = 2147483647
console.log('res', ~~n) // 2147483647

// 2. 정수 범위 초과
console.log('res', ~~(n+1)) // -2147483648

// 3. 연산결과가 정수형 범위 초가
console.log('res', ~~((n * 2 + 2) / 2)) // -2147483648

프로그래머스 - 콜라츠 추측
문제는 ~~사용하면, 중간에 터집니다. Math.trunc 사용합시다.

1. 개요

그냥 요즘 자바스크립트로 leetcode 풀고 있는데 자바스크립트 제일 낯선 부분 중 하나가 정수 나눗셈.

생각없이Math.floor 썼었는데 음수 나눗셈에서 생각과 다르게 동작합니다.

const a = -10
const b = 3

const res = Math.floor(a / b)
console.log('res', res) // -4

음수 나눗셈 할 일이 거의 없어서 하나씩 살펴보면

-10 = 3 * -3 + (-1)

몫: -3, 나머지: -1

따라서, -3이 나와야합니다.

2. Math.floor

Math.floor - 내림

MDN에 따르면 함수는 주어진 숫자와 같거나 작은 정수 중에서 가장 큰 수를 반환합니다. 이기 때문에

Math.floor(-10/3) 은 -4을 반환합니다.

양수일때는 잘 동작합니다.

3. Math.trunc

Math.trunc - 버림

정수 부분만 반환하기 때문에 정수 나눗셈 몫 구하기에 딱 얼룹니다.

Math.floor(-10/3) 은 -3을 반환합니다.

4. ~~ (not not)

bitwise not 연산자 2개를 사용하는 방법입니다.

MDN 에 따르면 bitwise not을 사용하면 x는 -(x+1)을 반환하고, 소수점을 모두 버립니다.

그래서 2번 중첩해서 사용하면 소수점을 버린 상태가 됩니다.

// 3.5 -> -4 -> 3
const a = 3.5

console.log(~a) // -4

console.log(~~a) // 3

5. 속도 비교

1억번 연산을 10번 수행했었는데 크롬에서는 크게 차이가 없었습니다.

1) 크롬

  • Math.trunc - 51.58 ms
  • not not - 51.4 ms

2) safari

  • Math.trunc - 1345.6 ms
  • not not - 1341.5 ms

파이어폭스에서는 하지 맙시다. 컴퓨터 터지는줄 알았습니다.

const a = 10000000000 // 100억
const b = 777777777 //  7억
const n = 100000000 // 1억
const testCase = 10
let timeSum = 0

for(let t=0; t<testCase; t++) {
    const startTime = performance.now()

    for(let i=0; i<n; i++) {
        const res = Math.trunc(a/b)
        // const res = ~~(a/b)
    }

    const endTime = performance.now()

    timeSum += endTime - startTime
}

console.log(`평균 속도: ${timeSum / testCase} ms`)

6. 최대 범위

not not의 최대범위는 2147483647입니다.

// 1. 정수 범위
const n = 2147483647
console.log('res', ~~n) // 2147483647

// 2. 정수 범위 초과
console.log('res', ~~(n+1)) // -2147483648

// 3. 연산결과가 정수형 범위 초가
console.log('res', ~~((n * 2 + 2) / 2)) // -2147483648

7. 개인적 의견

정수형 범위 이내라고 판단되면 ~~ not not 사용해도 괜찮지만, 안전하게 Math.trunc 사용합니다.

참고

https://codepen.io/supernova_at/post/javascript-s-double-bitwise-not-operator
https://www.delftstack.com/ko/howto/javascript/integer-division-javascript/

profile
callmeskye

0개의 댓글