import math


def range_around_float(x, i):
  """
  Returns a pair (min, max) of floats such that the half-open interval [min,max) contains 2^i
  representable floats, with x among them.
  """
  # This is hard to explain (so easy for this to be wrong). m is in [0.5, 1), with 52 bits of
  # precision (for 64-bit double-precision floats, as Python uses). We are trying to zero-out the
  # last i bits of the precision. So we shift the mantissa left by (52-i) bits, round down
  # (zeroing out remaining i bits), then shift back.
  m, e = math.frexp(x)
  mf = math.floor(math.ldexp(m, 53 - i))
  exp = e + i - 53
  return (math.ldexp(mf, exp), math.ldexp(mf + 1, exp))