I am working on an exercise where a small piece of code based on a for-loop is converted to preform the same operation with a while loop. The conversion is wrong by purpose, and looks like this:
int sum = 0;
for (int i = 0; i < 4; i++) {
if (i % 3 == 0) continue;
sum += i;
}
System.out.println(sum); // prints 3
This is converted into:
int i = 0, sum = 0;
while (i < 4) {
if (i % 3 == 0) continue;
sum += i;
i++;
}
System.out.println(sum); // will not print
In the exercise, I am asked to explain why the conversion is wrong and then fix it. My thoughts are:
With the initial value of i = 0, this will trigger continue instantly after entering the will loop, since (0 % 3 == 0) will make the if-statement true. As long as the initial value is 0, this will execute the loop, for so to skip it an endless amount of times. I tried changing the initial value of i = 1, but noe sum is printed. Then I tried to increment i before executing the if-statement, and the program now prints the sum 7. The question here is; why won't the program print if i incremented after the if statement, even if the initial value of i = 1 suggests (in my head) that program should run properly?
I made a table for each program to compare the summing.
The for-loop version:
i = 0, sum += i not preformed (continue), i++
i = 1, sum = 1, i++
i = 2, sum = 3, i++
i = 3, sum += i not preformed (continue), i++
i = 4, i < 4 false, loop stopped
The while-loop version:
i = 0, i++, sum = 1
i = 1, i++, sum = 3
i = 2, i++, sum += i not preformed (continue)
i = 3, i++, sum = 7
i = 4, i < 4 false, loop stopped
In the while-loop, sum += i is preformed once more than in the for-loop. Is this the right way to convert the for-loop into a while-loop?
int i = 0, sum = 0;
while (i < 3) {
i++;
if (i % 3 == 0) continue;
sum += i;
}
System.out.println(sum);
Your 1 is focussing on it being the initial value, but that's not the point. The point is that i is never incremented when i % 3 == 0 is true, not that 0 is the initial value. So the while loop loops forever.
Your 2 doesn't make any sense: The while version will loop forever, never summing anything.
Is this the right way to convert the for-loop into a while-loop?
No, you're incrementing i at the wrong time.
Think bout how a for loop works:
Initialization - First it sets the variables to the values in the first expression.
Test - Then it tests the values using the second expression.
Execute - If the value is true, it executes the loop body.
Increment - When the loop body is complete, it executes the third (increment) expression. Note that this is after the loop body.
Make your while loop do what the for loop is doing. (I'm intentionally not doing that for you; this is a learning exercise. I'll note that the best way to convert that for loop will not use continue, however. "Best," of course, is subjective.)
In the exercise, I am asked to explain why the conversion is wrong and then fix it
The conversion is wrong simply because when you will reach a i value that modulo 3 equals 0 (the first iteration in that case), you will skip to the next iteration and re-validate. However, since you skipped directly without incrementing i , you will re-validate the same condition and re-validate ad-infinitum.
You could fix it easily by getting rid of the continue and negating the condition :
while (i < 4) {
if (i % 3 != 0)
sum += i;
i++;
}
The for-loop given by the question if converted to plain English, it means sum up from 0 to 3 and exclude all multiples of 3. (0+1+2=3)
for (int i = 0; i < 4; i++) {
if (i % 3 == 0) continue;
sum += i;
}
So now, we ask ourselves, how do we sum up 0 to x and exclude all multiples of 3 using a while-loop. We will do this without looking at the original for-loop. (Sometimes it is easier to do it this way since we already know the intention of the for-loop)
To sum up a number from 0 to 3:
int i = 0;
while(i < 4){
sum += i;
i++;
}
To sum a number from 0 to 3, excluding multiples of 3:
int i = 0;
while(i < 4){
if(i % 3 != 0)
sum += i;
i++;
}
To sum a number from 0 to 3, excluding multiples of 3 (using continue):
int i = 0;
while(i < 4){
if(i % 3 == 0){
i++; //Remember to increase i before continue
continue;
}
else
sum += i;
i++;
}
Since after the continue, all statements below it will be skipped, you have to remember to do an increment i++ before calling continue. There will be another i++ since you branch out into 2 conditions now.
According to the while loop logic, increment of variable i is conditional where as for for-loop it is unconditional. To make the increment logic uniform, you should increment in both cases.
I think the proper converting would be -
int i = 0, sum = 0;
while (i < 4) {
if (i % 3 == 0) {i++;continue;}
sum += i;
i++;
}
System.out.println(sum);
Normally the increment would be on the last line of a while loop. However, in this "disaster waiting to happen" code, there is a condition to skip to the end of the while block without incrementing i. If you are relying on i to increment, make sure it is always executed on any iteration. And also, at the end, because you want it to iterate the first time.
while (i < 4) {
if (i % 3 == 0) {
// skip!
} else {
sum += i;
}
i++;
}
Related
This question already has answers here:
How to find prime numbers between 0 - 100?
(40 answers)
Closed 6 years ago.
I am trying to find the Prime Numbers between 1 and 100 using nested Loops but I am getting weird results.
I think I have a problem with my code but I can't figure out where exactly, can someone help me ?
The first loop that I made will count the numbers from 2 to 100 (i)
the second one will count the numbers from 2 to i-1 (j)
so when you divide i%j != 0 it should give you the Prime numbers am I right ?
thanks a lot for your help
public static void main (String []args){
for(int i = 2; i<=100 ; i++)
{
for(int j = 2 ; j < i-1 ; j++ )
{
if (i%j != 0)
{
System.out.println(i );
}
}
}
}
This tests if it's not prime:
if (i%j == 0)
In which case, abort further tests and try the next number, which can be implemented a few ways, but the minimal change to your code is:
outer:
for (int i = 2; i<=100 ; i++) {
for (int j = 2 ; j < i-1 ; j++ ) {
if (i%j == 0) {
continue outer;
}
}
System.out.println(i);
}
The code outer: is a label (it can be any name, eg foo:), and continue outer; means commence the next iteration of the loop with that label.
so when you divide i%j != 0 it should gives you the Prime numbers am i right ?
No. Only if this condition is true for all j, the number is prime.
the problem is this
if (i%j != 0){
System.out.println(i );
}
}
You are saying, for each value of j, test against, i and if modulus remainder is *not 0, print. However you must check for all iterations of j in the loop before deciding the candidate (i) is prime. *all values of j that must be checked before you can conclude the prime.
Set a boolean flag false (not prime), update the flag to true if (i%j != 0) else false
then after your nested for, print against an if with the flag
I'm writing a simple cpu scheduler simulator, currently im at Round Robin algorithm. At this little piece of code, my way of implementing it is this:
take the total sum of the burst time from user input for keeping track when
this block should finish. as long as the sum is greater then or equal to 0, keep executing.
now, the problem is that the sum becomes negative and the block stops executing before the processes' burst time become all 0. is there any way i can fix this?
for example, suppose in our case that our input is {9, 12, 1, 1, 4, 4},
the output for phase 1 after executing all processes with quantum 4 is:
(where first column is the original array and the second one the decremented by quantum's value)
sum: 31
phase nr: 1
9 7 not zero
12 10 not zero
1 0 check
1 0 check
4 2 not zero
4 2 not zero
phase nr: 2
7 5 not zero
10 8 not zero
0 0 check
0 0 check
2 0 check
2 0 check
at this stage sum becomes negative and stops printing other processes
this is the code ive been working so far. i dont know if this explanation is clear enough, i tried to be as clear and specific as i could.
note: all jobs has an arrival time of 0
int[] a = {9, 12, 1, 1, 4, 4};
int sum = 0;
//total sum of the a[]
for (int i = 0; i < a.length; i++)
{
sum += a[i];
}
System.out.printf("\nsum: %d\n\n", sum);
int counter = 1;
while(sum >= 0)
{
System.out.printf("\nphase nr: %d\n", counter);
for (int i = 0; i < a.length; i++)
{
//prints the original array
System.out.printf("%d ",a[i]);
int value = a[i]; //takes a value from a[] at index i
value -= 2; //decrement the value by quantum 2
a[i] = value; //put the value at the same index
if (a[i] < 0) //it checks if any element is less than 0, if yes replace it with 0
{
a[i] = 0;
}
/**
*prints the array after subtracting 2 from each element
*in the original array and checks if there is any value
*equal to 0, if yes print "check" else "not zero"
*/
System.out.printf("%d \t%s",a[i], a[i]==0?"check":"not zero");
System.out.println();
}
/**
* decrements the sum based on the quantum
* multiplied by processes
* sum = sum -(quantum * numberOfProcesses)
*/
sum = sum - (4 * 6);
counter++;
}
The problem is in calculating your sum.
sum = sum - (4 * 6);
You subtract 24 in every iteration even if processes finish earlier(like in 1 quantum of time) or are already finished.
What you should subtract from sum in every iteration is the total time spent on actual processing. So if process is done (a[i] == 0) you don't proceed, and if the a[i] < 4 you subtract that value. Only when a[i] >=4 you should subtract 4 quanta.
If you want to spend 4 quanta of time for every process regardless of its real needs and if it's done or not then you calculate your sum wrong and it's not really Round Robin.
while(sum >= 0)
{
System.out.printf("\nphase nr: %d\n", counter);
for (int i = 0; i < a.length; i++)
{
//prints the original array
System.out.printf("%d ",a[i]);
int value = a[i]; //takes a value from a[] at index i
if(a[i] == 0) { continue;} // skip process if it's done
else if(a[i]<=4) { sum -=a[i]; a[i]=0;} // if process is less than one quantum then it's done and sum is decreased by time needed
else { sum -=4; a[i] -=4} // otherwise process needs more than one quantum so it uses up all 4
/**
*prints the array after subtracting 2 from each element
*in the original array and checks if there is any value
*equal to 0, if yes print "check" else "not zero"
*/
System.out.printf("%d \t%s",a[i], a[i]==0?"check":"not zero");
System.out.println();
}
// this part was completely unnecessary so it was removed to for loop above
counter++;
}
I'm not sure too fully understand your algorithm, but the computation of the sum is not correct. You should define some function that will sum the actual values in the array a[] instead of having some wrong constant computation (you use 4 for quantum instead of 2) and ignore the fact that some a's are not decremented once they are set to 0.
You can define something like :
public static int totalBurstTime(int[] bursts) {
int total = 0;
for (int b : bursts) {
total += b;
}
return total;
}
and call it to initialise the sum before the while loop, and then at the end of each loop.
Also, you should use some constants instead of magic numbers, eg
static final int QUANTUM = 2;
and use it everywhere you need...
I have to write a program using loops that calculates the sum of all odd numbers between a and b (inclusive), where a and b are inputs.
I made this (below) and it works fine, but I noticed one problem with it: when i enter a larger number followed by a smaller number for the inputs, it returns 0, but when i enter the smaller number first it works perfectly. Any quick fixes for this? :)
import java.util.Scanner;
public class ComputeSumAAndB
{
public static void main (String[] args)
{
Scanner in = new Scanner(System.in);
System.out.print("Please enter 2 integers: "); //prompts user for ints
int a = in.nextInt();
int b = in.nextInt();
int sum = 0;
for (int j = a; j <= b; j++)
{
if (j % 2 == 1)
sum += j;
}
System.out.println("The sum of all odd numbers (inclusive) between " + a + " and "+ b + " is " + sum);
}
}
int temp;
if(a > b) {
temp = a;
a = b;
b = temp;
}
Put this right before your for loop starts.
The if checks whether a (the first number entered) is larger than b. If it is, it swaps a and b. Now your for loop will always start with the smallest number and iterate up to the larger number (because after this if, a will always be the smaller number).
Using this method has the added side effect of making your output make sense. Your output will now always say: "between [smaller number] and [larger number]".
rolfl's answer is more elegant and works perfectly fine, but when the user enters the larger number first, your output may look kind of weird: "between [larger number] and [smaller number]", etc.
You can get the smaller and larger inputs by using the Math.min() and Math.max functions....
for (int j = Math.min(a,b); j <= Math.max(a,b); j++) {
if (j % 2 == 1) {
sum += j;
}
}
It's not working because A is larger than B in the for loop, you have it iterate while A is less than or equal to B.
You could do what nhgrif says but it's changing your data.. But he is correct.
That's because you are first expecting for the a input (inferior limit) and then the b (superior). When your program reaches the for, j = a so the condition a <= b is False, if the first input is larger. In other words it never enters the for loop.
Actually you should do the following 2 things:
1 It is just just like rolfl mentioned above. You need to put the min and max in the right place in loop.
for (int j = Math.min(a,b); j <= Math.max(a,b); j++)
{
if (j % 2 == 1) {
sum += j;
}
}
2 Use if (j % 2 == 1) it is not enough to check whether the num is odd.
e.g.
a = -5, b =0;
What will be the result?
int sum = 0;
for(int j=-5;j<0;j++)
{
if(j%2 == 1)
{
sum+=j;
}
}
The value for sum will be 0.
We need to change the condition to if(!(j%2 == 0)) Then you will get the expected result.
That's because you are first expecting for the a input (inferior limit) and then the b (superior). When your program reaches the for, j = a so the condition a <= b is False, if the first input is larger. In other words it never enters the for loop.
I have a for loop that checks for every 5th position. And at every 5th position, I'm performing an action like so (which works):
for(int i = 0; i < foo().length; i++)
{
System.out.print(i);
if(i == 5 || i == 10 || i == 15)
System.out.println();
}
Is there a way to write if statement so no matter how long foo().length is, I don't have to keep coming back to adjust it?
Use modulus(%) operator: -
if (i % 5 == 0) {
}
5 % 5 == 0, 10 % 5 == 0, ...
Since you are using a for loop, you can simply change your increment from i++ to i += 5, and leave the if condition.
for (int i = 0; i < someNum; i += 5) {
// No need to check for `i` against `modulus 5`.
}
You can use next for witout if statement
for(int i = 0; i < foo().length; i+=5)
{
adding 5 to i step by step
Use the following:
if ( i % 5 == 0 )
if you want to put it in a single print statement this would work too.
for(int i = 0; i < foo().length; i++)
{
System.out.printf("%d%s", i, (i%5==0) ? "\n" : "");
}
I'm currently working on one of my assignments, and am looking for some help with the logic for one of my functions.
First off I have a array of numbers to be categorized, then a number interval, this number determines in which position each of the numbers being plotted goes into array2.
ie.
int interval = 2;
for(int i = 0; i < array1.length; i++) {
if((array1[i] > 0) && (array1[i] < interval)) {
array2[0]++;
}
}
However, the number from array1 is 3. I would then need another if statement like so:
...
}else if((array1[i] > 2) && (array1[i] < interval * 2)) {
array2[1]++;
}else if((array1[i] >
As you can start to see the problem with this is that I would need to continue for an infinite range of numbers. So my question is what is an easier way of achieving this goal? Or is there already a library which I can utilize to do so?
I'm sorry if I didn't make this clear enough, also I would prefer if code wasn't given to me. I would appreciate if someone would be able to tell me a more effective way about going about this, thanks in advance!
EDIT:
Assuming that the interval is set to 2, and the numbers from array1 are between 0 and 10, I would need to create a code that would do such:
2 < numFromArray1 > 0 == array2[0]++
4 < numFromArray1 > 2 == array2[1]++
6 < numFromArray1 > 4 == array2[2]++
8 < numFromArray1 > 6 == array2[3]++
10 < numFromArray1 > 8 == array2[4]++
However, the numbers from array1 can be positive or negative, whole or decimal.
Use a nested loop. Obviously it's not infinitely many possibilities for interval because array2 has a fixed size. So if you loop through all the cells in array2, and then do some math to figure out what your conditions need to be... I won't give complete code (you asked me not to, but it would look something like:
for ( ... ) {
for ( ... ) {
if (array1[i] > /* do some math here */ && ... ) {
array2[/* figure out what this should be too */]++;
}
}
}
Hopefully you can figure it out from this.
By the way, if you aren't required to use an array for array2, consider learning about LinkedList<?>for a data structure that can grow in size as you need it to.
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/LinkedList.html
http://www.dreamincode.net/forums/topic/143089-linked-list-tutorial/
Assuming I understood the question correct, and the interval would be 3, than occurrences of 0, 1 and 2 would increase array2[0], occurences of 3, 4 and 5 would increase array2[1] and so on, this would be a solution:
EDIT sorry, you did not want to see code. I can repost it, if you want. Think about a real easy way to determine which category a number will be in. I'll try to give a hint.
Interval = 3;
0,1,2 -> category 0
3,4,5 -> category 1
6,7,8 -> category 2
Once you know the category, it is easy to increment the desired number in array2.
It would look something like that:
for(int i = 0; i < array1.length; i++) {
int category = // determine category here
// increase correct position of array2
}
After some dicussion, here is my code:
for(int i = 0; i < array1.length; i++) {
int category = array1[i] / interval;
array2[category]++;
}
My solution won't work for negative numbers. Also it is not specified how to handle them
Here's what you can do to consider all cases: -
First find out what is the maximum value in your array: - array1.
Your range should be 0 to maxValueInArray1
Then inside your outer for loop, you can have another, that will run from 0 to the (maximum value) / 2. Because, you don't want to check for maximum value * 2 in your interval
And then for each value, you can check for the range, if it is in that range, use array2[j]
For E.G: -
for (...) // Outer loop {
for (int j = 0; j <= maximumValueinArray1 / 2; j++) {
// Make a range for each `j`
// use the `array2[j]` to put value in appropriate range.
}
}
In your inner loop, you might check for this condition, based on following reasoning: -
For interval = 2, and say maximumValueinArray1 is max, your range looks like: -
0 * interval ----- (1 * interval) --> in `array2[0]` (0 to 2)
1 * interval ----- (2 * interval) --> in `array2[1]` (2 to 4)
2 * interval ----- (3 * interval) --> in `array2[2]` (4 to 6)
and so on.
((max / 2) - 1) * interval ----- (max / 2) * interval (`max - 2` to max)
So, try relating these conditions, with the inner loop I posted, and your problem will be solved.
I'm not sure what exactly you're trying to do, but from your code snippets, I can come up with this inner for loop:
//OUTDATED CODE - please see code block in EDIT below
//for(int i = 0; i < array1.length; i++) {
// for (int j = 0; j < 100000; j++) { //or Integer.MAXVALUE or whatever
// if ((array1[i] > (j*2)) && (array1[i] < interval * ((j*2)==0?2:(j*2)) )) {
// array2[j]++;
// }
// }
//}
EDIT: Owing to your recent edit, this is more suitable and you don't have to run an inner loop!:
Loop through array1
For each element in array1, find array2 index by taking floor of element / interval
Add 1 to array2 element at found index.
DON'T LOOK AT THE CODE BELOW =)
for(int i = 0; i < array1.length; i++) {
int index = Math.floor(array1[i] / interval);
array2[index]++;
//the rest are actually not necessary as you just need to get the index
//and the element will be within range, left inclusive (lower <= value < upper)
//int lower_range = Math.floor(array1[i] / interval) * interval;
// //or int lower_range = index * interval;
//int upper_range = Math.ceil(array1[i] / interval) * interval;
//if ((array1[i] > lower_range) && (array1[i] < upper_range)) {
// array2[index]++;
//}
}
The relationships and pattern are hard to figure out. My attempt in interpreting what you want:
How about something like:
if ( array1[i] < interval * (interval - 2) ) {
array2[interval-2]++;
}