for循环累加double类型0.1出现精度偏差的原因及规避方法
为什么累加0.1会得到0.7999999999999999而非0.8?
精度偏差的成因
double类型遵循IEEE 754双精度浮点数标准,它用二进制存储小数。但十进制的0.1无法被二进制有限小数精确表示——就像十进制里没法写尽1/3的循环小数一样,0.1的二进制是无限循环的,只能用一个近似值(实际是0.10000000000000000555...)来存储。
每次循环累加的都是这个近似值,多次累加后,微小的误差不断累积,最终导致结果偏离了预期的0.8。
避免舍入问题的方案
- 使用
BigDecimal类:这是Java中处理精确小数计算的标准方案,尤其适合货币、高精度要求的场景。注意必须通过字符串构造BigDecimal,避免用double构造带入精度问题:
import java.math.BigDecimal; public class Main { public static void main(String[] args) { BigDecimal d1 = BigDecimal.ZERO; BigDecimal pointOne = new BigDecimal("0.1"); for (int i = 1; i <= 8; i++) { d1 = d1.add(pointOne); } System.out.println(d1); // 输出0.8 } }
- 改用整数运算:如果是固定小数位数的场景(比如保留1位小数),可以把数值放大为整数计算,最后再缩小回去。比如把0.1等价为1,累加8次得到8后再除以10:
int d1 = 0; for (int i = 1; i <= 8; i++) { d1 += 1; } System.out.println(d1 / 10.0); // 输出0.8
- 输出时做舍入处理:如果只是显示时的精度问题,可以在输出时指定小数位数进行四舍五入:
double d1 = 0; for (int i = 1; i <= 8; i++) { d1 += 0.1; } System.out.printf("%.1f%n", d1); // 输出0.8
内容的提问来源于stack exchange,提问作者Elias
相关产品推荐
相关产品推荐

