精易论坛

标题: [ 纯源码 ] 数字到中文 [打印本页]

作者: 希纱    时间: 2024-4-26 02:49
标题: [ 纯源码 ] 数字到中文

解决思路


一. 任务需求


1. 将数字转为中文读法
2. 支持处理整数, 小数
3. 支持正数与负数的处理

数值分解


1. 数字的转换需要首先将数值分解为可管理的单元:
    1.1 整数部分按数位分割, 每四位一组: 对应一级大数单位 (千, 万, 亿, 兆)
    1.2 小数部分将每位数直接转换为相应的中文数字, 从左到右读出

特殊情况


1. 特殊的数字如 “零” 的处理需特别注意, 避免在读法中出现连续的 “零” , 并正确使用 “点” 表示小数部分

大数单位


1. 根据数位系统, 超过四位的数需要添加适当的单位 (万, 亿, 兆等), 这些单位在数值中有明确的层级关系和位置

数据处理


1. 对于负数需在最终的中文读法前添加 “负” 字
2. 小数部分则按照每位对应的中文数字顺序读出,前面用 “点” 来分隔。

测试代码


1. std::cout << numberToChinese("9999") << std::endl;
2. std::cout << numberToChinese("99999999") << std::endl;
3. std::cout << numberToChinese("999999999999") << std::endl;
4. std::cout << numberToChinese("9999999999999999") << std::endl;

5. std::cout << numberToChinese("9999.9999") << std::endl;
6. std::cout << numberToChinese("99999999.99999999") << std::endl;
7. std::cout << numberToChinese("999999999999.999999999999") << std::endl;
8. std::cout << numberToChinese("9999999999999999.9999999999999999")

9. std::cout << numberToChinese("-9999") << std::endl;
10. std::cout << numberToChinese("-99999999") << std::endl;
11. std::cout << numberToChinese("-999999999999") << std::endl;
12. std::cout << numberToChinese("-9999999999999999") << std::endl;

13. std::cout << numberToChinese("-9999.9999") << std::endl;
14. std::cout << numberToChinese("-99999999.99999999") << std::endl;
15. std::cout << numberToChinese("-999999999999.999999999999") << std::endl;
16. std::cout << numberToChinese("-9999999999999999.9999999999999999") << std::endl;

17. std::cout << numberToChinese("09999") << std::endl;
18. std::cout << numberToChinese("099999999") << std::endl;
19. std::cout << numberToChinese("0999999999999") << std::endl;
20. std::cout << numberToChinese("09999999999999999") << std::endl;

21. std::cout << numberToChinese("09999.9999") << std::endl;
22. std::cout << numberToChinese("099999999.99999999") << std::endl;
23. std::cout << numberToChinese("0999999999999.999999999999") << std::endl;
24. std::cout << numberToChinese("09999999999999999.9999999999999999") << std::endl;

25. std::cout << numberToChinese("-09999") << std::endl;
26. std::cout << numberToChinese("-099999999") << std::endl;
27. std::cout << numberToChinese("-0999999999999") << std::endl;
28. std::cout << numberToChinese("-09999999999999999") << std::endl;

29. std::cout << numberToChinese("-09999.9999") << std::endl;
30. std::cout << numberToChinese("-099999999.99999999") << std::endl;
31. std::cout << numberToChinese("-0999999999999.999999999999") << std::endl;
31. std::cout << numberToChinese("-09999999999999999.9999999999999999") << std::endl;

测试结果


1. 九千九百九十九
2. 九千九百九十九万九千九百九十九
3. 九千九百九十九亿九千九百九十九万九千九百九十九
4. 九千九百九十九兆九千九百九十九亿九千九百九十九万九千九百九十九

5. 九千九百九十九点九九九九
6. 九千九百九十九万九千九百九十九点九九九九九九九九
7. 九千九百九十九亿九千九百九十九万九千九百九十九点九九九九九九九九九九九九
8. 九千九百九十九兆九千九百九十九亿九千九百九十九万九千九百九十九点九九九九九九九九九九九九九九九九

9. 负九千九百九十九
10. 负九千九百九十九万九千九百九十九
11. 负九千九百九十九亿九千九百九十九万九千九百九十九
12. 负九千九百九十九兆九千九百九十九亿九千九百九十九万九千九百九十九

13. 负九千九百九十九点九九九九
14. 负九千九百九十九万九千九百九十九点九九九九九九九九
15. 负九千九百九十九亿九千九百九十九万九千九百九十九点九九九九九九九九九九九九
16. 负九千九百九十九兆九千九百九十九亿九千九百九十九万九千九百九十九点九九九九九九九九九九九九九九九九

17. 九千九百九十九
18. 九千九百九十九万九千九百九十九
19. 九千九百九十九亿九千九百九十九万九千九百九十九
20. 九千九百九十九兆九千九百九十九亿九千九百九十九万九千九百九十九

21. 九千九百九十九点九九九九
22. 九千九百九十九万九千九百九十九点九九九九九九九九
23. 九千九百九十九亿九千九百九十九万九千九百九十九点九九九九九九九九九九九九
24. 九千九百九十九兆九千九百九十九亿九千九百九十九万九千九百九十九点九九九九九九九九九九九九九九九九

25. 负九千九百九十九
26. 负九千九百九十九万九千九百九十九
27. 负九千九百九十九亿九千九百九十九万九千九百九十九
28. 负九千九百九十九兆九千九百九十九亿九千九百九十九万九千九百九十九

29. 负九千九百九十九点九九九九
30. 负九千九百九十九万九千九百九十九点九九九九九九九九
31. 负九千九百九十九亿九千九百九十九万九千九百九十九点九九九九九九九九九九九九
32. 负九千九百九十九兆九千九百九十九亿九千九百九十九万九千九百九十九点九九九九九九九九九九九九九九九九

代码文件


#include <iostream>
#include <string>
#include <vector>

const std::vector digits = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
const std::vector units = { "", "十", "百", "千" };
const std::vector big_units = { "", "万", "亿", "兆" };

static std::string convertSection(unsigned int num, bool isLastSection) {
    std::string result = "";
    int i = 0;
    while (num > 0) {
        int digit = num % 10;
        if (digit > 0) {
            result = digits[zxsq-anti-bbcode-digit] + (i < units.size() ? units[zxsq-anti-bbcode-i] : "") + result;
        }
        else if (!result.empty() && result.back() != '零') {
            result = "零" + result;
        }
        num /= 10;
        ++i;
    }
    if (!isLastSection && !result.empty() && result.back() == '零') {
        result.pop_back();
    }
    return result;
}

std::string numberToChinese(const std::string& number) {
    size_t dotPos = number.find('.');
    std::string integerPartStr = number.substr(0, dotPos);
    std::string fractionalPartStr = dotPos != std::string::npos ? number.substr(dotPos + 1) : "";

    bool isNegative = !integerPartStr.empty() && integerPartStr[zxsq-anti-bbcode-0] == '-';
    unsigned long long integerPart = std::stoull(isNegative ? integerPartStr.substr(1) : integerPartStr);

    std::string result = "";
    std::vector parts;
    int counter = 0;
    while (integerPart > 0) {
        unsigned int part = integerPart % 10000;
        std::string section = convertSection(part, integerPart < 10000);
        if (!section.empty()) {
            if (counter < big_units.size()) {
                section += big_units[zxsq-anti-bbcode-counter];
            }
            parts.push_back(section);
        }
        integerPart /= 10000;
        counter++;
    }

    if (parts.empty()) {
        parts.push_back("零");
    }

    for (auto it = parts.rbegin(); it != parts.rend(); ++it) {
        result += *it;
    }

    if (!fractionalPartStr.empty()) {
        result += "点";
        for (char digit : fractionalPartStr) {
            if (digit >= '0' && digit <= '9') {
                result += digits[digit - '0'];
            }
        }
    }

    if (isNegative) {
        result = "负" + result;
    }
    return result;
}

int main() {
    std::cout << numberToChinese("9999") << std::endl;
    std::cout << numberToChinese("99999999") << std::endl;
    std::cout << numberToChinese("999999999999") << std::endl;
    std::cout << numberToChinese("9999999999999999") << std::endl;

    std::cout << numberToChinese("9999.9999") << std::endl;
    std::cout << numberToChinese("99999999.99999999") << std::endl;
    std::cout << numberToChinese("999999999999.999999999999") << std::endl;
    std::cout << numberToChinese("9999999999999999.9999999999999999") << std::endl;

    std::cout << numberToChinese("-9999") << std::endl;
    std::cout << numberToChinese("-99999999") << std::endl;
    std::cout << numberToChinese("-999999999999") << std::endl;
    std::cout << numberToChinese("-9999999999999999") << std::endl;

    std::cout << numberToChinese("-9999.9999") << std::endl;
    std::cout << numberToChinese("-99999999.99999999") << std::endl;
    std::cout << numberToChinese("-999999999999.999999999999") << std::endl;
    std::cout << numberToChinese("-9999999999999999.9999999999999999") << std::endl;

    std::cout << numberToChinese("09999") << std::endl;
    std::cout << numberToChinese("099999999") << std::endl;
    std::cout << numberToChinese("0999999999999") << std::endl;
    std::cout << numberToChinese("09999999999999999") << std::endl;

    std::cout << numberToChinese("09999.9999") << std::endl;
    std::cout << numberToChinese("099999999.99999999") << std::endl;
    std::cout << numberToChinese("0999999999999.999999999999") << std::endl;
    std::cout << numberToChinese("09999999999999999.9999999999999999") << std::endl;

    std::cout << numberToChinese("-09999") << std::endl;
    std::cout << numberToChinese("-099999999") << std::endl;
    std::cout << numberToChinese("-0999999999999") << std::endl;
    std::cout << numberToChinese("-09999999999999999") << std::endl;

    std::cout << numberToChinese("-09999.9999") << std::endl;
    std::cout << numberToChinese("-099999999.99999999") << std::endl;
    std::cout << numberToChinese("-0999999999999.999999999999") << std::endl;
    std::cout << numberToChinese("-09999999999999999.9999999999999999") << std::endl;
    return 0;
}


作者: xiaopingwangluo    时间: 2024-4-26 02:55
大哥又开源好玩的
作者: lzptts    时间: 2024-4-26 03:18
感谢分享!!!
作者: 一指温柔    时间: 2024-4-26 09:05
支持开源~!感谢分享
作者: xmtian    时间: 2024-4-26 09:59
感谢分享。
作者: bianyuan456    时间: 2024-4-26 12:20
已经顶贴,感谢您对论坛的支持!
作者: l790504    时间: 2024-4-26 13:48
已经顶贴,感谢您对论坛的支持!
作者: 无名霸道    时间: 2024-4-26 16:08
支持开源~!感谢分享
作者: 艾玛克138    时间: 2024-4-26 21:27
谢了,很实用,就喜欢这样的资料
作者: mood1000    时间: 2024-4-26 21:44
没看懂,学习学习
作者: 艾玛克138    时间: 2024-4-26 22:41
宝贵经验啊,很值得学习
作者: ZHuanR    时间: 2024-4-27 00:02
新技能已get√
作者: 396384183    时间: 2024-4-27 00:56
支持开源~!感谢分享
作者: 小虎来了    时间: 2024-4-27 07:22
已经顶贴,感谢您对论坛的支持!
作者: lmwdz    时间: 2024-4-27 18:47
感谢分享
作者: shuya1    时间: 2024-4-28 00:12
新技能已get√
作者: 光影魔术    时间: 2024-5-2 21:36
感谢分享
作者: futiem    时间: 2024-5-8 17:06
很实用,就喜欢这样的资料
作者: yuxuanju    时间: 2024-5-17 14:03
感谢分享,下载学习。
作者: li110    时间: 2024-6-27 09:51





欢迎光临 精易论坛 (https://125.confly.eu.org/) Powered by Discuz! X3.4