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

1. 개요

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

생각없이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. 정말 큰수

조, 경, 해... 1000해 까지가면 조금 이상해진다.

const a = 100000000000000000000000 // 천해
const b = 30

console.log('Math.floor', Math.floor(a/b)) // Math.floor 3.333333333333333e+21
console.log('Math.trunc', Math.trunc(a/b)) // Math.trunc 3.333333333333333e+21
console.log('not not', ~~(a/b)) // not not -435159040

7. 개인적 의견

사실 브라우저에서 나눗셈 연산 1억번 10 번하는 경우 거의 드물고

이러한 연산을 알고리즘 또는, 간단한 연산으로 한정한다면, 1조 이하의 연산으로 한정한다면

빠르고, 음수 나눗셈까지 지원할 수 있는 ~~(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/

좋은 웹페이지 즐겨찾기