Java中double转int异常:自定义四舍五入方法失效求助
问题根源与解决办法
嘿,我一眼就看出问题出在double类型的精度陷阱上了——这是Java浮点数处理里很常见的坑。
你看,当你传入23.6的时候,23.6 * 10在double里其实存的不是精确的236,而是类似235.99999999999997的近似值。这时候做%10运算,得到的checkD就是5.99999999999997,强制转int的时候会直接砍掉小数部分,结果check就变成了5,自然触发不了check > 5的条件,最后返回23而不是你想要的24。
几种可行的解决方案
1. 直接用Java内置的Math.round()(最推荐)
Java早就给我们做好了成熟的四舍五入实现,完全没必要自己造轮子:
public class Round { public int round(double value) { return (int) Math.round(value); } }
测试23.6会返回24,负数比如-23.6也会正确返回-24,完全符合标准四舍五入规则。
2. 修正自定义逻辑,抵消精度误差
如果你非要自己实现逻辑,可以加个极小的偏移量来修正double的精度问题:
public class Round { public int round(double value) { return (value > 0) ? roundPositiveNumber(value) : roundNegativeNumber(value); } private int roundPositiveNumber(double value) { // 加1e-10抵消精度误差,确保23.6*10能接近236 double checkD = (value * 10 + 1e-10) % 10; int check = (int) checkD; // 这里改成>=5,因为修正后check会变成6 if (check >= 5) { return (int) value + 1; } else { return (int) value; } } private int roundNegativeNumber(double value) { // 负数要减1e-10来修正 double checkD = (value * 10 - 1e-10) % 10; int check = (int) checkD; if (check > -5 && check < 0) { return (int) value - 1; } else { return (int) value; } } }
1e-10是个极小的数,不会影响正常数值,但能解决浮点数近似存储带来的误差。
3. 用BigDecimal做精确运算(适合高精度场景)
如果是金融这类对精度要求极高的场景,别用double了,直接上BigDecimal:
import java.math.BigDecimal; import java.math.RoundingMode; public class Round { public int round(double value) { BigDecimal bd = BigDecimal.valueOf(value); // HALF_UP就是标准四舍五入 return bd.setScale(0, RoundingMode.HALF_UP).intValue(); } }
这种方式完全避免了浮点数的精度问题,结果绝对准确。
补充说明
你说在main方法里转换正常?大概率是你测试的数值刚好是能被二进制精确表示的(比如0.5),但像0.1、0.6这种小数,二进制浮点数根本存不下精确值,就会触发你遇到的问题。
内容的提问来源于stack exchange,提问作者kejam
相关产品推荐
相关产品推荐

