Timing methods in Java produces incorrect values? - java

I tried outputting the average time it takes to run a particular method using System.currentTimeMillis():
for (int i = 1; i <= 18; i++) {
int n = (int) Math.pow(2, i);
double total_time = 0;
for (int j = 1; j <= 5; j++) {
long startTime = System.currentTimeMillis();
runMethod();
long endTime = System.currentTimeMillis();
double difference = (double) (endTime - startTime);
total_time += difference / 1000;
}
System.out.println("N = " + Integer.toString(n) +": " + Double.toString(total_time / 5) + " s");
}
However, I tried timing this myself between reported times in standard output but it seems to be way off (for one iteration, I timed it to be around 30 seconds but it reported 8). Is this the wrong method to use? Or am I implementing it incorrectly?
Is it possible that the standard output is delayed, such that the actual time is not reported until well after the method has finished, so that I would myself calculate a longer time based on what is shown in the output?

As others have observed:
- don't cast to double until you need to
- use System.nanoTime() instead of System.currentTimeMillis()
This is what it could look like:
for (int i = 1; i <= 18; i++) {
final int n = 1 << i; // = 2**i
/**/ long total_time = 0;
for (int j = 1; j <= 5; j++) {
final long t0 = System.nanoTime();
runMethod();
total_time += (System.nanoTime() - t0);
}
System.out.println("N = " + n + ": " + ((double)total_time / 1_000 / 1_000 / 1_000 / 5) + " s");
System.out.println("N = " + n + ": " + ((double)total_time / 1_000 / 1_000 / 5) + " ms");
System.out.println("N = " + n + ": " + ((double)total_time / 1_000 / 5) + " μs");
System.out.println("N = " + n + ": " + ((double)total_time / 5) + " ns");
}

you should do like this
long startTime = System.currentTimeMillis();
runMethod();
long endTime = System.currentTimeMillis();

Related

Trying a different approach for Projet Euler Problem 8

So I'm new to Java and I'm trying a different solution for Project Euler Problem 8. In this I have used BigInteger class datatype to store the 1000-digit number but I'm not able to traverse the particular values at any index or multiply it like I'm trying. Although I was able to do it with String, I want to try this method. It would be a great help.
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;
public class newexp{
public static void main(String[] args) {
BigInteger myBigInteger = new BigInteger(
"73167176531330624919225119674426574742355349194934\n" +
"96983520312774506326239578318016984801869478851843\n" +
"85861560789112949495459501737958331952853208805511\n" +
"12540698747158523863050715693290963295227443043557\n" +
"66896648950445244523161731856403098711121722383113\n" +
"62229893423380308135336276614282806444486645238749\n" +
"30358907296290491560440772390713810515859307960866\n" +
"70172427121883998797908792274921901699720888093776\n" +
"65727333001053367881220235421809751254540594752243\n" +
"52584907711670556013604839586446706324415722155397\n" +
"53697817977846174064955149290862569321978468622482\n" +
"83972241375657056057490261407972968652414535100474\n" +
"82166370484403199890008895243450658541227588666881\n" +
"16427171479924442928230863465674813919123162824586\n" +
"17866458359124566529476545682848912883142607690042\n" +
"24219022671055626321111109370544217506941658960408\n" +
"07198403850962455444362981230987879927244284909188\n" +
"84580156166097919133875499200524063689912560717606\n" +
"05886116467109405077541002256983155200055935729725\n" +
"71636269561882670428252483600823257530420752963450\n" +
"\n");
long s = 0;
int n = 1000;
long maxval = 0;
long currval = 1;
for (int i = 13; i <= n; i++){
for (long j = s; j <= 13; j++){
currval *= myBigInteger.valueOf(s);
}
s++;
}
if (maxval < currval){
maxval = currval;
}
System.out.println(maxval);
}
}
You don't really need BigInteger for this. The long's are sufficient to hold the product.
public class BigFib {
public static void main(String[] args) {
String bigNum =
"73167176531330624919225119674426574742355349194934"
+ "96983520312774506326239578318016984801869478851843"
+ "85861560789112949495459501737958331952853208805511"
+ "12540698747158523863050715693290963295227443043557"
+ "66896648950445244523161731856403098711121722383113"
+ "62229893423380308135336276614282806444486645238749"
+ "30358907296290491560440772390713810515859307960866"
+ "70172427121883998797908792274921901699720888093776"
+ "65727333001053367881220235421809751254540594752243"
+ "52584907711670556013604839586446706324415722155397"
+ "53697817977846174064955149290862569321978468622482"
+ "83972241375657056057490261407972968652414535100474"
+ "82166370484403199890008895243450658541227588666881"
+ "16427171479924442928230863465674813919123162824586"
+ "17866458359124566529476545682848912883142607690042"
+ "24219022671055626321111109370544217506941658960408"
+ "07198403850962455444362981230987879927244284909188"
+ "84580156166097919133875499200524063689912560717606"
+ "05886116467109405077541002256983155200055935729725"
+ "71636269561882670428252483600823257530420752963450";
int n = bigNum.length();
int start = 0;
long maxval = 0;
// count from 0 to the length of the string less 13.
for (int i = 0; i < n - 13; i++) {
// now starting at the first character, start taking the product of the
// digits.
long currval = 1;
for (int j = i; j < i+13; j++) {
// subtracting '0' from digit converts it to
// to an 'int'
currval *= (bigNum.charAt(j) - '0');
}
// if the current value is > maxval, assign to maxval
if (maxval < currval) {
maxval = currval;
start = i;
}
}
// now print the maxproduct and the string of digits.
System.out.println(maxval);
System.out.println("digits = " + bigNum.substring(start,start+13));
}
}

How to continue with the value you got in the first variable not start again

import java.util.Scanner;
public class MoneyChange {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.print("Input an amount of money: ");
double value = reader.nextDouble();
int money = (int) value;
int thousand = money / 1000;
int fivehundred = money / 500;
int hundred = money / 100;
int fifty = (money % 100) / 50;
int twenty = ((money % 100) % 50) / 20;
int ten = (((money % 100) % 50) % 20) / 10;
int five = ((((money % 100) % 50) % 20) % 10) / 5;
int one = (((((money % 100) % 50) % 20) % 10) % 5) / 1;
System.out.println("Number of 1000-Bhat Banknote(s) is " + thousand);
System.out.println("Number of 500-Bhat Banknote(s) is " + fivehundred);
System.out.println("Number of 100-Bhat Banknote(s) is " + hundred);
System.out.println("Number of 50-Bhat Banknote(s) is " + fifty);
System.out.println("Number of 20-Bhat Banknote(s) is " + twenty);
System.out.println("Number of 10-Bhat Coin(s) is " + ten);
System.out.println("Number of 5-Bhat Coin(s) is " + five);
System.out.println("Number of 1-Bhat Coin(s) is " + one);
reader.close();
}
}
I would like to know how to continue the values from the first variable onto the other and not start again. Help me out!
In this code
int fifty = (money % 100) / 50;
you can calculate money % 100 and store it in a variable you can re-use it
int hun = money % 100;
int fifty = (hun) / 50;
Also be aware of Integer division
please do small modifications in your program.please take the look below code once.
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.print("Input an amount of money: ");
double value = reader.nextDouble();
int money = (int) value;
int thousand = money / 1000;
int remain = money % 1000 ;
int fivehundred = remain / 500;
remain = remain % 500;
int hundred = remain / 100;
remain = remain % 100;
int fifty = remain / 50;
remain = remain % 50;
int twenty = remain / 20;
remain = remain % 20;
int ten = remain / 10;
remain = remain % 10;
int five = remain / 5;
remain = remain % 5;
int one = remain / 1;
System.out.println("Number of 1000-Bhat Banknote(s) is " + thousand);
System.out.println("Number of 500-Bhat Banknote(s) is " + fivehundred);
System.out.println("Number of 100-Bhat Banknote(s) is " + hundred);
System.out.println("Number of 50-Bhat Banknote(s) is " + fifty);
System.out.println("Number of 20-Bhat Banknote(s) is " + twenty);
System.out.println("Number of 10-Bhat Coin(s) is " + ten);
System.out.println("Number of 5-Bhat Coin(s) is " + five);
System.out.println("Number of 1-Bhat Coin(s) is " + one);
reader.close();
}

Math in Java(Combinatorics)

My problem is:
My math formula is:
In this case X = N; Y = L;U = K;
public class Play {
public static void main(String args[]) {
//n!(n−k−1)!
int n = 10;
int k =2;
int l = 12;
long result;
result = (calculaFator(n) / calculaFator(n-k-1));
result= (long) (result * Math.pow((n-k),(l-k)-1));
System.out.println(result);
}
public static long calculaFator(long x) {
long f = x;
while (x > 1) {
f = f * (x - 1);
x--;
}
return f;
}
}
It should be 721599986, but it is giving me 96636764160
I have some samples:
With n=10, k=2, l=12 it should be 721599986
With n=10, k=2, l=16 it should be 626284798
With n=10, k=1, l=20 it should be 674941304
With n=5, k=2, l=8 it should be 10800
The java codes is working according to your stated formula.
It seems like the formula is wrong rather than the codes. (or expected results or your x,u,y mapping to n,l,k is incorrect?)
int x = 10;
int u = 2;
int y = 12;
long numerator = calculaFator(x);
long denominator = calculaFator(x - u - 1);
int xu1 = x - u - 1;
long result = numerator / denominator;
System.out.println();
System.out.println(x + "!= numerator: " + numerator); //10!= numerator: 3_628_800
System.out.println(xu1 + "!= denominator: " + denominator); //7!= denominator: 5_040
System.out.println("result1: " + result); //result1: 720 (correct)
int xu = x - u;
int yu1 = y - u - 1;
double remainderPlaylist = Math.pow(xu, yu1);
System.out.println(xu + "^" + yu1 + " = " + remainderPlaylist);//8^9 = 1.34217728E8
System.out.println(xu + "^" + yu1 + " = " + (long) remainderPlaylist);//8^9 = 134_217_728 (correct)
long mul = (long) (result * remainderPlaylist);
System.out.println(result + "x" + (long)remainderPlaylist + " = " + mul); //720x134_217_728 = 96_636_764_160 (mathematically correct)

Java: Palindrome, not getting biggest number

I want to get the largest palindrome number of 3-digit numbers. This is my code:
for (int start = 100; start < 1000; start++) {
for (int start2 = 100; start2 < 1000; start2++) {
int temp = start * start2;
int biggest = 1;
String strTemp = temp + "";
if (strTemp.equals(new StringBuilder(strTemp).reverse().toString())) {
if (temp > biggest) {
biggest = temp;
System.out.println("Original: " + strTemp);
System.out.println("Reverse: " + new StringBuilder(strTemp).reverse().toString());
System.out.println("Siffra: " + start);
System.out.println("Siffra2: " + start2);
}
}
}
In the end, I get 995 x 583 and not 993 x 913, which is the largest one. Why? I have it so the int biggest always chooses the biggest number.
You need to move int biggest = 1; out of both for loops.
If you don't do that at every inner loop you restart the value of biggest.
int biggest = 1;
for (int start = 100; start < 1000; start++) {
for (int start2 = 100; start2 < 1000; start2++) {
int temp = start * start2;
String strTemp = temp + "";
if (strTemp.equals(new StringBuilder(strTemp).reverse().toString())) {
if (temp > biggest) {
biggest = temp;
System.out.println("Original: " + strTemp);
System.out.println("Reverse: " + new StringBuilder(strTemp).reverse().toString());
System.out.println("Siffra: " + start);
System.out.println("Siffra2: " + start2);
}
}
}
With java 8 you can rewrite this code as follow:
// Define what it means palindrome
IntPredicate isPalindrome = n -> new StringBuffer(String.valueOf(n)).reverse().toString().equals(String.valueOf(n));
OptionalInt max =
// Define a stream from 100 to 1000
IntStream.range(100, 1000)
// Map the original stream to a new stream
// Basically for each x of the first stream
// creates a new stream 100-1000 and map each element
// x of the first stream and y of the second stream
// to x * y
.flatMap(x -> IntStream.range(100, 1000).map(y -> x * y))
// Take only palyndrome of x * y
.filter(isPalindrome)
// take the max
.max();
A functional approach is more readable in most cases where you have to loop over n elements and is easier to filter and extract elements without
doing errors.
Move your declaration of biggest outside the loops:
int biggest = 1;
for (int start = 100; start < 1000; start++) {
for (int start2 = 100; start2 < 1000; start2++) {
int temp = start * start2;
String strTemp = temp + "";
if (strTemp.equals(new StringBuilder(strTemp).reverse().toString())) {
if (temp > biggest) {
biggest = temp;
System.out.println("Original: " + strTemp);
System.out.println("Reverse: " + new StringBuilder(strTemp).reverse().toString());
System.out.println("Siffra: " + start);
System.out.println("Siffra2: " + start2);
}
}
}
Output:
....
Original: 906609
Reverse: 906609
Siffra: 913
Siffra2: 993
int biggest = 1;
for (int start = 100; start < 1000; start++) {
for (int start2 = 100; start2 < 1000; start2++) {
int temp = start * start2;
in above you are initializing biggest=1 always. so you not getting proper result. Keep it outside of for loop.

RandomizedQuickSort method for arrays

IS there RandomizedQuickSort method in java API? OR we should write its code ourselves?
thanks
Unless you know that Arrays.sort() is not going to work for you, I suggest you use that. Otherwise I suggest you test any alternative is as good as it suggests.
I added the following to the source suggested by #org.life.java as well as a shuffle()/sort() methods which should be both randomised and quicksorted.
long runTimeNS = 2 * 1000 * 1000 * 1000L;
for (int i = 0; i < 3; i++) {
long start = System.nanoTime();
long r;
for (r = 1; r < runTimeNS; r++) {
Arrays.sort(list7.clone());
if (System.nanoTime() - start > runTimeNS) break;
}
long time = System.nanoTime() - start;
System.out.println("Average Arrays.sort() time " + time / r / 1000 + " us.");
long start1 = System.nanoTime();
for (r = 1; r < runTimeNS; r++) {
List<Integer> list = new ArrayList<Integer>();
for (int j : list7) list.add(j);
Collections.shuffle(list);
Collections.sort(list);
int[] ints = new int[list.size()];
for (int j = 0; j < list.size(); j++) ints[j] = list.get(j);
if (System.nanoTime() - start1 > runTimeNS) break;
}
long time1 = System.nanoTime() - start1;
System.out.println("Average shuffle/sort time " + time1 / r / 1000 + " us.");
long start2 = System.nanoTime();
for (r = 1; r < runTimeNS; r++) {
qrsort(list7.clone());
if (System.nanoTime() - start2 > runTimeNS) break;
}
long time2 = System.nanoTime() - start2;
System.out.println("Average qrsort() time " + time2 / r / 1000 + " us.");
}
and it prints
Average Arrays.sort() time 477 us.
Average shuffle/sort time 5964 us.
Average qrsort() time 36155 us.
Average Arrays.sort() time 474 us.
Average shuffle/sort time 5894 us.
Average qrsort() time 35078 us.
Average Arrays.sort() time 480 us.
Average shuffle/sort time 6211 us.
Average qrsort() time 34790 us.

Categories