Bagaimana cara memetakan angka, secara linier, antara a dan b untuk berpindah antara c dan d.
Artinya, saya ingin angka antara 2 dan 6 dipetakan ke angka antara 10 dan 20 ... tetapi saya memerlukan kasus umum.
Otak saya digoreng.
Bagaimana cara memetakan angka, secara linier, antara a dan b untuk berpindah antara c dan d.
Artinya, saya ingin angka antara 2 dan 6 dipetakan ke angka antara 10 dan 20 ... tetapi saya memerlukan kasus umum.
Otak saya digoreng.
Jawaban:
Jika bilangan X Anda berada di antara A dan B, dan Anda ingin Y berada di antara C dan D, Anda dapat menerapkan transformasi linier berikut:
Y = (X-A)/(B-A) * (D-C) + C
Itu akan memberi Anda apa yang Anda inginkan, meskipun pertanyaan Anda agak ambigu, karena Anda juga bisa memetakan interval ke arah sebaliknya. Hati-hati terhadap pembagian dengan nol dan Anda akan baik-baik saja.
Y=f(X)=m*X+b
, di mana m dan b telah ditentukan secara bersamaan dari dua persamaan kendala berikut yang dihasilkan dari penggantian nilai X dan Y pada titik akhir yang diperlukan: C=m*A+b
danD=m*B+b
X=A+(A-B)*t
untuk membuktikan kesetaraan antara pendekatan ini dan Peter. t pada dasarnya adalah nondimensionalization dari X. ( t=(X-A)/(A-B)
)
Bagilah untuk mendapatkan rasio antara ukuran kedua rentang, lalu kurangi nilai awal rentang awal Anda, kalikan dengan rasio dan tambahkan nilai awal rentang kedua Anda. Dengan kata lain,
R = (20 - 10) / (6 - 2)
y = (x - 2) * R + 10
Ini menyebarkan angka secara merata dari kisaran pertama di kisaran kedua.
Akan menyenangkan memiliki fungsi ini di java.lang.Math
kelas, karena ini adalah fungsi yang sangat dibutuhkan dan tersedia dalam bahasa lain. Berikut ini implementasi sederhana:
final static double EPSILON = 1e-12;
public static double map(double valueCoord1,
double startCoord1, double endCoord1,
double startCoord2, double endCoord2) {
if (Math.abs(endCoord1 - startCoord1) < EPSILON) {
throw new ArithmeticException("/ 0");
}
double offset = startCoord2;
double ratio = (endCoord2 - startCoord2) / (endCoord1 - startCoord1);
return ratio * (valueCoord1 - startCoord1) + offset;
}
Saya meletakkan kode ini di sini sebagai referensi untuk diri saya di masa depan dan mungkin itu akan membantu seseorang.
Selain itu, ini adalah masalah yang sama dengan klasik mengubah celcius ke farenheit di mana Anda ingin memetakan rentang angka yang menyamakan 0 - 100 (C) menjadi 32 - 212 (F).
Setiap interval satuan pada kisaran pertama membutuhkan (dc) / (ba) "spasi" pada kisaran kedua.
Semu:
var interval = (d-c)/(b-a)
for n = 0 to (b - a)
print c + n*interval
Bagaimana Anda menangani pembulatan itu terserah Anda.
int srcMin = 2, srcMax = 6;
int tgtMin = 10, tgtMax = 20;
int nb = srcMax - srcMin;
int range = tgtMax - tgtMin;
float rate = (float) range / (float) nb;
println(srcMin + " > " + tgtMin);
float stepF = tgtMin;
for (int i = 1; i < nb; i++)
{
stepF += rate;
println((srcMin + i) + " > " + (int) (stepF + 0.5) + " (" + stepF + ")");
}
println(srcMax + " > " + tgtMax);
Tentu saja dengan memeriksa bagi dengan nol.
jika rentang Anda dari [a hingga b] dan Anda ingin memetakannya di [c ke d] di mana x adalah nilai yang ingin Anda petakan, gunakan rumus ini (pemetaan linier)
double R = (d-c)/(b-a)
double y = c+(x*R)+R
return(y)
https://rosettacode.org/wiki/Map_range
[a1, a2] => [b1, b2]
if s in range of [a1, a2]
then t which will be in range of [b1, b2]
t= b1 + ((s- a1) * (b2-b1))/ (a2-a1)