2012-11-26 74 views
6

我有這行代碼:如何使用位操作來取代modulu和division操作符?

base_num = (arr[j]/base)%256; 

這條線在循環運行和操作「/」和「%」採取了大量的資源和時間來執行的。我想改變這一行並應用位操作以最大化程序性能。我怎樣才能做到這一點?

謝謝。

+0

「base」是一個常量,還是會改變? – Xymostech

+9

如果編譯器是值得的,它會在每個平臺上用'&0xFF'替換'%256',這比'%'快。 'base'的價值是什麼? –

+0

您可以將'base_num'聲明爲8位(無符號)整數 –

回答

7

如果基數是2的n次方,則可以用右移n來代替除法。然後,由於取一個整數的mod 256相當於取最後的8位,所以你可以用0xFF進行與之比較。或者,如果您使用256 * base進行AND操作,然後右移bit n,則可以撤消操作。

base_num = arr[j] >> n; 
base_num &= 0xFF; 

當然,任何half-decent編譯器都應該能夠爲你做到這一點。

+1

您需要按'n'位進行移位,'2^n'爲'1 << n'。 –

+1

[控制內核](http://www.kernel.org)的'pow'函數(來自[glibc](http://ftp.gnu.org/gnu/glibc/))定義在頂部作爲(簡化):'if(base == 2){return(1 << exp)}' –

+0

你是對的,我會修復它:) –

3

-O1或更高版本添加到您的編譯器選項,編譯器將爲您完成。

在GCC,-O1接通-ftree-slsr其是,根據該文檔,

執行在樹上直線強度的降低。這識別涉及乘法的相關表達式,並在可能的情況下用較便宜的計算代替它們。

這將取代模數和基數,如果它是恆定的。但是,如果您知道基數將是某個非恆定的冪數,則可以重構周圍的代碼,以便爲該數字的log2>>減去1。

1

你也可以只申報base_num爲8位整數:

#include <stdint.h> 

uint8_t base_num; 
uint16_t crap; 
crap = 0xFF00; 
base_num = crap; 

如果你的編譯器是標準的恭維,它會把的byte(0xFF00)0x00)的值到base_num

我還沒有滿足,它以純C(既不C++或C#)飽和算術一個編譯器,但如果這樣做,它會把的sat_byte(0xFF00)其比0xFF數值越大,就會把0xFFbase_num

請記住,在這種情況下,您的編譯器會警告您失去精度。在這種情況下,您的編譯器可能會出錯(Visual Studio與Treat Warnings as Errors打開)。如果發生這種情況,你可以這樣做:

base_num = (uint8_t)crap; 

但這似乎是你想要避免的。

你試圖做的似乎是去除模運算符,因爲這需要一個除法和除法是最昂貴的基本算術運算。我一般不會認爲這是任何方式與任何「智能」編譯器(甚至在調試模式)的瓶頸將「優化」它來:

base_num = crap & 0xFF; 

支持的平臺上(每主流處理器我已經聽說 - x86,AMD64,ARM,MIPS),這應該是任何。聽說沒有基本的AND和OR算術指令的處理器,我會驚呆了。