小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

數(shù)字與中文大寫數(shù)字互轉(zhuǎn)(5千萬億億億億以上的數(shù)字也支持轉(zhuǎn)換)

 小小明代碼實(shí)體 2022-08-09 發(fā)布于廣東

來源是看到知乎上一個(gè)奇葩問題:

image-20220807203558599

任意大小的數(shù)字字符串轉(zhuǎn)中文

其實(shí)10萬以內(nèi)的整數(shù)轉(zhuǎn)換大寫也太簡單,今天我們要實(shí)現(xiàn)的是任意大小的數(shù)字字符串轉(zhuǎn)大寫。

首先我們要保證4位數(shù)以內(nèi)的轉(zhuǎn)換函數(shù),能夠處理各種含"0"的情況,代碼:

import re

ch_num = '零一二三四五六七八九'
units = ' 十百千'


def num2Chinese1(num_str):
    "轉(zhuǎn)換9999以內(nèi)的數(shù)字到大寫"
    result = [ch_num[int(i)]+unit for i,
              unit in zip(reversed(num_str), units)]
    result = "".join(reversed(result))
    result = re.sub("(?:零[十百千])+", "零", result)
    result = re.sub("零+", "零", result)
    result = result.rstrip()
    if result != "零":
        result = result.rstrip("零")
    return result

然后生成測試用例并測試:

import random
import itertools

num_t = "123456789"
cases = []
for length in range(1, 5):
    nums = random.sample(num_t, length)
    cases.append("".join(nums))
    for n in range(1, length+1):
        # n個(gè)0
        for poss in itertools.combinations(range(length), n):
            num = nums.copy()
            for pos in poss:
                num[length-pos-1] = "0"
            num = "".join(num)
            cases.append(num)
for i in cases:
    print(i, num2Chinese1(str(i)))
6 六
0 零
54 五十四
50 五十
04 零四
00 零
831 八百三十一
830 八百三十
801 八百零一
031 零三十一
800 八百
030 零三十
001 零一
000 零
6895 六千八百九十五
6890 六千八百九十
6805 六千八百零五
6095 六千零九十五
0895 零八百九十五
6800 六千八百
6090 六千零九十
0890 零八百九十
6005 六千零五
0805 零八百零五
0095 零九十五
6000 六千
0800 零八百
0090 零九十
0005 零五
0000 零

保證了四位數(shù)的處理函數(shù)沒有問題后,然后就可以開始編寫能夠支持任意位數(shù)的處理函數(shù),并將轉(zhuǎn)換函數(shù)升級到支持小數(shù)。

import math
import re

ch_num = '零一二三四五六七八九'
units = ' 十百千'

def num2Chinese1(num_str):
    "轉(zhuǎn)換9999以內(nèi)的數(shù)字到大寫"
    result = [ch_num[int(i)]+unit for i,
              unit in zip(reversed(num_str), units)]
    result = "".join(reversed(result))
    result = re.sub("(?:零[十百千])+", "零", result)
    result = re.sub("零+", "零", result)
    result = result.rstrip()
    if result != "零":
        result = result.rstrip("零")
    return result


def num2Chinese2(num_str):
    if len(num_str) <= 4:
        result = num2Chinese1(num_str[-4:])
    else:
        result = num2Chinese1(num_str[:-4]) + "萬" + num2Chinese1(num_str[-4:])
    return result.replace("零萬", "零")


def num2Chinese3(num_str):
    num_str = num_str.lstrip("0")
    if not num_str:
        return "零"
    if len(num_str) <= 4:
        return num2Chinese1(num_str)
    e_num = math.ceil(len(num_str)/8)
    result = [num2Chinese2(num_str[-8:])]
    for e_i in range(1, e_num):
        result.append(num2Chinese2(num_str[-8-e_i*8:-e_i*8])+"億"*e_i+" ")
    result = "".join(reversed(result))
    result = re.sub(" (?:零+億+ )+", " 零", result)
    result = re.sub("零(億+)", r"\1", result)
    result = re.sub("零+", "零", result)
    return result.strip("零")


def num2Chinese(num_str):
    num_str = num_str.replace(" ", "").rstrip(".")
    if not re.fullmatch("\d+(?:\.\d+)?", num_str):
        raise Exception("不是一個(gè)數(shù)字字符串")
    if num_str.find(".") != -1:
        num_str1, num_str2 = num_str.split(".", 1)
        return num2Chinese3(num_str1)+" 點(diǎn) "+"".join(ch_num[int(c)] for c in num_str2.rstrip("0"))
    return num2Chinese3(num_str)

下面我們生成千萬億級別的各種具備代表性的測試數(shù)據(jù)進(jìn)行測試:

nums_t = random.choices("123456789", k=16)
num = "".join(nums_t)
print(num, num2Chinese(num))
for zero_len in range(4, 15, 3):
    for s_pos in range(17-zero_len):
        nums = nums_t.copy()
        nums[s_pos:s_pos+zero_len] = "0"*zero_len
        num = "".join(nums)
        print(num, num2Chinese3(num))
9681852243533934 九千六百八十一萬八千五百二十二億 四千三百五十三萬三千九百三十四
0000852243533934 八千五百二十二億 四千三百五十三萬三千九百三十四
9000052243533934 九千萬零五百二十二億 四千三百五十三萬三千九百三十四
9600002243533934 九千六百萬零二十二億 四千三百五十三萬三千九百三十四
9680000243533934 九千六百八十萬零二億 四千三百五十三萬三千九百三十四
9681000043533934 九千六百八十一萬億 四千三百五十三萬三千九百三十四
9681800003533934 九千六百八十一萬八千億 零三百五十三萬三千九百三十四
9681850000533934 九千六百八十一萬八千五百億 零五十三萬三千九百三十四
9681852000033934 九千六百八十一萬八千五百二十億 零三萬三千九百三十四
9681852200003934 九千六百八十一萬八千五百二十二億 零三千九百三十四
9681852240000934 九千六百八十一萬八千五百二十二億 四千萬零九百三十四
9681852243000034 九千六百八十一萬八千五百二十二億 四千三百萬零三十四
9681852243500004 九千六百八十一萬八千五百二十二億 四千三百五十萬零四
9681852243530000 九千六百八十一萬八千五百二十二億 四千三百五十三萬
0000000243533934 二億 四千三百五十三萬三千九百三十四
9000000043533934 九千萬億 四千三百五十三萬三千九百三十四
9600000003533934 九千六百萬億 零三百五十三萬三千九百三十四
9680000000533934 九千六百八十萬億 零五十三萬三千九百三十四
9681000000033934 九千六百八十一萬億 零三萬三千九百三十四
9681800000003934 九千六百八十一萬八千億 零三千九百三十四
9681850000000934 九千六百八十一萬八千五百億 零九百三十四
9681852000000034 九千六百八十一萬八千五百二十億 零三十四
9681852200000004 九千六百八十一萬八千五百二十二億 零四
9681852240000000 九千六百八十一萬八千五百二十二億 四千萬
0000000000533934 五十三萬三千九百三十四
9000000000033934 九千萬億 零三萬三千九百三十四
9600000000003934 九千六百萬億 零三千九百三十四
9680000000000934 九千六百八十萬億 零九百三十四
9681000000000034 九千六百八十一萬億 零三十四
9681800000000004 九千六百八十一萬八千億 零四
9681850000000000 九千六百八十一萬八千五百億 
0000000000000934 九百三十四
9000000000000034 九千萬億 零三十四
9600000000000004 九千六百萬億 零四
9680000000000000 九千六百八十萬億 
0000000000000000 零

目測已經(jīng)覆蓋所有基本情況,下面我們測試一個(gè)帶小數(shù)的超大數(shù)字:

num2Chinese("9506335 25566321 00000000 18945760 00424584 54444444 00000000 00000000 00000000 44487878 00000000 44487878.00980213")
'九百五十萬六千三百三十五億億億億億億億億億億億 二千五百五十六萬六千三百二十一億億億億億億億億億億 零一千八百九十四萬五千七百六十億億億億億億億億 零四十二萬四千五百八十四億億億億億億億 五千四百四十四萬四千四百四十四億億億億億億 零四千四百四十八萬七千八百七十八億億 零四千四百四十八萬七千八百七十八 點(diǎn) 零零九八零二一三'

測試一個(gè)python所支持的最大整數(shù):

num2Chinese("9223372036854775807")
'九百二十二億億 三千三百七十二萬零三百六十八億 五千四百七十七萬五千八百零七'

可以初步判斷能夠正確轉(zhuǎn)換。

中文數(shù)字轉(zhuǎn)數(shù)字

上面我們連如此復(fù)雜的數(shù)字轉(zhuǎn)中文都實(shí)現(xiàn)了,中文轉(zhuǎn)數(shù)字將會變得非常簡單,完整代碼如下:

import re

num_ch = dict(zip('零一二三四五六七八九', map(str, range(10))))
num_units = dict(zip('十百千', range(1, 4)))
num_units[""] = 0


def Chinese2Num1(ch_num_str):
    result = ["0"]*4
    for num, unit in re.findall("([^零十百千])([十百千]|$)", ch_num_str):
        result[num_units[unit]] = num_ch[num]
    result.reverse()
    return "".join(result)


def Chinese2Num2(ch_num_str):
    if ch_num_str.find("萬") != -1:
        ch_num_str1, ch_num_str2 = map(Chinese2Num1, ch_num_str.split("萬", 1))
        return ch_num_str1 + ch_num_str2
    return Chinese2Num1(ch_num_str).zfill(8)


def Chinese2Num3(ch_num_str):
    data = re.findall("[ 零]*([^億]+)(億+|$)", ch_num_str)
    result = ["0"*8]*(len(data[0][1])+1)
    for Chinese_str, e_str in data:
        result[len(e_str)] = Chinese2Num2(Chinese_str)
    result.reverse()
    return "".join(result).lstrip("0")


def Chinese2Num(ch_num_str):
    ch_num_str = ch_num_str.replace(" ", "").rstrip("點(diǎn)零")
    if ch_num_str == "":
        return "0"
    if not re.fullmatch("[零一二三四五六七八九十百千萬億]+(?:點(diǎn)[零一二三四五六七八九十百千萬億]+)?", ch_num_str):
        raise Exception(f"{ch_num_str}存在非法字符,無法轉(zhuǎn)換")
    if ch_num_str.find("點(diǎn)") != -1:
        ch_num_str1, ch_num_str2 = ch_num_str.split("點(diǎn)", 1)
        return Chinese2Num3(ch_num_str1)+"."+"".join(num_ch[c] for c in ch_num_str2).rstrip("0")
    return Chinese2Num3(ch_num_str)

測試一下:

Chinese2Num('九百五十萬六千三百三十五億億億億億億億億億億億 二千五百五十六萬六千三百二十一億億億億億億億億億億 零一千八百九十四萬五千七百六十億億億億億億億億 零四十二萬四千五百八十四億億億億億億億 五千四百四十四萬四千四百四十四億億億億億億 零四千四百四十八萬七千八百七十八億億 零二百六十五萬三千零二十一 點(diǎn) 零零九八零二一三')
'95063352556632100000000189457600042458454444444000000000000000000000000444878780000000002653021.00980213'

測試

接下面我們可以讓兩個(gè)轉(zhuǎn)換函數(shù)互相轉(zhuǎn)換,互相驗(yàn)證:

for i in range(0, 720368547758, 900025):
    a = str(i)
    ch_num_str = num2Chinese(a)
    b = Chinese2Num(ch_num_str)
    if a != b:
        print(a, ch_num_str, b)
        break
else:
    print("未發(fā)現(xiàn)轉(zhuǎn)換錯(cuò)誤!")

經(jīng)過半分鐘的時(shí)間,已經(jīng)初步互相驗(yàn)證完成,未發(fā)現(xiàn)轉(zhuǎn)換失敗的數(shù)據(jù)。

彩蛋:windows文件名排序

如何快速實(shí)現(xiàn)windows文件名的排序效果呢?示例代碼:

files = os.listdir()
files.sort(key=lambda s: [(s, int(n)) for s, n in re.findall('(\D+)(\d+)', f'a{s}0')])

要支持能夠根據(jù)中文大寫數(shù)字排序,也只需要先將大寫數(shù)字都轉(zhuǎn)換為普通數(shù)字再用上述方法排序即可。

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多