java 如何通过给定因子计算纵横比?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7442206/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to calculate the aspect ratio by a given factor?
提问by MC Emperor
How do I calculate the aspect ratio (formatted as integer:integer
) by a given factor?
如何integer:integer
按给定因子计算纵横比(格式为)?
For example, aspect ratio 16:9 has a factor of 1.778, because 16 / 9 = 1.778. But how can I find the ratio by that factor? So
例如,纵横比 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);
}
should return
应该回来
16:9
回答by Lukas Eder
Disclaimer: These algorithms are silly and inefficient. I'm sure there's a better one...
免责声明:这些算法既愚蠢又低效。我确定有更好的...
A silly, straightforward (not very efficient) algorithm to find an approximation is this:
一个愚蠢的,直接的(不是很有效)的算法来找到一个近似值是这样的:
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);
Output.
输出。
Closest ratio: 16/9
Ratio : 1.7777777777777777
Inaccurate by: 2.2222222222234578E-4
Update: Alternative algorithm
更新:替代算法
I've just thought of an alternative algorithm, which tries to close in on the approximation. Of course, it's still not very efficient...
我刚刚想到了一种替代算法,它试图接近近似值。当然,它仍然不是很有效......
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);
The output is the same
输出是一样的
Should I stumble upon an efficient algorithm, I'll post it here :-)
如果我偶然发现一个有效的算法,我会在这里发布:-)
回答by Chad Greenburg
This is an extremely late reply, but I have solved this using a much easier way and I know other's would appreciate it.
这是一个非常晚的回复,但我已经使用更简单的方法解决了这个问题,我知道其他人会很感激。
I'm assuming that you already know the screen resolution since you know the aspect ratio (decimal equivalent). You can find the aspect ratio (integer:integer) by solving for the greatest common factor between the screen width and height.
我假设您已经知道屏幕分辨率,因为您知道纵横比(十进制等值)。您可以通过求解屏幕宽度和高度之间的最大公因数来找到纵横比(整数:整数)。
public int greatestCommonFactor(int width, int height) {
return (height == 0) ? width : greatestCommonFactor(height, width % height);
}
This will return the greatest common factor between the screen width and height. To find the actual aspect ratio, you just divide the screen width and height by the greatest common factor. So...
这将返回屏幕宽度和高度之间的最大公因数。要找到实际的纵横比,您只需将屏幕宽度和高度除以最大公因数。所以...
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;
This outputs:
这输出:
Resolution: 1920x1080
Aspect Ratio: 16:9
Decimal Equivalent: 1.7777779
Hope this helps.
希望这可以帮助。
Note: This won't work for some resolutions. Comments contain more info.
注意:这不适用于某些分辨率。评论包含更多信息。
回答by aioobe
This is not possible in general, since a double may not represent the actual (exact) fraction. You'll have to rely on heuristics or brute force as suggested in the other answers.
这通常是不可能的,因为 double 可能不代表实际(精确)分数。您将不得不依赖其他答案中建议的启发式方法或蛮力。
If you had the exact decimal expansionand period you could solve it though.
如果你有精确的十进制扩展和周期,你可以解决它。
Here's the pen and paper way:
这是笔和纸的方式:
Suppose you start with
1.77777...
(which is 16/9 but let's assume that we didn't know that)You note that the period is
7
(one digit) so you multiply by 10 (i.e. move the decimal point one step to the right):10n = 17.77777...
You can now cancel out the repeating part by computing
10n - n
:10n - n = 17.77777... - 1.77777... = 16
Solving for
n
yieldsn = 16/9
假设你从
1.77777...
(这是 16/9 但假设我们不知道)你注意到句号是
7
(一位)所以你乘以 10(即小数点向右移动一步):10n = 17.77777...
您现在可以通过计算取消重复部分
10n - n
:10n - n = 17.77777... - 1.77777... = 16
解决
n
收益率n = 16/9
Translating this to code would require you to figure out the start and length of the period of the decimal expansion which will itself be a nasty problem, as the number could typically look something like 0.16666667
.
将其转换为代码需要您弄清楚十进制扩展周期的开始和长度,这本身就是一个令人讨厌的问题,因为数字通常看起来像0.16666667
.
回答by akkie
Here is an implementation in Scala which finds the Best rational approximation
based on the Farey sequence. This algorithm was suggested by @AakashM and it's translated from John D. Cook's Python implementationand David Weber's C++ modification.
这是 Scala 中的一个实现,它Best rational approximation
根据 Farey 序列找到 。这个算法是由@AakashM 提出的,它是从John D. Cook 的 Python 实现和David Weber 的 C++ 修改翻译过来的。
/**
* Calculates the `Best rational approximation` based on the Farey sequence.
*
* Translated from John D. Cook's Python implementation and David
* Weber's C++ modification.
*
* @param x A value to be approximated by two integers.
* @param eps The required precision such that abs(x-a/b) < eps. Eps > 0.
* @param n The maximum size of the numerator allowed.
* @return The best rational approximation for x.
*/
def farey(x: Double, eps: Double, n: Int): (Int, Int) = {
@tailrec
def iterate(a: Int, b: Int, c: Int, d: Int): (Int, Int) = {
if (b <= n && d <= n) {
val mediant = (a + c).toDouble / (b + d).toDouble
if (Math.abs(x - mediant) < eps) {
if (b + d <= n) {
(a + c) -> (b + d)
} else if (d > b) {
c -> d
} else {
a -> b
}
} else if (x > mediant) {
iterate(a + c, b + d, c, d)
} else {
iterate(a, b, a + c, b + d)
}
}
else if (b > n) c -> d
else a -> b
}
iterate(0, 1, 1, 0)
}
I've created a gistwhich contains also some tests.
我创建了一个gist,其中还包含一些测试。
回答by Suraj Chandran
This is a linear equation. In general you can't have two unknownsin a linear equation.
这是一个线性方程。一般来说,线性方程中不能有两个未知数。
回答by pupssman
Actually, all the factors of form a/b
are presented as finite ratios or infinite but periodic ratios (provided a
and b
are integers). Period can be pretty big, though. You could try to detect it and find exact ratio if period is, at least, half less than double precision. Or you could try to make best guess.
实际上,所有形式的因素a/b
都以有限比率或无限但周期性的比率(提供a
并且b
是整数)表示。不过,期间可能相当大。如果周期至少比双精度低一半,您可以尝试检测它并找到确切的比率。或者您可以尝试做出最佳猜测。
回答by bigGuy
Aspect ratio can be be real number (1.85:1 for example), so I'm afraid its impossible to "guess" aspect ration from factor.
纵横比可以是实数(例如1.85:1),所以恐怕不可能从因子“猜测”纵横比。
But there are maybe 10 common used aspect ratios. You could easy make factor-aspect ratio table.
但是可能有 10 种常用的纵横比。您可以轻松制作因子纵横比表。
回答by ManojP
If someone wants to calculate the tv height and width based on aspect ratio and diagonal use the below code.
如果有人想根据纵横比和对角线计算电视高度和宽度,请使用以下代码。
public void printTvHeightAndWidth(){
int widhtRatio = 16;
int heightRatio = 9;
int diagonal = 88;
double tvHeight = (heightRatio * diagonal) / Math.sqrt(widhtRatio * widhtRatio + heightRatio * heightRatio);
double tvWidth = (widhtRatio * diagonal) / Math.sqrt(widhtRatio * widhtRatio + heightRatio * heightRatio);
DecimalFormat df = new DecimalFormat("#.##");
System.out.println("W = " + df.format(tvWidth) + " H = " + df.format(tvHeight));
}