好吧……让我改一下这个问题……
如何在不使用除法或强制转换为双倍的情况下获得整数的 16 分之一......
int res = (ref * frac) >> 4
(但有点担心溢出。ref 和 frac 能有多大?如果它可能溢出,先转换为更长的整数类型)
在任何此类操作中,先乘后除是有意义的。现在,如果您的操作数是整数并且您使用的是可编译语言(例如 C),请使用 shr 4 而不是 /16 - 这将节省一些处理器周期。
假设这里的所有内容都是整数,任何值得优化的编译器都会注意到 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