写了一个类把数字转换成英语或是汉语表达

- 中国WEB开发者网络 (http://www.webasp.net)
-- 技术教程 (http://www.webasp.net/article/)
--- 写了一个类把数字转换成英语或是汉语表达 (http://www.webasp.net/article/27/26901.htm)
-- 作者:未知
-- 发布日期: 2005-10-18
今天总算有点空,抽时间写了一个类,把数字转换成英语或汉语表达,用法很简单。下面是代码及演示:


文件:textnumber.class.php
[code:1:9ee57400d9]
<?php
if(!defined('_IN_APP')) exit;

class TextNumber
{
var $resource = null;
var $number = 0;
var $groupLength = 3;
var $wordSeperated = true;

function setResource($resource = null){
$this->resource = $resource;
}

function setNumber($number){
$this->number = $number;
}

function setWordSeperated($seperated){
$this->wordSeperated = $seperated;
}

function split_number(&$sign, &$int, &$fraction){
list($int, $fraction) = explode('.', $this->number);
$sign = '';
if ($int{0} == '-'){
$sign = '-';
$int = substr($int, 1);
}
$int = preg_replace('/[^0-9]/', '', $int);
$int = preg_replace('/^[0]+/', '', $int);
$int = ($int == '')? '0' : $int;
$fraction = preg_replace('/[^0-9]/', '', $fraction);
if (preg_match('/^0*$/', $fraction))
$fraction = '';
}

function split_group($int){
$int = strrev($int);
$int = chunk_split($int, $this->groupLength, ',');
$int = substr(strrev($int), 1);
return $int;
}

function addSeperator($word = ''){
if ($this->wordSeperated){
if ($word != '')
$word .= ' ';
}
return $word;
}

function trans_sign($sign){
if ($sign == '-'){
if (isset($this->resource['group']['-']))
return $this->addSeperator($this->resource['group']['-']);
else
return '-';
}else{
return '';
}
}

function trans_int($int){
return $this->split_group($int);
}

function trans_dec_point($fraction = 0){
if (isset($this->resource['group']['.'])){
$point = $this->resource['group']['.'];
$point = $this->addSeperator($point);
}else{
$point = '.';
}
return ($fraction == 0)? '' : $point;
}

function trans_fraction($fraction){
return ($fraction == 0)? '' : $fraction;
}

function getText(){
$this->split_number($sign, $int, $fraction);
$ssign = $this->trans_sign($sign);
$sint = $this->trans_int($int);
$spoint = $this->trans_dec_point($fraction);
$sfrac = $this->trans_fraction($fraction);
return trim($ssign.$sint.$spoint.$sfrac);
}
}

//---------------------------------------------------------------------------

class TextNumberFactory
{
function &createTextNumber($lang = 'en_US'){
$class = 'TextNumber_'.$lang;
if (class_exists($class)){
$textnumber =& new $class;
if (!is_subclass_of($textnumber, 'TextNumber')){
unset($textnumber);
$textnumber =& new TextNumber;
}
}else{
$textnumber =& new TextNumber;
}
return $textnumber;
}
}

//---------------------------------------------------------------------------

class TextNumber_en_US extends TextNumber
{
function TextNumber_en_US(){
$this->__construct();
}

function __construct(){
$this->resource = array(
'group_int' => array(
0 => 'zero',
1 => 'one',
2 => 'two',
3 => 'three',
4 => 'four',
5 => 'five',
6 => 'six',
7 => 'seven',
8 => 'eight',
9 => 'nine',
10 => 'ten',
11 => 'eleven',
12 => 'twelve',
13 => 'thirteen',
14 => 'fourteen',
15 => 'fifteen',
16 => 'sixteen',
17 => 'seventeen',
18 => 'eighteen',
19 => 'nineteen',
20 => 'twenty',
30 => 'thirty',
40 => 'forty',
50 => 'fifty',
60 => 'sixty',
70 => 'seventy',
80 => 'eighty',
90 => 'ninety',
100 => 'hundred'
),
'group' => array(
0 => '',
1 => 'thousand',
2 => 'million',
3 => 'billion',
4 => 'trillion',
'-' => 'minus',
'.' => 'point',
'group_number' => 4
)
);
}

function trans_group_int($group_int){
$trans =& $this->resource['group_int'];
$h = intval(floor($group_int / 100));
$r = $group_int % 100;
$sh = '';
if ($h != 0){
$sh = $this->addSeperator($trans[$h]);
$sh .= $this->addSeperator($trans[100]);
}
$sr = '';
if ($r != 0){
if ($r <= 20){
$sr = $this->addSeperator($trans[$r]);
}else{
$rr = $r % 10;
$rt = $r - $rr;
if ($rr == 0){
$sr = $this->addSeperator($trans[$r]);
}else{
$sr = $trans[$rt];
$sr .= '-'.$this->addSeperator($trans[$rr]);
}
}
}
$ss = '';
if ($sh != '' && $sr != ''){
$ss = $sh. $this->addSeperator('and') .$sr;
}else{
$ss = $sh.$sr;
}
return $ss;
}

function trans_int($int){
if ($int <= 20) return $this->addSeperator($this->resource['group_int'][intval($int)]);
$groups = explode(',', $this->split_group($int));
$groups = array_reverse($groups);
$cgroup = $this->resource['group']['group_number'];
$result = '';
foreach($groups as $key => $group_int){
$sgroup = '';
$k = $key % $cgroup;
if ((int)$group_int != 0){
$sgroup = $this->resource['group'][$k];
$sgroup = $this->addSeperator($sgroup);
$sgroup = $this->trans_group_int($group_int).$sgroup;
}
$ss = '';
if ($k == 0 && $key >= $cgroup)
$ss = $this->addSeperator($this->resource['group'][$cgroup]);
$result = $sgroup.$ss.$result;
}
return $result;
}

function trans_fraction($fraction){
if ($fraction == '') return '';
$fraction = preg_replace('/([0-9])/e', '$this->addSeperator($this->resource[\'group_int\'][\\1])', $fraction);
return $fraction;
}

function getText($isupper = false){
$text = parent::getText();
if ($isupper){
$text = strtoupper($text);
}
return $text;
}
}

//---------------------------------------------------------------------------

class TextNumber_zh_CN extends TextNumber
{
var $groupLength = 4;
var $wordSeperated = false;

function TextNumber_zh_CN(){
$this->__construct();
}

function __construct(){
$this->resource = array(
'group_int' => array(
0 => '零',
1 => '一',
2 => '二',
3 => '三',
4 => '四',
5 => '五',
6 => '六',
7 => '七',
8 => '八',
9 => '九'
),
'group_int_digital' => array(
0 => '',
1 => '十',
2 => '百',
3 => '千'
),
'group' => array(
0 => '',
1 => '万',
2 => '亿',
3 => '兆',
'-' => '负',
'.' => '点',
'group_number' => 3
),
'trans_upper' => array(
'一' => '壹',
'二' => '贰',
'三' => '叁',
'四' => '肆',
'五' => '伍',
'六' => '陆',
'七' => '柒',
'八' => '捌',
'九' => '玖',
'十' => '拾',
'百' => '佰',
'千' => '仟'
)
);
}

function trans_group_int($group_int){
$si = strrev($group_int);
$ss = '';
$i = 0;
if (preg_match('/^([0]+)/', $si, $matches)){
$i = strlen($matches[1]);
}
for(; $i < strlen($si); $i++){
$s = ($si{$i} == '0')? '' : $this->addSeperator($this->resource['group_int_digital'][$i]);
$ss = $si{$i}.$s.$ss;
}
return $ss;
}

function trans_int($int){
if ($int < 10) return $this->addSeperator($this->resource['group_int'][intval($int)]);
/*
if ($int < 20){
$sint = $this->addSeperator($this->resource['group_int'][10]);
$sint .= $this->addSeperator($this->resource['group_int'][$int % 10]);
return $sint;
}
*/
$groups = explode(',', $this->split_group($int));
$groups = array_reverse($groups);
$cgroup = $this->resource['group']['group_number'];
$result = '';
foreach($groups as $key => $group_int){
$sgroup = '';
$k = $key % $cgroup;
if ((int)$group_int != 0){
$sgroup = $this->resource['group'][$k];
$sgroup = $this->addSeperator($sgroup);
$sgroup = $this->trans_group_int($group_int).$sgroup;
if ($k != 0 && substr($group_int, -1) == '0')
$sgroup .= '0';
}else{
$sgroup = '0';
}
$ss = '';
if ($k == 0 && $key >= $cgroup){
$ss = $this->addSeperator($this->resource['group'][$cgroup]);
if (substr($group_int, -1) == '0')
$ss .= '0';
}
$result = $sgroup.$ss.$result;
}
$result = preg_replace('/[0]+/', '0', $result);
$result = preg_replace('/(^|[^1-9])0([^1-9]|$)/', '\\1\\2', $result);
$result = preg_replace('/([0-9])/e', '$this->addSeperator($this->resource[\'group_int\'][\\1])', $result);
return $result;
}

function trans_fraction($fraction){
if ($fraction == '') return '';
$fraction = preg_replace('/([0-9])/e', '$this->addSeperator($this->resource[\'group_int\'][\\1])', $fraction);
return $fraction;
}

function getText($isupper = false){
$text = parent::getText();
if ($isupper && isset($this->resource['trans_upper'])){
$text = strtr($text, $this->resource['trans_upper']);
}
return $text;
}
}
?>
[/code:1:9ee57400d9]


文件:test.php
[code:1:9ee57400d9]
<?php
require_once ('textnumber.class.php');

$lang = array('en_us', 'zh_cn');
$number = '-00123020456006010335678901201.00086789';

echo "$number<br><br>\n";
for($i = 0; $i < count($lang); $i++){
$textnumber =& TextNumberFactory::createTextNumber($lang[$i]);
$textnumber->setNumber($number);
$sNormal = $textnumber->getText(false);
$sUpper = $textnumber->getText(true);
echo "$sNormal<br><br>\n";
echo "$sUpper<br><br>\n";
}
?>
[/code:1:9ee57400d9]

输出结果:
[code:1:9ee57400d9]
-00123020456006010335678901201.00086789

minus one hundred and twenty-three trillion twenty billion four hundred and fifty-six million six thousand ten trillion three hundred and thirty-five billion six hundred and seventy-eight million nine hundred and one thousand two hundred and one point zero zero zero eight six seven eight nine

MINUS ONE HUNDRED AND TWENTY-THREE TRILLION TWENTY BILLION FOUR HUNDRED AND FIFTY-SIX MILLION SIX THOUSAND TEN TRILLION THREE HUNDRED AND THIRTY-FIVE BILLION SIX HUNDRED AND SEVENTY-EIGHT MILLION NINE HUNDRED AND ONE THOUSAND TWO HUNDRED AND ONE POINT ZERO ZERO ZERO EIGHT SIX SEVEN EIGHT NINE

负一百二十三兆零二百零四亿五千六百万零六千零一十兆零三千三百五十六亿七千八百九十万零一千二百零一点零零零八六七八九

负壹佰贰拾叁兆零贰佰零肆亿伍仟陆佰万零陆仟零壹拾兆零叁仟叁佰伍拾陆亿柒仟捌佰玖拾万零壹仟贰佰零壹点零零零捌陆柒捌玖
[/code:1:9ee57400d9]

由于本人比较懒,所以都没有写注释,不过相信懂OO的人都看得懂。用法极简单,就按test.php中的写法照套就可以了,就是一二三的三步曲,第一步从类工厂中建立一个对象,第二步对该对象赋一个数字字符串待转换,第三步就是取得转换后的文字并输出了。在textnumber.class.php中,有一个基类,一个类工厂,两个派生类(英语与汉语)。至于说它们怎么协调工作,大家自己看看吧。

webasp.net