我试图拥有"范围"最后X秒的指南针标题。示例:在最后一分钟,我的标题在指南针上介于120deg和140deg之间。够容易吧?我有一个带有指南针标题的数组在这段时间内,比如每秒读一次。
[ 125, 122, 120, 125, 130, 139, 140, 138 ]
我可以使用最小值和最大值,然后你就可以了。我的范围是从120到140。
除此之外并非如此简单。举例来说,如果我的标题从10度转移到350度(即#34;通过"通过北方,改变-20度。
现在我的数组看起来像这样:
[ 9, 10, 6, 3, 358, 355, 350, 353 ]
现在Min 3且最大358 ,这不是我需要的:(我正在寻找最多"右手"(顺时针)值,大多数"左手"(逆时针)值。
我能想到的唯一方法是找到沿着圆圈的最大弧线,其中不包括阵列中的任何值,但我甚至不知道如何做到这一点。
非常感谢任何帮助!
答案 0 :(得分:0)
总结一下这个问题,听起来你想要找到以下两个方面:
所以在你的第二个例子中,9和10只相差1°,但它们并不包含所有其他读数。相反,顺时针方向从10到9将包含所有其他读数,但它们在该方向上相隔359°,因此它们不是最接近的。
在这种情况下,我不确定使用最小和最大读数是否有帮助。相反,我建议对所有读数进行排序。然后,您可以更轻松地检查上面指定的两个条件。
以下是您提供的第二个示例,按升序排序:
[ 3, 6, 9, 10, 350, 353, 355, 358 ]
如果我们从头开始,我们知道从阅读3到阅读358将包含所有其他读数,但它们相距358 - 3 = 355°
。我们可以继续逐步扫描结果。请注意,一旦我们绕圈,我们必须添加360以正确计算分离度。
[ 3, 6, 9, 10, 350, 353, 355, 358 ]
*--------------------------> 358 - 3 = 355° separation
[ 3, 6, 9, 10, 350, 353, 355, 358 ]
-> *----------------------------- (360 + 3) - 6 = 357° separation
[ 3, 6, 9, 10, 350, 353, 355, 358 ]
----> *-------------------------- (360 + 6) - 9 = 357° separation
[ 3, 6, 9, 10, 350, 353, 355, 358 ]
-------> *----------------------- (360 + 9) - 10 = 359° separation
[ 3, 6, 9, 10, 350, 353, 355, 358 ]
----------> *------------------- (360 + 10) - 350 = 20° separation
[ 3, 6, 9, 10, 350, 353, 355, 358 ]
--------------> *-------------- (360 + 350) - 353 = 357° separation
[ 3, 6, 9, 10, 350, 353, 355, 358 ]
-------------------> *--------- (360 + 353) - 355 = 358° separation
[ 3, 6, 9, 10, 350, 353, 355, 358 ]
------------------------> *---- (360 + 355) - 358 = 357° separation
这是用于确定读取值的最小程度范围的伪代码算法。如果考虑到性能,肯定有一些方法可以优化。
// Somehow, we need to get our reading data into the program, sorted
// in ascending order.
// If readings are always whole numbers, you can use an int[] array
// instead of a double[] array. If we use an int[] array here, change
// the "minimumInclusiveReadingRange" variable below to be an int too.
double[] readings = populateAndSortReadingsArray();
if (readings.length == 0)
{
// Handle case where no readings are provided. Show a warning,
// throw an error, or whatever the requirement is.
}
else
{
// We want to track the endpoints of the smallest inclusive range.
// These values will be overwritten each time a better range is found.
int minimumInclusiveEndpointIndex1;
int minimumInclusiveEndpointIndex2;
double minimumInclusiveReadingRange; // This is convenient, but not necessary.
// We could determine it using the
// endpoint indices instead.
// Check the range of the greatest and least readings first. Since
// the readings are sorted, the greatest reading is the last element.
// The least reading is the first element.
minimumInclusiveReadingRange = readings[array.length - 1] - readings[0];
minimumInclusiveEndpointIndex1 = 0;
minimumInclusiveEndpointIndex2 = array.length - 1;
// Potential to skip some processing. If the ends are 180 or less
// degrees apart, they represent the minimum inclusive reading range.
// The for loop below could be skipped.
for (int i = 1; i < array.length; i++)
{
if ((360.0 + readings[i-1]) - readings[i] < minimumInclusiveReadingRange)
{
minimumInclusiveReadingRange = (360.0 + readings[i-1]) - readings[i];
minimumInclusiveEndpointIndex1 = i;
minimumInclusiveEndpointIndex2 = i - 1;
}
}
// Most likely, there will be some different readings, but there is an
// edge case of all readings being the same:
if (minimumInclusiveReadingRange == 0.0)
{
print("All readings were the same: " + readings[0]);
}
else
{
print("The range of compass readings was: " + minimumInclusiveReadingRange +
" spanning from " + readings[minimumInclusiveEndpointIndex1] +
" to " + readings[minimumInclusiveEndpointIndex2]);
}
}
这个伪代码算法没有覆盖一个额外的边缘情况,并且存在多个最小包含范围的情况......
如果需要报告创建最小包含范围的每对可能端点,则此边缘情况会稍微增加逻辑的复杂性。如果重要的是确定最小包含范围的值,或者只报告一对代表最小包含范围就足够了,那么提供的算法就足够了。