<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Coding | Chia-An Lee</title><link>https://calee0219.github.io/tag/coding/</link><atom:link href="https://calee0219.github.io/tag/coding/index.xml" rel="self" type="application/rss+xml"/><description>Coding</description><generator>HugoBlox Kit (https://hugoblox.com)</generator><language>en-us</language><copyright>©</copyright><lastBuildDate>Wed, 23 Mar 2022 07:48:37 +0800</lastBuildDate><image><url>https://calee0219.github.io/media/icon_hu_da05098ef60dc2e7.png</url><title>Coding</title><link>https://calee0219.github.io/tag/coding/</link></image><item><title>位元運算</title><link>https://calee0219.github.io/blog/bit_manipulation/</link><pubDate>Wed, 23 Mar 2022 07:48:37 +0800</pubDate><guid>https://calee0219.github.io/blog/bit_manipulation/</guid><description>&lt;p&gt;最近迷上有趣的位元運算，發現原來有很多可玩的地方，所以就簡單紀錄一下
這裡幾乎都是以 32 bit 為主，若 64 bit 請自行擴充&lt;/p&gt;
&lt;h2 id="abs"&gt;ABS&lt;/h2&gt;
&lt;p&gt;取絕對值&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;int abs(int n) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; return ((n &amp;gt;&amp;gt; 31) ^ n) - (n &amp;gt;&amp;gt; 31);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="count-1"&gt;Count 1&lt;/h2&gt;
&lt;p&gt;計算 1 存在的數量&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;int count_1(uint32_t n) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; n = (n &amp;amp; 0x55555555) + ((n &amp;amp; 0xAAAAAAAA) &amp;gt;&amp;gt; 1);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; n = (n &amp;amp; 0x33333333) + ((n &amp;amp; 0xCCCCCCCC) &amp;gt;&amp;gt; 2);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; n = (n &amp;amp; 0x0F0F0F0F) + ((n &amp;amp; 0xF0F0F0F0) &amp;gt;&amp;gt; 4);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; n = (n &amp;amp; 0x00FF00FF) + ((n &amp;amp; 0xFF00FF00) &amp;gt;&amp;gt; 8);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; n = (n &amp;amp; 0x0000FFFF) + ((n &amp;amp; 0xFFFF0000) &amp;gt;&amp;gt; 16);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; return n;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;或用 &lt;code&gt;Brian Kernighan's Algorithm&lt;/code&gt;，此算法主要是由觀察 &lt;code&gt;n&lt;/code&gt; 與 &lt;code&gt;n-1&lt;/code&gt; 的 &lt;code&gt;&amp;amp;&lt;/code&gt; 會把最小非零位元歸零 &lt;code&gt;x..x10..0 &amp;amp; x..x01..1 = x..x00..0&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;int count_1(uint32_t n) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; int distance = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; while (n != 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; distance += 1;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; // remove the rightmost bit of &amp;#39;1&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; n &amp;amp;= n - 1;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; return distance;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id="pow-of-2"&gt;Pow of 2&lt;/h1&gt;
&lt;p&gt;簡單來說就是檢查 &lt;code&gt;Count 1 == 1&lt;/code&gt;，所以可以用前面的方法。&lt;/p&gt;
&lt;p&gt;但 &lt;code&gt;Brian Kernighan's Algorithm&lt;/code&gt; 的想法延伸可以找到更簡單作法，
&lt;code&gt;n&lt;/code&gt; 與 &lt;code&gt;n-1&lt;/code&gt;，如果 &lt;code&gt;n&lt;/code&gt; 呈現為 &lt;code&gt;xx...x10...0&lt;/code&gt;，而 &lt;code&gt;n-1&lt;/code&gt; 為 &lt;code&gt;xx..x01...1&lt;/code&gt;，相 &lt;code&gt;&amp;amp;&lt;/code&gt; 後為 &lt;code&gt;xx...x00...0&lt;/code&gt;，及 n 的最低位非 0 以下都會被壓縮成 0。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bool isPowerOfTwo(uint32_t n){
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; return (n &amp;amp; (n-1)) == 0;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="swap"&gt;Swap&lt;/h2&gt;
&lt;p&gt;可以完成 in-placed swap&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;void swap(int *a, int *b) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; *a ^= *b;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; *b ^= *a;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; *a ^= *b;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="reverse-bits"&gt;Reverse Bits&lt;/h2&gt;
&lt;p&gt;將數字前後顛倒&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uint32_t reverseBits(uint32_t n) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; n = ((n &amp;amp; 0xFFFF0000) &amp;gt;&amp;gt; 16) | ((n &amp;amp; 0x0000FFFF) &amp;lt;&amp;lt; 16);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; n = ((n &amp;amp; 0xFF00FF00) &amp;gt;&amp;gt; 8) | ((n &amp;amp; 0x00FF00FF) &amp;lt;&amp;lt; 8);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; n = ((n &amp;amp; 0xF0F0F0F0) &amp;gt;&amp;gt; 4) | ((n &amp;amp; 0x0F0F0F0F) &amp;lt;&amp;lt; 4);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; n = ((n &amp;amp; 0xCCCCCCCC) &amp;gt;&amp;gt; 2) | ((n &amp;amp; 0x33333333) &amp;lt;&amp;lt; 2);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; n = ((n &amp;amp; 0xAAAAAAAA) &amp;gt;&amp;gt; 1) | ((n &amp;amp; 0x55555555) &amp;lt;&amp;lt; 1);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; return n;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="find-not-duplicate--find-difference"&gt;Find not duplicate / find difference&lt;/h2&gt;
&lt;p&gt;檢查字串裡沒有重複的字元 / 檢查兩字串的字元差(確定只有一個了話)。&lt;/p&gt;
&lt;p&gt;透過 xor 自己會得 0 的性質。&lt;/p&gt;
&lt;h1 id="reference"&gt;Reference&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>