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

发布于 2025-01-11 05:39:47 字数 475 浏览 0 评论 0原文

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

后续问题:对于不具备此功能的语言,是否最好通过减去除法 * 分母的结果来计算模数?

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

Seeing as modulo and integer division are closely related, you'd think it would make sense to get both values in one operation. 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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

慵挽 2025-01-18 05:39:47

使用 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 / 分母myNumber % denominator 已融合到单个 idiv 指令中。

When you use BigInteger, you can query quotient and remainder in one operation

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.

E.g. 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

  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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文