codexbinary-expansion-nested-intervals.py
binary-expansion-nested-intervals.py
"""Draw exact dyadic brackets for 2/3; write the PNG in the working directory."""
from fractions import Fraction
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
def main():
value = Fraction(2, 3)
fig, ax = plt.subplots(figsize=(7.8, 3.3), dpi=120, facecolor="white")
fig.subplots_adjust(left=0.22, right=0.97, top=0.83, bottom=0.16)
labels = []
for n in range(7):
scale = 2**n
numerator = (value.numerator * scale) // value.denominator
left = Fraction(numerator, scale)
right = left + Fraction(1, scale)
prefix = format(numerator, f"0{n}b") if n else ""
labels.append(f"n={n} 0.{prefix}")
color = plt.cm.Blues(0.40 + 0.065 * n)
ax.add_patch(
Rectangle(
(float(left), n - 0.22),
float(right - left),
0.44,
facecolor=color,
edgecolor="none",
)
)
ax.plot(float(left), n, "o", ms=4.2, color="#16476b", zorder=4)
ax.plot(
float(right), n, "o", ms=4.2,
markerfacecolor="white", markeredgecolor="#16476b", zorder=4,
)
ax.axvline(float(value), color="#b13737", lw=1.5, ls="--", zorder=5)
ax.text(
float(value), -0.70, r"$x=2/3$",
ha="center", va="center", fontsize=11, color="#a12b2b",
)
ax.set_xlim(-0.015, 1.025)
ax.set_ylim(6.65, -0.45)
ax.set_yticks(range(7), labels, fontfamily="DejaVu Sans Mono", fontsize=9)
ax.set_xticks([0, 0.25, 0.5, 0.75, 1], ["0", "1/4", "1/2", "3/4", "1"])
ax.set_xlabel("Value on the number line", fontsize=10)
ax.tick_params(axis="y", length=0, pad=10)
ax.tick_params(axis="x", labelsize=9)
ax.grid(axis="x", color="#dedede", lw=0.6, zorder=0)
for side in ["top", "right", "left"]:
ax.spines[side].set_visible(False)
ax.spines["bottom"].set_color("#999999")
fig.suptitle("Each binary digit halves the remaining interval", fontsize=13, y=0.97)
fig.text(
0.22, 0.885,
r"After $n$ digits: $s_n\leq x<s_n+2^{-n}$",
fontsize=10,
)
fig.savefig(Path.cwd() / "binary-expansion-nested-intervals.png", facecolor="white")
plt.close(fig)
if __name__ == "__main__":
main()