diff --git a/CHANGELOG.md b/CHANGELOG.md
index 81d013d3d8aa4ee496a8c14e88cee5b753dc386d..e5362c59b4fd8cd2eb6446b5f2c3876e113ac5d3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,8 @@ API-breaking change is listed.
 
 - Rename `dom_map filter` → `dom_filter`, `dom_map_filter_L` → `dom_filter_L`,
   and `dom_map_filter_subseteq` → `dom_filter_subseteq` for consistency's sake.
+- Add `max` and `min` operations for `Qp`.
+- Add additional lemmas for `Qp`.
 
 ## std++ 1.4.0 (released 2020-07-15)
 
diff --git a/theories/numbers.v b/theories/numbers.v
index 932d4a7f69a4b98165659563a9fc6ccc6a4ca355..5df2de4fdc829bfe41f67fc7fc4ca5cde5bcef63 100644
--- a/theories/numbers.v
+++ b/theories/numbers.v
@@ -664,6 +664,9 @@ Delimit Scope Qp_scope with Qp.
 Bind Scope Qp_scope with Qp.
 Arguments Qp_car _%Qp : assert.
 
+Local Open Scope Qc_scope.
+Local Open Scope Qp_scope.
+
 Definition Qp_one : Qp := mk_Qp 1 eq_refl.
 Program Definition Qp_plus (x y : Qp) : Qp := mk_Qp (x + y) _.
 Next Obligation. by intros x y; apply Qcplus_pos_pos. Qed.
@@ -681,10 +684,15 @@ Next Obligation.
     <-Qcmult_assoc, Qcmult_inv_l, Qcmult_1_r.
 Qed.
 
+Definition Qp_max (q p : Qp) : Qp := if decide (q ≤ p) then p else q.
+Definition Qp_min (q p : Qp) : Qp := if decide (q ≤ p) then q else p.
+
 Infix "+" := Qp_plus : Qp_scope.
 Infix "-" := Qp_minus : Qp_scope.
 Infix "*" := Qp_mult : Qp_scope.
 Infix "/" := Qp_div : Qp_scope.
+Infix "`max`" := Qp_max (at level 35) : Qp_scope.
+Infix "`min`" := Qp_min (at level 35) : Qp_scope.
 Notation "1" := Qp_one : Qp_scope.
 Notation "2" := (1 + 1)%Qp : Qp_scope.
 Notation "3" := (1 + 2)%Qp : Qp_scope.
@@ -825,6 +833,123 @@ Qed.
 Lemma Qp_ge_0 (q: Qp): (0 ≤ q)%Qc.
 Proof. apply Qclt_le_weak, Qp_prf. Qed.
 
+Lemma Qp_le_plus_r (q p : Qp) : p ≤ q + p.
+Proof.
+  apply (Qcplus_le_mono_l _ _ (-p)%Qc). rewrite Qcplus_comm, Qcplus_opp_r.
+  rewrite Qcplus_comm, <- Qcplus_assoc, Qcplus_opp_r, Qcplus_0_r. apply Qp_ge_0.
+Qed.
+
+Lemma Qp_le_plus_l (q p : Qp) : q ≤ q + p.
+Proof. rewrite Qcplus_comm. apply Qp_le_plus_r. Qed.
+
+Lemma Qp_le_plus_compat (q p n m : Qp) : q ≤ n → p ≤ m → q + p ≤ n + m.
+Proof.
+  intros. eapply Qcle_trans. by apply Qcplus_le_mono_l. by apply Qcplus_le_mono_r.
+Qed.
+
+Lemma Qp_plus_weak_r (q p o : Qp) : q + p ≤ o → q ≤ o.
+Proof. intros Le. eapply Qcle_trans. apply Qp_le_plus_l. apply Le. Qed.
+
+Lemma Qp_plus_weak_l (q p o : Qp) : q + p ≤ o → p ≤ o.
+Proof. rewrite Qcplus_comm. apply Qp_plus_weak_r. Qed.
+
+Lemma Qp_plus_weak_2_r (q p o : Qp) : q ≤ o → q ≤ p + o.
+Proof. intros Le. eapply Qcle_trans; [apply Le| apply Qp_le_plus_r]. Qed.
+
+Lemma Qp_plus_weak_2_l (q p o : Qp) : q ≤ p → q ≤ p + o.
+Proof. rewrite Qcplus_comm. apply Qp_plus_weak_2_r. Qed.
+
+Lemma Qp_max_spec (q p : Qp) : (q < p ∧ q `max` p = p) ∨ (p ≤ q ∧ q `max` p = q).
+Proof.
+  unfold Qp_max. destruct (decide (q ≤ p)).
+  - destruct (Qcle_lt_or_eq _ _ q0) as [? | ->%Qp_eq]; [left|right]; done.
+  - right. split; [|done]. by apply Qclt_le_weak, Qcnot_le_lt.
+Qed.
+
+Lemma Qp_max_spec_le (q p : Qp) : (q ≤ p ∧ q `max` p = p) ∨ (p ≤ q ∧ q `max` p = q).
+Proof. destruct (Qp_max_spec q p) as [[?%Qclt_le_weak?]|]; [left|right]; done. Qed.
+
+Instance Qc_max_assoc : Assoc (=) Qp_max.
+Proof.
+  intros q p o. unfold Qp_max. destruct (decide (q ≤ p)), (decide (p ≤ o));
+    eauto using decide_True, Qcle_trans.
+  rewrite decide_False by done.
+  by rewrite decide_False by (eapply Qclt_not_le, Qclt_trans; by apply Qclt_nge).
+Qed.
+Instance Qc_max_comm : Comm (=) Qp_max.
+Proof.
+  intros q p. apply Qp_eq.
+  destruct (Qp_max_spec_le q p) as [[?->]|[?->]], (Qp_max_spec_le p q) as [[?->]|[?->]];
+    eauto using Qcle_antisym.
+Qed.
+
+Lemma Qp_max_id q : q `max` q = q.
+Proof. by destruct (Qp_max_spec q q) as [[_->]|[_->]]. Qed.
+
+Lemma Qc_le_max_l (q p : Qp) : q ≤ q `max` p.
+Proof. unfold Qp_max. by destruct (decide (q ≤ p)). Qed.
+
+Lemma Qc_le_max_r (q p : Qp) : p ≤ q `max` p.
+Proof. rewrite (comm _ q). apply Qc_le_max_l. Qed.
+
+Lemma Qp_max_plus (q p : Qp) : q `max` p ≤ q + p.
+Proof.
+  unfold Qp_max. destruct (decide (q ≤ p)). apply Qp_le_plus_r. apply Qp_le_plus_l.
+Qed.
+
+Lemma Qp_max_lub_l (q p o : Qp) : q `max` p ≤ o → q ≤ o.
+Proof.
+  unfold Qp_max. destruct (decide (q ≤ p)); [by apply Qcle_trans | done].
+Qed.
+
+Lemma Qp_max_lub_r (q p o : Qp) : q `max` p ≤ o → p ≤ o.
+Proof. rewrite (comm _ q). apply Qp_max_lub_l. Qed.
+
+Lemma Qp_min_spec (q p : Qp) : (q < p ∧ q `min` p = q) ∨ (p ≤ q ∧ q `min` p = p).
+Proof.
+  unfold Qp_min. destruct (decide (q ≤ p)).
+  - destruct (Qcle_lt_or_eq _ _ q0) as [?| ->%Qp_eq]; [left|right]; done.
+  - right. split; [|done]. by apply Qclt_le_weak, Qcnot_le_lt.
+Qed.
+
+Lemma Qp_min_spec_le (q p : Qp) : (q ≤ p ∧ q `min` p = q) ∨ (p ≤ q ∧ q `min` p = p).
+Proof. destruct (Qp_min_spec q p) as [[?%Qclt_le_weak?]|]; [left|right]; done. Qed.
+
+Instance Qc_min_assoc : Assoc (=) Qp_min.
+Proof.
+  intros q p o. unfold Qp_min.
+  destruct (decide (q ≤ p)), (decide (p ≤ o)); eauto using decide_False.
+  - rewrite decide_True by done. by rewrite decide_True by (eapply Qcle_trans; done).
+  - by rewrite (decide_False _ _) by (eapply Qclt_not_le, Qclt_trans; by apply Qclt_nge).
+Qed.
+Instance Qc_min_comm : Comm (=) Qp_min.
+Proof.
+  intros q p. apply Qp_eq.
+  destruct (Qp_min_spec_le q p) as [[?->]|[?->]], (Qp_min_spec_le p q) as [[? ->]|[? ->]];
+    eauto using Qcle_antisym.
+Qed.
+
+Lemma Qp_min_id (q : Qp) : q `min` q = q.
+Proof. by destruct (Qp_min_spec q q) as [[_->]|[_->]]. Qed.
+
+Lemma Qp_le_min_r (q p : Qp) : q `min` p ≤ p.
+Proof. by destruct (Qp_min_spec_le q p) as [[?->]|[?->]]. Qed.
+
+Lemma Qp_le_min_l (p q : Qp) : p `min` q ≤ p.
+Proof. rewrite (comm _ p). apply Qp_le_min_r. Qed.
+
+Lemma Qp_min_l_iff (q p : Qp) : q `min` p = q ↔ q ≤ p.
+Proof.
+  destruct (Qp_min_spec_le q p) as [[?->]|[?->]]; [done|].
+  split; [by intros ->|]. intros. by apply Qp_eq, Qcle_antisym.
+Qed.
+
+Lemma Qp_min_r_iff (q p : Qp) : q `min` p = p ↔ p ≤ q.
+Proof. rewrite (comm _ q). apply Qp_min_l_iff. Qed.
+
+Local Close Scope Qp_scope.
+Local Close Scope Qc_scope.
+
 (** * Helper for working with accessing lists with wrap-around
     See also [rotate] and [rotate_take] in [list.v] *)
 (** [rotate_nat_add base offset len] computes [(base + offset) `mod`