수학-매핑 번호


답변:


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.