1. 程式人生 > >取餘與位運算

取餘與位運算

在C風格語言中(比如C,C++,C# (注:排名按出生日期 ^_^)),取餘運算子定義為“%”。但在很久很久以前,CPU採用如下方法計算餘數(注意,該方法只對2的N次方數繫有效):

X & (2^N - 1)

首先從求餘數談起,我們知道,計算機中儲存的方式是0和1序列:

1 0001 2^0

2 0010 2^1

3 0011 2^1 + 1

4 0100 2^2

當我們把這些數字序列左移一位的時候... 是的,你答對了,相當與數字擴大為原來的2倍,同理可知右移一位就是縮小為原來的1/2。

那麼餘數在哪裡?被移掉的那些位便是餘數,這是無數前人的證明結果~可以自己拿筆和紙畫一畫就明白了。

那麼,說了這麼多,為什麼一個求餘的%被替換為:X & (2^N - 1)?

舉例:

9 的二進位制就是1001

8 的二進位制就是1000

顯然餘數是1,按照公式這麼做:

把8的二進位制1000換為8-1也就是7,7的二進位制表示為:0111

1001&0111 = 0001

答案為1與我們想的結果一致。

我們把9換成13,過程你親自來一遍,結果在你沒算錯的情況下必然和我的一樣:0101

但是注意,這種方法只是適合於求一個數除以二的N次冥才正確

先說原理再說疑問:

原理:

由於除數是2^N (N為0起始遞增的整數),所以隱藏條件就是,除數的2進位制真身只能是如下的方式展現:

0001,0010,0100,1000.。。。。。

沒看出來?那我們繼續:

10000,100000,1000000.。。。。

明白了吧,當我們求餘的時候,相當於除以2的N次冥,也就是相當於把數本身右移N位,但是移走的那些餘數可一去不復返了。(什麼?你說在CF暫存器中?嗯,這是個好注意,也許有另種一實現?!)。有什麼辦法保護這些即將失去的資料呢?

我們把上面的數字減一就發現:

0000,0001,0011,0111,01111,011111,0111111.。。。。。。

如您所見,當和1做位運算時候,得到的結果是那個數的本身。前面例子1001&0111= 0001相當於1001右移三位得到0001,那麼(13)1101右移三位還是0001,這2個0001表示的是商,兩個移走的餘數分別是“001”和“101”,發現特徵了嚒?除以2的N次方就是要儲存被除數即將被移走的低N位。

好了,我知道上面我講的可能不清楚,但是下面才是真正驚險的地方:

2^3=8 然後8表示為1000 有3個零,預示著右移位數,右移位數告訴我們被除數即將被移走幾位,我們如果將這幾位與1按位運算不就能知道這幾位到底是0還是1,也就是能完全儲存到移走的資料,它就是我們期望的餘數。

嗯,我確信看完我的解釋你還在暈眩之中,別管他們,該幹嘛幹嘛,睡完一覺之後我想我的這些話也許會被你的大腦自動解析,你最終也會明白這是怎麼一回事。

嗯,我想說,如果早起電腦都這麼做的話,那麼求一個非2的N次冥的取餘怎麼來實現呢?

相關推薦

運算

在C風格語言中(比如C,C++,C# (注:排名按出生日期 ^_^)),取餘運算子定義為“%”。但在很久很久以前,CPU採用如下方法計算餘數(注意,該方法只對2的N次方數繫有效): X & (2^N - 1) 首先從求餘數談起,我們知道,計算機中儲存的方式是0

【Java基礎】Java基本數據類型運算

右移 數據 bits 類型 span 網上 height 使用 常數 1.賦值運算符 賦值使用操作符“=”。它的意思是“取右邊的值(即右值),把它復制給左邊(即左值)”。右值可以是任何 常數、變量或者表達式 (只要它能 生成

Java:二進制(原碼、反碼、補碼)運算

無符號 位與 轉換成 轉換 不同 一個 位或 其他 log 一、二進制(原碼、反碼、補碼) 二進制的最高位是符號位(“0”代表正數,“1”代表負數); Java中沒有無符號數; 計算機以整數的補碼進行運算; 1. 原碼:將一個整數轉換成二進制表示 以 int 類型為例

運算

() key byte 內存 十進制 一次 內存對齊 常用 都沒有 有些數據在存儲時並不需要占用一個完整的字節,只需要占用一個或幾個二進制位即可。例如開關只有通電和斷電兩種狀態,用 0 和 1 表示足以,也就是用一個二進位。正是基於這種考慮,C語言又提供了一種叫做位域的數據

字節序,原碼和補碼運算

沒有 原碼 tools 大端 arr nta 內存地址 length 都是 計算機最小的數據獲取單元就是字節,一個字節byte = 8個位 bit,八個位是用二進制的形式保存的。假如11111111,如果是無符號數那麽可以保存0-255一共256(2的八次方)個數的數,

【題解】[牛客網NOIP賽前集訓營-提高組(第五場)]A.同方程 運算

#include<cstdio> #include<algorithm> using namespace std; typedef long long ll; const ll mod=998244353; ll m,l1,l2,r1,r2; ll

制轉換運算

1.其他進位制轉十進位制 位上的值*位數-1 相加  101=1*1 + 0*2 + 1*4   2.十進位制轉其他進位制 將該數不斷除以該進位制,直到商為0,將每步得到的餘數倒過來就是對應的進位制 356 / 2 = 0X164   3

[LeetCode][7]Reverse Integer解析運算實現 -Java實現

Q: Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 A: 以下解法和程式碼沒有借閱以往任何資料,如果有更好的解法請在評論區留言 這

python基礎知識之整除、、冪運算

數字和表示式python直譯器可以當作計算器使用>>>2+2 4整數除法一個整數被另一個整數除,計算結果的小數部分被截去,只保留整數部分。如果參與除法的兩個數中有一個為浮點數,運算結果為浮點數。>>>1/2 0 >>>1.

Java別說( )運算簡單,你真的會嗎

                        一,直擊現場

c語言邏輯運算運算區別

c語言中,邏輯運算與位運算很容易混淆,但是它們的功能是完全不同的。邏輯運算認為所有的非零的引數都為TRUE,引數0表示false,它們返回1或0. &&與||和&與|重要的區別是,如果第一個引數求值能確定表示式的結果,那麼邏輯運算子就不會對第二個引數

十進位制轉二進位制,短除法運算兩種方法

短除法:比如十進位制整數19 19/2=9……1 9/2=4……1 4/2=2……0 2/2=1……0 所以最後計算的結果就是10011 短除法程式碼: #include <iostream&g

邏輯運算運算區別

位運算: 位運算是講資料先轉化為二進位制數,再逐位(bit)按規則計算 1.“按位與”運算子“&”,規則:全1則1,否則為0 例如: a       00000000 00000000 00000000 00000111 b   ^  10000001 101001

【筆試題分享】異或運算的巧用

第1題  假設x和y都是整數,如果得到其中較小的那個。 微軟2012暑期實習生筆試題。這是道選擇題,從給出的四個選項中選出一個正確的答案。 仔細想想之後,發現A是正確解:y^( (x^y)& -(x<y) )  (現在才認識到異或的神奇之處) 說明自己的理解: 1. 對於(x<y)的判定

【小家java】Java中二進位制運算(“^,&,>>,>>>”),使用移位演算法寫一個流水號生成器(訂單號生成器)

相關閱讀 每篇一句 高樓大廈,都是平地起的。 整個java體系,其實就是一本祕籍,那就是:java基礎! (基礎如果打的紮實,在實際開發工作中會帶來極大的助益) 二進位制 二進位制是計算技術中廣泛採用的一種數制。二進位制資料是用0和1兩個數碼來表示的

老鼠試毒運算

沒有 import int system 表示 map 一點 rgs png 記錄一個有趣的問題:有 1000 個一模一樣的瓶子,其中有 999 瓶是普通的水,有一瓶是毒藥。任何喝下毒藥的生物都會在一星期之後死亡。現在,你只有 10 只小白鼠和一星期的時間,如何檢驗出哪個瓶

快速冪(大數運算/演算法優化)

快速冪取餘 int PowerMod(int a, int b, int k) { int ans = 1; a = a % k; while(b>0))

三分鐘熟悉進制轉換運算

## 進位制和位運算簡介 進位制也叫進位制,是一種記數方法,也稱進位計數法,利用這種記數法可以使用有限的數字符號來表示所有的數值。 一種進制中可以使用的數字符號的數目稱為這種進位制的基數,若一個進位制的基數為 N,則可稱之為 N 進位制,即表示數值時滿 N 進一。 在生活中最常用的是十進位制,使用 10

運算

關於位與運算&與取餘今天在研究hashmap原始碼的時候,發現其原始碼中在解決Entry分佈時,本來大多數人以為會用index = hash % length,但是原始碼中卻使用了index = hash & (lenth -1)的方式。 /** * The default initi

運算

位與也是可以用來取餘的,但是有一個條件:除數必須是2的n次冪才行。舉例子來說明 9%8=1 1001 & (1000 - 1) =1001 & 0111 =1 // 1001是9的二進位制表示,1000是8的二進位制表示 在二進位制計算中,眾所周知的是,