Próbuję przekonwertować jeden zakres liczb na inny, zachowując stosunek. Matematyka nie jest moją mocną stroną.
Mam plik obrazu, w którym wartości punktowe mogą wynosić od -16000,00 do 16000,00, chociaż typowy zakres może być znacznie mniejszy. Chcę skompresować te wartości do zakresu liczb całkowitych 0-100, gdzie 0 to wartość najmniejszego punktu, a 100 to wartość największego. Wszystkie punkty pośrednie powinny zachować względny stosunek, nawet pomimo utraty pewnej precyzji. Chciałbym to zrobić w Pythonie, ale nawet ogólny algorytm powinien wystarczyć. Wolałbym algorytm, w którym można dostosować min / maks lub dowolny zakres (tj. Drugi zakres może wynosić od -50 do 800 zamiast od 0 do 100).
Odpowiedzi:
Lub trochę bardziej czytelny:
Lub jeśli chcesz chronić w przypadku, gdy stary zakres wynosi 0 ( OldMin = OldMax ):
Zauważ, że w tym przypadku jesteśmy zmuszeni arbitralnie wybrać jedną z możliwych nowych wartości zakresu. W zależności od kontekstu rozsądnymi wyborami mogą być:
NewMin
( patrz próbka )NewMax
lub(NewMin + NewMax) / 2
źródło
To prosta konwersja liniowa.
Tak więc konwersja 10000 w skali od -16000 do 16000 do nowej skali od 0 do 100 daje:
źródło
W rzeczywistości istnieją przypadki, w których powyższe odpowiedzi byłyby zepsute. Takich jak błędnie wprowadzona wartość, błędnie wprowadzony zakres, ujemne zakresy wejścia / wyjścia.
źródło
Istnieje warunek, gdy wszystkie wartości, które sprawdzasz, są takie same, a kod @ jerryjvl zwróci NaN.
źródło
Nie wykopałem w tym celu BNF , ale dokumentacja Arduino miała świetny przykład tej funkcji i jej awarii. Byłem w stanie użyć tego w Pythonie, po prostu dodając zmianę nazwy def do mapowania (ponieważ mapa jest wbudowana) i usuwając rzutowania typu i nawiasy klamrowe (tj. Po prostu usuwam wszystkie długie).
Oryginalny
Pyton
https://www.arduino.cc/en/reference/map
źródło
W zestawieniu dostarczonym przez PenguinTD nie rozumiem, dlaczego zakresy są odwrócone, działa bez konieczności odwracania zakresów. Liniowa konwersja zakresu opiera się na równaniu liniowym
Y=Xm+n
, gdziem
in
są uzyskiwane z podanych zakresów. Zamiast odwoływać się do zakresów jakomin
imax
, lepiej byłoby odwoływać się do nich jako 1 i 2. Zatem wzór byłby następujący:Gdzie,
Y=y1
kiedyX=x1
iY=y2
kiedyX=x2
.x1
,x2
,y1
Iy2
można nadać dowolnypositive
lubnegative
wartość. Zdefiniowanie wyrażenia w makrze sprawia, że jest ono bardziej użyteczne, można go zatem używać z dowolnymi nazwami argumentów.float
Obsada zapewniłoby zmiennoprzecinkowych podział w przypadku, gdy wszystkie argumenty sąinteger
wartości. W zależności od zastosowania może nie być konieczne sprawdzenie zakresówx1=x2
iy1==y2
.źródło
float RangeConv(float input, float x1, float x2, float y1, float y2) { return (((input - x1) * (y2 - y1)) / (x2 - x1)) + y1; }
Oto kilka krótkich funkcji Pythona dla ułatwienia kopiowania i wklejania, w tym funkcja skalowania całej listy.
Które można wykorzystać tak:
W moim przypadku chciałem przeskalować krzywą logarytmiczną, tak:
źródło
Użyłem tego rozwiązania w problemie, który rozwiązałem w js, więc pomyślałem, że podzielę się tłumaczeniem. Dzięki za wyjaśnienie i rozwiązanie.
źródło
Wariant C ++
Uważam, że rozwiązanie PenguinTD jest przydatne, więc przeniosłem je do C ++, jeśli ktoś tego potrzebuje:
źródło
Port PHP
Uznałem, że rozwiązanie PenguinTD jest pomocne, więc przeniosłem je na PHP. Pomóż sobie!
źródło
Oto wersja Javascript, która zwraca funkcję, która wykonuje przeskalowanie dla z góry określonych zakresów źródłowych i docelowych, minimalizując ilość obliczeń, które należy wykonać za każdym razem.
Oto przykład użycia tej funkcji do skalowania 0-1 do -0x80000000, 0x7FFFFFFF
źródło
Wniosek skrócony / uproszczony
Wayne
źródło
NewRange/OldRange
tu jestOsobiście używam klasy pomocnika, która obsługuje generyczne (kompatybilny z Swift 3)
źródło
Ten przykład przekształca bieżącą pozycję utworu w zakres kątów 20–40.
źródło
Zrozumienie listy jedno rozwiązanie liniowe
Dłuższa wersja
źródło
Wersja Java
Zawsze działa bez względu na to, co go karmisz!
Zostawiłem wszystko rozszerzone, aby łatwiej było podążać za nauką. Zaokrąglanie na końcu jest oczywiście opcjonalne.
źródło