如何按给定因子计算纵横比?

MC *_*ror 4 java math aspect-ratio

如何根据integer:integer给定因子计算纵横比(格式化为)?

例如,宽高比16:9的因子为1.778,因为16/9 = 1.778.但是如何通过该因子找到比率?所以

Dimension getAspectRatio(double factor) {
    ...
}

public static void main(String[] arguments) {
    Dimension d = getAspectRatio(16d / 9d);
    System.out.println(d.width + ":" + d.height);
}
Run Code Online (Sandbox Code Playgroud)

应该回来

16:9
Run Code Online (Sandbox Code Playgroud)

Luk*_*der 9

免责声明:这些算法愚蠢且效率低下.我相信有更好的......

找到近似值的一种愚蠢,直接(不是非常有效)的算法是这样的:

double ratio = 1.778;
double bestDelta = Double.MAX_VALUE;
int bestI = 0;
int bestJ = 0;

for (int i = 1; i < 100; i++) {
  for (int j = 1; j < 100; j++) {
    double newDelta = Math.abs((double) i / (double) j - ratio);
    if (newDelta < bestDelta) {
      bestDelta = newDelta;
      bestI = i;
      bestJ = j;
    }
  }
}

System.out.println("Closest ratio: " + bestI + "/" + bestJ);
System.out.println("Ratio        : " + ((double) bestI / (double) bestJ));
System.out.println("Inaccurate by: " + bestDelta); 
Run Code Online (Sandbox Code Playgroud)

输出.

Closest ratio: 16/9
Ratio        : 1.7777777777777777
Inaccurate by: 2.2222222222234578E-4
Run Code Online (Sandbox Code Playgroud)

更新:替代算法

我刚刚想到了一种替代算法,它试图接近近似值.当然,它仍然不是很有效......

double bestDelta = Double.MAX_VALUE;
int i = 1;
int j = 1;
int bestI = 0;
int bestJ = 0;

for (int iterations = 0; iterations < 100; iterations++) {
  double delta = (double) i / (double) j - ratio;

  // Optionally, quit here if delta is "close enough" to zero
  if (delta < 0) i++;
  else j++;

  double newDelta = Math.abs((double) i / (double) j - ratio);
  if (newDelta < bestDelta) {
    bestDelta = newDelta;
    bestI = i;
    bestJ = j;
  }
}

System.out.println("Closest ratio: " + bestI + "/" + bestJ);
System.out.println("Ratio        : " + ((double) bestI / (double) bestJ));
System.out.println("Inaccurate by: " + bestDelta);
Run Code Online (Sandbox Code Playgroud)

输出是一样的

我应该偶然发现一个有效的算法,我会在这里发布:-)


aio*_*obe 8

这通常是不可能的,因为double可能不代表实际(精确)分数.您将不得不依赖于其他答案中建议的启发式或暴力.

如果你有精确的十进制扩展和周期,你可以解决它.

这是笔和纸的方式:

  1. 假设你开始1.77777...(这是16/9,但让我们假设我们不知道)

  2. 您注意到句点是7(一位数),因此您乘以10(即将小数点向右移动一步):

    10n = 17.77777...
    
    Run Code Online (Sandbox Code Playgroud)
  3. 您现在可以通过计算来取消重复部分10n - n:

    10n - n = 17.77777... - 1.77777... = 16
    
    Run Code Online (Sandbox Code Playgroud)
  4. 解决n收益率问题n = 16/9

将其转换为代码需要你弄清楚十进制扩展周期的开始和长度,这本身就是一个讨厌的问题,因为数字通常看起来像0.16666667.


Cha*_*urg 8

这是一个非常晚的回复,但我用一种更简单的方式解决了这个问题,我知道其他人会很感激.

我假设您已经知道屏幕分辨率,因为您知道宽高比(十进制等效值).您可以通过求解屏幕宽度和高度之间的最大公因子来找到纵横比(整数:整数).

public int greatestCommonFactor(int width, int height) {
    return (height == 0) ? width : greatestCommonFactor(height, width % height);
}
Run Code Online (Sandbox Code Playgroud)

这将返回屏幕宽度和高度之间的最大公因数.要查找实际宽高比,只需将屏幕宽度和高度除以最大公因子即可.所以...

int screenWidth = 1920;
int screenHeight = 1080;

int factor = greatestCommonFactor(screenWidth, screenHeight);

int widthRatio = screenWidth / factor;
int heightRatio = screenHeight / factor;

System.out.println("Resolution: " + screenWidth + "x" + screenHeight;
System.out.println("Aspect Ratio: " + widthRatio + ":" + heightRatio;
System.out.println("Decimal Equivalent: " + widthRatio / heightRatio;
Run Code Online (Sandbox Code Playgroud)

这输出:

Resolution: 1920x1080
Aspect Ratio: 16:9
Decimal Equivalent: 1.7777779
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

注意:这对某些分辨率不起作用.评论包含更多信息.