【发布时间】:2017-03-03 04:11:42
【问题描述】:
ApFloat http://www.apfloat.org/ 是一个 C/C++/Java 数学库,可以计算任意精度的数字,如平方根、指数、对数、三角函数/双曲函数、π 的数值等许多超越运算。在BigDecimal Java 类中不可用。
我们都知道 4/3 的展开是无限的:1.333....所以当我们试图以任何特定的精度得到它时,不管它有多长,都会丢失信息,但是四舍五入模式也很重要,即
- 4/3,精度为 5,地板舍入模式为 1.3333
- 4/3 与 精度为 5,上限舍入模式为 1.3334
不幸的是,在执行此类操作时无法指定舍入模式,可能是因为“由于实现中可能出现不同类型的舍入错误,因此无法保证任何方法的单调性。”
不过,有一种方法可以用特定的精度和舍入模式对 ApFloat 数字进行舍入 http://www.apfloat.org/apfloat_java/docs/org/apfloat/ApfloatMath.html#round-org.apfloat.Apfloat-long-java.math.RoundingMode-
一个简单的解决方案可以是计算具有额外精度的运算,然后以原始精度和所需的舍入模式对结果进行舍入,如下例所示:
// Trying to get the square root of 2
// with precision of 10
// and different roundig modes
Apfloat two = new Apfloat(2, 15); // precision is 15, not 10
// result: 2
Apfloat sqrt = ApfloatMath.sqrt(two);
// result: 1.41421356237309
ApfloatMath.round(sqrt, 10, RoundingMode.FLOOR);
// result: 1.414213562
ApfloatMath.round(sqrt, 10, RoundingMode.CEILING);
// result: 1.414213563
问题是:
- 这种方法[总是]正确吗?你知道任何反例或误报吗?
- 1 是否是添加到精度中的最少必要值,以便额外信息确保正确舍入?我认为在精度上加 1 是不够的,因为额外的数字可能已经被用于执行计算的内部算法四舍五入了。添加至少 2 个位置将确保第一个数字 - 正确的所需精度 - 将是数字的实数 - 无限 - 值中存在的真实数字,而不是四舍五入的数字。
- 你有更好的方法吗?特别是避免两步的情况,因为 Apfloat 与 BigDecimal 类似,是不可变的类,因此每一步都会创建新实例,这在使用具有数千或数百万个精度位的数字时可能会出现问题。
【问题讨论】:
-
你能发布一个输入-输出-预期输出的例子吗?谢谢
-
我希望提供的示例可以帮助澄清问题。问候
-
前段时间我有一个类似的问题。我发现即使对于许多数字 BigDecimal(例如 1000 或更高的精度),中间结果的额外精度 5 就足够了,至少对于正确编码的三角函数来说是这样。尚未测试任何其他功能。
标签: java rounding bigdecimal arbitrary-precision apfloat