Computer >> 컴퓨터 >  >> 프로그래밍 >> Ruby

Ruby로 배우는 실용 수학: 모듈로 연산자, 진법 변환, 비트마스킹까지

좋은 프로그래머가 되려면 수학을 잘 알아야 할까요?

경우에 따라 다릅니다!

하루 종일 CRUD(생성·조회·수정·삭제) 애플리케이션만 작성한다면 수학 지식은 크게 필요하지 않습니다.

하지만 코딩 테스트 문제를 풀거나 개발자 면접을 준비하는 등 조금 더 흥미로운 작업을 하고 싶다면, 몇 가지 기본 개념을 익혀두는 것이 큰 도움이 됩니다.

이 글에서 배울 내용:

  • 모듈로 연산자(%)
  • 진법(수 체계)
  • 비트마스킹

Ruby에서 이 개념들을 실제로 적용하는 방법까지 다루는 실용적인 가이드입니다.

그럼 시작해 보겠습니다!

Ruby 모듈로 연산자

Ruby의 모듈로 연산자는 다음과 같이 생겼습니다:

%

네, 백분율 기호와 똑같습니다.

이 연산자는 무슨 역할을 할까요?

모듈로 연산자는 나눗셈의 나머지를 구해줍니다. 이를 활용하면 숫자가 짝수인지 홀수인지 확인하는 작업도 가능합니다.

사실 Ruby에는 even?/odd? 메서드가 이미 내장되어 있습니다.

예제:

8.even?
# true

5.even?
# false

하지만 숫자가 3으로 나누어떨어지는지 확인하려면 모듈로 연산자를 사용해야 합니다.

예제:

9 % 3 == 0
# true

더 다양한 활용법을 살펴보겠습니다!

모듈로 연산자의 실용적인 활용법

모듈로 연산자를 사용하면 어떤 숫자가 다른 숫자로 나누어떨어지는지 확인할 수 있습니다.

나머지가 0이면 나누어떨어진다는 뜻입니다.

예제:

유명한 "FizzBuzz" 코딩 문제는 숫자가 3 또는 5로 나누어떨어지는지 판별하도록 요구합니다.

if n % 3 == 0
  puts "Fizz"
end

if n % 5 == 0
  puts "Buzz"
end

모듈로 연산자를 사용하면 N번째마다 특정 작업을 수행할 수도 있습니다.

예를 들면:

(1..10).select { |n| n % 2 == 0 }
# [2, 4, 6, 8, 10]

또는 step 메서드를 사용할 수도 있습니다:

(2..10).step(2).to_a
# [2, 4, 6, 8, 10]

divmod 메서드 활용하기

모듈로 연산자의 또 다른 활용 예로, 분 단위 시간을 '시간 + 남은 분' 형태로 변환하는 것이 있습니다.

예제:

90분은 1시간 30분과 같습니다.

hours, minutes = 90.divmod(60)
# [1, 30]

divmod 메서드에 주목하세요:

이 메서드는 나눗셈과 모듈로(나눗셈의 나머지)를 동시에 처리해 줍니다.

정말 유용합니다!

진법(수 체계) 이해하기

진법이란 숫자를 표현하는 방식을 말합니다.

일상에서 우리는 10진법을 사용합니다.

0123456789

진법은 숫자들, 그리고 경우에 따라 문자들로 구성됩니다.

예를 들어:

16진법은 총 16개의 기호를 사용합니다.

0123456789abcdef

아래는 주요 진법을 정리한 표입니다:

이름 기호 개수 기호
16진법(Hexadecimal) 16 0123456789abcdef
10진법(Decimal) 10 0123456789
8진법(Octal) 8 01234567
2진법(Binary) 2 01

Ruby에서는 to_s 메서드로 진법 간 변환을 할 수 있습니다.

10진수(9)를 2진수(1001)로 변환하는 방법은 다음과 같습니다:

9.to_s(2)
# "1001"

문자열에 to_i 메서드를 사용하면 다시 정수로 변환할 수 있습니다.

따라서 16진수(ff)를 10진수(255)로 바꾸고 싶다면 이렇게 하면 됩니다:

"ff".to_i(16)
# 255

여기서 16은 해당 숫자의 "기호 개수", 즉 밑(base)을 의미합니다.

비트마스킹이란?

아마 여러분은 매일 아침 눈을 뜨며 이런 생각을 하지는 않을 겁니다…

"좋아! 수많은 불리언 값을 최대한 작은 공간에 담아야 해!"

하지만 언젠가 그런 상황이 온다면…

'비트마스킹'이 큰 도움이 되는 훌륭한 기법입니다.

비트마스킹을 사용하면 수많은 불리언 값을 하나의 정수 값에 담을 수 있습니다.

어떻게 가능할까요?

바로 숫자를 이루는 개별 비트를 사용하기 때문입니다.

불리언 값은 1비트로 표현할 수 있고, 정수는 64비트이므로 하나의 숫자에 최대 64개의 불리언 값을 담을 수 있습니다.

여기서는 비트 연산자를 사용합니다.

정리하면 다음과 같습니다:

이름 기호 용도
XOR(배타적 OR) ^ 비트 토글
AND & 비트 확인
NOT ~ 비트 클리어
OR | 비트 설정

비트 연산자는 비트(BIT) 수준에서 동작하며, 이것이 바로 우리가 원하는 것입니다.

코드 예제:

class Bitmask
  def initialize
    @value = 0
  end

  def set(bit)
    @value |= bit
  end

  def clear(bit)
    @value &= ~bit
  end

  def check(bit)
    (@value & bit) == bit
  end

  def to_binary
    @value.to_s(2)
  end
end

bit = Bitmask.new

비트마스킹 사용 방법

이제 set, clear, check 메서드를 사용해 이 자료구조를 다룰 수 있습니다. 각 값이 무엇을 의미하는지 설명하는 상수를 정의해 두면 코드가 더욱 명확해집니다.

예제:

class Bitmask
  ENGINES_ENABLED = 1
  CAPTAIN_ABOARD  = 2
  SHIELDS_UP      = 4

  # ... 나머지 코드
end

bit = Bitmask.new

bit.set(Bitmask::ENGINES_ENABLED)
bit.check(Bitmask::ENGINES_ENABLED)

set에 사용할 수 있는 유효한 값은 1과 2의 거듭제곱(2, 4, 8, 16, 32…)입니다. 이렇게 해야 다른 비트를 덮어쓰지 않습니다.

예를 들어 64 + 32 + 1을 저장하면 값은 다음과 같이 표현됩니다:

1100001

Ruby의 수학 관련 메서드

Ruby에는 유용하게 쓸 수 있는 내장 수학 메서드들이 몇 가지 있습니다.

앞서 divmod, even?, odd?를 이미 살펴봤습니다.

그 외의 메서드들:

  • ** / pow (거듭제곱)
  • gcd (최대공약수)
  • abs (절댓값, 음수 부호 제거)
  • round (가장 가까운 정수로 반올림)
  • floor & ceil (내림 / 올림)
  • Math.sqrt(n) (n의 제곱근)
  • Math.log2(n) (n의 로그 밑 2 값)
  • digits (정수를 뒤집힌 자릿수 배열로 변환)

예제:

5 ** 2
# 25

-10.abs
# 10

300.digits
# [0, 0, 3]

정리

이번 글에서는 나눗셈의 나머지를 구하는 모듈로 연산자 % 같은 흥미로운 수학 트릭을 배웠습니다. 나머지를 활용하면 어떤 숫자가 다른 숫자로 나누어떨어지는지 손쉽게 확인할 수 있습니다.

또한 진법 변환, 비트마스킹, 비트 연산자에 대해서도 함께 알아보았습니다.

이 글이 도움이 되었다면 주변에 널리 공유해 주세요!