V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
jin5354
V2EX  ›  程序员

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

  •  
  •   jin5354 ·
    jin5354 · Sep 6, 2017 · 6385 views
    This topic created in 3155 days ago, the information mentioned may be changed or developed.
    天杀的需求竟然要展示大写数字,我要和产品搏命

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

    一会给下我帮你搜的电费
    xfspace
        2
    xfspace  
       Sep 6, 2017 via Android
    数字前加个“大写”

    大写 0
    大写 1

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

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

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

    记得给电费。。。
    haohaozaici
        24
    haohaozaici  
       Sep 6, 2017
    https://gist.github.com/binjoo/6028263

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

    ```
    var number = 1000
    number.toLocaleString('zh-Hans-CN-u-nu-hanidec')
    ```
    Kisesy
        38
    Kisesy  
       Sep 6, 2017
    @ShiHou 好多了,虽然还有不少数掉零,读起来不顺,不过念出来不至于错了,不错
    Kisesy
        39
    Kisesy  
       Sep 6, 2017
    @ShiHou 还有一个.. 20001 翻成了 二万一
    ipconfiger
        40
    ipconfiger  
       Sep 6, 2017
    第二种方法:

    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])]]))
    ipconfiger
        42
    ipconfiger  
       Sep 6, 2017   ❤️ 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  
       Sep 6, 2017
    @debuggerx 大佬,收徒吗
    zhx1991
        44
    zhx1991  
       Sep 6, 2017
    一百二 120
    两百零二 202
    两百二 220
    asj
        45
    asj  
       Sep 7, 2017
    @maplerecall
    我没做过,不过练习过几次数字转成英文的。反正我自己的水平是需要 1,2 个小时的。
    转汉字可能细节上有不同,我应该还是达不到十分钟完全解决的。
    calebx
        46
    calebx  
       Sep 7, 2017
    https://github.com/calebx/number_to_cn
    这是我多年前搞的。

    可以看看,其实挺复杂的
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2845 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 115ms · UTC 00:02 · PVG 08:02 · LAX 17:02 · JFK 20:02
    ♥ Do have faith in what you're doing.