I am testing a for-loop for smoothly moving an object on the screen.
int yPosLeft = 339;
int originalYPosLeft = yPosLeft;
for(yPosLeft < 30 + originalYPosLeft; yPosLeft++) {
// Changes the value in the statement
}
However, the loop somehow makes the object's y position go into the negative millions forever and pretty much requires a force quit. Any suggestions?
Update: I was stupid with this. Apologies for #BrainFart #Fixed
Your condition is:
yPosLeft < 30 + yPosLeft
...which will always be true. A value will always be less than 30 plus that same value.
Hence, the loop will continue forever and your object's y position will move forever! (That is, until yPosLeft gets so big that it overflows - but I seriously doubt that's the desired behaviour.)
Every number will always be inferior than itself + any positive number. So the condition is always evaluated to true, and hence your loop runs forever.
You need to rework your loop. You can read more about it here.
Maybe you meant:
int yPosLeft = 339;
for(int i = yPosLeft; i > yPosLeft - 30; i--) {
// Changes the value in the statement
}
but I'm not an Oracle ;) - just guessing
Related
I tried to do this LeetCode daily challenge but I've found out that my code loops infinitely.
I looked through it multiple times, but I cannot find where the problem is. If anyone could spot it, please answer.
public int longestValidParentheses(String s) {
int count, highestOne = 0, index = 0;
boolean isSevered = false;
boolean theEnd = false;
while(!theEnd) {
count = 0;
while(!isSevered) {
if(index<s.length()-2) {
if(s.charAt(index) == '(' & s.charAt(index++) == ')') {count = count + 2;index = index+2;}
else {isSevered = true;}}
else theEnd=true;isSevered=true;
}
highestOne = count;
}
return highestOne;
}
I have 2 suggestions for you:
Use indentation and do not write if/else on the same line as the code associated with them
Always, ALWAYS use bracelets, even if you have only a single command. I think one of the wrongs java did is letting the programmers the free not to use bracelets if there is just a single command after it. It confusing.
So you have 2 mistakes here that make your code run for infinity:
isSevered will always be true after one loop exactly, as you change it to true no matter what happens as it is outside the if else statements, hence the reason I wrote the 2 advices above.
You never changing isSeveres or theEnd at the outside loop. Meaning that if isSevers is true and theEnd is false, you will never enter the internal while and will never exit the outside while.
The two of those combined means that if the condition that make theEnd be initialized with true won't happen at the first run, you will be stuck with infinity loop.
I'm trying to write a Java program to calculate the square root of an integer x, without using in-built functions like Math.pow() . This is the approach I tried -
class Solution {
public int mySqrt(int x) {
if(x==0 || x==1)
return x;
// if(x>=2147395600)
// return 46340;
int i;
for(i=1 ; i*i<=x ; i++) {}
return i-1;
}
}
Without the commented part, I start getting errors if x is in the range 2147395600 <= x <= 2^31-1 (which is the upper limit of an int's value range in Java). For instance, for the input x=2147395600, the expected output is 46340 but the actual output is 289398. Why is this happening? Thanks to all in advance.
PS - I am aware there are other (better) methods to solve this problem, but I'd really like to know why this code behaves this way.
Since 46340 * 46340 = 2147395600, when i=46340, x=2147395600 and you reach the condition i*i<=x it evaluates to true since 2147395600 = 2147395600. So the loop counter will incremnet by 1 and in the next iteration we will get i=46341 and i * i will cause an overflow - 46341*46341 = -2147479015.
The loop condition will still be true, since -2147479015 <= 2147395600, and the loop will not stop.
You can replace the <= with =, and check for edge cases that may occur now.
Imagine you want to count how many non-ASCII chars a given char[] contains. Imagine, the performance really matters, so we can skip our favorite slogan.
The simplest way is obviously
int simpleCount() {
int result = 0;
for (int i = 0; i < string.length; i++) {
result += string[i] >= 128 ? 1 : 0;
}
return result;
}
Then you think that many inputs are pure ASCII and that it could be a good idea to deal with them separately. For simplicity assume you write just this
private int skip(int i) {
for (; i < string.length; i++) {
if (string[i] >= 128) break;
}
return i;
}
Such a trivial method could be useful for more complicated processing and here it can't do no harm, right? So let's continue with
int smartCount() {
int result = 0;
for (int i = skip(0); i < string.length; i++) {
result += string[i] >= 128 ? 1 : 0;
}
return result;
}
It's the same as simpleCount. I'm calling it "smart" as the actual work to be done is more complicated, so skipping over ASCII quickly makes sense. If there's no or a very short ASCII prefix, it can costs a few cycles more, but that's all, right?
Maybe you want to rewrite it like this, it's the same, just possibly more reusable, right?
int smarterCount() {
return finish(skip(0));
}
int finish(int i) {
int result = 0;
for (; i < string.length; i++) {
result += string[i] >= 128 ? 1 : 0;
}
return result;
}
And then you ran a benchmark on some very long random string and get this
The parameters determine the ASCII to non-ASCII ratio and the average length of a non-ASCII sequence, but as you can see they don't matter. Trying different seeds and whatever doesn't matter. The benchmark uses caliper, so the usual gotchas don't apply. The results are fairly repeatable, the tiny black bars at the end denote the minimum and maximum times.
Does anybody have an idea what's going on here? Can anybody reproduce it?
Got it.
The difference is in the possibility for the optimizer/CPU to predict the number of loops in for. If it is able to predict the number of repeats up front, it can skip the actual check of i < string.length. Therefore the optimizer needs to know up front how often the condition in the for-loop will succeed and therefore it must know the value of string.length and i.
I made a simple test, by replacing string.length with a local variable, that is set once in the setup method. Result: smarterCount has runtime of about simpleCount. Before the change smarterCount took about 50% longer then simpleCount. smartCount did not change.
It looks like the optimizer looses the information of how many loops it will have to do when a call to another method occurs. That's the reason why finish() immediately ran faster with the constant set, but not smartCount(), as smartCount() has no clue about what i will be after the skip() step. So I did a second test, where I copied the loop from skip() into smartCount().
And voilĂ , all three methods return within the same time (800-900 ms).
My tentative guess would be that this is about branch prediction.
This loop:
for (int i = 0; i < string.length; i++) {
result += string[i] >= 128 ? 1 : 0;
}
Contains exactly one branch, the backward edge of the loop, and it is highly predictable. A modern processor will be able to accurately predict this, and so fill its whole pipeline with instructions. The sequence of loads is also highly predictable, so it will be able to pre-fetch everything the pipelined instructions need. High performance results.
This loop:
for (; i < string.length - 1; i++) {
if (string[i] >= 128) break;
}
Has a dirty great data-dependent conditional branch sitting in the middle of it. That is much harder for the processor to predict accurately.
Now, that doesn't entirely make sense, because (a) the processor will surely quickly learn that the break branch will usually not be taken, (b) the loads are still predictable, and so just as pre-fetchable, and (c) after that loop exits, the code goes into a loop which is identical to the loop which goes fast. So i wouldn't expect this to make all that much difference.
I'm making a game where there is a goalie. i want him to move back and forth forever. i have an int called goalieposx (goalie position on the x axis) and i want this is go up by 1 until it hits 200, then go down by one till its back a 0 and repeat. I've tried the folllowing
//this bit isnt in the method, its outside as global varibale
boolean forward=true
//this bit is in a method which is continiouly called nonstop
if (goalieposx<200){
forward=true;
}
else if (goalieposx>200){
forward=false;
}
System.out.println(forward);
if(forward=true){
goalieposx++;
System.out.println("forward");
}
else if (forward=false){
goalieposx--;
System.out.println("backwards");
}
}
this method is called continously. It prints true until it gets to 200, then it prints false. However, it always prints forward, never backward. So conclusion is: the boolean changes as expected but the first if is always called, it seems to ignore the condition
ive also tried this
if(forward = true){
if(goalieposx==200){
forward=false;
}
else{
goalieposx++;}
}
else{
if(goalieposx==0){
forward=true;
}
else{
goalieposx--;}
System.out.println(goalieposx);
}
but this doesnt work either, it prints 1 then 2 etc upto 200 then prints 200 forever. Anyone know how i can solve this? is an if statement the wrong idea altogether?
This is why you should never do comparison for boolean types in if, while, for, whatever. You have just done the assignment in your if statement:
if(forward=true)
the above if statement will always evaluate to true. The problem with this is, this compiles successfully in Java, as syntax wise it's alright. Compiler just checks the type of expression in if evaluates to boolean or not. And it does, so it's ok with it.
You need to do the comparison:
if(forward==true)
.. but as I said, you should not do comparison for boolean types. So, simply doing this:
if(forward)
would be enough.
You also don't need those else if in both the conditions. Just an else will work fine. Well, I don't understand the use of boolean variable at all. It seems like you don't need it. You can change your code to:
if (goalieposx<200){
// forward=true;
goalieposx++;
System.out.println("forward");
}
else {
// forward=false;
goalieposx--;
System.out.println("backwards");
}
What you were previously doing is, setting a boolean variable, based on a condition, and using that boolean variable as condition to execute another if-else block. Well, whatever you are executing in the 2nd if-else block, can simply be moved in the original if-else block, without taking the help of the middle-actor boolean variable.
if(forward=true) does not do what you thing it does.
In java = is the assignment operator and == is the comparison operator. What you are doing with that statement is saying "if assign forward to true" which will set forward to true and always return true.
What you mean to say is if(forward) and if(!forward).
In fact you don't need the else if just an else as if the boolean is not true it must be false.
A better way to do it is to get it to move to the left by adding a minus number, and to the right by adding a positive number. Here's an example of doing this with a loop:
for(int i = -10; i < 100; i++) {
xPosition += i;
}
This would add -10 then -9 etc. to the position.
In your if statements, you need to put two equal signs to check for equality.
if (forward == true){
// execute code
}
EDIT 1:
if (forward)
would be much simpler.
First let's examine what you have already written:
if (goalieposx<200){
forward=true;
}
else if (goalieposx>200){
forward=false;
}
The problem with this code being first is that it while it might set the direction to false once 'goalieposx' has reached 201, in the next call, it will set the direction back to true.
Instead, try using this clever alternative:
//This goes before the infinite loop method
counter = 0;
//Then in the infinite loop method
counter++;
if(counter > 100) {
counter = -100;
}
goalieposx = 100 + counter; //(this shifts counter from
// between -100 and 100 to 0 and 200)
The problem is you are setting the direction based on the value of the integer, instead of whether a condition has previously been met. Try this:
//this bit is in a method which is continiouly called nonstop
if (forward && (goalieposx>200)){
forward=false;
}
System.out.println(forward);
if(forward=true){
goalieposx++;
System.out.println("forward");
}
else if (forward=false){
goalieposx--;
System.out.println("backwards");
}
}
I want to have a for statement that repeats until a given int reaches a certain value.
For example...
for (int variable = 0; variable < other_variable; variable++) {
The problem with this is that the for statement will never end. It will continue to repeat endlessly. What have I done wrong?
This is my code...
boolean itemexist_check = false;
do {
int i2 = m_area.m_items.size();
for (int i = 0; i < i2; i++) {
String s2 = m_area.m_items.get(i).returnName();
System.out.println("Checking...");
if (s2.contains(s)) {
System.out.println("You take the " + s2 + ".");
itemexist_check = true;
player.addItem(m_area.m_items.get(i));
m_area.m_items.remove(i);
}
else {
//do nothing, repeat loop
}
}
}
while (itemexist_check == false);
In this code, m_area.m_items.size() would return 1, so i2 would be 1.
There are several possibilities:
you change variable inside the body of the loop;
you change other_variable inside the body of the loop;
other_variable is set to a large value, in which case the loop might take a long time to terminate;
your code never completes a certain iteration of the loop, for example:
it's getting stuck inside a nested loop as suggested by #Eng.Fouad in the comments, or
it's waiting for a lock, or
it's blocking inside an I/O call that never completes (or takes a long time to complete) etc.
Without knowing the typical value of other_variable and seeing the body of the loop it's anyone's guess.
On a side note,
String s2 = m_area.m_items.get(i).returnName();
is going to cause an exception if invoked in a subsequent or later repetition after
m_area.m_items.remove(i);
is invoked, because every time m_area.m_items.remove(i) is invoked, the list/array loses an item and its size reduces, which is never reflected in the iteration boundary check.
Surely it is the do/while loop that isn't terminating? That for loop cannot possibly run forever.
You should try a
do {
}while(condition is true)
loop. However that said, you have to implement checks assuming that there will be runaway data or conditions resulting in an infinite loop. Just my 2 cents