我试图将一个范围的数字转换为另一个,保持比率。数学不是我的强项。
I have an image file where point values may range from -16000.00 to 16000.00 though the typical range may be much less. What I want to do is compress these values into the integer range 0-100, where 0 is the value of the smallest point, and 100 is the value of the largest. All points in between should keep a relative ratio even though some precision is being lost I'd like to do this in python but even a general algorithm should suffice. I'd prefer an algorithm where the min/max or either range can be adjusted (ie, the second range could be -50 to 800 instead of 0 to 100).
C++变体
我发现PenguinTD的解决方案很有用,所以我把它移植到c++,如果有人需要它:
float remap(float x, float oMin, float oMax, float nMin, float nMax ){
//range check
if( oMin == oMax) {
//std::cout<< "Warning: Zero input range";
return -1; }
if( nMin == nMax){
//std::cout<<"Warning: Zero output range";
return -1; }
//check reversed input range
bool reverseInput = false;
float oldMin = min( oMin, oMax );
float oldMax = max( oMin, oMax );
if (oldMin == oMin)
reverseInput = true;
//check reversed output range
bool reverseOutput = false;
float newMin = min( nMin, nMax );
float newMax = max( nMin, nMax );
if (newMin == nMin)
reverseOutput = true;
float portion = (x-oldMin)*(newMax-newMin)/(oldMax-oldMin);
if (reverseInput)
portion = (oldMax-x)*(newMax-newMin)/(oldMax-oldMin);
float result = portion + newMin;
if (reverseOutput)
result = newMax - portion;
return result; }
下面是一些简单的Python函数,便于复制和粘贴,包括一个扩展整个列表的函数。
def scale_number(unscaled, to_min, to_max, from_min, from_max):
return (to_max-to_min)*(unscaled-from_min)/(from_max-from_min)+to_min
def scale_list(l, to_min, to_max):
return [scale_number(i, to_min, to_max, min(l), max(l)) for i in l]
可以这样使用:
scale_list([1,3,4,5], 0, 100)
[0.0, 50.0, 75.0, 100.0]
在我的例子中,我想缩放一条对数曲线,像这样:
scale_list([math.log(i+1) for i in range(5)], 0, 50)
[0.0, 21.533827903669653, 34.130309724299266, 43.06765580733931, 50.0]
Java版本
不管你喂它什么,它都能工作!
我把所有内容都展开了,这样便于学习。当然,最后舍入是可选的。
private long remap(long p, long Amin, long Amax, long Bmin, long Bmax ) {
double deltaA = Amax - Amin;
double deltaB = Bmax - Bmin;
double scale = deltaB / deltaA;
double negA = -1 * Amin;
double offset = (negA * scale) + Bmin;
double q = (p * scale) + offset;
return Math.round(q);
}