如何找到两个值之间的分布
how to find distribution between two values
假设我有一张 210mm x 297mm (A4) 的页面。它的每边打印边距为 5 毫米。
我想打印 1cm x 1cm 的正方形来填充页面。每个正方形都有特定的边距,比如向右 1 毫米,向底部 2 毫米。
现在计算我能得到多少方块就很容易了:
( 210 - 10 ) / ( 10 + 1 ) = 18.181...
( 297 - 10 ) / ( 10 + 2 ) = 23.916...
所以 23 行 18 列的正方形适合我的页面。
现在我希望第一行正方形为 1cm x 1cm,最后一行为 5mm x 5mm。
但中间的所有行都应填满 < 1 厘米到 > 5 毫米的行。尺寸从上到下递减。
如何找到行数和每行的平方大小?
我能想到的最好的,但需要尝试以下步骤:
const heightAvailable = 287;
const maxSizeElement = 10;
const minSizeElement = 5;
const marginBottom = 2;
const step = 0.15;
function getElementsArray(availableLeft, minElement, maxElement, margin, step) {
const elementsArray = [];
elementsArray.push(minElement);
elementsArray.push(maxElement);
while(isSizeLeft(availableLeft, minElement, maxElement, margin)) {
minElement+=step;
maxElement-=step;
elementsArray.push(Number((minElement).toFixed(1)));
elementsArray.push(Number((maxElement).toFixed(1)));
availableLeft = getSizeLeft(availableLeft, minElement, maxElement, margin);
}
return elementsArray.sort(function(a,b) { return b - a;});;
}
function isSizeLeft(total, minElement, maxElement, margin) {
return 0 < total - (maxElement+margin) - (minElement+margin);
}
function getSizeLeft(total, minElement, maxElement, margin) {
return total - (maxElement+margin) - (minElement+margin);
}
哪个returns:
array(32) {
[0]=>
int(10)
[1]=>
float(9.9)
[2]=>
float(9.7)
[3]=>
float(9.6)
[4]=>
float(9.4)
[5]=>
float(9.3)
[6]=>
float(9.1)
[7]=>
float(9)
[8]=>
float(8.8)
[9]=>
float(8.7)
[10]=>
float(8.5)
[11]=>
float(8.4)
[12]=>
float(8.2)
[13]=>
float(8.1)
[14]=>
float(7.9)
[15]=>
float(7.8)
[16]=>
float(7.3)
[17]=>
float(7.1)
[18]=>
float(7)
[19]=>
float(6.8)
[20]=>
float(6.7)
[21]=>
float(6.5)
[22]=>
float(6.4)
[23]=>
float(6.2)
[24]=>
float(6.1)
[25]=>
float(5.9)
[26]=>
float(5.8)
[27]=>
float(5.6)
[28]=>
float(5.5)
[29]=>
float(5.3)
[30]=>
float(5.2)
[31]=>
int(5)
}
这是一个使用 Python 和 numpy 进行计算的解决方案。转换为 javascript 应该相当容易,尽管使用了更多的代码。最“复杂”的函数是 np.linspace
它将一个范围划分为 n
个均匀分布的值:
import numpy as np
heightAvailable = 287
maxSizeElement = 10
minSizeElement = 5
marginBottom = 2
for n in range(2, 100):
sizes = np.linspace(10, 5, n) # n evenly distributed numbers between 10 and 5 (both included)
total_space = np.sum(sizes) + (n - 1) * marginBottom
print(f"With {n} rows; total_space: {total_space:.2f} mm")
if total_space > heightAvailable:
sizes = np.linspace(10, 5, n - 1)
total_space = np.sum(sizes) + (n - 2) * marginBottom
print(f"Use {n - 1} rows; total_space: {total_space:.1f} mm\nsizes:")
print(sizes)
break
输出:
With 2 rows; total_space: 17.00 mm
With 3 rows; total_space: 26.50 mm
With 4 rows; total_space: 36.00 mm
...
With 28 rows; total_space: 264.00 mm
With 29 rows; total_space: 273.50 mm
With 30 rows; total_space: 283.00 mm
With 31 rows; total_space: 292.50 mm
Use 30 rows; total_space: 283.0 mm
sizes:
[10. 9.82758621 9.65517241 9.48275862 9.31034483 9.13793103
8.96551724 8.79310345 8.62068966 8.44827586 8.27586207 8.10344828
7.93103448 7.75862069 7.5862069 7.4137931 7.24137931 7.06896552
6.89655172 6.72413793 6.55172414 6.37931034 6.20689655 6.03448276
5.86206897 5.68965517 5.51724138 5.34482759 5.17241379 5. ]
对于更数学的方法,您可以用符号计算所有内容,例如使用 Python 的 sympy。请注意,小方块的单个大小是第一个和最后一个大小之间的插值。可以使用三角数的公式并求解二次方程“手动”计算公式,或者让 sympy 完成工作:
from sympy import symbols, Sum, Eq, solve
heightAvailable, maxSizeElement, minSizeElement, marginBottom = symbols(
'heightAvailable maxSizeElement minSizeElement marginBottom')
i, n = symbols('i n')
total = Sum((i - 1) / (n - 1) * maxSizeElement + (n - 1 - (i - 1)) / (n - 1) * minSizeElement,
(i, 1, n)) + (n - 1) * marginBottom
sol = solve(Eq(total.simplify(), heightAvailable), n)
print(sol)
print(sol[0].subs({heightAvailable: 287, maxSizeElement: 10, minSizeElement: 5, marginBottom: 2}).evalf())
输出:
[2*(heightAvailable + marginBottom)/(2*marginBottom + maxSizeElement + minSizeElement)]
30.4210526315789
假设我有一张 210mm x 297mm (A4) 的页面。它的每边打印边距为 5 毫米。 我想打印 1cm x 1cm 的正方形来填充页面。每个正方形都有特定的边距,比如向右 1 毫米,向底部 2 毫米。 现在计算我能得到多少方块就很容易了:
( 210 - 10 ) / ( 10 + 1 ) = 18.181...
( 297 - 10 ) / ( 10 + 2 ) = 23.916...
所以 23 行 18 列的正方形适合我的页面。
现在我希望第一行正方形为 1cm x 1cm,最后一行为 5mm x 5mm。
但中间的所有行都应填满 < 1 厘米到 > 5 毫米的行。尺寸从上到下递减。
如何找到行数和每行的平方大小?
我能想到的最好的,但需要尝试以下步骤:
const heightAvailable = 287;
const maxSizeElement = 10;
const minSizeElement = 5;
const marginBottom = 2;
const step = 0.15;
function getElementsArray(availableLeft, minElement, maxElement, margin, step) {
const elementsArray = [];
elementsArray.push(minElement);
elementsArray.push(maxElement);
while(isSizeLeft(availableLeft, minElement, maxElement, margin)) {
minElement+=step;
maxElement-=step;
elementsArray.push(Number((minElement).toFixed(1)));
elementsArray.push(Number((maxElement).toFixed(1)));
availableLeft = getSizeLeft(availableLeft, minElement, maxElement, margin);
}
return elementsArray.sort(function(a,b) { return b - a;});;
}
function isSizeLeft(total, minElement, maxElement, margin) {
return 0 < total - (maxElement+margin) - (minElement+margin);
}
function getSizeLeft(total, minElement, maxElement, margin) {
return total - (maxElement+margin) - (minElement+margin);
}
哪个returns:
array(32) {
[0]=>
int(10)
[1]=>
float(9.9)
[2]=>
float(9.7)
[3]=>
float(9.6)
[4]=>
float(9.4)
[5]=>
float(9.3)
[6]=>
float(9.1)
[7]=>
float(9)
[8]=>
float(8.8)
[9]=>
float(8.7)
[10]=>
float(8.5)
[11]=>
float(8.4)
[12]=>
float(8.2)
[13]=>
float(8.1)
[14]=>
float(7.9)
[15]=>
float(7.8)
[16]=>
float(7.3)
[17]=>
float(7.1)
[18]=>
float(7)
[19]=>
float(6.8)
[20]=>
float(6.7)
[21]=>
float(6.5)
[22]=>
float(6.4)
[23]=>
float(6.2)
[24]=>
float(6.1)
[25]=>
float(5.9)
[26]=>
float(5.8)
[27]=>
float(5.6)
[28]=>
float(5.5)
[29]=>
float(5.3)
[30]=>
float(5.2)
[31]=>
int(5)
}
这是一个使用 Python 和 numpy 进行计算的解决方案。转换为 javascript 应该相当容易,尽管使用了更多的代码。最“复杂”的函数是 np.linspace
它将一个范围划分为 n
个均匀分布的值:
import numpy as np
heightAvailable = 287
maxSizeElement = 10
minSizeElement = 5
marginBottom = 2
for n in range(2, 100):
sizes = np.linspace(10, 5, n) # n evenly distributed numbers between 10 and 5 (both included)
total_space = np.sum(sizes) + (n - 1) * marginBottom
print(f"With {n} rows; total_space: {total_space:.2f} mm")
if total_space > heightAvailable:
sizes = np.linspace(10, 5, n - 1)
total_space = np.sum(sizes) + (n - 2) * marginBottom
print(f"Use {n - 1} rows; total_space: {total_space:.1f} mm\nsizes:")
print(sizes)
break
输出:
With 2 rows; total_space: 17.00 mm
With 3 rows; total_space: 26.50 mm
With 4 rows; total_space: 36.00 mm
...
With 28 rows; total_space: 264.00 mm
With 29 rows; total_space: 273.50 mm
With 30 rows; total_space: 283.00 mm
With 31 rows; total_space: 292.50 mm
Use 30 rows; total_space: 283.0 mm
sizes:
[10. 9.82758621 9.65517241 9.48275862 9.31034483 9.13793103
8.96551724 8.79310345 8.62068966 8.44827586 8.27586207 8.10344828
7.93103448 7.75862069 7.5862069 7.4137931 7.24137931 7.06896552
6.89655172 6.72413793 6.55172414 6.37931034 6.20689655 6.03448276
5.86206897 5.68965517 5.51724138 5.34482759 5.17241379 5. ]
对于更数学的方法,您可以用符号计算所有内容,例如使用 Python 的 sympy。请注意,小方块的单个大小是第一个和最后一个大小之间的插值。可以使用三角数的公式并求解二次方程“手动”计算公式,或者让 sympy 完成工作:
from sympy import symbols, Sum, Eq, solve
heightAvailable, maxSizeElement, minSizeElement, marginBottom = symbols(
'heightAvailable maxSizeElement minSizeElement marginBottom')
i, n = symbols('i n')
total = Sum((i - 1) / (n - 1) * maxSizeElement + (n - 1 - (i - 1)) / (n - 1) * minSizeElement,
(i, 1, n)) + (n - 1) * marginBottom
sol = solve(Eq(total.simplify(), heightAvailable), n)
print(sol)
print(sol[0].subs({heightAvailable: 287, maxSizeElement: 10, minSizeElement: 5, marginBottom: 2}).evalf())
输出:
[2*(heightAvailable + marginBottom)/(2*marginBottom + maxSizeElement + minSizeElement)]
30.4210526315789