OKAY...この質問を言い換えさせてください...
除算や2倍のキャストを使用せずに、整数の16分の1を取得するにはどうすればよいですか。
OKAY...この質問を言い換えさせてください...
除算や2倍のキャストを使用せずに、整数の16分の1を取得するにはどうすればよいですか。
int res = (ref * frac) >> 4
(ただし、オーバーフローについては少し心配してください。refとfracはどのくらいの大きさになりますか?オーバーフローする可能性がある場合は、最初に長い整数型にキャストしてください)
このような種類の操作では、最初に乗算してから除算するのが理にかなっています。ここで、オペランドが整数で、コンパイル可能な言語(Cなど)を使用している場合は、/16の代わりにshr4を使用します。これにより、プロセッササイクルがいくらか節約されます。
ここですべてがintであると仮定すると、そのソルトに値する最適化コンパイラは、16が2の累乗であることに気付き、それに応じてfracをシフトします-最適化がオンになっている限り。コンパイラが実行できない主要な最適化についてもっと心配してください。
ref * frac
どちらかといえば、16未満のfracの値は、シフトまたは除算のいずれによっても0になるため、ブラケットしてから除算する必要があります。
左シフトまたは右シフトを使用できます。
public static final long divisionUsingMultiplication(int a, int b) {
int temp = b;
int counter = 0;
while (temp <= a) {
temp = temp<<1;
counter++;
}
a -= b<<(counter-1);
long result = (long)Math.pow(2, counter-1);
if (b <= a) result += divisionUsingMultiplication(a,b);
return result;
}
public static final long divisionUsingShift(int a, int b) {
int absA = Math.abs(a);
int absB = Math.abs(b);
int x, y, counter;
long result = 0L;
while (absA >= absB) {
x = absA >> 1;
y = absB;
counter = 1;
while (x >= y) {
y <<= 1;
counter <<= 1;
}
absA -= y;
result += counter;
}
return (a>0&&b>0 || a<0&&b<0)?result:-result;
}
私は制約を理解していませんが、この疑似コードは切り上げます (?):
res = 0
ref= 10
frac = 2
denominator = 16
temp = frac * ref
while temp > 0
temp -= denominator
res += 1
repeat
echo res