Bitwise operator XOR (^) 在 Linux 和 Windows 中产生不同的结果。

huangapple go评论58阅读模式
英文:

Bitwise operator XOR (^) gives different results in linux and windows

问题

由于某些难以解释的原因,我想在Perl中执行以下位操作:
(假设1表示真,0表示假)

$var1 = "11000001";
$var2 = "10000101";

$y = $var1 & $var2; # 位与操作
$o = $var1 | $var2; # 位或操作
print "var1 & var2: $y\n";
print "var1 | var2: $o\n";

然后,无论是在Windows上的Perl还是在Linux上的Perl中,我都会得到相同的输出:

var1 & var2: 10000001(这是我想要的结果)
var1 | var2: 11000101(这是我想要的结果)

但是,如果我执行以下操作:

$xox = $var1 ^ $var2; # 位异或操作
print "var1 ^ var2: $xox\n";

那么在Windows上的输出是:

var1 ^ var2: ☺   ☺

而在Linux上则是:

var1 ^ var2: 

考虑到 &| 运算符似乎按照预期工作,我也希望对于 ^ 运算符能够得到类似以下的结果:

$var1 = "11000001";
$var2 = "10000101";
$xox = $var1 ^ $var2; # 位异或操作
print "var1 ^ var2 --> $xox\n";

var1 ^ var2 --> 01000100

但如上所示,这不适用于Windows和Linux,尽管至少对于我的用途来说,Windows的异或运算输出是有用的,但Linux的输出却不是。

有人可以解释为什么 &| 运算符似乎起作用,但 ^(异或)运算符不起作用吗?
以及为什么Linux和Windows之间存在这种差异?
谢谢。

注意:指定 int($var1) ^ int($var2) 不会产生期望的结果(对我来说,即获得输出 01000100)。

【注意】:代码部分已被排除在翻译之外,只提供翻译好的部分。

英文:

for some reason long to explain I want to do the following bitwise operations in perl:
(let's assume that 1 means true and 0 means false)

$var1="11000001";
$var2="10000101";

$y=$var1 & $var2; #bitwise and
$o=$var1 | $var2; #bitwise or
print "var1 & var2: $y\n";
print "var1 | var2: $o\n";

Then, I get the same output both in windows perl and in Linux perl:

var1 & var2: 10000001 (which is what I wished)
var1 | var2: 11000101 (which is what I wished)

BUT if I do:

$xox=$var1^$var2; # bitwise xor
print "var1 ^ var2: $xox\n";

then the output in windows is:

var1 ^ var2:  ☺   ☺

while in linux is:

var1 ^ var2: 

Given that the & and | operators seem to work as 'expected', I was also expecting to get something like:

$var1="11000001";
$var2="10000101";
$xox=$var1^$var2; # bitwise xor
print "var1 ^ var2 --> $xox\n";

var1 ^ var2 --> 01000100

for the ^ operator.

But, as shown above, this is not the case for both windows and linux, although at least the windows output for xor is useful for my purposes, but not the linux output.

Can anyone explain why the '&' or '|' operators seem to work but not the '^' (XOR) operator?
And why is there that difference between linux and windows?
Thanks

NOTE: specifying int($var1) ^ int($var2) does not result in a desirable result (for me; i.e. to get as output 01000100)

答案1

得分: 9

> 有人能解释一下为什么&|运算符能正常工作,但^(XOR)运算符不能吗?

这更或多少是巧合,&|能正常工作是基于字符"0"和"1"的字符编码:

0x30 | 0x31 = 0x31(观察到:"0" | "1" = "1")
0x30 & 0x31 = 0x30(观察到:"0" & "1" = "0")

&|都保留了顶半字节的"3",而"0"和"1"字符的底半字节恰好分别为"0"和"1"。

XOR会将顶半字节的"3"置零,因此会得到一些无意义的字符,这些字符会根据操作系统的解释而显示不同。显然,值为1的字符(只是1,不是0x31,通常是不可打印字符)在Windows上在某些情况下显示为☺。

作为一种快速解决方法,你可以这样做来恢复顶半字节的"3":

$xox=($var1^$var2)|"00000000"; # 位异或

我认为这是一种权宜之计。

> 注意:指定int($var1) ^ int($var2)不会得到期望的结果(对我来说不是理想的结果,即获得01000100作为输出)

因为你没有指定这些是二进制数,它们没有被解析为预期的形式。这里有一种方法可以做到这一点,注意这种方式不会保留前导零:

print sprintf("%b", oct("0b$var1") ^ oct("0b$var2"));
英文:

> Can anyone explain why the '&' or '|' operators seem to work but not the '^' (XOR) operator?

It's more or less a coincidence that & and | work, based on the character codes of the 0 and 1 characters:

0x30 | 0x31 = 0x31 (observed: "0" | "1" = "1")
0x30 & 0x31 = 0x30 (observed: "0" & "1" = "0")

Both & and | preserve the 3 in the top nibble, and the bottom nibble of the 0 and 1 characters happen to be 0 and 1 respectively.

XOR zeroes out the 3 in the top nibble, so you get some nonsense characters, which are printed differently based on how the OS interprets them. Apparently the character with the value 1 (just 1, not 0x31, normally it's an unprintable character) is shown as ☺ on windows at least in some situations.

As a quick hack, you could do this to put the 3's back in the top nibbles:

$xox=($var1^$var2)|"00000000"; # bitwise xor

I think that's a hack though.

> NOTE: specifying int($var1) ^ int($var2) does not result in a desirable result (for me; i.e. to get as output 01000100)

Because you did not specify that these were numbers in binary, they're not being parsed as intended. Here's one way to do it, note that leading zeroes are not preserved this way:

print sprintf("%b", oct("0b$var1") ^ oct("0b$var2"));

huangapple
  • 本文由 发表于 2023年5月28日 22:01:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76351869.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定