如何解决将阿拉伯数字转换为中国金融数字
我正在尝试在函数式编程中创建一个函数,该函数将接收正常的Int值并将其转换为财务中文数字,并返回一个String,例如:301 =三百零一。首先,我有两张地图,一张地图的数字从0到9,另一张地图的指数从10到1000000。
val digits: Map[Int,String] = Map(0 -> "〇",1 -> "壹",2 -> "貳",3 -> "參",4 -> "肆",5 -> "伍",6 -> "陸",7 -> "柒",8 -> "捌",9 -> "玖");
val exponent: Map[Int,String] = Map(1 -> "",10 -> "拾",100 -> "佰",1000 -> "仟",10000 -> "萬",100000 -> "億",1000000 -> "兆");
对于不认识的人,这里对中文数字的工作原理进行一些解释。如果您已经知道,请不要阅读本段内容。在中文数字中,当您要写一个大数字(例如5000)时,请写下5和1000符号(伍仟)以表示您要乘以5 *1000。如果您有539,则为5 100 + 3 10 +9。这是伍佰参拾玖。最后,如果乘法之间的数字为0,则乘数无关紧要,在其他字符之间只写一个0。例如:501 = 5 100 +1。这是伍佰〇壹。最后一个校准示例:50103 = 5 10000 + 1 * 100 +3。这是伍万〇壹佰〇参。
所以我能做的是以下事情:
def format(unit: Int): String = {
val l = unit.toString.map(_.asDigit).toList
if(l.isEmpty) ""
else if(l.tail.isEmpty) digits(l.head)
else digits(l.head) + format(l.tail.mkString.toInt)
}
这将字符一一翻译。例如:
format(135) "壹參伍"
我不知道如何继续。
解决方法
如果我正确理解了您的问题,则可以执行以下操作:
def toChineseFinancial(number: Int): String = {
val digits = number.toString.iterator.map(_.asDigit).toList
val length = digits.length
val exponents = List.tabulate(length)(n => math.pow(10,n).toInt)
val (sb,_) =
digits
.iterator
.zip(exponents.reverseIterator)
.foldLeft(new collection.mutable.StringBuilder(length * 2) -> false) {
case ((sb,flag),(digit,exp)) =>
if (digit == 0) sb -> true
else if (flag) sb.append("〇").append(digitsMap(digit)).append(exponentsMap(exp)) -> false
else sb.append(digitsMap(digit)).append(exponentsMap(exp)) -> false
}
sb.result()
}
您可以看到它正在运行here。
注意:我使用mutable.StringBuilder
是因为构建字符串有点昂贵,但是如果您想避免任何类型的可变性,则可以轻松地将其替换为普通的字符串 。
我将使用简单的exponents
来扩展case class
地图的值,以涵盖:
- 数量级1、10、10 ^ 2,...,10 ^ 12
- “万”(10 ^ 4),“亿”(10 ^ 8)和“兆”(10 ^ 12)的10、100和1000'
如下所示:
case class CNU(unit: String,factor: Int)
val exponents: Map[Long,CNU] = Map(
1L -> CNU("",1),10L -> CNU("拾",100L -> CNU("佰",1000L -> CNU("仟",10000L ->CNU("萬",100000L -> CNU("萬",10),1000000L -> CNU("萬",100),10000000L -> CNU("萬",1000),100000000L -> CNU("億",1000000000L -> CNU("億",10000000000L -> CNU("億",100000000000L -> CNU("億",1000000000000L -> CNU("兆",10000000000000L -> CNU("兆",100000000000000L -> CNU("兆",1000000000000000L -> CNU("兆",1000)
)
创建方法:
val digits: Map[Int,String] = Map(
0 -> "〇",1 -> "壹",2 -> "貳",3 -> "參",4 -> "肆",5 -> "伍",6 -> "陸",7 -> "柒",8 -> "捌",9 -> "玖"
)
def toChineseNumber(num: Long): String = {
val s = num.toString
val ds = s.map(_.asDigit).zip(s.length-1 to 0 by -1)
ds.foldRight(List.empty[String],0){ case ((d,i),(accList,dPrev)) =>
val cnu = exponents(math.pow(10,i).toLong)
val digit =
if (d == 0) {
if (dPrev != 0 || num == 0) digits(d) else ""
}
else
digits(d)
val unit =
if (d == 0)
""
else {
if (cnu.factor == 1) cnu.unit else exponents(cnu.factor).unit
}
((digit + unit) :: accList,d)
}.
_1.mkString
}
请注意,方法foldRight
用于从右向左遍历和处理输入数字,而元组累加器中的dPrev
用于在迭代中携带数字以处理重复的0。
测试:
toChineseNumber(50)
// res1: String = 伍拾
toChineseNumber(30001)
// res2: String = 參萬〇壹
toChineseNumber(1023405)
// res3: String = 壹佰〇貳萬參仟肆佰〇伍
toChineseNumber(2233007788L)
// res4: String = 貳拾貳億參仟參佰〇柒仟柒佰捌拾捌
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。