代碼之謎(一) - 有限與無限(從整數的絕對值提及)

1、引子

開始本章以前我先提個問題:「若是一個整數的絕對值等於它本身,那麼這個數是幾?」若是你回答是 0 和 全部正數,那麼請你耐心讀完這篇文章吧。 html

本章是我『代碼之謎』系列的第二篇,前一篇『代碼之謎 - 開篇/前言/序』簡單介紹了計算機與數學的不一樣。 java

數學中有許多複雜深入的矛盾,數學家的工做就是解釋或者反駁這些矛盾, 例若有限與無限、連續與離散、存在與構造、邏輯與直觀、具體與抽象、概念與計算等等。 linux

在本章中,咱們把目標縮小,主要討論內容 編程

  • 概念: 有限與無限
  • 對象: 8bit整數

2、絕對值之謎

終於到主題了,也許你很想知道「負數的絕對值可能等於本身嗎?」,也就是 「若是x等於-x,那麼x有幾個解?」按照我一向的做風,我是不會輕易告訴你答案的。 《編程珠璣》記載,做者告訴了他同事一個結果,而不是方法,最後追悔莫及。 因此,我在這裏要告訴你方法,而不是告訴你答案編程語言

告訴你答案以前,首先得回答個問題:「整數(8bit)的表示範圍是多少?」,(也許你已經把教科書的知識背下來了,是 -2^7 到 2^7-1,也就是 -128 到 +127,如今的計算機科學都快成爲文科了^_^)。 翻譯

若是你不知道也不要緊,至少你知道 8bit 能夠表示的整數個數是 2^8 個,這個數等於多少無所謂,可是,它必定是個偶數(256)。 設計

那麼這裏就有一個頗有意思的問題了,0既不是正數也不是負數,把0去掉的話,整數的個數就是奇數了,整數還剩 255 個。 奇數個整數不可能平均分紅兩部分(正數和負數),要麼負數多一個,要麼正數多一個。事實就是,負數比正數多一個,最小的負數是 -128, 最大的整數是 127。 code

如今的問題是, -128 的絕對值是多少呢? -(-128)等於多少呢?是溢出呢,仍是等於它本身呢?也許計算機課本沒有告訴你, 整數是不會出現溢出異常的,整數的溢出被認爲是正常的捨棄(其實只要很合理)。整數只有被0除纔會異常,而浮點數,即便被0除也不會拋出異常。 浮點數除0的操做將放在本系列浮點數篇討論。 htm

絕對值等於本身的數有兩個,0 和最小的負數。 對象

你可能要像香港電影裏女主角那樣歇斯底里的大喊「絕對值怎麼多是負數呢? 不可能,我不信,我不信…」

忘掉你那可憐的數學知識吧,「發生這種事,你們都不想的。感情的事呢,是不能強求的。所謂吉人自有天相,作人呢,最要緊的就是開心…」跑題了,趕忙回來。

在經典數學(非皮亞諾算術系統,皮亞諾絕對是歐幾里德的鐵桿粉絲,要不怎麼會有如此天才的構想,這個之後會給你們普及)中,絕對值定義爲:「從原點到點A的距離,稱爲A的絕對值,它是一個非負數」。 既然講到了距離,不妨劇透一下(本系列「邏輯篇」會涉及到),兩個數的大小在數學中如何定義,「距離數軸原點的距離遠近」,計算機中大小如何定義的呢?給你們留個做業吧(別告訴我是設計編程語言或者設計電腦的科學家規定的,計算機科學絕對不是文科)。

計算機中沒有數軸,絕對值是如何定義的呢?看看java、C、Python的源碼(感謝那些開源大牛),和我們學的小學數學同樣。

abs(x) :=  (x >= 0) ? x : -x

翻譯過來就是,x的絕對值定義爲:正數和0的絕對值等於它本身,負數的絕對值等於-x。(這裏使用的是-x,而沒有用0-x,由於在浮點數中,這二者是有區別的。)

3、深刻 -x

那麼 -x 是如何計算的呢? 計算是數學概念,在計算機中,咱們應該說 -x是如何求值的呢?還得回到源碼,我只看了linux中關於C的源碼,若是你看過其它語言源碼發現和我說的不一樣,請聯繫我。 學過計算機原理的都知道,負數在計算機中以補碼形式存儲,計算補碼的方式和取反操做相似。

符號位不變,其它位取反,最後加一。

好比 -5

原碼:       1000,0101
其它位取反:  1111,1010
加一:       1111,1011

當咱們求它的絕對值時如何操做呢

補碼:     1111,1011      這是-5在計算機中的表示
各位取反:  0000,0100
加一:     0000,0101      此時結果爲+5

如今咱們回到最小的負數問題,最小的負數在計算機中表示爲 1000,000,下面咱們對這個數操做

補碼:     1000,0000
各位取反:  0111,1111
加一:     1000,0000

神奇嗎,尼瑪,竟然又回到本身了。

相關文章
相關標籤/搜索