public final class DecimalFunctions extends Static
float
and double
values while taking in account their representation in base 10.
Methods in this class may be helpful when used after parsing or before formatting a number in base 10:
floatToDouble(float)
and deltaForDoubleToDecimal(double)
:
fractionDigitsForValue(double)
and
fractionDigitsForDelta(double, boolean)
:
MathFunctions.pow10(int)
,
Math.log10(double)
Defined in the sis-utility
module
Modifier and Type | Method and Description |
---|---|
static double |
deltaForDoubleToDecimal(double value)
Returns the difference between the given
double value and the representation of that value in base 10. |
static double |
floatToDouble(float value)
Converts the given
float value to a double with the extra decimal fraction digits
set to zero. |
static int |
fractionDigitsForDelta(double accuracy,
boolean strict)
Returns the number of fraction digits needed for formatting in base 10 numbers of the given
accuracy.
|
static int |
fractionDigitsForValue(double value)
Returns the number of significant fraction digits when formatting the given number in base 10.
|
static int |
fractionDigitsForValue(double value,
int uncertainDigits)
Returns the number of significant fraction digits, potentially minus trailing digits that may be rounding error.
|
public static double floatToDouble(float value)
float
value to a double
with the extra decimal fraction digits
set to zero. This is different than the standard cast in the Java language, which set the extra binary
fraction digits to zero.
For example (double) 0.1f
gives 0.10000000149011612 while floatToDouble(0.1f)
returns 0.1.
Float.parseFloat(String)
(directly or indirectly), and if that call can not be replaced by a call to
Double.parseDouble(String)
(for example because the original String
is not available anymore),
then this method may be useful if one consider the String
representation in base 10 as definitive.
But if the value come from an instrument measurement or a calculation, then there is probably no reason to use
this method because base 10 is not more "real" than base 2 or any other base for natural phenomenon.return Double.parseDouble(Float.toString(value));
value
- the float
value to convert as a double
.double
with the extra decimal fraction digits set to zero.public static double deltaForDoubleToDecimal(double value)
double
value and the representation of that value in base 10.
For any value in the method's domain of validity (defined below), this method is approximatively
equivalent to the following code except that it is potentially faster since the actual implementation
avoids the creation of BigDecimal
objects:
BigDecimal base2 = new BigDecimal(value); // Exact same value as stored in IEEE 754 format. BigDecimal base10 = BigDecimal.valueOf(value); // Exact same value as shown by println(value). return base10.subtract(base2).doubleValue();Computing
value + deltaForDoubleToDecimal(value)
has no effect since the absolute value of the
returned delta is always smaller than Math.ulp(value) / 2
.
To see an effect, a type with more precision than the double
type is necessary.
abs(value) < 3E-8
approximatively,
except for the 0 value which is supported. For any non-zero value closer to zero than the 3E-8
threshold, this method returns NaN
because of insufficient algorithm accuracy.
This limitation may change in any future SIS version if we find a better algorithm.value
- the value for which to get the delta compared to its base 10 representation.double
value for getting a result
closer to its base 10 representation, or NaN
if it can not be computed.public static int fractionDigitsForDelta(double accuracy, boolean strict)
strict
argument is true
, then for any given accuracy
this method returns a value n such as the difference between adjacent numbers
formatted in base 10 with n fraction digits will always be equal or smaller
than accuracy
. Examples:
fractionDigitsForDelta(0.001, true)
returns 3.fractionDigitsForDelta(0.009, true)
returns 3.fractionDigitsForDelta(0.010, true)
returns 2.fractionDigitsForDelta(0.099, true)
returns 3 (special case).Special cases:
accuracy
is NaN
or infinity, then this method returns 0
since those values are not represented by decimal digits.accuracy
is 0, then this method returns 324 since 10-324 is the first power of 10
smaller than the minimal strictly positive double
value (4.9E-324).
double
value is guaranteed to be rounded to exactly 0 no matter what the
next fraction digits are.accuracy
is greater than 1, then this method returns
the number of "unnecessary" trailing zeros as a negative number.
fractionDigitsForDelta(100, …)
returns -2.accuracy
are equal or greater than 95
(e.g. 0.00099) and the strict
argument is true
, then this method
increases the number of needed fraction digits in order to prevent the rounded
number to be collapsed into the next integer value.
accuracy
is 0.95, then a return value of 1 is not sufficient since
the rounded value of 0.95 with 1 fraction digit would be 1.0. Such value would be a
violation of this method contract since the difference between 0 and that formatted
value would be greater than the accuracy. Note that this is not an artificial rule;
this is related to the fact that 0.9999… is mathematically strictly equals to 1.(int)
-floor(log10(accuracy))
except for the 0, NaN
, infinities and 0.…95
special cases.accuracy
- the desired accuracy of numbers to format in base 10.strict
- true
for checking the 0.…95
special case.
If false
, then the difference between adjacent formatted numbers is not
guaranteed to be smaller than accuracy
in every cases.NumberFormat.setMaximumFractionDigits(int)
public static int fractionDigitsForValue(double value)
fractionDigitsForValue(1.0)
returns 16,
because the double
format can store almost 16 decimal digits after 1.
fractionDigitsForDelta(Math.ulp(value), false)
, except that it is
potentially faster.
Special cases:
value
is NaN
or infinity, then this method returns 0
since those values are not represented by decimal digits.value
is 0, then this method returns 324 since
Math.ulp(0)
= 4.9E-324.NumberFormat
for formatting all significant digits of a
double
value, padding with trailing zeros if necessary, but no more than necessary.value
- the value for which to get the number of significant fraction digits.value
is NaN or infinity.NumberFormat.setMinimumFractionDigits(int)
public static int fractionDigitsForValue(double value, int uncertainDigits)
fractionDigitsForValue(double)
. Then there
is a choice:
value
to an amount of fraction digits given by (fractionDigits
- uncertainDigits
) the 4 last fraction digits before the rounded ones are zero, then this method
returns fractionDigits
- uncertainDigits
.fractionDigits
.fractionDigitsForValue(179.12499999999824)
returns 14,
the amount of digits after the decimal separator.fractionDigitsForValue(179.12499999999824, 3)
returns 11 because rounding the 3 last digits
(i.e. rounding after the 11th digit) results in 179.125000000000.
Since the 4 last fraction digits are zero, the condition for allowing that rounding is meet.fractionDigitsForValue(179.12499999999824, 2)
returns 14 because rounding the 2 last digits
(i.e. rounding after the 12th digit) results in 179.124999999998.
The condition for 4 trailing zero fraction digits is not meet.fractionDigitsForValue(179.12499997999999, 3)
returns 14 because rounding the 3 last digits
results in 179.12499997000. The condition for 4 trailing zero fraction digits is not meet.value
- the value for which to get the number of significant fraction fraction digits minus rounding error.uncertainDigits
- number of trailing fraction digits which may be rounding error artefacts.value
is NaN or infinity.Copyright © 2010–2017 The Apache Software Foundation. All rights reserved.