what is the correct code to calculating time in Java with
public static int getGcd( int a, int b, int temp) format?
A simple solution:
First, Grab and store the time before you start the piece of code you want the run time for:
long start =System.currentTimeMillis();
After the code that you are tracking grab the current time and subtract it from your starting point to get the total time elapsed:
System.out.println(System.currentTimeMillis() - start);
If it runs relatively fast and you're trying to get an average time by running it on a bunch of random inputs, use:
long totalTime = 0;
long start = System.nanoTime();
for(int i=0;i<n;i++){
//Generate a and b
getGcd(a, b);
}
long end = System.nanoTime();
totalTime = end - start;
start = System.nanoTime();
for (int i=0;i<n;i++){
//Generate a and b
}
end = System.nanoTime();
totalTime -= end - start;
return totalTime / n;
This gives you your average time in nanoseconds.
Finding the average running time of GCD is a very interesting and complex problem. In the worst case, the inputs have a ratio which is close to the golden mean (such as consecutive Fibonacci numbers) and then the running time is O(log n). But it's still possible to have extremely large inputs and end up with essentially constant time. I'd be curious to know your results.
Related
I am doing a project where I need to implement bubblesort, shellsort and quicksort algorithms in an array of 999 random doubles.
I need to measure the time it takes every algorithm to run.
I am using System.nanoTime() to measure this execution time for each algorithm. I have 3 buttons, one for each algorithm. Upon clicking a button, the timer starts, the function is called, the end timer is then called and the duration is calculated by having endtime-starttime. The duration is then printed on a label on top of the button.
public double[] randomArray = SortAlg.getArray();
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
long startTimeBubble = System.nanoTime();
SortAlg.bubble(randomArray);
long endTimeBubble = System.nanoTime();
long durationBubble = (endTimeBubble - startTimeBubble) / 1000000;
bubbleTiempo.setText("bubble took " + durationBubble + " ms");
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
long startTimeShellSort = System.nanoTime();
SortAlg.shellSort(randomArray);
long endTimeShellSort = System.nanoTime();
long durationShellSort = (endTimeShellSort - startTimeShellSort) / 1000000;
shellSortTime.setText("ShellSort took " + durationShellSort + " ms");
}
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
long startTimeQuickSort = System.nanoTime();
SortAlg.quickSort(randomArray, 0, randomArray.length - 1);
long endTimeQuickSort = System.nanoTime();
long durationQuickSort = (endTimeQuickSort - startTimeQuickSort) / 1000000;
quickSortTime.setText("Quicksort took " + durationQuickSort + " ms");
}
General clarifications:
1-getArray() generates a random array of 999 real (double) numbers between 0 and 2000.
2-None of the algorithm methods return an array, so this randomArray is NOT being saved as sorted, therefore, every time the button is clicked, the random array that is passed into the function is unsorted.
3-Every button has a unique label to display the results.
4-What you're seeing there is from the GUI class I created with Netbeans GUI editor, the buttons portion. Main simply creates a new GUI frame and sets it as visible, and the SortAlg contains the logic for the algorithms, which I already tested to be working.
But I have 2 issues here: If I click the button more than 1 time, the time decreases further for every click, until it's eventually 0, which makes no sense.
Also, I initially had a calculation error and I was dividing the time taken by 100000 rather than 1000000, but oddly enough, this was never giving me any errors. When I divide it by 1000000 though (which should be the correct operation for converting ns to ms) I sometimes get 0 MS execution time, which again makes no sense.
Lastly, and I know that this might be difficult to determine, but I was under the impression that quickSort had to be the fastest algorithm? But their execution times greatly vary within builds. Sometimes each one is 5 ms, other times its 30, other times its 68. I am concerned because it seems that, the first clicked is always the fastest one and the other ones end up being slower. I am not confident about these results at all.
When I divide it by 1000000 though (which should be the correct operation for converting ns to ms) I sometimes get 0 MS execution time, which again makes no sense.
Because you are using integer division:
long durationBubble = (endTimeBubble - startTimeBubble) / 1000000;
^^^^^^^
Just replace it with double to include the fraction:
double durationBubble = (endTimeBubble - startTimeBubble) / 1_000_000.0;
See:
Int division: Why is the result of 1/3 == 0?
Below is a simple for loop. I understand using growth rate analysis to look at a program and determine its rate. However, my question is after a program runs and you actually see the speed of which it works, how would you graph the actual growth rate of the program?
long startTime = System.nanoTime();
int sum = 0;
int N = 1000000;
for (int i=0; i<N; i++)
{
sum += Math.sqrt(i);
}
long endTime = System.nanoTime();
long duration = (endTime - startTime);
System.out.println("Here is the time it takes "+ duration);
Big O follows a certain trend depending on the complexity of the program.
Types of Big O Explained
Big O explained
I have listed some resources that I think should be useful.
Also if you don't need to draw it by hand, try looking up some Java resources that generate graphs.
This is just a hypothetical question, but could be a way to get around an issue I have been having.
Imagine you want to be able to time a calculation function based not on the answer, but on the time it takes to calculating. So instead of finding out what a + b is, you wish to continue perform some calculation while time < x seconds.
Look at this pseudo code:
public static void performCalculationsForTime(int seconds)
{
// Get start time
int millisStart = System.currentTimeMillis();
// Perform calculation to find the 1000th digit of PI
// Check if the given amount of seconds have passed since millisStart
// If number of seconds have not passed, redo the 1000th PI digit calculation
// At this point the time has passed, return the function.
}
Now I know that I am horrible, despicable person for using precious CPU cycles to simple get time to pass, but what I am wondering is:
A) Is this possible and would JVM start complaining about non-responsiveness?
B) If it is possible, what calculations would be best to try to perform?
Update - Answer:
Based on the answers and comments, the answer seems to be that "Yes, this is possible. But only if it is not done in Android main UI thread, because the user's GUI will be become unresponsive and will throw an ANR after 5 seconds."
A) Is this possible and would JVM start complaining about non-responsiveness?
It is possible, and if you run it in the background, neither JVM nor Dalvik will complain.
B) If it is possible, what calculations would be best to try to perform?
If the objective is to just run any calculation for x seconds, just keep adding 1 to a sum until the required time has reached. Off the top of my head, something like:
public static void performCalculationsForTime(int seconds)
{
// Get start time
int secondsStart = System.currentTimeMillis()/1000;
int requiredEndTime = millisStart + seconds;
float sum = 0;
while(secondsStart != requiredEndTime) {
sum = sum + 0.1;
secondsStart = System.currentTimeMillis()/1000;
}
}
You can and JVM won't complain if your code is not part of some complex system that actually tracks thread execution time.
long startTime = System.currentTimeMillis();
while(System.currentTimeMillis() - startTime < 100000) {
// do something
}
Or even a for loop that checks time only every 1000 cycles.
for (int i = 0; ;i++) {
if (i % 1000 == 0 && System.currentTimeMillis() - startTime < 100000)
break;
// do something
}
As for your second question, the answer is probably calculating some value that can always be improved upon, like your PI digits example.
I have some code that generates 1000 numbers in an array and then sorts them:
import java.util.Arrays;
import java.util.Random;
public class OppgA {
public static void main(String[] args) {
int[] anArray;
anArray = new int[1000];
Random generator = new Random();
for(int i=0; i<1000; i++){
anArray[i] = (generator.nextInt(1000)+1);
}
Arrays.sort(anArray);
System.out.println(Arrays.toString(anArray));
}
}
Now I'm asked to calculate and print the time it took to sort the array. Any clues how I can do this? I really couldn't find much by searching that could help me out in my case.
Thanks!
You can call (and store the result of) System.nanoTime() before and after the call to Arrays.sort()- the difference is the time spent in nanoseconds. That method is preferred over System.currentTimeMillis to calculate durations.
long start = System.nanoTime();
Arrays.sort(anArray);
long end = System.nanoTime();
long timeInMillis = TimeUnit.MILLISECONDS.convert(end - start, TimeUnit.NANOSECONDS);
System.out.println("Time spend in ms: " + timeInMillis);
But note that the result of your measurement will probably vary widely if you run the program several times. To get a more precise calculation would be more involved - see for example: How do I write a correct micro-benchmark in Java?.
Before sorting, declare a long which corresponds to the time before you start the sorting:
long timeStarted = System.currentTimeMillis();
//your sorting here.
//after sorting
System.out.println("Sorting last for:" + (System.currentTimeMillis() - timeStarted));
The result will return the milli seconds equivalent of your sorting.
As assylias commented you can also use System.nanoTime() if you prefer precise measurements of elapsed time.
Proper microbenchmarking is done using a ready-made tool for that purpose, like Google Caliper or Oracle jmh. However, if you want a poor-man's edition, follow at least these points:
measure with System.nanoTime() (as explained elsewhere). Do not trust small numbers: if you get timings such as 10 microseconds, you are measuring a too short timespan. Enlarge the array to get at least into the milliseconds;
repeat the sorting process many times (10, 100 perhaps) and display the timing of each attempt. You are expected to see a marked drop in the time after the first few runs, but after that the timings should stabilize. If you still observe wild variation, you know something's amiss;
to avoid garbage collection issues, reuse the same array, but re-fill it with new random data each time.
long beforeTime = System.currentTimeMillis();
// Your Code
long afterTime = System.currentTimeMillis();
long diffInMilliSeconds = afterTime- beforeTime;
before starting the calculation or exactly after generating the array you can use System#currentTimeMillis() to get the exact time and do the same exactly after completion of sorting and then find the difference.
do it this way :
long start = System.currentTimeMillis();
...
your sorting code
...
long end = System.currentTimeMillis();
long timeInMillis = end - start;
Hope that helps.
import java.util.Arrays;
import java.util.Random;
public class OppgA {
public static void main(String[] args) {
int[] anArray;
anArray = new int[1000];
Random generator = new Random();
for(int i=0; i<1000; i++){
anArray[i] = (generator.nextInt(1000)+1);
}
Date before = new Date();
Date after;
Arrays.sort(anArray);
after = new Date();
System.out.println(after.getTime()-before.getTime());
System.out.println(Arrays.toString(anArray));
}
}
This is not an ideal way. But this will work
long startingTime=System.currentTimeMillis();
Arrays.sort(anArray);
long endTime=System.currentTimeMillis();
System.out.println("Sorting time: "+(endTime-startingTime)+"ms");
Following can be the best way
long startingTime=System.nanoTime();
Arrays.sort(anArray);
long endTime=System.nanoTime();
System.out.println("Sorting time: "+(endTime-startingTime)+"ns");
In short, you can either extract our code to a method and than calculate the difference between the timestamps of start and end of that method or you can just run it in a profiler or an IDE and it will print the execution time
Ideally, you should not mix your business logic (array sorting in this case) with 'metrics' stuff.If you do need to measure execution time within the app, you can try to use AOP for that
Please refer to this post , which describes possible solutions in very detail
I'm supposed to be comparing a Recursive and a Non-Recursive function to see which one is quicker for a class project. The professor also wants us to time the iterations in milliseconds when the iterator is equal to 10,100,1000, etc. I got it all to work but was having loads of trouble in C++ getting the timer, so I switched to Java as it's much much easier to get millisecond output.
But now when I try to use any number over 8,000 I get a big fat stack overflow error from the Recursive algorithm. Can anyone give me any insight?
Bonus: I also can't figure out how to do the timer in the Recursive function like I did in the Non-Recursive. How would I approach this?
public class comparingTimes {
public static void main(String[] args) {
double num = 10000;
double result;
nonRec(num);
result = rec(num);
System.out.printf("Rec %.0f",(result));
}
public static void nonRec(double num)
{
double resultNum = 1;
double total = 0;
long startTime = System.currentTimeMillis();
long endTime;
for (double i = 1; i < num; i++)
{
total += i * (i+1);
if (i == resultNum)
{
endTime = System.currentTimeMillis();
System.out.printf("Total execution time: %f seconds - num = %.0f%n", (endTime - startTime)/1000.0, i);
resultNum *= 10;
}
}
System.out.printf("NonRec: %.0f%n", total);
}
public static double rec(double num)
{
if (num == 0)
return 0;
else
return num * (num-1) + rec(num-1);
}
}
The ideal use case for recursion is when you reduce the "search space" massively on each recursion level. For example, consider a binary search where each recursion level halves the remaining search space.
Your particular problem is that you're trying to do 8000 levels of recursion since each level simply decrements the value. That's going to require a fairly large chunk of stack space.
You can look into increasing the stack size for your JVM with the -ss or -oss options (depending on implementation, of course). But that will only buy you so much.
In terms of timing the whole recursive operation, I would simply store the time before the top-level call in main(), then compare that to the time after that top-level call returns, something like:
long startTime = System.currentTimeMillis();
result = rec(num);
long endTime = System.currentTimeMillis();
// Now calculate the elapsed time.
There's no need to try and do it within the recursive call itself.
If you want to do it at certain points within the recursive call, you can initialise a "global" counter variable (one outside the recursion itself, such as a class-level static variable) to 0 and have the recursive function increment it for every recursion level.
Then have it output the time deltas at the points you're interested in, such as when the variable is set to 10, 100, 1000 and so on.
Try increasing the stack size.
As for measuring time
public static void main(String[] args) {
double num = 10000;
double result;
long start = System.currentTimeMillis();
nonRec(num);
long finish = System.currentTimeMillis();
System.out.println("Time taken (non-recursive): " + (finish -start));
start = System.currentTimeMillis();
result = rec(num);
finish = System.currentTimeMillis();
System.out.println("Time taken (recursive): " + (finish -start));
System.out.printf("Rec %.0f",(result));
}