Matematik - sayıları eşleme


Yanıtlar:


213

X numaranız A ile B arasına denk geliyorsa ve Y'nin C ile D arasında kalmasını istiyorsanız, aşağıdaki doğrusal dönüşümü uygulayabilirsiniz:

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

Bu size istediğinizi vermelidir, ancak sorunuz biraz belirsizdir, çünkü aralığı ters yönde de haritalayabilirsiniz. Sadece sıfıra bölmeye dikkat edin ve iyi olmalısınız.


17
Netlik sağlamak için, new_value = (old_value - old_bottom) / (old_top - old_bottom) * (new_top - new_bottom) + new_bottom;
ftrotter

1
Bu denklem için bir yerde bir türev var mı?
shaveenk

@shaveenk Y=f(X)=m*X+b, m ve b'nin gerekli uç noktalarda X ve Y değerlerinin ikame edilmesinden kaynaklanan aşağıdaki iki kısıt denkleminden eşzamanlı olarak belirlendiği bir çizginin denklemi olmalıdır : C=m*A+bveD=m*B+b
Chris Chiasson

Ayrıca X=A+(A-B)*tbu yaklaşımla Peter'ın eşitliğini kanıtlamak için kullanma ihtiyacım da oldu . t esasen X'in boyutsuzlaştırılmasıdır. ( t=(X-A)/(A-B))
Chris Chiasson

Yönü tersine çevirmek için formül ((XA) / (AB) * (CD)) * -1 + D
Corey Levinson

21

İki aralığın boyutları arasındaki oranı elde etmek için bölün, ardından başlangıç ​​aralığınızın başlangıç ​​değerini çıkarın, oranla çarpın ve ikinci aralığınızın başlangıç ​​değerini ekleyin. Diğer bir deyişle,

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

Bu, ikinci aralıktaki ilk aralıktaki sayıları eşit olarak dağıtır.


Bu çalışmıyor.
Aralığım

@Odelya Elbette işe yarıyor. Bu yeterince basit bir matematiksel dönüşümdür. Yeterince büyük bir sayı türü (bignum veya benzeri) kullanmanız yeterlidir. Sayılarınız 32 bitlik tam sayılar için çok büyük - ancak örneğin 64 bitlik tam sayılar işe yarayacaktır.
Konrad Rudolph

Çift tiptedirler. çift ​​R = (20 - 10) / (6 - 2); çift ​​y = (X - 2) * R + 10;
Dejell

@Odelya Yine de aynı sorun. Kayan nokta hassasiyetini okumalısınız. Aslında, şunu okumak gerekir: Her Bilgisayar Bilimcisinin Kayan Nokta Aritmetiği Hakkında Bilmesi Gerekenler - Bu kadar büyük sayılara sahip bir kayan nokta türüne ihtiyacınız varsa, keyfi kesinlikte bir sayı türü kullanmanız gerekebilir .
Konrad Rudolph

Yapabileceğim bir java türü tavsiye edebilir misiniz?
Dejell

7

java.lang.MathSınıfta bu işlevselliğe sahip olmak güzel olurdu , çünkü bu çokça gerekli bir işlevdir ve diğer dillerde mevcuttur. İşte basit bir uygulama:

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

Bu kodu buraya kendim için referans olarak koyuyorum ve belki birine yardımcı olabilir.


4

Bir kenara olarak, bu, 0 - 100 (C) ile 32 - 212 (F) arasında bir sayı aralığını eşleştirmek istediğinizde, klasik celcius'u farenheit'e dönüştürmeyle aynı problemdir.


Bu nasıl bir cevap?
shinzou

Sorunun uygulanmasına bir örnektir. Birçoğunun bu basit problemi giriş bilgisayarları derslerinde var ve çözümün diğer problemlere genelleştirilebileceğini düşünmüyorlar. Orijinal soruya bağlam eklemeye çalışıyordum. İlk soru zaten yeterince cevaplanmıştı.
Metro


1

İlk aralıktaki her birim aralığı, ikinci aralıkta (dc) / (ba) "boşluk" kaplar.

Sözde:

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

Yuvarlamayı nasıl idare edeceğiniz size kalmış.


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

Elbette, sıfıra bölme kontrolleri ile.


1

[a - b] aralığınız varsa ve [c - d] ile eşlemek istiyorsanız, burada x eşlemek istediğiniz değerdir, bu formülü kullanın (doğrusal eşleme)

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

0

@PeterAllenWebb cevabına ek olarak, sonucu geri almak isterseniz aşağıdakileri kullanın:

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

0

Burada X, eşlemek için sayıdır , A - B için C - D ve Y, sonuç: lineer interpolasyon formülü LERP (al a , b , m ) = bir + ( m, * ( b - a )), ve koymak C ve D yerine bir ve b için Y = C + ( m * ( D - C )). Sonra m yerine ( X -A ) / ( B - A ) elde etmek için Y, = C + ((( X - Bir ) / ( B - A * ()) D - )). Bu iyi bir harita işlevidir, ancak basitleştirilebilir. ( D - C ) parçasını alın ve Y = C + ((( X - A ) * ( D - C )) / ( B - A )) elde etmek için kar payının içine koyun . Bu bize basitleştirebileceğimiz başka bir parça verir, ( X - A ) * ( D- C ), yani ( X * D ) - ( X * C ) - ( A * D ) + ( A * C ) ' ye eşittir . Açın ve Y = C + ((( X * D ) - ( X * C ) - ( A * D ) + ( A * C )) / ( B - A )) elde edin. Yapmanız gereken bir sonraki şey, + C bitini eklemek . Bunu yapmak için, C'yi ( B - A) (( B * C ) - ( A * C )) elde etmek için ve Y = ((( X * D ) - ( X * C ) - ( A * D ) + ( A * C ) + ( B * C ) - ( A * C )) / ( B - A )). Bu , birbirini iptal eden hem a + ( A * C ) hem de a - ( A * C ) içeren fazlalıktır . Bunları kaldırırsanız şunların nihai sonucunu alırsınız:Y = (( X * D ) - ( X * C ) - ( A * D ) + ( B * C )) / ( B - A )

TL; DR: Standart harita fonksiyonu, Y = C + ((( X - A ) / ( B - A )) * ( D - C )), Y = (( X * D ) - ( X * C ) - ( A * D ) + ( B * C )) / ( B - A )

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.