How to get the length of a numbers fraction part?
How do I find out the length or the number of digits of the fraction part of a decimal number?
I can see a few aproaches, e.g. with Strings like this one:
public static in开发者_Go百科t getNumberOfFractionDigits(Number number) {
Double fractionPart = number.doubleValue() - number.longValue();
return fractionPart.toString().length() - 2;
}
But what is the best way to determine the length?
I could imagine some problems if I use Strings, e.g. because the locale and number format may be different from system to system. Is there a nice way to calculate it? Maybe without iteration?
Thanks in advance.
Try this:
public static int getNumberOfFractionDigits(Number number) {
if( number == null ) return 0; //or throw
if( number.doubleValue() == 0.0d ) return 0;
BigDecimal bd = new BigDecimal(number.toString());
//BigDecimal bd = BigDecimal.valueOf(number.doubleValue()); // if double precision is ok, just note that you should use BigDecimal.valueOf(double) rather than new BigDecimal(double) due to precision bugs in the latter
bd = bd.stripTrailingZeros(); //convert 1.00 to 1 -> scale will now be 0, except for 0.0 where this doesn't work
return bd.scale();
}
Edit:
If the number is actually an iteger (i.e. fraction of 0) this would still return 1. Thus you might check whether there actually is a fractional part first.
Edit2:
stripTrailingZeros()
seems to do the trick, except for 0.0d. Updated the code accordingly.
I just wrote a simple method for this, hope it can help someone.
public static int getFractionDigitsCount(double d) {
if (d >= 1) { //we only need the fraction digits
d = d - (long) d;
}
if (d == 0) { //nothing to count
return 0;
}
d *= 10; //shifts 1 digit to left
int count = 1;
while (d - (long) d != 0) { //keeps shifting until there are no more fractions
d *= 10;
count++;
}
return count;
}
You may use java.text.NumberFormat.
nf = java.text.NumberFormat.getInstance ();
// without BigDecimal, you will reach the limit far before 100
nf.setMaximumFractionDigits (100);
String s = nf.format (number.doubleValue ())
You may set the Decimal-Identifier as you like, and use regular expressions to cut off the leading part, and String.length () to evaluate the rest.
Looks like many offered the Big Decimal. It's easy on the eyes at least. The code shall work for ya.
package t1;
import java.math.*;
public class ScaleZ {
private static final int MAX_PRECISION = 10;
private static final MathContext mc = new MathContext(MAX_PRECISION, RoundingMode.HALF_EVEN);
public static int getScale(double v){
if (v!=v || v == Double.POSITIVE_INFINITY || v == Double.NEGATIVE_INFINITY)
return 0;//throw exception or return any other stuff
BigDecimal d = new BigDecimal(v, mc);
return Math.max(0, d.stripTrailingZeros().scale());
}
public static void main(String[] args) {
test(0.0);
test(1000d);
test(1d/3);
test(Math.PI);
test(1.244e7);
test(1e11);
}
private static void test(double d) {
System.out.printf("%20s digits %d%n", d, getScale(d));
}
}
That was my best implementation:
public class NumberHandler {
private static NumberFormat formatter = NumberFormat.getInstance(Locale.ENGLISH);
static {
formatter.setMaximumFractionDigits(Integer.MAX_VALUE);
formatter.setGroupingUsed(false);
}
public static int getFractionLength(double doubleNumber) {
String numberStr = formatter.format(doubleNumber);
int dotIndex = numberStr.indexOf(".");
if (dotIndex < 0) {
return 0;
} else {
return numberStr.length() - (dotIndex + 1);
}
}
}
Not effective, probably not perfect, but the other options was worse.
public static int getNumberOfFractionDigits(double d) {
String s = Double.toString(d), afterDecimal="";
afterDecimal = s.subString(s.indexOf(".") + 1, s.length() - 1);
return afterDecimal.length();
}
精彩评论