在Javascript中,如何在考虑正负号的情况下获取余数而不使用模运算符(%)?

8
为了完成一份作业任务,我需要在不使用内置模运算符(%)的情况下返回num1除以num2的余数。我已经能够通过大部分测试,但是我卡在了如何处理给定数字的正负符号上。我需要保留num1的符号,并且如果num2为负数,则返回一个正数——这让我感到非常困惑... :) 如果有任何清晰的解释,将不胜感激! 我并不是要直接得到答案,只是好像我漏掉了什么显而易见的东西...也许我需要一种新的方法?
    function modulo(num1, num2) {
      if (num1 === 0) {
        return 0;
      }
      if (num2 === 0 || isNaN(num1) || isNaN(num2)) {
        return NaN;
      }
      if (num1 < num2) {
        return num1;
      }
      if (num1 > 0 && num2 > 0) {
        var counter = num1;
      while (counter >= Math.abs(num2)) {
        counter = counter - num2;
      }
      return counter;
      }
    }
    var output = modulo(25, 4);
    console.log(output); // 1

2
modulo(-25, 4)modulo(25, -4)的期望输出是什么? - Jordan Running
1
顺便提一下,在JavaScript中,余数运算符。 - Bergi
3个回答

9
如果您考虑一下计算模数的数学过程,也许就能发现如何不需要大量的情况语句来完成这个过程。相反,可以这样想,你只是在计算余数:
给定两个数字a和b,可以通过以下方式计算mod(a,b)
q = a / b;  //finding quotient (integer part only)
p = q * b;  //finding product
remainder = a - p;  //finding modulus

使用这个想法,你应该能够将它转移到 JS。你说你不是在寻找明确的答案,所以我只会说这么多! 编辑:这里是代码,如我在评论中所说,它就是我上面发布的伪代码:
function modulo(a,b){
  q = parseInt(a / b);  //finding quotient (integer part only)
  p = q * b;  //finding product
  return a - p;  //finding modulus
}

这将返回与使用百分号 % 完全相同的值。

不要仅仅从 q = a/b 中取整数部分,否则你的计算总会得到余数为零的结果。注:看起来 @jordan 删除了他的评论,但是我的回答是基于“你的计算总会得到余数为零”的理解。 - Pabs123
没问题,@Jordan。根据我的测试,它实际上会给你与“%”运算符完全相同的结果。我已经编写了代码,但如果OP不想要完整的解决方案,我不想泄露它。 - Pabs123
唉,我又犯错了。我忘记了Math.floor是向负无穷舍入,而不是0。 - Jordan Running
这是我现在的代码 - 现在我已经找到了逻辑解决方案(包括绝对值来考虑正负号),我现在也愿意接受更高效的方法。你有什么想法吗? - R. Noble
你可以使用我发布的伪代码来编写你所询问的解决方案。这是一个五行的解决方案。 - Pabs123
显示剩余4条评论

0
你可能在想得太多了。实际上,你在问题中已经阐述了解决方案:
“我需要携带num1上的任何符号,并且如果num2为负数,则返回正数。”
第二部分不准确,但我怀疑你只是说错了。当num2为负数时应返回正数,除非num1为负数。
无论如何,重要的是,如果num1为负数,则结果将为负数,否则结果将为正数。 num2的符号被丢弃。
从你写的代码开始(其他人很快就会指出这不是最简单的解决方案),修复方法是使用两个数字的绝对值计算余数,然后将num1的原始符号应用于结果。

function modulo(num1, num2) {
  var sign = num1 < 0 ? -1 : 1;
  var dividend = Math.abs(num1);
  var divisor = Math.abs(num2);

  if (dividend === 0) {
    return 0;
  }
  if (dividend === 0 || isNaN(dividend) || isNaN(divisor)) {
    return NaN;
  }
  if (dividend < divisor) {
    return sign * dividend;
  }
  
  var counter = dividend;
  while (counter >= divisor) {
    counter = counter - divisor;
  }
  return sign * counter;
}

console.log( 25 %  4, modulo( 25,  4));
console.log(-25 %  4, modulo(-25,  4));
console.log( 25 % -4, modulo( 25, -4));
console.log(-25 % -4, modulo(-25, -4));
.as-console-wrapper{min-height:100%;}


@quikst3r,我也很惊讶OP接受了这个答案,因为它本来是要作为Pabs123的答案(我点赞了)的补充,以向OP展示他们如何修改现有代码。作为初学者的作品,我个人不认为它是“可怕的解决方案”,但这只是我的看法。无论如何,感谢您的反馈。 - Jordan Running

0
这是基本公式: 被除数 = 除数 × 商 + 余数 根据这个方程式,你可以计算出余数。

也许你可以使用反引号 ` 来格式化公式,以提高可读性。 - Gregory Bleiker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接