import math
def evaluate_expression(expression, x):
"""
Helper function to safely evaluate a mathematical string.
Replaces '^' with '**' for user convenience.
Available math functions: sin, cos, tan, exp, sqrt, log.
"""
# Allow common math functions to be used in the eval context
safe_dict = {
'x': x,
'sin': math.sin,
'cos': math.cos,
'tan': math.tan,
'exp': math.exp,
'sqrt': math.sqrt,
'log': math.log,
'e': math.e,
'pi': math.pi
}
# Handle user using '^' for power instead of Python's '**'
clean_expr = expression.replace('^', '**')
try:
return eval(clean_expr, {"__builtins__": None}, safe_dict)
except Exception as e:
return None
def run_newton_raphson(func_str, deriv_str, x0, N):
"""
Runs the Newton-Raphson logic based on string inputs.
"""
x_current = x0
print(f"\nSolving for: f(x) = {func_str}")
print(f"{'Iter':<5} | {'x_n':<20} | {'Error (|f(x)|)':<20}")
print("-" * 50)
# Print initial state (n=0)
fx_start = evaluate_expression(func_str, x_current)
if fx_start is None:
print("Error: Could not evaluate function. Check your syntax.")
return
print(f"{0:<5} | {x_current:<20.10f} | {abs(fx_start):<20.10f}")
for n in range(1, N + 1):
# Calculate f(x) and f'(x)
fx = evaluate_expression(func_str, x_current)
dfx = evaluate_expression(deriv_str, x_current)
if fx is None or dfx is None:
print("Error parsing the equation. Please use python syntax (e.g., 3*x instead of 3x).")
return
# Check for zero derivative (division by zero risk)
if dfx == 0:
print("Derivative is zero. Newton-Raphson fails.")
return
# The Newton-Raphson Formula
x_next = x_current - (fx / dfx)
# Calculate error
# We evaluate the function at the NEW x to see how close to 0 we are
error = abs(evaluate_expression(func_str, x_next))
print(f"{n:<5} | {x_next:<20.10f} | {error:<20.10f}")
x_current = x_next
print("-" * 50)
print(f"Final Root Approximation: {x_current}\n")
def main():
# --- PART 1: Run the specific Assignment Question first ---
print("--- ASSIGNMENT DEFAULT RUN ---")
print("Function: x^3 - 7x")
print("Derivative: 3x^2 - 7")
run_newton_raphson("x**3 - 7*x", "3*x**2 - 7", 1.5, 20)
# --- PART 2: Interactive Loop ---
while True:
choice = input("Do you want to try another function? (y/n): ").strip().lower()
if choice != 'y':
print("Exiting program. Goodbye!")
break
print("\n--- CUSTOM INPUT MODE ---")
print("Instructions:")
print("1. Use '*' for multiplication (e.g., 3*x, not 3x)")
print("2. Use '**' or '^' for power (e.g., x^3)")
try:
# Get User Inputs
f_input = input("Enter Function f(x): ")
# Note: We ask for derivative because standard Python cannot do calculus automatically
df_input = input("Enter Derivative f'(x): ")
x0_input = float(input("Enter Initial Guess (x0): "))
N_input = int(input("Enter Number of Iterations (N): "))
run_newton_raphson(f_input, df_input, x0_input, N_input)
except ValueError:
print("Invalid input! Please enter numbers for x0 and N.")
if __name__ == "__main__":
main()