Conditional inside for loop or lots of for loop? - java

I'm trying to make my code work differently for different values of i in for loop, but I don't know if I should make the conditional go inside the loop or just create multiple for loops for enhanced speed.
My English does seem quite inefficient at explaining things, so here's an example:
for (int i = 1; i < 31; i++) {
if (i < 11) {
System.out.println(3*i);
} else if (i<21) {
System.out.println(2*i);
} else System.out.println(i);
}
or
for (int i = 1; i < 11; i++) System.out.println(3*i);
for (int i = 11; i < 21; i++) System.out.println(2*i);
for (int i = 21; i < 31; i++) System.out.println(i);
It would really help if the reason why one of them might be better or not could be explained as well. Thank you in advance :>

Enhanced speed should not be a consideration. The differences (if any) would be negligible.
You should choose the more readable version. When using a for loop, you usually mean you wish to perform the same action N times. In your case you want to perform 3 different actions, each a different number of times (or for different values of i). Therefore it makes more sense to have 3 loops.
for (int i = 1; i < 11; i++) {
System.out.println(3*i);
}
for (int i = 11; i < 21; i++) {
System.out.println(2*i);
}
for (int i = 21; i < 31; i++) {
System.out.println(i);
}

The first single loop analysis :-
Number of variable initialized 1.
Number of comparisons :-
1 < 31
1 < 11
2 < 31
2 < 11
so on.
Hence for 1 to 10 number of comparison 20.
for 11 to 20 number of comparison 30.
for 21 to 30 number of comparison 30.
so total 80 comparison for single loop.
but
for (int i = 1; i < 11; i++) System.out.println(3*i);
for (int i = 11; i < 21; i++) System.out.println(2*i);
for (int i = 21; i < 31; i++) System.out.println(i);
total comparison 31.
So the seperate loop is good instead of if else ledder.

Make the code readable is more important. The performance difference is very small, which can be ignored in most cases. Here is the experement result on my computer:
pattern 1:
run 100000 times cost 7548 milli seconds
run 1000000 times cost 70180 milli seconds
pattern 2:
run 100000 times cost 7536 milli seconds
run 1000000 times cost 70535 milli seconds

Unless driven by performance considerations let readability lead you.
The second one is surely easier to understand. Though I'd recommend using block statements:
for (int i = 1; i < 11; i++) {
System.out.println(3*i);
}
for (int i = 11; i < 21; i++) {
System.out.println(2*i);
}
for (int i = 21; i < 31; i++) {
System.out.println(i);
}
Of course you could make a formula:
for (int i = 1; i < 31; i++) {
int fac=3-((i-1)/10);
System.out.println(fac*i);
}
Though that seems fairly unreadable too it might be the best approach if the equivalent were many for-loops or a number of loops you couldn't determine at compile time.

The 3 for loops are faster (not important here), as there no longer is an if-else-if at every i-step. More important the three loops are far more readable because the if cascade is removed.
However using j = i + 1 the first loop can be converted to:
final int n = 30;
for (int j = 0; j < n; j++) {
int k = n/10 - j/10;
System.out.println(k * (j + 1));
}
Because of the division this will probably not be faster. However the removal of the if-cascade is an improvement. The expressions are harder to interprete while reading, but they specify a bit of calculating logic, which the mere stating of if conditions would not: one could change 30 with 300 and still everything would make sense.
Or
for (int j = 0; j < 3; ++j) {
for (int i = 1 + j*10; i < 11 + j*10; i++) {
System.out.println((3-j)*i);
}
}

Related

How to use two conditions (greater than and less than) for termination of a for loop in Java?

I was wondering, do you have a neat way of doing this ?
for (int i = 0; 4 > i < banners.size() ; i++) {
doSomeThing
}
bannrs.size maybe between 0 to 10 but i want just 4 time or less do work
Yes:
for (int i = 0; i < Math.min(4,banners.size()) ; i++) {
}
BTW, based on your question's title, perhaps you intended to have i in the range 4 < i < banners.size(). If that's the case, you can simply initialize i to 5:
for (int i = 5; i < banners.size() ; i++) {
}
Combine the conditions like this:
for (int i = 0; 4 > i && i < banners.size() ; i++) {
}
But this loop will terminate right away, so you probably want something like this:
for (int i = 0; i < banners.size() ; i++) {
if(4 > i){
continue;
}
}
You should probably start your loop with 4 because all the other conditions less than 4 are not going to fulfill your requirement and waste of iteration.
So the loop goes
for(int i=4;i
}

Big O for 3 nested for loops?

public int Loop(int[] array1) {
int result = 0;
for (int i = 0; i < array1.length; i++) {
for (int j = 0; j < array1.length; j++) {
for (int k = 1; k < array1.length; k = k * 2) {
result += j * j * array1[k] + array1[i] + array1[j];
}
}
}
return result;
}
I'm trying to find the complexity function that counts the number of arithmetic operations here. I know the complexity class would be O(n^3), but I'm having a bit of trouble counting the steps.
My reasoning so far is that I count the number of arithmetic operations which is 8, so would the complexity function just be 8n^3?
Any guidance in the right direction would be very much appreciated, thank you!
The first loop will run n times, the second loop will run n times however the third loop will run log(n) times (base 2). Since you are multiplying k by two each time the inverse operation would be to take the log. Multiplying we have O(n^2 log(n))
If we can agree that the following is one big step:
result += j * j * array1[k] + array1[i] + array1[j]
then let's call that incrementResult.
How many times is incrementResult called here? (log n)
for (int k = 1; k < array1.length; k = k * 2) {
// incrementResult
}
Lets call that loop3. Then how many times is loop3 called here? (n)
for (int j = 0; j < array1.length; j++) {
// loop 3
}
Let's call that loop2. Then, how many times is loop2 called here? (n)
for (int i = 0; i < array1.length; i++) {
// loop 2
}
Multiply all of those and you'll get your answer :)
That depends on the loops. For instance:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
sum += i * j * k;
}
}
}
has complexity O(1), because the number of iterations does not depend on the input at all.
Or this:
for (int i = 0; i < n*n*n*n*n*n; i++) {
sum += i;
}
is O(n^6), even though there is a single loop.
What really matters is how many iterations each loop makes.
In your case, it is easy to see that each iteration of the innermost loop is O(1). How many iterations are there? How many times do you need to double a number until you reach n? If x is the number of iterations, we'd exit the loop at the first x such that k = 2^x > n. Can you solve this for x?
Each iteration of the second loop will do this, so the cost of the second loop is the number of iterations (which are easier to count this time) times the cost of the inner loop.
And each iteration of the first loop will do this, so the cost of the first loop is the number of iterations (which is also easy to count) times the cost of the second loop.
Overall, the runtime is the product of 3 numbers. Can you find them?

Prime Numbers Java - Wheres my mistake [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
public class primzahlen {
public static void main(String[] args) {
System.out.println(2 % 1);
calculate_primenumber(10);
}
static void calculate_primenumber(int a) {
int zahl = 1;
boolean isprimenumber = false;
for (int i = 1; i <= a; i++) {
for (int j = 1; j <= i; j++) {
if (i % j > 0) {
// No PrimeNumber
isprimenumber = false;
} else {
// Is PrimeNumber
isprimenumber = true;
zahl = i;
System.out.println(zahl);
}
}
}
}
}
I don't know why this doesn't work.
I want to calculate 10 prime numbers.
But somehow it only prints counts up to 10 3 times and thats it.
I don't know wheres my mistake.
I have 2 for loops. That's how I learned the prime numbers calculation that I have to use 2 for loops for it but it don't work. I thought first it is the % (the rest) but when I do it on paper it should work.
There are at least four things wrong with your code.
First, you have the % condition backwards. If you're testing the number i, and you want to see if it has a divisor j, then you need to test i % j == 0. If this is true, the number is not prime. The way you tested it, though, you told it that if i % j is not zero, then the number is not prime.
Second, when you test to see if something divides i, you cannot test 1, and you cannot test i itself. Therefore,
for (int j = 1; j <= i; j++) {
should look more like
for (int j = 2; j < i; j++) {
although it's usually
for (int j = 2; j < Math.sqrt(i); j++) {
since once you get past the square root of i you don't need to search any more.
Third: your inner loop sets isprimenumber to either true or false on every iteration. That isn't right. If we find a case where i has a divisor, we know that isprimenumber is false, and we should never set it to true again, for that i. So a loop like this would work:
isprimenumber = true;
for (int j = 2; j < i; j++) {
if (i % j == 0) {
// No PrimeNumber
isprimenumber = false;
}
// If it's non-zero, don't set isprimenumber to true, because if we
// set it to false earlier, then it still should be false!
}
// And wait until we've tested all the j's before we can tell if it's true.
if (isprimenumber) {
}
You can also put break after isprimenumber = false, because once we've found a divisor we don't need to keep looking.
for (int j = 2; j < i; j++) {
if (i % j == 0) {
// No PrimeNumber
isprimenumber = false;
break;
}
Without the break, the loop will go on a few more times but it won't do anything useful. (But it won't be harmful, either.)
Fourth, you said you want to print 10 primes, but your logic tested all the numbers from 1 to 10, and there aren't 10 primes in that range. If you want the first 10 primes, where your parameter a is 10, you can't stop the loop at i <= a:
for (int i = 1; i <= a; i++) {
Instead, you'll need to declare another counter to count the number of primes.
int count = 0;
and when you find a prime and print it:
count++;
Then you could write your for loop like this:
for (int i = 1; count < a; i++) {
and it will stop when the number of primes reaches a.
EDIT: There's one more error I missed: the code I suggested will find that 1 is a prime number, but technically it isn't (so say the mathematicians). So you should start at i = 2:
for (int i = 2; count < a; i++) {
"I want to check for 10 prime numbers"
When you say
for (int i = 1; i <= a; i++)
You are saying "the numbers from 1 to a," which in this case is 1 to 10. Thus, you can only check 1 through 10 for primality. a is the upper bound you place on the numbers to check for primality.
If you want to get the first 10 prime number instead, you are going to have to use a condition which checks for the number of primes you have discovered (and keep count of that).
"It only prints counts up to 10 3 times and thats it"
Your modulus check should be (i % j == 0) - this means that j evenly divides i, and is therefore a factor of i. As you stand, you are saying that if any j is not a factor of i, the number is immediately composite. Not only is this not a correct conclusion, but it jumps the gun on your decision. You should assume it is prime until you can prove it is composite - then you can decide early.
One thing to keep in mind is the fact that a number, mod itself, is always 0. The same goes for a number mod 1. So, you will have to make sure you do not compare any i with itself or with 1. Change the second for loop to stop when j < i and to start with j = 2.
for (int i = 1; i <= a; i++) {
isprimenumber = true;
for (int j = 2; j < i; j++) {
// check each number less than this one for factors
if (i % j == 0) {
// found an even divisor, so the number is composite
isprimenumber = false;
break;
}
}
if (isprimenumber) {
System.out.println(i);
}
}
You can make other optimizations by noting that 1 is generally not considered a prime number, so you can have your first loop be for (int i = 2; i <= a; i++) and also considering that there are no even divisors of a number greater than one half of that number, so you can have your second loop be for (int j=2; j < i/2; j++).
This is one way
public class Primzahlen {
public static void main(String[] args){
calculate_primenumber(10);
}
static void calculate_primenumber(int a) {
int primesFound = 0;
boolean isprimenumber;
for(int i = 2; primesFound < a; i++){
isprimenumber = true;
for(int j = 2; j < i ; j++){
if(i % j == 0){
isprimenumber = false;
break;
}
}
if(isprimenumber){
primesFound++;
System.out.println(i);
}
}
}
}
but you can make it more efficient. This is only one way : klick
You must do the true thing on the end of the loop like this:
for (int i = 1; i <= a; i++) {
for (int j = 1; j <= i; j++) {
if (i % j > 0) {
// No PrimeNumber
isprimenumber = false;
} else {
// Is PrimeNumber
isprimenumber = true;
}
}
if(isprimenumber)
System.out.println(i);
}
you can only tell its a prime if you tested all numbers.

Big-Oh Notation?? Approximating the value of sum after the following code fragment, in terms of variable n

Okay, so I don't know what Big-Oh is because I swear my professor didn't cover it, and I need help for something I assume to be simple asap. I know the answers to it, but she wants code for it, and I don't know how to compile it. Basically, I googled help w/ this & they just simply have the answer, w/o an example of how to get it, or they have n = 1000 or something, but I don't see that in the prompt or what n should equal to. I hope someone understands me. Advice, please? lol.
This is the prompt:
1) Approximate the value of sum after the following code fragment, in terms of variable n in Big-Oh notation.
2) Answer the estimated run time of the following program segment in Big-Oh notation:
int sum = 0;
for (int i = 1; i <= n - 3; i++) {
for (int j = 1; j <= n + 4; j += 5) {
sum += 2;
}
sum++;
}
for (int i = 1; i <= 100; i++) {
sum++;
}
3) Answer the estimated run time of the following program segment in Big-Oh notation:
int sum = 0;
for (int i = 1; i <= n; i++) {
sum++;
}
for (int j = 1; j <= n / 2; j++) {
sum++;
}
I'm used to just sticking public static void main(String[] args) { in front of everything, so I did this:
public class BigO {
public static void main(String[] args) {
}
public static void main(int n) {
int sum = 0;
for (int i = 1; i <= n - 3; i++) {
for (int j = 1; j <= n + 4; j += 5) {
sum += 2;
}
sum++;
}
for (int i = 1; i <= 100; i++) {
sum++;
}
}
}
Of course that doesn't work.
Big O notation isn't about getting the program to work. It's about looking at the code to see how quickly the running-time of the program increases when you increase some variable (frequently the number of inputs but in this case, simply n).
Suppose that you analyse the running time of the program for successive values of n -> n=1, n=2, n-3, etc. and find that the running time is described by a linear equation like An + B. The dominant term here is the An term so you ignore the B. You can also ignore the A and say that it's order O(n).
If the running time is described by An^2 + Bn + C then it's order O(n^2).
You understand the nature of the performance by analyzing the code and determining how it's looping not by actually getting the code to run.

Traversal performance of multidimensional array in Java

In code and the results below, We can see that “Traverse2” is much faster than "Traverse1", indeed they just traverse the same number of elements.
1.How does this difference happened?
2.Putting longer interation inside shorter interation will have a better performance?
public class TraverseTest {
public static void main(String[] args)
{
int a[][] = new int[100][10];
System.out.println(System.currentTimeMillis());
//Traverse1
for(int i = 0; i < 100; i++)
{
for(int j = 0; j < 10; j++)
a[i][j] = 1;
}
System.out.println(System.currentTimeMillis());
//Traverse2
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 100; j++)
a[j][i] = 2;
}
System.out.println(System.currentTimeMillis());
}
}
Result:
1347116569345
1347116569360
1347116569360
If i change it to
System.out.println(System.nanoTime());
The result will be:
4888285195629
4888285846760
4888285914219
It means that if we put longer interation inside will have a better performance. And it seems to have some conflicts with cache hits theory.
I suspect that any strangeness in the results you are seeing in this micro-benchmark are due to flaws in the benchmark itself.
For example:
Your benchmark does not take account of "JVM warmup" effects, such as the fact that the JIT compiler does not compile to native code immediately. (This only happens after the code has executed for a bit, and the JVM has measured some usage numbers to aid optimization.) The correct way to deal with this is to put the whole lot inside a loop that runs a few times, and discard any initial sets of times that that look "odd" ... due to warmup effects.
The loops in your benchmark could in theory be optimized away. The JIT compiler might be able to deduce that they don't do any work that affects the program's output.
Finally, I'd just like to remind you that hand-optimizing like this is usually a bad idea ... unless you've got convincing evidence that it is worth your while hand-optimizing AND that this code is really where the application is spending significant time.
First, always run microbenchmark tests several times in a loop. Then you'll see both times are 0, as the array sizes are too small. To get non-zero times, increase array sizes in 100 times. My times are roughly 32 ms for Traverse1 and 250 for Traverse2.
The difference is because processor use cache memory. Access to sequential memory addresses is much faster.
My output(with you original code 100i/10j vs 10i/100j ):
1347118083906
1347118083906
1347118083906
You are using a very bad time resolution for a very quick calculation.
I changed the i and j limit to 1000 both.
int a[][] = new int[1000][1000];
System.out.println(System.currentTimeMillis());
//Traverse1
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 1000; j++)
a[i][j] = 1;
}
System.out.println(System.currentTimeMillis());
//Traverse2
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 1000; j++)
a[j][i] = 2;
}
System.out.println(System.currentTimeMillis());
output:
1347118210671
1347118210687 //difference is 16 ms
1347118210703 //difference is 16 ms again -_-
Two possibilities:
Java hotspot changes the second loop into a first-type or optimizes
with exchanging i and j.
Time resolution is still not enough.
So i changed output as System.nanoTime()
int a[][] = new int[1000][1000];
System.out.println(System.nanoTime());
//Traverse1
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 1000; j++)
a[i][j] = 1;
}
System.out.println(System.nanoTime());
//Traverse2
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 1000; j++)
a[j][i] = 2;
}
System.out.println(System.nanoTime());
Output:
16151040043078
16151047859993 //difference is 7800000 nanoseconds
16151061346623 //difference is 13500000 nanoseconds --->this is half speed
1.How does this difference happened?
Note that even ommiting you just used wrong time-resolution, you are making wrong comparations vs inequal cases. First is contiguous-access while second is not.
Lets say first nested loops are just a heating-preparing for the second one then it would make your assumption of "second is much faster" even more wrong.
Dont forget that 2D-array is an "array of arrays" in java. So, the right-most index would show a contiguous area. Faster for the first version.
2.Putting longer interation inside shorter interation will have a better performance?
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 100; j++)
a[j][i] = 2;
}
Increasing the first index is slower because the next iteration goes kbytes away so you cannot use your cache-line anymore.
Absolutely not!
In my point of view, size of array also affects the result. Like:
public class TraverseTest {
public static void main(String[] args)
{
int a[][] = new int[10000][2];
System.out.println(System.currentTimeMillis());
//Traverse1
for(int i = 0; i < 10000; i++)
{
for(int j = 0; j < 2; j++)
a[i][j] = 1;
}
System.out.println(System.currentTimeMillis());
//Traverse2
for(int i = 0; i < 2; i++)
{
for(int j = 0; j < 10000; j++)
a[j][i] = 2;
}
System.out.println(System.currentTimeMillis());
}
}
Traverse1 needs 10000*3+1 = 30001 comparisons to decide whether to exit the iteration,
however Traverse2 only needs 2*10001+1 = 20003 comparisons.
Traverse1 needs 1.5 times then number of comparisons of Traverse2.

Categories

Resources