Croot Blog

Home About Tech Hobby Archive

국가 별 숫자 표기방식

표기 형태 별 국가 목록

출처 : https://romeoh.tistory.com/447

형태 국가
1,234,567.89 호주,캐나다 (영어권, 비공식),중국,홍콩,아일랜드,이스라엘,일본,한국,말레이시아,멕시코,뉴질랜드,파키스탄,필리핀,싱가포르,대만,태국,영국,미국
1234567.89 국제단위계(SI) (영어),캐나다 (영어권),중국,스리랑카,스위스 (화폐 단위)
1234567,89 국제단위계(SI) (프랑스어),알바니아,오스트리아,벨기에,보스니아헤르체고비나,브라질,불가리아,캐나다 (프랑스어권),체코,덴마크,에스토니아,핀란드,프랑스,독일,그리스,헝가리,이탈리아,네덜란드 (화폐 단위 제외),노르웨이,페루,폴란드,포르투갈,루마니아,러시아,세르비아,슬로바키아,슬로베니아,남아프리카공화국,스페인,스웨덴,스위스 (화폐 단위 이외),우크라이나
1,234,567·89 아일랜드,말레이시아,뉴질랜드,필리핀,싱가포르,대만,태국,영국,미국 (구식, 수기에서 쓰임)
1.234.567,89 아르헨티나,오스트리아,브라질,덴마크,독일,그리스,인도네시아,이탈리아,네덜란드 (화폐 단위),포르투갈,루마니아,러시아,슬로베니아,스페인,스웨덴 (권장되지 않음),터키
1˙234˙567,89 이탈리아 (수기)
12,34,567.89 인도
1’234’567.89 스위스 (인쇄, 전산, 화폐 단위, 일상용)
1’234’567,89 스위스 (수기)

변환

Number 타입의 숫자를 각 국가 별 표기 형태로 변환하는 예제

/**
 *
 * @param inputValue 입력할 숫자 값
 * @param customLocale 사용자 지정 로케일 (선택 사항)
 * @returns 로케일에 맞춰 형식화된 문자열
 * @example
 *   el: 1352.23 => "1.352,23"
 *   en: 1352.23 => "1,352.23"
 *   fr: 1352.23 => "1 352,23"
 */
function formatNumber(inputValue: number, customLocale?: string): string {
  if (isNaN(inputValue)) return inputValue.toString();

  const locale = customLocale || navigator.language;
  return new Intl.NumberFormat(locale).format(inputValue);
}


// 사용 예
console.log(formatNumberByLocale(100000.50, 'el-GR')); // 그리스 - 1.000.000,5
console.log(formatNumberByLocale(100000.50, 'en-US')); // 미국 - 1,000,000.5
console.log(formatNumberByLocale(100000.50, 'de-DE')); // 독일 - 1.000.000,5
console.log(formatNumberByLocale(100000.50, 'fr-FR')); // 프랑스 - 1 000 000,5
console.log(formatNumberByLocale(100000.50, 'hi-IN')); // 인도 - 10,00,000.5

의문

실제 키보드 입력시에도 표기 형태로 입력하는지?

⇒ 그리스 경우 실제로 소수점을 입력시에 “,”를 입력함.

역변환

국가 별 입력 문자를 Number 타입으로 변환하는 예제

/**
 * 국가별 형식의 숫자 문자열을 Number 타입으로 변환하는 함수
 * @param inputNum 숫자 형식의 문자열
 * @param customLocale 사용자 지정 로케일 (선택 사항)
 * @returns 변환된 숫자
 * @example
 *   el: "1.352,23" => 1352.23
 *   en: "1,352.23" => 1352.23
 *   fr: "1 352,23" => 1352.23
 */
function parseNumber(inputNum: string, customLocale?: string): number {
  if (!inputNum) return NaN;

  const locale = customLocale || navigator.language;
  const numberFormat = new Intl.NumberFormat(locale);
  
  // 소수점 구분 기호 추출
  const decimalSeparator = numberFormat
    .formatToParts(0.1)
    .find(part => part.type === 'decimal')?.value || '.';

  // 소수점 이외의 숫자 구분 기호 추출
  const groupSeparator = numberFormat
    .formatToParts(1000)
    .find(part => part.type === 'group')?.value || ',';

  // 숫자 표기 형식을 표준화된 형식으로 변환
  const standardizedNumber = inputNum
    .replace(new RegExp(`\\${groupSeparator}`, 'g'), '') // 그룹 구분 기호 제거
    .replace(new RegExp(`\\${decimalSeparator}`), '.'); // 소수점 구분 기호를 '.'로 변경

  return parseFloat(standardizedNumber);
}


// 사용 예
console.log(parseLocalizedNumber("1.352,23", 'el-GR')); // 그리스 스타일, 출력: 1352.23
console.log(parseLocalizedNumber("1,352.23", 'en-US')); // 미국 스타일, 출력: 1352.23
console.log(parseLocalizedNumber("1.352,23", 'de-DE')); // 프랑스 스타일, 출력: 1352.23
console.log(parseLocalizedNumber("1 352,23", 'fr-FR')); // 프랑스 스타일, 출력: 1352.23
console.log(parseLocalizedNumber("1352", 'en-US'));     // 소수 없는 경우, 출력: 1352
console.log(parseLocalizedNumber("-1.352,23", 'el-GR')); // 음수 테스트, 출력: -1352.23

입력값 검증

function validate(event: HTMLInputEvent) {
	const value = event.currentTarget.value
  const locale = navigator.language
  const numberFormat = new Intl.NumberFormat(locale);
  
  // 소수점 구분 기호 추출
  const decimalSeparator = numberFormat.formatToParts(0.1).find(part => part.type === 'decimal')?.value || '.';

  // 숫자와 소수점만 허용하는 정규식 생성
  const regex = new RegExp(`[^0-9${decimalSeparator}]`, 'g');
  // 소수점 하나만 허용하는 정규식
  const regex2 = new RegExp(`(\\${decimalSeparator}.*?)\\${decimalSeparator}`, 'g');

  // 숫자와 소수점 하나만 허용되도록 수정
  const parsedValue = value.replace(regex, '').replace(regex2, '$1');

  // 숫자 형식을 로케일에 맞게 변환
  const formattedValue = $aup.i18n.formatNumber(parseFloat(parsedValue));
  event.currentTarget.value = fomattedValue
}