진법 변환기

숫자를 2진, 8진, 10진, 16진 및 2부터 36까지 임의 진법으로 상호 변환. 고정 폭 2의 보수와 비트 그리드 포함.

비트 폭
2진수
8진수
10진수
16진수
진법
비트 — 클릭해 뒤집기

폭 8비트, 그중 8개가 켜짐

이 도구가 하는 일

같은 수를 여러 진법으로 쓸 수 있고, 프로그래머는 그중 넷 사이를 끊임없이 오갑니다: 하드웨어가 담는 것이라 2진수, 2진수의 읽을 수 있는 약기라 16진수, 사람이 그렇게 생각하니 10진수, 그리고 파일 권한과 몇몇 오래된 시스템이 아직 쓰니 8진수입니다. 여기 어느 칸에 값을 입력해도 나머지가 따라오고, 더해서 2부터 36까지 임의 진법으로 설정할 수 있는 칸도 하나 딸려 옵니다.

이것을 학교 계산기와 가르는 것은 폭 선택과 비트 그리드입니다. 8, 16, 32, 64비트를 고르면 음수가 빼기 기호가 아니라 진짜 기계 표현을 얻고, 모든 비트가 클릭할 수 있는 것이 됩니다.

진법이란 실제로 무엇인가

진법이란 다 써서 올림해야 하기까지 숫자가 몇 개 있느냐입니다. 10진수에는 열 개가 있어 9 다음이 10입니다. 2진수에는 두 개가 있어 1 다음이 10입니다. 각 자리의 위치는 진법의 거듭제곱이고, 그게 전부입니다:

1011           # 이 수를 2진수로
1 x 8 = 8      # 비트 3
0 x 4 = 0      # 비트 2
1 x 2 = 2      # 비트 1
1 x 1 = 1      # 비트 0
8+0+2+1 = 11   # 합계를 10진수로

열을 넘는 진법에는 열 개보다 많은 숫자 기호가 필요해 글자를 빌립니다: 16진수는 0-9 다음 a-f로 가고 a는 10, f는 15입니다. 그것이 진법 36까지 이어지며, 거기서는 모든 숫자와 모든 글자를 씁니다 — 맨 알파벳으로 쓸 수 있는 가장 큰 진법이자, 이 도구가 거기서 멈추는 이유입니다.

왜 16진수이고 다른 무언가가 아닌가

16진수는 하나의 특정한 이유로 인기입니다: 16은 2의 4제곱이라 정확히 16진수 한 자리가 정확히 4비트를 덮습니다. 그 덕에 16진수와 2진수의 변환이 계산 없는 찾아보기가 됩니다 — 각 16진수 자리가 주변 자리와 무관하게 저만의 4비트로 펼쳐집니다.

d    e    a    d
1101 1110 1010 1101   # 각 16진수 자리가 저마다의 니블

8진수는 한 자리 3비트로 같은 방식으로 돕니다. 8이 2의 3제곱이기 때문입니다 — 그래서 Unix 권한이 8진수입니다: 사용자 그룹마다 세 권한 비트가 정확히 한 자리에 들어맞습니다. 10진수는 2진수와 그런 관계가 없어, 둘 사이의 변환에는 찾아보기가 아니라 진짜 나눗셈이 필요합니다.

여기 2진수 칸이 넷씩, 16진수 칸이 둘씩 묶인 것도 그래서입니다: 그 묶음이 중요한 경계에 맞으므로 세지 않고도 니블이나 바이트를 화면에서 읽어 낼 수 있습니다.

음수와 2의 보수

음수는 그 자체로는 2진 형태가 없습니다. 레지스터에 빼기 기호는 없고 — 비트뿐입니다 — 그래서 부호는 비트 자체에 부호화되어야 하고, 그러려면 비트가 몇 개인지 정해야 합니다. 폭 선택이 있는 이유이자, 바꾸면 답이 바뀌는 이유입니다.

모든 현대 기계가 쓰는 방식은 2의 보수입니다: 음수를 나타내려면 그 양수 형태를 취해 모든 비트를 뒤집고 1을 더합니다. 그 결과 맨 위 비트가 "음수"를 뜻하게 되고, 부호를 위한 특별한 경우 없이 보통의 덧셈이 계속 통합니다.

0000 0101   # 5
1111 1010   # 모든 비트 뒤집기
1111 1011   # 1 더하기: 바이트로 -5, 16진수로 fb

레지스터를 넓히면 같은 수가 다른 패턴을 얻습니다: -5는 8비트로 fb, 16비트로 fffb, 32비트로 fffffffb입니다. 값은 바뀌지 않았습니다. 그것을 나르는 비트의 수가 바뀌었습니다. 이 도구에서 폭을 바꾸면 바로 그것이 보입니다.

0xFF가 255이면서 -1이기도 한 이유

비트 ff는 그것이 부호 있는지를 말하지 않습니다. 1111 1111을 담은 바이트는 그것을 읽는 코드가 부호 없는 타입을 선언했으면 255로, 부호 있는 것을 선언했으면 -1로 읽힙니다. 바이트 자체에는 둘을 가르는 것이 아무것도 없습니다 — 타입은 그런 정보를 지니지 않은 비트에 대해 프로그램이 하는 주장입니다.

그것이 진짜 버그 한 무리의 근원입니다: 음수로 나오는 체크섬, 파일에서 읽어 0보다 작게 비교되는 바이트, 부호 유무가 구현 정의라 ARM에서 x86과 다르게 동작하는 C의 char입니다. 부호 있는 읽기와 부호 없는 읽기가 다를 때마다 이 도구는 둘 다 보여 줍니다. 그 어긋남이야말로 대개 당신이 찾던 것이기 때문입니다.

비트 그리드

현재 값의 모든 비트가 위치 번호와 함께 표시되고, 하나를 클릭하면 뒤집힙니다. 진법이 곧바로 갱신되어, 몇몇 물음을 손으로 하기보다 훨씬 쉽게 답할 수 있게 합니다:

  • 이 플래그 값에서 어느 비트가 켜졌나 — 하나씩 클릭하며 위치를 읽으세요.
  • 비트 4와 7의 마스크는 무엇인가 — 그 둘을 켜고 16진수를 읽으세요.
  • 맨 위 비트를 켜면 부호 있는 값에 무슨 일이 생기나 — 눈에 보이게 음수가 됩니다.
  • 이 값이 2의 거듭제곱인가 — 2의 거듭제곱은 정확히 한 비트만 켜져 있습니다.

비트 0이 최하위 비트이고 오른쪽에 있으며, 이는 보편적 관례이자 오른쪽에서 왼쪽으로 쓰는 페이지에서도 그리드가 왼쪽에서 오른쪽으로 남는 이유입니다. 행은 여덟 비트 폭이라 바이트 경계가 한눈에 보입니다.

큰 수도 정확하게 남는다

JavaScript 숫자는 배정밀도라 정수를 정확히 담는 것은 2^53 — 약 9천조 — 까지뿐입니다. 64비트 값은 그것을 넘을 수 있고, 보통 숫자로 만든 변환기는 그것을 조용히 반올림해 그럴듯해 보이지만 마지막 자릿수가 틀린 16진수 문자열을 냅니다.

여기서는 모든 것이 대신 임의 정밀도 정수를 씁니다. 그래서 온전한 64비트 값이 정확히 변환됩니다. 임의 정밀도 폭 모드는 더 나아가 한계를 아예 없앱니다 — 암호 값과 큰 식별자에 유용합니다 — 다만 고정 폭이 없으면 2의 보수도 없으므로, 그 모드에서 음수는 어느 진법에서든 그저 빼기 기호를 지닙니다.

2진수에서 10진수로, 10진수에서 2진수로

2진수와 10진수는 여기서 서로 아무 관계가 없는 유일한 짝입니다: 2는 10의 거듭제곱이 아니고 10도 2의 거듭제곱이 아니어서, 어느 방향도 찾아보기로 끝나지 않고 둘 다 진짜 계산이 필요합니다. 게다가 같은 계산도 아닙니다. 좀처럼 소리 내어 말하지 않는 대목인데, 한쪽 방향의 빠른 손계산은 돌아오는 방향의 빠른 손계산을 뒤집은 것이 아닙니다.

  • 2진수에서 10진수로, 두 배로 하는 법: 맨 왼쪽 비트에서 0으로 시작해, 비트마다 지금까지의 값을 두 배 하고 그 비트를 더합니다. 1011이면 1, 2, 5, 11로 갑니다 — 한 번의 훑기로 끝나고 자릿값을 외울 필요가 없으며, 이 도구가 입력을 읽을 때 하는 일이 바로 이것입니다.
  • 2진수에서 10진수로, 자리로 더하는 법: 켜진 비트의 자릿값을 모두 더합니다. 위의 풀이 예가 그것입니다. 켜진 비트가 두셋일 때는 빠르고, 대부분 켜져 있으면 느립니다.
  • 10진수에서 2진수로, 나누는 법: 2로 나누고 나머지를 적기를 아무것도 남지 않을 때까지 되풀이한 다음, 나머지를 아래에서 위로 읽습니다. 답이 최하위 비트부터 나오기 때문에, 적는 내내 거꾸로 보입니다.
  • 10진수에서 2진수로, 빼는 법: 들어가는 가장 큰 2의 거듭제곱을 빼고 되풀이합니다. 200은 128을 잃어 72가 남고, 72는 64를 잃어 8이 남고, 8은 8을 잃어 아무것도 남지 않습니다 — 그래서 위치 7, 6, 3의 비트가 켜지고 바이트는 1100 1000입니다. 켜진 비트가 적을 때는 나눗셈보다 빠릅니다.

여기 어느 손계산도 다루지 못하는 것이 하나 있습니다: 음의 10진수는 폭을 고르기 전까지 2진 형태가 아예 없습니다. 마이너스 5를 2진수로 어떻게 쓰느냐고 물으면 정직한 답은 되물음입니다 — 몇 비트인가요? 그것을 정하는 것이 폭 선택이고, 위의 2의 보수 절이 다루는 것도 그것입니다. 임의 정밀도 모드에는 폭이 없으므로 빼기 기호가 어느 진법에나 그대로 따라옵니다.

10진수에서 16진수로, 16진수에서 10진수로

이 일을 자주 하는 사람은 16으로 나누지 않습니다. 16진수와 2진수의 관계가 바로 지름길입니다: 10진수를 한 번 2진수로 바꾸고, 비트를 오른쪽부터 넷씩 자른 뒤, 각 묶음을 16진수 한 자리로 읽습니다. 돌아올 때는 같은 길을 거꾸로 가서, 16진수 각 자리를 그 4비트로 펼치고 켜진 비트의 자릿값을 더합니다. 한 바이트까지라면 더 짧은 길도 있습니다: 16진수 첫 자리는 둘째 자리의 16배이니 곱해서 더하면 됩니다.

  • 255는 ff — 모든 비트가 켜진 바이트입니다. 외워 둘 값이 하나라면 이것인데, 거기서 바이트가 끝나기 때문입니다.
  • 256은 100입니다. 꽉 찬 바이트에서 한 걸음 넘어가면 10진수에서 99가 100으로 넘어가는 것과 똑같이 자리가 넘어가고, 16진수는 바이트가 담을 수 없는 자리를 얻습니다.
  • 65535는 ffff이고 65536은 10000 — 한 바이트 위의 같은 두 이정표이며, 16비트 계수기가 멈추는 곳입니다.
  • 4096은 1000이고, 그래서 페이지 크기와 정렬과 메모리 오프셋이 16진수에서는 둥글고 10진수에서는 들쭉날쭉해 보입니다. 16진수는 비트를 넷씩 세고 하드웨어도 그렇게 셉니다.

대문자와 소문자는 구별되지 않습니다: FF와 ff는 같은 값이고, 이 도구는 입력에서 둘 다 받아들이며 출력에서는 소문자를 씁니다. 하지 않는 것은 추측입니다. 접두사 0x는 16진수 칸의 것이라 10진수 칸에서는 조용히 버려지지 않고 거부됩니다. 틀린 진법으로 읽힌 값은 변환기가 결코 그럴듯해 보이게 만들어서는 안 되는 단 하나의 잘못이기 때문입니다.

8진수에서 10진수로, 그리고 답을 바꾸는 앞자리 0

8진수가 다른 어디보다 오래 살아남은 곳은 파일 권한입니다. 사용자 그룹마다 세 권한 비트가 정확히 8진수 한 자리에 들어맞기 때문입니다. 10진수로 바꾸는 일은 8의 거듭제곱을 쓰는 평범한 자리 계산이어서, 8진수 755는 64가 일곱에 8이 다섯에 5, 즉 493입니다. 반대 방향은 8로 나누고 나머지를 아래에서 위로 읽는 것으로, 10진수에서 2진수로 갈 때와 같은 모양이고 같은 이유입니다: 8도 10과 아무 관계가 없습니다.

  • 755는 10진수로 493, 644는 420, 777은 511입니다. 이 10진수들은 하나도 쓸모가 없는데 그게 요점입니다 — 권한을 8진수로 쓰는 것은 자리가 권한 비트에 맞기 때문이지 값이 무언가를 세기 때문이 아닙니다.
  • 앞자리 0은 C와 Python 2에서 진법 표시입니다: 거기서 0755는 8진수, 곧 493입니다. Python 3은 그 표기를 아예 거부하고 대신 0o755를 요구하는데, 그것이 조용한 버그 한 무리를 통째로 없앴습니다.
  • YAML 1.1도 따옴표 없는 0755를 493으로 읽습니다. 그래서 설정 파일의 권한 모드는 따옴표로 감싸야 하고, 그러지 않으면 적어 둔 그 모드가 아니게 됩니다.
  • JSON은 처음부터 허용한 적이 없습니다. 문법이 수의 앞자리 0을 금하므로 0755는 거기서 수도 아니고 구문 오류입니다 — 셋 가운데 가장 요란하고, 유일하게 잘못 읽힐 수 없는 동작입니다.

이 도구는 앞자리 0을 무엇의 표시로도 보지 않습니다. 진법을 정하는 것은 입력하는 칸이어서, 0755는 10진수 칸에서 755이고 8진수 칸에서 493입니다. 접두사 0o는 8진수 칸에서 받아들여지고 그 밖의 어디서도 거부됩니다. 접두사로 진법을 짐작한다는 것은 입력된 것과 다른 수를 돌려준다는 뜻이기 때문입니다.

8진수에서 16진수로: 지름길이 없는 짝

둘 다 2의 거듭제곱이라 둘 다 같은 비트를 다시 묶는 일일 뿐입니다. 그런데도 이것은 네 진법 가운데 자리와 자리를 맞대는 규칙이 아예 없는 유일한 짝입니다. 8진수 한 자리는 3비트, 16진수 한 자리는 4비트이고, 셋과 넷은 서로 나누어떨어지지 않으므로 경계가 결코 맞지 않습니다. 비트를 펼쳐 쓰고 다시 묶는 일을 건너뛸 길은 없습니다.

  • 8진수의 각 자리를 순서대로 그 3비트로 씁니다: 755는 111 101 101이 됩니다.
  • 그 비트를 오른쪽 끝에서부터 넷씩 다시 묶고, 개수가 딱 나누어떨어지지 않으면 왼쪽을 0으로 채웁니다: 0001 1110 1101.
  • 넷씩 묶인 것을 16진수 한 자리로 읽습니다: 1ed. 채우는 끝을 잘못 고르는 것이 여기서 흔한 실수인데, 틀려 보이지도 않습니다 — 그저 조용히 답을 몇 배로 만들 뿐입니다.

16진수 두 자리가 정확히 한 바이트이고 8진수 두 자리는 그렇지 않다는 것이, 메모리를 읽는 자리에서 16진수가 8진수를 밀어낸 이유의 전부입니다: 8비트는 8진수 두 자리와 3분의 2여서 바이트 경계가 자리 한가운데 떨어집니다. 8진수는 워드 크기가 3비트의 배수였던 기계에 맞았고, 16진수는 8비트 바이트에 맞습니다. 그리고 이 페이지에서는 이 짝에 한해 비트 그리드가 어느 손계산보다 빠릅니다 — 비트를 한 번 켜면 두 칸이 이미 답을 보여 줍니다.

자주 묻는 질문

-5가 2진수로 -101이 아니라 fb로 표시되는 이유는 무엇인가요?
레지스터에 빼기 기호가 없기 때문입니다. 폭을 고르면 음수는 2의 보수로 표시되고, 이는 기계가 실제로 저장하는 것입니다: 바이트로 -5는 1111 1011, 즉 fb입니다. 부호 있는 수학적 형태를 원하면 폭을 임의 정밀도로 바꾸세요.
0xFF는 255인가요, -1인가요?
둘 다입니다 — 비트는 동일하고 선언된 타입만이 정합니다. 부호 있는 8비트 값은 ff를 -1로, 부호 없는 것은 255로 읽습니다. 두 읽기가 다를 때마다 이 도구는 그것들을 나란히 보여 줍니다.
10진수 대신 16진수가 그토록 많이 쓰이는 이유는 무엇인가요?
16진수 한 자리가 정확히 4비트라, 16진수와 2진수가 계산 없는 찾아보기로 변환되고 자리가 바이트 경계에 맞기 때문입니다. 10진수는 2진수와 그런 관계가 없어, 10진수 값은 어느 비트가 켜졌는지 아무것도 말해 주지 않습니다.
여기서 가장 높은 진법은 무엇이고 왜 36인가요?
36입니다. 숫자 10개에 글자 26개 — 맨 라틴 알파벳이 주는 모든 기호 — 이기 때문입니다. 더 높이 가려면 어떤 추가 문자를 쓸지에 대한 합의가 필요한데, 합의된 하나가 없습니다.
0x나 공백이 든 값을 붙여넣을 수 있나요?
네. 0x, 0b, 0o 접두사는 맞는 진법에서 받아들여지고, 공백과 밑줄은 무시되므로, 코드나 데이터시트에서 그대로 붙여넣어도 먼저 정리할 필요가 없습니다.
64비트 값이 정확히 변환되나요?
네. 모든 연산이 임의 정밀도 정수를 쓰므로, 2^53 — 보통 JavaScript 숫자가 반올림하기 시작하는 곳 — 을 넘은 값도 정확히 남습니다.
제가 입력한 것이 서버로 전송되나요?
아니요. 브라우저 안의 연산입니다. 아무것도 업로드되거나 기록되지 않고, 네트워크 연결 없이 동작합니다.
2진수를 손으로 10진수로 바꾸려면 어떻게 하나요?
왼쪽부터 두 배 하고 더합니다: 0에서 시작해 비트마다 지금까지의 값을 두 배 하고 그 비트를 더하세요. 1011은 1, 다음 2, 다음 5, 다음 11로 갑니다. 한 번의 훑기로 끝나고 자릿값을 외울 필요가 없으며, 같은 방법이 어느 진법에서나 통합니다 — 두 배 대신 진법을 곱하면 됩니다.
255는 16진수로 얼마이고, 왜 이 수가 자꾸 나오나요?
ff입니다. 여덟 비트가 모두 켜진 바이트라 한 바이트가 담는 가장 큰 값이고, 셈이 둘째 바이트로 넘어가는 지점입니다 — 그래서 색 채널과 마스크와 크기 한계 곳곳에 나옵니다. 그보다 하나 큰 256은 16진수로 100이라고 씁니다.
0755는 755와 같은 수인가요?
여기서는 10진수 칸에서는 같고 8진수 칸에서는 다릅니다: 진법을 정하는 것은 칸이고 앞자리 0은 그저 0이라는 자리입니다. 그 밖에서는 언어에 따라 다릅니다 — C와 Python 2는 0755를 8진수, 곧 493으로 읽고, Python 3은 그 표기를 거부하며 0o755를 요구하고, YAML 1.1은 493으로 읽으며, JSON은 구문 오류로 다룹니다.
8진수를 16진수로 어떻게 바꾸나요?
2진수를 거칩니다. 더 짧은 길이 없기 때문입니다: 8진수 한 자리에 3비트, 16진수 한 자리에 4비트라 둘은 결코 맞지 않습니다. 8진수의 각 자리를 그 3비트로 펼치고, 전체를 오른쪽부터 넷씩 다시 묶고, 넷씩을 16진수 한 자리로 읽으세요 — 755는 111 101 101이 되고, 다음은 0001 1110 1101, 그다음이 1ed입니다.

관련 도구

  • 데이터 용량 변환

    같은 수를 비트의 배열이 아니라 데이터 양으로 읽으면 어떻게 되는가. 저 페이지는 바이트 수를 KB, MB, GB와 KiB, MiB, GiB로 나란히 바꾸고, 두 체계가 어디서 갈리는지도 알려 줍니다.

  • 백분율 계산기

    진법은 수를 어떻게 적는지를, 백분율은 다른 수 옆에서 얼마나 큰지를 말합니다. 저 페이지는 비율과 변화와 역산을 계산하고, 직접 넣은 숫자가 들어간 공식까지 함께 보여 줍니다.