演算法中的溢出
『壹』 補碼運算為什麼會溢出
什麼是溢出?
溢出,是指數據的大小,超出了編碼所能表示的范圍。
不僅是補碼計算,任何形式的計算,都可能產生溢出。
比如:1999 年、2000 年 ...,這是用 4 位十進製表示。
當到了 9999 年,再過一年,你如果還用 4 位表示,就會溢出了。
如果不限制編碼的位數,那就不存在溢出的問題。
-----------------------------
兩種常用的數字,在計算機中,都是用機器碼代表的。其范圍如下:
機器碼,無論代表什麼數字,只要運算結果超出范圍,就是【溢出】。
但是,在計算機專業人的嘴裡,就不一樣了。
【無符號數的溢出】,不叫溢出,要叫做【進位】。
【帶符號數的溢出】,才叫做【溢出】。
搞計算機的這些人,基本概念不清,卻自命不凡!
冒充腦迴路清奇。。。正常人對此,就只能無語了。
---------------------------
就按照計算機專業的說法吧:
溢出,是指「補碼運算結果超出范圍」。
溢出的特徵,是「符號錯誤」。
知道了這些,判斷是否溢出,就很容易了。
一、無符號數的運算,肯定不會溢出。只有進位。
二、只有:正+正、負+負,才有可能超出范圍。不是這些,就絕不會溢出。
三、人工用數值計算。和,如果沒有超出范圍,就沒有溢出。
四、人工用補碼計算。和的符號,如果正確,就沒有溢出。
五、編個程序,讓計算機計算。然後觀察溢出標志位,為零,就沒有溢出。
六、人工用補碼計算,如「最高位的進位」和「次高位的進位」相同,就沒有溢出。
第六種,本是 CPU 的硬體所用的方法。
硬體,其理論基礎,是很晦澀難懂的。
異或運算,一般也不需要初學者掌握。
但是,一些愛得瑟的老師,偏愛介紹這種方法。
卻又拿不出任何的理論!
其實,這是很無聊的表現,其實,他們就是想要難為學生。
『貳』 計算機補碼運算的溢出叛別方法
使用雙符號位進行計算就可以了,正的前面符號位是"00",負的前面的符號位是"11",假如進行補碼運算的結果符號位是"00"或者"11",則表示沒有溢出;假如結果符號位是"10"或者"01",則表示有溢出.
『叄』 什麼是下溢和上溢
上溢是當一個超長的數據進入到緩沖區時,超出部分被寫入上級緩沖區,下溢是當一個超長的數據進入到緩沖區時,超出部分被寫入下級緩沖區。
隨便往緩沖區中填東西造成它溢出一般只會出現「分段錯誤」(Segmentation fault),而不能達到攻擊的目的。
最常見的手段是通過製造緩沖區溢出使程序運行一個用戶shell,再通過shell執行其它命令。如果該程序有root或者suid執行許可權的話,攻擊者就獲得了一個有root許可權的shell,可以對系統進行任意操作了。
攻擊原理:
通過往程序的緩沖區寫超出其長度的內容,造成緩沖區的溢出,從而破壞程序的堆棧,造成程序崩潰或使程序轉而執行其它指令,以達到攻擊的目的。造成緩沖區溢出的原因是程序中沒有仔細檢查用戶輸入的參數。
當程序需要接收用戶數據,程序預先為之分配了4個格子(下圖1中黃色的0~3號格子)。按照程序設計,就是要求用戶輸入的數據不超過4個。而用戶在輸入數據時,假設輸入了16個數據,而且程序也沒有對用戶輸入數據的多少進行檢查。
就往預先分配的格子中存放,這樣不僅4個分配的格子被使用了,其後相鄰的12個格子中的內容都被新數據覆蓋了。這樣原來12個格子中的內容就丟失了。
以上內容參考:網路-緩沖區溢出
『肆』 c語言數據溢出怎麼辦
C語言的強大之處就在於他的靈活性,程序員自己把握。編譯器可以幫助預防錯誤,但有些程序會利用溢出,所以溢出不完全是錯誤的事情。
1、溢出:
數據類型超過了計算機字長的界限而出現的數據溢出;
2、溢出可能原因:
當應用程序讀取用戶數據,復制到應用程序開辟的內存緩沖區中,卻無法保證緩沖區的空間足夠時 (假設定義數組int Array[10], 而在調用時使用Array[11] 或存放的數據超過int類型容量等), 內存緩沖區就可能會溢出.
3、溢出因素分析:
由於C/C++語言所固有的缺陷,既不檢查數組邊界,又不檢查類型可靠性,且用C/C++語言開發的程序由於目標代碼非常接近機器內核,因而能夠直接訪問內存和寄存器,只要合理編碼,C/C++應用程序在執行效率上必然優於其它高級語言。然而,C/C++語言導致內存溢出問題的可能性也要大許多。
『伍』 針對定點小數加法運算,分析 產生溢出的原因,並給出兩種溢出的方法
(1)產生「溢出」的原因:
當最高有效數值位的運算進位與符號位的運算進位不一致時,將產生運算「溢出」。 當最高有效位產生進位而符號位無進位時,產生上溢; 當最高有效位無進位而符號位有進位時,產生下溢。
(2)「溢出」檢測方法:
為了判斷「溢出」是否發生,可採用兩種檢測的方法。
第一種方法:採用雙符號位法, 稱為「變形補碼」或「模4補碼」,可使模2補碼所能表示的數的范圍擴大一倍
第二種溢出檢測方法:採用「單符號位法」。當最高有效位產生進位而符號位無進位時,產生上溢;
『陸』 我的程序的出現堆棧溢出,怎麼辦
雖然我沒有親眼見到你的源程序代碼,但是根據你所描述的情況來看,我估計你在你的程序源代碼中使用了遞歸調用子函數。因為程序在頻繁地遞歸調用子函數過程中就會產生頻繁地產生壓棧、出棧操作。
遞歸調用子函數的最大優點就是:程序的編寫起來較容易、並且程序的可讀性較好;但是它也有它的缺點。即:如果需要處理的數據量很大時,就必然會導致堆棧溢出的現象。此時就必須將遞歸演算法修改為非遞歸的演算法。
至於具體的修改方法,現在的數據結構教材上都有講解的。但是這樣一改,其程序的非遞歸可讀性必然不如遞歸調用的看起來可讀性要好。
例如:最最經典的遞歸調用子函數就是:計算一個整數的階乘。當需要計算的整數比較小的時候,那麼使用遞歸調用子函數來編寫程序,那簡直就是一種享受。但是當需要計算的整數很大、很大的時候,那麼如果還是使用遞歸演算法,必然會造成堆棧的溢出。此時就必須要把遞歸演算法修改為非遞歸演算法。
『柒』 計算機基本運算中,補碼運算怎樣判斷數值是否有溢出
用二進制補碼,表示正負數,具有一定的表示範圍。
當運算結果,超出了它所能表示的范圍,就會溢出。
如果出現了溢出,這組代碼,就不能正確表示結果。
八位二進制代碼:00000000~11111111。
也就是十進制數:0~255。
它們如果是補碼:0~127,就直接代表零和正數;
128~255,則以補碼代表-128~-1。
八位補碼的范圍:-128~+127。
在127上,再加上+1,就超出了范圍,必然溢出。
這兩個正數相加之後,將會得出128,卻是個負數。
在-128上,再加上-1,也超范圍,也會溢出。
這兩個負數相加之後,將會得出127,這是個正數。
補碼計算出現了溢出,最重要的特徵是:符號不正確。
你只要判斷符號正確與否,就可以了。
另外,
能夠超出范圍的演算法,一定是:正+正、負+負。
捎帶還有:正-負、負-正。
除了這四種演算法之外的計算,都不可能溢出。
『捌』 二進制補碼運算溢出判斷
補碼運算的溢出判別方式為雙高位判別法,利用Cs表示符號位是否進位,利用Cp表示最高數值位是否進位。如果Cs ^ Cp的結果為真,則代表發生了溢出(運算結果大於0則為負溢出,小於0則為正溢出),否則運算結果正確。
例如:
1000 0011(補碼為-3,原碼為-125) 0000 0011(補碼為3,原碼為3)
+1100 1001(補碼為-73,原碼為-55) +1100 1001(補碼為-73,原碼為-55)
10100 1100(補碼為76,原碼為76) 01100 1100(補碼為-76,原碼為-52)
Cs為1,Cp為0所以產生了負溢出。 Cs為0,Cp為0所以結果正確。
(8)演算法中的溢出擴展閱讀
二進制補碼運算規則:
1、正數:原碼=反碼=補碼
2、負數:原碼(第一位是1符號位)=反碼(除第一位符號位外,其它按位取反)=補碼(反碼+1)
3、0:原碼=反碼=補碼=0
舉例:
1、15-5=15+(-5)=10
原碼:
15:0000 1111
-5:1000 0101
反碼:
15:0000 1111
-5:1111 1010
補碼:
15:0000 1111
-5:1111 1011
『玖』 二進制補碼如何判斷溢出
首先符號相反是不會產生溢出的~~所以就是X0Y0或~X0~Y0X0Y0~S0:負+負仍為負,故S0若0(即為正)則溢出;~X0~Y0S0:正+正仍為正,故S0為1(即為負)則溢出;至於減法似乎不對比如1-(-1)就為00000001-11111111=00000010,結果是對的,沒有溢出,所以減法應該是不對的;正確的方法還是應該判斷最符號位進位和最高位進位,異或為1則溢出,為0不溢出,加減法都適用。
『拾』 快速排序演算法運行顯示棧溢出,怎麼解決
剛運行 QuickSort(array,0,array.length-1);這句的時候,進入函數內部key=11, 然後根據判斷條件要找到比key小的數字,但是你的數組為int[]array=new int[]{11,213,134,44,77,78,23,43};沒有比11小的,所以循環會直接運行到最後,當退出循環的時候,i變成了8,但是你的數組只有8個元素,對應索引0-7,所以會出現數組越界的情況,樓主應該是編程新手吧,編程強調邏輯能力,要把很多條件綜合考慮才可以,否則編寫出來的程序會有很多bug。