397 Stimmen

Umwandlung eines Zahlenbereichs in einen anderen Bereich unter Beibehaltung des Verhältnisses

Ich versuche, einen Zahlenbereich in einen anderen umzurechnen und dabei das Verhältnis beizubehalten. Mathe ist nicht meine Stärke.

Ich habe eine Bilddatei, in der die Punktwerte von -16000.00 bis 16000.00 reichen können, obwohl der typische Bereich viel kleiner sein kann. Ich möchte diese Werte in den ganzzahligen Bereich 0-100 komprimieren, wobei 0 der Wert des kleinsten Punktes und 100 der Wert des größten Punktes ist. Alle Punkte dazwischen sollten ein relatives Verhältnis behalten, auch wenn etwas Präzision verloren geht. Ich möchte dies in Python tun, aber auch ein allgemeiner Algorithmus sollte ausreichen. Ich würde einen Algorithmus bevorzugen, bei dem der Min-/Max-Wert oder einer der beiden Bereiche angepasst werden kann (d.h. der zweite Bereich könnte -50 bis 800 statt 0 bis 100 sein).

2voto

Brian Plummer Punkte 31

In der Auflistung von PenguinTD verstehe ich nicht, warum die Bereiche vertauscht sind, es funktioniert auch ohne Umkehrung der Bereiche. Die lineare Bereichskonvertierung basiert auf der folgenden linearen Gleichung Y=Xm+n , donde m y n werden aus den angegebenen Bereichen abgeleitet. Anstatt sich auf die Bereiche als min y max wäre es besser, sie als 1 und 2 zu bezeichnen. Die Formel würde also lauten:

Y = (((X - x1) * (y2 - y1)) / (x2 - x1)) + y1

どこ Y=y1 wenn X=x1 y Y=y2 wenn X=x2 . x1 , x2 , y1 & y2 kann jede beliebige positive o negative Wert. Die Definition des Ausdrucks in einem Makro macht ihn nützlicher, da er dann mit beliebigen Argumentnamen verwendet werden kann.

#define RangeConv(X, x1, x2, y1, y2) (((float)((X - x1) * (y2 - y1)) / (x2 - x1)) + y1)

El float cast würde eine Gleitkommadivision gewährleisten, wenn alle Argumente integer Werte. Je nach Anwendung ist es möglicherweise nicht erforderlich, die Bereiche zu überprüfen x1=x2 y y1==y2 .

0 Stimmen

Merci ! hier ist die C#-Konvertierung: float RangeConv(float input, float x1, float x2, float y1, float y2) { return (((input - x1) * (y2 - y1)) / (x2 - x1)) + y1; }

1voto

user1767754 Punkte 20816

C++-Variante

Ich fand die Lösung von PenguinTD nützlich, also habe ich sie nach C++ portiert, falls jemand sie braucht:

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; }

1voto

Neil Punkte 52

PHP-Anschluss

Da ich die Lösung von PenguinTD hilfreich fand, habe ich sie auf PHP portiert. Helfen Sie sich selbst!

/**
* =====================================
*              Remap Range            
* =====================================
* - Convert one range to another. (including value)
*
* @param    int $intValue   The value in the old range you wish to convert
* @param    int $oMin       The minimum of the old range
* @param    int $oMax       The maximum of the old range
* @param    int $nMin       The minimum of the new range
* @param    int $nMax       The maximum of the new range
*
* @return   float $fResult  The old value converted to the new range
*/
function remapRange($intValue, $oMin, $oMax, $nMin, $nMax) {
    // Range check
    if ($oMin == $oMax) {
        echo 'Warning: Zero input range';
        return false;
    }

    if ($nMin == $nMax) {
        echo 'Warning: Zero output range';
        return false;
    }

    // Check reversed input range
    $bReverseInput = false;
    $intOldMin = min($oMin, $oMax);
    $intOldMax = max($oMin, $oMax);
    if ($intOldMin != $oMin) {
        $bReverseInput = true;
    }

    // Check reversed output range
    $bReverseOutput = false;
    $intNewMin = min($nMin, $nMax);
    $intNewMax = max($nMin, $nMax);
    if ($intNewMin != $nMin) {
        $bReverseOutput = true;
    }

    $fRatio = ($intValue - $intOldMin) * ($intNewMax - $intNewMin) / ($intOldMax - $intOldMin);
    if ($bReverseInput) {
        $fRatio = ($intOldMax - $intValue) * ($intNewMax - $intNewMin) / ($intOldMax - $intOldMin);
    }

    $fResult = $fRatio + $intNewMin;
    if ($bReverseOutput) {
        $fResult = $intNewMax - $fRatio;
    }

    return $fResult;
}

1voto

Jamie Fenton Punkte 76

Hier ist eine Javascript-Version, die eine Funktion zurückgibt, die die Skalierung für vorgegebene Quell- und Zielbereiche vornimmt und so die Menge der Berechnungen, die jedes Mal durchgeführt werden müssen, minimiert.

// This function returns a function bound to the 
// min/max source & target ranges given.
// oMin, oMax = source
// nMin, nMax = dest.
function makeRangeMapper(oMin, oMax, nMin, nMax ){
    //range check
    if (oMin == oMax){
        console.log("Warning: Zero input range");
        return undefined;
    };

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

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

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

    // Hot-rod the most common case.
    if (!reverseInput && !reverseOutput) {
        let dNew = newMax-newMin;
        let dOld = oldMax-oldMin;
        return (x)=>{
            return ((x-oldMin)* dNew / dOld) + newMin;
        }
    }

    return (x)=>{
        let portion;
        if (reverseInput){
            portion = (oldMax-x)*(newMax-newMin)/(oldMax-oldMin);
        } else {
            portion = (x-oldMin)*(newMax-newMin)/(oldMax-oldMin)
        }
        let result;
        if (reverseOutput){
            result = newMax - portion;
        } else {
            result = portion + newMin;
        }

        return result;
    }   
}

Hier ist ein Beispiel für die Verwendung dieser Funktion zur Skalierung 0-1 in -0x80000000, 0x7FFFFFFF

let normTo32Fn = makeRangeMapper(0, 1, -0x80000000, 0x7FFFFFFF);
let fs = normTo32Fn(0.5);
let fs2 = normTo32Fn(0);

1voto

zulia Punkte 11

Liste Verständnis Einzeiler Lösung

color_array_new = [int((((x - min(node_sizes)) * 99) / (max(node_sizes) - min(node_sizes))) + 1) for x in node_sizes]

Längere Version

def colour_specter(waste_amount):
color_array = []
OldRange = max(waste_amount) - min(waste_amount)
NewRange = 99
for number_value in waste_amount:
    NewValue = int((((number_value - min(waste_amount)) * NewRange) / OldRange) + 1)
    color_array.append(NewValue)
print(color_array)
return color_array

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X