2016-12-03 94 views
-1

我得到了以下操作:C++位運算反向

uint8_t input = 10; 
uint8_t output = ((0x190 - (input * 8)) & 0xFF); 

// newInput should be 10 again, but is 255 
uint8_t newInput = (((output * 8) + 0x190) | 0xFF); 

我怎樣才能糾正操作設置newInput,這樣會造成早在10?

+0

'如果值== 184值= 25 ;'? –

+2

'| (0&0x07)'什麼都不做!試了一下,得到了200的25,那麼'my_value'的類型是什麼? –

+0

my_value是typeof uint8_t – Alex

回答

2

你想反轉從input得到你output的轉換,但不幸的是邏輯是有缺陷的。 |不是&* 8的倒數絕對不是與另一個* 8相反。此外,如果您想要顛倒y = 0x190 - x的行爲,那不是+,而是另一個x = 0x190 - y(在紙上試試!)最後,如果您的所有操作都是正確的,則操作順序需要按順序顛倒撤消它們(先入先出)。

實際上,您的轉換不能倒置,因爲它會丟失定義input的部分信息。 (從數學上講,它不是單射。)考慮:

uint8_t input = 10; 
uint8_t output = ((0x190 - (input * 8)) & 0xFF); /* 0x40 */ 

uint8_t input2 = 42; 
uint8_t output2 = ((0x190 - (input2 * 8)) & 0xFF); /* also 0x40! */ 

如果你有這將撤消操作的功能,那會是什麼預期返回爲0x40,10或42的output?這沒有解決辦法。如果你想要原始的input,你需要在某處保留該變量的副本。

,可以在無符號8位計算來撤消操作的例子是

  • 加法和一個常數的減法:y = x + ax = y - a
  • 減法從恆定:y = c - xx = c - y,包括普通否定(c = 0),
  • XOR:y = x^px = y^p,包括~x(這是x^0xFF),
  • 乘以一個常數一些的情況下(單數),但倒數並不明顯。

逆操作,以像y = -((x + 0x17)^0x15)化合物會是什麼樣x = ((-y)^0x15) - 0x17,注意,其中的步驟是撤消相反的順序。

在另一方面,這些是不可逆的:

  • AND,
  • OR,
  • 乘以偶數,
  • 比特移位,

有時候你可以找到如果這對你來說可行的話。在這裏,如果你保證input018(即0x90/8)之間,你可以嘗試

uint8_t input = 10; 
uint8_t output = 0x90 - (input * 8); // spot two differences 
uint8_t newInput = (0x90 - output)/8; 

但如果input較大,例如20,這反而給碰巧產生一些其它的值同樣的output

+0

另外,即使假設您有一系列內射操作,您通常也需要按相反的順序應用相反操作,以返回到原始值 – Caleth

+0

,例如(((輸出|(魔術&0xFF00))+ 0x190)/ 8),對於魔術的某些價值 – Caleth

+0

@Caleth我在第一段的某個點添加了這樣的句子,但也許你顯示了以前的編輯。 –

2

有幾個問題,爲什麼你的代碼將無法正常工作,讓我解釋一下其中的一些:

  1. 你有一個無符號的8位整數,所以你可以爲0x00到0xFF之間使用的值。 0x190 - (10 *8) = 0x190 - 0x50 = 0x140可以完成,但是之後您會用&FF刪除前導1,這樣會丟失以後無法恢復的信息。
  2. | FF是一個按位「或」,它將計算的每一位都變爲1,所以無論輸出如何,您都將獲得0xFF = 255
  3. 您的計算錯誤。
  4. 在一次計算中使用十進制數(10)和十六進制數(0x190)是很危險的。它可能會令人困惑。

我建議確保你不會溢出你的變量。使用其他常量,所以你會留在unit8_t的範圍內,或者使用另一個類型,如int16_t,它不會溢出那些小數字。 請注意您的按位運算符。就像我說的最後一個OR將始終使newInput = 255。

這裏是一個將用於給定參數的示例:

int16_t input = 10; // int16_t wont overflow 
int16_t output = ((0x190 - (input * 8))); // without &FF there is no 
              // loss of information 

int16_t newInput = (0x190- output)/8; // Reshape of the line obove 
1

幾點這裏:

  1. 你似乎是試圖用& 0xFF截斷到8位,你應該擺脫,因爲標準已經保證這將發生無符號整數:https://stackoverflow.com/a/36234166/2642059
  2. 你應該做(0x190 - output)/8U恢復輸入,所以即使尺寸允許你的數學是錯誤的:

O = 400 - 8倍速
-O - 400 = -8x
(鄰 - 400)/ -8 = X

  • 400以二進制爲0b1'1001'0000如此以來,垂頭喪氣被截斷它可將最顯著位,不得進行設置,這樣你將永遠有2個可能的答案(其中output爲正):
  • const uint8_t newInputSmall = (0x190 - (output | 0b1'0000'0000))/8U; 
    cosnt uint8_t newInputLarge = (0x190 - output)/8U; 
    
  • 您需要處理的可能性,即output是負的,因爲input * 8U大於400