そのため、数値の範囲を取り、範囲に合わせて値を縮小する方法を見つけようとしています。これをやりたい理由は、Java Swing JPanel で楕円を描こうとしているからです。各楕円の高さと幅を1〜30の範囲にしたい。データセットから最小値と最大値を見つけるメソッドがありますが、実行時まで最小値と最大値はわかりません。これを行う簡単な方法はありますか?
8 に答える
[min,max]
範囲をにスケーリングするとし[a,b]
ます。あなたは満足する(連続)関数を探しています
f(min) = a
f(max) = b
あなたの場合、a
は1で30になりますが、もっと簡単なものから始めて、範囲b
にマッピングしてみましょう。[min,max]
[0,1]
関数に入れmin
て0を出すことは、次のようにして達成できます。
f(x) = x - min ===> f(min) = min - min = 0
だから、それはほとんど私たちが望んでいることです。しかし、入れると、実際に1が必要なときにmax
得られmax - min
ます。したがって、スケーリングする必要があります。
x - min max - min
f(x) = --------- ===> f(min) = 0; f(max) = --------- = 1
max - min max - min
それが私たちが望むものです。したがって、変換とスケーリングを行う必要があります。代わりにとの任意の値を取得したい場合はa
、b
もう少し複雑なものが必要です。
(b-a)(x - min)
f(x) = -------------- + a
max - min
今のところ入れるとが与えられmin
、入れるとが与えられることを確認できます。x
a
max
b
(b-a)/(max-min)
また、これが新しい範囲のサイズと元の範囲のサイズの間のスケーリング係数であることに気付くかもしれません。したがって、実際には、最初にを変換x
し-min
、それを正しい係数にスケーリングしてから、新しい最小値のに変換し直しますa
。
このソリューションに出くわしましたが、これは私のニーズにはあまり合いません。そこで、d3 のソース コードを少し掘り下げました。個人的には d3.scale のようにすることをお勧めします。
したがって、ここではドメインを範囲にスケーリングします。利点は、標識をターゲット範囲に反転できることです。これは、コンピューター画面の y 軸が上から下に移動するため、大きな値の y が小さくなるため便利です。
public class Rescale {
private final double range0,range1,domain0,domain1;
public Rescale(double domain0, double domain1, double range0, double range1) {
this.range0 = range0;
this.range1 = range1;
this.domain0 = domain0;
this.domain1 = domain1;
}
private double interpolate(double x) {
return range0 * (1 - x) + range1 * x;
}
private double uninterpolate(double x) {
double b = (domain1 - domain0) != 0 ? domain1 - domain0 : 1 / domain1;
return (x - domain0) / b;
}
public double rescale(double x) {
return interpolate(uninterpolate(x));
}
}
そして、これが私が何を意味するかを見ることができるテストです
public class RescaleTest {
@Test
public void testRescale() {
Rescale r;
r = new Rescale(5,7,0,1);
Assert.assertTrue(r.rescale(5) == 0);
Assert.assertTrue(r.rescale(6) == 0.5);
Assert.assertTrue(r.rescale(7) == 1);
r = new Rescale(5,7,1,0);
Assert.assertTrue(r.rescale(5) == 1);
Assert.assertTrue(r.rescale(6) == 0.5);
Assert.assertTrue(r.rescale(7) == 0);
r = new Rescale(-3,3,0,1);
Assert.assertTrue(r.rescale(-3) == 0);
Assert.assertTrue(r.rescale(0) == 0.5);
Assert.assertTrue(r.rescale(3) == 1);
r = new Rescale(-3,3,-1,1);
Assert.assertTrue(r.rescale(-3) == -1);
Assert.assertTrue(r.rescale(0) == 0);
Assert.assertTrue(r.rescale(3) == 1);
}
}