简体   繁体   English

在 360 度以上的列表中查找最接近的值

[英]Find closest value in a list over 360 degrees

I have a long list of numbers that contains measured angles .我有一长串包含测量角度的数字。 The basic idea is that it looks something like this:基本思想是它看起来像这样:

var list = new List<double>() {352.9, 354.9, 356.9, 359, 1, 3.1, 5.9};

I am looking for a way to obtain the nearest upper and lower value when I specify some value x .当我指定某个值x时,我正在寻找一种方法来获取最近的上限值和下限值。 So for example if x = 354.6 , I want the upper value to be x_up = 354.9 and the lower value to be x_low = 352.9 .因此,例如,如果x = 354.6 ,我希望上限值为x_up = 354.9 ,下限值为x_low = 352.9 I though about using this method , but it does not taking into account that circle angles follow a modulo system .我虽然使用这种方法,但它没有考虑到圆角遵循模系统

When x = 0.2 , I want x_up = 1 and x_low = 359 .x = 0.2时,我想要x_up = 1x_low = 359

Any ideas on how I can implement this?关于如何实现这一点的任何想法?

Please, note that floating point types ( double , float ) support remainder operation % ;请注意浮点类型( doublefloat )支持余数运算% ; so you can put it as所以你可以把它当作

  using System.Linq;

  ...

  List<double> list = new() {
    352.9, 354.9, 356.9, 359, 1, 3.1, 5.9
  };

  double x = 0.2;

  // 359
  var x_low = list.MaxBy(item => ((item - x) % 360 + 360) % 360);
  // 1
  var x_up = list.MinBy(item => ((item - x) % 360 + 360) % 360);

I would highly recommend creating a Angle-type rather than using float/double to represent angles.我强烈建议创建一个角度类型,而不是使用浮点/双精度来表示角度。 This saves so much confusion when reading code since you do not have to worry about if it is in degrees or radians, and gives a nice way to gather various angle-related functionality.这在阅读代码时避免了很多混乱,因为您不必担心它是度数还是弧度,并且提供了一种收集各种与角度相关的功能的好方法。 Make it a readonly struct reduce the overhead to nearly nothing.使其成为readonly struct将开销减少到几乎为零。

This should allow you to make a function to normalize the angles:这应该允许您制作 function 来标准化角度:

private readonly double radians;
public Angle Normalized180_180{
  get{
     var Pi2 = PI * 2;
     var rad = radians;
     rad = (((rad % Pi2) + Pi2) % 360) - 180;
     return new Angle(rad);
  }
}

This should give you a angle guaranteed to be in the -180 to 180 interval, but you could adjust the code to use whatever interval you prefer.这应该为您提供一个保证在 -180 到 180 区间内的角度,但您可以调整代码以使用您喜欢的任何区间。

Then you can take the difference, (overload operators to make this simple), normalize, and select the smallest negative and smallest positive value:然后你可以取差,(重载运算符使这个简单),规范化,select 最小负值和最小正值:

var nextSmallest = myAngles.MinBy(a => {
    var diff = (targetAngle - a).Normalized180_180.Radians;
    if(diff < 0)   return double.MaxValue;
    return diff;
};

Another approach would be to normalize and sort your values, and use BinarySearch to find the position of your target value in the list, but you need to fiddle around with the returned value to get the position, and probably also some separate checks to handle edge cases, like the beginning and end of the list.另一种方法是规范化和排序您的值,并使用BinarySearch在列表中查找目标值的 position,但您需要摆弄返回值以获取 position,并且可能还需要一些单独的检查来处理边缘情况,例如列表的开头和结尾。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM