(Apologies if this has been asked before - I can't believe it hasn't, but I couldn't find one. Perhaps my search-fu is weak.)
For years I've "known" that Java has no native function to scale an array (i.e. multiply each element by a constant). So I've been doing this:
for (int i=0; i<array.length; i++) {
array[i] = array[i] * scaleFactor;
}
Is this actually the most efficient way (in this application, for example, it's an array of around 10000 doubles)? Or is there a better way?
Looks absolutely fine to me. I can't think of a more efficient way. Obviously try to put that code in one place rather than having the actual code all over the place, but other than that, no obvious problems.
Only other suggestion I can offer is to lazily scale whereby you only pay the cost of multiplication on accessing each element; e.g.
public class MyArray {
private final double[] arr;
private double scale = 1.0;
public MyArray(double[] arr) {
this.arr = arr;
}
public double getScale() {
return scale;
}
public void setScale(double scale) {
this.scale = scale;
}
public double elementAt(int i) {
return arr[i] * scale;
}
}
Obviously this is only better in certain situations:
When your array is huge AND
You are only accessing a few elements AND
You are typically accessing these elements once.
In other situations it's a micro-optimisation with no real benefit on modern CPUs.
The "better way" is to write array[i] *= scaleFactor; instead of array[i] = array[i] * scaleFactor;. :-)
Really, that's just syntactic sugar though - the compiled output (and hence performance) should be exactly the same. As Jon says, you're not going to be able to get any better performance, but personally I'll take a reduction in typing any day.
Only thing I can think to add in addition to Adamski and Jon Skeet is that if it happens to be an array of ints/longs and you're scaling by a power of 2, then you might get a slight improvement by using bitshift operators. YMMV though, since it will depend on the compiler (and possibly even the VM).
In Java 8:
double coef = 3.0;
double[] x1 = {1,2,3};
double[] x2 = DoubleStream.of(x1).map(d->d*coef).toArray();
System.out.println(Arrays.toString(x2));
output: [3.0, 6.0, 9.0]
You could work with threads, to reduce the runtime, but the bottom line is you would include this code and let each thread run a part of the for loop so the resulting program is as efficient as yours; it's just made faster
Looks optimal to me.
Don't fall for false optimisations like declaring the array length in a final field outside the loop. This works for Collections by avoiding repeat method calls to .size() and Strings avoiding method calls to .length() but on an array .length is already a public final field.
Also, looping backwards towards zero might be an assembly language optimisation but in a high level language like Java the VM will take care of any obvious tweaks.
Related
Through my humble experience in programming I can tell with 90% certainty that it would not be possible to do such a thing. However I know that you guys out there are more experienced than me and thus have better and more elegant solutions to my problem.
Here is my question:
I have made a class method to check for matrix addition or subtraction compatibility. It returns true if two given matrices are compatible for addition or subtraction. My next method is addMatrices which takes two matrices as follows:
double [][] addMatrices(double matA [][], double matB[][])
so the method return a 2d array here is my code solution:
double [][] addMatrices(double A [][], double B[][]){
double reusltMat;
if(AddSubComp(A,B){
resultMat= new double [A.getRows][A.getCols];
//getRows returns the # of crows
for (int i=0;i<A.getRows;i++)
for(int j= 0;j<A.getCols;j++)
reslutMat[i][j]=A[i][j]+B[i][j];
return resultMat;
else
System.out.println("Out of boundaries");
resultMat= new double[0][0];
return resultMat;
so my question is there any possible way to avoid initialising the resultMat if the if (statement)is false? so that I return a 2D array IFF the addition is compatible i.e the two given matrices are of the same dimensions.
Thank you for your time.
Did you tried returning null?
double[][] reusltMat = null;
After the else
return resultMat;
One way could be to use the Optional introduced in Java 8. It is built for such cases. Returning null is not the best solution particularly in view of the ugly nullpointer exceptions that arise because of it.
See here : Java 8 Optional.
Ask me if you need anything else.
I have to search a list of objects to find the 2 lower and the 2 bigger values of a couple of atributes. In Java what is more efficient: To check the list once asking for the 4 values or do it twice to check for 2? in my experience 1 loop should be better, but there may be compilation optimization I may not know about.
This is the code for the single loop:
Cell[] getEdges(List<Cell> coordinateList)
{
int minX = coordinateList.get(0).getX;
int minY = coordinateList.get(0).getY;
int maxX = coordinateList.get(0).getX;
int maxY = coordinateList.get(0).getY;
Cell[] edgePair = new Cell[2];
For(Cell currentCell: List<Cell> coordinateList)
{
if(currentCell.getX()<minX)
{
minX = currentCell.getX();
}
if(currentCell.getY()<minY)
{
minY = currentCell.getY();
}
if(currentCell.getX()>maxX)
{
maxX = currentCell.getX();
}
if(currentCell.getY()>maxY)
{
maxY = currentCell.getY();
}
}
edgePair[0] = new Cell(minX, minY);
edgePair[1] = new Cell(maxX, maxY);
return edgePair;
}
this is the code for a 2 loops (Same for the max, just change condition)
Cell getMinEdge(List<Cell> coordinateList)
{
int minX = coordinateList.get(0).getX;
int minY = coordinateList.get(0).getY;
For(Cell currentCell: List<Cell> coordinateList)
{
if(currentCell.getX()<minX)
{
minX = currentCell.getX();
}
if(currentCell.getY()<minY)
{
minY = currentCell.getY();
}
}
return new Cell(minX, minY);
}
Thanks in advance for any suggestions.
My intuition is that the version of the code with one loop should be faster than the version with two loops. (Assuming that you correct the syntax errors first!) I doubt that the optimizer would be able to combine the two loops into one, and performing the list iteration twice is going to take longer than performing it once.
However, my advice to you would be:
Don't rely too much on your (or my, or other peoples') intuition to tell you what is more efficient.
Don't spend too much time up-front thinking about what could / would / should be fastest.
Instead:
Write the code in a simple, natural way, and then benchmark it to measure your application's performance with real input. (Or a good approximation to real.)
Only spend time trying to make the code go faster if the performance measurements say that it needs to go faster.
Once you have decided that you need to optimize, use a profiler to tell you what parts of the code to focus your attention on. Don't rely on your intuition, because intuition is often wrong.
While I strongly agree that early micro-optimizations are bad, this is a case where two different algorithms are considered. And algorithms are indeed the things that make good or bad performance, as opposed to questions like which of (++x) or (x++) or (x+=1) is "more efficient".
Hence, +1 for the question.
(That being said, most probably, you'll have only so many items in your coordinate list, that even the less optimal algorithm will not delay the program in any noticeable way.)
Generalizing a bit, you are asking if, when you need to reduce a list of size n in k different ways, it is better to do k separate reductions or a single reduction that combines the k ways.
The answer being that, if possible, one should strive to combine the k reductions into one. Or, in short: avoid repeated loops, if possible.
I want to point out that this is only a weak advice. If, for example, you had already 2 methods for determining the minima and maxima, it would be probably not worth writing a 3rd one that does it both in one run. (Except if it turns out that this is the absolute performance killer.)
But in this case, you have the choice and combining it all in one loop is also the most logical and hence best understandable thing to do.
If I would see code like this
for (X x: xs) { maxX = ...; }
for (X x: xs) { maxY = ...; }
I would ask myself on the 2nd line: "Why did he not do that in the first loop?"
I would then check the previous code again to see if I have overlooked something that prevented computing the maxY right away. Since I wouldn't find anything, I would have to accept it somehow ... but still with the feel that I might have overlooked something.
I have a Double that I want to knock the extra digits after the decimal place off of (I'm not too concerned about accuracy but feel free to mention it in your answer) prior to conversion into a String.
I was wondering whether it would be better to cast to an int or to use a DecimalFormat and call format(..) . Also, is it then more efficient to specify String.valueOf() or leave it as it is and let the compiler figure it out?
Sorry if I sound a bit ignorant, I'm genuinely curious to learn more of the technical details.
For reference, i'm drawing text to and android canvas:
c.drawText("FPS: " + String.valueOf((int)lastFps), xPos, yPos, paint);
Casting will probably be more efficient. This is implemented as native code while using a method will have to go through the java code. Also it's much more readable.
For the string.valueof, I expect the performance to be strictly the same. I find it more readable to just do "string" + intValue than "string" + String.valueof(intValue)
I made a program that used System.nanoTime() to calculate the execution time of these two methods:
public static void cast() {
for (int i=0; i<1000000; i++) {
int x= (int)Math.random();
}
}
public static void format() {
for (int i=0; i< 1000000; i++) {
DecimalFormat df = new DecimalFormat("#");
df.format(Math.random());
}
}
Here are the respective results:
80984944
6048075593
Granted my tests probably aren't perfect examples. I'm just using math.random(), which generates a number that will always cast to 0, which might affect results. However, these results do make sense - casting should be cheap, since it likely doesn't operate on the bits at all - the JVM just treats the bits differently.
Edit: If I pull out the instantiation of the formatter for the second example, the program runs in 3155165182ns. If I multiply the random numbers by Integer.MAX_VALUE in both cases (with the instantiation pulled out), the results are: 82100170 and 4174558079. Looks like casting is the way to go.
This is a job for Math.floor().
Generally speaking, function/method calls come at the cost of performance overhead. My vote is that typecasting would be faster, but as #Zefiryn suggested, the best way is to create a loop and do each action a multitude of times and measure the performance with a timer.
I'm not sure about the efficiency of either, but here's a third option that could be interesting to compare:
String.valueOf(doubleValue).substring(0, endInt)
which would give a set number of characters rather than decimals/numbers, and would skip the typecasting but make two function calls instead.
EDIT: Was too curious so I tried running each option:
integerNumberFormat.format(number)
String.valueOf(doubleValue).substring(0, endInt)
String.valueOf((int)doubleValue)
10^6 cycles with the results being ~800 ms, ~300 ms and ~40 ms, respectively. I guess my results won't be immediately translatable to your situation but they could give a hint that the last one is indeed, as the previous posters suggested, the fastest one.
In "Core java 1" I've read
CAUTION: An ArrayList is far
less efficient than an int[] array
because each value is separately
wrapped inside an object. You would
only want to use this construct for
small collections when programmer
convenience is more important than
efficiency.
But in my software I've already used Arraylist instead of normal arrays due to some requirements, though "The software is supposed to have high performance and after I've read the quoted text I started to panic!" one thing I can change is changing double variables to Double so as to prevent auto boxing and I don't know if that is worth it or not, in next sample algorithm
public void multiply(final double val)
{
final int rows = getSize1();
final int cols = getSize2();
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
this.get(i).set(j, this.get(i).get(j) * val);
}
}
}
My question is does changing double to Double makes a difference ? or that's a micro optimizing that won't affect anything ? keep in mind I might be using large matrices.2nd Should I consider redesigning the whole program again ?
The big issue with double versus Double is that the latter adds some amount of memory overhead -- 8 bytes per object on a Sun 32-bit JVM, possibly more or less on others. Then you need another 4 bytes (8 on a 64-bit JVM) to refer to the object.
So, assuming that you have 1,000,000 objects, the differences are as follows:
double[1000000]
8 bytes per entry; total = 8,000,000 bytes
Double[1000000]
16 bytes per object instance + 4 bytes per reference; total = 20,000,000 bytes
Whether or not this matters depends very much on your application. Unless you find yourself running out of memory, assume that it doesn't matter.
It changes the place where autoboxing happens, but nothing else.
And 2nd - no, don't worry about this. It is unlikely to be a bottleneck. You can make some benchmarks to measure it for the size of your data, to prove that the difference is insignificant in regard to your application performance.
Double is dramatically more expensive than double, however in 90% of cases it doesn't matter.
If you wanted an efficient matrix class, I would suggest you use one of the libraries which already do this efficiently. e.g. Jama.
Changing the double argument into Double won't help much, it will worsen performance slightly because it needs to be unboxed for the multiplication.
What will help is preventing multiple calls to get() as in:
for (int i = 0; i < rows; i++)
{
List row = this.get(i);
for (int j = 0; j < cols; j++)
{
row.set(j, row.get(j) * val);
}
}
(btw, I guessed the type for row.)
Assuming that you use a list of lists, using iterators instead of geting and setting via loop indices will win some more performance.
I have an array of floats and I would like to convert it to an array of doubles in Java. I am aware of the obvious way of iterating over the array and creating a new one. I expected Java to digest a float[] smoothly where it wishes to work with double[]... but it can not work with this.
What is the elegant, effective way of doing this conversion?
Basically something has to do the conversion of each value. There isn't an implicit conversion between the two array types because the code used to handle them after JITting would be different - they have a different element size, and the float would need a conversion whereas the double wouldn't. Compare this to array covariance for reference types, where no conversions are required when reading the data (the bit pattern is the same for a String reference as an Object reference, for example) and the element size is the same for all reference types.
In short, something will have to perform conversions in a loop. I don't know of any built-in methods to do this. I'm sure they exist in third party libraries somewhere, but unless you happen to be using one of those libraries already, I'd just write your own method. For the sake of convenience, here's a sample implementation:
public static double[] convertFloatsToDoubles(float[] input)
{
if (input == null)
{
return null; // Or throw an exception - your choice
}
double[] output = new double[input.length];
for (int i = 0; i < input.length; i++)
{
output[i] = input[i];
}
return output;
}
In Java 8 you can, if you really want to, do:
IntStream.range(0, floatArray.length).mapToDouble(i -> floatArray[i]).toArray();
But it's better (cleaner, faster, better semantics) to use Jon Skeet's function.
Do you actually need to copy your float array to a double array? If you are having trouble with the compiler and types when using the floats you can use this...
float x = 0;
double d = Double.valueOf(x);
What advantage do you get by taking a copy? If you need greater precision in the results of computations based on the floats then make the results double. I can see quite a lot of downsides to having a copy of the array, and performing the copy function, especially if it is large. Make sure you really need to do it.
HTH