Issues with adding doubles. Arithmetic Coding

184 views Asked by At

So, basically I have this algorithm that codes a word using arithmetic coding. The matrix with the percentages(String[][] tabelaProbs and the word (String palavra) are the following :

Matrix:

 String tabelaProbs[][] = {{"A", "E", "I", "O", "U", "!"},{"0.2", "0.3", "0.1", "0.2", "0.1", "0.1"}};

Word:

String palavra = "EAII!"; (in lower case: " e a i i ! ")

The thing is, it's giving me the wrong result because some of sums with the doubles are giving the wrong result and that's affecting the final result aswell. The final result ( credencialCodificada ) is expected to be : 0.23354

Can anyone help?

   public static double codificarCredenciaisAcesso(String[][] tabelaProbs, String palavra) {
    double  aux = 0;
    String letra, palavraAux = "";
    int indice = 0;

    double[] probabilidadesAux = new double[tabelaProbs[1].length + 2];
    probabilidadesAux[0] = 0;
    for (int i = 0; i < tabelaProbs[1].length; i++) {
        aux += Double.parseDouble(tabelaProbs[1][i].trim());
        probabilidadesAux[i + 1] = aux;
    }
    probabilidadesAux[probabilidadesAux.length - 1] = 1;


    for (int indiceLetra = 0; indiceLetra < palavra.length(); indiceLetra++) {
        letra = palavra.charAt(indiceLetra) + "";
        palavraAux += letra;


        for (int iProb = 0; iProb < tabelaProbs[0].length; iProb++) {
            if (letra.equalsIgnoreCase(tabelaProbs[0][iProb])) {
                indice = iProb;
                break;
            }
        }

        double intervaloProb = probabilidadesAux[indice + 1] - probabilidadesAux[indice];
        for (int i = 0; i < probabilidadesAux.length; i++) {
            if (indice == i) {
                probabilidadesAux[0] = probabilidadesAux[indice];
                probabilidadesAux[probabilidadesAux.length - 1] = probabilidadesAux[indice + 1];
                aux = probabilidadesAux[0];
                for (int j = 1; j < probabilidadesAux.length - 1; j++) {
                    double probabilidadeX = Double.parseDouble(tabelaProbs[1][j - 1]);
                    probabilidadesAux[j] = aux + (probabilidadeX * intervaloProb);
                    aux = probabilidadesAux[j];
                }
                break;
            }
        }
    }
    double credencialCodificada = probabilidadesAux[indice];

    return credencialCodificada;
}
2

There are 2 answers

2
Jacob On

The problem is that doubles have accuracy less than their total size. So 3.0000004 is accurate to 4 decimal points, but it is longer than 4 decimal points.

This is also why you should avoid comparing or grouping by doubles.

Here is a link talking about something like that : how to fix double precision issue in java

0
The Javatar On

For example, if you sum 0.1 + 0.2 the result wont be 0.3 but rather something like 0.30000004. Its seems small but it will affect the final result

If you want arbitrary precision floating-point value I recomend you to use BigDecimal, a class found in java.math. More about it here()