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 - Cı )). 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.