出题:如何优雅转换大写数字? 19 转成 十九

2017-09-06 11:43:32 +08:00
 jin5354
天杀的需求竟然要展示大写数字,我要和产品搏命

0 -> 零
5 -> 五
19 -> 十九
20 -> 二十
21 -> 二十一
100 -> 一百
5817 次点击
所在节点    程序员
46 条回复
ShiHou
2017-09-06 14:06:13 +08:00
debuggerx
2017-09-06 14:13:52 +08:00
@debuggerx 只记了记不住的正则替换部分,完整方法和测试如下:

public class Int2Big {
static String int2big(int src) {
final String num[] = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
final String unit[] = {"圆", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟"};
String dst = "";
int count = 0;
while (src > 0) {
dst = (num[src % 10] + unit[count]) + dst;
src = src / 10;
count++;
}
return dst.replaceAll("零[仟佰拾]", "零").replaceAll("零+万", "万")
.replaceAll("零+亿", "亿").replaceAll("亿万", "亿零")
.replaceAll("零+", "零").replaceAll("零圆", "圆");
}

public static void main(String[] args) {
System.out.println(int2big(123004506)); //-->壹亿贰仟叁佰万肆仟伍佰零陆圆
System.out.println(int2big(6523464)); //-->陆佰伍拾贰万叁仟肆佰陆拾肆圆
System.out.println(int2big(1001000100));//-->壹拾亿零壹佰万零壹佰圆
System.out.println(int2big(808)); //-->捌佰零捌圆
}
}
haohaozaici
2017-09-06 14:22:40 +08:00
https://gist.github.com/binjoo

记得给电费。。。
haohaozaici
2017-09-06 14:23:21 +08:00
https://gist.github.com/binjoo/6028263

记得给电费。。。 这个。。。
BlackBerry
2017-09-06 14:24:55 +08:00
0 零 〇
ipconfiger
2017-09-06 14:29:08 +08:00
Python 一行的实现方式 之一:
"".join(list(reversed(["%s%s" % (["", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"][int(list(reversed(seq))[idx])], unit) for idx, unit in enumerate(reversed(reduce(list.__add__, [ ["仟", "佰", "拾", big_unit] for big_unit in ["兆", "亿", "万", ""]]))) if idx<len(seq)])))

能实现千兆以下数字的大写转换

But 并没有什么卵用, 为了实现一行写下, 牺牲了效率, 这是其一, 可读性差, 这是其二, 且, 对于 19 => 拾玖 这种省略转换, 并不支持, 会转换成 壹拾玖 所以, 不要这么干
mengyaoss77
2017-09-06 14:32:08 +08:00
@ipconfiger #26 对于发票上面写大写的话 好像 19 就需要写成 一十九吧
wenzhoou
2017-09-06 14:33:13 +08:00
19 转成 十九 优雅还是 一十九 优雅。119 呢?
ipconfiger
2017-09-06 14:37:26 +08:00
@mengyaoss77 还有别的问题, 比如中间全是 0 的时候省略的问题
ipconfiger
2017-09-06 14:55:09 +08:00
再改一版:
lambda seq:"".join(list(reversed([("%s%s" % (["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"][int(list(reversed(seq))[idx])], unit)) if idx>0 or int(list(reversed(seq))[1]) else ("零%s" % ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"][int(list(reversed(seq))[idx])]) for idx, unit in enumerate(reversed(reduce(list.__add__, [ ["仟", "佰", "拾", big_unit] for big_unit in ["兆", "亿", "万", ""]]))) if idx<len(seq) and int(list(reversed(seq))[idx])>0])))

支持了中间一堆 0 的情况, but, 代码完全没有可读性了, Orz
a87150
2017-09-06 14:59:20 +08:00
@ipconfiger from functools import reduce 我信了你的邪
Kisesy
2017-09-06 15:04:45 +08:00
@ShiHou 你这个有点像 youtube 上关注数的显示方式,太机械
比如 2000105 会翻成 二百万一百五,掉了中间的零还行,后面的也掉了,读出来成了 2000150
应该是 二百万零一百零五
ipconfiger
2017-09-06 15:06:11 +08:00
@a87150 并没有啊, 不信你试试, 2.7 哈
ShiHou
2017-09-06 15:21:00 +08:00
@Kisesy 更新了下。
lixiangzaizheli
2017-09-06 15:34:24 +08:00
百度不会吗
sirm2z
2017-09-06 15:37:23 +08:00
js 自带:

```
var number = 1000
number.toLocaleString('zh-Hans-CN-u-nu-hanidec')
```
LancerEvo
2017-09-06 15:46:26 +08:00
Kisesy
2017-09-06 15:51:53 +08:00
@ShiHou 好多了,虽然还有不少数掉零,读起来不顺,不过念出来不至于错了,不错
Kisesy
2017-09-06 15:55:24 +08:00
@ShiHou 还有一个.. 20001 翻成了 二万一
ipconfiger
2017-09-06 16:04:06 +08:00
第二种方法:

lambda seq: "".join(reversed(["".join([prefix, ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"][int(num)], unit]) for prefix, num, unit in [["零", tp[0], tp[1]] if idx<(len(seq)-1) and int(seq[len(seq)-idx-2])<1 else ["", tp[0], tp[1]] for idx, tp in enumerate(zip(list(reversed(seq)) , list(reversed(reduce(list.__add__, [ ["仟", "佰", "拾", big_unit] for big_unit in ["兆", "亿", "万", ""]]))))) if int(tp[0])]]))

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/388568

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX