Zulip Chat Archive

Stream: new members

Topic: converting between reals, ENNReals and Nats


Becker A. (Jan 11 2026 at 00:32):

I keep having to close proofs that would be trivial in Nat's but feels non-trivial because some of the numbers involved are Nat literals casted to Reals or ENNReals.

below are just a couple that I can think of atm:

import Mathlib.Analysis.Normed.Group.Basic
import Mathlib.MeasureTheory.MeasurableSpace.Defs
import Mathlib.MeasureTheory.Measure.MeasureSpaceDef
import Mathlib.MeasureTheory.Measure.Typeclasses.Probability
import Mathlib.Probability.Independence.Basic
import Mathlib.Probability.Moments.Basic
import Mathlib.MeasureTheory.Function.L1Space.Integrable
import Mathlib.Data.Finset.Range

open scoped ENNReal


theorem memLp_pow.extracted_1_1
  (n m : )
  (x : )
  : x ^ (OfNat.ofNat 2 * m) = x ^ (2 * m)
  := by
  sorry

theorem moment_2_biased_svar.extracted_1_3
  : (@OfNat.ofNat 0 2 instOfNatAtLeastTwo) * (@OfNat.ofNat 0 2 instOfNatAtLeastTwo)
    = OfNat.ofNat 4
  := by
  sorry

please advise, thanks!

Ilmārs Cīrulis (Jan 11 2026 at 00:58):

import Mathlib.Data.ENNReal.Basic

open scoped ENNReal

theorem memLp_pow.extracted_1_1
    (n m : ) (x : ) : x ^ (OfNat.ofNat 2 * m) = x ^ (2 * m) := by
  rfl

theorem moment_2_biased_svar.extracted_1_3 :
    (@OfNat.ofNat 0 2 instOfNatAtLeastTwo) *
    (@OfNat.ofNat 0 2 instOfNatAtLeastTwo) = OfNat.ofNat 4 := by
  grind

Kevin Buzzard (Jan 11 2026 at 01:06):

I'm surprised you're seeing OfNat.ofNat 2 ever: how did those appear? What was the line you wrote that made them show up?

Becker A. (Jan 11 2026 at 01:12):

@Kevin Buzzard it was this (I feel bad for not reducing but it's not too long):

import Mathlib.Analysis.Normed.Group.Basic
import Mathlib.MeasureTheory.MeasurableSpace.Defs
import Mathlib.MeasureTheory.Measure.MeasureSpaceDef
import Mathlib.MeasureTheory.Measure.Typeclasses.Probability
import Mathlib.Probability.Independence.Basic
import Mathlib.Probability.Moments.Basic
import Mathlib.MeasureTheory.Function.L1Space.Integrable
import Mathlib.Data.Finset.Range

open Finset MeasureTheory ProbabilityTheory NNReal
open scoped ENNReal


theorem memLp_pow
  (Ω : Type u_1) [MeasurableSpace Ω]
  (n m : )
  (f : Ω  )
  (P : Measure Ω) [IsProbabilityMeasure P]
  (hFMemLp : MemLp f ((2 * m) * n) P)
  : MemLp (f ^ (2 * m)) n P
  := by
  have hFFun : f ^ (2 * m) = fun ω => f ω ^ (2 * m) := by rfl
  conv in (f ^ (2 * m)) => rw [hFFun]
  conv in (_ ^ (2 * m)) => rw [pow_mul, <- sq_abs, <- Real.norm_eq_abs, <- pow_mul]
  have h1 :=  MemLp.norm_rpow_div (f := f) (q := (2 * m)) (hFMemLp)
  have h2 :  x : , x ^ (@OfNat.ofNat  2 instOfNatAtLeastTwo * m) = x ^ (2 * m) := by
    sorry
  conv at h1 in (_ ^ (2 * _).toReal) =>
    rw [ENNReal.toReal_mul, ENNReal.toReal_ofNat, ENNReal.toReal_natCast, h2]
  conv at h1 in (_ / _) => rw [mul_comm, <- mul_div]
  sorry

Becker A. (Jan 11 2026 at 01:14):

it showed up around the sorry's; specifically I'm trying to use MemLp.norm_rpow_div and it involves doing division of Nat's casted to Reals and ENNReals (I may have written the original problem wrong, but this is the source so this should be representative of what I actually need)

Kevin Buzzard (Jan 11 2026 at 01:15):

Wait, so the horrible ofNats (which a user should never see) are literally introduced by you in h2? What is the role of h2 here? You never use it?

Becker A. (Jan 11 2026 at 01:16):

I use it on the third to last line... I just copied my tactic state into a have so I could solve it in an isolated context

Becker A. (Jan 11 2026 at 01:17):

the tactic state showed ofNat, I didn't intentionally reach for it it's just what I was presented to solve by mathlib

Kevin Buzzard (Jan 11 2026 at 01:21):

Right, so what I am asking you is what you typed to make the ofNat appear, because it wasn't in your goal to start with, and it was in your goal at some point, so something you did made it appear.

Kevin Buzzard (Jan 11 2026 at 01:22):

theorem memLp_pow
    (Ω : Type*) [MeasurableSpace Ω]
    (n m : )
    (f : Ω  )
    (P : Measure Ω) [IsProbabilityMeasure P]
    (hFMemLp : MemLp f ((2 * m) * n) P) :
    MemLp (f ^ (2 * m)) n P := by
  have hFFun : f ^ (2 * m) = fun ω => f ω ^ (2 * m) := by rfl
  conv in (f ^ (2 * m)) => rw [hFFun]
  conv in (_ ^ (2 * m)) => rw [pow_mul, <- sq_abs, <- Real.norm_eq_abs, <- pow_mul]
  have h1 :=  MemLp.norm_rpow_div (f := f) (q := (2 * m)) (hFMemLp)
  -- I didn't read any of the above but here's my instinct on what to do next
  convert h1
  · rw [ Real.rpow_natCast]
    congr
    norm_num
  · -- goal looks problematic because you've divided by something which might be zero
    sorry

Becker A. (Jan 11 2026 at 01:22):

Kevin Buzzard said:

Right, so what I am asking you is what you typed to make the ofNat appear, because it wasn't in your goal to start with, and it was in your goal at some point, so something you did made it appear.

I hovered over the infoview tactic state to know what to copy into h2, and the infoview gave me ofNat

Kevin Buzzard (Jan 11 2026 at 01:24):

Let's talk about h1 before h2: you have divided by 2m. Do you know that 2m isn't zero?

Becker A. (Jan 11 2026 at 01:24):

yeah; I can switch that to (2 * (m + 1)) and it'll still be useful

Kevin Buzzard (Jan 11 2026 at 01:25):

You shouldn't be using lots of lemmas: there are tools like norm_num which should be doing all the work for you. See for example how I solved the first goal.

Becker A. (Jan 11 2026 at 01:30):

okay, is there any way I would I know about stuff like norm_num on my own? it seems like most solutions to my questions use tactics that I just don't know exist (e.g., grind or norm_num), so that alone might fix a lot of my problems

Kevin Buzzard (Jan 11 2026 at 01:31):

  -- I didn't read any of the above but here's my instinct on what to do next
  convert h1 -- because modulo stupid issues with nat v ennreal the goal is solved by h1
  -- now pick up the pieces
  · rw [ Real.rpow_natCast] -- change x^natural to x^(coerced to real)
    simp
  · norm_cast
    rw [ENNReal.eq_div_iff] -- clear denominators
    · norm_cast
    · sorry -- impossible
    · exact?

Kevin Buzzard (Jan 11 2026 at 01:33):

I found Real.rpow_natCast by writing the lemma I wanted

example (x : ) (n : ) : x ^ (n : ) = x ^ n := by exact?

and using exact?, and similarly I found the last lemma in my proof using exact? (and left the exact? there). norm_num and norm_cast are useful tactics in this situation; there are only a small number of useful tactics and it's just worth picking them up and then hovering over them to read their docstrings. push_cast is another one. I found ENNReal.eq_div_iff by guessing the name but usually I find lemmas using exact? -- there are hundreds of thousands of lemmas so it's hopeless learning them all, but learning the relevant tactics for your area is definitely a doable thing.

Becker A. (Jan 11 2026 at 01:33):

wait do the dots automatically enter you into generated cases? I thought you had to do case NAME => every time

Kevin Buzzard (Jan 11 2026 at 01:35):

After the rewrite I had three goals (because the rewrite only worked under some assumptions) so I just wrote \. sorry and then cut and pasted it three times

Becker A. (Jan 11 2026 at 01:42):

yeahhh I kept trying to use div_eq_iff instead of ENNReal.eq_div_iff and didn't know why it didn't work :\ also I replaced it with exact? and that failed, then I tried rw? and that was overwhelming.

-> searching lemmas is hard T-T

Becker A. (Jan 11 2026 at 01:43):

ohhh you set aside the lemma and then use exact?, got it

Kevin Buzzard (Jan 11 2026 at 01:47):

yeah there are lots of ways to search, there is loogle and there are semantic search engines like https://leandex.projectnumina.ai/ but sometimes when you know the lemma will be there and you're pretty sure you know the exact form, exact? is the easiest approach (and works without internet).

div_eq_iff, if you #check it, you'll see it works for GroupWithZeros, so it would work for R\mathbb{R} and R0\mathbb{R}_{\geq0} (both of which are multiplicative groups if you remove the zero) but not for ENNReal (which isn't, because infinity is problematic). In situations like this it's often best to search for the analogous lemma but in the relevant namespace, because then you'll get a version which works for the bespoke type possibly with extra assumptions (e.g. I had to not only prove that something wasn't 0, but also that it wasn't infinity, here).

Becker A. (Jan 11 2026 at 01:49):

so in general: instead of going to the infoview and copying stuff like ofNat, it's better to use expressions with coercion like 2 : Real?

Becker A. (Jan 11 2026 at 02:05):

also small style question: is there a well-accepted preference when specifying nonzero nats to use
(n : Nat) (hn : n ≠ 0) : n ...
or
(n : Nat) : (n + 1) ...?

i.e., provide an explicit proof of non-zero, or just use (n + 1) instead?

Aaron Liu (Jan 11 2026 at 02:12):

If you have n - 1 in the statement for n nonzero then usually it's a good idea to replace n with n + 1


Last updated: Feb 28 2026 at 14:05 UTC