java - convertir - talend bigdecimal
Conversión de cadena segura a BigDecimal (9)
Así es como lo haría:
public String cleanDecimalString(String input, boolean americanFormat) {
if (americanFormat)
return input.replaceAll(",", "");
else
return input.replaceAll(".", "");
}
Obviamente, si esto fuera en código de producción, no sería tan simple.
No veo ningún problema con simplemente eliminar las comas de String.
Estoy tratando de leer algunos valores BigDecimal de la cadena. Digamos que tengo esta cadena: "1,000,000,000.999999999999999" y quiero obtener un BigDecimal de ella. ¿Cuál es la manera de hacerlo?
Antes que nada, no me gustan las soluciones que usan cadenas reemplaza (reemplazando comas, etc.). Creo que debería haber algún formateador aseado para hacer ese trabajo por mí.
Encontré una clase DecimalFormatter, sin embargo, como funciona a través del doble, se pierden enormes cantidades de precisión.
Entonces, ¿cómo puedo hacerlo?
Echa un vistazo a setParseBigDecimal
en DecimalFormat. Con este setter, Parse te devolverá un BigDecimal.
El código podría ser más limpio, pero esto parece ser el truco para diferentes lugares.
import java.math.BigDecimal;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
public class Main
{
public static void main(String[] args)
{
final BigDecimal numberA;
final BigDecimal numberB;
numberA = stringToBigDecimal("1,000,000,000.999999999999999", Locale.CANADA);
numberB = stringToBigDecimal("1.000.000.000,999999999999999", Locale.GERMANY);
System.out.println(numberA);
System.out.println(numberB);
}
private static BigDecimal stringToBigDecimal(final String formattedString,
final Locale locale)
{
final DecimalFormatSymbols symbols;
final char groupSeparatorChar;
final String groupSeparator;
final char decimalSeparatorChar;
final String decimalSeparator;
String fixedString;
final BigDecimal number;
symbols = new DecimalFormatSymbols(locale);
groupSeparatorChar = symbols.getGroupingSeparator();
decimalSeparatorChar = symbols.getDecimalSeparator();
if(groupSeparatorChar == ''.'')
{
groupSeparator = "//" + groupSeparatorChar;
}
else
{
groupSeparator = Character.toString(groupSeparatorChar);
}
if(decimalSeparatorChar == ''.'')
{
decimalSeparator = "//" + decimalSeparatorChar;
}
else
{
decimalSeparator = Character.toString(decimalSeparatorChar);
}
fixedString = formattedString.replaceAll(groupSeparator , "");
fixedString = fixedString.replaceAll(decimalSeparator , ".");
number = new BigDecimal(fixedString);
return (number);
}
}
El siguiente código de ejemplo funciona bien (la configuración regional debe obtenerse dinámicamente)
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.DecimalFormat;
import java.text.ParsePosition;
import java.util.Locale;
class TestBigDecimal {
public static void main(String[] args) {
String str = "0,00";
Locale in_ID = new Locale("in","ID");
//Locale in_ID = new Locale("en","US");
DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance(in_ID);
nf.setParseBigDecimal(true);
BigDecimal bd = (BigDecimal)nf.parse(str, new ParsePosition(0));
System.out.println("bd value : " + bd);
}
}
Necesitaba una solución para convertir un String en un BigDecimal sin conocer la configuración regional y ser independiente de la configuración regional. No pude encontrar ninguna solución estándar para este problema, así que escribí mi propio método de ayuda. Puede ser que ayude a alguien más también:
Actualización: ¡Advertencia! Este método de ayuda solo funciona para números decimales, ¡por lo que los números siempre tienen un punto decimal! De lo contrario, el método auxiliar podría arrojar un resultado incorrecto para números entre 1000 y 999999 (más / menos). ¡Gracias a Bezmax por su gran contribución!
static final String EMPTY = "";
static final String POINT = ''.'';
static final String COMMA = '','';
static final String POINT_AS_STRING = ".";
static final String COMMA_AS_STRING = ",";
/**
* Converts a String to a BigDecimal.
* if there is more than 1 ''.'', the points are interpreted as thousand-separator and will be removed for conversion
* if there is more than 1 '','', the commas are interpreted as thousand-separator and will be removed for conversion
* the last ''.'' or '','' will be interpreted as the separator for the decimal places
* () or - in front or in the end will be interpreted as negative number
*
* @param value
* @return The BigDecimal expression of the given string
*/
public static BigDecimal toBigDecimal(final String value) {
if (value != null){
boolean negativeNumber = false;
if (value.containts("(") && value.contains(")"))
negativeNumber = true;
if (value.endsWith("-") || value.startsWith("-"))
negativeNumber = true;
String parsedValue = value.replaceAll("[^0-9//,//.]", EMPTY);
if (negativeNumber)
parsedValue = "-" + parsedValue;
int lastPointPosition = parsedValue.lastIndexOf(POINT);
int lastCommaPosition = parsedValue.lastIndexOf(COMMA);
//handle ''1423'' case, just a simple number
if (lastPointPosition == -1 && lastCommaPosition == -1)
return new BigDecimal(parsedValue);
//handle ''45.3'' and ''4.550.000'' case, only points are in the given String
if (lastPointPosition > -1 && lastCommaPosition == -1){
int firstPointPosition = parsedValue.indexOf(POINT);
if (firstPointPosition != lastPointPosition)
return new BigDecimal(parsedValue.replace(POINT_AS_STRING, EMPTY));
else
return new BigDecimal(parsedValue);
}
//handle ''45,3'' and ''4,550,000'' case, only commas are in the given String
if (lastPointPosition == -1 && lastCommaPosition > -1){
int firstCommaPosition = parsedValue.indexOf(COMMA);
if (firstCommaPosition != lastCommaPosition)
return new BigDecimal(parsedValue.replace(COMMA_AS_STRING, EMPTY));
else
return new BigDecimal(parsedValue.replace(COMMA, POINT));
}
//handle ''2.345,04'' case, points are in front of commas
if (lastPointPosition < lastCommaPosition){
parsedValue = parsedValue.replace(POINT_AS_STRING, EMPTY);
return new BigDecimal(parsedValue.replace(COMMA, POINT));
}
//handle ''2,345.04'' case, commas are in front of points
if (lastCommaPosition < lastPointPosition){
parsedValue = parsedValue.replace(COMMA_AS_STRING, EMPTY);
return new BigDecimal(parsedValue);
}
throw new NumberFormatException("Unexpected number format. Cannot convert ''" + value + "'' to BigDecimal.");
}
return null;
}
Por supuesto que he probado el método:
@Test(dataProvider = "testBigDecimals")
public void toBigDecimal_defaultLocaleTest(String stringValue, BigDecimal bigDecimalValue){
BigDecimal convertedBigDecimal = DecimalHelper.toBigDecimal(stringValue);
Assert.assertEquals(convertedBigDecimal, bigDecimalValue);
}
@DataProvider(name = "testBigDecimals")
public static Object[][] bigDecimalConvertionTestValues() {
return new Object[][] {
{"5", new BigDecimal(5)},
{"5,3", new BigDecimal("5.3")},
{"5.3", new BigDecimal("5.3")},
{"5.000,3", new BigDecimal("5000.3")},
{"5.000.000,3", new BigDecimal("5000000.3")},
{"5.000.000", new BigDecimal("5000000")},
{"5,000.3", new BigDecimal("5000.3")},
{"5,000,000.3", new BigDecimal("5000000.3")},
{"5,000,000", new BigDecimal("5000000")},
{"+5", new BigDecimal("5")},
{"+5,3", new BigDecimal("5.3")},
{"+5.3", new BigDecimal("5.3")},
{"+5.000,3", new BigDecimal("5000.3")},
{"+5.000.000,3", new BigDecimal("5000000.3")},
{"+5.000.000", new BigDecimal("5000000")},
{"+5,000.3", new BigDecimal("5000.3")},
{"+5,000,000.3", new BigDecimal("5000000.3")},
{"+5,000,000", new BigDecimal("5000000")},
{"-5", new BigDecimal("-5")},
{"-5,3", new BigDecimal("-5.3")},
{"-5.3", new BigDecimal("-5.3")},
{"-5.000,3", new BigDecimal("-5000.3")},
{"-5.000.000,3", new BigDecimal("-5000000.3")},
{"-5.000.000", new BigDecimal("-5000000")},
{"-5,000.3", new BigDecimal("-5000.3")},
{"-5,000,000.3", new BigDecimal("-5000000.3")},
{"-5,000,000", new BigDecimal("-5000000")},
{null, null}
};
}
Por favor, intente esto, funciona para mí
BigDecimal bd ;
String value = "2000.00";
bd = new BigDecimal(value);
BigDecimal currency = bd;
Viejo tema, pero tal vez el más fácil es usar Apache commons NumberUtils que tiene un método createBigDecimal (valor de cadena) ....
Supongo (espero) que tenga en cuenta las configuraciones regionales o de lo contrario sería inútil.
String value = "1,000,000,000.999999999999999";
BigDecimal money = new BigDecimal(value.replaceAll(",", ""));
System.out.println(money);
Código completo para demostrar que no se arrojó NumberFormatException
:
import java.math.BigDecimal;
public class Tester {
public static void main(String[] args) {
// TODO Auto-generated method stub
String value = "1,000,000,000.999999999999999";
BigDecimal money = new BigDecimal(value.replaceAll(",", ""));
System.out.println(money);
}
}
Salida
1000000000.999999999999999
resultString = subjectString.replaceAll("[^.//d]", "");
eliminará todos los caracteres excepto los dígitos y el punto de su cadena.
Para que sea compatible con la configuración regional, es posible que desee utilizar getDecimalSeparator()
desde java.text.DecimalFormatSymbols
. No sé Java, pero podría verse así:
sep = getDecimalSeparator()
resultString = subjectString.replaceAll("[^"+sep+"//d]", "");