开发者

How to add two java.lang.Numbers?

开发者 https://www.devze.com 2022-12-28 02:58 出处:网络
I have two Numbers. Eg: Number a = 2; Number b = 3; //Following is an error: Number c = a + b; Why arithmetic operations are not supported on Numbers? Anyway开发者_StackOverflow社区 how would I add

I have two Numbers. Eg:

Number a = 2;
Number b = 3;
//Following is an error:
Number c = a + b;

Why arithmetic operations are not supported on Numbers? Anyway开发者_StackOverflow社区 how would I add these two numbers in java? (Of course I'm getting them from somewhere and I don't know if they are Integer or float etc).


You say you don't know if your numbers are integer or float... when you use the Number class, the compiler also doesn't know if your numbers are integers, floats or some other thing. As a result, the basic math operators like + and - don't work; the computer wouldn't know how to handle the values.

START EDIT

Based on the discussion, I thought an example might help. Computers store floating point numbers as two parts, a coefficient and an exponent. So, in a theoretical system, 001110 might be broken up as 0011 10, or 32 = 9. But positive integers store numbers as binary, so 001110 could also mean 2 + 4 + 8 = 14. When you use the class Number, you're telling the computer you don't know if the number is a float or an int or what, so it knows it has 001110 but it doesn't know if that means 9 or 14 or some other value.

END EDIT

What you can do is make a little assumption and convert to one of the types to do the math. So you could have

Number c = a.intValue() + b.intValue();

which you might as well turn into

Integer c = a.intValue() + b.intValue();

if you're willing to suffer some rounding error, or

Float c = a.floatValue() + b.floatValue();

if you suspect that you're not dealing with integers and are okay with possible minor precision issues. Or, if you'd rather take a small performance blow instead of that error,

BigDecimal c = new BigDecimal(a.floatValue()).add(new BigDecimal(b.floatValue()));


It would also work to make a method to handle the adding for you. Now I do not know the performance impact this will cause but I assume it will be less than using BigDecimal.

public static Number addNumbers(Number a, Number b) {
    if(a instanceof Double || b instanceof Double) {
        return a.doubleValue() + b.doubleValue();
    } else if(a instanceof Float || b instanceof Float) {
        return a.floatValue() + b.floatValue();
    } else if(a instanceof Long || b instanceof Long) {
        return a.longValue() + b.longValue();
    } else {
        return a.intValue() + b.intValue();
    }
}


The only way to correctly add any two types of java.lang.Number is:

Number a = 2f; // Foat
Number b = 3d; // Double
Number c = new BigDecimal( a.toString() ).add( new BigDecimal( b.toString() ) );

This works even for two arguments with a different number-type. It will (should?) not produce any sideeffects like overflows or loosing precision, as far as the toString() of the number-type does not reduce precision.


java.lang.Number is just the superclass of all wrapper classes of primitive types (see java doc). Use the appropriate primitive type (double, int, etc.) for your purpose, or the respective wrapper class (Double, Integer, etc.).

Consider this:

Number a = 1.5; // Actually Java creates a double and boxes it into a Double object
Number b = 1; // Same here for int -> Integer boxed

// What should the result be? If Number would do implicit casts,
// it would behave different from what Java usually does.
Number c = a + b; 

// Now that works, and you know at first glance what that code does.
// Nice explicit casts like you usually use in Java.
// The result is of course again a double that is boxed into a Double object
Number d = a.doubleValue() + (double)b.intValue();


Use the following:

Number c = a.intValue() + b.intValue(); // Number is an object and not a primitive data type.

Or:

int a = 2;
int b = 3;
int c = 2 + 3;


I think there are 2 sides to your question.

Why is operator+ not supported on Number?

Because the Java language spec. does not specify this, and there is no operator overloading. There is also not a compile-time natural way to cast the Number to some fundamental type, and there is no natural add to define for some type of operations.

Why are basic arithmic operations not supported on Number?

(Copied from my comment:)

Not all subclasses can implement this in a way you would expect. Especially with the Atomic types it's hard to define a usefull contract for e.g. add.

Also, a method add would be trouble if you try to add a Long to a Short.


If you know the Type of one number but not the other it is possible to do something like

public Double add(Double value, Number increment) {
   return value + Double.parseDouble(increment.toString());
}

But it can be messy, so be aware of potential loss of accuracy and NumberFormatExceptions


Number is an abstract class which you cannot make an instance of. Provided you have a correct instance of it, you can get number.longValue() or number.intValue() and add them.


First of all, you should be aware that Number is an abstract class. What happens here is that when you create your 2 and 3, they are interpreted as primitives and a subtype is created (I think an Integer) in that case. Because an Integer is a subtype of Number, you can assign the newly created Integer into a Number reference.

However, a number is just an abstraction. It could be integer, it could be floating point, etc., so the semantics of math operations would be ambiguous.

Number does not provide the classic map operations for two reasons:

First, member methods in Java cannot be operators. It's not C++. At best, they could provide an add()

Second, figuring out what type of operation to do when you have two inputs (e.g., a division of a float by an int) is quite tricky.

So instead, it is your responsibility to make the conversion back to the specific primitive type you are interested in it and apply the mathematical operators.


The best answer would be to make util with double dispatch drilling down to most known types (take a look at Smalltalk addtition implementation)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号