Java统计double类型小数点后位数出现死循环的原因及解决方法
死循环触发原因
double是基于IEEE 754标准的二进制浮点数,绝大多数十进制小数无法被二进制精确存储,只会存储一个和目标值最接近的近似值。比如常见的0.1,实际存储的是约等于0.1的无限循环二进制小数对应的截断值,这类值每次乘10之后的结果永远不会刚好等于整数,只会无限接近。同时double的二进制有效位只有53位,对应十进制约15~17位有效数字,当乘10的次数超过这个范围后,数值精度会丢失,永远无法和强制转换为int后的整数值完全相等,就会触发死循环。
可行解决方案(无包装类/String类依赖)
核心思路是做两个优化:1. 新增循环次数上限,最多执行16次(覆盖double的最大有效十进制位长度),从根本上避免死循环;2. 放弃绝对相等判断,改用差值小于极小阈值的近似判断,容忍浮点计算的固有误差,只要差值足够小就认为当前值已经是整数。
修改后的代码如下:
import java.util.*; class Flt { public static void main(String args[]) { Scanner sc = new Scanner(System.in); // 误差阈值,可根据实际精度需求调整 final double EPS = 1e-10; // double最大有效十进制位长度,作为循环上限 final int MAX_COUNT = 16; System.out.print("Enter a double number: "); double f = sc.nextDouble(); double tmp = f; int len = 0; // 差值超过阈值且未到循环上限时继续执行 while(Math.abs(tmp - (int)tmp) > EPS && len < MAX_COUNT) { tmp *= 10; len++; } System.out.println(len); } }
修改后输入0.1、0.2这类原本会触发死循环的值,都能正确返回对应的小数位数,完全满足不使用包装类、String类方法的要求。
内容的提问来源于stack exchange,提问作者millionleafclover
相关产品推荐
相关产品推荐

