diff --git a/e2e/calculate-all-params.e2e-spec.ts b/e2e/calculate-all-params.e2e-spec.ts
index 9533c2fca374524be2406530d9c2c63526783d37..dcbd5b7c34bc1aa36b71d913555c0a3660ff7dc2 100644
--- a/e2e/calculate-all-params.e2e-spec.ts
+++ b/e2e/calculate-all-params.e2e-spec.ts
@@ -23,6 +23,7 @@ describe("ngHyd − calculate all parameters of all calculators", () => {
     11, 12, 13, 15, 17, 18, 19, 20,
     21,
     // 22 - Solveur is not calculated here because it is not independent
+    23
   ];
 
   // for each calculator
diff --git a/e2e/check-translations.e2e-spec.ts b/e2e/check-translations.e2e-spec.ts
index b0c10f97084467c212a1497b3425d4b21b9cbe47..d8491b8d970b93b1ca0cf6b46822aed0ff4cc0ee 100644
--- a/e2e/check-translations.e2e-spec.ts
+++ b/e2e/check-translations.e2e-spec.ts
@@ -25,7 +25,7 @@ describe("ngHyd − check translation of all calculators", () => {
   });
 
   // get calculators list (IDs) @TODO read it from config, but can't import jalhyd here :/
-  const calcTypes = [ 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 15, 17, 18, 19, 20, 21, 22 ];
+  const calcTypes = [ 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23 ];
 
   // options of "Language" selector on preferences page
   const langs = [ "English", "Français" ];
diff --git a/e2e/clone-all-calc.e2e-spec.ts b/e2e/clone-all-calc.e2e-spec.ts
index 8c32c1ff622ac258da4f6cd15fc6e03d7c434146..1f0ba7fcb4e709057e83ac12fa424f117a700285 100644
--- a/e2e/clone-all-calc.e2e-spec.ts
+++ b/e2e/clone-all-calc.e2e-spec.ts
@@ -23,6 +23,7 @@ describe("ngHyd − clone all calculators with all possible <select> values", ()
     11, 12, 13, 15, 17, 18, 19, 20,
     21,
     // 22 - Solveur is not cloned here because it is not independent
+    23
   ];
 
   // for each calculator
diff --git a/src/app/calculators/yaxb/yaxb.config.json b/src/app/calculators/yaxb/yaxb.config.json
new file mode 100644
index 0000000000000000000000000000000000000000..1a02898b73e6ad4d0d99160054e9b9608b6cec18
--- /dev/null
+++ b/src/app/calculators/yaxb/yaxb.config.json
@@ -0,0 +1,12 @@
+[
+    {
+        "id": "fs_yaxb",
+        "type": "fieldset",
+        "fields": [ "Y", "A", "X", "B" ]
+    },
+    {
+        "type": "options",
+        "idCal": "Y",
+        "_help": "util/yaxb.html"
+    }
+]
\ No newline at end of file
diff --git a/src/app/calculators/yaxb/yaxb.en.json b/src/app/calculators/yaxb/yaxb.en.json
new file mode 100644
index 0000000000000000000000000000000000000000..a3595ae59ad8bbdccab7c9c9b2398f64e279f596
--- /dev/null
+++ b/src/app/calculators/yaxb/yaxb.en.json
@@ -0,0 +1,8 @@
+{
+    "fs_yaxb": "Equation parameters",
+
+    "Y": "Y",
+    "A": "A",
+    "X": "X",
+    "B": "B"
+}
\ No newline at end of file
diff --git a/src/app/calculators/yaxb/yaxb.fr.json b/src/app/calculators/yaxb/yaxb.fr.json
new file mode 100644
index 0000000000000000000000000000000000000000..97f602e313f8419c7c5cf10da2dfd71ce7faeb5a
--- /dev/null
+++ b/src/app/calculators/yaxb/yaxb.fr.json
@@ -0,0 +1,8 @@
+{
+    "fs_yaxb": "Paramètres de l'équation",
+
+    "Y": "Y",
+    "A": "A",
+    "X": "X",
+    "B": "B"
+}
\ No newline at end of file
diff --git a/src/app/services/formulaire.service.ts b/src/app/services/formulaire.service.ts
index 536af784a86eea59425290587c39de106a2af409..d8b6d13f8b70b15c23ca71bd479c3a89dbe92f8b 100644
--- a/src/app/services/formulaire.service.ts
+++ b/src/app/services/formulaire.service.ts
@@ -86,6 +86,7 @@ export class FormulaireService extends Observable {
         this.calculatorPaths[CalculatorType.Pente] = "pente";
         this.calculatorPaths[CalculatorType.Bief] = "bief";
         this.calculatorPaths[CalculatorType.Solveur] = "solveur";
+        this.calculatorPaths[CalculatorType.YAXB] = "yaxb";
     }
 
     private get _intlService(): I18nService {
diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json
index b12fe6900f404f69dad1c63a622f23a2756d659d..4d329f2cbc297e6e36a3c9a4b057ad840e823f2b 100644
--- a/src/locale/messages.en.json
+++ b/src/locale/messages.en.json
@@ -16,6 +16,7 @@
     "ERROR_DICHO_NULL_STEP": "Dichotomy (initial interval search): invalid null step",
     "ERROR_DICHO_TARGET_TOO_HIGH": "Dichotomy: the solution %targetSymbol%=%targetValue% is greater than the maximum computable value %targetSymbol%(%variableSymbol%=%variableExtremeValue%)=%extremeTarget%)",
     "ERROR_DICHO_TARGET_TOO_LOW": "Dichotomy: the solution %targetSymbol%=%targetValue%  is lower than the minimum computable value %targetSymbol%(%variableSymbol%=%variableExtremeValue%)=%extremeTarget%)",
+    "ERROR_DIVISION_BY_ZERO": "Division by zero",
     "ERROR_ELEVATION_ZI_LOWER_THAN_Z2": "Upstream elevation is lower than downstream elevation",
     "ERROR_IN_CALC_CHAIN": "An error occurred in calculation chain",
     "WARNING_ERROR_IN_CALC_CHAIN_STEPS": "Errors occurred during chain calculation",
@@ -466,6 +467,8 @@
     "INFO_EXAMPLE_LABEL_PAB_COMPLETE": "Standard fish ladder",
     "INFO_EXAMPLES_TITLE": "Examples",
     "INFO_EXAMPLES_SUBTITLE": "Load standard examples",
+    "INFO_YAXB_TITRE": "Y = A.X + B",
+    "INFO_YAXB_TITRE_COURT": "Y=A.X+B",
     "WARNING_WARNINGS_ABSTRACT": "%nb% warnings occurred during calculation",
     "WARNING_REMOUS_ARRET_CRITIQUE": "Calculation stopped: critical elevation reached at abscissa %x%",
     "WARNING_STRUCTUREKIVI_HP_TROP_ELEVE": "h/p must not be greater than 2.5. h/p is forced to 2.5",
diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json
index adf9a72ce481cee7026e216e955fbc6563446343..c4ab404cfb5dbe946dbaa8f60719489020b48aa8 100644
--- a/src/locale/messages.fr.json
+++ b/src/locale/messages.fr.json
@@ -16,6 +16,7 @@
     "ERROR_DICHO_NULL_STEP": "Dichotomie&nbsp;: le pas pour la recherche de l'intervalle de départ ne devrait pas être nul",
     "ERROR_DICHO_TARGET_TOO_HIGH": "Dichotomie&nbsp;: la solution %targetSymbol%=%targetValue% est supérieure à la valeur maximale calculable %targetSymbol%(%variableSymbol%=%variableExtremeValue%)=%extremeTarget%)",
     "ERROR_DICHO_TARGET_TOO_LOW": "Dichotomie&nbsp;: la solution %targetSymbol%=%targetValue% est inférieure à la valeur minimale calculable %targetSymbol%(%variableSymbol%=%variableExtremeValue%)=%extremeTarget%)",
+    "ERROR_DIVISION_BY_ZERO": "Division par zéro",
     "ERROR_ELEVATION_ZI_LOWER_THAN_Z2": "La cote amont est plus basse que la cote aval",
     "ERROR_IN_CALC_CHAIN": "Une erreur est survenue dans la chaîne de calcul",
     "WARNING_ERROR_IN_CALC_CHAIN_STEPS": "Des erreurs sont survenues durant le calcul en chaîne",
@@ -465,6 +466,8 @@
     "INFO_EXAMPLE_LABEL_PAB_COMPLETE": "Passe à bassins type",
     "INFO_EXAMPLES_TITLE": "Exemples",
     "INFO_EXAMPLES_SUBTITLE": "Charger des exemples types",
+    "INFO_YAXB_TITRE": "Y = A.X + B",
+    "INFO_YAXB_TITRE_COURT": "Y=A.X+B",
     "WARNING_WARNINGS_ABSTRACT": "%nb% avertissements rencontrés lors du calcul",
     "WARNING_REMOUS_ARRET_CRITIQUE": "Arrêt du calcul&nbsp;: hauteur critique atteinte à l'abscisse %x%",
     "WARNING_STRUCTUREKIVI_HP_TROP_ELEVE": "h/p ne doit pas être supérieur à 2,5. h/p est forcé à 2,5",