天天看點

數字轉中文漢字(php書寫)

數字轉換為漢字

          前段時間,因為一個朋友提到了數字轉化為漢字,開始我并不以為這有什麼難度,但千一段時間想着自己動手寫一下相關的算法,發現好像還是沒那麼容易,後來一下午過去了,試寫了各種方式,但好像都不能很好地相容,特别是0的處理。于是在網上搜尋了一些資料,但好像并沒能很好地解決這個0的問題,找了些相關代碼見下。

來自: http://my.csdn.net/Q718330882(田小濤)(在這并沒想說誰是誰非,隻想為書寫代碼而奮鬥),因為沒有完整的源碼是以自己手動加了類名。

class numberToChanise
{
 public function num2ch($num) //整體讀取轉換
 {
  $num_real = $this->del0($num);//去掉前面的“0”
  $numlen = strlen($num_real);
 
  if($numlen >= 9)//如果滿九位,讀取“億”位
  {
   $y=substr($num_real, -9, 1);
   //echo $y;
   $wsbq = substr($num_real, -8, 4);
   $gsbq = substr($num_real, -4);
   $a = $this->num_r($this->del0($gsbq));
   $b = $this->num_r($this->del0($wsbq))."萬";
   $c = $this->num_r($this->del0($y))."億";
  }
  elseif($numlen <= 8 && $numlen >= 5) //如果大于等于“萬”
  {
   $wsbq = substr($num_real, 0, $numlen-4);
   $gsbq = substr($num_real, -4);
   $a = $this->num_r($this->del0($gsbq));
   $b = $this->num_r($this->del0($wsbq))."萬";
   $c="";
  }
  elseif($numlen <= 4) //如果小于等于“千”
  {
   $gsbq = substr( $num_real, -$numlen);
   $a = $this->num_r($this->del0($gsbq));
   $b="";
   $c="";
  }
  $ch_num = $c.$b.$a;
 
  return $ch_num ;
 }
 
 public function del0($num) //去掉數字段前面的0
 {
  return "".intval($num);
 }
 
 public function n2c($x) //單個數字變漢字
 {
  $arr_n = array("零","一","二","三","四","五","六","七","八","九","十");
  return $arr_n[$x];
 }
 
 
 public function num_r($abcd) //讀取數值(4位)
 {
  $arr= array();
  $str = ""; //讀取後的漢字數值
  $flag = 0; //該位是否為零
  $flag_end = 1; //是否以“零”結尾
  $size_r = strlen($abcd);
  for($i=0; $i<$size_r; $i++)
  {
   $arr[$i] = $abcd{$i};
  }
  $arrlen = count($arr);
  for($j=0; $j<$arrlen; $j++)
  {
   $ch = $this->n2c($arr[$arrlen-1-$j]); //從後向前轉漢字
   
   if($ch == "零" && $flag == 0)
   { //如果是第一個零
    $flag = 1; //該位為零
    $str = $ch.$str; //加入漢字數值字元串
    continue;
   }
   elseif($ch == "零")
   { //如果不是第一個零了
    continue;
   }
   $flag = 0; //該位不是零
   switch($j)
   {
    case 0: $str = $ch; $flag_end = 0; break; //第一位(末尾),沒有以“零”結尾
    case 1: $str = $ch."十".$str; break; //第二位
    case 2: $str = $ch."百".$str; break; //第三位
    case 3: $str = $ch."千".$str; break; //第四位
   }
  }
  if($flag_end == 1) //如果以“零”結尾
  {
   mb_internal_encoding("UTF-8");
   $str = mb_substr($str, 0, mb_strlen($str)-1); //把“零”去掉
  }
  return $str;
 }
 }
 $obj = new numberToChanise();
//數字2009080
echo $obj->num2ch('2009080');
//結果如下:
//二百萬九千零八十(該結果正确)
//數字200980
echo $obj->num2ch('200980');
//二十萬九百八十(不正确)
           

        其實這個算法相容性很小,中間帶0的不能很好處理,很容易出錯,這裡就不繼續列舉了(例如:2000009800590,209800590)。當然我還找了其他算法(好像都不太完整相容),這裡就不一一粘貼出來了。

還是自己想辦法吧,隻能占時将這個問題擱置了,晚上睡覺時也在思考用什麼方式處理0出現的問題比較好,過了兩天不知道從哪裡來的靈感,這種存儲和取出的感覺很強烈,後來采用歸拿總結的方式就能很好的處理數字轉化中文的問題,就是劃分最小單元(四位數為一最小機關組),這裡貼出的代碼沒有處理10(十)這種,不過讀者可以自己處理。其他的就不多說了,上代碼如下。

function number2Chanise($num)
{
    //支援到M級别
$unit = array(
        "",
        "",
        "十",
        "百",
        "千",
        "萬",
        "億",
        "萬億",
        "億億",
        "萬億億",
);
$code = array(
        '0000' => "",
        '0001' => "零x",
        '0010' => "零x十",
        '0011' => "零x十x",
        '0101' => "零x百零x",
        '0100' => "零x百",
        '0110' => "零x百x十",
        '0111' => "零x百x十x",
        1000 => "x千",
        1001 => "x千零x",
        1100 => 'x千x百',
        1010 => 'x千零x十',
        1011 => 'x千零x十x',
        1101 => 'x千x百零x',
        1110 => 'x千x百x十',
        1111 => 'x千x百x十x',
        100  => 'x百',
        101  => 'x百零x',
        110  => 'x百x十',
        111  => 'x百x十x',
        10   => 'x十',
        11   => 'x十x',
        1    => 'x',
        0     => '零'
);
$arr = array(
        0 => "零",
        1 => "一",
        2 => "二",
        3 => "三",
        4 => "四",
        5 => "五",
        6 => "六",
        7 => "七",
        8 => "八",
        9 => "九"
);
    $strNum = (string)$num;
$len = strlen($strNum);
$tmp = "";
$count = ceil($len / 4);
$remain = $len % 4;
if($remain)
{
    $count -= 1;
}
for($i=1;$i <= $count;$i++)
{
    $tmpStr[] = substr($strNum, -4 * $i,4);
}
if($remain)
{
    $tmpStr[] = substr($strNum, -4 * $count - $remain,$remain);
}
$tmpStr = array_reverse($tmpStr);
$c = count($tmpStr);
$strk = "";
$t = $c;
//拆分成數組形式
foreach($tmpStr as $k => $strNum)
{
    $tmp = "";
    $l = 0;
    $len = strlen($strNum);
    for($i=0;$i<$len;$i++)
    {
        if($strNum[$i] == 0)
        {
            $tmp .= 0;
        }
        else $tmp .= 1;
    }
    $ts = $code[$tmp];
    for($i = 0; $i < $len;$i++)
    {
        if($strNum[$i] != 0)
        {
            $ts = substr_replace($ts,$arr[$strNum[$i]],strpos($ts, 'x'),1);
        }
        else $l++;
    }
    if($t > 1)
    {
        if($l < 4)
        {
            $ts .= $unit[$c - $k + 3];
        }
        $t--;
    }
    $strk .= $ts;
}
return $strk;
}
$num = '29000407';
echo number2Chanise($num)


//輸出:二千九百萬零四百零七
但由于這種狀況不知道怎麼讀。
$num = '2900009407';
//輸出:二十九億九千四百零七
           

若是讀作:二十九億零九千四百零七,則上面的代碼需要修正下。

1).在 $code數組中将0000=>''變為0000=>'零';

2).在傳回前加上代碼:return str_replace('零零','零',$strk);

若需要交流,請發送郵件到[email protected]