无关紧要的话:好久没有更新博客了,似乎都快忘记了自己还有个博客,嘻嘻~~

项目需求简单说明
最近在项目里面用到了一个需求,我从本地数据库中读到了很多法律条文,但是从数据库里面拿到的数据有可能是没有顺序的,我需要对这些数据进行排序,但是需要注意的是,所有的条文的序号都是中文的,类似“第一条”、“第一章”等,这样我就需要将这些中文数字转成阿拉伯数字再进行比较。

解决方法

重要提示:请自己保证方法参数为数字,这里没有进行校验。如果不是数字,会出现异常情况!!!

重要提示:请自己保证方法参数为数字,这里没有进行校验。如果不是数字,会出现异常情况!!!

重要提示:请自己保证方法参数为数字,这里没有进行校验。如果不是数字,会出现异常情况!!!

下面提供转换方法:

java版本

/**
	 * 将中文数字转换成阿拉伯数字,支持含有小数的数字
	 * 
	 * @param string
	 *            中文内容
	 * @return
	 */
	private double parseChineseToDecimal(String string) {
		double result = 0.0;

		String str = string;
		// 计算小数部分
		int index = str.indexOf("点");
		if (index != -1) {
			// 如果“.”在最后一个字,则不作任何操作
			// 一般情况下,“.”不会在最后一个字
			if (index != str.length() - 1) {
				StringBuilder sb = new StringBuilder("0.");
				// 由于小数部分读法直接是读数字,而没有“十”、“百”、“千”、“万”、“亿”这些中文,所以需要一个个字进行翻译
				// 这里已经确定了有小数部分,且“点”字不是最后一位
				char[] decimal = str.split("点")[1].toCharArray();
				for (int i = 0; i < decimal.length; i++) {
					sb.append((int) parseChineseToDecimal(String.valueOf(decimal[i])));
				}
				result += Double.parseDouble(sb.toString());
			}
			// 如果中文含有“点”字,重构整数部分
			str = str.substring(0, index);
		}

		// 计算整数部分
		str = str.replaceAll("零", "");
		index = str.lastIndexOf("亿");
		if (index != -1) {
			result += parseChineseToDecimal(str.substring(0, index)) * Math.pow(10.0, 8.0);
			if (index != str.length() - 1) {
				result += parseChineseToDecimal(str.substring(index + 1));
			}
		} else {
			index = str.lastIndexOf("万");
			if (index != -1) {
				result += parseChineseToDecimal(str.substring(0, index)) * Math.pow(10.0, 4.0);
				if (index != str.length() - 1) {
					result += parseChineseToDecimal(str.substring(index + 1));
				}
			} else {
				index = str.lastIndexOf("千");
				if (index != -1) {
					result += parseChineseToDecimal(str.substring(0, index)) * Math.pow(10.0, 3.0);
					if (index != str.length() - 1) {
						result += parseChineseToDecimal(str.substring(index + 1));
					}
				} else {
					index = str.lastIndexOf("百");
					if (index != -1) {
						result += parseChineseToDecimal(str.substring(0, index)) * Math.pow(10.0, 2.0);
						// 如果“百”不是最后一个字,则应该加上后面的内容
						if (index != str.length() - 1) {
							result += parseChineseToDecimal(str.substring(index + 1));
						}
					} else {
						index = str.lastIndexOf("十");
						if (index != -1) {
							// 当分解“十”时,需要对“十”开头的数据进行额外处理
							if (index == 0) {
								result += 10;
								if (index != str.length() - 1) {
									result += parseChineseToDecimal(str.substring(index + 1));
								}
							} else {
								result += parseChineseToDecimal(str.substring(0, index)) * 10.0;
								if (index != str.length() - 1) {
									result += parseChineseToDecimal(str.substring(index + 1));
								}
							}
						} else {
							switch (str) {
							case "零":
								result += 0.0;
								break;
							case "一":
								result += 1.0;
								break;
							case "二":
								result += 2.0;
								break;
							case "三":
								result += 3.0;
								break;
							case "四":
								result += 4.0;
								break;
							case "五":
								result += 5.0;
								break;
							case "六":
								result += 6.0;
								break;
							case "七":
								result += 7.0;
								break;
							case "八":
								result += 8.0;
								break;
							case "九":
								result += 9.0;
								break;
							default:
								result += 0.0;
								break;
							}
						}
					}
				}
			}
		}
		return result;
	}

kotlin版本

/**
     * 将中文数字转换成阿拉伯数字,支持含有小数的数字
     *
     * @param string
     * 中文内容
     * @return
     */
    private fun parseChineseToDecimal(string: String): Double {
        var result = 0.0

        var str = string
        // 计算小数部分
        var index = str.indexOf("点")
        if (index != -1) {
            // 如果“.”在最后一个字,则不作任何操作
            // 一般情况下,“.”不会在最后一个字
            if (index != str.length - 1) {
                val sb = StringBuilder("0.")
                // 由于小数部分读法直接是读数字,而没有“十”、“百”、“千”、“万”、“亿”这些中文,所以需要一个个字进行翻译
                // 这里已经确定了有小数部分,且“点”字不是最后一位
                val decimal =
                    str.split("点".toRegex()).dropLastWhile({ it.isEmpty() }).toTypedArray()[1].toCharArray()
                for (i in decimal.indices) {
                    sb.append(parseChineseToDecimal(decimal[i].toString()).toInt())
                }
                result += java.lang.Double.parseDouble(sb.toString())
            }
            // 如果中文含有“点”字,重构整数部分
            str = str.substring(0, index)
        }

        // 计算整数部分
        str = str.replace("零".toRegex(), "")
        index = str.lastIndexOf("亿")
        if (index != -1) {
            result += parseChineseToDecimal(str.substring(0, index)) * Math.pow(10.0, 8.0)
            if (index != str.length - 1) {
                result += parseChineseToDecimal(str.substring(index + 1))
            }
        } else {
            index = str.lastIndexOf("万")
            if (index != -1) {
                result += parseChineseToDecimal(str.substring(0, index)) * Math.pow(10.0, 4.0)
                if (index != str.length - 1) {
                    result += parseChineseToDecimal(str.substring(index + 1))
                }
            } else {
                index = str.lastIndexOf("千")
                if (index != -1) {
                    result += parseChineseToDecimal(str.substring(0, index)) * Math.pow(10.0, 3.0)
                    if (index != str.length - 1) {
                        result += parseChineseToDecimal(str.substring(index + 1))
                    }
                } else {
                    index = str.lastIndexOf("百")
                    if (index != -1) {
                        result += parseChineseToDecimal(str.substring(0, index)) * Math.pow(
                            10.0,
                            2.0
                        )
                        // 如果“百”不是最后一个字,则应该加上后面的内容
                        if (index != str.length - 1) {
                            result += parseChineseToDecimal(str.substring(index + 1))
                        }
                    } else {
                        index = str.lastIndexOf("十")
                        if (index != -1) {
                            // 当分解“十”时,需要对“十”开头的数据进行额外处理
                            if (index == 0) {
                                result += 10.0
                                if (index != str.length - 1) {
                                    result += parseChineseToDecimal(str.substring(index + 1))
                                }
                            } else {
                                result += parseChineseToDecimal(str.substring(0, index)) * 10.0
                                if (index != str.length - 1) {
                                    result += parseChineseToDecimal(str.substring(index + 1))
                                }
                            }
                        } else {
                            when (str) {
                                "零" -> result += 0.0
                                "一" -> result += 1.0
                                "二" -> result += 2.0
                                "三" -> result += 3.0
                                "四" -> result += 4.0
                                "五" -> result += 5.0
                                "六" -> result += 6.0
                                "七" -> result += 7.0
                                "八" -> result += 8.0
                                "九" -> result += 9.0
                                else -> result += 0.0
                            }
                        }
                    }
                }
            }
        }
        return result
    }

此外,我还另外写了一个一个方法,专门针对不含小数部分的中文数字解析。

java版本

/**
	 * 将中文数字转换成阿拉伯数字,只支持不含小数的数字
	 * 
	 * @param string
	 *            中文内容
	 * @return
	 */
	private double parseChineseToInteger(String string) {
		String str = string.replaceAll("零", "");
		int index = str.lastIndexOf("亿");
		if (index != -1) {
			if (index != str.length() - 1) {
				return parseChineseToInteger(str.substring(0, index)) * Math.pow(10.0, 8.0)
						+ parseChineseToInteger(str.substring(index + 1));
			} else {
				return parseChineseToInteger(str.substring(0, index)) * Math.pow(10.0, 8.0);
			}
		} else {
			index = str.lastIndexOf("万");
			if (index != -1) {
				if (index != str.length() - 1) {
					return parseChineseToInteger(str.substring(0, index)) * Math.pow(10.0, 4.0)
							+ parseChineseToInteger(str.substring(index + 1));
				} else {
					return parseChineseToInteger(str.substring(0, index)) * Math.pow(10.0, 4.0);
				}
			} else {
				index = str.lastIndexOf("千");
				if (index != -1) {
					if (index != str.length() - 1) {
						return parseChineseToInteger(str.substring(0, index)) * Math.pow(10.0, 3.0)
								+ parseChineseToInteger(str.substring(index + 1));
					} else {
						return parseChineseToInteger(str.substring(0, index)) * Math.pow(10.0, 3.0);
					}
				} else {
					index = str.lastIndexOf("百");
					if (index != -1) {
						// 如果“百”不是最后一个字,则应该加上后面的内容
						if (index != str.length() - 1) {
							return parseChineseToInteger(str.substring(0, index)) * Math.pow(10.0, 2.0)
									+ parseChineseToInteger(str.substring(index + 1));
						} else {
							// 如果“百”是最后一个字,则只需要考虑前面的内容
							return parseChineseToInteger(str.substring(0, index)) * Math.pow(10.0, 2.0);
						}
					} else {
						index = str.lastIndexOf("十");
						if (index != -1) {
							// 当分解“十”时,需要对“十”开头的数据进行额外处理
							// 还需要注意,“十”不能是最后一个字
							if (index == 0 && index != str.length() - 1)
								return 10.0 + parseChineseToInteger(str.substring(index + 1));
							if (index == 0 && index == str.length() - 1)
								return 10.0;
							if (index != str.length() - 1) {
								return parseChineseToInteger(str.substring(0, index)) * 10.0
										+ parseChineseToInteger(str.substring(index + 1));
							} else {
								return parseChineseToInteger(str.substring(0, index)) * 10.0;
							}

						} else {
							switch (str) {
							case "零":
								return 0.0;
							case "一":
								return 1.0;
							case "二":
								return 2.0;
							case "三":
								return 3.0;
							case "四":
								return 4.0;
							case "五":
								return 5.0;
							case "六":
								return 6.0;
							case "七":
								return 7.0;
							case "八":
								return 8.0;
							case "九":
								return 9.0;
							default:
								return 0.0;
							}
						}
					}
				}
			}
		}
	}

kotlin版本

/**
     * 将中文数字转换成阿拉伯数字,只支持不含小数的数字
     *
     * @param string
     * 中文内容
     * @return
     */
    private fun parseChineseToInteger(string: String): Double {
        val str = string.replace("零".toRegex(), "")
        var index = str.lastIndexOf("亿")
        if (index != -1) {
            return if (index != str.length - 1) {
                parseChineseToInteger(str.substring(0, index)) * Math.pow(
                    10.0,
                    8.0
                ) + parseChineseToInteger(str.substring(index + 1))
            } else {
                parseChineseToInteger(str.substring(0, index)) * Math.pow(10.0, 8.0)
            }
        } else {
            index = str.lastIndexOf("万")
            if (index != -1) {
                return if (index != str.length - 1) {
                    parseChineseToInteger(str.substring(0, index)) * Math.pow(
                        10.0,
                        4.0
                    ) + parseChineseToInteger(str.substring(index + 1))
                } else {
                    parseChineseToInteger(str.substring(0, index)) * Math.pow(10.0, 4.0)
                }
            } else {
                index = str.lastIndexOf("千")
                if (index != -1) {
                    return if (index != str.length - 1) {
                        parseChineseToInteger(str.substring(0, index)) * Math.pow(
                            10.0,
                            3.0
                        ) + parseChineseToInteger(str.substring(index + 1))
                    } else {
                        parseChineseToInteger(str.substring(0, index)) * Math.pow(10.0, 3.0)
                    }
                } else {
                    index = str.lastIndexOf("百")
                    if (index != -1) {
                        // 如果“百”不是最后一个字,则应该加上后面的内容
                        return if (index != str.length - 1) {
                            parseChineseToInteger(str.substring(0, index)) * Math.pow(
                                10.0,
                                2.0
                            ) + parseChineseToInteger(str.substring(index + 1))
                        } else {
                            // 如果“百”是最后一个字,则只需要考虑前面的内容
                            parseChineseToInteger(str.substring(0, index)) * Math.pow(10.0, 2.0)
                        }
                    } else {
                        index = str.lastIndexOf("十")
                        if (index != -1) {
                            // 当分解“十”时,需要对“十”开头的数据进行额外处理
                            // 还需要注意,“十”不能是最后一个字
                            if (index == 0 && index != str.length - 1)
                                return 10.0 + parseChineseToInteger(str.substring(index + 1))
                            if (index == 0 && index == str.length - 1)
                                return 10.0
                            return if (index != str.length - 1) {
                                parseChineseToInteger(
                                    str.substring(
                                        0,
                                        index
                                    )
                                ) * 10.0 + parseChineseToInteger(str.substring(index + 1))
                            } else {
                                parseChineseToInteger(str.substring(0, index)) * 10.0
                            }

                        } else {
                            when (str) {
                                "零" -> return 0.0
                                "一" -> return 1.0
                                "二" -> return 2.0
                                "三" -> return 3.0
                                "四" -> return 4.0
                                "五" -> return 5.0
                                "六" -> return 6.0
                                "七" -> return 7.0
                                "八" -> return 8.0
                                "九" -> return 9.0
                                else -> return 0.0
                            }
                        }
                    }
                }
            }
        }
    }

测试代码

List<String> list = new ArrayList<String>();
		list.add("一");
		list.add("二");
		list.add("三");
		list.add("四");
		list.add("五");
		list.add("六");
		list.add("七");
		list.add("八");
		list.add("九");
		list.add("十");
		list.add("十一");
		list.add("十四");
		list.add("二十");
		list.add("二十三");
		list.add("五十");
		list.add("六十九");
		list.add("一百");
		list.add("一百零一点零零五");
		list.add("一百零九点三");
		list.add("一百一十");
		list.add("一百二十");
		list.add("一百三十五点二零七");
		list.add("一千");
		list.add("一千零三");
		list.add("一千零五十");
		list.add("一千一百");
		list.add("三千一百零八");
		list.add("一千三百五十九");
		list.add("九千三百五十九");
		list.add("一万");
		list.add("一万零五");
		list.add("一万零一十");
		list.add("一万零一百八十");
		list.add("一万三千五百");
		list.add("十万九千九百九十九");
		list.add("十一万九千九百九十九");
		list.add("二十五万九千九百九十九");
		list.add("一百万九千九百九十九");
		list.add("二亿");
		list.add("二亿零一");
		list.add("二亿零三百");
		list.add("二亿零五千");
		list.add("二亿零三万");
		list.add("五千万零三");
		list.add("二百万零四");
		list.add("一百亿零三万");
		list.add("三千亿");
		list.add("六万亿");

		list.forEach(new Consumer<String>() {
			@Override
			public void accept(String t) {
				System.out.println(t + "		" + new ChineseNumCompare().parseChineseToDecimal(t));
			}
		});

测试结果

一		1.0
二		2.0
三		3.0
四		4.0
五		5.0
六		6.0
七		7.0
八		8.0
九		9.0
十		10.0
十一		11.0
十四		14.0
二十		20.0
二十三		23.0
五十		50.0
六十九		69.0
一百		100.0
一百零一点零零五		101.005
一百零九点三		109.3
一百一十		110.0
一百二十		120.0
一百三十五点二零七		135.207
一千		1000.0
一千零三		1003.0
一千零五十		1050.0
一千一百		1100.0
三千一百零八		3108.0
一千三百五十九		1359.0
九千三百五十九		9359.0
一万		10000.0
一万零五		10005.0
一万零一十		10010.0
一万零一百八十		10180.0
一万三千五百		13500.0
十万九千九百九十九		109999.0
十一万九千九百九十九		119999.0
二十五万九千九百九十九		259999.0
一百万九千九百九十九		1009999.0
二亿		2.0E8
二亿零一		2.00000001E8
二亿零三百		2.000003E8
二亿零五千		2.00005E8
二亿零三万		2.0003E8
五千万零三		5.0000003E7
二百万零四		2000004.0
一百亿零三万		1.000003E10
三千亿		3.0E11
六万亿		6.0E12


如果数太大,我们就不能再使用double了。我们可以使用 BigDecimal 来代替double。然后只需要稍微对其加减乘除运算进行代码修改就好,逻辑完全不需要变。BigDecimal的具体使用不做介绍。