diff --git a/src/plugins/value/engine/subdivided_evaluation.ml b/src/plugins/value/engine/subdivided_evaluation.ml
index 3ab7878306eaa3f8abb5ed4e234a11b1a79f4ffa..57806d98601a89e71b58b76c3ee291bea7225090 100644
--- a/src/plugins/value/engine/subdivided_evaluation.ml
+++ b/src/plugins/value/engine/subdivided_evaluation.ml
@@ -639,12 +639,14 @@ module Make
   (* Subdivision of the evaluation of the expression [expr], according to the
      values of a list of lvalues [lvals], in the state [state].
      [subexpr] is the smallest subexpression of [expr] containing all
-     occurrences of the lvalues in [lvals]. At the end of the subdivision, we
-     reduce the final value of [expr], [subexpr], and of the lvalues in [lvals].
+     occurrences of the lvalues in [lvals].
      [valuation] is the result of the evaluation of [expr] without subdivision.
-     This function returns the alarms and the valuation resulting from the
-     subdivided evaluation. *)
-  let subdivide_lvals context valuation subdivnb expr subexpr lvals =
+     The subdivision is stopped after [subdivnb] splits, or as soon as they can
+     no longer improve the precision of the value computed for [expr].
+     The function returns the alarms and the valuation resulting from the
+     subdivided evaluation. In the resulting valuation, the values of [expr],
+     [subexpr] and of the lvalues in [lvals] have been reduced. *)
+  let subdivide_lvals context valuation subdivnb ~expr ~subexpr lvals =
     let Hypotheses.L variables = Hypotheses.from_list lvals in
     (* Split function for the subvalues of [lvals]. *)
     let split = make_split valuation variables in
@@ -742,13 +744,15 @@ module Make
       (* List of non-linear subexpressions [subexpr], with the lvalues that
          appear multiple times in [subexpr], candidates for the subdivision. *)
       let vars = compute_non_linear expr in
+      (* Compute necessary information about the lvalues to be subdivided.
+         Also remove lvalues with pointer or singleton values. *)
+      let make_info = make_info_list context initial_valuation in
+      let vars_info = List.map (fun (e, lvals) -> e, make_info lvals) vars in
+      let vars_info = List.filter (fun (_, infos) -> infos <> []) vars_info in
       let rec subdivide_subexpr vars valuation result alarms =
         match vars with
         | [] -> `Value (valuation, result), alarms
-        | (subexpr, lvals) :: tail ->
-          (* Retrieve necessary information about the lvalues.
-             Also remove lvalues with pointer or singleton values. *)
-          let lvals_info = make_info_list context initial_valuation lvals in
+        | (subexpr, lvals_info) :: tail ->
           match lvals_info with
           | [] -> subdivide_subexpr tail valuation result alarms
           | _ ->
@@ -767,10 +771,26 @@ module Make
             Value_parameters.result ~current:true ~once:true ~dkey
               "subdividing on %a"
               (Pretty_utils.pp_list ~sep:", " Printer.pp_lval) lvals;
-            subdivide_lvals context valuation subdivnb expr subexpr lvals_info
-            >>> subdivide_subexpr tail
+            let subdivide =
+              subdivide_lvals context valuation subdivnb lvals_info
+            in
+            (* If there are no other variables to subdivide, stops the
+               subdivision as soon as they can no longer improve the value
+               of the final expression [expr]. *)
+            if tail = []
+            then subdivide ~expr ~subexpr
+            else
+              (* Otherwise, later subdivisions on other sub-expressions may
+                 improve the value of [expr] thanks to a reduction of [subexpr],
+                 even if this reduction has not directly improved the value of
+                 [expr]. Thus, stop the subdivisions according to [subexpr]
+                 instead of [expr]. Use [~expr:subexpr], then evaluate [expr]
+                 with the reduced valuation, then continue to subdivide. *)
+              subdivide ~expr:subexpr ~subexpr >>> fun valuation _ _ ->
+              Eva.evaluate context valuation expr >>>
+              subdivide_subexpr tail
       in
-      subdivide_subexpr vars valuation result alarms
+      subdivide_subexpr vars_info valuation result alarms
 
   let evaluate context valuation ~subdivnb expr =
     if subdivnb = 0 || not activated
diff --git a/tests/float/oracle/nonlin.1.res.oracle b/tests/float/oracle/nonlin.1.res.oracle
index 3a1506cfa7bae0a013c33b2f8ac41af58f2b66cf..3ddef66ef496f7061b9f8444af849b2b4bd1bafb 100644
--- a/tests/float/oracle/nonlin.1.res.oracle
+++ b/tests/float/oracle/nonlin.1.res.oracle
@@ -342,7 +342,7 @@
   d ∈ [0x1.4000000000000p2 .. 0x1.c000000000000p2]
 [eva:final-states] Values at end of function norm:
   Frama_C_entropy_source ∈ [--..--]
-  v1 ∈ [-0x1.0f0cf00000000p73 .. 0x1.bc16d60000000p59]
+  v1 ∈ [-0x1.0f0cde0000000p64 .. 0x1.bc16d60000000p59]
   v2 ∈ [-0x1.0f0cf00000000p73 .. 0x1.bc16d60000000p59]
   square ∈ [0x0.0000000000000p0 .. 0x1.fffffc0000020p256]
   square2 ∈ [0x0.0000000000000p0 .. 0x1.fffffe0000000p127]
diff --git a/tests/float/oracle/nonlin.2.res.oracle b/tests/float/oracle/nonlin.2.res.oracle
index 2b0e030e86b354257dc29606a9413e9e8dcd4744..ba81c19d44c306730614d89d500ccdb7fde507a5 100644
--- a/tests/float/oracle/nonlin.2.res.oracle
+++ b/tests/float/oracle/nonlin.2.res.oracle
@@ -317,7 +317,7 @@
   v1 ∈ [-0x1.0f0cf00000000p73 .. 0x1.bc16d60000000p59]
   v2 ∈ [-0x1.0f0cf00000000p73 .. 0x1.bc16d60000000p59]
   square ∈ [0x0.0000000000000p0 .. inf] ∪ {NaN}
-  square2 ∈ [-inf .. inf] ∪ {NaN}
+  square2 ∈ [0x0.0000000000000p0 .. inf]
 [eva:final-states] Values at end of function other:
   Frama_C_entropy_source ∈ [--..--]
   i ∈ [-0x1.8effffffffff7p1 .. 0x1.8680000000000p1]
diff --git a/tests/float/oracle/nonlin.4.res.oracle b/tests/float/oracle/nonlin.4.res.oracle
index d891c92adecec0773a0a204be2e8ade3147c4753..2f06c2710cf66d8592b8fdae363e0a41589b4481 100644
--- a/tests/float/oracle/nonlin.4.res.oracle
+++ b/tests/float/oracle/nonlin.4.res.oracle
@@ -342,7 +342,7 @@
   d ∈ [0x1.4000000000000p2 .. 0x1.c000000000000p2]
 [eva:final-states] Values at end of function norm:
   Frama_C_entropy_source ∈ [--..--]
-  v1 ∈ [-0x1.0f0cf00000000p73 .. 0x1.bc16d60000000p59]
+  v1 ∈ [-0x1.0f0cde0000000p64 .. 0x1.bc16d60000000p59]
   v2 ∈ [-0x1.0f0cf00000000p73 .. 0x1.bc16d60000000p59]
   square ∈ [0x0.0000000000000p0 .. 0x1.fffffc0000020p256]
   square2 ∈ [0x0.0000000000000p0 .. 0x1.fffffe0000000p127]
diff --git a/tests/float/oracle/nonlin.5.res.oracle b/tests/float/oracle/nonlin.5.res.oracle
index 3a7da9b287ed6d48a6065ed1689ff2f9760e1681..a26018dc5a7b1e8f6e79c7f951bc2d4b1e746db0 100644
--- a/tests/float/oracle/nonlin.5.res.oracle
+++ b/tests/float/oracle/nonlin.5.res.oracle
@@ -317,7 +317,7 @@
   v1 ∈ [-0x1.0f0cf00000000p73 .. 0x1.bc16d60000000p59]
   v2 ∈ [-0x1.0f0cf00000000p73 .. 0x1.bc16d60000000p59]
   square ∈ [0x0.0000000000000p0 .. inf] ∪ {NaN}
-  square2 ∈ [-inf .. inf] ∪ {NaN}
+  square2 ∈ [0x0.0000000000000p0 .. inf]
 [eva:final-states] Values at end of function other:
   Frama_C_entropy_source ∈ [--..--]
   i ∈ [-0x1.8efff00000000p1 .. 0x1.8680000000000p1]
diff --git a/tests/value/oracle/nonlin.res.oracle b/tests/value/oracle/nonlin.res.oracle
index ca1b870962dc9a89c3d58e9d29bea23a70cbdfec..1783b2b8ca0f5b2892b7b555733d4c107057dd16 100644
--- a/tests/value/oracle/nonlin.res.oracle
+++ b/tests/value/oracle/nonlin.res.oracle
@@ -198,7 +198,7 @@
   y ∈ [-10..10]
   z ∈ [-10..10]
   norm ∈ [0..200]
-  mult ∈ [-10000..10000]
+  mult ∈ [0..10000]
   zero ∈ [-26..26]
   square ∈ [-48..400]
   square2 ∈ [-48..400]