338 votes

Convertir un numéro de plage à l'autre de la gamme, le maintien du ratio

Je suis en train de convertir une plage de numéros à l'autre, le maintien du ratio. Les Maths, c'est pas mon point fort.

J'ai un fichier image où les valeurs de point peut varier de -16000.00 à 16000.00 bien que la gamme typique peut être beaucoup moins. Ce que je veux faire est de compresser ces valeurs dans l'intervalle entier de 0 à 100, où 0 est la valeur de la plus petite, et 100 est la valeur de la plus grande. Tous les points entre les deux doit maintenir un ratio relatif, même si la précision est perdu j'aimerais le faire en python, mais même un algorithme général devrait suffire. Je préfère un algorithme où les min/max ou soit à la portée peut être réglée (c'est à dire, la deuxième gamme de -50 à 800 au lieu de 0 à 100).

669voto

jerryjvl Points 9310
NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin

Ou un peu plus lisible:

OldRange = (OldMax - OldMin)  
NewRange = (NewMax - NewMin)  
NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin

Ou si vous voulez protéger pour le cas où l'ancienne gamme est 0 (OldMin = OldMax):

OldRange = (OldMax - OldMin)
if (OldRange == 0)
    NewValue = NewMin
else
{
    NewRange = (NewMax - NewMin)  
    NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin
}

Notez que dans ce cas nous sommes obligés d'en choisir un de la possible nouvelle gamme de valeurs arbitrairement. Selon le contexte, des choix judicieux pourrait être: est - NewMin (voir l'exemple), NewMax ou (NewMin + NewMax) / 2

76voto

cletus Points 276888

C'est un linéaire simple de conversion.

new_value = ( (old_value - old_min) / (old_max - old_min) ) * (new_max - new_min) + new_min

La conversion 10000 sur l'échelle de -16000 de 16000 à une nouvelle échelle de 0 à 100, on obtient:

old_value = 10000
old_min = -16000
old_max = 16000
new_min = 0
new_max = 100

new_value = ( ( 10000 - -16000 ) / (16000 - -16000) ) * (100 - 0) + 0
          = 81.25

25voto

PenguinTD Points 61

En fait, il existe certains cas que les réponses ci-dessus se briser. Comme, à tort, la valeur d'entrée, à tort, d'entrée de gamme, négatif plages d'entrée/sortie.

def remap( x, oMin, oMax, nMin, nMax ):

    #range check
    if oMin == oMax:
        print "Warning: Zero input range"
        return None

    if nMin == nMax:
        print "Warning: Zero output range"
        return None

    #check reversed input range
    reverseInput = False
    oldMin = min( oMin, oMax )
    oldMax = max( oMin, oMax )
    if not oldMin == oMin:
        reverseInput = True

    #check reversed output range
    reverseOutput = False   
    newMin = min( nMin, nMax )
    newMax = max( nMin, nMax )
    if not newMin == nMin :
        reverseOutput = True

    portion = (x-oldMin)*(newMax-newMin)/(oldMax-oldMin)
    if reverseInput:
        portion = (oldMax-x)*(newMax-newMin)/(oldMax-oldMin)

    result = portion + newMin
    if reverseOutput:
        result = newMax - portion

    return result

#test cases
print remap( 25.0, 0.0, 100.0, 1.0, -1.0 ), "==", 0.5
print remap( 25.0, 100.0, -100.0, -1.0, 1.0 ), "==", -0.25
print remap( -125.0, -100.0, -200.0, 1.0, -1.0 ), "==", 0.5
print remap( -125.0, -200.0, -100.0, -1.0, 1.0 ), "==", 0.5
#even when value is out of bound
print remap( -20.0, 0.0, 100.0, 0.0, 1.0 ), "==", -0.2

9voto

Teddy Garland Points 72

Il y a une condition, lorsque toutes les valeurs que vous contrôlez sont les mêmes, où @jerryjvl code du retour NaN.

        if (OldMin != OldMax && NewMin != NewMax)
            return (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin;
        else
            return (NewMax + NewMin) / 2;  

2voto

fonstok Points 11

J'ai utilisé cette solution à un problème que j'ai des problèmes dans le js, j'ai donc pensé que je voudrais partager la traduction. Merci pour l'explication et la solution.

function remap( x, oMin, oMax, nMin, nMax ){
//range check
if (oMin == oMax){
    console.log("Warning: Zero input range");
    return None;
};

if (nMin == nMax){
    console.log("Warning: Zero output range");
    return None
}

//check reversed input range
var reverseInput = false;
oldMin = Math.min( oMin, oMax );
oldMax = Math.max( oMin, oMax );
if (oldMin != oMin){
    reverseInput = true;
}

//check reversed output range
var reverseOutput = false;  
newMin = Math.min( nMin, nMax )
newMax = Math.max( nMin, nMax )
if (newMin != nMin){
    reverseOutput = true;
};

var portion = (x-oldMin)*(newMax-newMin)/(oldMax-oldMin)
if (reverseInput){
    portion = (oldMax-x)*(newMax-newMin)/(oldMax-oldMin);
};

var result = portion + newMin
if (reverseOutput){
    result = newMax - portion;
}

return result;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X