【问题标题】:Minimum size that matches aspect ratio匹配纵横比的最小尺寸
【发布时间】:2011-03-31 12:38:08
【问题描述】:

我需要找到纵横比恰好(或在 0.001 以内)某个值的 最小 尺寸。是否有任何快速的数学技巧或框架技巧可以做到这一点?

这是我在 O(n^2) 中运行的当前 bad 想法的伪代码:

epsilon = 0.001;

from x = 1 to MAX_X
{
  from y = 1 to MAX_Y
  {
    if(Abs(x / y - aspectRatio) <= epsilon)
    {
      return new Size(x, y);
    }
  }
}
return Size.Empty;

【问题讨论】:

  • 为什么是Abs(..)?这个数字永远不会是负数...
  • 基本上你想找到十进制值的最小分数(=最小纵横比)。我确定这是一道 GCSE 数学题,但我现在不记得是怎么回事了,哈哈
  • 对于初学者,我认为您的伪代码是错误的,除非我误解了它,它绝不是指纵横比值..
  • 你正在做的事,再看一遍,就是找到一个等于 0.001 的分数(即,像 x = 1 和 y = 1000)。但是根据您的描述,我会说您有一个比率,例如 3.8 并找到等于该比率的 x 和 y,即 x = 38 和 y = 10(假设只需要整数),最大偏差为epsilon(即 38001 和 1000 也是一个很好的答案)。那是对的吗?如果是这样,一个问题是偏差与因素无关。我认为它应该是一个百分比。

标签: c# .net algorithm


【解决方案1】:

不寻常。您需要找到最大公约数并将宽度和高度除以它。该算法由 Euclid 提出,已有 2300 年的历史。详情are here.

【讨论】:

  • GCD的值是什么?宽度和高度?
【解决方案2】:

您可以将 aspectRatio 写为 fraction(如果您希望它达到 0.001 的精度,则可以使用 round(aspectRatio,3)/1000)

那么,simplify this fraction。结果分数就是您要查找的 x/y。

【讨论】:

  • 这并不一定会给您带来最小的结果。例如,对于aspectRatio=0.3333333,您将四舍五入为333/1000,并且无法简化。但是,1/3 是更好的解决方案。
  • @steve - 是的,这就是我在测试他的想法时遇到的问题。
【解决方案3】:

一种更快但仍然不是公式化的方法是只查看可能的 y 值而不是迭代到 MAX_Y。例如:

    static Size FindMinSize(double requiredRatio, double epsilon)
    {
        int x = 1;
        do
        {
            int y = (int)(x * requiredRatio);
            if (Test(x, y, requiredRatio, epsilon))
            {
                return new Size(x, y);
            }

            y = (int)((x + 1) * requiredRatio);
            if (Test(x, y, requiredRatio, epsilon))
            {
                return new Size(x, y);
            }
            x++;
        } while (x != int.MaxValue);

        return new Size(0, 0);
    }

    static bool Test(int x, int y, double requiredRatio, double epsilon)
    {
        double aspectRatio = ((double)y)/x;
        return Math.Abs(aspectRatio - requiredRatio) < epsilon;
    }

【讨论】:

    【解决方案4】:

    无需测试所有可能的组合,只需增加使您更接近纵横比的一侧:

    public static Size GetSizeFromAspectRatio(double aspectRatio) {
      double epsilon = 0.001;
      int x = 1;
      int y = 1;
      while (true) {
        double a = (double)x / (double)y;
        if (Math.Abs(aspectRatio - a) < epsilon) break;
        if (a < aspectRatio) {
          x++;
        } else {
          y++;
        }
      }
      return new Size(x, y);
    }
    

    【讨论】:

      【解决方案5】:

      纵横比是 x 和 y 之间的比率。您可以将纵横比定义为 x / y 或 y / x。

      最小纵横比为 0 / 0。

      必须定义其他最小值,最小值 x 或最小值 y。

      min x = (min y * x) / y

      min y = (min x * y) / x

      【讨论】:

      • 我认为您需要寻找的一点是他想要产生纵横比值的最小整数(请参阅问题中使用的Size)。
      • 0 / 0 在我看来就像 DivisionByZero ;)
      猜你喜欢
      • 2019-04-12
      • 1970-01-01
      • 2016-08-06
      • 1970-01-01
      • 2019-06-22
      • 1970-01-01
      • 1970-01-01
      • 2018-09-07
      • 2012-10-06
      相关资源
      最近更新 更多