题解 | #人民币转换#
人民币转换
https://www.nowcoder.com/practice/00ffd656b9604d1998e966d555005a4b
import java.util.*; import java.util.stream.Collectors; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { private static Map<Integer, String> map = new HashMap<Integer, String>() { { put(0, "零"); put(1, "壹"); put(2, "贰"); put(3, "叁"); put(4, "肆"); put(5, "伍"); put(6, "陆"); put(7, "柒"); put(8, "捌"); put(9, "玖"); put(10, "拾"); put(100, "佰"); put(1000, "仟"); } }; private static Map<Integer, String> map1 = new HashMap<Integer, String>() { { put(1, "元"); put(10000, "万"); put(100000000, "亿"); } }; public static void main(String[] args) { Scanner in = new Scanner(System.in); double money = in.nextDouble(); System.out.println(transfer(money)); } public static String transfer(double money) { String result = ""; double n = 1; money = Math.round(money * 100);// 防止精度丢失 todo 坑:0.29-》0.289999999999,double 类型浮点数精度丢失 while (money > 0) { int c = (int) (money % 10); if (n < 100) {//处理 角 分 if (c > 0) result = appendBefore(result, map(c), n == 1 ? "分" : "角"); } else { n /= 100; result = appendBefore(result, c > 0 ? map(c) : "", map1(n));// 元 万 亿 int n1 = 10; for (int i = 0; i < 3 && money > 0; ++i) { n *= 10; money = Math.floor(money / 10); if (money <= 0) { break; } double c1 = money % 10; if (c1 > 0) { boolean b = c1 == 1 && n1 == 10;// 10->拾;100-> 一百 result = appendBefore(result, b ? "" : map(c1), map(n1)); } else { char c2; if ((c2 = result.charAt(0)) != '零' && !map1.containsValue(c2)) { result = appendBefore(result, map(0)); } } n1 *= 10; } n *= 100; } n *= 10; money = Math.floor(money / 10); } if (result.endsWith("元")) result = appendBefore(result, "整"); if (result.isEmpty()) result = appendBefore(result, map(0), "元"); result = appendBefore(result, "人民币"); return result; } private static String appendBefore(String origin, String... strs) { return String.join("", strs) + origin; } private static String map(double n) { return map.get((int) n); } private static String map1(double n) { return map1.get((int) n); } }
说下思路:
在西方的数字体系中,K(koli), M(Million),G(Giga),T(Tera), 以 1000 为进制差。
而在我们的数字体系中,只有万和亿,以 10000 为进制差。
因此,我们可以 4 位一个循环,补位一个汉字:亿、万、元(刚好1后面什么都不用接)。每个循环内部逻辑通用。数字和汉字的转换直接用一个 map 封装,随用随取,堪称完美!
注意点:
1、映射数据结构为:map<Integer,String> ,多数时候我们用的是 double,直接用 double 是取不出来的,map(double n){ ...get((int)n)...}, 这种写法可以兼容 int 和 double.
2、double 小数存在失真问题(所有数字都以二进制存储,二进制无法精确表示所有小数),做一次转换更舒服:money=Math.round(money *100);
3、appendBefore(String origin, String... strs) ,转递可变参数有性能缺陷,对性能有要求的场景不介意这种写法。