たとえば、2のべき乗のモジュロは次のように表現できることがわかります。
x % 2 inpower n == x & (2 inpower n - 1).
例:
x % 2 == x & 1
x % 4 == x & 3
x % 8 == x & 7
2つの数値の一般的な非べき乗についてはどうですか?
まあ言ってみれば:
x%7 ==?
たとえば、2のべき乗のモジュロは次のように表現できることがわかります。
x % 2 inpower n == x & (2 inpower n - 1).
例:
x % 2 == x & 1
x % 4 == x & 3
x % 8 == x & 7
2つの数値の一般的な非べき乗についてはどうですか?
まあ言ってみれば:
x%7 ==?
回答:
まず第一に、それを言うことは実際には正確ではありません
x % 2 == x & 1
単純な反例:x = -1
。Javaを含む多くの言語-1 % 2 == -1
。つまり、%
必ずしも従来の数学的定義のモジュロではありません。たとえば、Javaでは「剰余演算子」と呼ばれています。
ビット単位の最適化に関しては、2のべき乗のモジュロのみがビット単位の算術演算で「簡単に」実行できます。一般的に言えば、基数bのモジュロベキのみが、数値の基数b表現で「簡単に」実行できます。
たとえば、基数10では、負N
でない値の場合、N mod 10^k
最下位k
桁のみが使用されます。
(a / b) / b + a % b == a
ため)、C型の演算子の場合、aとbの整数、bはゼロ以外、およびabs(a % b) < abs(b)
同じ条件の場合です。
(a / b)
* b + a % b == a
。
これは2の累乗(多くの場合正の1のみ)でのみ機能します。これは、2進数表現で1ビットのみを「1」に設定するという固有のプロパティがあるためです。他のクラスの数値はこのプロパティを共有しないため、ほとんどのモジュラス式に対してビットごとのAND式を作成することはできません。
「%」演算子なしのモジュロ「7」
int a = x % 7;
int a = (x + x / 7) & 7;
ビットごとのand(&
バイナリで)演算子ない場合はありません。証明のスケッチ:
次のような値kがあったとしますx & k == x % (k + 1)
が、k!= 2 ^ n-1です。次に、x == kの場合、式x & k
は「正しく動作する」ように見え、結果はkになります。ここで、x == kiについて考えます。kに「0」ビットがあった場合、0より大きいiがいくつかあります。これらの位置では、kiは1ビットでしか表現できません。(たとえば、10 11(11)は、100(4)が減算されると0111(7)になる必要があります。この場合、i = 4の場合、000ビットは100になります。)kの式のビットがゼロから変化する必要がある場合気を表すために、それからx%(k + 1)を正しく計算できません。この場合、これはなければなりki、ただしビット単位のブール値を使用して、マスクを指定してその値を生成する方法はありません。
この特定のケース(mod 7)では、%7をビットごとの演算子で置き換えることができます。
// Return X%7 for X >= 0.
int mod7(int x)
{
while (x > 7) x = (x&7) + (x>>3);
return (x == 7)?0:x;
}
これは8%7 = 1であるため機能します。明らかに、このコードはおそらく単純なx%7よりも効率が悪く、読みにくくなります。