3 minute read

Math.rando( )

(JS) Math.random 으로 범위 정하기

일반적으로 난수를 발생시켜야 하는 경우 Math.random() 함수를

사용하여 구현을 하는 경우가 많다.


Math.random은 0 ~ 1 사이의 난수를 무작위로 생성을 한다.

오늘 다룰 주제는 무작위로 생성된 난수의 범위를 지정해 주는 것이다.

흔히 최솟값과 최댓값을 지정해서 그 사이를 범위로 갖게 만든다.


범위를 정하는 방법의 순서이다.

1️⃣ Math.random의 최댓값을 지정한다.

2️⃣ Math.random의 최솟값을 지정한다.

3️⃣ 최솟값 지정 시의 문제점을 해소한다.

순서로 작성을 해놓았지만 최댓값과 최솟값은 동시에 지정되어야 범위가 정해진다.


✔️Math.random의 최댓값을 지정한다.

Math.random이 발생시킨 0 ~ 1 사이의 수에서 최댓값을 지정해 주려면 Math.random에 *(곱하기) 최댓값을 해주면 된다.

Math.random() * 최대값

최대값을 10으로 정하고 싶다면 Math.random( ) * 10이며

발생되는 난수이 범위는 0 ~ 10 사이가 된다.

여기서 최대값을 10이라고 하였지만 10은 포함되지 않는다.

정확히는 0 초과 10미만이 범위로 지정되는 것이다.


✔️Math.random의 최소값을 지정한다.

최소값을 지정할 경우에는 약간의 머리를 써야 한다. 예시를 들어서 생각해 보자.

늘 상 기준은 0 ~ 1이다. 범위가 1 ~ 10 사이인 경우를 생각해 보자.

Math.random() + 1 을 해주면 1 ~ 2 사이가 된다.

여기에 우리는 최대값을 10으로 해주고 싶다.

그렇다면 + 1을 먼저 해주어서는 방법이 없다.


✔️최소값 지정시의 문제점을 해소한다.

최대값 부터 먼저 정해주고 최소값을 정해 보자.


💡 질문) 1~10 범위를 난수를 발생시켜보자!

예제) 1️⃣

Math.random() * 10 ==> 0 ~ 10

(Math.random() * 10) + 1 ==> 1 ~ 11 ( 11에서 1을 빼주어야 한다.)

(Math.random() * (10 - 1)) + 1 ==> 최대값이 10이어야 하는데 11이되어서 1을 빼주었다.


예제) 2️⃣

Math.random() * 9를 해서 0 ~ 9 사이로 만들어주고

(Math.random() * 9) + 1을 해서 1 ~ 10 사이로 범위가 정해지게 되었다.

(Math.random() * (최대값 - 최소값)) + 최소값

더해주거나 곱해주는 경우 최대값과 최소값에 동시에 적용되기 때문에

원하는 범위를 지정하기 위해 최대값과 최소값을

동시에 지정해서 계산해야 하는 이유를 위의 사례를 통해 알 수 있다.

여기까지 해서  1 ~ 10 사이의 난수를 발생시켰다.




Math.round()

함수는 입력값을 반올림한 수와 가장 가까운 정수 값을 반환 한다.

✔️ 파라미터로 입력받은 숫자의 소수점 이하의 값이 0.5보다 크면,

입력받은 수보다 다음으로 높은 절대값을 가지는 정수를 리턴한다.

✔️소수점 이하의 값이 0.5보다 작으면, 입력받은 수보다

절대값이 더 낮은 정수를 리턴한다.

✔️소수점 이하의 값이 0.5와 같으면, 입력받은 수보다 큰 다음 정수를 리턴한다.

**정수 반올림 (음수 포함)**

// 1.반올림
const round_1 = Math.round(1); // 1
const round_2 = Math.round(1.222); // 1
const round_3 = Math.round(1.5); // 2
const round_4 = Math.round(1.777); // 2

// 2. null 또는 0인 경우
const round_5 = Math.round(null); // 0
const round_6 = Math.round(0); // 0

// 3. 음수인 경우
const round_7 = Math.round(-1); // -1
const round_8 = Math.round(-1.111); // -1
const round_9 = Math.round(-1.5); // -1
const round_10 = Math.round(-1.777); // -2


**자릿수 지정 (소수점 이하, 10단위, 100단위)**

// 1.소수점이하
const round_1 = Math.round(1.222 * 10) / 10; // 1.2
const round_2 = Math.round(1.5 * 10) / 10; // 1.5
const round_3 = Math.round(1.777 * 10) / 10; // 1.8
// 2. 10단위
const round_4 = Math.round(1001 / 10) * 10; // 1000
const round_5 = Math.round(1005 / 10) * 10; // 1010
const round_6 = Math.round(1007 / 10) * 10; // 1010


**소수점 숫자 정밀도 문제**

// 부동소수점 오차 확인 (1.005 반올림)
const n1 = 1.005 * 100; // 100.49999999999999
const round_1 = Math.round(1.005 * 100) / 100;

// 부동소수점 오차 보정 (1.005 반올림)
const n2 = (1.005 + Number.EPSILON) * 100; // 100.50000000000001
const round_2 = Math.round((1.005 + Number.EPSILON) * 100) / 100;

부동 소수점 오차 확인 (1.005 반올림)

const n1 = 1.005 * 100;

1.005 * 100은 100.5 이다.

하지만, 실제 결과는 ‘100.49999999999999’로,

Javascript에서 실수를 처리하는 방식 때문에 약간의 오차가 발생하게 된다.

const round_1 = Math.round(1.005 * 100) / 100;

따라서 위 코드에서 우리는 ‘1.01’이 나올 것을 기대하지만,

위와 같은 이유로 아래의 결과는 ‘1’이다.

부동 소수점 오차 보정 (1.005 반올림)

const n2 = (1.005 + Number.EPSILON)  100;*

const round_2 = Math.round((1.005 * Number.EPSILON) * 100) / 100;

위와 같은 부동 소수점 오차를 해결하기 위해 여기서는 

 Number.EPSILON  이라는 상수를 사용하였다.

이 값은 Javascript에서 오차없이 나타낼수 있는 가장 작은 양의 수이다.


따라서 위 예제에서는 이러한 부동 소수점 오차를 보정하기 위해

Number.EPSILON 값을 더해 준 뒤, 그 값으로 반올림을 처리하였다.

물론, ‘(1.005 * Number.EPSILON) * 100’ 값은 우리가 기대하는 것처럼 정확하게 100.5가 아니다.

하지만, 적어도 이렇게 처리를 하면, 오차가 많이 줄어들게 될 것 같다.




Math.ceil( )

Math.ceil() 함수는 Math 객체 내 ceil 함수는 전달받는 숫자를 반올림한다.

예제

Math.ceil(**10.95**);  *// 11*
Math.ceil(**11.01**);  *// 12*
Math.ceil(**11**);     *// 11*
Math.ceil(-**10.95**); *// -10*
Math.ceil(-**11.01**); *// -11*




Math.floor( )

Math.random 외에 알아두어야 할 것이 Math.floor()다.

Math.floor()는 발생된 난수의 소수점을 없애고 정수를 추출하는 데 사용된다.

**Math.floor() 사용하여 소수점을 삭제해 보자.**

3.14534235234

난수를 발생시켜 리턴 값을 정수로만 하고 싶은 경우 Math.floor() 함수를 사용한다.

floor 함수는 주어진 숫자와 같거나 더 작은 정수 중에서 가장 큰 값을 반영한다. 

그렇기 때문에 Math.floor(3.14534235234) = 3을 추출한다.

양의 정수에서는 신경 쓸게 없으나 음수는 주의를 조금 해야 한다.


Math.floor(-3.14534235234) = -4이다.

왜냐하면 floor의 정의가 같거나 더 작은 정수 중에서 가장 큰 값이기 때문이다.

Math.floor((Math.random() * (최대값 - 최소값)) + 최소값)


💡 결론적으로 우리는 위와 같은 식을 통해

최소 최대값의 범위안에서 정수 형태의 난수를 생성시킬 수 있다.

Leave a comment