2진수, 8진수, 16진수(hex라고도 해요)는 밑이 서로 다른 진법이에요. 2진수는 밑이 2이고, 8진수는 밑이 8, 16진수는 밑이 16이에요. Crystal에서 일반적인 정수는 밑이 10이에요. 2진수, 8진수, 16진수는 모두 정수를 나타내는 표현 방식이에요. 즉, 분수나 소수 없이 양수와 음수(0 포함)를 표현하고, 정수로 할 수 있는 모든 연산을 지원해요.
2진수는 숫자 0과 1만 사용하는 밑이 2인 진법이에요. 컴퓨터의 트랜지스터와 스위치를 흐르는 전류의 0("꺼짐")과 1("켜짐") 상태, 그리고 자기 저장 매체의 양전하와 음전하를 흔히 나타내요. 2진수는 밑이 10인 체계에서 사용하는 모든 정수를 표현할 수 있어요.
밑이 2인 체계의 일부를 보면 다음과 같아요. 다만 이 체계는 128에서 멈추지 않고 무한히 이어져요:
| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
|---|---|---|---|---|---|---|---|
| 2 ** 7 | 2 ** 6 | 2 ** 5 | 2 ** 4 | 2 ** 3 | 2 ** 2 | 2 ** 1 | 2 ** 0 |
그래서 숫자 6을 표현하려면 2진수로는 110이 돼요:
| Place value | 4 | 2 | 1 |
|---|---|---|---|
| Binary number | 1 | 1 | 0 |
계산은 이렇게 해요: 4 + 2 + 0 = 6
또 다른 예로 19를 보면 다음과 같아요:
| Place value | 16 | 8 | 4 | 2 | 1 |
|---|---|---|---|---|---|
| Binary number | 1 | 0 | 0 | 1 | 1 |
2진수로는 10011이에요.
계산은 이렇게 해요: 16 + 0 + 0 + 2 + 1 = 19
Crystal에서는 0b 접두사를 사용해 2진수 리터럴을 표현할 수 있어요.
0b10011이라고 쓰면 Crystal은 이를 2진수로 해석해 밑이 10인 수로 변환해요.
0b10011
# => 19
typeof(0b10011)
# => Int32
0b 접두사를 붙인 수에 2진법에 없는 숫자가 있으면 컴파일 오류가 발생해요.
0b10211
# => Error: unexpected token: "211"
2진수는 정수이므로, 정수로 할 수 있는 모든 연산을 2진수에도 할 수 있어요.
0b10011 + 0b10011
# => 38
0b10011 * 0b10011
# => 361
0b10011 / 3
# => 6.333333333333333
Crystal은 2진수 리터럴을 자동으로 Int32로 변환해요.
Int32를 2진수 표현으로 변환하려면 <int>.to_s(base) 메서드에 base 인자를 2로 지정해서 사용해요.
이 메서드는 2진수를 문자열로 표현한 값을 반환해요:
19.to_s(2)
# => "10011"
2진수를 나타내는 문자열을 정수로 변환하려면 <int>.to_i(base) 메서드에 밑(2)을 인자로 넘겨서 사용할 수 있어요:
"10011".to_i(2)
# => 19
밑을 잘못 지정하거나 (유효하지 않은 2진수 표현을 지정하면) ArgumentError가 발생해요:
"011021".to_i(2)
# => Invalid Int32: "011021" (ArgumentError)
정수에 사용해서 그 수의 2진수 표현에 대한 정보를 얻을 수 있는 메서드들이 있어요.
<int>.bit_length는 수를 표현하는 데 필요한 비트 수를 반환해요:
19.bit_length
# => 5
<int>.bit(index)는 오른쪽(최하위 비트)부터 세어 주어진 인덱스에 있는 비트를 반환해요:
19.bit(0)
# => 1
0b10011.bit(1)
# => 1
8진수는 밑이 8인 진법이에요. 숫자 0, 1, 2, 3, 4, 5, 6, 7을 사용해요.
Crystal에서는 0o 접두사를 사용해 8진수를 표현할 수 있어요.
2진수와 마찬가지로, Crystal은 8진수 표현을 자동으로 Int32로 변환해요.
0o123
# => 83
8진법에 없는 숫자에 0o를 붙이면 컴파일 오류가 발생해요.
2진수와 마찬가지로, <int>.to_s(base) 메서드를 사용해 Int32를 8진수 표현으로 변환할 수 있어요.
그리고 <int>.to_i(base) 메서드를 사용해 8진수 표현을 Int32로 변환할 수 있어요.
83.to_s(8)
# => "123"
"123".to_i(8)
# => 83
2진수와 마찬가지로, 밑을 잘못 지정하면 ArgumentError가 발생해요.
16진수는 밑이 16인 진법이에요. 숫자 0 - 9와 문자 A, B, C, D, E, F를 사용해요. A는 10, B는 11, C는 12, D는 13, E는 14, F는 15예요.
Crystal에서는 0x 접두사를 사용해 16진수를 표현할 수 있어요.
2진수와 8진수와 마찬가지로, Crystal은 16진수 리터럴을 자동으로 Int32로 변환해요.
#=> 0x123
291
16진법이 아닌 숫자에 0x를 붙이면 컴파일 오류가 발생해요.
2진수와 마찬가지로, <int>.to_s(base) 메서드를 사용해 Int32를 16진수 표현으로 변환할 수 있어요.
그리고 <int>.to_i(base) 메서드를 사용해 16진수 표현을 Int32로 변환할 수 있어요.
291.to_s(16)
# => "123"
"123".to_i(16)
# => 291
2진수와 8진수와 마찬가지로, 밑을 잘못 지정하면 ArgumentError가 발생해요.
수를 문자열 표현으로 변환할 때, 그 수의 정밀도를 지정할 수 있어요.
정밀도란 수를 표현하는 데 사용하는 숫자의 최소 개수를 뜻해요.
수의 자릿수가 정밀도보다 적으면 문자열 표현 앞에 0이 채워져요.
이는 <int>.to_s(<base>, precision: <value>) 메서드에 precision 인자를 넘겨서 해요.
291.to_s(16, precision: 5)
# => "00123"
543.to_s(precision: 2)
# => "543"
친구가 사진 편집 소프트웨어에 돈을 쓰는 것에 지쳐서 직접 만들어 보기로 했어요. 친구는 새 소프트웨어의 이름을 Foto Fusionist라고 짓기로 했어요.
Foto Fusionist는 다양한 일을 할 수 있는 사진 편집 소프트웨어지만, 지금까지는 그중 몇 가지 기능만 구현한 상태예요. 그래도 친구는 진행 상황에 아주 만족하며, 몇 가지 기능을 더 구현해 달라고 부탁했어요.
첫 번째 기능으로, 친구는 숫자의 이진 표현을 정수로 변환할 수 있기를 원해요. 소프트웨어가 색상 채널의 이진 표현을 읽어서 정수로 변환할 수 있어야 하기 때문에 필요한 기능이에요.
String 타입의 binary 인자를 받는 FotoFusionist.binary_to_int 메서드를 구현하세요.
메서드는 이진수의 정수 표현을 반환해야 해요.
FotoFusionist.binary_to_int("10011")
# => 19
친구가 원하는 두 번째 기능은 정수에서 최하위 비트를 구하는 거예요. 최하위 비트는 가장 오른쪽에 있는 비트예요. 값이 가장 작기 때문에 최하위 비트라고 불러요.
최하위 비트는 색상 채널을 표현하는 데 사용되는 비트 수를 줄여서 이미지를 최적화할 수 있는지 판단할 때 필요해요.
Int32 타입의 number 인자를 받는 FotoFusionist.least_significant_bit 메서드를 구현하세요.
메서드는 숫자의 최하위 비트를 반환해야 해요.
FotoFusionist.least_significant_bit(0b10011)
# => 1
FotoFusionist.least_significant_bit(0b10010)
# => 0
친구가 원하는 세 번째 기능은 색상 채널에서 16진수 값을 구하는 거예요. 16진수 값은 색상 채널을 16진수 표현으로 변환하는 데 필요하고, 그 16진수 표현은 두 자리로 이루어져야 해요.
Int32 타입의 number 인자를 받는 FotoFusionist.hex_value 메서드를 구현하세요.
메서드는 숫자의 16진수 값을 String으로 반환해야 해요.
FotoFusionist.hex_value(19)
# => "13"
친구가 원하는 네 번째 기능은 RGB 색상에서 16진수 값을 구하는 거예요. 사용자가 색상을 하나의 문자열 표현으로 얻을 수 있게 하려면 이 기능이 필요해요. RGB 색상은 빨강, 초록, 파랑 세 개의 색상 채널로 표현되는 색상이에요. 각 색상 채널은 0과 255 사이의 숫자로 표현돼요.
RGB 색상의 16진수 값은 색상을 16진수로 나타낸 문자열이며, 빨강 색상 채널이 먼저, 그다음 초록 색상 채널, 마지막으로 파랑 색상 채널이 와요.
Int32 타입의 red, green, blue 세 인자를 받는 FotoFusionist.hex_value_from_rgb 메서드를 구현하세요.
메서드는 RGB 색상의 16진수 값을 String으로 반환해야 해요.
FotoFusionist.hex_value_from_rgb(255, 0, 0)
# => "ff0000"
Exercism에 가입하고 Crystal 트랙을 개념 26개연습 문제 142개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.