package org.goko.core.common.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.regex.Pattern;
import org.goko.core.common.exception.GkException;
import org.goko.core.common.exception.GkTechnicalException;
public class BigDecimalUtils {
private static final BigDecimal SQRT_DIG = new BigDecimal(10);
private static final BigDecimal SQRT_PRE = new BigDecimal(10).pow(SQRT_DIG.intValue());
/**
* Uses Newton Raphson to compute the square root of a BigDecimal.
*
* @author Luciano Culacciatti
* @url http://www.codeproject.com/Tips/257031/Implementing-SqrtRoot-in-BigDecimal
*/
private static BigDecimal sqrtNewtonRaphson (BigDecimal c, BigDecimal xn, BigDecimal precision){
BigDecimal fx = xn.pow(2).add(c.negate());
BigDecimal fpx = xn.multiply(new BigDecimal(2));
BigDecimal xn1 = fx.divide(fpx,2*SQRT_DIG.intValue(),RoundingMode.HALF_DOWN);
xn1 = xn.add(xn1.negate());
BigDecimal currentSquare = xn1.pow(2);
BigDecimal currentPrecision = currentSquare.subtract(c);
currentPrecision = currentPrecision.abs();
if (currentPrecision.compareTo(precision) <= -1){
return xn1;
}
return sqrtNewtonRaphson(c, xn1, precision);
}
public static BigDecimal sqrt(BigDecimal c, int scale){
double d = Math.sqrt(c.doubleValue());
// return sqrtNewtonRaphson(c,new BigDecimal(1),new BigDecimal(1).divide(SQRT_PRE));
return new BigDecimal( Math.sqrt(c.doubleValue())).setScale(scale, RoundingMode.HALF_DOWN);
}
public static String toString(BigDecimal value){
return toString(value, null);
}
public static String toString(BigDecimal value, Integer decimalCount){
DecimalFormat df = (DecimalFormat)NumberFormat.getNumberInstance();
DecimalFormatSymbols sym = df.getDecimalFormatSymbols();
sym.setDecimalSeparator('.');
if(decimalCount != null){
df.setMinimumFractionDigits(decimalCount);
df.setMaximumFractionDigits(decimalCount);
}
df.setDecimalFormatSymbols(sym);
df.setGroupingUsed(false);
df.setParseBigDecimal(true);
return df.format(value);
}
public static BigDecimal parse(String value) throws GkException{
try {
DecimalFormat df = (DecimalFormat)NumberFormat.getNumberInstance();
DecimalFormatSymbols sym = df.getDecimalFormatSymbols();
sym.setDecimalSeparator('.');
df.setDecimalFormatSymbols(sym);
df.setGroupingUsed(false);
df.setParseBigDecimal(true);
return (BigDecimal) df.parse(value);
} catch (ParseException e) {
throw new GkTechnicalException(e);
}
}
public static boolean isBigDecimal(String value){
DecimalFormat df = (DecimalFormat)NumberFormat.getNumberInstance();
df.setGroupingUsed(false);
DecimalFormatSymbols sym = df.getDecimalFormatSymbols();
String decimalSepStr = ".";//""+sym.getDecimalSeparator();
if(".".equals(decimalSepStr)){
decimalSepStr = "\\"+decimalSepStr;
}
String integerPart = "-?[0-9]+";
String decimalPart = "("+decimalSepStr+"[0-9]+)?";
String numberRegex = integerPart+decimalPart;
Pattern pattern = Pattern.compile(numberRegex);
return pattern.matcher(value).matches();
}
// public static BigDecimal parseUser(String value) throws GkException{
// try {
// DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(Locale.US);
// df.setParseBigDecimal(true);
// df.setGroupingUsed(false);
// return (BigDecimal) df.parseObject(value);
// } catch (ParseException e) {
// throw new GkTechnicalException(e);
// }
// }
//
// public static String formatUser(BigDecimal value) throws GkException{
// DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(Locale.US);
// return df.format(value);
// }
//
// public static boolean isBigDecimal(String value){
// //return new BigDecimalValidator().isValid(value, Locale.US);
// try {
// DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(Locale.US);
// df.setParseBigDecimal(true);
// df.setGroupingUsed(false);
// df.parseObject(value);
// return true;
// } catch (ParseException e) {
// return false;
// }
// }
}