floating-point - 小数到二进制精度
问题描述
考虑以下分数:
9.8765
如何在不丢失任何价值的情况下将其转换为精确的浮点二进制?
现在考虑以下分数
9.87654321
同样,我如何将其转换为浮点二进制而不丢失其值。
我想确定从浮点二进制值重建分数需要多少精确的二进制位。
这只是一个示例,我希望对具有许多数字的大分数执行操作(例如 9.876543210192283647582910)。
欣赏该示例是否使用 Java。
谢谢!
解决方案
一般来说,一个有理数可以表示为一个基数 R 分数,当且仅当,在其最低条件下,分母的所有质因数都是 R 的因数。
将此应用于十进制,当且仅当在其最低项中 2 和 5 是分母的唯一质因数时,有理数具有终止的十进制扩展。因此 13/40 有一个终止的十进制扩展,而 1/3 没有。
对于二进制分数,这意味着将整数 A 和 B 的有理数表示为 A/2 B。因为 2 是 10 的因数,所以所有二进制分数都可以表示为十进制分数。5 不是 2 的因数,所以 1/10 等小数部分不能表示为二进制小数。
作为普通 Java 的精确表示还有其他条件double
。B 必须在 [-1022, 1023] 范围内,并且 A 必须有不超过 53 个有效位。还有其他次正规数,指数为 -1023。增加位数会放宽这些限制,但仍然不允许像 1/10 这样的数字以二进制浮点数精确表示。
两种最常见的解决方案是接受它,或者切换到BigDecimal
.
9.87650000000000005684341886080801486968994140625 非常非常接近 9.8765。对于长度和重量等物理量,即使使用良好的实验室设备,测量误差也将超过转换误差。当然,有些算法在后续计算中会因为四舍五入而累积较大的误差。
BigDecimal
对于带有终止小数扩展的数字特别有用。财务计算通常必须处理 0.01 或 0.001 的精确倍数。尽管它允许任意精度,直到可用内存,但它无法避免所有舍入误差。没有BigDecimal
正好等于 1/3。
推荐阅读
- angular6 - 如何获取激活路线的部分路段数据?[角度 6]
- javascript - 使用 jquery 解析 xml(格式错误的 xml)
- java - Javadoc,Eclipse 中的“未引发异常”
- python - 你能让我在networkx上的丑陋图表漂亮吗?
- jquery - jQuery过滤器不起作用
- search - 禁用 ezPublish 搜索功能
- .net - WPF,只能在 DependencyObject 的 DependencyProperty 上设置“绑定”
- java - 在 Spring Boot,JPA 中使用多个数据源时会降低性能
- javascript - 如何将对象文字作为键值对推送到数组?
- c# - 创建一个 ImmutableArray 而不复制