strange results of Double.MIN_VALUE is collection sort

K

Kevin

A strange results of some simple code:

The code:

ArrayList al = new ArrayList();
al.add("-3.5");
al.add("+5");
al.add("+myinf");
al.add("-myinf");
al.add("+10");
System.out.println(al.toString());
Collections.sort(al, new Comparator()
{
public int compare(Object o1, Object o2)
{
Double D1 = null;
if ( ((String) o1).compareTo("-myinf") ==0)
D1 = new Double(Double.MIN_VALUE);
else
if ( ((String) o1).compareTo("+myinf") ==0)
D1 = new Double(Double.MAX_VALUE);
else
D1 = new Double((String) o1);
//
Double D2 = null;
if ( ((String) o2).compareTo("-myinf") ==0)
D2 = new Double(Double.MIN_VALUE);
else
if ( ((String) o2).compareTo("+myinf") ==0)
D2 = new Double(Double.MAX_VALUE);
else
D2 = new Double((String) o2);
//
return D1.compareTo(D2);
}
});
System.out.println(al.toString());


The output:
[-3.5, +5, +myinf, -myinf, +10]
[-3.5, -myinf, +5, +10, +myinf]

Any idea why -3.5 is sorted before (smalller than) -myinf?
 
P

Patricia Shanahan

Kevin said:
A strange results of some simple code:

The code:

ArrayList al = new ArrayList();
al.add("-3.5");
al.add("+5");
al.add("+myinf");
al.add("-myinf");
al.add("+10");
System.out.println(al.toString());
Collections.sort(al, new Comparator()
{
public int compare(Object o1, Object o2)
{
Double D1 = null;
if ( ((String) o1).compareTo("-myinf") ==0)
D1 = new Double(Double.MIN_VALUE);
else
if ( ((String) o1).compareTo("+myinf") ==0)
D1 = new Double(Double.MAX_VALUE);
else
D1 = new Double((String) o1);
//
Double D2 = null;
if ( ((String) o2).compareTo("-myinf") ==0)
D2 = new Double(Double.MIN_VALUE);
else
if ( ((String) o2).compareTo("+myinf") ==0)
D2 = new Double(Double.MAX_VALUE);
else
D2 = new Double((String) o2);
//
return D1.compareTo(D2);
}
});
System.out.println(al.toString());


The output:
[-3.5, +5, +myinf, -myinf, +10]
[-3.5, -myinf, +5, +10, +myinf]

Any idea why -3.5 is sorted before (smalller than) -myinf?

Double.MIN_VALUE is defined to be "smallest positive nonzero value of
type double" [API javadocs for java.lang.Double]. As a positive number,
it is greater than any negative number, including -3.5.

Either "+myinf" and "-myinf" are badly named, or they should be mapped
to Double.POSITIVE_INFINITY and Double.NEGATIVE_INFINITY.
Double.NEGATIVE_INFINITY is less than all finite double numbers.

Patricia
 
R

Roedy Green

ArrayList al = new ArrayList();
al.add("-3.5");
al.add("+5");
al.add("+myinf");
al.add("-myinf");
al.add("+10");

How about putting Doubles directly into your ArrayList like this:

ArrayList<Double> al = new ArrayList<Double>();
// use autoboxing to convert double -> Double
al.add( 3.5d );
al.add( 5.0d );
al.add( Double.POSITIVE_INFINITY );
al.add( Double.NEGATIVE_INFINITY );
Now your comparator is much simpler, and it will compare numerically
not alphabetically.


I forget if POSTITIVE_INFINITY sorts without special attention. If
not, USE Double.MAX_VALUE instead.

You add numbers only once, and compare them many times. Therefore any
converting should be done as you put things in the ArrayList.

--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
K

Kevin

1)
oh! I never noticed that the "MIN_VALUE" for Double and Integer are so
different!
Yes, for Double, MIN_VALUE is the smallest value >0,
while for Integer, MIN_VALUE is the smallest value.
I just wonder why they make it this way? So confusing
.....................
Thanks Patricia to point it out!
And, yes, if I use NEGATIVE_INFINITY, it will work out as what we
expect.

2)
as to Roedy's suggestion, add Double to the arraylist will be faster
(the above code is just a hello world).
But do you have any idea of this situation (which is more close to my
real situation):
the Strings in ArrayList come from some records (sorry, I can not
change the input strings), like: "xyz_3.4_zex", "xex_6.5_seze", etc. in
which, '_' is a divider and the middle item is a double type value. The
first and third item are some strings (can be arbitrary long having any
chars except the divider char '_'). It is required to sort these
strings based on the middle double value, and output the strings (so we
can not just take out the double value and replace the string with a
Double).
Any idea how to sort these kind of thing?
I am not expert, and the only way I can think out (if not using the new
Comparator() as in above code) is to map each string back to a class
similar to ("xyz_3.4_zex" will become):
class X
{
String S1 = "xyz";
Double D = new Double(3.4);
String S2 = "zex";
}
and add it to a arraylist, sort them base on Double D, and convert the
class back to the string. But I am thinking that is slow too.

Thank you guys a lot. :)
 
C

Chris Head

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Kevin wrote:
[snip]
Yes, for Double, MIN_VALUE is the smallest value >0,
while for Integer, MIN_VALUE is the smallest value.
I just wonder why they make it this way? So confusing
[snip]


Hi,
Confusing, maybe, but if you think about it a bit it makes sense. For
Integer, of course MIN_VALUE is the lowest possible value and MAX_VALUE
is the highest. It doesn't make sense to have a special constant for
"the positive number closest to zero", because everyone knows it's 1.

For Double, you get into floating-point arithmetic where unfortunately
you can't represent every decimal number. Exactly what number is "the
positive number closest to zero" is no longer obvious, so there's a
constant for it. I agree that maybe there should be some constants for
the negative equivalents, though it looks from the bit patterns passed
into the longBitsToDouble() method that the equivalents may simply be
the negation (that is to say that "the negative number closest to zero"
is -Double.MIN_VALUE, and "the negative number closest to negative
infinity" is -Double.MAX_VALUE), but I'm not sure about this.

Anyway, that's why the floating-point types need more magic constants
than the integers.

Chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (MingW32)

iD8DBQFC5y5q6ZGQ8LKA8nwRAkBLAJ9g/kKeVJbCtAX2e0ICYlI5THoAOwCfY/Sl
CXCEz+1MG//LGf7ta+oamKk=
=rQfA
-----END PGP SIGNATURE-----
 
C

Chris Uppal

Kevin said:
class X
{
String S1 = "xyz";
Double D = new Double(3.4);
String S2 = "zex";
}

Why not:

class X
{
String full; // = "xyz_3.4_zex"
double sortValue; // = 3.4
}

A) It's simpler.
B) There is no overhead for parsing/unparsing as you sort.
C) You avoid the time and space overhead for using a Double.
D) You can retrieve the full string quickly in constant time.
E) You don't have the overhead of using two small strings when one slightly
longer one will do.
F) It's simpler ;-)

-- chris
 
C

Chris Uppal

Chris said:
Anyway, that's why the floating-point types need more magic constants
than the integers.

Double.MIN_VALUE is nevertheless still an excellent example of bad naming.

-- chris
 
K

Kevin

Thanks Chris, I will take your advice.
Also many thanks for all the other guys in this post. Have a nice day!~
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,480
Members
44,900
Latest member
Nell636132

Latest Threads

Top