❓ 문제: 점의 위치 구하기
머쓱이는 구슬을 친구들에게 나누어주려고 합니다. 구슬은 모두 다르게 생겼습니다.
머쓱이가 갖고 있는 구슬의 개수 balls와 친구들에게 나누어 줄 구슬 개수 share이 매개변수로 주어질 때,
balls개의 구슬 중 share개의 구슬을 고르는 가능한 모든 경우의 수를 return 하는 solution 함수를 완성해주세요.
📝 문제 풀이
재귀로 푸는 문제였지만 아직 재귀에 익숙하지 않아
부끄럽지만 힌트에 나온 공식을 그대로 적용해서 풀었다.
function solution(balls, share) {
let x = 1;
let y = 1;
let z = 1;
for (let i = 1; i <= balls; i++) x *= i;
for (let i = 1; i <= (balls - share); i++) y *= i;
for (let i = 1; i <= share; i++) z *= i;
return x / (y * z);
}
...정말 아름답지 않은 코드....많이 부끄럽다.....
그런데 테스트 케이스는 모두 통과하는데 채점이 80점을 넘기지 못했다.
계속 붙잡고 이런저런 시도를 하다가 정말 모르겠어서 질문하기를 보니
Math.round 를 해줘야한다는 얘기를 보고 리턴값에 추가하니 바로 통과됐다.
통과해서 기분은 좋았지만 정확하게 파악하고 넘어가고자 한다.
function solution(balls, share) {
let x = 1;
let y = 1;
let z = 1;
for (let i = 1; i <= balls; i++) x *= i;
for (let i = 1; i <= (balls - share); i++) y *= i;
for (let i = 1; i <= share; i++) z *= i;
// 기존 코드에 Math.round()만 추가
return Math.round(x / (y * z));
}
🔍 더 파고들기 - 소수점 오류
우선 문제의 '다른 사람의 풀이'의 댓글에 적혀있는 사이트를 살펴봤다.
정리를 잘 해놓으셔서 이해하기 좋았다.
더 자세히 알아보니,
자바스크립트에서는 소수점 오류가 생기는 이유는
실수를 이진수로 변환(부동소수점)해서 연산하기 때문이다.
10진법으로 계산하는 우리와 다르게 컴퓨터는 2진법으로 연산하는데,
2진수로 정확하게 표현할 수 없는 일부 10진수 값들은 정확한 값이 아닌 근사값으로 저장돼
반올림 오차가 생기기 때문이다.
예를 들어, 우리가 생각하기에 0.1 * 10 은 1이지만
부동소수점 형식, 즉, 2진수로 0.1을 정확히 나타낼 수 없기 때문에 생기는 반올림 오차로
1에 도달하지 못하고 0.9999999999999999와 같은 값이 나올 수 있다.
(물론 컴퓨터의 메모리 한계로 소수점 아래가 자릿수가 무한대로 생기진 않고 유한소수로 저장한다)
이렇듯 연산을 위한 10진수 → 2진수 변환 과정에서 정수가 소수가 되어 버리면서
우리가 예상하지 못한 오차가 생기는 경우가 생기는 게 바로 소수점 게산 오류 현상이다.
그렇다면 이런 오류를 방지하기 위해서는 어떻게 해야할까?
크게 3가지 방법이 있다.
1. 자바스크립트 메소드 사용
toFixed()
소수점 이하의 자릿수를 지정해서 결과값을 문자열로 반환한다.
var numObj = 12345.6789;
numObj.toFixed(); // Returns '12346': 별도 값을 주지 않으면 0을 사용한다.
numObj.toFixed(1); // Returns '12345.7': 소수점 이하 한자리만 남기고 반올림한다.
numObj.toFixed(6); // Returns '12345.678900': 빈 공간을 0으로 채운다.
Math.round()
입력값을 반올림한 수와 가장 가까운 정수 값을 반환한다.
Math.round( 20.49); // 20
Math.round( 20.5 ); // 21
Math.round( 42 ); // 42
Math.round(-20.5 ); // -20
Math.round(-20.51); // -21
2. 가급적 정수형 사용
계산할 때부터 정수형을 사용하는 방법도 가능하다.
// 소수점 아래 길이에 맞춰 정수로 변환
let num1 = 0.1;
let num2 = 0.2;
let result = (num1 * 10 + num2 * 10) / 10;
console.log(result); // 0.3
3. 기타 라이브러리 사용
▶ decimal.js
JavaScript에서 소수점 연산을 위한 라이브러리로 toFixed()와 같은 내장 함수에서 발생하는 소수점 오류를 방지할 수 있다.
대규모 숫자의 연산도 지원하고, 자바스크립트의 Number 타입으로 표현할 수 없는 숫자도 정확하게 처리할 수 있다.
▶ big.js
자바스크립트의 기본적인 숫자 연산 방식을 개선하여 소수점 오류를 해결할 수 있는 라이브러리.
숫자를 문자열 형태로 다루기 때문에, 오차 없는 숫자 계산이 가능합니다.
둘 다 많이 사용되는 라이브러리이며, 깃헙 자료 보시고
프로젝트에 따라 적절한 라이브러리를 선택하시면 될 듯 하다.
현재 21,700위........ 쭉 가보자
모두 즐코하세요-!
'코딩 생활' 카테고리의 다른 글
[깃을 마스터해보쟈] 2. 깃 설치하기 (mac) (0) | 2023.04.10 |
---|---|
[깃을 마스터해보쟈] 1. 깃이란? (0) | 2023.04.10 |
[xcode 오류] xcode-select: error: tool 'opendiff' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance (0) | 2023.04.08 |
터미널에서 code 명령어로 VS code 열기 (mac) (0) | 2023.04.07 |
터미널에 파일, 폴더명에 공백이 있을 경우 (0) | 2023.04.07 |
댓글