PHPで漢数字を半角数字に変換する(整数版)

(1/1)
Web上の新聞記事や書籍の文章をOCRで取り込むと、数字の部分が「十三兆九千二百五十六億円」という漢数字になっていたり、「2009年」という全角数字のままである。これを、そのまま横書きのテキストファイルとして扱うと違和感がある。計算などに二次利用しにくいという問題もある。
そこで、「PHPで半角数字を漢数字にする」とは逆に、漢数字や全角数字を半角数字に変換するプログラムを作ってみることにする。

(2021年7月7日)PHP8対応,リファラ・チェック追加,大幅改訂

目次

サンプル・プログラムの実行例

PHPで漢数字を半角数字に変換する(整数版)

サンプル・プログラム

出力書式を3種類から選択できるようにした。
たとえば、「十二万三千四百五十六」を「123456」に変換したいなら「ベタ数字」を、「123,456」に変換したいなら「カンマ区切り」を、「12万3456」に変換したいなら「漢字交じり」を選ぶ。

また、コマンドラインから指定できるようにした。
sourに変換したい漢数字(UTF-8エンコード)を、modeに出力書式(1=カンマ区切り,2=漢字混じり, それ以外=ベタ数字)を指定する。

download ダウンロード(PHP8対応)

解説:漢数字を半角数字に変換

0199: /**
0200:  * 漢数字を数値に変換する
0201:  * @param   string $kanji漢数字
0202:  * @param   int $mode出力書式/1=3桁カンマ区切り,2=漢字混じり, それ以外=ベタ打ち
0203:  * @return  double数値
0204: */
0205: function kan2num($kanji$mode) {
0206:     //全角=半角対応表
0207:     $kan_num = array(
0208:         '' => 0, '' => 0,
0209:         '' => 1, '' => 1, '' => 1,
0210:         '' => 2, '' => 2, '' => 2,
0211:         '' => 3, '' => 3, '' => 3,
0212:         '' => 4, '' => 4,
0213:         '' => 5, '' => 5,
0214:         '' => 6, '' => 6,
0215:         '' => 7, '' => 7,
0216:         '' => 8, '' => 8,
0217:         '' => 9, '' => 9
0218:     );
0219:     //位取り
0220:     $kan_deci_sub = array('' => 10, '' => 100, '' => 1000);
0221:     $kan_deci = array('' => 10000, '' => 100000000, '' => 1000000000000, '' => 10000000000000000);
0222: 
0223:     //右側から解釈していく
0224:     $ll = mb_strlen($kanji);
0225:     $a = '';
0226:     $deci = 1;
0227:     $deci_sub = 1;
0228:     $m = 0;
0229:     $n = 0;
0230:     for ($pos = $ll - 1; $pos >= 0; $pos--) {
0231:         $c = mb_substr($kanji$pos, 1);
0232:         if (isset($kan_num[$c])) {
0233:             $a = $kan_num[$c] . $a;
0234:         } else if (isset($kan_deci_sub[$c])) {
0235:             if ($a != '')   $m = $m + $a * $deci_sub;
0236:             else if ($deci_sub != 1) $m = $m + $deci_sub;
0237:             $a = '';
0238:             $deci_sub = $kan_deci_sub[$c];
0239:         } else if (isset($kan_deci[$c])) {
0240:             if ($a != '')   $m = $m + $a * $deci_sub;
0241:             else if ($deci_sub != 1) $m = $m + $deci_sub;
0242:             $n = $m * $deci + $n;
0243:             $m = 0;
0244:             $a = '';
0245:             $deci_sub = 1;
0246:             $deci = $kan_deci[$c];
0247:         }
0248:     }
0249: 
0250:     $ss = '';
0251:     if (preg_match("/^(0+)/", $a$regs) != FALSE)  $ss = $regs[1];
0252:     if ($a != '')   $m = $m + $a * $deci_sub;
0253:     else if ($deci_sub != 1) $m = $m + $deci_sub;
0254:     $n = $m * $deci + $n;
0255: 
0256:     //出力書式に変換
0257:     if ($ss == '') {
0258:         $dest = $n;
0259:         switch ($mode) {
0260:             case 1:
0261:                 $dest = number_format($n);
0262:                 break;
0263:             case 2:
0264:                 $dest = int2kanji($n);
0265:                 break;
0266:             default:
0267:         }
0268:      } else if ($n == 0) {
0269:         $dest = $ss;
0270:     } else {
0271:         $dest = $ss . $n;
0272:     }
0273: 
0274:     return $dest;
0275: }

まず、漢数字の構造を考える。
漢数字は、一、二、三‥‥という数字の部分($kan_num)と、位取りの部分に分かれる。
位取りの漢字は、十、百、千のグループ($kan_deci_sub)と、万、億、兆‥‥のグループ($kan_deci)に分かれる。
厄介なのは、「二千九」と「二〇〇九」という2種類の表記ができることである。

そこで、漢数字を右から順に1文字ずつ処理し、$kan_num$kan_deci_sub$kan_deci の現れ方によって変数 $n に結果を入れていくことにした。

なお、今回のプログラムは整数しか変換することができない。

参考サイト

(この項おわり)
header