0

Quick question. I am currently making a synthetic division calculator and as a part of that I need to test whether or not a P/Q (a double) will work as a factor in an equation (given to the method as a list of integers).

Here is my code in the main class:

public static void main(String[] args)
{
    List<Integer> coeffs = new ArrayList<>();
    coeffs.add(1);
    coeffs.add(-6);
    coeffs.add(11);
    coeffs.add(-6);
    System.out.println(coeffs); // Returns [1, -6, 11, -6]
    System.out.println(doesPqWork(coeffs, 1)); // Returns 'true' as intended
    System.out.println(coeffs); // Returns [-6, 11, -6]
    System.out.println(doesPqWork(coeffs, -2)); // Returns 'false' not as intended
    System.out.println(coeffs); // Returns [11, -6]
    System.out.println(doesPqWork(coeffs, 3)); // Returns 'false' not as intended
    System.out.println(coeffs); // Returns [-6]
}

and here is the P/Q method itself:

private static boolean doesPqWork(List<Integer> coefficients, double PQ)
{
    List<Double> results = new ArrayList<>();
    double lastResult = coefficients.get(0);
    coefficients.remove(0);
    for(int coeff : coefficients) // 2, 1
    {
        double multiplied = PQ * lastResult;
        lastResult = coeff + multiplied;
        results.add(lastResult);
    }
    return results.get(results.size() - 1) == 0;
}

Please ignore how this method works to calculate it, I am only wondering why on earth the "coeffs" ArrayList is shrinking every time. I have been coding in Java for two years now and I have never come across this issue.

I thought that it was because when I call "coefficients.remove(0)" it is for some reason linking back to the "coeffs" list in the "main" method, yet when I create a new variable which would not possibly link back it still does weird thing.

I know a way I could fix this by creating some choppy code and repeating variables, but that seems really wasteful and I really want to know the source of this unintended behavior so I can fix it.

I am probably making a stupid mistake here, but if I am not then could someone please explain to me just what the heck is going on? Haha.

Garry
  • 11
  • 2
  • 1
    I mean you call coefficients.remove(0) So, unless I am missing something, I would assume that's why... – Michael Queue Dec 11 '15 at 04:24
  • Yes, but wouldn't that only affect the new "coefficients" variable and not the "coeffs" variable? I thought that for some reason Java thought that those two variables were the same so I created a third variable equal to "coefficients" and used that instead, but the same behavior occurred where the "coeffs" variable shrinks every time. Is it also possible that the "remove()" method is somehow buggy? – Garry Dec 11 '15 at 04:29
  • No you have a misunderstanding. You are calling `doesPqwork` multiple times in `main`. Each time you call it, it is running through that method and calling `remove` – Michael Queue Dec 11 '15 at 04:30
  • I apologize, I now know from what par said below that it is in fact NOT a copy when you pass it into a method. – Garry Dec 11 '15 at 04:34
  • oooh. I see what your saying. I believe it is because you are passing coeffs directly into your method and it is being modified. Let me work on this for a sec. – Michael Queue Dec 11 '15 at 04:34
  • Yeah I think that is the reason. Have you stepped through it in a debugger? That would be really helpful for you, but, I'm not sure if you've been introduced to it yet. Whenever you are questioning what values are where your first thought should be, I need to set a breakpoint and debug this! – Michael Queue Dec 11 '15 at 04:35
  • No, I have never really been introduced to the debugger as I haven't really needed to use it before (or I have come up with some hacky way of figuring it out ;^) I am trying to see what is happening with the variables right now using the debugger. – Garry Dec 11 '15 at 04:37
  • 1
    **This is NOT a forum** do not edit titles to say "Solved" or add it to the content. Mark an answer as correct with a checkmark to indicate that it solved your problem. Upvote the correct answer and any others that helped you, down vote anything that is incorrect or unhelpful. –  Dec 11 '15 at 04:57
  • I apologize for making it "forum", I can understand that. I do not have "enough" reputation to upvote anything yet. I am also quite unfamiliar with the whole system (my account is new, like I just made it a few minutes ago). If you would care to explain it I would love to hear it over a PM. – Garry Dec 11 '15 at 05:06

4 Answers4

0

Objects in Java (such as Arrays) are not passed as copies. Your function receives a reference to the argument passed in, so when you call coefficients.remove(0) you are removing the first element of the array you passed from main() (the coeffs array).

par
  • 17,361
  • 4
  • 65
  • 80
  • Ah, thank you. Is there some way I could make it copy and not be passed on as the same object? – Garry Dec 11 '15 at 04:32
  • No, you should definitely not make a copy of the array, that is extremely wasteful. Pass another argument to the function that is the index you want to start scanning the array from, then change the `for` loop to use that index as its starting point (or just start your loop index at `1` depending on what you want your algorithm to do). – par Dec 11 '15 at 04:56
  • Oh, I see what you mean. I will take this into consideration. Thank you. – Garry Dec 11 '15 at 05:14
0

Aha! Here is the answer OP.

When you return results.get(results.size()-1) == 0; that .size()-1 is shrinking your array. This is because when you look at your code you are passing the Array List coeffs directly into that method and changing it b/c like @par said you are passing references and not copies.

Edit: Here is the simplest way to modify your code.

public static void main(String[] args) {
        List<Integer> coeffs = new ArrayList<>();
        coeffs.add(1);
        coeffs.add(-6);
        coeffs.add(11);
        coeffs.add(-6);
        List<Integer> coeffCopy = new ArrayList(coeffs);
        System.out.println(coeffs); // Returns [1, -6, 11, -6]
        System.out.println(doesPqWork(coeffCopy, 1)); // Returns 'true' as intended
        System.out.println(coeffCopy); // Returns [-6, 11, -6]
        System.out.println(doesPqWork(coeffCopy, -2)); // Returns 'false' not as intended
        System.out.println(coeffs); // Returns [11, -6]
        System.out.println(doesPqWork(coeffCopy, 3)); // Returns 'false' not as intended
        System.out.println(coeffs); // Returns [-6]
    }

    private static boolean doesPqWork(List<Integer> coefficients, double PQ) {

        List<Double> results = new ArrayList<>();
        double lastResult = coefficients.get(0);
        coefficients.remove(0);
        for (int coeff : coefficients) // 2, 1
        {
            double multiplied = PQ * lastResult;
            lastResult = coeff + multiplied;
            results.add(lastResult);
        }
        return results.get(results.size() - 1) == 0;
    }
Michael Queue
  • 1,340
  • 3
  • 23
  • 38
  • Actually, this isn't the problem because this is relating to the "results" arraylist and has nothing at all to do with the "coeffs" arraylist :P – Garry Dec 11 '15 at 04:48
  • Yes but that logic is in the return statement, therefore, when the method is called it is modifying the original array. – Michael Queue Dec 11 '15 at 04:50
  • I really don't see how you mean. "results.get(results.size()-1) == 0" only returns a boolean by getting the last value in the arraylist, there is no code here to modify any object at all. – Garry Dec 11 '15 at 04:53
  • @Garry it's a pass by reference thing. – Michael Queue Dec 11 '15 at 05:00
  • Yeah, I got it fixed. Thanks a bunch for your help. See you around! :) – Garry Dec 11 '15 at 05:09
  • @Garry No problem! Good luck and good question! It may have been a duplicate but you didn't know. In the future, take a look at how to ask questions and make sure to do extensive research. Don't get discouraged and good work! – Michael Queue Dec 11 '15 at 05:12
-1

It is because you're calling coefficients.remove(0).

Java is pass by value, however; it passes the reference to the object as the value. See Is Java "pass-by-reference" or "pass-by-value"?

So in your case, you're passing your coeffs ArrayList and actually are manipulating it within doesPqWork().

Just creating a new reference won't fix it either. I.e. ArrayList<Integer> tmp = coeffs; just creates another reference, not a new "copy" of it.

A possible solution is to send a "copy" of your coeffs object to doesPqWork(), e.g. doesPqWork(new ArrayList<Integer>(coeffs), 1));

This creates a new object with the same values as coeffs.

How do I clone a generic List in Java? may help as well.

erratum
  • 81
  • 2
  • 7
  • Thank you! I think I will use this. I was thinking of just using this: List coeffs = coefficients.subList(1, coefficients.size()); But I like your solution a lot better! – Garry Dec 11 '15 at 04:47
-1

You need to copy the array:

    private static boolean doesPqWork(List<Integer> coefficients, double PQ) {


    // here you need to copy the coefficients. for example:
    List<Integer> copyOfCoeffs = new ArrayList<Integer>(coefficients);

    List<Double> results = new ArrayList<>();
    double lastResult = copyOfcoeffs.get(0);
    copyOfcoeffs.remove(0);
    for(int coeff : coefficients) // 2, 1
    {
        double multiplied = PQ * lastResult;
        lastResult = coeff + multiplied;
        results.add(lastResult);
    }
    return results.get(results.size() - 1) == 0;
}
franklinexpress
  • 1,149
  • 14
  • 44