Skip to content

Instantly share code, notes, and snippets.

@pepve
Created February 27, 2017 13:19
Show Gist options
  • Save pepve/8b8fb173e52fdaa85e51321bd7c40c24 to your computer and use it in GitHub Desktop.
Save pepve/8b8fb173e52fdaa85e51321bd7c40c24 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import random"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"random.seed(1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's say we have 32 random bits:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"577090037"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r = random.getrandbits(32)\n",
"r"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But we actually need to pick two things from a collection, so we need two numbers, easy:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(45557, 8805)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r1 = r & ((1 << 16) - 1)\n",
"r2 = r >> 16\n",
"(r1, r2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Just some shifting and masking.\n",
"\n",
"But how do we do that for a random number in [0, 100)?"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"72"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"q = random.randint(0, 100)\n",
"q"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Don't know why, but apparently like this:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"(2, 7)"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"q1 = q % 10\n",
"q2 = q // 10\n",
"(q1, q2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here I had my Eureka moment, and I realized that these computations look a lot like radix conversions. So to restate what I said on Signal:\n",
"\n",
"Say you want to \"split up\" number $x \\in [0, n)$ into $k$ \"parts\". Assume $x$ is in radix $\\sqrt[k]{n}$ and compute all the positional values.\n",
"\n",
"(Example for what I mean by positional values: 625 in decimal has 6, 2, and 5. And 5 in binary has 1, 0, and 1.)\n",
"\n",
"We can write a function for that!"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def splitup(k, n, x):\n",
" radix = n ** (1 / k)\n",
" parts = []\n",
" for i in range(k):\n",
" num = x % radix ** (i + 1)\n",
" x -= num\n",
" parts.append(num / radix ** i)\n",
" return parts"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"And use that function for the two earlier examples:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[45557.0, 8805.0]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"splitup(2, 1 << 32, r)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[2.0, 7.0]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"splitup(2, 100, q)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Or for something more complex:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[54.21414069759116, 64.7746922652914, 37.00765694885452, 64.0]"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"splitup(4, 1 << 25, random.getrandbits(25))"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[87.3058979352777,\n",
" 179.12551484100817,\n",
" 341.17462767317403,\n",
" 275.97554923866954,\n",
" 308.5272914689921,\n",
" 208.78397447298113,\n",
" 290.0]"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"splitup(7, 1 << 60, random.getrandbits(60))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Okay, but the last value is always a whole number. I don't understand why. Open question. :-)"
]
}
],
"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.6.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment