作 ▸
JavaScriptで数値を漢数字表記に変換する
例えば 1,234,567,890 → 十二億三千四百五十六万七千八百九十 とかです。
関数を作ってみました。が、コード内には無量大数とか書いてありますが、実際には safe integer
の範囲内にしか対応してません。これは今のChrome (ver.71) だと -9007199254740991 ~ 9007199254740991 です。
safe integerの範囲を無視しても、1垓 (10^20) を超えたあたりからは数値を文字列にキャストした時に指数表記 (1e+20みたいな) になってしまうので、うまく変換できませんでした。
なので、以下のコードでは9,007兆くらいが限界です。
/**
* 数値を漢数字表記に変換
* @param {String|Number} num - 半角数字
* @return {String} 漢数字表記
* @throws {TypeError} 半角数字以外の文字が含まれている場合
* @throws {RangeError} 数値が Number.MIN_SAFE_INTEGER ~ Number.MAX_SAFE_INTEGER の範囲外の場合
*/
const numbersToKanji = (num) => {
if (num === undefined || num === null || num === '') {
return '';
}
if (!(/^-?[0-9]+$/g.test(num))) {
throw new TypeError('半角数字以外の文字が含まれています。漢数字に変換できませんでした。-> '+ num);
}
num = Number(num);
if (!Number.isSafeInteger(num)) {
throw new RangeError('数値が '+ Number.MIN_SAFE_INTEGER +' ~ '+ Number.MAX_SAFE_INTEGER +' の範囲外です。漢数字に変換できませんでした。-> '+ num);
}
if (num === 0) {
return '零';
}
let ret = '';
if (num < 0) {
ret += 'マイナス';
num *= -1;
}
const numStr = num + '';
const kanjiNums = ['','一','二','三','四','五','六','七','八','九'];
const kanjiNames = ['十','百','千','万','億','兆','京','垓','𥝱','穣','溝','澗','正','載','極','恒河沙','阿僧祇','那由他','不可思議','無量大数'];
const exponents = [1,2,3,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68];
const exponentsLen = exponents.length;
for (let i = exponentsLen; i >= 0; --i) {
const bias = Math.pow(10, exponents[i]);
if (num >= bias) {
const top = Math.floor(num / bias);
if (top >= 10) {
ret += numbersToKanji(top);
} else {
if (top == 1 && exponents[i] <= 3) {
// ※先頭の数字が1、かつ指数が3 (千の位) 以下の場合のみ『一』をつけない
} else {
ret += kanjiNums[top];
}
}
ret += kanjiNames[i];
num -= top * bias;
}
}
ret += kanjiNums[num];
return ret;
};
以下テストケースです。
console.log(numbersToKanji(0)); // -> '零'
console.log(numbersToKanji(1)); // -> '一'
console.log(numbersToKanji(2)); // -> '二'
console.log(numbersToKanji(3)); // -> '三'
console.log(numbersToKanji(4)); // -> '四'
console.log(numbersToKanji(5)); // -> '五'
console.log(numbersToKanji(6)); // -> '六'
console.log(numbersToKanji(7)); // -> '七'
console.log(numbersToKanji(8)); // -> '八'
console.log(numbersToKanji(9)); // -> '九'
console.log(numbersToKanji(10)); // -> '十'
console.log(numbersToKanji(11)); // -> '十一'
console.log(numbersToKanji(100)); // -> '百'
console.log(numbersToKanji(111)); // -> '百十一'
console.log(numbersToKanji(1000)); // -> '千'
console.log(numbersToKanji(1111)); // -> '千百十一'
console.log(numbersToKanji(10000)); // -> '一万'
console.log(numbersToKanji(11111)); // -> '一万千百十一'
console.log(numbersToKanji(100000)); // -> '十万'
console.log(numbersToKanji(111111)); // -> '十一万千百十一'
console.log(numbersToKanji(1000000)); // -> '百万'
console.log(numbersToKanji(1111111)); // -> '百十一万千百十一'
console.log(numbersToKanji(10000000)); // -> '千万'
console.log(numbersToKanji(11111111)); // -> '千百十一万千百十一'
console.log(numbersToKanji(100000000)); // -> '一億'
console.log(numbersToKanji(111111111)); // -> '一億千百十一万千百十一'
console.log(numbersToKanji(1234567890)); // -> '十二億三千四百五十六万七千八百九十'
console.log(numbersToKanji(1000000000000)); // -> '一兆'
console.log(numbersToKanji(9007199254740991)); // -> '九千七兆千九百九十二億五千四百七十四万九百九十一'
console.log(numbersToKanji(-1)); // -> 'マイナス一'
console.log(numbersToKanji(-1234567890)); // -> 'マイナス十二億三千四百五十六万七千八百九十'
console.log(numbersToKanji()); // -> ''
console.log(numbersToKanji(null)); // -> ''
console.log(numbersToKanji('')); // -> ''
console.log(numbersToKanji('9')); // -> '九'
// エラーケース
try {
numbersToKanji('1a');
} catch (e) {
console.log(e.toString()); // -> TypeError: 半角数字以外の文字が含まれています。漢数字に変換できませんでした。-> 1a
}
try {
numbersToKanji(9007199254740991 + 1);
} catch (e) {
console.log(e.toString()); // -> RangeError: 数値が -9007199254740991 ~ 9007199254740991 の範囲外です。漢数字に変換できませんでした。-> 9007199254740992
}