Python での 16 進数のビットごとの XOR

Salman Mehmood 2023年6月21日
Python での 16 進数のビットごとの XOR

この記事の主な目的は、Python の 16 進数システムで XOR 数を処理する方法を示すことです。

Python での 16 進数のビットごとの XOR

XOR はビット単位の演算子で、排他的 OR を意味します。 論理演算を実行し、両方の入力 (0 または 1) が同じ場合は 1 を返します。 それ以外の場合、入力数値が異なる場合 (0 と 1 または 1 と 0 など)、出力は 0 になります。

XOR は通常、圧縮、暗号化、グラフィックス、またはあらゆる形式の通信に使用されるアプリケーションで使用されます。 XOR はビット単位の論理演算子の一部であるため、精度が向上し、必要なリソースが少なくなるため、コードがはるかに高速かつ効率的になります。

^ 演算子を使用すると、10 進数の数値を XOR するのはかなり簡単です。 最初に文字列に含まれる、または文字列の一部である数値についてはどうでしょうか?

次のコードを検討してください。

def strxor(a, b):
    if len(a) > len(b):
        return "".join(["%s" % (ord(x) ^ ord(y)) for (x, y) in zip(a[: len(b)], b)])
    else:
        return "".join(["%s" % (ord(x) ^ ord(y)) for (x, y) in zip(a, b[: len(a)])])


if __name__ == "__main__":

    print("1C2 ^ ABC = ", strxor("1C2", "ABC"))
    print("2FF ^ 78B = ", strxor("2FF", "78B"))
    print("29A ^ 90C = ", strxor("29A", "90C"))
    print("10C ^ 24B = ", strxor("10C", "24B"))
    print("BAD ^ 432 = ", strxor("BAD", "432"))
    print("54F ^ 123 = ", strxor("54F", "123"))

これにより、以下の出力が得られます。

1C2 ^ ABC =  1121113
2FF ^ 78B =  51264
29A ^ 90C =  1192
10C ^ 24B =  341
BAD ^ 432 =  118114118
54F ^ 123 =  46117

ソリューションを検証しましょう。

if __name__ == "__main__":

    print("1C2 ^ 0xABC = ", 0x1C2 ^ 0xABC)
    print("2FF ^ 0x78B = ", 0x2FF ^ 0x78B)
    print("29A ^ 0x90C = ", 0x29A ^ 0x90C)
    print("10C ^ 0x24B = ", 0x10C ^ 0x24B)
    print("BAD ^ 0x432 = ", 0xBAD ^ 0x432)
    print("54F ^ 0x123 = ", 0x54F ^ 0x123)

これにより、次の出力が得られます。

1C2 ^ 0xABC =  2942
2FF ^ 0x78B =  1396
29A ^ 0x90C =  2966
10C ^ 0x24B =  839
BAD ^ 0x432 =  3999
54F ^ 0x123 =  1132

上記のコードからわかるように、strxor という名前の新しいメソッドを作成しました。このメソッドは、関数に渡される 2つの文字列に対応する ab という名前の 2つのパラメーターを取ります。 このメソッドの目的は、2つの文字列を取得して XOR し、結果 (これも文字列) を返すことです。

ソリューションを検証すると、結果が予想とは異なることがわかります。 つまり、実装された関数 strxor には論理エラーがあります。

この問題の解決策には、複数の方法があります。 これらのいくつかは、次のように定義されています。

解決策 1

def strxor(a, b):
    if len(a) > len(b):
        res = "".join(
            ["%x" % (int(x, 16) ^ int(y, 16)) for (x, y) in zip(a[: len(b)], b)]
        )
        return int("0x" + res, 0)
    else:
        res = "".join(
            ["%x" % (int(x, 16) ^ int(y, 16)) for (x, y) in zip(a, b[: len(a)])]
        )
        return int("0x" + res, 0)

これにより、次の出力が得られます。

1C2 ^ ABC =  2942
2FF ^ 78B =  1396
29A ^ 90C =  2966
10C ^ 24B =  839
BAD ^ 432 =  3999
54F ^ 123 =  1132

上記のソリューションでは、指定された文字の Unicode コードを表す数値を返す ord() を使用する代わりに、コードの変更内容を検査したときに正しい出力を表示するように元の関数に修正が加えられました。

パラメータが文字列の 1つと 16 である int を使用し、16 進数に対応する数値の基数を参照します。

解決策 2

def strxor(a, b):
    if len(a) > len(b):
        res = "%x" % (int(a[: len(b)], 16) ^ int(b, 16))
        return int("0x" + res, 0)

    else:
        res = "%x" % (int(a, 16) ^ int(b[: len(a)], 16))
        return int("0x" + res, 0)

これにより、次の出力が得られます。

1C2 ^ ABC =  2942
2FF ^ 78B =  1396
29A ^ 90C =  2966
10C ^ 24B =  839
BAD ^ 432 =  3999
54F ^ 123 =  1132

この方法は、for ループと zip に依存しません。 ランタイムと全体的な実行時間に関しては、対応するものよりもはるかに高速です。

著者: Salman Mehmood
Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn

関連記事 - Python Hex