繁体   English   中英

获得模数和除法结果的最佳方法?

[英]Best way to get both modulo and result of division?

鉴于模和 integer 除法密切相关,您会认为在一次操作中获得这两个值是有意义的。 有没有具有这种能力的语言?

跟进问题:对于没有这种能力的语言,最好通过减去除法 * 分母的结果来计算模数吗?

// In java, if I want both values I need to do this:
int myNumber = 125;
int denominator = 6;

int division = myNumber / denominator;  // 20
int modulo1   = myNumber % denominator;  // 5

// Follow up: Is this a more efficient way to compute the modulo?
int modulo2 = myNumber - division * denominator;

当您使用BigInteger时,您可以一次查询商和余数

BigInteger myNumber = BigInteger.valueOf(125), denominator = BigInteger.valueOf(6);
BigInteger[] result = myNumber.divideAndRemainder(denominator);
System.out.println(myNumber + " / " + denominator + " = " + result[0]);
System.out.println(myNumber + " % " + denominator + " = " + result[1]);
125 / 6 = 20
125 % 6 = 5

但是,当您使用整数值进行计算时,最好信任 JIT 编译器/热点优化器。

例如当我使用

static void test(int myNumber, int denominator) {
    int division = myNumber / denominator;  // 20
    int modulo1   = myNumber % denominator;  // 5

    // prevent over-optimization
    if(division != 20 || modulo1 != 5) throw new AssertionError();
}

并经常运行test(125, 6) ,我得到以下使用 JDK 11/x86 编译的本机代码

  0x0000029f3ef97b2c: mov     eax,edx
  0x0000029f3ef97b2e: test    r8d,r8d
  0x0000029f3ef97b31: je      29f3ef97b63h      ;*idiv {reexecute=0 rethrow=0 return_oop=0}
                                                ; - SO71326541::test@2 (line 23)

  0x0000029f3ef97b33: cmp     eax,80000000h
  0x0000029f3ef97b38: jne     29f3ef97b42h
  0x0000029f3ef97b3a: xor     edx,edx
  0x0000029f3ef97b3c: cmp     r8d,0ffffffffh
  0x0000029f3ef97b40: je      29f3ef97b46h
  0x0000029f3ef97b42: cdq
  0x0000029f3ef97b43: idiv    eax,r8d
  0x0000029f3ef97b46: mov     r11d,edx
  0x0000029f3ef97b49: cmp     eax,14h
  0x0000029f3ef97b4c: jne     29f3ef97b72h      ;*if_icmpne {reexecute=0 rethrow=0 return_oop=0}
                                                ; - SO71326541::test@11 (line 27)

  0x0000029f3ef97b4e: cmp     edx,5h
  0x0000029f3ef97b51: jne     29f3ef97b86h      ;*if_icmpeq {reexecute=0 rethrow=0 return_oop=0}
                                                ; - SO71326541::test@16 (line 27)

我们可以清楚地看到, myNumber / denominatormyNumber % denominator这两个操作已融合到一条idiv指令中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM