Java function is updating its input variable - java

I'm doing a lab at the moment working on fitness functions. The problem is I'm making a SmallChange() function that does what it says, annoyingly it seems to update the variable you give it, when it shouldn't.
Here's a copy of the full class: https://gist.github.com/1710367
Line 38 is the problem line.
And below is the function. When I give it solution as an input it updates solution with the small change it makes, but I can't figure out how or why.
Anyone know where I'm going wrong? It's starting to hurt my brain.
// Edits either the angle or velocity of our solution
// by a small amount (about 1% of the diffrence between max and min)
public static Double[] SmallChange(Double[] sol) {
// Pick a 0 or 1
switch (r.nextInt(2)) {
case 1: // Changing the angle
// The angle change amount
Double angle = (angleLimits[1] - angleLimits[0]) * 0.01;
// Make the change, either + or -
if (r.nextInt(2) == 0) {
sol[0] += angle;
} else {
sol[0] -= angle;
}
// Check it's within the limits
if (sol[0] > angleLimits[1]) {
sol[0] = angleLimits[1];
} else if (sol[0] < angleLimits[0]) {
sol[0] = angleLimits[1];
}
break;
case 0: // Changing the velocity
// The velocity change amount
Double velocity = (velocityLimits[1] - velocityLimits[0]) * 0.01;
// Make the change, either + or -
if (r.nextInt(2) == 0) {
sol[1] += velocity;
} else {
sol[1] -= velocity;
}
// Check it's within the limits
if (sol[1] > velocityLimits[1]) {
sol[1] = velocityLimits[1];
} else if (sol[1] < velocityLimits[0]) {
sol[1] = velocityLimits[1];
}
break;
}
return sol;
}

In Java, everything is passed by value - but that value is always either a primitive, or a reference.
So the value of any array variable is a reference to an array object. When you use that variable as an argument, the value (the reference) ends up as the initial value of the parameter. It's still referring to the same array object as the caller's variable - so any changes made to the array will be seen by the caller.
So just to clarify, your statement here is incorrect:
annoyingly it seems to update the variable you give it, when it shouldn't
It hasn't changed the value of the variable at all: that variable in the calling code still has the same value it did before, a reference to the same array. It's just that the method is changing the contents of the array.
It's like copying down your address on a piece of paper, then giving that to someone: they can't change where you live, but they can change the colour of your front door.
Now, to fix your problem...
If you want to clone the array, you'll have to do so explicitly. For example:
public static Double[] smallChange(Double[] sol) {
Double[] ret = (Double[]) sol.clone();
// Now work on ret instead of sol, and return ret at the end
You could reassign to sol, but personally I wouldn't.
Note that you might also want to use a double[] instead of Double[].

Related

For loop and if statement within a method

I am new to using java and am having some issues in my java class right now and will be needing help with my specific code. I try to look at others questions on here all the time but it's never exactly what I need. Here are my directions:
Create a Java file called CompoundInterestYourLastName. Write a method called computeBalance() that computes the balance of a bank account with a given initial balance and interest rate, after a given number of years. Assume interest is compounded yearly.
Use a loop to control the iterations through the years in your method.
Your method should return a double value.
In your main method, run the following tests to verify your method is working correctly.
System.out.printf("Your total is $%.2f", computeBalance(1000, .045, 3));
// should return $1141.17
I am using eclipse and my only current error is in the comments. I also want some general tips and let me know if my logic is wrong. It probably is. :D
Here is what I have currently although I have been trying different things:
import java.util.Scanner;
import java.lang.Math;
public class CompoundInterestTidwell {
public static void main(String[] args) {
double compInt = computeBalance(1000, 0.045, 3);
System.out.printf("Your new balance is $%.2f", compInt);
}
// Getting arror for line of code below.
// Error: This method must return a result of type double
public static double computeBalance(int P, double r, int t) {
// Formula for compounding interest
// A = P(1+(r/n))^(n(t))
// The examples to check my math had rate already divided by 100 so I left out r/n.
for(int c = 0; c <= t; c++ ) {
// deleted 'n' from equation because it need to equal 1 anyways.
double compInt = Math.pow(P*(1+r), t);
if (c < t) {
c++;
return compInt;
}
}
}
}
Thanks.
Your function computeBalance doesn't guarantee to return a value, because the only return statement is in an if clause, within a loop (making it two conditions deep).
This is a thing the compiler is warning you about. Basically it scans your code and makes sure that a function declared as double will actually return a valid value of type double and so on.
If you add a return statement at the end of the body in the function (or throw an error) it should compile.
I am not exactly sure what your function does in technical terms, but I've rewritten it so it should return the same value, but should now actually compile.
public static double computeBalance(int P, double r, int t) {
// Formula for compounding interest
// A = P(1+(r/n))^(n(t))
// The examples to check my math had rate already divided by 100 so I left out r/n.
double compInt = 0; // Declare compInt outside the loop.
for(int c = 0; c <= t; c++ ) {
// deleted 'n' from equation because it need to equal 1 anyways.
compInt = Math.pow(P*(1+r), t);
if (c < t) {
c++;
break; // Break instead of return, will immediately
// go to the return statement outside the loop.
}
}
return compInt; // Moved the return statement to outside the loop so
// the function always will return a double.
}

Simple if-clause not working, can't find the mistake

So I am working on an incremental game at the moment. In case you don't know what this is a short explanation. You click a button to get some kind of money (in my case gold). With enough money you can buy stuff that makes you money without even clicking. With more money you can get better upgrades which makes you even more money and so on.
Now to my problem; I created a class called Upgrade which you can see here:
public class Upgrade {
double baseCost;
double baseIncome;
int count =0;
double cost = baseCost*Math.pow(1.07,count);
double goldPerSecond = baseIncome; //TODO find usefull formula!
public Upgrade(double baseC, double baseIn){
baseCost = baseC;
baseIncome = baseIn;
}
}
The variables should explain themselves.
Now I created some Upgrades via the constructor:
Upgrade waitress = new Upgrade(50 ,2); //Constructor for Waitress
Upgrade seats = new Upgrade(100, 5); //Constructor for More-Seats
Upgrade decoration = new Upgrade(500, 20); //Constructor for Decoration
Upgrade bartender = new Upgrade (1000, 50); //Constructor for Bartender
To buy upgrades I have written the method buyUpgrade which is bound to buttons referring to the upgrades listed above.
public void buyUpgrade(Upgrade U) {
if (goldCount >= U.cost) {
goldCount = goldCount - U.cost;
clickGoldPerSecond++;
U.count++;
} else {
error.setText(getResources().getString(R.string.no_gold));
}
}
And here comes the problem. As the game starts you have 0 gold. That 0 is stored in the variable goldCount. But even though goldCount is I can buy every Upgrade in unlimited amounts. I just cant figure out the problem. Probably it is really simple and afterwards I realize how stupid I was but I just cant figure it out.
Every help is appreciated. Thank you!
The problem is that
double baseCost;
double baseIncome;
int count =0;
double cost = baseCost*Math.pow(1.07,count);
baseCost being the member variable of the class, is intialized to 0.0
SO "cost" set to 0.0 and it never changed after that.
You should move the cost calculation in the constructor.
public Upgrade(double baseC, double baseIn){
baseCost = baseC;
baseIncome = baseIn;
cost = baseCost*Math.pow(1.07,count);
}
public class Upgrade
{
double baseCost;
double baseIncome;
int count =0;
double cost ;
double goldPerSecond;
public Upgrade(double baseC, double baseIn)
{
baseCost = baseC;
cost = baseCost * Math.Pow(1.07,count);
baseIncome = baseIn;
}
}
Your Upgrade class should be similar to what I have created here. If there is a non static filed in the class and you are assigning value to that variable in the way you were doing it will not work.
In your case you also cannot use the static variable as the variable baseCost is passed as constructor parameter and will not be available until you create an instance of upgrade class.
If Condition if(goldCount >= U.cost){} Here the cost will have value of zero only as it would not get updated.
Here is your problem:
int count =0;
double cost = baseCost*Math.pow(1.07,count); // cost is set and will not be updated
Pls note that you update baseCost in your constructor, but before that the default value 0.0 is being used for baseCost * Math.pow(...);. But even if you update that, by having it done in the constructor, still you will not see any price going up, because the cost is not being recalculated at all.
Set the initial value in the constructor (or have baseCost always being added to the cost when accessing the cost).
Make a method which adds one to count and then does Math.pow(...) on cost again.
Now for a much better solution: hence, in this case the attribute cost is useless. Change it into a method:
public double getCost() {
return baseCost*Math.pow(1.07,count);
}
call it (change 2x U.cost --> U.getCost()) and your sky will be blue again, no further change needed where ever.
You are missing getter/setter for cost i guess. Therefore it always return 0.0.
I mean try to create an Upgrade object with the constructor, then print out the cost. No matter what you give in the constructor, the cost for the object always print out "0.0".

Finding local minimum of minima

I have a list of double values (distances between point p0 and a point list L) and I'm looking for their minimum. Then I'm changing the list (which now contains distances between point p1 and the point list L) and compute this new minimum.
I repeat this until the new minimum is bigger than the minimum at the previous step.
In pseudo Java code:
double minDistanceTotal = Double.MAX_VALUE;
double minDistanceCurrent = ?????;
while (minDistanceCurrent < minDistanceTotal) {
Point curPoint = ... // take another point p0, p1, p2...
// compute current minimum distance
for (Point otherPoint : pointList) {
double curDistance = distance(curPoint, otherPoint);
if (curDistance < minDistanceCurrent) {
minDistanceCurrent = curDistance;
}
}
// compare it to the total minimum distance
if (minDistanceCurrent < minDistanceTotal) {
... // do something
minDistanceTotal = minDistanceCurrent;
}
}
My problem now is that I'm not sure about how to initialize minDistanceCurrent. First I tried Double.MAX_VALUE - 1, but then the while-loop isn't executed at all.
After checked the Java API to find the actual value of Double.MAX_VALUE which is 0x1.fffffffffffffP+1023. So I tried 0x1.ffffffffffffeP+1023 as the value for minDistanceCurrent, which seems to work.
But I'm not sure if this is really the second highest double value in Java.
So, what's the value I should initialize minDistanceCurrent with? Or is there some different approach to get what I want that I missed?
EDIT: After the answer of #resueman, I realized a flaw in the code. The check of current minimum and total minimum can just be done after a new current minimum is computed and not before (as it is in the condition of the while loop).
The problem was fixed using the following code:
double minDistanceTotal = Double.MAX_VALUE;
double minDistanceCurrent = Double.MAX_VALUE;
while (true) {
Point curPoint = ... // take another point
// compute current minimum distance
for (Point otherPoint : pointList) {
double curDistance = distance(curPoint, otherPoint);
if (curDistance < minDistanceCurrent) {
minDistanceCurrent = curDistance;
}
}
// compare it to the total minimum distance
if (minDistanceCurrent < minDistanceTotal) {
... // do something
minDistanceTotal = minDistanceCurrent;
} else {
break;
}
}
An alternative would be while(!pointList.isEmpty()) to avoid an infinite loop when the list is empty.
It looks like you only want to break out of the loop after this block of code is called
if (minDistanceCurrent < minDistanceTotal) {
... // do something
minDistanceTotal = minDistanceCurrent;
}
If that's the case, then I'd suggest changing your while loop to either while(true) and putting a break in the if statement, or making it while(minDistanceTotal != minDistanceCurrent)
If I'm not wrong, your loop will execute just once. Either the distances calculated by the 'distance' method are lower than MAX_VALUE or overflow the double. In any case, your last 'if' will set current and total distances equal, hence getting you out of the loop. I doubt this is what you really want.
Probably you want just to make minDistanceTotal = minDistanceCurrent just at beginning of the loop, and probably you want to use BigDecimal instead of double to avoid overflowing and inaccurate calculations, but I can't really say as I don't get the idea behind your algorithm.
Summarizing:
Be careful on how you calculate distances inside your "distance(curPoint, otherPoint)", in particular consider overflowing effects. Maybe use BigDecimal instead of Double.
Get ride of the last if and change it for whatever you really need to do.
Hope it helps somehow.

making sure i am doing this problem correctly

this is my first programming course, and i want to make sure i am doing this problem correctly. if you could check over my work it would be greatly appreciated.
Write a method to compute and return the balance for a checking account, given the starting balance and an array of Check objects. You may assume that the Check class already exists and has a method to get the amount from a particular check object called: double getAmount()
The array is not full, and may have gaps in it – make sure you test to see if there is an object there before you try to access it! Make your code work for any length array!
The header for the method is provided for you:
public double computeBalance(double startingBalance, Check[] register) {
int i = 0; // i must be initialized and declared somewhere at least
double total = 0.0;
while ((i >= check.length) && check[i] != null) { // is >= correct? you do i++!
total = (total + getAmount(check[i])); // should you add/compute somewhere
// the given amounts
i++;
}  
System.out.println(total);
}
Forget programming for a second. If I told you "Here's the starting balance in your account." and then handed you a bunch of checks and told you to compute the ending balance, how would you do it? Once you understand that, you can start to work on the programming problem.
Some questions:
Where are you tracking the account balance?
What will happen in your loop if one of the slots in register is empty (i.e. null)?
What is this check variable in your loop? Where is it being declared? Is check really what it should be called?
The function is declared as returning double. What are you returning?
Have you tried compiling your code? What happens?
I understand that you are asking for more than for the solution itself but there are obviously better people to guide you. You can use my example as a reference to what others are explaining to you.
public double computeBalance(double startingBalance, Check[] register) {
// let's start off from the starting balance
double total = startingBalance;
// go over all elements starting from 0
for (int i = 0; i < check.length; i++) {
// make sure you did not encounter null element
if (register[i] != null) {
// increase the total by the amount of the Check
total += register[i].getAmount();
}
}
// and finally return the resulting value
return total;
}
The execution will end when you reach a gap. Use an if-statement inside the loop for the null check instead.
If you could run your code through a compiler (which it sounds like you can't, or at least aren't being encouraged to), it would tell you that it has no idea what i, check, or getAmount are.
A method body that doesn't refer to the method parameters is generally missing something -- especially if the parameter declarations were given by your instructor.
Look again at your loop condition. What is the value of i going to be at the beginning?

How to detect an infinite loop in a recursive call?

I have a function that is recursively calling itself, and i want to detect and terminate if goes into an infinite loop, i.e - getting called for the same problem again. What is the easiest way to do that?
EDIT: This is the function, and it will get called recursively with different values of x and y. i want to terminate if in a recursive call, the value of the pair (x,y) is repeated.
int fromPos(int [] arr, int x, int y)
One way is to pass a depth variable from one call to the next, incrementing it each time your function calls itself. Check that depth doesn't grow larger than some particular threshold. Example:
int fromPos(int [] arr, int x, int y)
{
return fromPos(arr, x, y, 0);
}
int fromPos(int [] arr, int x, int y, int depth)
{
assert(depth < 10000);
// Do stuff
if (condition)
return fromPos(arr, x+1, y+1, depth + 1);
else
return 0;
}
If the function is purely functional, i.e. it has no state or side effects, then you could keep a Set of the arguments (edit: seeing your edit, you would keep a Set of pairs of (x,y) ) that it has been called with, and every time just check if the current argument is in the set. That way, you can detect a cycle if you run into it pretty quickly. But if the argument space is big and it takes a long time to get to a repeat, you may run out of your memory before you detect a cycle. In general, of course, you can't do it because this is the halting problem.
You will need to find a work-around, because as you've asked it, there is no general solution. See the Halting problem for more info.
An easy way would be to implement one of the following:
Pass the previous value and the new value to the recursive call and make your first step a check to see if they're the same - this is possibly your recursive case.
Pass a variable to indicate the number of times the function has been called, and arbitrarily limit the number of times it can be called.
You can only detect the most trivial ones using program analysis. The best you can do is to add guards in your particular circumstance and pass a depth level context. It is nearly impossible to detect the general case and differentiate legitimate use of recursive algorithms.
You can either use overloading for a consistent signature (this is the better method), or you can use a static variable:
int someFunc(int foo)
{
static recursionDepth = 0;
recursionDepth++;
if (recursionDepth > 10000)
{
recurisonDepth = 0;
return -1;
}
if (foo < 1000)
someFunc(foo + 3);
recursionDepth = 0;
return foo;
}
John Kugelman's answer with overloading is better beacuse it's thread safe, while static variables are not.
Billy3
Looks like you might be working on a 2D array. If you've got an extra bit to spare in the values of the array, you can use it as a flag. Check it, and terminate the recursion if the flag has been set. Then set it before continuing on.
If you don't have a bit to spare in the values, you can always make it an array of objects instead.
If you want to keep your method signature, you could keep a couple of sets to record old values of x and y.
static Set<Integer> xs;
static Set<Integer> ys;//Initialize this!
static int n=0;//keeps the count function calls.
int fromPos(int [] arr, int x, int y){
int newX= getX(x);
int newY= getY(y);
n++;
if ((!xs.add(Integer.valueOf(newX)) && !ys.add(Integer.valueOf(newY))){
assert(n<threshold); //threshold defined elsewhere.
fromPos(arr,newx,newy);
}
}
IMHO Only loops can go into an infinite loop.
If your method has too many level of recursion the JVM will throw a StackOverflowError. You can trap this error with a try/catch block and do whatever you plan to do when this condition occurs.
A recursive function terminates in case a condition is fulfilled.
Examples:
The result of a function is 0 or is 1
The maximum number of calls is reached
The result is lower/greater than the input value
In your case the condition is ([x0,y0] == [xN,yN]) OR ([x1,y1] == [xN,yN]) OR ([xN-1,yN-1] == [xN,yN])
0, 1, ...N are the indexes of the pairs
Thus you need a container(vector, list, map) to store all previous pairs and compare them to the current pair.
First use mvn findbugs:gui to open a gui which point to the line where this error is present.
I also faced the same problem and I solved it by adding a boolean variable in the loop verification.
Code before ->
for (local = 0; local < heightOfDiv; local = local + 200) { // Line under Error
tileInfo = appender.append(tileInfo).append(local).toString();
while (true) {
try {
tileInfo = appender.append(tileInfo).append(getTheTextOfTheElement(getTheXpathOfTile(incr))).toString();
incr++;
} catch (Exception e) {
incr = 1;
tileInfo = appender.append(tileInfo).append("/n").toString();
}
}
To Solve this problem, I just added a boolean variable and set it to false in the catch block. Check it down
for (local = 0; local < heightOfDiv; local = local + 200) {
tileInfo = appender.append(tileInfo).append(local).toString();
boolean terminationStatus = true;
while (terminationStatus) {
try {
tileInfo = appender.append(tileInfo).append(getTheTextOfTheElement(getTheXpathOfTile(incr))).toString();
incr++;
} catch (Exception e) {
incr = 1;
tileInfo = appender.append(tileInfo).append("/n").toString();
terminationStatus = false;
}
}
This is how i Solved this problem.
Hope this will help. :)

Categories