V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
jin5354
V2EX  ›  程序员

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

  •  
  •   jin5354 ·
    jin5354 · 2017-09-06 11:43:32 +08:00 · 5649 次点击
    这是一个创建于 2417 天前的主题,其中的信息可能已经有所发展或是发生改变。
    天杀的需求竟然要展示大写数字,我要和产品搏命

    0 -> 零
    5 -> 五
    19 -> 十九
    20 -> 二十
    21 -> 二十一
    100 -> 一百
    第 1 条附言  ·  2017-09-06 12:55:10 +08:00
    我知道有轮子。
    本来是想看看这种繁琐的小需求,有没人有搞出优雅姿势让我学习学习(比如 codewar 上的炫酷单行题解),所以说是出题。
    46 条回复    2017-09-07 11:25:19 +08:00
    Light3
        1
    Light3  
       2017-09-06 11:45:08 +08:00   ❤️ 3
    https://github.com/wilon/php-number2chinese

    一会给下我帮你搜的电费
    xfspace
        2
    xfspace  
       2017-09-06 11:46:02 +08:00 via Android
    数字前加个“大写”

    大写 0
    大写 1

    没毛病
    Famio
        3
    Famio  
       2017-09-06 11:50:30 +08:00
    上古:<big>1234567890</big>
    Sanko
        4
    Sanko  
       2017-09-06 11:55:11 +08:00 via Android
    记得给二楼转一下电费
    顺带给我发一下流量费
    zonyitoo
        5
    zonyitoo  
       2017-09-06 11:59:22 +08:00
    自己写一个到底有多难?
    misaka19000
        6
    misaka19000  
       2017-09-06 12:01:33 +08:00 via Android
    赔我点进来的流量费
    asj
        7
    asj  
       2017-09-06 12:14:12 +08:00
    这个自己写写也就一两个小时吧
    maplerecall
        8
    maplerecall  
       2017-09-06 12:24:14 +08:00 via Android
    @asj 这个很简单吧,十分钟就够了…
    yuanfnadi
        9
    yuanfnadi  
       2017-09-06 12:35:08 +08:00
    这种普遍的需求,git 上任何语言肯定有轮子。
    debuggerx
        10
    debuggerx  
       2017-09-06 12:57:50 +08:00   ❤️ 1

    当年自学 java 的笔记……
    虽然早就不写 java 了,这个小本子却总是习惯性地装在包里。。。
    gstqc
        11
    gstqc  
       2017-09-06 13:00:30 +08:00 via iPhone
    提这需求不是很正常吗?
    再说调个轮子也就两行代码
    jianleer
        12
    jianleer  
       2017-09-06 13:09:38 +08:00
    jianleer
        13
    jianleer  
       2017-09-06 13:11:58 +08:00
    看错了,以为是日常使用,请忽略楼上截图
    ipconfiger
        14
    ipconfiger  
       2017-09-06 13:13:55 +08:00
    大写应该是 拾玖 才对吧
    kslr
        15
    kslr  
       2017-09-06 13:24:00 +08:00
    arr [
    0 = 零
    1 = 壹
    2 = 贰
    3 = 叁
    ]

    第 1 天
    第 arr[1]天
    aksoft
        16
    aksoft  
       2017-09-06 13:40:30 +08:00
    @debuggerx 你这个本子 我喜欢
    8Cangtou
        17
    8Cangtou  
       2017-09-06 13:41:04 +08:00
    reduce~~~~map~~~~
    silymore
        18
    silymore  
       2017-09-06 13:44:46 +08:00 via iPhone
    可以来个 web api
    ipconfiger
        19
    ipconfiger  
       2017-09-06 14:00:47 +08:00
    这个单行搞不出来, 就算你憋着搞出来了, 一是无法容错, 二是无法调试, 三是没有可读性 所以一点实用价值也没有
    AlisterTT
        20
    AlisterTT  
       2017-09-06 14:04:52 +08:00
    alfred 有个 workflow 有这功能的,你可以参考一下 https://github.com/yourtion/Alfred_NumToCny
    ShiHou
        21
    ShiHou  
       2017-09-06 14:06:13 +08:00
    debuggerx
        22
    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
        23
    haohaozaici  
       2017-09-06 14:22:40 +08:00
    https://gist.github.com/binjoo

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

    记得给电费。。。 这个。。。
    BlackBerry
        25
    BlackBerry  
       2017-09-06 14:24:55 +08:00
    0 零 〇
    ipconfiger
        26
    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
        27
    mengyaoss77  
       2017-09-06 14:32:08 +08:00
    @ipconfiger #26 对于发票上面写大写的话 好像 19 就需要写成 一十九吧
    wenzhoou
        28
    wenzhoou  
       2017-09-06 14:33:13 +08:00 via Android
    19 转成 十九 优雅还是 一十九 优雅。119 呢?
    ipconfiger
        29
    ipconfiger  
       2017-09-06 14:37:26 +08:00
    @mengyaoss77 还有别的问题, 比如中间全是 0 的时候省略的问题
    ipconfiger
        30
    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
        31
    a87150  
       2017-09-06 14:59:20 +08:00
    @ipconfiger from functools import reduce 我信了你的邪
    Kisesy
        32
    Kisesy  
       2017-09-06 15:04:45 +08:00
    @ShiHou 你这个有点像 youtube 上关注数的显示方式,太机械
    比如 2000105 会翻成 二百万一百五,掉了中间的零还行,后面的也掉了,读出来成了 2000150
    应该是 二百万零一百零五
    ipconfiger
        33
    ipconfiger  
       2017-09-06 15:06:11 +08:00
    @a87150 并没有啊, 不信你试试, 2.7 哈
    ShiHou
        34
    ShiHou  
       2017-09-06 15:21:00 +08:00
    @Kisesy 更新了下。
    lixiangzaizheli
        35
    lixiangzaizheli  
       2017-09-06 15:34:24 +08:00
    百度不会吗
    sirm2z
        36
    sirm2z  
       2017-09-06 15:37:23 +08:00
    js 自带:

    ```
    var number = 1000
    number.toLocaleString('zh-Hans-CN-u-nu-hanidec')
    ```
    LancerEvo
        37
    LancerEvo  
       2017-09-06 15:46:26 +08:00
    Kisesy
        38
    Kisesy  
       2017-09-06 15:51:53 +08:00
    @ShiHou 好多了,虽然还有不少数掉零,读起来不顺,不过念出来不至于错了,不错
    Kisesy
        39
    Kisesy  
       2017-09-06 15:55:24 +08:00
    @ShiHou 还有一个.. 20001 翻成了 二万一
    ipconfiger
        40
    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])]]))
    szopen
        41
    szopen  
       2017-09-06 16:35:01 +08:00
    ipconfiger
        42
    ipconfiger  
       2017-09-06 21:38:21 +08:00   ❤️ 1
    终极一行写法, 解决了大部分已知问题, 并且支持输入数字

    lambda number_string: (lambda seq: "".join(reversed(["".join(["".join([p, ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"][int(n)], u]) for p, n, u in reversed(s[0])]) + s[1] for s in [(lambda sub_seq: [[["零", tp[0], tp[1]] if i<(len(sub_seq)-1) and int(sub_seq[i+1])< 1 else ["", tp[0], tp[1]] for i, tp in enumerate(zip(sub_seq, ["", "拾", "佰", "仟"])) if int(tp[0])], unit])(seq[idx*4:(idx+1)*4] or []) for idx, unit in enumerate(["", "万", "亿", "兆", "京"])] if s[0]])))("".join(reversed(str(number_string))))
    natforum
        43
    natforum  
       2017-09-06 22:01:55 +08:00
    @debuggerx 大佬,收徒吗
    zhx1991
        44
    zhx1991  
       2017-09-06 23:35:31 +08:00
    一百二 120
    两百零二 202
    两百二 220
    asj
        45
    asj  
       2017-09-07 08:21:38 +08:00
    @maplerecall
    我没做过,不过练习过几次数字转成英文的。反正我自己的水平是需要 1,2 个小时的。
    转汉字可能细节上有不同,我应该还是达不到十分钟完全解决的。
    calebx
        46
    calebx  
       2017-09-07 11:25:19 +08:00
    https://github.com/calebx/number_to_cn
    这是我多年前搞的。

    可以看看,其实挺复杂的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5365 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 08:58 · PVG 16:58 · LAX 01:58 · JFK 04:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.