計算機是用n位0和1來表示數字的,這樣很容易表示正數,但是怎麼表示負數呢?
人類聰明的大腦想到了用第一位來表示符號,0代表正數,1代表負數。這種表示方法最好理解,叫做原碼。
但是計算機在計算的時候,為了簡化,需要把減法當做加法運算。這個很簡單,負數不就是幹這個的嗎?比如2-1=2+(-1)。
但是負數如果按照原碼表示的話,就不好辦了,比如:
2-1=2+(-1)=00000010+10000001=10000011=-3
顯然是錯的,所以人類習慣的方法無法滿足這個需求,根本原因在於符號位的引入不符合計算機執行原理。
那麼,腫麼辦呢?
首先介紹模的概念:數學上7位數可以表示[0, 127]共128個值,超過128就會溢位,那麼128就是7位數的模。
而模一定的情況下,減法都可以變換成加法來運算,比如:
你要把鐘錶往前撥2個小時,你可以把它往前撥10個小時來實現。這裡-2就轉化為了+10。
下面看同餘數的數學定義:
如果a和b對於乙個數m的餘數相同,成a和b為m的同餘數,或者稱a和b互為補數,記做:
a ≡ b (mod m)
那麼問題來了,負數的餘數如何定義?
數學上是
就是: x對y的餘數等於x減去y乘上x與y的商的下界。
而顯然,乙個數的餘數一定是它的同餘數。
這樣如果你想算a-b的話(a,b都是正數),可以算成a+(-b的補數),比如:
模為128的情況下,2-1=2+(-1)=2+(128-1)=128+1,由於溢位,結果是1
終於算對了!
給定負數的原碼,如何讓計算機方便的算出負數的補數?
假如用n位來表示數,那麼-a=2^(n-1)-a-2^(n-1),其中a為正數
而a表示成10進製的話, 是
a=k0*2^0+k1*2^1+k2*2^2+...k(n-2)*2^(n-2),為什麼是n-2呢?因為原碼要留一位給符號位,所以只有n-1位有效位。
而2^(n-1)=1+1*2^0+1*2^1+1*2^2+...+1*2^(n-2),所以
2^(n-1)-a=1+(1-
k0)*2^0+(1-k1)*2^1+(1-k2)*2^2+...(1-k(n-2))*2^(n-2),也就是除了最高位之外,其他部分取反加1。
而剩下的
-2^(n-1),它的補數是2^(n-1),也就是還要再加上個最高位為1其他全為0的數.
那麼就得出我們教科書的結論:
對於負數,原碼到補碼就是:符號位為1,其他位取反加1(不可進製到符號位)。
顯然,對於正數,補碼等於原碼(想想鐘錶的例子)。
注意乙個特例,-128是沒有原碼的,因為原碼的表示範圍就是[-127~127],0有10000000和00000000兩個。
但是按補碼算的話,-127-1=11111111+10000001=10000000
所以補碼是可以表示-128的,因此補碼的表示範圍是[-128~127]
注意,補碼的計算完全是2進製的計算,沒有符號位,而且該溢位溢位。
總結:
1. 計算機都是用補碼表示數,語言在編譯的時候已經把原碼轉換成了補碼,再寫入記憶體。 比如
int i=-1;
printf("%x\n",i);
輸出就是0xffffffff
2. 計算機不知道減法,也不知道符號位,它只知道加法和溢位。所以補碼運算只有加法和溢位。
3. print的時候,%d是列印原碼,%x是列印計算機裡的原始資料。而用0x80000000來賦值的話,其實是直接賦值給計算機記憶體原始資料。
比如int i=0x80000000;
printf("%d\n",i);
輸出就是-2147483648
RSA 數學原理
提起rsa大家一定不陌生,在開發中經常使用,也經常聽同事說道。話說很久以前,人們就懂的了加密這個技術。在戰爭時期,間諜就會拿著密文和密匙來對資訊就行傳遞。這種簡單的密文 密匙 key 就是對稱加密 加密 明文 密匙 解密 密文 密匙 由於這種加密方式過於簡單,所以後來引入了數學演算法。rsa就是由特...
LOST OF DETAIL 的數學原理
主要是這兩個公式 l df l d c d2 max c d2,1 f 1 基本上看不懂!但是從原理上來思考的話,應該歸結為以下兩點 1.所有的長度的方塊經過投影之後應該是同乙個長度或者比它更大。保證乙個螢幕上沒有過多的三角形 2.垂直方向上,要麼,我們的分解後,產生的高度誤差,經過投影之後,產生的...
PCA的數學原理
pca的數學原理 pca principal component analysis 是一種常用的資料分析方法。pca通過線性變換將原始資料變換為一組各維度線性無關的表示,可用於提取資料的主要特徵分量,常用於高維資料的降維。網上關於pca的文章有很多,但是大多數只描述了pca的分析過程,而沒有講述其中...