3

追加要件:

  • 関数の入力は 2 つの数値であり、整数である必要はありません

  • 速度が主な関心事です。できるだけ速くする必要があります

  • 出力が十分にランダムに見える限り、安全である必要はありません。

例:

getValue(0,0) -> 0.326458921
getValue(100,30) -> 0.598713621
getValue(5.12687, 600.471536) -> 0.21458796

編集 明確にするために:出力値は決定論的である必要がありますが、ランダムに見えます。

4

3 に答える 3

0

ハッシュ関数を書くことができます:

function hash(x, y) {
    // You cast the int parts and decimal parts of your entries as 16-bits signed integers.
    var xi = x & 0xFFFF;
    var xf = (((x-xi) * (1 << 16)) & 0xFFFF);
    var yi = y & 0xFFFF;
    var yf = (((y-yi) * (1 << 16)) & 0xFFFF);

    // You hash theses numbers
    var r1 = ((39769 * xi) & 0xFFFF);
    r1 = ((r1 + xf) * 23747) & 0xFFFF;
    r1 = ((r1 + yi) * 19073) & 0xFFFF;
    r1 = ((r1 + yf) * 25609) & 0xFFFF;

    var r2 = ((25609 * xf) & 0xFFFF);
    r2 = ((r2 + yf) * 39769) & 0xFFFF;
    r2 = ((r2 + xi) * 23747) & 0xFFFF;
    r2 = ((r2 + yi) * 19073) & 0xFFFF;

    // And returns a floating number between 0 and 1.
    return ((r1&0xFF)/(1<<24)) + ((r2&0xFFFF)/(1<<16));
}

この関数は、int 部分の最初の 16 ビットのみを保持するため、各 65536 をラップしますが、アイデアはここにあります。ハッシュ関数を変更できます。はるかに良い方法は次のとおりです。

var arrayBuffer = new ArrayBuffer(8);
var dataView = new DataView(arrayBuffer);

function hash(x, y) {
    dataView.setFloat32(0, x);
    dataView.setFloat32(4, y);

    var xi = dataView.getUint16(0);
    var xf = dataView.getUint16(2);
    var yi = dataView.getUint16(4);
    var yf = dataView.getUint16(6);

    // You hash theses numbers
    var r1 = ((39769 * xi) & 0xFFFF);
    r1 = ((r1 + xf) * 23747) & 0xFFFF;
    r1 = ((r1 + yi) * 19073) & 0xFFFF;
    r1 = ((r1 + yf) * 25609) & 0xFFFF;

    var r2 = ((25609 * xf) & 0xFFFF);
    r2 = ((r2 + yf) * 39769) & 0xFFFF;
    r2 = ((r2 + xi) * 23747) & 0xFFFF;
    r2 = ((r2 + yi) * 19073) & 0xFFFF;

    // And returns a floating number between 0 and 1.
    dataView.setUint16(0, r1);
    dataView.setUint16(2, r2);
    return Math.abs(dataView.getFloat32(0) % 1);
}

この最後の方法では WebGLTypedArrayを使用します。これにより、エントリの一部にアクセスでき、より優れたハッシュが得られます。しかし、私の経験からすると、これは本当に遅くなります (私のコンピューターの最初のメソッドでは 8 億回の呼び出し/秒、2 番目のメソッドではわずか 200 万回です。参考までに、従来のランダム関数は 2 億回の呼び出し/秒です)。すべてのブラウザで利用できるわけではありません。

于 2012-07-24T10:05:28.210 に答える
0

これがあなたのニーズに合っているかどうかはわかりませんが、これは私が自発的に思いついたアイデアです (Java の String.hashCode() の JavaScript 実装を使用して、この Web サイトから取得しました: http://werxltd.com/wp/2010/05/ 13/javascript-implementation-of-javas-string-hashcode-method/ )

<script>
    String.prototype.hashCode = function(){
        var hash = 0;
        if (this.length == 0) return hash;
        for (i = 0; i < this.length; i++) {
            char = this.charCodeAt(i);
            hash = ((hash<<5)-hash)+char;
            hash = hash & hash; // Convert to 32bit integer
        }
        return hash;
    }

    function hash(x, y) {
        var hash = Math.abs((x + "" + y).hashCode())
        return hash / Math.pow(10, (hash + "").length);
    }

    alert(hash(5.12687, 600.471536));
</script>
于 2012-07-21T16:51:10.923 に答える
0
unsigned int hash(int key) {
    key +=~(key << 15);
    key ^=(key >> 10);
    key +=(key << 3);
    key ^=(key >> 6);
    key +=~(key << 11);
    key ^=(key >> 16);
    return key;
}

unsigned int localseed = hash(x^hash(y^baseSeed));

これは baseSeed 値を使用しますが、これはオプションです。基本的に、x/y 座標からハッシュを作成します。

于 2013-03-01T06:17:23.150 に答える