Newton类中iterate方法修改私有Complex变量root后打印为null,如何解决?
Hey there! Let's tackle your two technical questions, starting with the concrete bug in your Newton-Raphson code since that's what's blocking you right now.
For instance variables (like your root in the Newton class) that belong to an object:
- If the method modifying the variable is an instance method (non-static, like your
iteratemethod), you just need to access the variable via the object instance after calling the method. Exactly like you're doing withn.rootinmain—the issue here isn't the access method, it's thatrootnever actually gets assigned a value in your code (we'll fix that next). - For local variables inside a method, you have two options: either return the modified value from the method, or pass a mutable container (like an array or a custom class) into the method so changes are visible outside.
root始终为null? Looking at your iterate method, there are a few critical logic and comparison bugs that prevent root from ever being assigned:
1. Broken floating-point comparison
You're using != TOL here:
if(f.evaluate(z[i]).abs() != TOL){ this.err = -2; return; }
Floating-point values almost never match exactly, so this condition will almost always be true. It causes the method to exit immediately with err=-2 before reaching the code that sets root. Never use == or != with doubles/floats—always check if the absolute difference is below a threshold.
2. Incorrect order of operations & logic checks
Your loop calculates z[i+1] but then checks the error on z[i] instead of the new value. Also, the check for convergence happens before you've even used the newly computed z[i+1].
3. Array index out-of-bounds risk
Your z array has length MAXITER, but in the loop you try to assign z[i+1] when i reaches MAXITER-1—that's an index beyond the array's bounds.
Fixed iterate method
Here's the corrected version with comments explaining the changes:
public void iterate(Complex z0) { Complex currentZ = z0; for(int i = 0 ; i < MAXITER ; i++){ Complex fpEval = fp.evaluate(currentZ); // Check if derivative is too small (avoid division by zero) if(fpEval.abs() <= TOL){ this.err = -1; return; } Complex fEval = f.evaluate(currentZ); // Check if current value is already a root if(fEval.abs() <= TOL){ this.err = 0; this.root = currentZ; this.numIterations = i; return; } // Compute next iteration (fixed the sign: Newton-Raphson is z - f(z)/f'(z)) Complex nextZ = currentZ.subtract(fEval.divide(fpEval)); // Check if change is below tolerance (converged) if(nextZ.subtract(currentZ).abs() <= TOL){ this.err = 0; this.root = nextZ; this.numIterations = i + 1; return; } currentZ = nextZ; } // If we exit the loop, we hit max iterations without converging this.err = -3; // Add an error code for max iterations }
Key fixes made:
- Removed the unnecessary
zarray (we only need the current and next value, not the entire iteration history) - Fixed floating-point comparisons to use safe threshold checks instead of equality/inequality
- Corrected the Newton-Raphson formula sign (it's
z - f(z)/f'(z), notz + ...) - Reordered logic to validate current state, compute next state, then check for convergence
- Added handling for hitting the maximum number of iterations without converging
After applying this fix, when you run your main method, n.root should no longer be null—it will hold the converged root from the Newton-Raphson iteration.
内容的提问来源于stack exchange,提问作者dwara s

