ApFloat http://www.apfloat.org/ is a C/C++/Java math library that can calculate many trascendental operations such as square roots, exponentiations, logarithms, trigonometric/hyperbolic functions, numeric value of π, etc. with numbers of arbitrary precision, which are not available in the BigDecimal
Java class.
We all know that the expansion of 4/3 is infinite: 1.333.... so when we try to get it at any specific precision, no matters how long it is, there will be loss of information, but the rounding mode is important, too, i.e.
- 4/3 with precision of 5 and floor rounding mode is 1.3333
- 4/3 with precision of 5 and ceiling rounding mode is 1.3334
Unfortunately, the rounding mode cannot be specified when performing such those operations, maybe because "Due to different types of round-off errors that can occur in the implementation, no guarantees about e.g. monotonicity are given for any of the methods."
There is, however a method to round an ApFloat numbers with a specific precision and rounding mode http://www.apfloat.org/apfloat_java/docs/org/apfloat/ApfloatMath.html#round-org.apfloat.Apfloat-long-java.math.RoundingMode-
A simple solution could be calculating the operation with an extra precision and then rounding the result with the original precision and desired rounding mode, as the following example:
// 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
The questions are:
- Is this method [always] correct ? do you know any counterexample or false-positive ?
- Is 1 the least necessary value to be added to the precision in order to the extra information ensures a correct rounding ? I think adding 1 to the precision will not be enough, because the additional digit could be already rounded by the internal algorithm used to perform the calculation. Adding at least 2 positions would ensure the first digit -right to the desired precision- will be the the true digit present in the real -infinite- value of the number and not a rounded one.
- Do you realize a better method ? specially one where two-steps is avoided, because Apfloat -like BigDecimals- are immutable classes so new instances are created for every step, that could be problematic when using numbers with thousand or millions of precision places.