I refactored the code in this class to be in a form that is more friendly to my use cases; one issue that I noticed during testing is that I cannot convert this particular equation to use long inputs because assigning to the a and m variables overflow on the multiplication/subtraction steps. Everything is just peachy when using int inputs because they can be casted to a long to prevent overflow. Is there anything one can do to get the proper behavior when the inputs are long?*
public static Func<int, int> Scale(int inputX, int inputY, int outputX, int outputY) {
if (inputX > inputY) {
var z = inputX;
inputX = inputY;
inputY = z;
}
if (outputX > outputY) {
var z = outputX;
outputX = outputY;
outputY = z;
}
var a = (((((double)inputScaleX) * (outputScaleX - outputScaleY)) / ((long)inputScaleY - inputScaleX)) + outputScaleX);
var m = (((double)(outputScaleY - outputScaleX)) / ((long)inputScaleY - inputScaleX));
return (value) => ((int)((value * m) + a));
}
For example, if I replaced every instance of int in the function above with long then result will have an incorrect value in the following code:
Func<long, long> scaler = Scale(long.MinValue, long.MaxValue, -5, 5);
var result = scaler(long.MaxValue - 3);
The expected result is 4 but the actual result of -9223372036854775808 is not only wrong, it ends up being way outside the defined range of [-5, 5].
*Other than straight up using BigInt or implementing 64-bit multiplication and division in software; I am already implementing these operations as workaround and am looking for alternative solutions that I haven't yet come across.
If you have to do math and none of the buildin .NET Integer types is long/large enough, BigInt is the droid you are looking for.
As long as you do not run out of memory, it can take a number of arbitrary size. Do however note that the performance is very bad, as should be expected. After all, Arbtitrary size does not come without tradeoffs. And unlike any other Numeric type, it can grow big.
Looking at the source code, it seems to be little more then a List<uint> with a int for the sign. Unfortunately that designs makes it vulnerable to Fragmentation based OutOfMemory exceptions and related List<uint> growth issues. I was hoping it would use a Linked List internally, but no such luck.
Java has a equivalent type (I asume all higher languages do), but I have no data on it's workings.
Is there any difference in performance between doing an int division with a cast or implicit cast
eg.
int a = 7;
int b = 3;
float x = ((float)a)/b;
or
float y = (a+0f)/b;
As the comments point out, the two versions are different because of operator precedence rules.
float y = a + 0f / b;
is actually equivalent to
float y = a + (0f / b);
i.e.
float y = a;
You should have written
float y = (a + 0f) / b;
Provided that you get the operator precedence correct, there is no difference, semantically, or in terms of performance. (The JIT compiler is highly likely to optimize away the artificial addition of zero.)
However, there is an important difference. Your second form is an unusual idiom, and unusual idioms make it harder for other people to read your code. It is best to write your code the "normal" way ... if you (or your boss!!) anticipate that other people may need to read / maintain it.
(And if you make a habit of getting the operator precedence wrong, they may need to read your code sooner than you expect ... :-) )
I want to use a method that requires an int. This int is determined by a division potentially solved as a double. I need to perform this as neat and short as possible and I am wondering if I can count that the method will take the double directly casted as int and if this means a single truncation with no roundings.
Do I have to necessarily use Math static methods?
Could this give errors for non int parameter entries to subList?
Could someone provide any guidance about this?
List<Integer> b = null;
List<Integer> c = null;
int size = a.size();
b.addAll(a.subList(0, size / 2)); // To hold the first half
c.addAll(a.subList(size / 2, size)); // To hold the second half [and excess]
Thank you in advance for your help.
it will take the double casted to integer and will not round it, just disregard everything after the "."
so if the division of 9.8/2 is 4.9 then you'll get 4 for doing
int x = 9.8/2;
you don't need to use the Math static methods for devision and you won't get errors for the code you gave
to conclude, you can just run your code and see if the result is as you want it.
b.addAll(a.subList(0, size / 2));
should run without problem
What's wrong with b.addAll(a.subList(0, (int)(size / 2)));?
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 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)
I'm not sure the question is clearly worded, but an example will be clearer.
I found out that will not work in Java:
int a = ...;
a = 5.0;
but this will:
int a = ...;
a += 5.0;
I.e., it seems that the = operator is type safe but += isn't.
Is there any deep reason for this or is it just another arbitrary decision language designers must take.
The reason is that math operations do some implicit casting:
a += 5.0; is evaluated as follows:
a = (int) ((double) a + 5.0);
Assignment, however, requires an explicit cast.
(It might be float rather than double, I don't remember which Java treats as decimal literals.)
To make life easier.
Let's go a little further. Consider:
byte b;
...
++b;
The increment is really doing:
b = (byte)(1 + (int)b);
Even using += it doesn't get any better:
b += b;
is:
b = (byte)((int)b+(int)b);
That would make these operators useless for byte/short/char.
Of course I wont be happy until we have arbitrary sized integers.