通常,您可以使用以下公式将值input
从一个范围[inputMin, inputMax]
转换为另一个范围[outputMin, outputMax]
:
output = (input-inputMin) * ((outputMax-outputMin)/(inputMax-inputMin)) + outputMin
但是如果inputMax = double.MaxValue
和inputMin = double.MinValue
怎么办?然后inputMax - inputMin == double.PositiveInfinity
,整个公式就会变得毫无用处。
在以下限制下,是否有更好的方法进行这种转换?
inputMax >= outputMax
和inputMin <= outputMin
答案 0 :(得分:2)
为避免lista = ['479 000', '350 000']
lista = list(map(lambda x: int(''.join((x.split()))), lista))
溢出到无穷大,请按inputMax - inputMin
缩放input, inputMin, inputMax
。除了一些较小的值外,这应该是准确的:设置了最低有效位的子法线。
/2
@aka.nice对下面改进的精度方法的确定局限性。待会儿再审核。
保持精度是棘手的,但是以FP解释的方式以x解释的方式形成interpolation很有优势。主要思想不是从x = input/2; // scale `input` also
x0 = inputMin/2;
x1 = inputMax/2;
dx = x1 - x0;
中形成一些小的y
,因为在乘法之后会进行加法运算。由于取消,任何加法/减法都可能导致精度的严重损失。
y-mx*b
x截距y = (x - x_intercept)*slope
有其自身的问题。如果可能,应该在扩展数学中完成。除非我们可以利用,否则对于现实生活中的应用,x_intercept = (x1*y2 - x2*y1)/(y2 - y1)
不会是极端的,因此可以在最重要的时候为x_intercept
节省一些精度(x - x_intercept
会很小)。
y
y0 = outputMin/2;
y1 = outputMax/2;
dy = y1 - y0;
// Avoid (y1*x0 - y0*x1)/dy to prevent overflow in the multiplications
x_intercept = y1/dy*x0 - y0/dy*x1;
y = (x - x_intercept)/dx*dy;
output = 2*y; // scale `output` at the end.
等特殊情况可以根据需要通过测试进行处理。
此方法类似于@aka.nice。然而,代码看起来不是中间的outputMin == outputMax
,而是计算x截距。
答案 1 :(得分:0)
您可以做的是绕中间旋转:
inputMiddle = 0.5*inputMax + 0.5*inputMin
然后,通过输入的中间范围:
inputMidRange = 0.5*inputsMax - 0.5*inputMin
计算输入到中间的距离(在-1和1之间):
howFar = (input-inputMiddle) / inputMidRange
然后通过输出中间和输出中间范围,将其综合报告给输出
output = howFar * outputMidRange + outputMiddle
如埃里克(Eric)所述,如果某些区间边界已经是次法线,则可能会出现下溢问题,但是即使降至最小次法线的两倍,这仍然应该起作用。
编辑
上面的公式是关于溢出的答案,但是在操作(input-inputMiddle)
中仍然存在灾难性取消的问题。
例如,将[0,double.MaxValue]
映射到[0,double.MaxValue/2]
的所有“小”值都将投影在outputMin
上,尽管简单的input/2
操作会导致正确的输出...