DIU Long Division Update

Updated DIU for detection of repeating decimals in aspect ratios
Updated bandwidth calculator with preliminary support for same thing
master
Glenwing 6 years ago
parent 75b2079373
commit 6e8829894a

@ -0,0 +1,41 @@
DebugSettings = {};
function DEBUG(text) {
Fn = DEBUG.caller.name;
proceed_with_msg = false;
if ('all' in DebugSettings) {
if (!DebugSettings['all']) {
return;
}
else if (DebugSettings['all']) {
proceed_with_msg = true;
}
}
else if (Fn in DebugSettings) {
if (DebugSettings[Fn] == false) {
proceed_with_msg = false;
}
else {
proceed_with_msg = true;
}
}
else {
proceed_with_msg = true;
}
if (proceed_with_msg == true) {
str = 'console.log("[" + Fn + "()] ::"';
for (var i = 0; i < arguments.length; i++) {
str += ', arguments[' + i + ']';
}
str += ');';
eval(str);
}
return;
}
function DebugConfig(settings) {
DebugSettings = settings;
}

@ -1697,6 +1697,169 @@ function SameRatio(H, V, A) {
}
function long_division(A, B, options) {
if (isNaN(A / B) || !isFinite(A / B)) { DEBUG('Answer is NaN or Infinity. Function aborted.'); return ''; }
var OL_open = '<span style="text-decoration:overline;">'; // Overline markup opening tag
var OL_close = '</span>'; // Overline markup closing tag. Used in conjunction with OL_open to surround the repeating numbers. May be set to control markup, separate it with parentheses, or simply left blank, etc.
var p_max = 8; // Maximum number of decimal places
var p_min = 3; // Minimum number of decimal places
var Approx = '≈'; // Symbol to be used for "approximately equal to". Can be set to '~' or blank if desired, etc.
var Radix_Point = '.'; // Character to use for the radix point ("decimal point")
var Base = 10; // Number base system to use
var Minus_Sign = '&minus;'; // Character to preceed negative numbers
var Plus_Sign = ''; // Character to preceed positive numbers
var RepeatSinglesFlag = true; // Display single-digit repeating patterns as 1.(33) instead of 1.(3)
if (typeof(options) === 'number') { // If 3rd argument is a number rather than a dictionary, use it as the p_max value
p_max = options;
}
else if(options) {
if ('OL_open' in options) { OL_open = options['OL_open']; }
if ('OL_close' in options) { OL_close = options['OL_close']; }
if ('p_max' in options) { p_max = options['p_max']; }
if ('p_min' in options) { p_min = options['p_min']; }
if ('radix' in options) { Radix_Point = options['radix']; }
if ('approx' in options) { Approx = options['approx']; }
if ('minus' in options) { Minus_Sign = options['minus']; }
if ('plus' in options) { Plus_Sign = options['plus']; }
if ('base' in options) { Base = options['base']; }
if ('repeat_singles' in options) { RepeatSinglesFlag = options['repeat_singles']; }
}
p_max = parseInt(p_max);
p_min = parseInt(p_min);
Base = parseInt(Base);
if (p_max < 0 || p_min < 0 || p_max < p_min || isNaN(p_max) || isNaN(p_min) || !isFinite(p_max) || !isFinite(p_min)) {
DEBUG('Invalid p_max and p_min values. Both values must be non-negative numbers, and p_min cannot be greater than p_max. p_max:', p_max, 'p_min', p_min)
return '';
}
if (isNaN(Base)) {
DEBUG('Invalid Base value. Must be an integer number. Base:', Base);
return '';
}
if (p_max == 0) {
var Result = Math.round(A / B).toFixed(0);
if (Result != (A / B)) { Result = '≈'.concat(Result); }
return Result;
}
var Max_Depth = 32; // Depth of internal calculations, regardless of p_max or p_min settings
var Decimal_Digits = '';
var Previous_Dividends = {};
var Prefix = '';
var Repetend = '';
var RepeatFlag = false;
var ApproxFlag = true;
var Sign = Plus_Sign;
// Determine if answer will be negative, then use the absolute value of inputs for the rest of the calculations.
if ((A < 0) ? !(B < 0) : (B < 0)) { Sign = Minus_Sign; } // If (A is negative) XOR (B is negative) then final result will be negative.
var Dividend = Math.abs(parseFloat(A));
var Divisor = Math.abs(parseFloat(B));
var Quotient = Dividend / Divisor;
var Remainder = Dividend % Divisor;
var Result = Math.floor(Quotient).toString() + Radix_Point; // Use floor division to determine the front part of the number immediately
Dividend = Remainder * Base;
// Use long division for the decimal places, so that repeating decimals can be detected
var i = 0;
while (i < p_max + 2) {
if (!(Dividend in Previous_Dividends)) {
Previous_Dividends[Dividend] = i;
Quotient = Dividend / Divisor;
Remainder = Dividend % Divisor;
Dividend = Remainder * Base;
//if (i < p_max) {
Decimal_Digits += Math.floor(Quotient).toString();
//}
//DEBUG('i:', i, 'Quotient:', Quotient, 'Remainder:', Remainder, 'Dividend:', Dividend, 'Result:', Result, 'Decimal_Digits:', Decimal_Digits);
}
else {
RepeatFlag = true;
ApproxFlag = false;
Prefix = Decimal_Digits.substring(0, Previous_Dividends[Dividend]);
Repetend = Decimal_Digits.substring(Previous_Dividends[Dividend], Decimal_Digits.length);
if (Repetend == '0') { // A "repeating" dividend of 0 signals a non-repeating result
Repetend = '';
RepeatFlag = false;
Decimal_Digits = Prefix;
}
//Decimal_Digits = Prefix + Repetend;
break;
}
i += 1;
}
if (RepeatFlag == false) {
if (Decimal_Digits.length > p_max) {
//Decimal_Digits = Decimal_Digits.substr(0, p_max);
Decimal_Digits = Math.round(parseFloat(Decimal_Digits.substr(0, p_max) + '.' + Decimal_Digits.substr(p_max))).toString();
if (p_max - Decimal_Digits.length >= 0) {
Decimal_Digits = '0'.repeat(p_max - Decimal_Digits.length) + Decimal_Digits;
}
ApproxFlag = true;
}
if (Decimal_Digits.length < p_min) {
if (p_min - Decimal_Digits.length >= 0) {
Decimal_Digits += '0'.repeat(p_min - Decimal_Digits.length);
}
}
}
if (RepeatFlag == true) {
if (Prefix.length + Repetend.length > p_max) {
if (Prefix.length > p_max) {
Prefix = Math.round(parseFloat(Prefix.substr(0, p_max) + '.' + Prefix.substr(p_max))).toString();
if (p_max - Prefix.length >= 0) {
Prefix = '0'.repeat(p_max - Prefix.length) + Prefix;
}
}
else {
Prefix = Prefix + Repetend.substr(0, p_max - Prefix.length);
}
Decimal_Digits = Prefix;
RepeatFlag = false;
ApproxFlag = true;
}
if (Prefix.length + Repetend.length < p_min) {
if ((p_min - (Prefix.length + Repetend.length)) >= Repetend.length) {
Repetend += Repetend.repeat(Math.floor((p_min - (Prefix.length + Repetend.length)) / Repetend.length));
}
while (Prefix.length + Repetend.length < p_min) {
Prefix = Prefix.concat(Repetend[0]);
Repetend = Repetend.slice(1).concat(Repetend[0]);
}
}
}
if (RepeatFlag == true) {
if (Repetend.length == 1 && (Prefix.length + Repetend.length < p_max) && RepeatSinglesFlag == true) { Repetend = Repetend.repeat(2); } // Single-digit repetitions will be displayed twice, i.e. 4/3 will result in 1.(33) rather than 1.(3)
Result += Prefix + OL_open + Repetend + OL_close;
}
else {
Result += Decimal_Digits;
}
Result = Sign.concat(Result);
if (ApproxFlag == true) {
Result = Approx.concat(Result);
}
if (Result[Result.length - 1] == Radix_Point) { Result = Result.replace(Radix_Point, ''); }
return Result;
//return Result * Sign;
}
/*
function parseNum(val) {
// Converts string to floating point if it has a decimal point, or integer if there is no decimal point. Also strips commas and spaces, and optionally applies absolute value.
@ -1761,15 +1924,14 @@ function parseNum(val) {
// First, remove all non-numeric characters on the outsides of the string
for (var i = 0; i < val.length; i++) {
if (!(i < val.length)) { break; }
//DEBUG('i:', i, 'val:', val, 'val[i]:', val[i]);
// Loop through each character starting from the front
if (!(i < val.length)) { break; }
if ((/[^0-9.-]/g).test(val[i]) == true) {
// If character is not a number, period, or minus sign, remove it
if (i == 0 && val.length > 1) { val = val.slice(1); }
else if (i == val.length - 1) { return NaN; } // If this is the last character in the string, then there are no digits in the string; return NaN
else if (i > 0) { val = (val.slice(0, i)) + (val.slice(i+1));}
i = i - 1; // Since a character has been removed, the next character is now at the same index
i = i - 1; // Since a character has been removed, the next character is now at the same index, so the loop counter must be adjusted to compensate
continue;
}
else if ((/[-]/g).test(val[i]) == true) {
@ -1777,14 +1939,14 @@ function parseNum(val) {
continue;
}
else if ((/[.]/g).test(val[i]) == true) {
// If character is a period, then following character MUST be a digit, unless it's the end of the number.
// If character is a period, then following character MUST be a digit, unless it's the end of the number. Otherwise the input is not a valid number.
if (i + 1 < val.length) {
if ((/[0-9]/g).test(val[i+1]) == true) {
// If the character after the period is a digit, then the first digit has been reached
// If the character after the period is a digit, then the "number" part of the number has definitely been reached and the code can proceed with the next section.
break;
}
else {
// If the string contained a period followed by a non-numeric character, it is not a number
// If the string contained a period followed by a non-numeric character, it cannot be interpreted as a valid number. Return NaN.
return NaN;
}
}
@ -1824,7 +1986,7 @@ function parseNum(val) {
// Now that the string only contains numeric characters, minus signs, and periods, we must check if there are any invalid usages of the periods and signs, such as multiple periods/signs, or a minus sign anywhere other than the first character.
if (val == '' // string is empty
|| val.indexOf('.') != val.lastIndexOf('.') // string contains multiple decimal point
|| val.indexOf('.') != val.lastIndexOf('.') // string contains multiple periods
|| val.indexOf('-') != val.lastIndexOf('-') // string contains multiple minus signs
|| (val.indexOf('-') != -1 && val.indexOf('-') != 0)) // input contains a minus sign and it isn't the first character
{

@ -4,7 +4,11 @@
var unit_select = $('#unit_select input[type="radio"]:checked').val();
var hres1 = parseInt(parseNum($('#INPUT_HRES').val()));
var vres1 = parseInt(parseNum($('#INPUT_VRES').val()));
var ar1 = hres1 / vres1;
var ar_options = {
'p_max': 4,
'p_min': 2,
}
var ar1 = long_division(hres1, vres1, ar_options);
var diag = parseFloat(size);
var width = size * Math.sin(Math.atan(hres1 / vres1));
@ -17,11 +21,11 @@
var vres2 = parseNum($('#INPUT_VRES2').val());
var ar2 = hres2 / vres2;
var d_match = Math.sqrt((height * height) * (1 + (ar2 * ar2)));
var opt_res = parseInt(vres1 * ar2) + '&nbsp;&times;&nbsp;' + vres1;
var opt_res = parseInt(vres1 * ar2) + '&thinsp;&times;&thinsp;' + vres1;
var hres_den = parseInt(parseNum($('#INPUT_HRES_DENSITY').val()));
var vres_den = parseInt(parseNum($('#INPUT_VRES_DENSITY').val()));
var ar_den = hres_den / vres_den;
var ar_den = long_division(hres_den, vres_den, ar_options);
var width2 = width * (hres_den / hres1);
var height2 = height * (vres_den / vres1);
@ -60,7 +64,8 @@
//if (hres1 != '' && vres1 != '' && hres1 != 0 && vres1 != 0 && isNaN(hres1) == false && isNaN(vres1) == false) {
if (isNum([hres1, vres1]) && isPositive([hres1, vres1])) {
$('#RESULT_RATIO').html(commas(ar1.toFixed(3)) + ' (' + parseInt(hres1 / GCD(hres1, vres1)) + '<span style="vertical-align:baseline; position:relative; top:-0.05em;">:</span>' + parseInt(vres1 / GCD(hres1, vres1)) + ')');
// $('#RESULT_RATIO').html(commas(ar1.toFixed(3)) + ' (' + parseInt(hres1 / GCD(hres1, vres1)) + '<span style="vertical-align:baseline; position:relative; top:-0.05em;">:</span>' + parseInt(vres1 / GCD(hres1, vres1)) + ')');
$('#RESULT_RATIO').html(ar1 + '&#x2236;1 (' + commas(parseInt(hres1 / GCD(hres1, vres1))) + '&#x2236;' + commas(parseInt(vres1 / GCD(hres1, vres1))) + ')');
$('#RESULT_TOTAL_PX').html(commas(total_px) + ' (' + prefixGen(total_px, 2)['num'] + ' ' + prefixGen(total_px, 2)['prefix'] + 'px)');
}
else {
@ -71,8 +76,11 @@
//!= '' && vres1 != '' && hres1 != 0 && vres1 != 0 && isNaN(hres1) == false && isNaN(vres1) == false
//DEBUG('isInt', isInt([hres1, vres1, hres_den, vres_den]), 'isPositive', isPositive([hres1, vres1, hres_den, vres_den]));
//DEBUG('hres1', hres1, isInt(hres1), 'vres1', vres1, isInt(vres1), 'hres_den', hres_den, isInt(hres_den), 'vres_den', vres_den, isInt(vres_den));
if (isInt([hres1, vres1, hres_den, vres_den]) && isPositive([hres1, vres1, hres_den, vres_den])) {
$('#RESULT_DENSITY_RATIO').html(commas(ar_den.toFixed(3)) + ' (' + parseInt(hres_den / GCD(hres_den, vres_den)) + '<span style="vertical-align:baseline; position:relative; top:-0.05em;">:</span>' + parseInt(vres_den / GCD(hres_den, vres_den)) + ')');
// $('#RESULT_DENSITY_RATIO').html(commas(ar_den.toFixed(3)) + ' (' + parseInt(hres_den / GCD(hres_den, vres_den)) + '<span style="vertical-align:baseline; position:relative; top:-0.05em;">:</span>' + parseInt(vres_den / GCD(hres_den, vres_den)) + ')');
$('#RESULT_DENSITY_RATIO').html(ar_den + '&#x2236;1 (' + commas(parseInt(hres_den / GCD(hres_den, vres_den))) + '&#x2236;' + commas(parseInt(vres_den / GCD(hres_den, vres_den))) + ')');
}
else {
$('#RESULT_DENSITY_RATIO').html('');
@ -85,32 +93,31 @@
// Returns false if input is a non-integer number or NaN
function isInt(num) {
num = parseNum(num);
if (Array.isArray(num) == true) {
for (a = 0; a < num.length; a++) {
if (Number.isInteger(num[a]) == false) {
if (Number.isInteger(parseNum(num[a])) == false) {
//DEBUG('isInt Array False. a:', a, 'num[a]:', num[a], 'Number.isInteger(num[a]):', Number.isInteger(num[a]));
return false;
}
return true;
}
}
else
return Number.isInteger(num);
return Number.isInteger(parseNum(num));
}
function isFloat(num) {
num = parseNum(num);
if (Array.isArray(num) == true) {
for (a = 0; a < num.length; a++) {
if (Number.isInteger(num[a]) == true || Number.isNaN(num[a]) == true) {
if (Number.isInteger(parseNum(num[a])) == true || Number.isNaN(num[a]) == true) {
return false;
}
return true;
}
}
else
return !(Number.isInteger(num) || Number.isNaN(num));
return !(Number.isInteger(parseNum(num)) || Number.isNaN(parseNum(num)));
}
@ -322,8 +329,178 @@ function GCD(a, b) {
}
function commas(x) {
var parts = x.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
function commas(input, group, radix) {
if (!group) { group = ','; }
if (!radix) { radix = '.'; }
var parts = input.toString().split(radix);
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, group);
return parts.join(radix);
}
function long_division(A, B, options) {
if (isNaN(A / B) || !isFinite(A / B)) { DEBUG('Answer is NaN or Infinity. Function aborted.'); return ''; }
var OL_open = '<span style="text-decoration:overline;">'; // Overline markup opening tag
var OL_close = '</span>'; // Overline markup closing tag. Used in conjunction with OL_open to surround the repeating numbers. May be set to control markup, separate it with parentheses, or simply left blank, etc.
var p_max = 8; // Maximum number of decimal places
var p_min = 3; // Minimum number of decimal places
var Approx = '≈'; // Symbol to be used for "approximately equal to". Can be set blank to turn off this functionality, etc.
var Radix_Point = '.'; // Character to use for the radix point ("decimal point")
var Group = ','; // Character to use for digit grouping. Can be set blank to disable digit grouping.
var Base = 10; // Number base system to use
var Minus_Sign = '&minus;'; // Character to preceed negative numbers. Default minus sign, can be set blank to output absolute value, or set to hyphen-minus for better compatibility or for other functions to be able to parse as a number correctly.
var Plus_Sign = ''; // Character to preceed positive numbers. Default blank, but can be set to "+" if explicit signs on both positive and negative numbers is desired.
var RepeatSinglesFlag = true; // Display single-digit repeating patterns as 1.(33) instead of 1.(3)
if (typeof(options) === 'number') { // If 3rd argument is a number rather than a dictionary, use it as the p_max value
p_max = options;
}
else if(options) {
if ('OL_open' in options) { OL_open = options['OL_open']; }
if ('OL_close' in options) { OL_close = options['OL_close']; }
if ('p_max' in options) { p_max = options['p_max']; }
if ('p_min' in options) { p_min = options['p_min']; }
if ('radix' in options) { Radix_Point = options['radix']; }
if ('group' in options) { Group = options['group']; }
if ('approx' in options) { Approx = options['approx']; }
if ('minus' in options) { Minus_Sign = options['minus']; }
if ('plus' in options) { Plus_Sign = options['plus']; }
if ('base' in options) { Base = options['base']; }
if ('repeat_singles' in options) { RepeatSinglesFlag = options['repeat_singles']; }
}
var Decimal_Digits = '';
var Previous_Dividends = {};
var Prefix = '';
var Repetend = '';
var RepeatFlag = false;
var ApproxFlag = true;
var Sign = Plus_Sign;
// Determine if answer will be negative, then use the absolute value of inputs for the rest of the calculations.
if ((A < 0) ? !(B < 0) : (B < 0)) { Sign = Minus_Sign; } // If (A is negative) XOR (B is negative) then final result will be negative.
var Dividend = Math.abs(parseFloat(A));
var Divisor = Math.abs(parseFloat(B));
p_max = parseInt(p_max);
p_min = parseInt(p_min);
Base = parseInt(Base);
if (p_max < 0 || p_min < 0 || p_max < p_min || isNaN(p_max) || isNaN(p_min) || !isFinite(p_max) || !isFinite(p_min)) {
DEBUG('Invalid p_max and p_min values. Both values must be non-negative numbers, and p_min cannot be greater than p_max. p_max:', p_max, 'p_min', p_min)
return '';
}
if (!isInt(Base)) {
DEBUG('Invalid Base value. Must be an integer number. Base:', Base);
return '';
}
if (p_max == 0) { // If p_max is 0, then output is integer values only, and the long division section is not necessary.
var Result = Math.round(Dividend / Divisor).toFixed(0);
if (Result != (Dividend / Divisor)) { ApproxFlag = true; }
Result = Sign.concat(Result.toString());
if (ApproxFlag == true) { Result = Approx.concat(Result); }
return Result;
}
var Quotient = Dividend / Divisor;
var Remainder = Dividend % Divisor;
var Result = Math.floor(Quotient).toString() + Radix_Point; // Use floor division to determine the front part of the number immediately
Dividend = Remainder * Base;
// Use long division for the decimal places, so that repeating decimals can be detected
var i = 0;
while (i < p_max + 2) {
if (!(Dividend in Previous_Dividends)) {
Previous_Dividends[Dividend] = i;
Quotient = Dividend / Divisor;
Remainder = Dividend % Divisor;
Dividend = Remainder * Base;
//if (i < p_max) {
Decimal_Digits += Math.floor(Quotient).toString();
//}
//DEBUG('i:', i, 'Quotient:', Quotient, 'Remainder:', Remainder, 'Dividend:', Dividend, 'Result:', Result, 'Decimal_Digits:', Decimal_Digits);
}
else {
RepeatFlag = true;
ApproxFlag = false;
Prefix = Decimal_Digits.substring(0, Previous_Dividends[Dividend]);
Repetend = Decimal_Digits.substring(Previous_Dividends[Dividend], Decimal_Digits.length);
if (Repetend == '0') { // A "repeating" dividend of 0 signals a non-repeating result
Repetend = '';
RepeatFlag = false;
Decimal_Digits = Prefix;
}
//Decimal_Digits = Prefix + Repetend;
break;
}
i += 1;
}
if (RepeatFlag == false) {
if (Decimal_Digits.length > p_max) {
//Decimal_Digits = Decimal_Digits.substr(0, p_max);
Decimal_Digits = Math.round(parseFloat(Decimal_Digits.substr(0, p_max) + '.' + Decimal_Digits.substr(p_max))).toString();
if (p_max - Decimal_Digits.length >= 0) {
Decimal_Digits = '0'.repeat(p_max - Decimal_Digits.length) + Decimal_Digits;
}
ApproxFlag = true;
}
if ((Decimal_Digits.length < p_min) && (p_min - Decimal_Digits.length >= 0)) {
Decimal_Digits += '0'.repeat(p_min - Decimal_Digits.length);
}
}
if (RepeatFlag == true) {
if (Prefix.length + Repetend.length > p_max) {
if (Prefix.length > p_max) {
Prefix = Math.round(parseFloat(Prefix.substr(0, p_max) + '.' + Prefix.substr(p_max))).toString();
if (p_max - Prefix.length >= 0) {
Prefix = '0'.repeat(p_max - Prefix.length) + Prefix;
}
}
else {
Prefix = Prefix + Repetend.substr(0, p_max - Prefix.length);
}
Decimal_Digits = Prefix;
RepeatFlag = false;
ApproxFlag = true;
}
if (Prefix.length + Repetend.length < p_min) {
if ((p_min - (Prefix.length + Repetend.length)) >= Repetend.length) {
Repetend += Repetend.repeat(Math.floor((p_min - (Prefix.length + Repetend.length)) / Repetend.length));
}
while (Prefix.length + Repetend.length < p_min) {
Prefix = Prefix.concat(Repetend[0]);
Repetend = Repetend.slice(1).concat(Repetend[0]);
}
}
}
if (RepeatFlag == true) {
if (Repetend.length == 1 && (Prefix.length + Repetend.length < p_max) && RepeatSinglesFlag == true) { Repetend = Repetend.repeat(2); } // Single-digit repetitions will be displayed twice, i.e. 4/3 will result in 1.(33) rather than 1.(3)
Result += Prefix + OL_open + Repetend + OL_close;
}
else {
Result += Decimal_Digits;
}
if (Result[Result.length - 1] == Radix_Point) { Result = Result.replace(Radix_Point, ''); }
Result = commas(Result, Group, Radix_Point);
Result = Sign.concat(Result);
if (ApproxFlag == true) {
Result = Approx.concat(Result);
}
return Result;
//return Result * Sign;
}

@ -3,6 +3,7 @@
<meta name="viewport" content="width=device-width">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="../DebugControl.js"></script>
<script src="diuJS.js"></script>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
@ -85,17 +86,17 @@
<td class="label">Secondary Display<br />Aspect Ratio:</td>
<td>
<input class="res_input" id="INPUT_HRES2" style="width:32px; text-align:right;" type="text" onchange="update();" oninput="this.onchange()" onfocus="this.select();" />
<span>:</span>
<span>&#x2236;</span>
<input class="res_input" id="INPUT_VRES2" style="width:32px; text-align:left;" type="text" onchange="update();" oninput="this.onchange()" onfocus="this.select();" />
</td>
</tr>
<tr id="21_9_warning" style="display:none;">
<td class="label">&nbsp;</td>
<td class="result" style="color:#DD1111;">
<b>Warning: Formats commonly known as "21:9" are not an exact 21:9 ratio</b><br />
&nbsp;&nbsp;2560 <span class="res_x">&#10005;</span> 1080 is a 64:27 ratio<br />
&nbsp;&nbsp;3440 <span class="res_x">&#10005;</span> 1440 is a 43:18 ratio<br />
&nbsp;&nbsp;3840 <span class="res_x">&#10005;</span> 1600 is a 12:5 ratio<br />
<b>Warning: Formats commonly known as "21&#x2236;9" are not an exact 21&#x2236;9 ratio</b><br />
&nbsp;&nbsp;2560 <span class="res_x">&#10005;</span> 1080 is a 64&#x2236;27 ratio<br />
&nbsp;&nbsp;3440 <span class="res_x">&#10005;</span> 1440 is a 43&#x2236;18 ratio<br />
&nbsp;&nbsp;3840 <span class="res_x">&#10005;</span> 1600 is a 12&#x2236;5 ratio<br />
</td>
</tr>
<tr>

Loading…
Cancel
Save