You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Apache Commons Math实现分式函数f(x)=(5x-2)/(1-3x)?

处理有理函数(分式多项式)的实现方案

要实现像$f(x) = \frac{5x - 2}{1 - 3x}$这样的分式函数,Apache Commons Math3已经提供了专门的类,无需从零实现:

1. 选用RationalFunction类

org.apache.commons.math3.analysis.polynomials.RationalFunction专门用于表示两个多项式的商(即有理函数),它和PolynomialFunction一样实现了UnivariateFunction接口,完全适配你现有的数值求导逻辑。

2. 改造求导类提升通用性

把Derivee方法的参数类型从PolynomialFunction改为通用的UnivariateFunction,这样既能兼容原有的多项式,也能支持有理函数,扩展性更强:

import org.apache.commons.math3.analysis.UnivariateFunction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;

public class Derivee {
    private static final Logger LOGGER = LoggerFactory.getLogger(Derivee.class);

    /**
     * Obtenir un nombre dérivé.
     * @param f Fonction.
     * @param x Valeur x0 où l'on veut le nombre dérivé.
     * @param h écart pour calculer la limite.
     * @return Nombre dérivé.
     * @throws IllegalArgumentException si h vaut zéro.
     */
    public double getNombreDerive(UnivariateFunction f, double x, double h) {
        Objects.requireNonNull(f, "La fonction ne peut pas valoir null");

        if (h == 0) {
            throw new IllegalArgumentException("L'écart pour calculer le nombre dérivé ne peut pas valoir zéro.");
        }

        double nombreDerive = (f.value(x + h) - f.value(x)) / h;

        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Le nombre dérivé en {} est {} pour f(x) = {}, mesuré avec h = {}.", x, nombreDerive, f, h);
        }

        return nombreDerive;
    }
}

3. 编写有理函数的测试用例

针对目标分式函数$\frac{5x - 2}{1 - 3x}$,分别构造分子、分母的多项式,再创建RationalFunction实例完成测试:

import org.apache.commons.math3.analysis.polynomials.PolynomialFunction;
import org.apache.commons.math3.analysis.polynomials.RationalFunction;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class DeriveeTest {
    @Test
    @DisplayName("nombres dérivés - polynôme")
    void nombresDerivesPolynome() {
        PolynomialFunction f = new PolynomialFunction(new double[] {-2.0, 5.0});
        Derivee derivee = new Derivee();

        assertEquals(5.0, derivee.getNombreDerive(f, 3.0, 0.5), 0.01, "Le nombre dérivé du polynôme n'est pas celui attendu");
        assertThrows(IllegalArgumentException.class, () -> derivee.getNombreDerive(f, 3.0, 0), "Un h = 0 a été accepté : il aurait dû être refusé");
    }

    @Test
    @DisplayName("nombres dérivés - fonction rationnelle")
    void nombresDerivesRationnelle() {
        // 分子多项式:5x - 2 → 系数数组为[-2.0, 5.0]
        PolynomialFunction numerator = new PolynomialFunction(new double[] {-2.0, 5.0});
        // 分母多项式:1 - 3x → 系数数组为[1.0, -3.0]
        PolynomialFunction denominator = new PolynomialFunction(new double[] {1.0, -3.0});
        // 创建有理函数实例
        RationalFunction f = new RationalFunction(numerator, denominator);
        Derivee derivee = new Derivee();

        // 理论导数计算:f'(x) = -1/(1-3x)²,x=0时结果为-1.0
        double expectedDerivative = -1.0;
        assertEquals(expectedDerivative, derivee.getNombreDerive(f, 0.0, 0.001), 0.01, "Le nombre dérivé de la fonction rationnelle n'est pas celui attendu");

        // 测试分母为0的点(x=1/3≈0.333),此时函数无定义,会抛出异常
        assertThrows(ArithmeticException.class, () -> derivee.getNombreDerive(f, 1.0/3, 0.001), "Le point où le dénominateur est nul n'a pas déclenché d'exception");
    }
}

4. 运行效果说明

测试运行后会输出类似日志:

08:15:30.123 [main] DEBUG fr.ecoemploi.domain.utils.math.derivees.Derivee - 
   Le nombre dérivé en 0.0 est -0.999000999000999 pour f(x) = (-2 + 5 x)/(1 - 3 x), mesuré avec h = 0.001.

由于采用的是数值向前差分法,结果与理论值会有微小误差,缩小h的取值(比如改为0.0001)可以降低误差。


内容的提问来源于stack exchange,提问作者Marc Le Bihan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 03:25:55