import streamlit as st import pandas as pd def divided_differences(x, y): """ Calculates the divided differences table for Newton's Divided Difference formula. Args: x (list): List of x-values. y (list): List of y-values corresponding to x-values. Returns: pandas.DataFrame: Divided differences table. """ n = len(y) if n == 0: return pd.DataFrame() dd_table = pd.DataFrame(index=range(n), columns=range(n)) dd_table[0] = pd.Series(y) for j in range(1, n): for i in range(n - j): dd_table.loc[i, j] = (dd_table.loc[i+1, j-1] - dd_table.loc[i, j-1]) / (float(x[i+j]) - float(x[i])) return dd_table def newton_interpolation_steps_latex(x, y, x_interp): """ Calculates the interpolated value at x_interp using Newton's Divided Difference formula and provides step-by-step solution in LaTeX. Args: x (list): List of x-values. y (list): List of y-values corresponding to x-values. x_interp (float): The x-value to interpolate at. Returns: tuple: (interpolated_y, dd_table, steps_latex) interpolated_y (float): The interpolated y-value at x_interp. dd_table (pandas.DataFrame): The divided differences table. steps_latex (list of str): List of LaTeX strings describing each step of the calculation. Returns (None, None, None) if there's an error (e.g., empty input). """ n = len(x) if n == 0 or len(y) != n: return None, None, None dd_table_df = divided_differences(x, y) if dd_table_df.empty: return None, None, None dd_table = dd_table_df.values.tolist() y_interp = dd_table[0][0] steps_latex = [] # Initial step in LaTeX steps_latex.append(r"Initial value: $P(x) = f[x_0] = {:.4f}$".format(y_interp)) for i in range(1, n): term = 1.0 for j in range(i): term *= (x_interp - float(x[j])) current_term_value = dd_table[0][i] * term # Construct divided difference notation in LaTeX: f[x_0, ..., x_i] dd_notation_latex = r"f[x_0" for k in range(1, i + 1): dd_notation_latex += r", x_{" + str(k) + r"}" dd_notation_latex += r"]" # Construct polynomial term in LaTeX: (x - x_0)(x - x_1)...(x - x_{i-1}) polynomial_term_latex = "" for j in range(i): polynomial_term_latex += r"(x - " + str(x[j]) + r")" if not polynomial_term_latex: polynomial_term_latex = "1" # Step description in LaTeX step_latex_description = r"Add term {}: ${} \times {} = {:.4f} \times $".format(i, dd_notation_latex, polynomial_term_latex.replace('x', str(x_interp)), dd_table[0][i]) if i > 0: term_values_latex = r" $\times$ ".join([r"({:.1f} - {})".format(x_interp, val) for val in x[:i]]) # more robust float formatting step_latex_description += term_values_latex else: step_latex_description = r"Initial value: $f[x_0] = {:.4f}$".format(dd_table[0][0]) # Should not happen in loop, but for clarity step_latex_description += r" = {:.4f}$".format(current_term_value) steps_latex.append(step_latex_description) steps_latex.append(r"Current $P(x) = {:.4f}$".format(y_interp + current_term_value)) # Corrected accumulation here y_interp += current_term_value # Accumulate interpolation value here return y_interp, dd_table_df, steps_latex st.title("Newton's Divided Difference Interpolation") st.write("Enter the x and y values as comma-separated lists, and the x value you want to interpolate.") x_values_input = st.text_area("Enter x values (comma-separated):", "2000, 2005, 2010, 2015") y_values_input = st.text_area("Enter y values (comma-separated):", "1000, 1040, 1032, 1025") x_interpolate = st.number_input("Enter x value to interpolate:", value=2001.0) if st.button("Calculate Interpolated Value with Steps (LaTeX)"): try: x_values_str = x_values_input.strip() y_values_str = y_values_input.strip() if not x_values_str or not y_values_str: st.error("Please enter both x and y values.") else: x_values = [val.strip() for val in x_values_str.split(',')] y_values = [val.strip() for val in y_values_str.split(',')] if len(x_values) != len(y_values): st.error("The number of x values and y values must be the same.") else: try: x_values_float = [float(x) for x in x_values] y_values_float = [float(y) for y in y_values] if not all(isinstance(x, (int, float)) for x in x_values_float) or not all(isinstance(y, (int, float)) for y in y_values_float): st.error("Please ensure all x and y values are numbers.") else: interpolated_y, dd_table, steps_latex = newton_interpolation_steps_latex(x_values_float, y_values_float, x_interpolate) if interpolated_y is not None: st.success(f"The interpolated value at x = {x_interpolate} is: **{interpolated_y:.4f}**") st.subheader("Divided Difference Table:") st.dataframe(dd_table.fillna('')) st.subheader("Step-by-step Calculation:") for step_latex in steps_latex: st.latex(step_latex) else: st.error("An error occurred during interpolation. Please check your input data.") except ValueError: st.error("Invalid input. Please enter comma-separated numbers for x and y values.") except Exception as e: st.error(f"An unexpected error occurred: {e}")