{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Picking apart a floating point number"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# Never mind the details of this function...\n",
        "\n",
        "def pretty_print_fp(x):\n",
        "    print(\"---------------------------------------------\")\n",
        "    print(\"Floating point structure for %r\" % x)\n",
        "    print(\"---------------------------------------------\")\n",
        "    import struct\n",
        "    s = struct.pack(\"d\", x)\n",
        "\n",
        "    def get_bit(i):\n",
        "        byte_nr, bit_nr = divmod(i, 8)\n",
        "        return int(bool(\n",
        "            s[byte_nr] & (1 << bit_nr)\n",
        "            ))\n",
        "\n",
        "    def get_bits(lsb, count):\n",
        "        return sum(get_bit(i+lsb)*2**i for i in range(count))\n",
        "\n",
        "    # https://en.wikipedia.org/wiki/Double_precision_floating-point_format\n",
        "\n",
        "    print(\"Sign bit (1:negative):\", get_bit(63))\n",
        "    exponent = get_bits(52, 11)\n",
        "    print(\"Stored exponent: %d\" % exponent)\n",
        "    print(\"Exponent (with offset): %d\" % (exponent - 1023))\n",
        "    fraction = get_bits(0, 52)\n",
        "    if exponent != 0:\n",
        "        significand = fraction + 2**52\n",
        "    else:\n",
        "        significand = fraction\n",
        "    print(\"Significand (binary):\", bin(significand)[2:])\n",
        "    print(\"Shifted significand:\", repr(significand / (2**52)))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "---------------------------------------------\n",
            "Floating point structure for 3\n",
            "---------------------------------------------\n",
            "Sign bit (1:negative): 0\n",
            "Stored exponent: 1024\n",
            "Exponent (with offset): 1\n",
            "Significand (binary): 11000000000000000000000000000000000000000000000000000\n",
            "Shifted significand: 1.5\n"
          ]
        }
      ],
      "source": [
        "pretty_print_fp(3)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Things to try:\n",
        "\n",
        "* Twiddle the sign bit\n",
        "* 1,2,4,8\n",
        "* 0.5,0.25\n",
        "* $2^{\\pm 1023}$, $2^{\\pm 1024}$\n",
        "* `float(\"nan\")`"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": true
      },
      "outputs": [],
      "source": []
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.5.0+"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}