如何检测和修复-0.0与0.0的双值/对象?

时间:2017-05-29 09:16:26

标签: java

我的问题似乎是一个宣传。但是我没找到,我在找什么。

Double.compare()和Double.equals()都存在-0.0的困难。我在一个小的代码片段中检查了这个行为,并希望与其他人分享这个行为。

我的问题是,如何在一组中避免-0.0值:

if (Math.abs(dv - 0.0) < 1E-14)) dv = 0.0; // possiby a -0.0 value
set.add(dv);

在将-0.0添加到集合之前,应将其强制为0.0。 是否有推荐的解决方案:

if (dv > -1E-14 && dv < 1E-14) dv = 0.0;
set.add.(dv);

或:

import java.util.*;

public class TesterMain
{

public static void main(String[] args) 
{   
try
{   
  ArrayList<Double> list = new ArrayList<Double>();
  double eps10 = 1E-10,eps15 = 1E-15,eps16 = 1E-16;

  Double d_proper_0 = new Double(0.0);
  Double dv = new Double(-0.0); 
  double a = -0.0,b = 0.0;

  list.add(d_proper_0);  
  list.add(dv); 

  Double d12 = new Double(12.0);
  list.add(d12 - eps10);
  list.add(d12 + eps15);  list.add(d12 - eps15);
  list.add(d12 + eps16); // rounded to 12.0 
  Double dx = new Double(12.123456789012345678); 
  // results in rounded value 12.123456789012346 with 15 after-dot-digits  
  list.add(dx); 

  System.out.println("--- java has 0.0 and -0.0, unfortunately they are different values");
  System.out.println("Wrong: equals of " + dv + " and " + d_proper_0 + " is: " + dv.equals(d_proper_0));   
  boolean res = dv.doubleValue() == d_proper_0.doubleValue();
  System.out.println("Correct: '" + dv + ".doubleValue() == " + d_proper_0 + ".doubleValue() ? ' returns " + res); 
  System.out.println("Correct: double variable " + a + " == 0.0 returns: " + (a==0.0));
  System.out.println("Wrong: compare " + dv + " with " + d_proper_0 + ": " + Double.compare(dv,d_proper_0));
  System.out.println("Wrong: compare double variables " + a + " with " + b + ": " + Double.compare(a,b));

  java.util.Collections.sort(list);  
  System.out.println("\n--- Sorting result is correct: "+list.toString());

  System.out.println("\ncontains() test: " + dv + ": " + list.contains(dv)); 
  System.out.println("contains() test: " + dx + ": " + list.contains(dx)); 

  System.out.println("\n---  -0.0 values, where do they come from ? Result of calculating or parsing strings");
  Double dv3 = new Double(1.0); 
  Double dv4 = dv * dv3;
  System.out.println("Double objects: " + dv + " * " + dv3 + " = " + dv4); //Result: -0.0 * 1.0 = -0.0

  try { dv4 = Double.parseDouble("-0.0"); } catch (NumberFormatException e) { System.out.println(e);};    
  System.out.println("Parsing a string results in: " + dv4); //Parsing a string results in: -0.0

  double db1 = 0.0,db2 = -1.0;
  System.out.println("double values: " + db1 + " * " + db2 + " = " + (db1 * db2)); // Result: 0.0 * -1.0 = -0.0

  System.out.println("\n--- How to detect and fix a -0.0 value ?");
  Double diff = Math.abs(dv - 0.0);
  System.out.println("Difference between " + dv + " and 0.0 is: " + diff);  
  if (diff < 1E-14) // if (Math.abs(dv - 0.0) < 1E-14)
  {   dv = 0.0;
      System.out.println("-0.0 fixed now: " + dv);
  }
  System.out.println("\n--- Repeating the tests for the fixed -0.0");
  System.out.println("Correct: equals of " + dv + " and " + d_proper_0 + " is: " + dv.equals(d_proper_0)); 
  System.out.println("'" + dv + ".doubleValue() == " + d_proper_0 + ".doubleValue() ?' returns: " + (dv.doubleValue() == d_proper_0.doubleValue())); 
  System.out.println("compare " + dv + " with " + d_proper_0 + ": " + Double.compare(dv,d_proper_0));

} catch (Exception e)
{   
    e.printStackTrace();   
}
    System.exit(1);      
} //---------------------------------------------------- end of main()
} // end class

任何想法都很好。

要分享的代码段:

--- java has 0.0 and -0.0, unfortunately they are different values
Wrong: equals of -0.0 and 0.0 is: false
Correct: '-0.0.doubleValue() == 0.0.doubleValue() ? ' returns true
Correct: double variable -0.0 == 0.0 returns: true
Wrong: compare -0.0 with 0.0: -1
Wrong: compare double variables -0.0 with 0.0: -1

--- Sorting result is correct: [-0.0, 0.0, 11.9999999999, 11.999999999999998, 12.0, 12.000000000000002, 12.123456789012346]

contains() test: -0.0: true
contains() test: 12.123456789012346: true

---  -0.0 values, where do they come from ? Result of calculating or parsing strings
Double objects: -0.0 * 1.0 = -0.0
Parsing a string results in: -0.0
double values: 0.0 * -1.0 = -0.0

--- How to detect and fix a -0.0 value ?
Difference between -0.0 and 0.0 is: 0.0
-0.0 fixed now: 0.0

--- Repeating the tests for the fixed -0.0
Correct: equals of 0.0 and 0.0 is: true
'0.0.doubleValue() == 0.0.doubleValue() ?' returns: true
compare 0.0 with 0.0: 0

输出是:

epochs = 1

2 个答案:

答案 0 :(得分:0)

static double convertNegativeZero(double value) {
    if (value == 0.0) {
        value = 0.0;  // convert -0.0 to +0.0
    }

    return value;
}

答案 1 :(得分:0)

将元素添加到Set时,它会使用hashCodeequals方法来确定对象的唯一性。现在,这是Double equals()方法javadoc所说的:

  

如果d1代表+0.0而d2代表-0.0,反之亦然   等值测试的值为false,即使+0.0 == - 0.0具有该值   真。

因此,如果你想使+0.0和-0.0相等,你手动需要比较和更改值,例如:

Double dv = -0.0; //can be any value
if(dv.doubleValue() == 0){
    dv = +0.0;
}