我试图将一个范围的数字转换为另一个,保持比率。数学不是我的强项。
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).
使用Numpy和interp函数,你可以将你的值从旧范围转换为新范围:
>>> import numpy as np
>>> np.interp(0, [-16000,16000], [0,100])
50.0
你也可以尝试映射一个值列表:
>>> np.interp([-16000,0,12000] ,[-16000,16000], [0,100])
array([ 0. , 50. , 87.5])
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);
}
增加了KOTLIN版本的数学解释
假设我们有一个介于(OMin, Omax)之间的刻度,我们在这个范围内有一个值X
我们要把它转换成比例(NMin, NMax)
我们知道X,我们需要找到Y,比值必须相等:
=> (Y-NMin)/(NMax-NMin) = (X-OMin)/(OMax-OMin)
=> (Y-NMin)/NewRange = (X-OMin)/OldRange
=> Y = ((X-OMin)*NewRange)/oldRange)+NMin Answer
从实用主义的角度来看,我们可以这样写这个问句:
private fun convertScale(oldValueToConvert:Int): Float {
// Old Scale 50-100
val oldScaleMin = 50
val oldScaleMax = 100
val oldScaleRange= (oldScaleMax - oldScaleMin)
//new Scale 0-1
val newScaleMin = 0.0f
val newScaleMax = 1.0f
val newScaleRange= (newScaleMax - newScaleMin)
return ((oldValueToConvert - oldScaleMin)* newScaleRange/ oldScaleRange) + newScaleMin
}
JAVA
/**
*
* @param x
* @param inMin
* @param inMax
* @param outMin
* @param outMax
* @return
*/
private long normalize(long x, long inMin, long inMax, long outMin, long outMax) {
long outRange = outMax - outMin;
long inRange = inMax - inMin;
return (x - inMin) *outRange / inRange + outMin;
}
用法:
float brightness = normalize(progress, 0, 10, 0,255);
我个人使用支持泛型的helper类(Swift 3,4)。x兼容)
struct Rescale<Type : BinaryFloatingPoint> {
typealias RescaleDomain = (lowerBound: Type, upperBound: Type)
var fromDomain: RescaleDomain
var toDomain: RescaleDomain
init(from: RescaleDomain, to: RescaleDomain) {
self.fromDomain = from
self.toDomain = to
}
func interpolate(_ x: Type ) -> Type {
return self.toDomain.lowerBound * (1 - x) + self.toDomain.upperBound * x;
}
func uninterpolate(_ x: Type) -> Type {
let b = (self.fromDomain.upperBound - self.fromDomain.lowerBound) != 0 ? self.fromDomain.upperBound - self.fromDomain.lowerBound : 1 / self.fromDomain.upperBound;
return (x - self.fromDomain.lowerBound) / b
}
func rescale(_ x: Type ) -> Type {
return interpolate( uninterpolate(x) )
}
}
Ex:
let rescaler = Rescale<Float>(from: (-1, 1), to: (0, 100))
print(rescaler.rescale(0)) // OUTPUT: 50