Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] committed Oct 12, 2023
1 parent 7f7cc8c commit 5c22176
Show file tree
Hide file tree
Showing 88 changed files with 582 additions and 82 deletions.
4 changes: 2 additions & 2 deletions 404.html

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion _next/data/RALCedqTr8WnZdwXBOCc8/index.json

This file was deleted.

1 change: 0 additions & 1 deletion _next/data/RALCedqTr8WnZdwXBOCc8/posts.json

This file was deleted.

1 change: 0 additions & 1 deletion _next/data/RALCedqTr8WnZdwXBOCc8/tags.json

This file was deleted.

1 change: 0 additions & 1 deletion _next/data/RALCedqTr8WnZdwXBOCc8/tags/typescript.json

This file was deleted.

1 change: 1 addition & 0 deletions _next/data/YK9qWzohV16kOX2X7D8V4/index.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions _next/data/YK9qWzohV16kOX2X7D8V4/posts.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"pageProps":{"article":{"title":"0xffffffffffffffffn: uint64 hack to decrement by one using addition","layout":"posts","slug":"0xffffffffffffffffn-uint64-hack-to-decrement-by-one-using-addition","draft":false,"frontMatter":{"title":"0xffffffffffffffffn: uint64 hack to decrement by one using addition","publishedDate":"2023-10-12T10:15:02Z","tags":["Deno","Deno KV","TypeScript","JavaScript","Binary Arithmetic"],"description":"","disableComments":false},"rawContent":"\n## Introduction\n\nIn the world of software development, there are often clever tricks and hacks that developers use to solve specific problems. One such trick involves using `uint64` (unsigned 64-bit integer) arithmetic to subtract 1 from a number without actually using subtraction. This might sound confusing at first, but with a simple analogy and some examples, it becomes clear!\n\n## The Toy Cash Register Analogy\n\nImagine a child's toy cash register that can only count up to `9`. When it reaches `9`, and you try adding `1` more, it wraps around and returns to `0`. Now, if this toy didn't have a subtraction button, how could you subtract `1` from any number? The trick is to add `9`! When you add `9`, you essentially go full circle and land `1` number behind where you started.\n\n## The Technical Explanation\n\nIn binary arithmetic, numbers are represented using bits. A `uint64` number uses 64 bits. When you add two numbers and the result is too big to fit in 64 bits, it wraps around, similar to our toy cash register.\n\nThe magic number `0xffffffffffffffffn` (which represents all `1`s in binary for a 64-bit number) acts like the number `9` in our analogy. When you add this number to any `uint64`, it's equivalent to subtracting `1`.\n\n| Bit Position: | 63-56 | 55-48 | 47-40 | 39-32 | 31-24 | 23-16 | 15-8 | 7-0 |\n| -------------------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |\n| Previous Number: 3 | 00000000 | 00000000 | 00000000 | 00000000 | 00000000 | 00000000 | 00000000 | 00000011 |\n| Magic Number to add: | 11111111 | 11111111 | 11111111 | 11111111 | 11111111 | 11111111 | 11111111 | 11111111 |\n| Result: 2 | 00000000 | 00000000 | 00000000 | 00000000 | 00000000 | 00000000 | 00000000 | 00000010 |\n\n### Example Code\n\n```javascript\n// Convention for BigInts is to add an \"n\" at the end.\nconst previousNumber = 3n;\n\n// Hexadecimal representation of 64-bit magic number.\nconst magicNumber = 0xffffffffffffffffn;\n\n// Convert to 64-bit unsigned integer.\nconst result = BigInt.asUintN(64, previousNumber + magicNumber);\n\nconsole.log(result); // This will be 2n.\n```\n\n## Why is this Useful?\n\nIn the realm of programming, there are instances where certain operations, like subtraction, might be restricted due to system constraints. This \"magic number\" trick offers a clever workaround for such situations.\n\nTake, for example, [Deno KV](https://deno.com/kv). This key-value storage system in Deno provides an atomic [sum](https://docs.deno.com/kv/manual/operations#sum) operation, allowing you to add two [`Deno.KvU64`](https://deno.land/[email protected]?s=Deno.KvU64&unstable=) values. This is particularly handy for incrementing numeric counters in an [ACID-compliant way](https://en.wikipedia.org/wiki/ACID). However, there's a catch: you can't directly decrement a value using this method since `Deno.KvU64` requires a positive number in the construction.\n\nHere's how you'd typically increment a counter:\n\n```typescript\nawait kv\n .atomic()\n .mutate({\n type: 'sum',\n key: ['users_count'],\n value: new Deno.KvU64(1n)\n })\n .commit();\n```\n\nBut what if you wanted to decrease this counter? Enter our magic number trick. By using the magic number `0xffffffffffffffffn`, you can effectively subtract from the counter:\n\n```typescript\nawait kv\n .atomic()\n .mutate({\n type: 'sum',\n key: ['users_count'],\n value: new Deno.KvU64(0xffffffffffffffffn)\n })\n .commit();\n```\n\nIn essence, this approach leverages the properties of binary arithmetic to bypass system constraints. Pretty cool, right?\n\n## Conclusion\n\nUnderstanding the underlying principles of binary arithmetic can open the door to many clever tricks in programming. The `uint64` subtraction trick is just one example. Hopefully, you can find efficient solutions to complex problems by understanding and applying these concepts to your following projects.\n","excerpt":"\n## Introduction\n\nIn the world of software development, there are often clever tricks and hacks that developers use to solve specific problems. One such trick involves using `uint64` (unsigned 64-bit integer) arithmetic to subtract 1 from a number without actually using subtraction. This might sound...","serializedContent":{"compiledSource":"var u=Object.defineProperty,m=Object.defineProperties;var c=Object.getOwnPropertyDescriptors;var r=Object.getOwnPropertySymbols;var o=Object.prototype.hasOwnProperty,l=Object.prototype.propertyIsEnumerable;var p=(t,n,a)=>n in t?u(t,n,{enumerable:!0,configurable:!0,writable:!0,value:a}):t[n]=a,e=(t,n)=>{for(var a in n||(n={}))o.call(n,a)&&p(t,a,n[a]);if(r)for(var a of r(n))l.call(n,a)&&p(t,a,n[a]);return t},d=(t,n)=>m(t,c(n));var s=(t,n)=>{var a={};for(var i in t)o.call(t,i)&&n.indexOf(i)<0&&(a[i]=t[i]);if(t!=null&&r)for(var i of r(t))n.indexOf(i)<0&&l.call(t,i)&&(a[i]=t[i]);return a};const layoutProps={},MDXLayout=\"wrapper\";function MDXContent(a){var i=a,{components:t}=i,n=s(i,[\"components\"]);return mdx(MDXLayout,d(e(e({},layoutProps),n),{components:t,mdxType:\"MDXLayout\"}),mdx(\"h2\",e({},{id:\"introduction\"}),\"Introduction\"),mdx(\"p\",null,\"In the world of software development, there are often clever tricks and hacks that developers use to solve specific problems. One such trick involves using \",mdx(\"inlineCode\",{parentName:\"p\"},\"uint64\"),\" (unsigned 64-bit integer) arithmetic to subtract 1 from a number without actually using subtraction. This might sound confusing at first, but with a simple analogy and some examples, it becomes clear!\"),mdx(\"h2\",e({},{id:\"the-toy-cash-register-analogy\"}),\"The Toy Cash Register Analogy\"),mdx(\"p\",null,\"Imagine a child's toy cash register that can only count up to \",mdx(\"inlineCode\",{parentName:\"p\"},\"9\"),\". When it reaches \",mdx(\"inlineCode\",{parentName:\"p\"},\"9\"),\", and you try adding \",mdx(\"inlineCode\",{parentName:\"p\"},\"1\"),\" more, it wraps around and returns to \",mdx(\"inlineCode\",{parentName:\"p\"},\"0\"),\". Now, if this toy didn't have a subtraction button, how could you subtract \",mdx(\"inlineCode\",{parentName:\"p\"},\"1\"),\" from any number? The trick is to add \",mdx(\"inlineCode\",{parentName:\"p\"},\"9\"),\"! When you add \",mdx(\"inlineCode\",{parentName:\"p\"},\"9\"),\", you essentially go full circle and land \",mdx(\"inlineCode\",{parentName:\"p\"},\"1\"),\" number behind where you started.\"),mdx(\"h2\",e({},{id:\"the-technical-explanation\"}),\"The Technical Explanation\"),mdx(\"p\",null,\"In binary arithmetic, numbers are represented using bits. A \",mdx(\"inlineCode\",{parentName:\"p\"},\"uint64\"),\" number uses 64 bits. When you add two numbers and the result is too big to fit in 64 bits, it wraps around, similar to our toy cash register.\"),mdx(\"p\",null,\"The magic number \",mdx(\"inlineCode\",{parentName:\"p\"},\"0xffffffffffffffffn\"),\" (which represents all \",mdx(\"inlineCode\",{parentName:\"p\"},\"1\"),\"s in binary for a 64-bit number) acts like the number \",mdx(\"inlineCode\",{parentName:\"p\"},\"9\"),\" in our analogy. When you add this number to any \",mdx(\"inlineCode\",{parentName:\"p\"},\"uint64\"),\", it's equivalent to subtracting \",mdx(\"inlineCode\",{parentName:\"p\"},\"1\"),\".\"),mdx(\"table\",null,mdx(\"thead\",{parentName:\"table\"},mdx(\"tr\",{parentName:\"thead\"},mdx(\"th\",e({parentName:\"tr\"},{align:null}),\"Bit Position:\"),mdx(\"th\",e({parentName:\"tr\"},{align:null}),\"63-56\"),mdx(\"th\",e({parentName:\"tr\"},{align:null}),\"55-48\"),mdx(\"th\",e({parentName:\"tr\"},{align:null}),\"47-40\"),mdx(\"th\",e({parentName:\"tr\"},{align:null}),\"39-32\"),mdx(\"th\",e({parentName:\"tr\"},{align:null}),\"31-24\"),mdx(\"th\",e({parentName:\"tr\"},{align:null}),\"23-16\"),mdx(\"th\",e({parentName:\"tr\"},{align:null}),\"15-8\"),mdx(\"th\",e({parentName:\"tr\"},{align:null}),\"7-0\"))),mdx(\"tbody\",{parentName:\"table\"},mdx(\"tr\",{parentName:\"tbody\"},mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"Previous Number: 3\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000011\")),mdx(\"tr\",{parentName:\"tbody\"},mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"Magic Number to add:\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"11111111\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"11111111\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"11111111\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"11111111\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"11111111\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"11111111\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"11111111\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"11111111\")),mdx(\"tr\",{parentName:\"tbody\"},mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"Result: 2\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000000\"),mdx(\"td\",e({parentName:\"tr\"},{align:null}),\"00000010\")))),mdx(\"h3\",e({},{id:\"example-code\"}),\"Example Code\"),mdx(\"pre\",null,mdx(\"code\",e({parentName:\"pre\"},{className:\"language-javascript\"}),`// Convention for BigInts is to add an \"n\" at the end.\nconst previousNumber = 3n;\n\n// Hexadecimal representation of 64-bit magic number.\nconst magicNumber = 0xffffffffffffffffn;\n\n// Convert to 64-bit unsigned integer.\nconst result = BigInt.asUintN(64, previousNumber + magicNumber);\n\nconsole.log(result); // This will be 2n.\n`)),mdx(\"h2\",e({},{id:\"why-is-this-useful\"}),\"Why is this Useful?\"),mdx(\"p\",null,'In the realm of programming, there are instances where certain operations, like subtraction, might be restricted due to system constraints. This \"magic number\" trick offers a clever workaround for such situations.'),mdx(\"p\",null,\"Take, for example, \",mdx(\"a\",e({parentName:\"p\"},{href:\"https://deno.com/kv\"}),\"Deno KV\"),\". This key-value storage system in Deno provides an atomic \",mdx(\"a\",e({parentName:\"p\"},{href:\"https://docs.deno.com/kv/manual/operations#sum\"}),\"sum\"),\" operation, allowing you to add two \",mdx(\"a\",e({parentName:\"p\"},{href:\"https://deno.land/[email protected]?s=Deno.KvU64&unstable=\"}),mdx(\"inlineCode\",{parentName:\"a\"},\"Deno.KvU64\")),\" values. This is particularly handy for incrementing numeric counters in an \",mdx(\"a\",e({parentName:\"p\"},{href:\"https://en.wikipedia.org/wiki/ACID\"}),\"ACID-compliant way\"),\". However, there's a catch: you can't directly decrement a value using this method since \",mdx(\"inlineCode\",{parentName:\"p\"},\"Deno.KvU64\"),\" requires a positive number in the construction.\"),mdx(\"p\",null,\"Here's how you'd typically increment a counter:\"),mdx(\"pre\",null,mdx(\"code\",e({parentName:\"pre\"},{className:\"language-typescript\"}),`await kv\n .atomic()\n .mutate({\n type: 'sum',\n key: ['users_count'],\n value: new Deno.KvU64(1n)\n })\n .commit();\n`)),mdx(\"p\",null,\"But what if you wanted to decrease this counter? Enter our magic number trick. By using the magic number \",mdx(\"inlineCode\",{parentName:\"p\"},\"0xffffffffffffffffn\"),\", you can effectively subtract from the counter:\"),mdx(\"pre\",null,mdx(\"code\",e({parentName:\"pre\"},{className:\"language-typescript\"}),`await kv\n .atomic()\n .mutate({\n type: 'sum',\n key: ['users_count'],\n value: new Deno.KvU64(0xffffffffffffffffn)\n })\n .commit();\n`)),mdx(\"p\",null,\"In essence, this approach leverages the properties of binary arithmetic to bypass system constraints. Pretty cool, right?\"),mdx(\"h2\",e({},{id:\"conclusion\"}),\"Conclusion\"),mdx(\"p\",null,\"Understanding the underlying principles of binary arithmetic can open the door to many clever tricks in programming. The \",mdx(\"inlineCode\",{parentName:\"p\"},\"uint64\"),\" subtraction trick is just one example. Hopefully, you can find efficient solutions to complex problems by understanding and applying these concepts to your following projects.\"))}MDXContent.isMDXComponent=!0;\n","scope":{}}}},"__N_SSG":true}
1 change: 1 addition & 0 deletions _next/data/YK9qWzohV16kOX2X7D8V4/tags.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"pageProps":{"tags":[{"name":"Deno","slug":"deno"},{"name":"Deno KV","slug":"deno-kv"},{"name":"TypeScript","slug":"typescript"},{"name":"JavaScript","slug":"javascript"},{"name":"Binary Arithmetic","slug":"binary-arithmetic"},{"name":"GitHub","slug":"github"},{"name":"GitHub Actions","slug":"github-actions"},{"name":"Coverage","slug":"coverage"},{"name":"3D","slug":"3d"},{"name":"Data Visualization","slug":"data-visualization"},{"name":"React Three Fiber","slug":"react-three-fiber"},{"name":"React","slug":"react"},{"name":"The Wandering Inn","slug":"the-wandering-inn"},{"name":"Three.js","slug":"threejs"},{"name":"Vercel","slug":"vercel"},{"name":"Art","slug":"art"},{"name":"Fanart","slug":"fanart"},{"name":"Vector","slug":"vector"},{"name":"Stable Diffusion","slug":"stable-diffusion"},{"name":"Inntober","slug":"inntober"},{"name":"Inktober","slug":"inktober"},{"name":"Linode","slug":"linode"},{"name":"Keybase","slug":"keybase"},{"name":"Hugo","slug":"hugo"},{"name":"Gitpod","slug":"gitpod"}]},"__N_SSG":true}
Loading

0 comments on commit 5c22176

Please sign in to comment.