Zulip Chat Archive

Stream: new members

Topic: Polymorphic Round Function


Colin Jones ⚛️ (Mar 30 2025 at 03:46):

I understand the round function in mathlib requires a LinearOrderedField to work, but is there a way to make it polymorphic.

def rp (x : α) [HSub α α α] := x - round x

Specifically, is there a way to make this evaluate using Float.round when alpha is a Float, but still keep the flexibility of polymorphism?

Derek Rhodes (Mar 30 2025 at 17:00):

Hi, I not an expert in this, but, I wanted to see where things start breaking down.

import Mathlib

variable (α : Type) [LinearOrderedRing α] [FloorRing α]

def rp (x : α) := x - round x

instance : AddMonoid Float where
  add := (· + ·)
  add_assoc a b c := by
    -- IEEE 754 floats are not associative
    sorry

-- the CS stack exchange has a workable example of non-associativity
-- https://cs.stackexchange.com/a/169153

def x : Float := -1e9
def y : Float := 1e9
def z : Float := 1e-9

#eval (x + y) + z  -- result: 1e-09, Lean doesn't show enough precision to see
#eval x + (y + z)  -- result: 0.0

#eval (x + y) + z == x + (y + z)  -- false
#eval (x + y) + z = x + (y + z)   -- failed to synthesize Decidable

Here's a nice paragraph from the Lean language reference

Lean exposes the underlying platform's floating-point values for use in
programming, but they are not encoded in Lean's logic. They are represented
by an opaque type. This means that the kernel is not capable of computing
with or reasoning about floating-point values without additional axioms. A
consequence of this is that equality of floating-point numbers is not
decidable...

I've seen other discussion here on zulip regarding algebra and proofs on IEEE Floats, and they were not heartening.

However, I think it would be really cool to see what people could prove about them. For instance: bounds on error accumulation with sequences of machine instructions. I would imagine that capability would be appreciated in robotics, aerospace, missile defense, machine learning, etc. So, maybe there's already work done? As I said, I'm not an expert but am also interested in the answer to your question.

Eric Wieser (Mar 30 2025 at 18:22):

Regarding docs#Int.floor` etc, I think it would be reasonable to split the data-only parts of docs#FloorRing into a new base typeclass

Colin Jones ⚛️ (Apr 01 2025 at 03:12):

Figured it out:

class HasRound (α : Type) where
  pround : α  α

instance : HasRound Float where
  pround := Float.round

instance [LinearOrderedField α] [FloorRing α] : HasRound α where
  pround := (fun (x : α) => round x)

I didn't want to prove anything on floats; I know they are wacky. I just wanted a function that could do both round functions


Last updated: May 02 2025 at 03:31 UTC