programing

파이썬에서 두 변수의 논리 xor를 어떻게 얻습니까?

nasanasas 2020. 10. 3. 10:55
반응형

파이썬에서 두 변수의 논리 xor를 어떻게 얻습니까?


파이썬에서 두 변수 논리 xor어떻게 얻 습니까?

예를 들어, 문자열이 될 것으로 예상되는 두 개의 변수가 있습니다. 그중 하나만 True 값 (None 또는 빈 문자열이 아님)을 포함하는지 테스트하고 싶습니다.

str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
if logical_xor(str1, str2):
    print "ok"
else:
    print "bad"

^연산자는 비트 것 같다, 모든 개체에 대해 정의되지 :

>>> 1 ^ 1
0
>>> 2 ^ 1
3
>>> "abc" ^ ""
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for ^: 'str' and 'str'

이미 입력을 부울로 정규화하고 있다면! =는 xor입니다.

bool(a) != bool(b)

항상 xor의 정의를 사용하여 다른 논리 연산에서 계산할 수 있습니다.

(a and not b) or (not a and b)

그러나 이것은 나에게 너무 장황하고 언뜻보기에 특히 명확하지 않습니다. 이를 수행하는 또 다른 방법은 다음과 같습니다.

bool(a) ^ bool(b)

두 개의 부울에 대한 xor 연산자는 논리적 xor입니다 (비트 단위 인 int와 달리). 은의 bool하위 클래스int 일 뿐이며 0값만 갖도록 구현됩니다 1. 그리고 논리적 xor는 도메인이 0and 로 제한 될 때 비트 xor와 동일합니다 1.

따라서 logical_xor함수는 다음과 같이 구현됩니다.

def logical_xor(str1, str2):
    return bool(str1) ^ bool(str2)

Python-3000 메일 링리스트의 Nick Coghlan 에게 감사드립니다 .


Bitwise exclusive-or는 operator모듈 ( ^연산자와 동일 함 ) 에서 이미 Python에 내장되어 있습니다 .

from operator import xor
xor(bool(a), bool(b))  # Note: converting to bools is essential

자크는 설명했다, 당신은 사용할 수 있습니다 :

xor = bool(a) ^ bool(b)

개인적으로 저는 약간 다른 방언을 선호합니다.

xor = bool(a) + bool(b) == 1

이 방언은 내가 학교에서 배운 논리적 다이어그램 언어에서 영감을 얻었습니다. 여기서 "OR"은 ≥1(1보다 크거나 같음)을 포함하는 상자로 표시되고 "XOR"는를 포함하는 상자로 표시됩니다 =1.

이것은 배타적 또는 다중 피연산자에 대해 올바르게 구현하는 이점이 있습니다.

  • "1 = a ^ b ^ c ..."는 실제 피연산자의 수가 홀수임을 의미합니다. 이 연산자는 "패리티"입니다.
  • "1 = a + b + c ..."는 정확히 하나의 피연산자가 참임을 의미합니다. 이것은 "배타적 또는", "다른 하나를 배제하는 것"을 의미합니다.

  • 파이썬의 논리 or: A or B: 반환 A하는 경우 bool(A)이고 True, 그렇지 않으면 반환B
  • 파이썬의 논리 and: A and B: 반환 A하는 경우 bool(A)이고 False, 그렇지 않으면 반환B

대부분의 사고 방식을 유지하기 위해 논리적 xor 정의는 다음과 같습니다.

def logical_xor(a, b):
    if bool(a) == bool(b):
        return False
    else:
        return a or b

이렇게 a하면 b, 또는 False다음을 반환 할 수 있습니다 .

>>> logical_xor('this', 'that')
False
>>> logical_xor('', '')
False
>>> logical_xor('this', '')
'this'
>>> logical_xor('', 'that')
'that'

나는 여러 가지 접근 방식을 테스트했으며 not a != (not b)가장 빠른 것으로 나타났습니다.

다음은 몇 가지 테스트입니다.

%timeit not a != (not b)
10000000 loops, best of 3: 78.5 ns per loop

%timeit bool(a) != bool(b)
1000000 loops, best of 3: 343 ns per loop

%timeit not a ^ (not b)
10000000 loops, best of 3: 131 ns per loop

편집 : 위의 예 1과 3에는 괄호가 누락되어 결과가 올바르지 않습니다. 새로운 결과 + truth()ShadowRanger가 제안한 기능.

%timeit  (not a) ^  (not b)   # 47 ns
%timeit  (not a) != (not b)   # 44.7 ns
%timeit truth(a) != truth(b)  # 116 ns
%timeit  bool(a) != bool(b)   # 190 ns

보상 스레드 :

Anoder 아이디어 ... 논리«xor»의 동작을 얻기 위해 비단뱀 표현식«is not»을 시도해보십시오.

진리표는 다음과 같습니다.

>>> True is not True
False
>>> True is not False
True
>>> False is not True
True
>>> False is not False
False
>>>

그리고 예제 문자열 :

>>> "abc" is not  ""
True
>>> 'abc' is not 'abc' 
False
>>> 'abc' is not '' 
True
>>> '' is not 'abc' 
True
>>> '' is not '' 
False
>>> 

However; as they indicated above, it depends of the actual behavior you want to pull out about any couple strings, because strings aren't boleans... and even more: if you «Dive Into Python» you will find «The Peculiar Nature of "and" and "or"» http://www.diveintopython.net/power_of_introspection/and_or.html

Sorry my writed English, it's not my born language.

Regards.


Exclusive Or is defined as follows

def xor( a, b ):
    return (a or b) and not (a and b)

Sometimes I find myself working with 1 and 0 instead of boolean True and False values. In this case xor can be defined as

z = (x + y) % 2

which has the following truth table:

     x
   |0|1|
  -+-+-+
  0|0|1|
y -+-+-+
  1|1|0|
  -+-+-+

I know this is late, but I had a thought and it might be worth, just for documentation. Perhaps this would work:np.abs(x-y) The idea is that

  1. if x=True=1 and y=False=0 then the result would be |1-0|=1=True
  2. if x=False=0 and y=False=0 then the result would be |0-0|=0=False
  3. if x=True=1 and y=True=1 then the result would be |1-1|=0=False
  4. if x=False=0 and y=True=1 then the result would be |0-1|=1=True

Simple, easy to understand:

sum( (bool(a), bool(b) ) == 1

If an exclusive choice is what you're after, it can be expanded to multiple arguments:

sum( bool(x) for x in y ) % 2 == 1

As I don't see the simple variant of xor using variable arguments and only operation on Truth values True or False, I'll just throw it here for anyone to use. It's as noted by others, pretty (not to say very) straightforward.

def xor(*vars):
    sum = False
    for v in vars:
        sum = sum ^ bool(v)
    return sum

And usage is straightforward as well:

if xor(False, False, True, False):
    print "Hello World!"

As this is the generalized n-ary logical XOR, it's truth value will be True whenever the number of True operands is odd (and not only when exactly one is True, this is just one case in which n-ary XOR is True).

Thus if you are in search of a n-ary predicate that is only True when exactly one of it's operands is, you might want to use:

def isOne(*vars):
    sum = False
    for v in vars:
        if sum and v:
            return False
        else:
            sum = sum or v
    return sum

How about this?

(not b and a) or (not a and b)

will give a if b is false
will give b if a is false
will give False otherwise

Or with the Python 2.5+ ternary expression:

(False if a else b) if b else a

Some of the implementations suggested here will cause repeated evaluation of the operands in some cases, which may lead to unintended side effects and therefore must be avoided.

That said, a xor implementation that returns either True or False is fairly simple; one that returns one of the operands, if possible, is much trickier, because no consensus exists as to which operand should be the chosen one, especially when there are more than two operands. For instance, should xor(None, -1, [], True) return None, [] or False? I bet each answer appears to some people as the most intuitive one.

For either the True- or the False-result, there are as many as five possible choices: return first operand (if it matches end result in value, else boolean), return first match (if at least one exists, else boolean), return last operand (if ... else ...), return last match (if ... else ...), or always return boolean. Altogether, that's 5 ** 2 = 25 flavors of xor.

def xor(*operands, falsechoice = -2, truechoice = -2):
  """A single-evaluation, multi-operand, full-choice xor implementation
  falsechoice, truechoice: 0 = always bool, +/-1 = first/last operand, +/-2 = first/last match"""
  if not operands:
    raise TypeError('at least one operand expected')
  choices = [falsechoice, truechoice]
  matches = {}
  result = False
  first = True
  value = choice = None
  # avoid using index or slice since operands may be an infinite iterator
  for operand in operands:
    # evaluate each operand once only so as to avoid unintended side effects
    value = bool(operand)
    # the actual xor operation
    result ^= value
    # choice for the current operand, which may or may not match end result
    choice = choices[value]
    # if choice is last match;
    # or last operand and the current operand, in case it is last, matches result;
    # or first operand and the current operand is indeed first;
    # or first match and there hasn't been a match so far
    if choice < -1 or (choice == -1 and value == result) or (choice == 1 and first) or (choice > 1 and value not in matches):
      # store the current operand
      matches[value] = operand
    # next operand will no longer be first
    first = False
  # if choice for result is last operand, but they mismatch
  if (choices[result] == -1) and (result != value):
    return result
  else:
    # return the stored matching operand, if existing, else result as bool
    return matches.get(result, result)

testcases = [
  (-1, None, True, {None: None}, [], 'a'),
  (None, -1, {None: None}, 'a', []),
  (None, -1, True, {None: None}, 'a', []),
  (-1, None, {None: None}, [], 'a')]
choices = {-2: 'last match', -1: 'last operand', 0: 'always bool', 1: 'first operand', 2: 'first match'}
for c in testcases:
  print(c)
  for f in sorted(choices.keys()):
    for t in sorted(choices.keys()):
      x = xor(*c, falsechoice = f, truechoice = t)
      print('f: %d (%s)\tt: %d (%s)\tx: %s' % (f, choices[f], t, choices[t], x))
  print()

Many folks, including myself, need an xor function that behaves like an n-input xor circuit, where n is variable. (See https://en.wikipedia.org/wiki/XOR_gate). The following simple function implements this.

def xor(*args):
   """
   This function accepts an arbitrary number of input arguments, returning True
   if and only if bool() evaluates to True for an odd number of the input arguments.
   """

   return bool(sum(map(bool,args)) % 2)

Sample I/O follows:

In [1]: xor(False, True)
Out[1]: True

In [2]: xor(True, True)
Out[2]: False

In [3]: xor(True, True, True)
Out[3]: True

It's easy when you know what XOR does:

def logical_xor(a, b):
    return (a and not b) or (not a and b)

test_data = [
  [False, False],
  [False, True],
  [True, False],
  [True, True],
]

for a, b in test_data:
    print '%r xor %s = %r' % (a, b, logical_xor(a, b))

This gets the logical exclusive XOR for two (or more) variables

str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")

any([str1, str2]) and not all([str1, str2])

The first problem with this setup is that it most likely traverses the whole list twice and, at a minimum, will check at least one of the elements twice. So it may increase code comprehension, but it doesn't lend to speed (which may differ negligibly depending on your use case).

The second problem with this setup is that it checks for exclusivity regardless of the number of variables. This is may at first be regarded as a feature, but the first problem becomes a lot more significant as the number of variables increases (if they ever do).


Xor is ^ in Python. It returns :

  • A bitwise xor for ints
  • Logical xor for bools
  • An exclusive union for sets
  • User-defined results for classes that implements __xor__.
  • TypeError for undefined types, such as strings or dictionaries.

If you intend to use them on strings anyway, casting them in bool makes your operation unambiguous (you could also mean set(str1) ^ set(str2)).


To get the logical xor of two or more variables in Python:

  1. Convert inputs to booleans
  2. Use the bitwise xor operator (^ or operator.xor)

For example,

bool(a) ^ bool(b)

When you convert the inputs to booleans, bitwise xor becomes logical xor.

Note that the accepted answer is wrong: != is not the same as xor in Python because of the subtlety of operator chaining.

For instance, the xor of the three values below is wrong when using !=:

True ^  False ^  False  # True, as expected of XOR
True != False != False  # False! Equivalent to `(True != False) and (False != False)`

(P.S. I tried editing the accepted answer to include this warning, but my change was rejected.)


Python has a bitwise exclusive-OR operator, it's ^:

>>> True ^ False
True
>>> True ^ True
False
>>> False ^ True
True
>>> False ^ False
False

You can use it by converting the inputs to booleans before applying xor (^):

bool(a) ^ bool(b)

(Edited - thanks Arel)


XOR is implemented in operator.xor.


We can easily find xor of two variables by the using:

def xor(a,b):
    return a !=b

Example:

xor(True,False) >>> True

참고URL : https://stackoverflow.com/questions/432842/how-do-you-get-the-logical-xor-of-two-variables-in-python

반응형