Сохраняющий знак модульное расстояние

Я ищу оператора модуля Mod(a,b,m) такой что:

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

Таким образом, оператор избегает пути 4-прыжка между 2 и 6 и вместо этого объезжает путь длиной 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;
}

3

Решение

Вы можете использовать способ, которым стандартная функция по модулю обрабатывает отрицательные числа, чтобы заставить ее решать, в каком направлении идти:

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

Другие решения

Функция остатка математической библиотеки, как следует из ее названия, возвращает остаток от деления первого аргумента на второй. В отличие от fmod он возвращает результат со знаком, и, действительно, остаток (a, d) является наименьшим числом r по абсолютной величине, так что a-r является целым кратным числа d.
То, что вы хотите, это применяется к б-а, то есть:

double  ModDist( double a, double b, double m)
{ return remainder( b-a, m);
}
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);
}
0
По вопросам рекламы [email protected]