Strange error when adding value while iterating through a collection in Java

I recently wrote a program that does Ant Colony Optimization on a graph.

There is an error in the following code that I cannot figure out.

    Map<Node, Edge> nodesLinkedToCurrentNode = a.getCurrentNode().getLinkedNodes();

    TreeMap<Double, Node> probabilitiesForNodes = new TreeMap<>();
    double totalProb = 0d;

    for (Node n : graph.values()) {
        if (!a.getVisited().contains(n)) {
            //For each node that has not yet been visited
            //calculate it weighted probabily
            double weightedProbability
                    = (Math.pow(nodesLinkedToCurrentNode.get(n).getPheremoneLevel(), RPI))
                    * (Math.pow((double) 1 / nodesLinkedToCurrentNode.get(n).getDistance(), RHI));
            totalProb += weightedProbability;

            //Map the node to its probability
            probabilitiesForNodes.put(weightedProbability, n);
        }
    }

    double testTotalProb = 0d;
    for (Double d : probabilitiesForNodes.keySet()) {
        testTotalProb += d;
    }
    if (testTotalProb != totalProb) { <----------How can this happen??
        System.out.println("Why?");
        totalProb = testTotalProb;
    }

      

This if statement is being executed all the time and I don't understand why.

I am just increasing the value, but for some reason it will not increase correctly.

I made an open source project if you want to check it out

Java file with code in it

I reproduced the error with the following code:

    TreeMap<Double, String> probabilitiesForNodes = new TreeMap<>();
    double totalProb = 0d;

    for (int i = 1; i < 10; i++) {
        //For each node that has not yet been visited
        //calulate it weighted probabily
        double weightedProbability
                = (Math.pow(0.7 + 1 / i, 2))
                * (Math.pow((double) 1 / 30, i));
        totalProb += weightedProbability;

        String sudoNode = "node" + i;

        //Map the node to its probability
        probabilitiesForNodes.put(weightedProbability, sudoNode);
    }

    double testTotalProb = 0d;
    for (Double d : probabilitiesForNodes.keySet()) {
        testTotalProb += d;
    }
    if (testTotalProb != totalProb) {
        System.out.println("Why?");
        totalProb = testTotalProb;
    }

      

+3


source to share


1 answer


You are working with numbers double

, so you should expect this. Specifically, you get totalProb

and testTotalProb

by iteratively adding the same numbers double

, but in a different order. Since adding doubles is not exactly an associative operation, there is enough inconsistency to make your equality test fail.



Another thing that can happen is collision with the same key double

. There is nothing that stops two nodes having exactly the same weighted probability. So for starters, you can just check the sizes of the two collections.

+4


source







All Articles