{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Format numbers for display\n",
    "\n",
    "**The question.** You have a number and need it as a *string* a human will read — with thousands separators, a fixed number of decimals, a percent sign, currency, scientific notation, or padded to line up in a column.\n",
    "\n",
    "The answer is the **format mini-language**, used inside f-strings after a colon: `f'{value:spec}'`. One compact spec controls grouping, precision, sign, width, and notation. Here are the pieces you'll actually use; the full grammar is in the [number formatting reference](https://agilearn.co.uk/guides/numbers-and-maths/reference/number-formatting-reference)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Fixed decimal places — `.Nf`\n",
    "\n",
    "`.2f` means \"fixed-point, two decimals\". It rounds for display and always shows that many places, even trailing zeros."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "print(f'{3.14159:.2f}')        # '3.14'\n",
    "print(f'{2:.2f}')              # '2.00' — trailing zeros kept\n",
    "print(f'{1/3:.4f}')            # '0.3333'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Thousands separators — `,` and `_`\n",
    "\n",
    "A `,` inserts comma thousands separators; `_` uses underscores. Combine with `.2f` by writing the grouping before the precision: `,.2f`."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "print(f'{1234567:,}')          # '1,234,567'\n",
    "print(f'{1234567.5:,.2f}')     # '1,234,567.50'\n",
    "print(f'{1234567:_}')          # '1_234_567'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Percentages — `%`\n",
    "\n",
    "The `%` type multiplies by 100 and appends a percent sign. Set the decimals as usual."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "print(f'{0.1234:.1%}')         # '12.3%'\n",
    "print(f'{0.5:.0%}')            # '50%'\n",
    "print(f'{1/3:.2%}')            # '33.33%'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Scientific and general — `e` and `g`\n",
    "\n",
    "`e` forces scientific notation; `g` (\"general\") picks fixed or scientific automatically and trims trailing zeros, rounding to *significant figures* rather than decimal places."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "print(f'{1234567:.2e}')        # '1.23e+06'\n",
    "print(f'{0.000123:.2e}')       # '1.23e-04'\n",
    "print(f'{1234567:.3g}')        # '1.23e+06'\n",
    "print(f'{0.000123:.3g}')       # '0.000123'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sign control — `+`\n",
    "\n",
    "By default only negatives show a sign. `+` forces a sign on positives too (handy for deltas); a space puts a blank where the `+` would go, so positive and negative line up."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "print(f'{42:+}')               # '+42'\n",
    "print(f'{-42:+}')              # '-42'\n",
    "print(f'{42: }')               # ' 42' — space holds the sign column"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Width, fill, and alignment\n",
    "\n",
    "A number before the type sets a minimum **width**; `<`, `>`, `^` align left, right, centre; a character before the alignment is the **fill**. Numbers right-align by default. This is how you make columns line up."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "for n in [5, 42, 1337]:\n",
    "    print(f'{n:>6}')           # right-aligned in a 6-wide field\n",
    "\n",
    "print(f'{42:08.2f}')           # '00042.00' — zero-padded to width 8\n",
    "print(f'{\"mid\":^9}')           # '   mid   ' — centred"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Other bases — `b`, `o`, `x`\n",
    "\n",
    "For integers, `b`, `o`, and `x` format in binary, octal, and hex. The `#` flag adds the `0b`/`0o`/`0x` prefix."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "print(f'{255:b}')              # '11111111'\n",
    "print(f'{255:x}')              # 'ff'\n",
    "print(f'{255:#x}')             # '0xff' — with prefix\n",
    "print(f'{255:08b}')            # '11111111' padded to 8 bits"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Putting it together\n",
    "\n",
    "Specs compose, in the order *fill/align, sign, #, 0, width, grouping, .precision, type*. A realistic example — a right-aligned, signed, comma-grouped currency figure:"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "value = 1234567.891\n",
    "print(f'£{value:>15,.2f}')     # '£   1,234,567.89'\n",
    "\n",
    "# a small table\n",
    "rows = [('Coffee', 2.5), ('Sandwich', 4.95), ('Cake', 12)]\n",
    "for name, price in rows:\n",
    "    print(f'{name:<10}{price:>8,.2f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Quick reference\n",
    "\n",
    "| Spec | On `1234.5` | Meaning |\n",
    "| --- | --- | --- |\n",
    "| `.2f` | `1234.50` | fixed, 2 decimals |\n",
    "| `,.2f` | `1,234.50` | + thousands separator |\n",
    "| `.1%` | (on `0.1234`) `12.3%` | percent |\n",
    "| `.2e` | `1.23e+03` | scientific |\n",
    "| `.3g` | `1.23e+03` | significant figures |\n",
    "| `>10` | `    1234.5` | right-align, width 10 |\n",
    "| `08.1f` | `001234.5` | zero-pad to width 8 |\n",
    "\n",
    "See the [number formatting reference](https://agilearn.co.uk/guides/numbers-and-maths/reference/number-formatting-reference) for the complete grammar."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}