수학-매핑 번호


답변:


211

숫자 X가 A와 B 사이에 있고 Y가 C와 D 사이에 속하도록하려면 다음 선형 변환을 적용 할 수 있습니다.

Y = (X-A)/(B-A) * (D-C) + C

그것은 당신이 원하는 것을 줄 것입니다. 비록 당신이 반대 방향으로 간격을 매핑 할 수 있기 때문에 당신의 질문은 약간 모호합니다. 0으로 나누는 것에주의하면 괜찮을 것입니다.


16
명확성을 위해 new_value = (old_value-old_bottom) / (old_top-old_bottom) * (new_top-new_bottom) + new_bottom;
ftrotter 2014-06-02

1
어딘가에이 방정식에 대한 유도가 있습니까?
shaveenk

@shaveenk 라인의 방정식이어야합니다. Y=f(X)=m*X+b여기서 m과 b는 필요한 끝점에서 X와 Y의 값을 대체 한 다음 두 가지 제약 방정식에서 동시에 결정되었습니다. C=m*A+b그리고D=m*B+b
Chris Chiasson

나는 또한 X=A+(A-B)*t이 접근 방식과 Peter의 접근 방식이 동등 함을 증명하기 위해 사용해야 했습니다. t는 기본적으로 X에서의 무차 원화 (이다 t=(X-A)/(A-B))
크리스 Chiasson

방향을 바꾸려면 공식은 ((XA) / (AB) * (CD)) * -1 + D
Corey Levinson 2018

21

두 범위의 크기 사이의 비율을 구하기 위해 나눈 다음 초기 범위의 시작 값을 빼고 비율을 곱한 다음 두 번째 범위의 시작 값을 더합니다. 다시 말해,

R = (20 - 10) / (6 - 2)
y = (x - 2) * R + 10

이렇게하면 두 번째 범위의 첫 번째 범위에있는 숫자가 균등하게 분산됩니다.


이것은 작동하지 않습니다. 내 범위는 1000000000 ~ 9999999999이고 숫자는 1 ~ 999999999 일 수 있습니다.
Dejell

@Odelya 물론 작동합니다. 이것은 충분히 간단한 수학적 변환입니다. 충분히 큰 숫자 유형 (bignum 또는 유사)을 사용해야합니다. 숫자는 32 비트 정수에 비해 너무 큽니다. 예를 들어 64 비트 정수가 작동합니다.
Konrad Rudolph

이중 유형입니다. 이중 R = (20-10) / (6-2); 이중 y = (X-2) * R + 10;
Dejell 2013

@Odelya 그래도 같은 문제입니다. 부동 소수점 정밀도를 읽어야합니다. 사실, 이것은 읽기가 필요합니다 : 모든 컴퓨터 과학자가 부동 소수점 산술에 대해 알아야 할 것 – 만약 당신이 그렇게 큰 숫자를 가진 부동 소수점 유형이 필요하다면, 임의의 정밀도 숫자 유형 을 사용해야 할 수도 있습니다 .
Konrad Rudolph

내가 할 수있는 자바 타입을 추천 해 줄 수 있나요?
Dejell 2013

7

이 기능은 java.lang.Math광범위하게 필요한 기능이고 다른 언어로도 사용할 수 있기 때문에 클래스 에이 기능이 있으면 좋을 것 입니다. 다음은 간단한 구현입니다.

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

이 코드를 미래에 대한 참조로 여기에 넣고 누군가에게 도움이 될 수 있습니다.


4

제쳐두고, 이것은 0-100 (C)에서 32-212 (F)에 해당하는 숫자 범위를 매핑하려는 고전적인 섭씨를 화씨로 변환하는 것과 동일한 문제입니다.


이것은 어떻게 대답입니까?
shinzou

질문 적용 사례입니다. 많은 사람들이 초급 CS 수업에서이 간단한 문제를 가지고 있으며 솔루션이 다른 문제로 일반화 될 수 있다고 생각하지 않습니다. 원래 질문에 컨텍스트를 추가하려고했습니다. 원래 질문은 이미 적절하게 답변되었습니다.
Metro

1

첫 번째 범위의 각 단위 간격은 두 번째 범위의 (dc) / (ba) "공백"을 차지합니다.

가짜:

var interval = (d-c)/(b-a)
for n = 0 to (b - a)
    print c + n*interval

반올림 처리 방법은 귀하에게 달려 있습니다.


1
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);

물론 0으로 나누는 검사를 사용합니다.


1

범위가 [a에서 b]이고 [c에서 d]로 매핑하려는 경우 여기에서 x는 매핑하려는 값입니다.이 공식을 사용합니다 (선형 매핑).

double R = (d-c)/(b-a)
double y = c+(x*R)+R
return(y)


0

@PeterAllenWebb 답변 외에도 결과를 되돌리려면 다음을 사용하십시오.

reverseX = (B-A)*(Y-C)/(D-C) + A
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.