два направления от 0 до 1 в цикле - PullRequest
1 голос
/ 16 октября 2011

Это так просто, я не могу поверить, что у меня столько проблем с этим.

Для аналогии с тем, что я ищу, представьте двуручный циферблат, где вместо 12 часов было время от 0 до 1.

Обе стрелки могут указывать в любом направлении, при условии, что значения от 0 до 1, например, одна указывает вверх, а другая по диагонали вниз и влево - 0 и 0,625.

Мне нужна функция c ++ \ c #, которая с учетом позиции обеих рук и логического значения, представляющего, если требуется больший или меньший сегмент между руками, возвращает позицию на полпути между обеими руками.

Например, «0,2, 0,8, ложь» будет означать меньший сегмент между обеими руками, и ответ будет 0.

float func(float a, float b, bool side)
{
    return 0f;
}

Во многих случаях вычисление будет просто "(a + b) * 0.5", однако при пересечении 0, как в приведенном выше примере, это не так. Это также не так просто, как вставить одну ветку, как «если». Кажется, должно быть решение, намного более элегантное, чем то, которое я пробовал.

edit: я наконец-то решил это сам, см. Код ниже, кроме того, после того, как различные другие попытались решить проблему, было найдено гораздо более изящное решение.

float segment_size(float a, float b, bool side)
{
    float larger, smaller, c, d_smaller, d_larger;
    if (a > b)
    {
        smaller = b;
        larger = a;
    }
    else
    {
        smaller = a;
        larger = b;
    }
    c = larger - smaller;
    if (c > 0.5) {d_larger = c; d_smaller = 1 - c;} else {d_larger = 1 - c; d_smaller = c;}
    return side ? d_larger : d_smaller;
}

float func(float a, float b, bool side)
{
    float larger, smaller, c;
    if(a > b)
    {
        smaller = b;
        larger = a;
    }
    else
    {
        smaller = a;
        larger = b;
    }
    c = larger - smaller;
    float outf = 0, out1 = (float)((a + b) * 0.5),
    out3 = (float)(smaller - (segment_size(a, b, false) * 0.5)),
    out4 = (float)((smaller + larger) * 0.5);
    if(out4 > 0.5) {out4 -= 0.5f;} else {out4 += 0.5f;}
    if ((side == false && c <= 0.5) || (side == true && c > 0.5)) {outf = out1;}
    if (side == false && c > 0.5) {outf = out3;}
    if (side == true && c <= 0.5) {outf = out4;}
    if(outf < 0) {outf += 1;} if(outf >= 1) {outf -= 1;}
    return outf;
}

Ответы [ 3 ]

2 голосов
/ 16 октября 2011

Да, поэтому я ошибся в первый раз (вычислил длину сегмента вместо его точки деления пополам), а также во второй раз (был довольно хитрым, поэтому в итоге удалил ответ), нопотерпите меня.

Решение заключается в том, что мы говорим о круге здесь.Поэтому, если у нас есть одна точка деления пополам, мы можем получить другую, добавив к ней половину окружности круга (0,5).

предположим, что 0 <= a <1, 0 <= b <1 </p>

if(a>b) {
   hi=a;
   lo=b;
} else {
   hi=b;
   lo=a;
}

d=hi-lo;

if( (d>0.5 && greater_segment_needed) || (d<=0.5 && !greater_segment_needed)) { 
    result=lo+d/2
} else
    result=lo+d/2+0.5; //the marvels of geometry
}

if(result>1) result-=1; //handling possible overflow
return result;

Я почти уверен, что это работает.И да, я снова отредактировал его> _>

1 голос
/ 16 октября 2011

Вот моя попытка.Не проверено:)

float func(float a, float b, bool side)
{
  float seg_a = a - b;
  if (seg_a < 0) seg_a += 1;

  float seg_b = 1 - seg_a;
  float result;

  if (side && seg_a > 0.5 || !side && !(seg_a > 0.5))
    result = b + seg_a / 2;
  else
    result = a + seg_b / 2;

  if (result > 1) result -= 1;

  return result;
}
1 голос
/ 16 октября 2011

Вы правы с (a + b) / 2. Но если результат больше 0,5, это указывает на то, что это не самая короткая часть, и вам нужно рассчитать больше нуля, чтобы получить его.

Если вы рассчитываете больше нуля, представьте, что большее число отрицательно. Например, 0,8 составляет -0,2 (= a-1). И используйте то же уравнение, которое вы предложили. Так что 0,8 и 0,2 в вашем примере будут выглядеть так (-0,2 + 0,2) / 2 = 0 И наоборот для размера = true.

Источник будет выглядеть так:

float func(float a, float b, bool side)
{
    float result = (a+b)/2;

    if (result > 0.5)
        result = (a+b-1)/2;

    if (side == true)
        return result;
    else
        return result<0.5 ? result+0.5 : result -0.5;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...