C.W.K.
Stream
Lesson 04 of 08 · published

숫자 — IEEE 754 의 경고들

~10 min · json, numbers, ieee754, precision

Level 0평문
0 XP0/64 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

JSON 숫자 타입 하나, 그리고 그건 float

JSON 숫자는 IEEE 754 double-precision float 에 매핑돼. spec 에 별도 정수 타입 없음; 55.0 은 같은 값. 대부분 파서가 내부에서 정수/float 구분 보존하지만 spec 은 안 요구.

문법 규칙

  • leading zero 금지007 무효; 7 써.
  • 양수에 + 금지+5 무효; 5 써.
  • 소수점 양쪽에 숫자 필요.55. 무효; 0.55.0 써.
  • 지수 표기 OK1e6, 1.5e-3, 2E10 다 유효.
  • NaN 과 Infinity 허용 안 됨null 로 인코딩, 또는 관행으로 tagged 문자열.

253 정밀도 절벽

JS 숫자 (와 대부분 JSON 파서) 는 Number.MAX_SAFE_INTEGER (= 253 - 1 = 9,007,199,254,740,991) 위로 정수 정밀도 잃어. 64-bit Twitter ID, Stripe object ID, 데이터베이스 BIGINT 가 통과시키면 조용히 반올림돼. 큰 정수는 문자열 로 보내.

Twitter ID 버그: Twitter API 가 64-bit tweet ID 반환. 10 년간 순진한 JS 클라이언트가 253 위 ID 를 조용히 손상. Twitter 문서가 결국 id 대신 id_str 읽으라고 안내. 큰 정수를 JSON 숫자로 보내는 API 는 지뢰밭 — 문서에 따로 명시 없으면 문자열로 가정해.

Code

유효한 숫자·json
{
  "int": 42,
  "negative": -17,
  "zero": 0,
  "float": 3.14159,
  "scientific": 6.022e23,
  "small": 1.5e-9,
  "big_id_as_string": "1234567890123456789"
}
무효 (각 줄이 파스 에러)·text
007        ← leading zero
+5         ← explicit positive sign
.5         ← no leading digit
5.         ← no trailing digit
NaN        ← unquoted, not a value
Infinity   ← unquoted, not a value
Python 의 큰 정수 (작동, JS 는 반올림)·python
import json

# Python int 는 임의 정밀도
big = 9007199254740993  # 2**53 + 1
text = json.dumps({"id": big})
print(text)            # {"id": 9007199254740993}
back = json.loads(text)
print(back["id"] == big)  # True — 깨끗하게 라운드트립

# 같은 텍스트를 JS 엔진에 먹이면:
# JSON.parse('{"id": 9007199254740993}').id
# → 9007199254740992  (조용히 반올림)

External links

Exercise

정상 int, 음수 float, 지수 표기 값, 64-bit ID 를 문자열로 인코딩한 JSON 문서 작성. 같은 데이터를 ID 를 숫자로 다시 작성. 둘 다 JSON.parse (node REPL) 로 파싱하고 ID 값 비교. 정밀도가 실시간으로 죽는 거 봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.