Zulip Chat Archive

Stream: lean4

Topic: ToExpr Float


Tomas Skrivan (Dec 15 2025 at 14:28):

Are there somewhere ToExpr Float and ToExpr Float32 instances? Or has anyone done this before? Or what would be the best approach to implement it? Should I just manually hack out mantisa and exponent and then build expresion with ofScientific?

Robin Arnez (Dec 15 2025 at 16:47):

Here's a prototype (which is probably pretty slow but whatever):

import Mathlib

open Lean Qq

def Float.toScientificParts (f : Float) : Bool × Nat × Int :=
  let bits := f.toBits
  let expPart : UInt64 := (bits >>> 52) &&& 0x7ff
  let mantPart : UInt64 := bits &&& ((1 : UInt64) <<< 52 - 1)
  if expPart = 0  mantPart = 0 then
    (bits >>> 63 != 0, 0, -1)
  else
    let exp : Int := (if expPart = 0 then (-0x3fe : Int) else expPart.toNat - 0x3ff) - 52
    let mant : Nat := if expPart = 0 then mantPart.toNat else mantPart.toNat + 1 <<< 52
    let qval : Rat := mant * 2^exp
    let log10 : Int := Int.log 10 qval
    let value : Nat := qval * 10^(17 - log10)⌋₊
    let (value, log10) := removeUnnecessaryDigits f.abs value (log10 - 17)
    (bits >>> 63 != 0, value, log10)
where
  removeUnnecessaryDigits (f : Float) (mant : Nat) (exp : Int) : Nat × Int :=
    if mant  10  exp  -1  Float.ofScientific ((mant + 5) / 10) (exp < 0) (exp + 1).natAbs == f then
      removeUnnecessaryDigits f ((mant + 5) / 10) (exp + 1)
    else
      (mant, exp)

instance : ToExpr Float where
  toExpr x :=
    if x.isFinite then
      let (isNeg, mant, exp) := Float.toScientificParts x
      let mantE : Q(Nat) := mkRawNatLit mant
      let esign : Q(Bool) := if exp < 0 then q(true) else q(false)
      let expE : Q(Nat) := mkRawNatLit exp.natAbs
      let fval : Q(Float) := q(OfScientific.ofScientific $mantE $esign $expE)
      if isNeg then q(-$fval) else fval
    else if x.isNaN then
      q(Float.nan)
    else if 0 < x then
      q(Float.inf)
    else
      q(-Float.inf)
  toTypeExpr := mkConst ``Float

/-- info: 0.30000000000000004 -/
#guard_msgs in
#eval 0.1 + 0.2

Tomas Skrivan (Dec 16 2025 at 10:41):

Nice! works pretty well!


Last updated: Dec 20 2025 at 21:32 UTC