Cómo analizar una cantidad de moneda (EE. UU. O UE) para flotar el valor en Java

En Europa, los decimales se separan con ', 'y utilizamos' @ opcion. 'para separar miles. Permito valores de moneda con:

Notación 123,456.78 de estilo estadounidense Estilo europeo 123.456,78 notación

Uso la siguiente expresión regular (de la biblioteca RegexBuddy) para validar la entrada. Permito fracciones opcionales de dos dígitos y separadores opcionales de miles.

^[+-]?[0-9]{1,3}(?:[0-9]*(?:[.,][0-9]{0,2})?|(?:,[0-9]{3})*(?:\.[0-9]{0,2})?|(?:\.[0-9]{3})*(?:,[0-9]{0,2})?)$

Me gustaría analizar una cadena de moneda en un flotante. Por ejempl

123,456.78 debe almacenarse como 123456.78
123.456,78 debe almacenarse como 123456.78
123.45 debe almacenarse como 123.45
1.234 debe almacenarse como 1234 12.34 debe almacenarse como 12.34

y así..

Existe una manera fácil de hacer esto en Java?

public float currencyToFloat(String currency) {
    // transform and return as float
}

Utilice BigDecimal en lugar de Float

Gracias a todos por las excelentes respuestas. He cambiado mi código para usar BigDecimal en lugar de flotante. Mantendré la parte anterior de esta pregunta con flotante para evitar que las personas cometan los mismos errores que yo iba a hacer.

Solució

El siguiente código muestra una función que se transforma de la moneda de EE. UU. Y la UE en una cadena aceptada por el constructor BigDecimal (String). Es decir una cadena sin mil separadores y un punto para fracciones.

   import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class TestUSAndEUCurrency {

    public static void main(String[] args) throws Exception {       
        test("123,456.78","123456.78");
        test("123.456,78","123456.78");
        test("123.45","123.45");
        test("1.234","1234");
        test("12","12");
        test("12.1","12.1");
        test("1.13","1.13");
        test("1.1","1.1");
        test("1,2","1.2");
        test("1","1");              
    }

    public static void test(String value, String expected_output) throws Exception {
        String output = currencyToBigDecimalFormat(value);
        if(!output.equals(expected_output)) {
            System.out.println("ERROR expected: " + expected_output + " output " + output);
        }
    }

    public static String currencyToBigDecimalFormat(String currency) throws Exception {

        if(!doesMatch(currency,"^[+-]?[0-9]{1,3}(?:[0-9]*(?:[.,][0-9]{0,2})?|(?:,[0-9]{3})*(?:\\.[0-9]{0,2})?|(?:\\.[0-9]{3})*(?:,[0-9]{0,2})?)$"))
                throw new Exception("Currency in wrong format " + currency);

        // Replace all dots with commas
        currency = currency.replaceAll("\\.", ",");

        // If fractions exist, the separator must be a .
        if(currency.length()>=3) {
            char[] chars = currency.toCharArray();
            if(chars[chars.length-2] == ',') {
                chars[chars.length-2] = '.';
            } else if(chars[chars.length-3] == ',') {
                chars[chars.length-3] = '.';
            }
            currency = new String(chars);
        }

        // Remove all commas        
        return currency.replaceAll(",", "");                
    }

    public static boolean doesMatch(String s, String pattern) {
        try {
            Pattern patt = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
            Matcher matcher = patt.matcher(s);
            return matcher.matches();
        } catch (RuntimeException e) {
            return false;
        }           
    }  

}

Respuestas a la pregunta(8)

Su respuesta a la pregunta