首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将阿拉伯数字转换为中文财务数字

将阿拉伯数字转换为中文财务数字
EN

Stack Overflow用户
提问于 2020-10-22 14:59:53
回答 2查看 187关注 0票数 1

我正在尝试在函数式编程中创建一个函数,该函数接收一个正常的Int值,并将其转换为金融中文数字并返回一个字符串,用于exaple: 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‘s,那么不管它们是多少,在其他字符之间只写一个0。例如: 501 = 5_100 + 1,这是伍佰0壹。最后一个例子是: 50103 = 5_10000 + 1*100 + 3,这是伍萬0壹佰0參。

所以我能做的是:

代码语言:javascript
复制
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)
}

这是一个接一个地翻译字符。例如:

代码语言:javascript
复制
format(135) "壹參伍"

我不知道怎么继续下去。

EN

回答 2

Stack Overflow用户

发布于 2020-10-22 16:18:20

如果我正确理解了你的问题,你可以这样做:

代码语言:javascript
复制
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()
}

您可以看到它运行这里

注意:我使用mutable.StringBuilder是因为构建Strings有点昂贵,但是如果您想避免任何类型的可更改性,您可以轻松地用一个普通的字符串替换它。

票数 1
EN

Stack Overflow用户

发布于 2020-10-23 06:19:20

我将使用一个简单的exponents映射来扩展它的值,包括:

  • 1,10,10^2,.,10^12级数
  • "萬“(10^4)、"億”(10^8)和"兆“(10^12)的10's、100 s和1000 s

如下所示:

代码语言:javascript
复制
case class CNU(unit: String, factor: Int)

val exponents: Map[Long, CNU] = Map(
  1L -> CNU("", 1),
  10L -> CNU("拾", 1),
  100L -> CNU("佰", 1),
  1000L -> CNU("仟", 1),
  10000L ->CNU("萬", 1),
  100000L -> CNU("萬", 10),
  1000000L -> CNU("萬", 100),
  10000000L -> CNU("萬", 1000),
  100000000L -> CNU("億", 1),
  1000000000L -> CNU("億", 10),
  10000000000L -> CNU("億", 100),
  100000000000L -> CNU("億", 1000),
  1000000000000L -> CNU("兆", 1),
  10000000000000L -> CNU("兆", 10),
  100000000000000L -> CNU("兆", 100),
  1000000000000000L -> CNU("兆", 1000)
)

创建方法:

代码语言:javascript
复制
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's。

测试它:

代码语言:javascript
复制
toChineseNumber(50)
// res1: String = 伍拾

toChineseNumber(30001)
// res2: String = 參萬〇壹

toChineseNumber(1023405)
// res3: String = 壹佰〇貳萬參仟肆佰〇伍

toChineseNumber(2233007788L)
// res4: String = 貳拾貳億參仟參佰〇柒仟柒佰捌拾捌
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64485015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档