384 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).

9voto

Teddy Garland Punkte 117

Es gibt eine Bedingung, wenn alle zu prüfenden Werte gleich sind, bei der der Code von @jerryjvl NaN zurückgeben würde.

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

6voto

Tabaraei Punkte 389

使用方法 Numpy y interp Funktion, können Sie Ihren Wert vom alten Bereich in den neuen Bereich umrechnen :

>>> import numpy as np
>>> np.interp(0, [-16000,16000], [0,100])
50.0

Sie können es auch versuchen, um eine Liste von Werten abbilden :

>>> np.interp([-16000,0,12000] ,[-16000,16000], [0,100])
array([ 0. , 50. , 87.5])

5voto

Hitesh Sahu Punkte 37527

KOTLIN-Version mit mathematischer Erläuterung hinzugefügt

Nehmen wir an, wir haben eine Skala zwischen (OMin, Omax) und wir haben einen Wert X in diesem Bereich

Wir wollen es in einen Maßstab umwandeln (NMin, NMax)

Wir kennen X und müssen Y finden, das Verhältnis muss gleich sein:

 => (Y-NMin)/(NMax-NMin) = (X-OMin)/(OMax-OMin)  

 =>  (Y-NMin)/NewRange = (X-OMin)/OldRange 

 =>   Y = ((X-OMin)*NewRange)/oldRange)+NMin  Answer

Pragmatisch können wir diese Frage wie folgt formulieren:

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

Verwendung:

float brightness = normalize(progress, 0, 10, 0,255);

3voto

Grzegorz Krukowski Punkte 15401

Ich persönlich verwende die Hilfsklasse, die Generika unterstützt (Swift 3, 4.x kompatibel)

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

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

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