Why does Java not have a RealNumber class?

S

Sideswipe

This is a question that continues to bug me.

There is Number. Double, Float, Int ... all extends Number and then
implement Comparable independently.

I know plenty of Math geeks troll this group. I know why Number is not
Comparable, but number has methods like: "doubleValue()"

What I would love is something like:


public abstract class RealNumber<T> extends Number implements
Comparable<T> {
.....
}

public class Double extends RealNumber<Double> {
// impement comparable <double>
}

public class Integer extends RealNumber<Integer> {
// impement comparable <Integer>
}

That way I could do ... Set<RealNumber> someSet = new
TreeSet<RealNumber>();

I don't care which type they are, as long as they are all the same and
I can't do <Number> because they aren't comparable.

And, I already know I can do:

Set<Number> someSet = new TreeSet<Number>(new Comparator<Number>() {
int compare(Number a, Number b) {return a.doublValue() -
b.doubleValue());}
});

But this has the inherent flaw of precision issues between Integer
and, say Double that this would mask.

I am tempted to actually implement this exact solution for my problem
space through delegation but I am hesitant that there might be some
hidden number theory problem with this approach.

Thoughts?

Christian Bongiorno
http://christian.bongiorno.org
 
D

Daniel Pitts

Sideswipe said:
This is a question that continues to bug me.

There is Number. Double, Float, Int ... all extends Number and then
implement Comparable independently.

I know plenty of Math geeks troll this group. I know why Number is not
Comparable, but number has methods like: "doubleValue()"

What I would love is something like:


public abstract class RealNumber<T> extends Number implements
Comparable<T> {
.....
}

public class Double extends RealNumber<Double> {
// impement comparable <double>
}

public class Integer extends RealNumber<Integer> {
// impement comparable <Integer>
}

That way I could do ... Set<RealNumber> someSet = new
TreeSet<RealNumber>();

I don't care which type they are, as long as they are all the same and
I can't do <Number> because they aren't comparable.

And, I already know I can do:

Set<Number> someSet = new TreeSet<Number>(new Comparator<Number>() {
int compare(Number a, Number b) {return a.doublValue() -
b.doubleValue());}
});

But this has the inherent flaw of precision issues between Integer
and, say Double that this would mask.

I am tempted to actually implement this exact solution for my problem
space through delegation but I am hesitant that there might be some
hidden number theory problem with this approach.

Thoughts?

Christian Bongiorno
http://christian.bongiorno.org
Wait, what are you trying to do?

Integer is already Comparable<Integer>. Double implements
Comparable<Double>, what do you hope to achieve?
 
S

Sideswipe

I would prefer just to understand why there is no "RealNumber" that
all the basic java types extends from. But to answer your question, I
will have to work with numbers and perform basic mathematical steps on
them but I won't know which types until runtime. What I am working on
will not know if it will be Integer Double, etc. So, unless I want to
make methods for all those types (and then types I don't know about --
like subclasses of BigDecimal) I would like to just have (in a perfect
world) a method like

NUM_T extends RealNumber

public void doJob(NUM_T a, NUM_T b) {
a / b;
}

I want to polymorphically encapsulate mathematical operations without
having to overload the same method for everytype. I understand that
isn't possible now, and so, that is what I am asking.

If I had a class called "RealNumber" that I could count on for these
basic ops, I would be set. So, look at the original post.
 
S

Stefan Ram

Sideswipe said:
NUM_T extends RealNumber
public void doJob(NUM_T a, NUM_T b) {
a / b;
}

This can be written in C++:

#include <iostream>
#include <ostream>

template<typename NUM_T>
NUM_T doJob( NUM_T const a, NUM_T const b )
{ return a / b; }

int main()
{ ::std::cout << doJob( 2, 3 )<< '\n';
::std::cout << doJob( 2., 3. )<< '\n'; }

Possibly one can restrict »NUM_T« to numeric types better than
I did above.

There is no C++ implementation for the JVM.

In Java, an approximation would be:

public class Main
{
static int doJob( final int a, final int b ){ return a / b; }
static double doJob( final double a, final double b ){ return a / b; }

public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( doJob( 2, 3 ));
java.lang.System.out.println( doJob( 2., 3. )); }}
I want to polymorphically encapsulate mathematical operations
without having to overload the same method for everytype.

You do not want to overload.

Overloading is a kind of polymorphism (static polymorphism).

This uses only a single method declaration:

public class Main
{
@java.lang.SuppressWarnings( "unchecked" )
static< T >T doJob( final T a, final T b )
{ if( a instanceof java.lang.Integer && b instanceof java.lang.Integer )
{ return ( T )
java.lang.Integer.valueOf((( java.lang.Integer )a ).intValue() /
(( java.lang.Integer )b ).intValue() ); }
else if( a instanceof java.lang.Double && b instanceof java.lang.Double )
{ return ( T )
java.lang.Double.valueOf((( java.lang.Double )a ).doubleValue() /
(( java.lang.Double )b ).doubleValue() ); }
else return null; }

public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( doJob( 2, 3 ));
java.lang.System.out.println( doJob( 2., 3. )); }}
 
M

mike.mainguy

Sideswipe said:
NUM_T extends RealNumber
public void doJob(NUM_T a, NUM_T b) {
       a / b;
}

  This can be written in C++:

#include <iostream>
#include <ostream>

template<typename NUM_T>
NUM_T doJob( NUM_T const a, NUM_T const b )
{ return a / b; }

int main()
{ ::std::cout << doJob( 2, 3 )<< '\n';
  ::std::cout << doJob( 2., 3. )<< '\n'; }

  Possibly one can restrict »NUM_T« to numeric types better than
  I did above.

  There is no C++ implementation for the JVM.

  In Java, an approximation would be:

public class Main
{
  static int    doJob( final int    a, final int    b ){ return a / b; }
  static double doJob( final double a, final double b ){ return a / b; }

  public static void main( final java.lang.String[] args )
  { java.lang.System.out.println( doJob(  2, 3  ));
    java.lang.System.out.println( doJob( 2., 3. )); }}
I want to polymorphically encapsulate mathematical operations
without having to overload the same method for everytype.

  You do not want to overload.

  Overloading is a kind of polymorphism (static polymorphism).

  This uses only a single method declaration:

public class Main
{
  @java.lang.SuppressWarnings( "unchecked" )
  static< T >T doJob( final T a, final T b )
  { if( a instanceof java.lang.Integer && b instanceof java.lang.Integer )
    { return ( T )
      java.lang.Integer.valueOf((( java.lang.Integer )a ).intValue() /
      (( java.lang.Integer )b ).intValue() ); }
    else if( a instanceof java.lang.Double && b instanceof java.lang.Double )
    { return ( T )
      java.lang.Double.valueOf((( java.lang.Double )a ).doubleValue() /
      (( java.lang.Double )b ).doubleValue() ); }
    else return null; }

  public static void main( final java.lang.String[] args )
  { java.lang.System.out.println( doJob(  2, 3  ));
    java.lang.System.out.println( doJob( 2., 3. )); }}

I'm not a mathematician, I just play one on TV, but...

I believe most of the our more modern dynamic languages (ruby, python,
groovy) do this type of coercion, so I doubt there is a mathematical
basis for not doing this. I suspect it was more of an engineering
problem (Double and Int are fundamentally different, how can you
possibly compare them?).

In the same line, would you want to compare a string to a double?
Practically speaking "1.2" == 1.2d should return true for probably
99.9% of the non-trivial use cases one would need to implement. But
from a design/engineering perspective and looking out from the jvm, I
can see where this could be a contentious statement.
 
S

Sideswipe

Yeah,

I have investigated this before but never got a conclusive answer. So
I am asking a very specific question. You're the only one who has
given me a reasonable answer.

So, yes, Double and Integer are fundamentally different. But, generics
will allow me to force type compatibility (So String compared to
Double will never occur). Since this is runtime, however, I don't have
that luxury. I will be dealing with reflection and other scary
dynamics. What I can do is assume that I would be passed incompatable
types -- I can only enforce this through exception which people don't
like.

So, given that, I want to have 1 method that could handle all those
types, with the assumption that they are type compatible.

Christian
 
D

Daniel Pitts

Sideswipe said:
I would prefer just to understand why there is no "RealNumber" that
all the basic java types extends from. But to answer your question, I
will have to work with numbers and perform basic mathematical steps on
them but I won't know which types until runtime. What I am working on
will not know if it will be Integer Double, etc. So, unless I want to
make methods for all those types (and then types I don't know about --
like subclasses of BigDecimal) I would like to just have (in a perfect
world) a method like

NUM_T extends RealNumber

public void doJob(NUM_T a, NUM_T b) {
a / b;
}

I want to polymorphically encapsulate mathematical operations without
having to overload the same method for everytype. I understand that
isn't possible now, and so, that is what I am asking.

If I had a class called "RealNumber" that I could count on for these
basic ops, I would be set. So, look at the original post.
Something that might get you a step closer:
class MyMathClass<T extends Number&Comparable<T>> {
}

This says that T must extend Number and it must be Comparable to itself.

The trouble is that Java has no operator overloading. It may trick you
into thinking it does, based on the fact that it will auto-box/unbox for
you.

For your use case, now that I'm understanding it a bit better, you need
an interface (Field probably) which represents the ability to perform
addition/subtraction/etc... Then you would have IntegerField implements
Field, DoubleField implements Field, etc...

Granted this is a bit of a pain, but in Java, its the way to do it. In
C++, templates and operator overloading save you some of this tiresome
framework.
 
L

Lasse Reichstein Nielsen

Sideswipe said:
So, given that, I want to have 1 method that could handle all those
types, with the assumption that they are type compatible.

Something like:

Number add(Number a, Number b) {
if (a instanceof Float) {
return ((Float)a) + ((Float)b);
}
if (a instanceof Double) {
return ((Double)a) + ((Double)b);
}
// etc
}

/L
 
T

Tom Anderson

In some cases, this can be refined to:

< T extends java.lang.Number & java.lang.Comparable< ? >>

Should that be T extends Number & Comparable<T> - with a 'T' binding the
Comparable, rather than another '?'?

Generics still confuse me, so perhaps not!

tom
 
S

Stefan Ram

Tom Anderson said:
Should that be T extends Number & Comparable<T> - with a 'T' binding the
Comparable, rather than another '?'?

I thought so, too. But I get a compilation error:


public class Main
{
static< T extends java.lang.Comparable< T >>boolean test( final T t )
{ return t instanceof java.lang.Integer; }

public static void main( final java.lang.String[] args )
{} }


Main.java:4: inconvertible types
found : T
required: java.lang.Integer
{ return t instanceof java.lang.Integer; }
^
1 error


Usually, this means, that the compiler already can prove that
t cannot be an instance of java.lang.Integer.

I do not understand how he does this.

Maybe someone else can explain.
 
D

Daniel Pitts

Stefan said:
Tom Anderson said:
Should that be T extends Number & Comparable<T> - with a 'T' binding the
Comparable, rather than another '?'?

I thought so, too. But I get a compilation error:


public class Main
{
static< T extends java.lang.Comparable< T >>boolean test( final T t )
{ return t instanceof java.lang.Integer; }

public static void main( final java.lang.String[] args )
{} }


Main.java:4: inconvertible types
found : T
required: java.lang.Integer
{ return t instanceof java.lang.Integer; }
^
1 error


Usually, this means, that the compiler already can prove that
t cannot be an instance of java.lang.Integer.

I do not understand how he does this.

Maybe someone else can explain.
I actually think that is a compiler bug.
It works if you *don't* use instance of:

public class Main {
static <T extends Number&Comparable<? extends T>>
boolean test(final T t ) { return Integer.class.isInstance(t); }

public static void main( final String[] args) {
System.out.println("test(42) = " + test(42));
System.out.println("test(42L) = " + test(42L));

}
}
 
T

Tom Anderson

I have investigated this before but never got a conclusive answer. So I
am asking a very specific question. You're the only one who has given me
a reasonable answer.

I've only been following this thread vaguely, but i suspect the answer is
that there's no good reason, and the java implementers just didn't feel
like it. Smalltalk has a comprenehsive system of number interoperability,
and has done since at least 1980, covering comparison, arithmetic, etc
over floats, integers, bigints, etc, so it's clearly possible.

I think the answers you're getting reflect an unfortunate behaviour which
is rather common in users of any langage, which is assuming that there's a
good reason for every property of that language. Double and Integer aren't
comparable, so there must be a good reason for it, so let's see if we can
think of one.
So, yes, Double and Integer are fundamentally different. But, generics
will allow me to force type compatibility (So String compared to Double
will never occur). Since this is runtime, however, I don't have that
luxury. I will be dealing with reflection and other scary dynamics. What
I can do is assume that I would be passed incompatable types -- I can
only enforce this through exception which people don't like.

So, given that, I want to have 1 method that could handle all those
types, with the assumption that they are type compatible.

This isn't easy to implement. It would be easier if you could edit the
number classes, as then you could at least use some polymorphism, but
you're going to have to do it all with instanceof switches. Or getClass
and a map or some other clever structure. Or reflection:

public class NumberComparator implements Comparator {

public int compare(double d, short s) // etc

public int compare(Object a, Object b) throws various {
Class ca = a.getClass() ;
Class cb = b.getClass() ;
Method m = NumberComparator.class.getMethod("compare", new Class[] {ca, cb}) ;
int result = ((Integer)m.invoke(this, new Object[] {a, b})).intValue) ;
return result ;
}

}

This needs some fudging to work - at the moment, you'd have to declare the
methods as taking wrappers rather than primitives. Is there a way to go
from the Class of a wrapper type to the Class of its primitive?

Anyway, my approach would be to try to coerce each number to a common
'base' type, which can represent both exactly. If both types are some size
of integer, use whatever the smallest integer is (or, pragmatically, use
int if both will fit, and long otherwise). If both are some type of float,
use a double (unless they're both floats). If one is a float and one is an
integer of less than 23 bits, use a float; if one is a float or double and
the other is an integer of less than 52 bits, use a double.

The problem comes when you want to compare a floating-point value to an
integer of >52 bits, ie a long. There is no numeric type in java which
will hold both without loss of precision. It's not hard to do the
comparison 'manually', though. Step 0 is to check to see if the double is
a NaN and dispose of it if so. Step 1 is to check to see if the double is
greater than Long.MAX_VALUE or smaller than Long.MIN_VALUE; if it is, you
have your answer. This will actually take some subtlety, as those values
are not exactly expressible as doubles (i think) - you'll need to work out
what the smallest double truly bigger than those values is. If it isn't
outside that range, then you must have a double whose integer part will
fit in a long. Split the double into whole and fractional parts, with the
whole part expressed as a long. Compare the whole part to the actual long.
If they're equal, use the fractional part to break the tie.

I'm not quite sure if making the whole-part double is also tricky - can
the whole part always be expressed exactly in a double? You might need to
use doubleToLongBits and unpack it manually. Or maybe Double.longValue()
will do what you need. Urgh.

tom
 
S

Stefan Ram

Tom Anderson said:
I've only been following this thread vaguely, but i suspect the answer is
that there's no good reason, and the java implementers just didn't feel
like it. Smalltalk has a comprenehsive system of number interoperability,

When coding algorithms in Java, I try to make sure to code to
the most general number type possible. Unfortunately, since
there is not such a type in Java, I have to use a custom
interface for this.

For example, here is an algorithm:

/**
* Is the year given as the argument year number a leap
* year?
*
* @param yearNumber a year number
* @return truth value of the assertion "the year given by
* the parameter year number yearNumberParameter is a leap
* year"
*/
@de.dclj.ram.meta.quality.Tested
public static
< Int extends de.dclj.ram.type.number.IntNumber< Int >>
boolean
isLeapYear( final Int yearNumber )
{ final boolean isQuad = yearNumber.hasFactor( 4 );
final boolean isCentury = yearNumber.hasFactor( 100 );
final boolean isQuadcentury = yearNumber.hasFactor( 400 );
final boolean isCanceled = isCentury & !isQuadcentury;
final boolean isLeapYear = isQuad & !isCanceled;
return isLeapYear; }

The IntNumber type only contains the operations needed
so far:

http://www.purl.org/stefan_ram/html/ram.jar/de/dclj/ram/type/number/IntNumber.html

There is a single implementation of this interface for now,
and I also have a float type:

http://www.purl.org/stefan_ram/html/ram.jar/de/dclj/ram/type/number/package-summary.html

I might factor out common methods of IntNumber and FloatNumber
into a superinterface »Number«, but there was not yet need for it.
 
A

Arved Sandstrom

Daniel Pitts wrote:

[ SNIP ]
Something that might get you a step closer:
class MyMathClass<T extends Number&Comparable<T>> {
}

This says that T must extend Number and it must be Comparable to itself.

The trouble is that Java has no operator overloading. It may trick you
into thinking it does, based on the fact that it will auto-box/unbox for
you.

For your use case, now that I'm understanding it a bit better, you need
an interface (Field probably) which represents the ability to perform
addition/subtraction/etc... Then you would have IntegerField implements
Field, DoubleField implements Field, etc...

Granted this is a bit of a pain, but in Java, its the way to do it. In
C++, templates and operator overloading save you some of this tiresome
framework.

It appears that the JScience library (http://jscience.org/) has largely
followed the above approach. They have a field interface for those number
types that support addition, subtraction, multiplication and division by
non-zero, also rings, groups etc. And also Comparable.

AHS
 
C

Chronic Philharmonic

Sideswipe said:
This is a question that continues to bug me.

There is Number. Double, Float, Int ... all extends Number and then
implement Comparable independently.

I know plenty of Math geeks troll this group. I know why Number is not
Comparable, but number has methods like: "doubleValue()"

What I would love is something like:


public abstract class RealNumber<T> extends Number implements
Comparable<T> {
....
}

public class Double extends RealNumber<Double> {
// impement comparable <double>
}

public class Integer extends RealNumber<Integer> {
// impement comparable <Integer>
}

That way I could do ... Set<RealNumber> someSet = new
TreeSet<RealNumber>();

I don't care which type they are, as long as they are all the same and
I can't do <Number> because they aren't comparable.

And, I already know I can do:

Set<Number> someSet = new TreeSet<Number>(new Comparator<Number>() {
int compare(Number a, Number b) {return a.doublValue() -
b.doubleValue());}
});

But this has the inherent flaw of precision issues between Integer
and, say Double that this would mask.

I am tempted to actually implement this exact solution for my problem
space through delegation but I am hesitant that there might be some
hidden number theory problem with this approach.

Before you do that, you should check out
org.jscience.mathematics.number.Number<T>. They may have already done what
you need:
http://jscience.org/api/org/jscience/mathematics/number/Number.html

See http://jscience.org/.
 

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,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top