【问题标题】:A sign preserving modular distance符号保持模距离
【发布时间】:2016-05-12 02:08:10
【问题描述】:

我正在寻找一个模数运算符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;
}

【问题讨论】:

  • 建议删除C标签。
  • Code Review 上可能更好
  • 也许您应该展示您对模数为 7 的其他示例的期望;另外,您对ModDist(2,5,6)ModDist(5,2,6) 有什么期望,为什么?
  • @JonathanLeffler,这是一个很好的边缘案例,我对此没有特别的期望,因为它的距离相同。
  • @chux:我已经更改了一些标签,但是 C/C++ 在这里都很好,因为感兴趣的操作在两种语言之间进行了很少的修改。

标签: c++ c algorithm math mod


【解决方案1】:

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

假设0&lt;=src,dest&lt;=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);
}

【讨论】:

    【解决方案2】:

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

    double  ModDist( double a, double b, double m)
    { return remainder( b-a, m);
    }
    

    【讨论】:

    • 与其只是随意粘贴一堆代码,不如解释一下你做了什么以及为什么。这样,OP 和任何有相同问题的未来读者实际上都可以从您的答案中学到一些东西,而不是仅仅复制/粘贴它并在明天再次提出相同的问题。
    • 在查找 fmod() 时,我看到了剩余()作为替代方案,但我确信我找到了最简单的方法,我没有研究它。 :-)
    【解决方案3】:

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

    #include <cmath>
    double ModDist(double s, double d, double m) {
        return std::fmod((d - s) * 2, m) + s - d;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-07-22
      • 2021-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多