Câu trả lời:
Nếu số X của bạn nằm giữa A và B, và bạn muốn Y nằm giữa C và D, bạn có thể áp dụng phép biến đổi tuyến tính sau:
Y = (X-A)/(B-A) * (D-C) + C
Điều đó sẽ cung cấp cho bạn những gì bạn muốn, mặc dù câu hỏi của bạn hơi mơ hồ, vì bạn cũng có thể lập bản đồ khoảng thời gian theo hướng ngược lại. Chỉ cần chú ý đến phép chia cho số 0 và bạn sẽ ổn.
Y=f(X)=m*X+b
, trong đó m và b đã được xác định cùng một lúc từ hai phương trình ràng buộc sau đó kết quả từ thay thế các giá trị của X và Y tại điểm cuối yêu cầu: C=m*A+b
vàD=m*B+b
X=A+(A-B)*t
để chứng minh sự bình đẳng giữa cách tiếp cận này và của Peter. t bản chất là một nondimensionalization của X. ( t=(X-A)/(A-B)
)
Chia để có tỷ lệ giữa các kích thước của hai phạm vi, sau đó trừ giá trị bắt đầu của phạm vi đầu tiên của bạn, nhân với tỷ lệ và cộng giá trị bắt đầu của phạm vi thứ hai. Nói cách khác,
R = (20 - 10) / (6 - 2)
y = (x - 2) * R + 10
Điều này trải đều các số từ phạm vi đầu tiên trong phạm vi thứ hai.
Sẽ rất tuyệt nếu có chức năng này trong java.lang.Math
lớp, vì đây là một chức năng được yêu cầu rộng rãi và có sẵn trong các ngôn ngữ khác. Đây là một cách triển khai đơn giản:
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;
}
Tôi đang đặt mã này ở đây như một tài liệu tham khảo cho bản thân trong tương lai và có thể nó sẽ giúp ích cho ai đó.
Ngoài ra, đây là vấn đề tương tự như chuyển đổi celcius cổ điển thành giá trị mà bạn muốn ánh xạ một dải số từ 0 - 100 (C) đến 32 - 212 (F).
Mỗi khoảng đơn vị trên phạm vi đầu tiên chiếm (dc) / (ba) "không gian" trên phạm vi thứ hai.
Pseudo:
var interval = (d-c)/(b-a)
for n = 0 to (b - a)
print c + n*interval
Cách bạn xử lý việc làm tròn là tùy thuộc vào bạn.
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);
Tất nhiên với séc chia cho 0.
nếu phạm vi của bạn từ [a đến b] và bạn muốn ánh xạ nó trong [c đến d] trong đó x là giá trị bạn muốn ánh xạ, hãy sử dụng công thức này (ánh xạ tuyến tính)
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)