[英]C++ bitwise operation reverse
我得到以下操作:
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?
您想反转从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
或42的output
将会返回什么? 这没有解决办法。 如果您想要原始input
,则需要将该变量的副本保存在某个地方。
在无符号8位计算中可以撤消的操作示例如下:
y = x + a
a⇔x x = y - a
, y = c - x
x⇔x x = c - y
,包括纯否定( c
= 0), y = x ^ p
p⇔x x = y ^ p
,包括~x
(即x ^ 0xFF
), 对类似于y = -((x + 0x17) ^ 0x15)
的化合物进行逆运算将看起来像x = ((-y) ^ 0x15) - 0x17
,请注意步骤的相反顺序。
另一方面,这些不是不可逆的:
有时,您可以找到一个逆函数,如果这对您来说可行。 在这里,如果保证input
在0
到18
之间(即0x90 / 8
),则可以尝试
uint8_t input = 10;
uint8_t output = 0x90 - (input * 8); // spot two differences
uint8_t newInput = (0x90 - output) / 8;
但是,如果input
较大,例如20,它将提供可能产生相同output
其他值。
为什么您的代码无法正常工作有几个问题,让我解释其中的一些问题:
0x190 - (10 *8) = 0x190 - 0x50 = 0x140
可以完成,但是之后您用&FF切掉了前导1,因此您丢失了以后无法恢复的信息。 | FF
| FF
是按位或,它将计算的每一位变为1,因此无论输出如何,您始终将获得0xFF = 255
。 我建议确保您不会使变量溢出。 使用其他常量,这样您就可以保持在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
这里有几点:
& 0xFF
截断为8位,您应该摆脱它,因为该标准已经保证了无符号整数会发生这种情况: https : //stackoverflow.com/a/36234166/2642059 (0x190 - output) / 8U
以恢复输入,所以即使允许的大小您的数学也是错误的: o = 400-8倍
o-400 = -8x
(o-400)/ -8 = x
0b1'1001'0000
因此,因为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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.