Timing bubble sorting in different scenarios - java

I am trying determine the running times of bubble sort algorithm in three different kinds of input:
1) randomly selected numbers
2) already sorted numbers
3) sorted in reverse order numbers
My expectation about their running time was:
Reverse ordered numbers would take longer than other two.
Already sorted numbers would have the fastest running time.
Randomly selected numbers would lie between these two.
I've tested the algorithm with inputs containing more than 100.000 numbers. The results wasn't like I expected. Already sorted numbers had the fastest running time but randomly selected numbers took almost twice as much time to execute compared to reverse ordered numbers. I was wondering why this is happening?
Here is how I test the inputs
int[] random = fillRandom();
int[] sorted = fillSorted();
int[] reverse = fillReverse();
int[] temp;
long time, totalTime = 0;
for (int i = 0; i < 100; i++) {
temp = random.clone();
time = System.currentTimeMillis();
BubbleSort.sort(temp);
time = System.currentTimeMillis() - time;
totalTime += time;
}
System.out.println("random - average time: " + totalTime/100.0 + " ms");
totalTime = 0;
for (int i = 0; i < 100; i++) {
temp = sorted.clone();
time = System.currentTimeMillis();
BubbleSort.sort(temp);
time = System.currentTimeMillis() - time;
totalTime += time;
}
System.out.println("sorted - average time: " + totalTime/100.0 + " ms");
totalTime = 0;
for (int i = 0; i < 100; i++) {
temp = reverse.clone();
time = System.currentTimeMillis();
BubbleSort.sort(temp);
time = System.currentTimeMillis() - time;
totalTime += time;
}
System.out.println("reverse - average time: " + totalTime/100.0 + " ms");

Benchmarks for java code are not easy, as JVM might apply a lot of optimizations to your code at runtime. It can optimize out a loop if computation result is not used, it can inline some code, JIT can compile some code into native and many other things. As a result, benchmark output is very unstable.
There are tools like jmh that simplify benchmarking a lot.
I recommend you to check this article, it has an example of benchmark for sorting algorithm.

Related

Java timer displaying incorrect times

I've been working on a 3-way merge sort algorithm, and the professor wants me to average how much time it takes to merge sort an array of 1000, 10000, 100000, 1000000 and 10000000 randomized integers over 10 trials each. However, I've been facing a problem while trying to calculate the run time; for example, when I calculate the run time for 1 million elements it displays that it took around 300ms while in reality it's taking around 40 seconds. I'm going to leave the code of my main function, I also tried putting startTime at the start and it would display the same running time.
public static void main(String args[]) {
Random r = new Random();
int[] arr = new int[1000000];
for (int i = 0; i < arr.length; i++)
arr[i] = r.nextInt();
long startTime = System.currentTimeMillis();
MergeSort test = new MergeSort();
test.sort(arr, 0, arr.length);
long endTime = System.currentTimeMillis();
long timeElapsed = endTime - startTime;
print(arr);
System.out.println("Execution time in milliseconds: " + timeElapsed);
}

Java Fib iterative and Fib recursive time comparison

Please if you could just check my work and help guide me through the System.currentTimeMillis() function. I understand that it takes a snapshot of my computer time and then when I end it it takes another snap shot and I use the difference of those times to get my run time. Just not sure I'm implementing it properly as my times for my iterative function and my recursive are almost always identical or at most 1 off. I'm confused a little as to if my start time is called again before my iterative starts or if really my time check for iterative time is iterative plus my recursive function. Should I have my total iterative time be endTimeIter - endTimeRecur? Any help is appreciated.
public class FibTest{
public static void main (String[] args){
long startTime = System.currentTimeMillis();
int n = 40;
System.out.println("The 40th Fibonacci number per my recursive function is: " + fibRecur(n));
long endTimeRecur = System.currentTimeMillis();
long totalTimeRecur = endTimeRecur - startTime;
System.out.println("The 40th Fibonacci number per my recursive function is: " + fibIter(n));
long endTimeIter = System.currentTimeMillis();
long totalTimeIter = endTimeIter - startTime;
System.out.println("The time it took to find Fib(40) with my recursive method was: " + totalTimeRecur);
System.out.println("The time it took to find Fib(40) with my iterative method was: " + totalTimeIter);
}
public static int fibRecur(int n){
if (n < 3) return 1;
return fibRecur(n-2) + fibRecur(n-1);
}
public static int fibIter(int n){
int fib1 = 1;
int fib2 = 1;
int i, result = 0;
for (i = 2; i < n; i++ ){
result = fib1 + fib2;
fib1 = fib2;
fib2 = result;
}
return result;
}
}
That's one way of how the time difference must be done
long time = System.currentTimeMillis();
methodA();
System.out.println(System.currentTimeMillis() - time);
time = System.currentTimeMillis();
methodB();
System.out.println(System.currentTimeMillis() - time);
In addition to Amir's answer:
One bug in your program is that you print
System.out.println("The 40th Fibonacci number per my recursive function is: " + fibIter(n));
I think what you want to say is:
System.out.println("The 40th Fibonacci number per my iterative function is: " + fibIter(n));

how to get more signficant digits to print from a long value?

I am trying to print a long value held by elapsed, can someone help me with the format of how to do it?
This prints 0.0
but i know it has more significant digits (maybe like .0005324 or something)
System.out.println("It took " + (double)elapsed + " milliseconds to complete SELECTION_SORT algorithm.");
'
System.currentTimeMillis();
long start = System.currentTimeMillis();
int sortedArr[] = selectionSort(arr1);
long elapsed = System.currentTimeMillis() - start;
System.out.println("\n///////////SELECTIONSort//////////////");
System.out.println("\nSelection sort implemented below prints a sorted list:");
print(sortedArr);
System.out.printf("It took %.7f ms....", elapsed);
//System.out.println("It took " + (double)elapsed + " milliseconds to complete SELECTION_SORT algorithm.");'
'
private static int[] selectionSort(int[] arr) {
int minIndex, tmp;
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
minIndex = i;
for (int j = i + 1; j < n; j++)
if (arr[j] < arr[minIndex])
minIndex = j;
if (minIndex != i) {
tmp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = tmp;
}
}
return arr;
}'
Changing the format won't give you more resolution which is what your real problem is hee if you print 1 ms with 7 digits you just get 1.0000000 every time. This doesn't help you at all.
What you need is a high resolution timer
long start = System.nanoTime();
int sortedArr[] = selectionSort(arr1);
long elapsed = System.nanoTime() - start;
System.out.println("\n///////////SELECTIONSort//////////////");
System.out.println("\nSelection sort implemented below prints a sorted list:");
print(sortedArr);
System.out.printf("It took %.3f ms....", elapsed / 1e6);
However, if you do this once you are fooling yourself because Java compiles code dynamically and gets fast the more you run it. It can get 100x faster or more making the first number you see pretty useless.
Normally I suggest you run loops many times and ignore the first 10,000+ times. This will change the results so much that you will see that the first digit was completely wrong. I suggest you try this
for(int iter = 1; iter<=100000; iter *= 10) {
long start = System.nanoTime();
int[] sortedArr = null
for(int i=0;i<iter;i++)
sortedArr = selectionSort(arr1);
long elapsed = System.nanoTime() - start;
System.out.println("\n///////////SELECTIONSort//////////////");
System.out.println("\nSelection sort implemented below prints a sorted list:");
print(sortedArr);
System.out.printf("It took %.3f ms on average....", elapsed / 1e6 / iter);
}
You will see you results improve 10x maybe even 100x just by running the code for longer.
You can use print formatting. For a double or float, to get 7 places after the decimal place, you would do:
System.out.printf("It took %.7f ms....", elapsed);
EDIT:
You are actually using a long, not a double, so you cannot have significant digits, because long only takes on integer values.
A long is an integer value and does not have decimal places.
To get an approximation of the runtime, run the same sort in a loop, say 1000 times and then divide the measured time by 1000.
For example:
System.out.println("It took " + ((double)elapsed) / NUMBER_OF_ITERATONS);
Try this:
String.format("%.7f",longvalue);
by using above line you can format your long or any floating point numbers. Here 7 is referred how many digits you want after '.' .

Array Sorting Performance

This is a pretty simple, straightforward problem, but, of course, I've managed to do something wrong. First, I generated 5 different arrays of 10 random numbers--from 1 to 10, 1 to 100, up to 1 to 100,000. Then I took each array and performed 5 different types of sorts (for a total of 25), calculating the time it takes to perform the sorts. I cannot figure out why each and every result is 0ms regardless of the size of n. What am I doing wrong?
public class Lab16Sorting {
public static void main(String[] args)
{
final int TOTAL_NUMBERS = 10;
int count;
int[] num = new int[TOTAL_NUMBERS];
Random rand = new Random();
// Generate 10 numbers from 1 - 10
System.out.println("SORT 10");
System.out.println("----------------");
for (count = 0; count < TOTAL_NUMBERS; count++)
num[count] = rand.nextInt(10);
System.out.println("Array: " + num);
runSort(num);
// Generate 10 numbers from 1 - 100
System.out.println("\nSORT 100");
System.out.println("----------------");
for (count = 0; count < TOTAL_NUMBERS; count++)
num[count] = rand.nextInt(100);
System.out.println("Array: " + num);
runSort(num);
// Generate 10 numbers from 1 - 1,000
System.out.println("\nSORT 1,000");
System.out.println("----------------");
for (count = 0; count < TOTAL_NUMBERS; count++)
num[count] = rand.nextInt(1000);
System.out.println("Array: " + num);
runSort(num);
// Generate 10 numbers from 1 - 10,000
System.out.println("\nSORT 10,000");
System.out.println("----------------");
for (count = 0; count < TOTAL_NUMBERS; count++)
num[count] = rand.nextInt(10000);
System.out.println("Array: " + num);
runSort(num);
// Generate 10 numbers from 1 - 100,000
System.out.println("\nSORT 100,000");
System.out.println("----------------");
for (count = 0; count < TOTAL_NUMBERS; count++)
num[count] = rand.nextInt(100000);
System.out.println("Array: " + num);
runSort(num);
}
/**
* Run sort algorithms
*/
private static void runSort(int[] num)
{
long before;
long after;
// Run and display selection sort
before = System.currentTimeMillis();
selectionSort(num);
after = System.currentTimeMillis();
System.out.println("Selection sort took "+ (after-before) +" milliseconds");
// Run and display bubble sort
before = System.currentTimeMillis();
bubbleSort(num);
after = System.currentTimeMillis();
System.out.println("Bubble sort took "+ (after-before) +" milliseconds");
// Run and display insertion sort
before = System.currentTimeMillis();
insertionSort(num);
after = System.currentTimeMillis();
System.out.println("Insertion sort took "+ (after-before) +" milliseconds");
// Run and display merge sort
before = System.currentTimeMillis();
mergeSort(num);
after = System.currentTimeMillis();
System.out.println("Merge sort took "+ (after-before) +" milliseconds");
// Run and display quick sort
before = System.currentTimeMillis();
quickSort(num);
after = System.currentTimeMillis();
System.out.println("Quick sort took "+ (after-before) +" milliseconds");
}
I printed out the various array addresses and I see they're all the same (which makes sense since I'm using the same array object). I thought that was the problem and so I tried using different arrays (int[] num, int[] num2...) and I tried re-initializing the array after each runSort() method call with num = new int[TOTAL_NUMBERS].
That's because the size 10 is too less to actually find out the difference in timings between the various types of sorts. Try to increase your size to somewhere around 50,000 to 1,00,000, to actually be able to see the difference(even then its gonna be in few seconds).
And if your machine can take enough load, then go about sorting elements in the range of 10,00,000(highly non-advisable just for testing time difference).
RJ is correct, you array is just too small that the sorting algorithms don't matter.
Also see this thread
Test case for Insertion Sort, MergeSort and Quick Sort
The sorting algorithm is a tuned quicksort, adapted from Jon L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function", Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November 1993). This algorithm offers n*log(n) performance on many data sets that cause other quicksorts to degrade to quadratic performance.
Above is in java doc.

JAVA BubbleSort Run Time Trouble

I've written a bubble sort program that sorts 10000 unique values into order.
I've run the program and it gives me an output, but the output doesn't seem to look right to me.
Here is the code:
public class BubbleSort {
public static void main(String[] args) {
int BubArray[] = new int[]{#here are 10000 integers#};
System.out.println("Array Before Bubble Sort");
for(int a = 0; a < BubArray.length; a++){
System.out.print(BubArray[a] + " ");
}
double timeTaken = bubbleSortTimeTaken(BubArray);
bubbleSort(BubArray);
System.out.println("");
System.out.println("Array After Bubble Sort");
for(int a = 0; a < BubArray.length; a++){
System.out.println(" Time taken for Sort : " + timeTaken + " milliseconds.");
System.out.print(BubArray[a] + " ");
}
}
private static void bubbleSort(int[] BubArray) {
int z = BubArray.length;
int temp = 0;
for(int a = 0; a < z; a++){
for(int x=1; x < (z-a); x++){
if(BubArray[x-1] > BubArray[x]){
temp = BubArray[x-1];
BubArray[x-1] = BubArray[x];
BubArray[x] = temp;
}
}
}
}
public static double bubbleSortTimeTaken(int[] BubArray) {
long startTime = System.nanoTime();
bubbleSort(BubArray);
long timeTaken = System.nanoTime() - startTime;
return timeTaken;
}
}
The code runs smooth and no errors, but this is the output I receive:
Array Before Bubble Sort
#10000 integers randomly#
Array After Bubble Sort
Time taken for Sort : 1.0114869E7 milliseconds.
10 Time taken for Sort : 1.0114869E7 milliseconds.
11 Time taken for Sort : 1.0114869E7 milliseconds.
17 Time taken for Sort : 1.0114869E7 milliseconds.
24 Time taken for Sort : 1.0114869E7 milliseconds.
35 Time taken for Sort : 1.0114869E7 milliseconds.
53 Time taken for Sort : 1.0114869E7 milliseconds.
....
14940 Time taken for Sort : 1.0114869E7 milliseconds.
14952 Time taken for Sort : 1.0114869E7 milliseconds.
14957 Time taken for Sort : 1.0114869E7 milliseconds.
14958 Time taken for Sort : 1.0114869E7 milliseconds.
14994 Time taken for Sort : 1.0114869E7 milliseconds.
14997 Time taken for Sort : 1.0114869E7 milliseconds.
BUILD SUCCESSFUL (total time: 1 second)
The 1.0114869E7 milliseconds runs throughout the program, and I don't think the output is exactly what I'm trying to do, though it looks like. I wish to output time taken for the program to run through and also each sort time.
~I hope this makes sense.
Any help would be appreciated, thanks.
I guess you might want to output this. The sysout should be before the for loop.
System.out.println(" Time taken for Sort : " + timeTaken + " milliseconds.");
for(int a = 0; a < BubArray.length; a++){
System.out.print(BubArray[a] + " ");
}
You have sorted down the array already, and you displaying it in the for loop later. The time you see output is the total time taken by bubble sort (approx.), which is being calculated in following method
public static double bubbleSortTimeTaken(int[] BubArray) {
long startTime = System.nanoTime();
bubbleSort(BubArray);
long timeTaken = System.nanoTime() - startTime;
return timeTaken;
}
}
So, that's the total time.

Categories