Java double equality

天大地大妈咪最大 提交于 2019-12-13 04:06:43

问题


I'm having a problem in comparing doubles. The comparison is responsible for stopping a while cycle. The code runs fine, but then suddenly, the cycle never stops. The values from centroidList's dimVal are being compared to the temp variable which is calculated(the bold bit). The code always enters the if, it doesn't matter if I use "!=" or "==". Printed out the values, they are exactly the same. What is wrong?

    package clusters;

import java.util.LinkedList;

public class KMeansV2 {

    LinkedList<Record> table;
LinkedList<Centroid> centroidList;
LinkedList<Double> intervalList;
boolean clusterStop;

int meassureType;
int prec=10000000;

KMeansV2()
{
    Read read=new Read(true,"BrCa_HD_full.xlsx");
    table=new LinkedList<Record>(read.table);
    centroidList=new LinkedList<Centroid>();
    CreateCentroids(2);
    SetMeassureType(1);
    while(clusterStop==false)
    {
        UpdateRecords();
        UpdateClusters();
    }
    Output();
}

public void SetMeassureType(int meassureType)
{
    this.meassureType=meassureType;
}

public void CreateCentroids(int centroidCount)
{
    if(centroidList.isEmpty())
    {
        for(int i=0;i<centroidCount;i++)
        {
                centroidList.add(new Centroid(table.get(0).values.size(),i));
        }
    }
    else
    {
        centroidList.clear();
        for(int i=0;i<centroidCount;i++)
        {
                centroidList.add(new Centroid(table.get(0).values.size(),i));
        }
    }

}

public void UpdateRecords()
{
    for(int i=0;i<table.size();i++)
    {
        table.get(i).Update(centroidList, meassureType);
    }
}

public void UpdateClusters()
{
    clusterStop=true;
    for(int i=0;i<centroidList.size();i++) //staiga pa centroidiem
    {
        for(int j=0;j<table.get(0).values.size();j++) //staiga pa kolonnam
        {
            double sum=0;
            double count=0;
            for(int k=0;k<table.size();k++) //staiga pa rindam
            {
                if(centroidList.get(i).type==table.get(k).type)
                {
                    sum+=table.get(k).values.get(j);
                    count++;
                }
            }
            System.out.println(clusterStop);

            double temp=(1/count)*sum;

            **if(centroidList.get(i).dimVal.get(j)==temp);
            {
                System.out.println(centroidList.get(i).dimVal.get(j)+" != "+(1/count)*sum);
                clusterStop=false;
            }**

            centroidList.get(i).dimVal.set(j,temp);
        }
        System.out.println(clusterStop);
    }
}

public void Output()
{
    LinkedList<String> types=new LinkedList<String>();
    for(int i=0;i<table.size();i++)
    {
        if(!types.contains(table.get(i).realType))
        {
            types.add(table.get(i).realType);
        }   
    }   

    for(int i=0;i<centroidList.size();i++) //staiga pa centroidiem
    {       
        for(int j=0;j<types.size();j++) //staiga pa klasem
        {
            int count=0;
            for(int k=0;k<table.size();k++) // staiga pa rindam
            {
                if(table.get(k).type==i && table.get(k).realType.equals(types.get(j)))
                {
                        count++;    
                }
            }
            System.out.println("Centroid "+(i+1)+" has "+count+" of type "+types.get(j));
            //kMeansUI.UpdateLog("Centroid "+(i+1)+" has "+count+" of type "+types.get(j));
        }
    }

    for(int i=0;i<centroidList.size();i++)
    {
        int count=0;
        for(int j=0;j<table.size();j++)
        {
            if(table.get(j).type==i)
            {
                count++;
            }
        }
        System.out.println("Cluster "+i+" has "+count+" records.");
        //kMeansUI.UpdateLog("Cluster "+(i+1)+" has "+count+" records.");
    }
    //kMeansUI.UpdateLog("/-------------------------------------------------------------------------/");

}

public static void main(String[] args)
{
    KMeansV2 test=new KMeansV2();
}

}


回答1:


Due to representation of decimal numbers in computer memory (float, double) you shouldn't compare them directly - you should use deltas:

  double x = 123.123;
  double y = 123.1234;
  double delta = 0.01;

  boolean areEqual = Math.abs(x - y) <= delta

But I strongly recommend you using some other types which are applicable. Maybe in your case integer/long is suitable? If no, and you need exact precision please use BigDecimal class instances. Also please remember to construct them from strings.

Regarding the console output, java is tricking on you (; - it's using some kind of approximation (in memory 0.1 is 'almost' 0.1, it's rather closer to 0.(9)).




回答2:


Due to floating point numbers (double is double precision float) are treated by the vast majority of modern processors, performing operations on them rarely gets you an exact value.

So you have basically to options. Either round your values before the comparison OR make some comparison method yourself which allows for some error margin.




回答3:


if(centroidList.get(i).dimVal.get(j) <--- are you sure that that is returning a double? Be aware when printing out variables in order to check their equality. Their string representation is not always the same as their equality representation.



来源:https://stackoverflow.com/questions/15782529/java-double-equality

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!