【问题标题】:How can I remove a modulo out of my math operation?如何从我的数学运算中删除模数?
【发布时间】:2013-10-15 19:18:08
【问题描述】:

我的教授不喜欢使用模数,因为它不够高效,但我不确定如何使用逻辑运算符或其他东西获得相同的答案。有人可以帮我解决这个问题吗?

j = (j + 1) % a.length;

【问题讨论】:

  • 叹息教授
  • 我同意。教授的担心是没有根据的。除了专门的应用程序外,在许多语言中,取模通常比条件跳转快,即使速度较慢,这种微优化仍然比磁盘访问或网络延迟慢几个数量级。
  • 转学。或者当有新教授时放弃课程并参加。 Modulo 可以提供一些最优雅、最高效、最易读的代码。
  • @Cruncher 或与教授交谈并参考此处的讨论和其他证据。
  • 有没有关于 j 和 a.length 的假设?否则我非常怀疑是否有人会找到更快的代码。因为如果有的话; java会做到的

标签: java modulo


【解决方案1】:

这应该可以解决问题。

 int k = a.length;
 int d = (j+1)/k;
 j = (j+1) - d*k

【讨论】:

  • 这个解决方案的问题是,在大多数系统上,/ 和 % 无论如何都应该是相同的操作,只是存储结果的不同部分,因此它实际上根本不会改变速度。
  • 所以,如果教授讨厌一个模,他或她真的会讨厌一个除法加一乘法。
  • 大概这会比 % 慢?没关系,这都是荒谬的微优化
【解决方案2】:

我认为没有模数的唯一方法仍然不是很好:

j = (++j < a.length)? j : (j - a.length);

或者,为了提高可读性:

j++;
j = (j < a.length)? j : (j - a.length);

j++;
if (j >= a.length) {
    j -= a.length;
}

另外,我不完全确定 Java 如何处理循环预测,但至少在 C 中,如果可读性较差,以下内容的速度会稍好一些,因为一般假设是 if 语句的参数会是真的,而且j &lt; a.length 往往不是(除非a.length &lt;= 2,这似乎不太可能。)

j++;
if(j < a.length) {
}
else {
    j -= a.length;
}

如果j 的初始值超出0a.length 的范围(包括-不包括),那么唯一的解决方案要么使用模数,要么使用除法,它们是相同的运算,速度相同,或者一个减法循环,它基本上可以完成与非常旧的处理器上的模数相同的事情,这比我所知道的任何当前处理器上的内置模数运算都要慢。

【讨论】:

  • 抱歉,试图阅读一个语句,在该语句中你使用了一个变量的预增量,你在同一个语句的其他地方分配和使用的变量让我头疼。即使它有效。除非您使用 APL 编程,否则将所有内容都塞进一行是没有意义的。 :)
  • @ajb 我可以承担责任,这是我的想法。当时似乎是个好主意,但我明白你的意思。
  • 我担心我可能会遗漏一些东西,但是如果 j 很大,比如 1000000,该怎么办?并且 a.length 很小,比如 5
  • j 有多大并不重要,重要的是它与a.length 相比如何。这(与大多数其他解决方案一样)假设j 始终保持在0a.length(包括-不包括)之间,因为如果不使用 divmod 操作或实施这样的操作就无法做到这一点否则 - (甚至更低效)。
【解决方案3】:

你可以这样做:

j = j + 1;
if (j >= a.length) {
    j = j - a.length; // assumes j was less than length before increment
}

@ajp 提出了另一种实际上可以正常工作的解决方案。

j = j + 1;
if (j >= a.length) { // assumes j was less than length before increment
    j = 0; 
}

如果我正在编写代码,请以这种方式编写,以防万一。它几乎没有额外的开销,并且消除了“假设”

j = j + 1;
while (j >= a.length) {
    j = j - a.length;
}

当然,% 也是一个不错的方法。除非是你的教授。

这可能比除法/模运算更快或更慢,具体取决于跳转的成本(以及对指令管道/前瞻的任何影响)和整数除法指令的效率。

旧处理器可能会在跳跃方面做得更好。更现代的有鸿沟。

【讨论】:

  • 我建议您在有时间的时候运行一些基准测试,以加强您的回答。
  • 注意:如果 j 在增量之前“小于”长度,则您的条件将始终失败。您的意思可能是“假设 j 是 if (j >= a.length)。
  • 另外:如果假设是正确的,那么你也可以说if (j &gt;= a.length) j = 0;。有时这会让发生的事情更清楚。
  • @LeeMeador 喜欢 6502 的吗?我曾经为那些编写汇编语言。他们没有除法指令。
  • 如果这比使用模数要慢,你可能不会比你拥有的更好,除非你用某个特定的数字做模数(例如 2 的幂。)
【解决方案4】:

想想你在这里做什么。你本质上是在说:

if j + 1 is smaller than a.length, set j to j + 1
otherwise, we set j to a value smaller than a.length

这个伪代码应该给你一个非常清晰的解决方案提示。

【讨论】:

  • “小于a.length的值”是什么意思
  • @RichardTingle 我认为他的意思是 a value that is a.length less than j 或 a.length 小于 j 的某个因子,因此该值小于 a.length
猜你喜欢
  • 1970-01-01
  • 2022-08-15
  • 2020-10-28
  • 2011-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-24
相关资源
最近更新 更多