【问题标题】:Rounding at specific precision with ApFloat使用 ApFloat 以特定精度舍入
【发布时间】: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


【解决方案1】:

给你,希望对你有帮助

public static void main(String[] args) {
    Apfloat two = new Apfloat(2, 15); // Line 1: If you want precision be 10, than you can´t get result 1.41421356237309 on Line 4, because result have more than 10 numbers after . (decimal dot)
                                      // you can add new Apfloat variable with precision 15 for line 4 and for line 5,6 with precision 10
    System.out.print("Line2: Expected: 2 Result:" + two + "\n"); // Line 2:
    Apfloat sqrt = ApfloatMath.sqrt(two); // Line 3:
    System.out.print("Line4: Expected: 1.41421356237309 Result:" + sqrt + "\n"); // Line 4:
    System.out.print("Line5: Expected: 1.414213562 Result:" + ApfloatMath.round(sqrt, 10, RoundingMode.FLOOR) + "\n"); // Line 5:
    System.out.print("Line6: Expected: 1.414213563 Result:" + ApfloatMath.round(sqrt, 10, RoundingMode.CEILING) + "\n"); // Line 6:
}

结果:

【讨论】:

  • 嗨。那么问题不是关于编码,而是关于确保正确舍入值的建议方法的有效性,因为 Apfloat 库提供的结果是未定义的(在文档中),不知道这些结果是否被截断、下限、上限,四舍五入,四舍五入等。谢谢
猜你喜欢
  • 2015-02-04
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-06
  • 2012-09-15
  • 1970-01-01
相关资源
最近更新 更多