首页 > 试题广场 >

阿拉伯数字转中文

[编程题]阿拉伯数字转中文
  • 热度指数:2137 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个整数,请你输出这个整数的中文读法。
例如:
153,读作一百五十三
103,读作一百零三
1003,读作一千零三

数据范围:
示例1

输入

114514

输出

"十一万四千五百一十四"
示例2

输入

1000

输出

"一千"
示例3

输入

-1035

输出

"负一千零三十五"
#include <bits/stdc++.h>

using namespace std;

string suffixs[4]={"","万","亿"};
string dig_name[4]={"","十","百","千"};
string dig_chinese[11]={"","一","二","三","四","五","六","七","***"};

int main(){
    int val;
    cin>>val;
    bool zero_front = true;//当前位前面是否存在非零数字,用于判断前面存在零时是否需要打印零
    if(val==0){
        cout<<"零"<<endl;
        return 0;
    }
    int suffixs_id = 2;//后缀,亿,万
    int zero_cnt = 0;//当前位前面存在的零的个数,用于解决*0*问题
    if(val<0){
        cout<<"负";
        val = abs(val);
    }
    while(val){
        int cur_val = val/(int)pow(10,4*suffixs_id);//得到ABCD
        if(cur_val){//ABCD不为0时,才需要进行转化
            for(int i=3;i>=0;--i){
                int dig = cur_val/(int) pow(10,i);
                cur_val%=(int)pow(10,i);
                if(dig){
                    if(!zero_front&&zero_cnt)
                        cout<<"零";
                    //当A01D时,不念做一十D
                    if(dig!=1||zero_cnt==0||i!=1)cout<<dig_chinese[dig];
                    cout<<dig_name[i];

                    zero_cnt=0;
                }else
                    zero_cnt++;
                zero_front = zero_front&&dig==0;//更新
            }
            cout<<suffixs[suffixs_id];
        }
        val%=(int)pow(10,4*suffixs_id);
        suffixs_id--;
    }
    return 0;
}

思路如下:
在汉语里,我们使用万进制而非千进制,因此,对于一个数字,它的读法为几千几百几十几单位(亿、万)几千几百几十几。。。
因此,将一个数以四位进行拆分,得到ABCD亿ABCD万ABCD,然后解决ABCD的中文化。
如果直接得到A千B百C十D。,但当ABCD中出现0时,不符合中文习惯。当前数字dig不为0且前一位为0时,存在两种情况,前面只存在0和前面不全为0。对于第一种情况,直接忽略前面的0,对于第二种情况,仅输出一个零。
解决4位转化之后,需要处理一些特殊情况:
1.ABCD均为0,不处理
2.C为1且C前存在0时,直接读作十几而不是一十几。如1011读作一千零十一而不是一千零一十一。11读作十一而不是一十一。
发表于 2023-08-07 22:27:57 回复(0)
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param n int整型 
     * @return string字符串
     */
     vector<string> chnNumChar = {"零","一","二","三","四","五","六","七","***"};
     vector<string> chnUnitSection = {"", "万","亿","万亿"};
     vector<string> chnUnitChar = {"", "十","百","千"};
     void SectionToChinese(unsigned int section, string& chnStr) {
        string strIns;
        int unitPos = 0;
        bool zero = true;
        while(section > 0) {
            int v = section % 10;
            if (v != 0) {
                strIns = chnNumChar[v];
                strIns += chnUnitChar[unitPos];
                zero = false;
            } else {
                if (!zero) {
                    strIns = chnNumChar[v];
                    zero = true;
                }
            }
            chnStr.insert(0, strIns);
            if ((section / 10 == 0 && strIns.substr(0, 3) == "一") && chnUnitChar[unitPos] == "十") {
                chnStr.erase(chnStr.begin(), chnStr.begin() + 3);
            }
            unitPos++;
            section /= 10;
        }
    }
    string num2cn(int num) {
        if (num == 0) return "零";
        bool flag = false;
        if (num < 0) {
            num = -num;
            flag = true;
        }
        string chnStr;
        int unitPos = 0;
        
        bool needZero = false;
        while (num > 0) {
            uint32_t section = num % 10000;
            string strIns;
            SectionToChinese(section, strIns);
            strIns += (section != 0) ? chnUnitSection[unitPos] : chnUnitSection[0];
            chnStr.insert(0, strIns);
            num = num / 10000;
            unitPos++;
            if (num > 0 && section < 1000 && section > 0) { // 针对60500这种,五百前面需要加0
                chnStr.insert(0, "零");
            }
        }
        if (flag) {
            chnStr.insert(0, "负");
        }
        return chnStr;
    }
};

发表于 2023-04-27 15:00:10 回复(0)
import java.util.*;


public class Solution {

    public String num2cn (int num) {
        String[] arr1 = {"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
        String[] arr2 = {"", "十", "百", "千", "万", "十", "百", "千", "亿", "十", "百", "千", "万", "十", "百", "千", "亿"}; //可继续追加更高位转换值
        if (num == 0) {
            return "零";
        }
        boolean negative = false;
        if (num < 0) {
            num = Math.abs(num);
            negative = true;
        }
        String english = String.valueOf(num);
        String result = "";
        for (int i = 0; i < english.length(); i++) {
            int des_i = english.length() - 1 - i;//倒序排列设值
            result = arr2[i] + result;
            int arr1_index = Integer.parseInt(String.valueOf(english.charAt(des_i)));
            result = arr1[arr1_index] + result;
        }
        //将【零千、零百】换成【零】 【十零】换成【十】
        result = result.replaceAll("零(千|百|十)", "零").replaceAll("十零",
                 "十");
        //合并中间多个零为一个零
        result = result.replaceAll("零+", "零");
        //将【零亿】换成【亿】【零万】换成【万】
        result = result.replaceAll("零亿", "亿").replaceAll("零万", "万");
        //将【亿万】换成【亿】
        result = result.replaceAll("亿万", "亿");
        //移除末尾的零
        result = result.replaceAll("零+$", "");
        //将【零一十】换成【零十】
        //result = result.replaceAll("零一十", "零十");//貌似正规读法是零一十
        //将【一十】换成【十】
        result = result.replaceAll("^一十", "十");
        if(negative) {
            result = "负" + result;
        }
        return result;
    }
}

发表于 2023-03-28 09:46:26 回复(0)
javascript代码:
思路:注意就是发现中文数字的规律。
  1. 1.中文数字每四个一组,每个组都有不同的称谓,比如最小的四位没有称谓,第二组四位统一是万,第三组统一是亿。用字母a表示
  2. 2.每一组内部从左到右分别是个、十、百、千。用字母b表示
  3. 3. 每个数字单独对应的中文从零-九,用字母c表示
所以中文数字组合规则就是:c+b+a。比如121。属于第一组,所以没有称谓,a=‘’,1属于百位,b=‘百’,1对应一,c=‘一’,所以右边第一个一读作c+b+a,一百,类推,就是‘一百二十一’
特殊规则:
  1. 中间有零的,只保留一个零
  2. 末尾有零的忽略
  3. 当十位在最前面,且数字是一,则省略一,之读成‘十’,比如312,十位在中间,所以读:‘一十’,如果十位在最前面,比如:‘18’,读作‘十’
剩下的就是将规则翻译成代码:
function num2cn( n ) {
    const absN = Math.abs(n)
    const arr = String(absN).replace(/\d(?=(?:[0-9]{4})+$)/g, (...params) => {
        return params[0] + ','
    }).split(',')
    const names1 = ['', '十', '百', '千']
    const names2 = ['', '万', '亿']
    const names3 = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
    let res = ''
    for (let i=arr.length - 1; i>=0; --i) {
        const val = arr[i]
        let str = ''
        for (let j=val.length - 1; j>=0; --j) {
            const v = Number(val[j])
            const suffix =  names3[v] === '零' ? '' : names1[val.length - 1 - j]
            let prefix = (names3[v] === '零' && (str[0] === '零' || (!str && res[0] === '零')))
                         || (names3[v] === '零' && !str && !res)
                         || (names3[v] === '一' && j === val.length - 2 && i === 0)
                        ? '' : names3[v]
            str = prefix + suffix + str
        }
        if (str) {
            res = str +  names2[arr.length - 1 - i] + res
        }
        
    }
    return res === '' ? '零' : n < 0 ? '负' + res : res
}


发表于 2023-01-19 12:54:44 回复(0)
package main
import (
    "strconv"
)

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param n int整型 
 * @return string字符串
*/
func num2cn( n int ) string {
    digits := []string{
        "零", "一", "二", "三", "四", 
        "五", "六", "七", "八", "九", 
    }
    
    innerUnit := []string{
        "", "十", "百", "千",
    }
    outerUnit := []string{
        "", "万", "亿",
    }

    // 特殊case
    if n==0{
        return digits[0]
    }

    sign := 1
    if n<0{
        sign = -1
        n = -n
    }
    numStr := strconv.Itoa(n)


    var res string
    outerStep := 0
    for i:=len(numStr)-1;i>=0;{
        step := 0
        secNumStr := ""
        hasRightNonZero := false
        for step<4 && i>=0{

            //特殊case,0是否发音取决于后面还有没有非0数字
            if numStr[i]=='0' {
                if hasRightNonZero{
                    //多个0只留一个
                    for step<4 && i>=0 && numStr[i]=='0'{
                        step++
                        i--
                    }
                    secNumStr = digits[0] +secNumStr
                } else{
                    step++
                    i--
                }
                continue
            }

            hasRightNonZero = true

            //处理特殊case  整个part如果为12这种,应该读作十二,1不发音
            if step==1 && numStr[i]=='1' && i==0{
                secNumStr = innerUnit[step]  + secNumStr
            } else{ // 普通模式
                secNumStr = digits[numStr[i]-'0'] + innerUnit[step] + secNumStr
            }
            step++
            i--
        }
        //特殊case,整个part不发音,也就不能带单位了
        if secNumStr==""{
            //
        } else{
            res = secNumStr + outerUnit[outerStep] + res
        }
        
        outerStep++
    }

    if sign == -1{
        res = "负" + res
    }
    return res

}

发表于 2022-11-22 13:48:25 回复(0)
https://www.yuque.com/u21069870/ip39m8/gq5pyt 
体用一个 go 解法
发表于 2022-06-22 16:36:53 回复(0)
小于等于十亿然后给了我一个十亿零七的测试数据?😶
发表于 2022-03-17 18:28:36 回复(2)