Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# PointF[]数组中的最大值和最小值_C#_Arrays_Floating Point_Max - Fatal编程技术网

C# PointF[]数组中的最大值和最小值

C# PointF[]数组中的最大值和最小值,c#,arrays,floating-point,max,C#,Arrays,Floating Point,Max,我有一个PointF数组,我想用它来用Graphics.DrawCurve方法绘制曲线 为了做到这一点,我现在需要最大和最小的X和Y,以便我可以缩放我的位图图像框正确 如何在PointF数组中找到X&Y的最大值和最小值 我想出了这个主意,但我不确定这是否是最好的方法 //Find the max value on X axis (Time) and Y axis (Current) float xMax = 0; float yMax = 0; foreach

我有一个PointF数组,我想用它来用Graphics.DrawCurve方法绘制曲线

为了做到这一点,我现在需要最大和最小的X和Y,以便我可以缩放我的位图图像框正确

如何在PointF数组中找到X&Y的最大值和最小值

我想出了这个主意,但我不确定这是否是最好的方法

    //Find the max value on X axis (Time) and Y axis (Current)
    float xMax = 0;
    float yMax = 0;

    foreach (PointF point in points)
    {
        if (point.X > xMax)
        {
            xMax = point.X;
        }

        if (point.Y > yMax)
        {
            yMax = point.Y;
        }
    }

您需要迭代数组中的所有元素,并根据边界框测试每个元素,当当前项位于边界框之外时,增加边界框。像这样:

Point 
  min = first item in array, 
  max = first item in array;

foreach (item in array of points)
{
  min.x = Math.Min (min.x, item.x)
  min.y = Math.Min (min.y, item.y)
  max.x = Math.Max (max.x, item.x)
  max.y = Math.Max (max.y, item.y)
}


(min,max) are now the opposite corners of an axis aligned bounding box
编辑:您的想法是对的,但是有一个.NETFramework API来进行最小/最大测试:Math.min和Math.max。除非有关于点阵列的其他信息可用于减少测试次数,否则必须测试阵列中的每个点。不幸的是,那里没有捷径。我想知道JIT编译器是否足够聪明,可以为此使用SIMD


此外,如果数组中的所有点都小于零,则使用值0初始化可能会导致错误。

您需要迭代数组中的所有元素,并根据边界框测试每个元素,当当前项位于边界框之外时,增加边界框。像这样:

Point 
  min = first item in array, 
  max = first item in array;

foreach (item in array of points)
{
  min.x = Math.Min (min.x, item.x)
  min.y = Math.Min (min.y, item.y)
  max.x = Math.Max (max.x, item.x)
  max.y = Math.Max (max.y, item.y)
}


(min,max) are now the opposite corners of an axis aligned bounding box
编辑:您的想法是对的,但是有一个.NETFramework API来进行最小/最大测试:Math.min和Math.max。除非有关于点阵列的其他信息可用于减少测试次数,否则必须测试阵列中的每个点。不幸的是,那里没有捷径。我想知道JIT编译器是否足够聪明,可以为此使用SIMD


此外,如果数组中的所有点都小于零,则使用值0初始化可能会导致错误。

您的代码不好。如果您有点2、4和3、1,那么xMax将是3,yMax将是4,这不是一个点。

您的代码不好。如果有点2、4和3、1,那么xMax将是3,yMax将是4,这不是一个点。

如果找到最小左上点和最大右下点,则可以计算图形的大小

var minX = points.Min().x;
var minY = points.Min().y;
var maxX = points.Max().x;
var maxY = points.Max().y;
首先,您需要一种比较点值的方法-如果点类结构?实现IComparable您已经准备好了,否则您可能需要编写一个自定义IComparaler类

接下来,您可以在IEnumerable上编写一个简单的扩展方法,以从集合中获取最小值或最大值:

static class ExtensionsClass
{
    /// <summary>
    /// Returns the mimimum value within the collection.
    /// </summary>
    static public T Min(this IEnumerable<T> values) where T : IComparable<T>
    {
        T min = values.First();

        foreach(T item in values)
        {
            if (item.CompareTo(min) < 0)
                min = item;
        }

        return min;
    }

    /// <summary>
    /// Returns the maximum value within the collection.
    /// </summary>
    static public T Max(this IEnumerable<T> values) where T : IComparable<T>
    {
        T max= values.First();

        foreach(T item in values)
        {
            if (item.CompareTo(min) > 0)
                max= item;
        }

        return max;
    }
}

如果找到最小左上角点和最大右下角点,则可以计算图形的大小

var minX = points.Min().x;
var minY = points.Min().y;
var maxX = points.Max().x;
var maxY = points.Max().y;
首先,您需要一种比较点值的方法-如果点类结构?实现IComparable您已经准备好了,否则您可能需要编写一个自定义IComparaler类

接下来,您可以在IEnumerable上编写一个简单的扩展方法,以从集合中获取最小值或最大值:

static class ExtensionsClass
{
    /// <summary>
    /// Returns the mimimum value within the collection.
    /// </summary>
    static public T Min(this IEnumerable<T> values) where T : IComparable<T>
    {
        T min = values.First();

        foreach(T item in values)
        {
            if (item.CompareTo(min) < 0)
                min = item;
        }

        return min;
    }

    /// <summary>
    /// Returns the maximum value within the collection.
    /// </summary>
    static public T Max(this IEnumerable<T> values) where T : IComparable<T>
    {
        T max= values.First();

        foreach(T item in values)
        {
            if (item.CompareTo(min) > 0)
                max= item;
        }

        return max;
    }
}
通过使用,这些操作可以大大加速

  void MinMax(int[] a, out int minimum, out int maximum) {
  int simdLength = Vector<int>.Length;
  Vector<int> vmin = new Vector<int>(int.MaxValue);
  Vector<int> vmax = new Vector<int>(int.MinValue);
  for (int i = 0; i < a.Length; i += simdLength) {
      Vector<int> va = new Vector<int>(a, i);
      Vector<int> vLessThan = Vector.LessThan(va, vmin);
      vmin = Vector.ConditionalSelect(vLessThan, va, vmin);
      Vector<int> vGreaterThan = Vector.GreaterThan(va, vmax);
      vmax = Vector.ConditionalSelect(vGreaterThan, va, vmax);
  }
  int min = int.MaxValue, max = int.MinValue;
  for (int i = 0; i < simdLength; ++i) {
      min = Math.Min(min, vmin[i]);
      max = Math.Max(max, vmax[i]);
  }
  minimum = min;
  maximum = max;
}
显然,用PointF数组替换int数组。本质上,SIMD能够在每次循环迭代中处理4-8项的最小值和最大值。理论上,这将根据您的CPU提供4-8倍的加速比。使用支持AVX2的CPU可以提供最快的性能提升

来源:

通过使用,这些操作可以大大加速

  void MinMax(int[] a, out int minimum, out int maximum) {
  int simdLength = Vector<int>.Length;
  Vector<int> vmin = new Vector<int>(int.MaxValue);
  Vector<int> vmax = new Vector<int>(int.MinValue);
  for (int i = 0; i < a.Length; i += simdLength) {
      Vector<int> va = new Vector<int>(a, i);
      Vector<int> vLessThan = Vector.LessThan(va, vmin);
      vmin = Vector.ConditionalSelect(vLessThan, va, vmin);
      Vector<int> vGreaterThan = Vector.GreaterThan(va, vmax);
      vmax = Vector.ConditionalSelect(vGreaterThan, va, vmax);
  }
  int min = int.MaxValue, max = int.MinValue;
  for (int i = 0; i < simdLength; ++i) {
      min = Math.Min(min, vmin[i]);
      max = Math.Max(max, vmax[i]);
  }
  minimum = min;
  maximum = max;
}
显然,用PointF数组替换int数组。本质上,SIMD能够在每次循环迭代中处理4-8项的最小值和最大值。理论上,这将根据您的CPU提供4-8倍的加速比。使用支持AVX2的CPU可以提供最快的性能提升


来源:

如果您使用TDD,则很容易编写测试来探索算法的正确性,这可能是重复的。作为奖励,你可以得到回归测试,如果你想改变建议的话,回归测试非常有用。@Moo Juice我不同意你的最后一票,我已经看到了那篇文章,它对于像我这样的乞丐来说太复杂了,现在帮不了我。@Sean87,很公平如果您使用TDD,则很容易编写测试来探索算法的正确性。作为奖励,你可以得到回归测试,如果你想改变建议的话,回归测试非常有用。@Moo Juice我不同意你的最后一票,我已经看到了那篇文章,它对于像我这样的乞丐来说太复杂了,现在帮不了我。@Sean87,很公平我想他的想法是正确的。要绘制图形,最大x/y值不必来自同一点。所以你的答案不正确。我想他的想法是正确的。要绘制图形,最大x/y值不必来自同一点。所以你的答案不正确。谢谢你的提示!在X轴上,我处理的是时间,所以它总是一个正数。但是对于Y轴,它将变得更复杂,因为我必须检查最大正Y和最大最小Y,abs方法可以派上用场。谢谢提示!在X轴上,我处理的是时间,所以它是
总是一个正数。但是对于Y轴,它将更加复杂,因为我必须检查最大正Y和最大最小Y,abs方法可以派上用场。使用这个解决方案,你必须在数组上迭代4次。根据阵列的大小,这可能是一个问题。@M4N您不必这样做,我的示例中的最后4行可以轻松优化为2次迭代。进一步优化到1次迭代将需要更多的工作,但如果被确定为性能瓶颈,则仍然微不足道。使用此解决方案,您将不得不在阵列上迭代4次。根据阵列的大小,这可能是一个问题。@M4N您不必这样做,我的示例中的最后4行可以轻松优化为2次迭代。进一步优化到1次迭代将需要更多的工作,但如果确定为性能瓶颈,则仍然是微不足道的