257

そのため、数値の範囲を取り、範囲に合わせて値を縮小する方法を見つけようとしています。これをやりたい理由は、Java Swing JPanel で楕円を描こうとしているからです。各楕円の高さと幅を1〜30の範囲にしたい。データセットから最小値と最大値を見つけるメソッドがありますが、実行時まで最小値と最大値はわかりません。これを行う簡単な方法はありますか?

4

8 に答える 8

591

[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

それが私たちが望むものです。したがって、変換とスケーリングを行う必要があります。代わりにとの任意の値を取得したい場合はabもう少し複雑なものが必要です。

       (b-a)(x - min)
f(x) = --------------  + a
          max - min

今のところ入れるとが与えられmin、入れるとが与えられることを確認できます。xamaxb

(b-a)/(max-min)また、これが新しい範囲のサイズと元の範囲のサイズの間のスケーリング係数であることに気付くかもしれません。したがって、実際には、最初にを変換x-min、それを正しい係数にスケーリングしてから、新しい最小値のに変換し直しますa

于 2011-03-14T05:49:25.993 に答える
12

このソリューションに出くわしましたが、これは私のニーズにはあまり合いません。そこで、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);
    }
}
于 2015-03-10T07:08:19.743 に答える