2진수 연산 마스터

숫자 세기 (Binary Counter)

버튼을 눌러 10진수 숫자가 2진수로 차오르는 원리를 확인하세요.

0

1의 보수 (One's Complement)

비트를 뒤집으면(반전) 1의 보수가 됩니다.
원래 값과 1의 보수를 비트별 OR 하면 모든 비트가 1이 됩니다. 현대 컴퓨터의 일반적인 signed 정수 음수 표현은 여기에 1을 더한 2의 보수입니다.
양수 N
0
1의 보수
(반전)
반전

뺄셈의 과정 (Step-by-Step)

A - B는 8비트에서 A + (-B)로 계산합니다. -B는 B를 반전한 뒤 1을 더한 2의 보수입니다.
같은 8비트 결과도 unsigned와 signed 해석의 십진수 값은 다를 수 있습니다.
-
STEP 1: B를 음수(-B)로 변환
B
0
↓ 반전 (1의 보수)
~B
(반전)
↓ +1
-B (2의보수)
0
+
STEP 2: A와 더하기
A
0
-B
0
=
FINAL RESULT (버림 발생 확인)
결과
0

비트 이동 vs 산술 연산

시프트(주황색)는 비트를 이동하며, 8비트 범위를 벗어난 비트는 버려집니다.
일반 곱셈(청록색)은 비트 패턴이 완전히 바뀝니다.
입력값:
Current: 5

비트 논리 연산 (AND, OR, XOR, NOT)

각 비트 자리마다 논리 연산을 수행합니다.
보라색은 연산 결과를 의미합니다.
A:
B:
A
0
&
B
0
결과
0
12 & 10 = 8

Float32와 떠다니는 소수점

부동소수점(Floating Point)의 ‘부동’은 움직이지 않는다는 뜻이 아닙니다. 소수점 위치가 둥둥 떠다니듯 이동한다는 뜻입니다.
예를 들어 12300을 1.23 × 10⁴로 표현하듯, 컴퓨터도 중요한 숫자 부분과 소수점 이동량을 나누어 저장합니다.
Float32의 32bit 구성

부호 1bit + 지수 8bit + 가수 저장 공간 23bit = 32bit

가수의 맨 앞에는 보통 항상 1이 오므로 저장하지 않고 생략합니다. 이 숨은 1bit까지 포함하면 실제 유효숫자 정밀도는 24bit입니다.

① 부호 1bit0은 양수, 1은 음수
② 지수 8bit소수점을 얼마나 옮길지
③ 가수 저장 23bit숨은 1을 포함하면 24bit 정밀도
② 지수 8bit는 소수점 위치를 어떻게 저장할까?

먼저 이진수를 맨 앞이 1이 되도록 정규화합니다. 0.1은 다음처럼 소수점을 오른쪽으로 네 칸 옮겨 표현합니다.

0.000110011…₂ = 1.100110011…₂ × 2⁻⁴
  1. 실제 지수는 -4입니다.
  2. 음수 지수도 8bit unsigned 칸에 넣기 위해 Bias 127을 더합니다.
  3. -4 + 127 = 123
  4. 123₁₀ = 01111011₂

따라서 0.1의 지수 필드는 01111011입니다. 값을 다시 읽을 때는 저장값 123에서 Bias 127을 빼서 실제 지수 -4를 복원합니다.

③ 가수는 반복되는 비트를 어디서 자르고 어떻게 반올림할까?

정규화된 수의 맨 앞 1은 항상 있다고 약속하고 저장하지 않습니다. 이를 숨은 1이라고 합니다.

1.100110011001100110011001100…₂
숨은 1 제외 → 100110011001100110011001100…
  1. 가수 필드에 들어갈 앞의 23bit를 먼저 취합니다.
    10011001100110011001100
  2. 그 뒤에도 1100…이 계속 남아 있으므로 정확히 잘라 버리면 원래 값보다 작아집니다.
  3. IEEE 754의 기본 방식은 가장 가까운 표현 가능 값으로 반올림합니다. 경계에 정확히 걸리면 마지막 비트가 짝수가 되는 쪽을 고릅니다.
  4. 0.1은 잘린 다음 첫 비트가 1이고 뒤에도 1이 남아 있어 위쪽 값으로 반올림합니다.
자르기 전 23bit: 10011001100110011001100
반올림 후 저장: 10011001100110011001101

그래서 0.1보다 아주 조금 큰 0.10000000149011612가 저장됩니다. 23bit를 단순히 버리는 것이 아니라 남은 비트를 보고 가장 가까운 값으로 반올림한다는 점이 핵심입니다.

왜 0.1을 정확히 저장할 수 없을까?

1단계: 10진수 0.1을 이진수로 바꾸면 0.00011001100110011…₂처럼 0011이 끝없이 반복됩니다.

2단계: Float32의 저장 공간은 한정되어 있으므로 반복되는 비트를 끝까지 담을 수 없습니다.

3단계: 23bit까지만 저장하고 가장 가까운 값으로 반올림합니다.

저장 결과: 0 | 01111011 | 10011001100110011001101
16진수: 0x3DCCCCCD
저장된 값은 원래 0.1과 완전히 같지 않습니다.
Float32의 0.1 실제 값: 약 0.10000000149011612
그래서 실수는 보통 a === b로 직접 비교하지 않고 |a-b| < epsilon처럼 허용 오차 범위로 비교합니다.
0.1 + 0.2는 왜 정확히 0.3이 아닐까?

0.1과 0.2 모두 이진수로 정확히 끝나지 않아 각각 근삿값으로 저장됩니다. 그 근삿값을 더한 결과에도 작은 오차가 남습니다. 이는 계산 오류가 아니라 한정된 비트로 무한한 실수를 표현하는 방식의 한계입니다.