Optimization 不使用除法或强制转换将整数除以16

Optimization 不使用除法或强制转换将整数除以16,optimization,division,fractions,Optimization,Division,Fractions,好的。。。让我重新表述一下这个问题 如何在不使用除法或双精度转换的情况下获得整数的x 16分之一 int res = (ref * frac) >> 4 (但要担心一下溢出。ref和frac会有多大?如果它会溢出,请先转换为更长的整数类型)假设这里的所有内容都是int,任何值得一试的优化编译器都会注意到16是2的幂,并相应地移动frac——只要启用优化。更担心编译器无法为您完成的重大优化 如果有什么问题,你应该用括号括住ref*frac,然后进行除法,因为任何小于16的frac值都

好的。。。让我重新表述一下这个问题

如何在不使用除法或双精度转换的情况下获得整数的x 16分之一

int res = (ref * frac) >> 4

(但要担心一下溢出。ref和frac会有多大?如果它会溢出,请先转换为更长的整数类型)

假设这里的所有内容都是int,任何值得一试的优化编译器都会注意到16是2的幂,并相应地移动frac——只要启用优化。更担心编译器无法为您完成的重大优化


如果有什么问题,你应该用括号括住
ref*frac
,然后进行除法,因为任何小于16的frac值都将导致0,无论是移位还是除法。

在任何此类操作中,都应该先乘法,然后除法。现在,如果您的操作数是整数,并且您使用的是可编译语言(例如C),请使用shr 4而不是/16-这将节省一些处理器周期

我不理解约束,但是这个伪代码将(?)


您可以使用左移或右移:

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;
}
公共静态最终长除法使用乘法(int a,int b){
内部温度=b;
int计数器=0;

while(temp)frac的类型是什么?如果它是
int
,那么如果frac是2,ref的任何值res都将是0。@Jon,我会根据文本,而不是(不正确的)第一次通过的代码,我想你试过“int res=(ref>>4)*frac吗?@dwb-这将为0到15之间的ref提供0。可能不是预期的。我认为Jon工作的意思是
int res=(ref*frac)/16
。自适应是将
/16
转换为
>4
,OP可能没有使用C(etc)作为实现语言,但要求更广泛。没有特定于语言的标记。语言无关紧要,只有一位可以容纳的值的数量。如果需要,可以将真正的“编译器”称为“编译器或解释器”因为老实说,一个好的动态语言解释器应该注意到关于原始数字类型的同样的事情,IMO。只有当它能够证明值总是数字时,才是真的。如果它必须在运行时进行检查,检查的开销可能超过任何可能的优化。并且可能会因为最慢的实现而获奖。Consider frac=2,ref=MAXINT/2。它还存在其他解决方案的溢出问题。嘿,我认为整件事都是不明智的!:)没有除法的限制有现实原因吗?在我工作的平台上,除法大约比加法/减法/移位慢25倍,比乘法慢10倍。对于某些应用程序,有足够的代码在热路径中进行除法,以尝试找到替代方法。
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;
}