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
사용합시다.
그냥 요즘 자바스크립트로 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이 나와야합니다.
Math.floor - 내림
MDN에 따르면 함수는 주어진 숫자와 같거나 작은 정수 중에서 가장 큰 수를 반환합니다.
이기 때문에
Math.floor(-10/3)
은 -4을 반환합니다.
양수일때는 잘 동작합니다.
Math.trunc - 버림
정수 부분만 반환하기 때문에 정수 나눗셈 몫 구하기에 딱 얼룹니다.
Math.floor(-10/3)
은 -3을 반환합니다.
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
1억번 연산을 10번 수행했었는데 크롬에서는 크게 차이가 없었습니다.
파이어폭스에서는 하지 맙시다. 컴퓨터 터지는줄 알았습니다.
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`)
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
정수형 범위 이내라고 판단되면 ~~ 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/