3

我正在尝试解决我在学位方面遇到的问题。我有一个角度列表的数据,以标准度数表示法 - 例如26度。

通常在处理角度时,如果一个角度超过 360 度,则该角度继续围绕并有效地“重置”——即角度“重新开始”,例如 357 度、358 度、359 度、0 度、1 度等。我想要发生的是继续增加的度数 - 即 357 度、358 度、359 度、360 度、361 度等。我想修改我的数据,以便在其中包含转换后的数据。

当数字接近 0 度限制时,我希望它们变为负数——即 3 度、2 度、1 度、0 度、-1 度、-2 度等。

对于 360 度的倍数(正数和负数),我希望度数继续,例如 720 度等。

关于采取什么方法的任何建议?毫无疑问,有一种令人沮丧的简单方法可以做到这一点,但我目前的解决方案至少可以说是笨拙的......!迄今为止我最好的尝试是查看角度 n 和角度 n - 1 之间的百分比差异。如果这是一个很大的差异 - 例如 > 60% - 那么这需要通过添加或减去 360 度来修改当前值,取决于先前的角度值。也就是说,如果前一个角度为负,则减去 360,如果前一个角度为正,则加 360。

有什么改进的建议吗?有什么改进吗?

4

6 回答 6

2

您在谈论的是一种unwrap算法,它可以泛化(不特定于数字 360 ......您可以使用 m=2*pi 的弧度来实现)。这是javascript中的一个:

/*  symmetric modulo: 
 *  y = smod(x,m) = x+k*m where k is an integer,
 *  and y is always in the range [-0.5,0.5)*m
 */
function smod(x, m)
{
  return x-((Math.floor(x/m + 0.5))*m);
}

/*  unwrap:
 *  for all i, y[i] = x[i] + k*m where k is an integer,
 *  and for i > 0, the increment y[i]-y[i-1] is in the
 *  range [-0.5,0.5)*m as in smod().
 *
 *  the "init" parameter is optional (default to 0)
 *  and specifies the starting value for the unwrap state.
 */ 

function unwrap(x, m, init)
{
  var yi = init || 0;
  var y = [];
  for (i = 0; i < x.length; ++i)
  {
     yi += smod(x[i]-yi, m);
     y[i] = yi;
  }    
  return y;
}

这是一个示例输出:

js>unwrap([100, 200, 348, 359, 23, 37, 46, 10, 350, 190], 360)
100,200,348,359,383,397,406,370,350,190

另一个 m=100:

js>unwrap([99,1,7,60,80,22,30,20,90,88,61,23,2,87,50,12], 100, 1000)
999,1001,1007,960,980,1022,1030,1020,990,988,961,923,902,887,850,812

仅供参考:在 C/Java/等中。位扩展存在类似的算法,其中输入为 16 位,输出为 32 位,环绕模数 m = 65536 = 输入值的跨度。您不需要“smod”函数,只需使用签名数学:

typedef short int16_t;
typedef long  int32_t;
// do typedefs as appropriate on your CPU

int32_t unwrap_extend(int32_t prev, int16_t input)
{
  int16_t delta = input - prev;
  return prev + delta;
}
于 2010-03-24T14:11:08.640 回答
1

您可以继续加/减所有度数,然后在 360 的最终结果上使用 MODULUS 运算符。这将为您提供剩余的度数。

于 2010-03-23T14:01:25.853 回答
1

使用某种方法获取每个角度与前一个角度的差异,以确保在两个方向上穿过 0/360 时获得正确的符号。然后将此差异添加到不翻转的运行总计中。

于 2010-03-23T14:04:18.657 回答
0

此 C 程序从标准输入获取 0 到 359 度范围内的角度列表,并通过累积角度的变化将无界值打印到标准输出。通过假设每个输入的最大可能角度变化来检测环绕。

#include <stdio.h>
#include <stdlib.h>

int
main()
{
    const float MAX_DELTA = 180.f;          /* highest expected change */
    float previous, next, delta, output;

    /* set the initial value */
    if (EOF == scanf("%f", &next))
        exit(0);   
    previous = next;
    output = previous;

    do {
        /* calculate the change in angle and adjust if too big */
        delta = next - previous;
        if (MAX_DELTA < delta)
            delta -= 360.f;
        else if (-MAX_DELTA > delta)
            delta += 360.f;

        /* accumlate the changes without wrap-around */
        output += delta;
        printf("%f\n", output);

        /* store the value for calculating the next delta */
        previous = next;

        /* read angle values until end of file is reached */
    } while (EOF != scanf("%f", &next));

    exit(0);
}
于 2010-03-23T15:03:05.223 回答
0

使用模函数

static inline float GetAbsoluteModulous(float input ,float devisor )
{
    double output = (devisor==0)?input:fmod(input, devisor);
    return (output>0)?output:devisor+output;
} 

angle = GetAbsoluteModulous(angle,360);
于 2010-03-24T12:04:10.953 回答
0

如果我正确理解了这个问题,这可能会起作用:

int prev=[first data piece in data set]
int total=prev
foreach data in [the rest of the data set]
    total+=data-prev
    prev=data
    data=total

然后在循环结束时,数据集将包含所有数据,按照您指定的方式添加。

所以基本上循环遍历数据集,并将差异添加到运行总数中。当您迭代时,运行总计将成为每个数据片段。

于 2010-03-23T14:03:53.837 回答