大家好,欢迎来到《猫头虎技术团队》的技术分享!今天,我们要讨论一个在编程和计算中非常常见但又令人头疼的问题:“Non-terminating Decimal Expansion”,即无限循环小数,以及它如何影响浮点数的精确表示。
大家好,我是 猫头虎,猫头虎技术团队创始人,也被大家称为猫哥。我目前是COC北京城市开发者社区主理人、COC西安城市开发者社区主理人,以及云原生开发者社区主理人,在多个技术领域如云原生、前端、后端、运维和AI都具备丰富经验。
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用方法、前沿科技资讯、产品评测、产品使用体验,以及产品优缺点分析、横向对比、技术沙龙参会体验等。我的分享聚焦于云服务产品评测、AI产品对比、开发板性能测试和技术报告。
目前,我活跃在CSDN、51CTO、腾讯云、阿里云开发者社区、知乎、微信公众号、视频号、抖音、B站、小红书等平台,全网粉丝已超过30万。我所有平台的IP名称统一为猫头虎或猫头虎技术团队。
我希望通过我的分享,帮助大家更好地掌握和使用各种技术产品,提升开发效率与体验。
作者名片 ✍️
部分专栏链接
:
🔗 精选专栏:
在计算机科学中,浮点数(float
或 double
)用于表示非常大的或非常小的数。然而,由于计算机的存储和表示限制,有些小数不能精确地用二进制浮点数表示,这会导致无限循环小数的问题。
我们来看看这个问题的典型例子:
0.0001100110011...
,这个无限循环的小数无法精确地存储在计算机中。0.1 + 0.2 != 0.3
,而是出现 0.30000000000000004
的原因。计算机使用二进制(0 和 1)来表示所有数字,而我们日常生活中使用的是十进制。许多十进制数无法在二进制中精确表示。比如:
0.0001100110011...
,这是一个无限的二进制循环。这意味着,许多“看起来非常简单”的十进制数在计算机中会变成无限的小数,无法精确存储。
在计算机中,浮点数是有限位数的表示。对于 Java 中的 float
和 double
类型,它们是 32 位和 64 位的二进制格式,分别对应有限的精度。
由于精度的限制,当一个数无法精确表示时,它会进行四舍五入,导致误差积累。这就是为什么即使看起来是简单的加法,结果却不是我们期待的准确值。
解决非终止小数扩展和浮点数精度问题有几种常见方法,我们可以选择最适合具体应用的方式。
BigDecimal
类Java 中的 BigDecimal
类专门用于精确表示和处理任意精度的十进制数。它是为了避免浮点数精度问题而设计的,尤其适用于财务计算和其他要求高精度的场景。
BigDecimal
允许我们指定精确的小数位数,从而避免了浮点数引起的误差。
import java.math.BigDecimal;
public class BigDecimalExample {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
BigDecimal sum = a.add(b);
System.out.println(sum); // 输出 0.3
}
}
优势:
缺点:
float
或 double
,BigDecimal
的计算速度较慢,因为它是通过字符串或数组进行运算的。使用浮点数时,增加精度并使用合适的 舍入模式 可以有效减少由于非终止小数带来的误差。在 Java 中,你可以通过 MathContext
和 RoundingMode
来控制 BigDecimal
运算的精度和舍入方式。
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BigDecimalPrecisionExample {
public static void main(String[] args) {
BigDecimal a = new BigDecimal("0.1");
BigDecimal b = new BigDecimal("0.2");
BigDecimal sum = a.add(b).setScale(1, RoundingMode.HALF_UP); // 设置精度为 1
System.out.println(sum); // 输出 0.3
}
}
优势:
缺点:
float
和 double
时避免比较相等在使用 float
或 double
类型时,避免直接比较两个浮点数是否相等。由于精度问题,浮点数的计算结果可能会有微小差异,直接比较可能导致错误。
public class FloatComparison {
public static void main(String[] args) {
double a = 0.1 + 0.2;
double b = 0.3;
if (Math.abs(a - b) < 1E-9) { // 使用一个足够小的容差
System.out.println("a is approximately equal to b");
} else {
System.out.println("a is not equal to b");
}
}
}
优势:
缺点:
如果业务逻辑允许,可以使用整数来代替浮点数进行计算。例如,处理财务数字时,将金额以分为单位进行存储和计算,而不是直接使用小数。
public class IntegerMoneyExample {
public static void main(String[] args) {
int priceInCents = 99; // 99 分
int quantity = 3;
int total = priceInCents * quantity; // 计算总价,仍然是整数
System.out.println("Total price: " + total + " cents");
}
}
优势:
缺点:
在编程中遇到 “Non-terminating Decimal Expansion”(非终止小数扩展)的问题是由于计算机无法精确表示某些十进制小数,特别是在二进制浮点数表示时。要解决这个问题,我们可以采用以下几种方法:
BigDecimal
类进行高精度计算;通过这些方法,我们可以有效避免由于浮点数精度导致的计算错误,确保程序的准确性和健壮性。如果你有更好的解决方案,欢迎在评论区与大家分享!
👉 更多信息:有任何疑问或者需要进一步探讨的内容,欢迎点击文末名片获取更多信息。我是猫头虎博主,期待与您的交流! 🦉💬
点击✨⬇️下方名片
⬇️✨,加入猫头虎AI共创社群矩阵。一起探索科技的未来,共同成长。🚀