Zulip Chat Archive

Stream: Is there code for X?

Topic: casting natural division to rat


Jakob von Raumer (Feb 26 2024 at 10:46):

Do we have a lemma for this or a lemma that would make such a lemma superfluous?

theorem Rat.nat_cast_div_eq {a b : } :
    (a / b) = (a : ) / (b : ) - (a % b : ) / (b : ) := by
  by_cases hb : b = 0
  · subst hb; simp
  · rw [Nat.div_eq_sub_mod_div, Nat.cast_div (Nat.dvd_sub_mod a) (Nat.cast_ne_zero.mpr hb),
      Nat.cast_sub (Nat.mod_le a b), sub_div]

Edward van de Meent (Feb 26 2024 at 10:49):

why are you assuming z : ℚ?

Jakob von Raumer (Feb 26 2024 at 10:50):

Fixed :grinning_face_with_smiling_eyes:

Richard Copley (Feb 26 2024 at 11:40):

That proof doesn't work (because the statement isn't true) if you import Mathlib. Perhaps this has something to do with Mathlib redefining /.

import Mathlib

example {a b : } :
    (a / b) = (a : ) / (b : ) - (a % b : ) / (b : ) 
      ((a / b : ) : ) = (a : ) / (b : ) := by
  by_cases hb : b = 0
  . subst hb ; simp
  rw [EuclideanDomain.mod_eq_sub_mul_div, div_sub_div_same, sub_sub_self, mul_div,
    mul_div_right_comm, mul_div_right_comm,  Rat.coe_nat_div_self,
    Nat.div_self (Nat.pos_of_ne_zero hb), div_mul_comm, show ((1 : ) : ) = (1 : ) from rfl,
    mul_one]

Did you have a set of imports where it does work?

Jakob von Raumer (Feb 26 2024 at 12:08):

This is a snippet that works stand-alone for me:

import Mathlib.Data.Rat.Basic
import Mathlib.Data.Nat.Order.Basic
import Mathlib.Data.Nat.Cast.Field
import Mathlib.Algebra.CharZero.Defs
import Mathlib.Data.ZMod.Basic

theorem Rat.nat_cast_div_eq {a b : } :
    (a / b) = (a : ) / (b : ) - (a % b : ) / (b : ) := by
  by_cases hb : b = 0
  · subst hb; simp
  · rw [Nat.div_eq_sub_mod_div, Nat.cast_div (Nat.dvd_sub_mod a) (Nat.cast_ne_zero.mpr hb),
      Nat.cast_sub (Nat.mod_le a b), sub_div]

Richard Copley (Feb 26 2024 at 12:37):

Here's what changed, for what it's worth:

import Mathlib.Data.Rat.Basic

def xxx (a b : ) := (a % b : )

set_option pp.coercions false in
#print xxx
-- def xxx : ℕ → ℕ → ℚ :=
-- fun a b => Nat.cast (a % b)
import Mathlib.Data.Rat.Basic
import Mathlib.Algebra.EuclideanDomain.Instances

def xxx (a b : ) := (a % b : )

set_option pp.coercions false in
#print xxx
-- def xxx : ℕ → ℕ → ℚ :=
-- fun a b => Nat.cast a % Nat.cast b

Jakob von Raumer (Feb 26 2024 at 12:41):

Yes, writing ↑(a % b) instead, solves the disambiguity.

Richard Copley (Feb 26 2024 at 13:04):

@Kevin Buzzard, I was shocked too, but I think I have come to terms with it.
We want for example (a / b : ℝ) to mean ↑a / ↑b, not ↑(a / b).
And we want (a % b : ℚ) to mean something, but ↑a % ↑b doesn't make sense until gets a Mod instance, so ↑(a % b) it is.

Richard Copley (Feb 26 2024 at 13:05):

And @Jakob von Raumer's is the right solution, not a workaround

Kevin Buzzard (Feb 26 2024 at 13:08):

Since we switched from lean 3 to lean 4 I've never had any idea what we want (a / b : \R) to mean.

Ruben Van de Velde (Feb 26 2024 at 13:13):

Neither does lean!

Eric Rodriguez (Feb 26 2024 at 13:39):

We really don't want fields getting this % instance but it's not really possible (I don't think) to turn it off, right?

Eric Rodriguez (Feb 26 2024 at 13:45):

Maybe we could make a linter for % on Q


Last updated: May 02 2025 at 03:31 UTC