目录一、工具类功能二、所需环境三、方法与调用示例按需调用四、工具类源码可直接复制一、工具类功能人民币金额的加减乘除、元分互转与千分位格式化一个类接住全程走 BigDecimal 避开 double 直接运算的精度丢失统一保留两位小数四舍五入、null 入参按 0 计。二、所需环境JDK 17或以上三、方法与调用示例按需调用方法序号1方法用途把多个金额一次加总结果固定两位小数、四舍五入全程走BigDecimal不用躲double相加掉精度null元素按 0 计不用先过滤方法定义public static BigDecimal add(BigDecimal... amounts)️入参解释public static BigDecimal add(相加的多个金额)返回值解释BigDecimal求和结果不为null标度恒为 2边界口径元素为null按 0 累加数组本身传null是编程错误抛IllegalArgumentException: 相加金额数组不能为null一个都不传、或全是null都得到0.00结果标度恒为 2第三位小数当场按四舍五入收掉不会留到下游再决定金额很大时用long/int累加的溢出担忧在这里不存在方法示例add(new BigDecimal(10.00), new BigDecimal(7.50), null)拿到17.50add()一个都不传拿到0.00add(null, null)全是null元素拿到0.00add(new BigDecimal(0.001), new BigDecimal(0.002))拿到0.00半分以下被收掉add(BigDecimal.ONE, BigDecimal.TEN)的scale()拿到2add((BigDecimal[]) null)抛IllegalArgumentException: 相加金额数组不能为null方法序号2方法用途把可能是null的金额兜成BigDecimal.ZERO后续运算不用再判空从数据库、报文里取出来的金额字段直接喂进加减乘除不用每处写三元判断方法定义public static BigDecimal nullToZero(BigDecimal amount)️入参解释public static BigDecimal nullToZero(金额)返回值解释BigDecimal非null的金额入参不是null时原样返回边界口径只兜null不改标度也不做舍入非null的入参按同一个引用返回兜出来的BigDecimal.ZERO标度是 0要两位小数得再setScale(2, HALF_UP)本类其它方法内部已经调它单独用它只是为了让自己写的求和代码少一处判空方法示例nullToZero(null)拿到0scale()是0不是0.00nullToZero(new BigDecimal(3.14159))拿到3.14159一位没被收掉方法序号3方法用途算两个金额的差被减数减减数结果两位小数、四舍五入余额扣减、退款找差这类场景直接调null按 0 计方法定义public static BigDecimal subtract(BigDecimal minuend, BigDecimal subtrahend)️入参解释public static BigDecimal subtract(被减数, 减数)返回值解释BigDecimal差值标度恒为 2边界口径两个入参都可以是null各按 0 计结果可以是负数扣超了不会替你把符号抹平参数顺序是被减数在前、减数在后写反了符号就反了方法示例subtract(new BigDecimal(100.00), new BigDecimal(23.60))余额扣减拿到76.40subtract(new BigDecimal(100), new BigDecimal(123.75))拿到-23.75扣超了就是负数subtract(null, null)拿到0.00方法序号4方法用途算两个金额或金额与数量的乘积结果两位小数、四舍五入单价乘数量、按比例算钱一行搞定不用再手动setScale方法定义public static BigDecimal multiply(BigDecimal multiplier, BigDecimal multiplicand)️入参解释public static BigDecimal multiply(乘数, 被乘数)返回值解释BigDecimal乘积标度恒为 2边界口径任一入参为null按 0 计结果就是0.00舍入发生在乘完之后先把两位小之外的第三位按四舍五入收掉不做两次舍入数量类入参比如3、1.5也当金额传标度不影响结果方法示例multiply(new BigDecimal(1.3335), new BigDecimal(5))单价乘数量拿到6.67multiply(new BigDecimal(0.1), new BigDecimal(0.2))拿到0.02double算法在这里会给0.020000000000000004multiply(null, BigDecimal.TEN)拿到0.00multiply(new BigDecimal(1.005), BigDecimal.ONE)拿到1.01方法序号5方法用途两个金额相除默认保留两位小数、四舍五入均摊、单价反算这类除法不用再包一层setScale除零也被转成说得清的异常方法定义public static BigDecimal divide(BigDecimal dividend, BigDecimal divisor)️入参解释public static BigDecimal divide(被除数, 除数)返回值解释BigDecimal商标度为 2边界口径就是三参版把小数位数固定成 2 的入口除数为 0 或为null按 0 计抛IllegalArgumentException: 除数不能为 0不会漏出 JDK 的ArithmeticException被除数为null按 0 计拿到0.00方法示例divide(new BigDecimal(100), new BigDecimal(3))百人均摊拿到33.33divide(BigDecimal.ONE, BigDecimal.ZERO)抛IllegalArgumentException: 除数不能为 0divide(null, BigDecimal.TEN)拿到0.00divide(BigDecimal.TEN, null)抛IllegalArgumentException: 除数不能为 0方法序号6方法用途两个金额相除并自己指定保留几位小数费率、单位成本这类要更多位数的商不用为了多两位小数先放大再缩小方法定义public static BigDecimal divide(BigDecimal dividend, BigDecimal divisor, int scale)️入参解释public static BigDecimal divide(被除数, 除数, 小数位数)返回值解释BigDecimal商标度就是传入的小数位数边界口径小数位数给 0 得到整数商给负数抛IllegalArgumentException: 小数位数不能为负: -1除数为 0 同样抛IllegalArgumentException与位数无关舍入仍是四舍五入指定位数之外的部分被收掉方法示例divide(new BigDecimal(100), new BigDecimal(3), 6)拿到33.333333divide(new BigDecimal(1), new BigDecimal(3), 10)拿到0.3333333333divide(new BigDecimal(100), new BigDecimal(3), 0)拿到33标度 0divide(BigDecimal.ONE, BigDecimal.TEN, -1)抛IllegalArgumentException: 小数位数不能为负: -1方法序号7方法用途把元转成分交回一个long正好对上银行和支付渠道按分传整数的约定不足一分的部分四舍五入进率固定 100不用自己乘 100 再担心精度方法定义public static long yuanToFen(BigDecimal yuan)️入参解释public static long yuanToFen(金额元)返回值解释long金额分边界口径金额为null按 0 计拿到0四舍五入是离零方向的1.005元进成 101 分-0.005元进成 -1 分超出long能表达的分数抛IllegalArgumentException不会静默截断成别的数结果是long而不是BigDecimal转完再想加总要注意精度口径方法示例yuanToFen(new BigDecimal(1.005))拿到101分yuanToFen(new BigDecimal(1.004))拿到100分yuanToFen((BigDecimal) null)拿到0yuanToFen(new BigDecimal(-0.005))拿到-1yuanToFen(new BigDecimal(1E20))抛IllegalArgumentException消息是「金额超出可表示范围单位分: 1E20」方法序号8方法用途直接把前端传来的金额文本转成分跳过自己new BigDecimal(...)这一步表单里的128.50、空字符串都能吃下解不出来时说得清是哪段文本的问题方法定义public static long yuanToFen(String yuanText)️入参解释public static long yuanToFen(金额文本元)返回值解释long金额分边界口径null、空串、全空白都按 0 计拿到0文本先去掉首尾空白再解析1E3这种科学计数法按BigDecimal的规则认拿到100000分带千分位逗号的文本1,234.5不认抛IllegalArgumentException要处理展示串得先把逗号去掉解析成功后的分数量级仍受long约束超限抛IllegalArgumentException方法示例yuanToFen(128.50)拿到12850分yuanToFen( )拿到0分空串与null同样是0yuanToFen( 128.50 )拿到12850首尾空白被去掉yuanToFen(1E3)拿到100000yuanToFen(abc)抛IllegalArgumentException: 无法解析的金额文本: abcyuanToFen(1,234.5)抛IllegalArgumentException: 无法解析的金额文本: 1,234.5方法序号9方法用途把渠道给的分数转回以元为单位的金额两位小数展示、入账前统一单位不用自己divide(100)还担心标度方法定义public static BigDecimal fenToYuan(long fen)️入参解释public static BigDecimal fenToYuan(金额分)返回值解释BigDecimal金额元标度恒为 2边界口径进率固定 100分数本来就是整数这里不会出现舍入损失负数照常转-1分就是-0.01元入参是long分数量级超过long的数据应该在上游就拦住方法示例fenToYuan(12850L)拿到128.50fenToYuan(0L)拿到0.00标度仍是 2fenToYuan(-1L)拿到-0.01fenToYuan(Long.MAX_VALUE)拿到92233720368547758.07方法序号10方法用途分转元后直接交出两位小数的字符串接口回包和页面渲染能直接用免去BigDecimal到字符串这一步也不会被toString的科学计数法写法坑到方法定义public static String fenToYuanText(long fen)️入参解释public static String fenToYuanText(金额分)返回值解释String形如1.23的金额文本边界口径内部就是fenToYuan(fen).toPlainString()永远不会出现E记数法两位小数补齐5 分是0.05而不是0.5不带货币符号、不带千分位要展示成对账单样子用方法11方法示例fenToYuanText(12850L)拿到128.50fenToYuanText(5L)拿到0.05不足一位也补零方法序号11方法用途把金额格式化成带千分位的展示串固定两位小数、四舍五入对账单、报表、小票这类要给人看的地方直接用它输出不随 JVM 语言环境变方法定义public static String formatThousands(BigDecimal amount)️入参解释public static String formatThousands(金额)返回值解释String千分位金额文本分组符恒为逗号、小数分隔符恒为点号边界口径数字符号固定按Locale.ROOT换成中文或德语语言环境跑输出仍是逗号分组、点号小数金额为null按 0 计拿到0.00小数第三位按四舍五入收掉1234567.891出来是1,234,567.89负数舍入到零时结果会是-0.00展示前要判断的话记得这条方法示例formatThousands(new BigDecimal(1234567.891))拿到1,234,567.89formatThousands(null)拿到0.00formatThousands(new BigDecimal(-9876543.217))拿到-9,876,543.22formatThousands(new BigDecimal(1000))拿到1,000.00整数也补两位小数formatThousands(new BigDecimal(-0.004))拿到-0.00四、工具类源码可直接复制领取方式 关注点赞收藏私信回复「java工具类」可领取100个工具类「Java企业级工具类全家桶1-100」的完整源码 工具类已调试通过复制粘贴即可使用省时省力 可保存到自己网盘永久有效觉得对您有帮助麻烦点点关注啦您的关注是我创作的最大动力~