简体   繁体   English

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

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

Seeing as modulo and integer division are closely related, you'd think it would make sense to get both values in one operation.鉴于模和 integer 除法密切相关,您会认为在一次操作中获得这两个值是有意义的。 Are there languages that have this capability?有没有具有这种能力的语言?

Follow up question: For languages that don't have this capability, is it best to compute the modulo by subtracting off the result of the division * denominator?跟进问题:对于没有这种能力的语言,最好通过减去除法 * 分母的结果来计算模数吗?

// 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;

When you use BigInteger , you can query quotient and remainder in one operation当您使用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

However, when you are calculating with integral values, it's best to trust the JIT compiler/ hotspot optimizer.但是,当您使用整数值进行计算时,最好信任 JIT 编译器/热点优化器。

Eg when I use例如当我使用

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();
}

and run test(125, 6) often enough, I get the following compiled native code with JDK 11/x86并经常运行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)

We can clearly see that the two operations, myNumber / denominator and myNumber % denominator have been fused into a single idiv instruction.我们可以清楚地看到, myNumber / denominatormyNumber % denominator这两个操作已融合到一条idiv指令中。

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

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