3

我正在寻找一个模数运算符Mod(a,b,m),例如:

  • Mod(2,6,7)=-3
  • Mod(6,2,7)=3

也就是说,操作员避开 2 和 6 之间的 4 跳路径,而是通过长度为 3 的路径绕圈。如果您离开a并前往 ,答案将保留路径方向b

以下代码计算了这一点,但几乎可以肯定有更好的方法。

#include <iostream>
#include <cmath>

double absmin(double a, double b){
  if(std::abs(a)<std::abs(b))
    return a;
  else
    return b;
}

double ModDist(double src, double dest, double m){
  if(dest<src)
    return absmin(dest+m-src, dest-src);
  else
    return absmin(dest-src, dest-m-src);
}

int main(){
  std::cout<<ModDist(2,6,7)<<std::endl;
  std::cout<<ModDist(6,2,7)<<std::endl;
}
4

3 回答 3

1

顾名思义,数学库函数余数返回第一个参数除以第二个参数的余数。与 fmod 不同,它返回一个有符号的结果,实际上,residual(a,d) 是绝对值的最小数字 r,因此 ar 是 d 的整数倍。你想要的是这适用于 ba,即:

double  ModDist( double a, double b, double m)
{ return remainder( b-a, m);
}
于 2016-05-12T07:52:11.310 回答
1

如果您的直接距离小于距离的一半,则另一种方式不会做得更好。相反,如果它大于距离的一半,则通过改变方向做得更好。

这假设0<=src,dest<=m

double ModDist(double src, double dest, double m){
  double directDistance = dest - src;
  if(abs(directDistance)<m/2)
    return directDistance;
  return -(m - abs(directDistance))*sgn(directDistance);
}
于 2016-05-12T03:23:54.823 回答
0

您可以使用标准模函数处理负数的方式来决定进入哪个方向:

#include <cmath>
double ModDist(double s, double d, double m) {
    return std::fmod((d - s) * 2, m) + s - d;
}
于 2016-05-12T04:11:21.980 回答