返回列表

随机数加随机序列

默认分类 2016/01/18 03:38

随机数加随机序列

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled 1</title>
<script type="text/javascript">
<!--
// 3, 1, 4
// 30, 1 , 4

function doit(countNum, min, max, seed){ 
    //todo
    seed = seed === undefined ? new Date().getTime() + Math.random()*100000000 : Number(seed);
    min  = min  === undefined ? 0 : Number(min);
    max  = max  === undefined ? 100000000000000 : Number(max) + 1;

    var list = [],
        key,
        result = [];

    if (Object.prototype.toString.call(countNum) !== '[object Array]') {
        count = Math.max(Number(countNum), max - min);
        for (var i=0,len=count; i<len; i++) {
            list.push(min + i%(max-min));
        }
    }
    else {
        list = countNum;
    }
    list.sort(function(m,n){ return Math.random() > 0.5});

    var count = list;
    list = [];

    for (var i=0,len=count.length; i<len; i++) {
        key = Number(String(((i+seed)*9301+49297)%233280/233280.0).replace('0.', '').substring(6, 7));
        list.push({index: key, value: i});
    }

    var field = 'index',
        order = 'desc';
    list = list.sort(function (a, b) {
        var m, n;
        m = String(a[field]).toLowerCase();
        n = String(b[field]).toLowerCase();

        if (String(parseInt('0' + m, 10)) == m && String(parseInt('0' + n, 10)) == n) {
            m = parseInt(m, 10);
            n = parseInt(n, 10);
        }
        else {
            if (m > n) {
                m = 1;
                n = -m;
            }
            else if (m < n) {
                m = -1;
                n = -m;
            }
            else {
                m = 1;
                n = m;
            }
        }
        return (order == 'desc' ? n - m : m - n);
    });

    for (var i=0,len=list.length; i<len; i++) {
        result.push(count[list[i].value]);
    }

    if (Object.prototype.toString.call(countNum) !== '[object Array]') {
        list = result.splice(0, countNum);
    }
    else {
        list = result;
    }

    alert(list);
}
function doit2(){
    //Todo
    doit(10, 1, 4)
}

//-->
</script>
</head>

<body><button type="button" onclick="doit2()">doit</button>

</body>

</html>

======================================
注:实测这种方式生成的随机数概率不均匀!! 不推荐!

推荐 https://www.npmjs.com/package/random-js

源码及示例如下:(见最后)

/*jshint eqnull:true*/
(function (root) {
    "use strict";

    var GLOBAL_KEY = "Random";

    var imul = (typeof Math.imul !== "function" || Math.imul(0xffffffff, 5) !== -5 ?
        function (a, b) {
            var ah = (a >>> 16) & 0xffff;
            var al = a & 0xffff;
            var bh = (b >>> 16) & 0xffff;
            var bl = b & 0xffff;
            // the shift by 0 fixes the sign on the high part
            // the final |0 converts the unsigned value into a signed value
            return (al * bl) + (((ah * bl + al * bh) << 16) >>> 0) | 0;
        } :
        Math.imul);

    var stringRepeat = (typeof String.prototype.repeat === "function" && "x".repeat(3) === "xxx" ?
        function (x, y) {
            return x.repeat(y);
        } : function (pattern, count) {
            var result = "";
            while (count > 0) {
                if (count & 1) {
                    result += pattern;
                }
                count >>= 1;
                pattern += pattern;
            }
            return result;
        });

    function Random(engine) {
        if (!(this instanceof Random)) {
            return new Random(engine);
        }

        if (engine == null) {
            engine = Random.engines.nativeMath;
        }
        else if (typeof engine !== "function") {
            throw new TypeError("Expected engine to be a function, got " + typeof engine);
        }
        this.engine = engine;
    }
    var proto = Random.prototype;

    Random.engines = {
        nativeMath: function () {
            return (Math.random() * 0x100000000) | 0;
        },
        mt19937: (function (Int32Array) {
            // http://en.wikipedia.org/wiki/Mersenne_twister
            function refreshData(data) {
                var k = 0;
                var tmp = 0;
                for (;
                    (k | 0) < 227; k = (k + 1) | 0) {
                    tmp = (data[k] & 0x80000000) | (data[(k + 1) | 0] & 0x7fffffff);
                    data[k] = data[(k + 397) | 0] ^ (tmp >>> 1) ^ ((tmp & 0x1) ? 0x9908b0df : 0);
                }

                for (;
                    (k | 0) < 623; k = (k + 1) | 0) {
                    tmp = (data[k] & 0x80000000) | (data[(k + 1) | 0] & 0x7fffffff);
                    data[k] = data[(k - 227) | 0] ^ (tmp >>> 1) ^ ((tmp & 0x1) ? 0x9908b0df : 0);
                }

                tmp = (data[623] & 0x80000000) | (data[0] & 0x7fffffff);
                data[623] = data[396] ^ (tmp >>> 1) ^ ((tmp & 0x1) ? 0x9908b0df : 0);
            }

            function temper(value) {
                value ^= value >>> 11;
                value ^= (value << 7) & 0x9d2c5680;
                value ^= (value << 15) & 0xefc60000;
                return value ^ (value >>> 18);
            }

            function seedWithArray(data, source) {
                var i = 1;
                var j = 0;
                var sourceLength = source.length;
                var k = Math.max(sourceLength, 624) | 0;
                var previous = data[0] | 0;
                for (;
                    (k | 0) > 0; --k) {
                    data[i] = previous = ((data[i] ^ imul((previous ^ (previous >>> 30)), 0x0019660d)) + (source[j] | 0) + (j | 0)) | 0;
                    i = (i + 1) | 0;
                    ++j;
                    if ((i | 0) > 623) {
                        data[0] = data[623];
                        i = 1;
                    }
                    if (j >= sourceLength) {
                        j = 0;
                    }
                }
                for (k = 623;
                    (k | 0) > 0; --k) {
                    data[i] = previous = ((data[i] ^ imul((previous ^ (previous >>> 30)), 0x5d588b65)) - i) | 0;
                    i = (i + 1) | 0;
                    if ((i | 0) > 623) {
                        data[0] = data[623];
                        i = 1;
                    }
                }
                data[0] = 0x80000000;
            }

            function mt19937() {
                var data = new Int32Array(624);
                var index = 0;
                var uses = 0;

                function next() {
                    if ((index | 0) >= 624) {
                        refreshData(data);
                        index = 0;
                    }

                    var value = data[index];
                    index = (index + 1) | 0;
                    uses += 1;
                    return temper(value) | 0;
                }
                next.getUseCount = function () {
                    return uses;
                };
                next.discard = function (count) {
                    uses += count;
                    if ((index | 0) >= 624) {
                        refreshData(data);
                        index = 0;
                    }
                    while ((count - index) > 624) {
                        count -= 624 - index;
                        refreshData(data);
                        index = 0;
                    }
                    index = (index + count) | 0;
                    return next;
                };
                next.seed = function (initial) {
                    var previous = 0;
                    data[0] = previous = initial | 0;

                    for (var i = 1; i < 624; i = (i + 1) | 0) {
                        data[i] = previous = (imul((previous ^ (previous >>> 30)), 0x6c078965) + i) | 0;
                    }
                    index = 624;
                    uses = 0;
                    return next;
                };
                next.seedWithArray = function (source) {
                    next.seed(0x012bd6aa);
                    seedWithArray(data, source);
                    return next;
                };
                next.autoSeed = function () {
                    return next.seedWithArray(Random.generateEntropyArray());
                };
                return next;
            }

            return mt19937;
        }(typeof Int32Array === "function" ? Int32Array : Array)),
        browserCrypto: (typeof crypto !== "undefined" && typeof crypto.getRandomValues === "function" && typeof Int32Array === "function") ? (function () {
            var data = null;
            var index = 128;

            return function () {
                if (index >= 128) {
                    if (data === null) {
                        data = new Int32Array(128);
                    }
                    crypto.getRandomValues(data);
                    index = 0;
                }

                return data[index++] | 0;
            };
        }()) : null
    };

    Random.generateEntropyArray = function () {
        var array = [];
        var engine = Random.engines.nativeMath;
        for (var i = 0; i < 16; ++i) {
            array[i] = engine() | 0;
        }
        array.push(new Date().getTime() | 0);
        return array;
    };

    function returnValue(value) {
        return function () {
            return value;
        };
    }

    // [-0x80000000, 0x7fffffff]
    Random.int32 = function (engine) {
        return engine() | 0;
    };
    proto.int32 = function () {
        return Random.int32(this.engine);
    };

    // [0, 0xffffffff]
    Random.uint32 = function (engine) {
        return engine() >>> 0;
    };
    proto.uint32 = function () {
        return Random.uint32(this.engine);
    };

    // [0, 0x1fffffffffffff]
    Random.uint53 = function (engine) {
        var high = engine() & 0x1fffff;
        var low = engine() >>> 0;
        return (high * 0x100000000) + low;
    };
    proto.uint53 = function () {
        return Random.uint53(this.engine);
    };

    // [0, 0x20000000000000]
    Random.uint53Full = function (engine) {
        while (true) {
            var high = engine() | 0;
            if (high & 0x200000) {
                if ((high & 0x3fffff) === 0x200000 && (engine() | 0) === 0) {
                    return 0x20000000000000;
                }
            }
            else {
                var low = engine() >>> 0;
                return ((high & 0x1fffff) * 0x100000000) + low;
            }
        }
    };
    proto.uint53Full = function () {
        return Random.uint53Full(this.engine);
    };

    // [-0x20000000000000, 0x1fffffffffffff]
    Random.int53 = function (engine) {
        var high = engine() | 0;
        var low = engine() >>> 0;
        return ((high & 0x1fffff) * 0x100000000) + low + (high & 0x200000 ? -0x20000000000000 : 0);
    };
    proto.int53 = function () {
        return Random.int53(this.engine);
    };

    // [-0x20000000000000, 0x20000000000000]
    Random.int53Full = function (engine) {
        while (true) {
            var high = engine() | 0;
            if (high & 0x400000) {
                if ((high & 0x7fffff) === 0x400000 && (engine() | 0) === 0) {
                    return 0x20000000000000;
                }
            }
            else {
                var low = engine() >>> 0;
                return ((high & 0x1fffff) * 0x100000000) + low + (high & 0x200000 ? -0x20000000000000 : 0);
            }
        }
    };
    proto.int53Full = function () {
        return Random.int53Full(this.engine);
    };

    function add(generate, addend) {
        if (addend === 0) {
            return generate;
        }
        else {
            return function (engine) {
                return generate(engine) + addend;
            };
        }
    }

    Random.integer = (function () {
        function isPowerOfTwoMinusOne(value) {
            return ((value + 1) & value) === 0;
        }

        function bitmask(masking) {
            return function (engine) {
                return engine() & masking;
            };
        }

        function downscaleToLoopCheckedRange(range) {
            var extendedRange = range + 1;
            var maximum = extendedRange * Math.floor(0x100000000 / extendedRange);
            return function (engine) {
                var value = 0;
                do {
                    value = engine() >>> 0;
                } while (value >= maximum);
                return value % extendedRange;
            };
        }

        function downscaleToRange(range) {
            if (isPowerOfTwoMinusOne(range)) {
                return bitmask(range);
            }
            else {
                return downscaleToLoopCheckedRange(range);
            }
        }

        function isEvenlyDivisibleByMaxInt32(value) {
            return (value | 0) === 0;
        }

        function upscaleWithHighMasking(masking) {
            return function (engine) {
                var high = engine() & masking;
                var low = engine() >>> 0;
                return (high * 0x100000000) + low;
            };
        }

        function upscaleToLoopCheckedRange(extendedRange) {
            var maximum = extendedRange * Math.floor(0x20000000000000 / extendedRange);
            return function (engine) {
                var ret = 0;
                do {
                    var high = engine() & 0x1fffff;
                    var low = engine() >>> 0;
                    ret = (high * 0x100000000) + low;
                } while (ret >= maximum);
                return ret % extendedRange;
            };
        }

        function upscaleWithinU53(range) {
            var extendedRange = range + 1;
            if (isEvenlyDivisibleByMaxInt32(extendedRange)) {
                var highRange = ((extendedRange / 0x100000000) | 0) - 1;
                if (isPowerOfTwoMinusOne(highRange)) {
                    return upscaleWithHighMasking(highRange);
                }
            }
            return upscaleToLoopCheckedRange(extendedRange);
        }

        function upscaleWithinI53AndLoopCheck(min, max) {
            return function (engine) {
                var ret = 0;
                do {
                    var high = engine() | 0;
                    var low = engine() >>> 0;
                    ret = ((high & 0x1fffff) * 0x100000000) + low + (high & 0x200000 ? -0x20000000000000 : 0);
                } while (ret < min || ret > max);
                return ret;
            };
        }

        return function (min, max) {
            min = Math.floor(min);
            max = Math.floor(max);
            if (min < -0x20000000000000 || !isFinite(min)) {
                throw new RangeError("Expected min to be at least " + (-0x20000000000000));
            }
            else if (max > 0x20000000000000 || !isFinite(max)) {
                throw new RangeError("Expected max to be at most " + 0x20000000000000);
            }

            var range = max - min;
            if (range <= 0 || !isFinite(range)) {
                return returnValue(min);
            }
            else if (range === 0xffffffff) {
                if (min === 0) {
                    return Random.uint32;
                }
                else {
                    return add(Random.int32, min + 0x80000000);
                }
            }
            else if (range < 0xffffffff) {
                return add(downscaleToRange(range), min);
            }
            else if (range === 0x1fffffffffffff) {
                return add(Random.uint53, min);
            }
            else if (range < 0x1fffffffffffff) {
                return add(upscaleWithinU53(range), min);
            }
            else if (max - 1 - min === 0x1fffffffffffff) {
                return add(Random.uint53Full, min);
            }
            else if (min === -0x20000000000000 && max === 0x20000000000000) {
                return Random.int53Full;
            }
            else if (min === -0x20000000000000 && max === 0x1fffffffffffff) {
                return Random.int53;
            }
            else if (min === -0x1fffffffffffff && max === 0x20000000000000) {
                return add(Random.int53, 1);
            }
            else if (max === 0x20000000000000) {
                return add(upscaleWithinI53AndLoopCheck(min - 1, max - 1), 1);
            }
            else {
                return upscaleWithinI53AndLoopCheck(min, max);
            }
        };
    }());
    proto.integer = function (min, max) {
        return Random.integer(min, max)(this.engine);
    };

    // [0, 1] (floating point)
    Random.realZeroToOneInclusive = function (engine) {
        return Random.uint53Full(engine) / 0x20000000000000;
    };
    proto.realZeroToOneInclusive = function () {
        return Random.realZeroToOneInclusive(this.engine);
    };

    // [0, 1) (floating point)
    Random.realZeroToOneExclusive = function (engine) {
        return Random.uint53(engine) / 0x20000000000000;
    };
    proto.realZeroToOneExclusive = function () {
        return Random.realZeroToOneExclusive(this.engine);
    };

    Random.real = (function () {
        function multiply(generate, multiplier) {
            if (multiplier === 1) {
                return generate;
            }
            else if (multiplier === 0) {
                return function () {
                    return 0;
                };
            }
            else {
                return function (engine) {
                    return generate(engine) * multiplier;
                };
            }
        }

        return function (left, right, inclusive) {
            if (!isFinite(left)) {
                throw new RangeError("Expected left to be a finite number");
            }
            else if (!isFinite(right)) {
                throw new RangeError("Expected right to be a finite number");
            }
            return add(
                multiply(
                    inclusive ? Random.realZeroToOneInclusive : Random.realZeroToOneExclusive,
                    right - left),
                left);
        };
    }());
    proto.real = function (min, max, inclusive) {
        return Random.real(min, max, inclusive)(this.engine);
    };

    Random.bool = (function () {
        function isLeastBitTrue(engine) {
            return (engine() & 1) === 1;
        }

        function lessThan(generate, value) {
            return function (engine) {
                return generate(engine) < value;
            };
        }

        function probability(percentage) {
            if (percentage <= 0) {
                return returnValue(false);
            }
            else if (percentage >= 1) {
                return returnValue(true);
            }
            else {
                var scaled = percentage * 0x100000000;
                if (scaled % 1 === 0) {
                    return lessThan(Random.int32, (scaled - 0x80000000) | 0);
                }
                else {
                    return lessThan(Random.uint53, Math.round(percentage * 0x20000000000000));
                }
            }
        }

        return function (numerator, denominator) {
            if (denominator == null) {
                if (numerator == null) {
                    return isLeastBitTrue;
                }
                return probability(numerator);
            }
            else {
                if (numerator <= 0) {
                    return returnValue(false);
                }
                else if (numerator >= denominator) {
                    return returnValue(true);
                }
                return lessThan(Random.integer(0, denominator - 1), numerator);
            }
        };
    }());
    proto.bool = function (numerator, denominator) {
        return Random.bool(numerator, denominator)(this.engine);
    };

    function toInteger(value) {
        var number = +value;
        if (number < 0) {
            return Math.ceil(number);
        }
        else {
            return Math.floor(number);
        }
    }

    function convertSliceArgument(value, length) {
        if (value < 0) {
            return Math.max(value + length, 0);
        }
        else {
            return Math.min(value, length);
        }
    }
    Random.pick = function (engine, array, begin, end) {
        var length = array.length;
        var start = begin == null ? 0 : convertSliceArgument(toInteger(begin), length);
        var finish = end === void 0 ? length : convertSliceArgument(toInteger(end), length);
        if (start >= finish) {
            return void 0;
        }
        var distribution = Random.integer(start, finish - 1);
        return array[distribution(engine)];
    };
    proto.pick = function (array, begin, end) {
        return Random.pick(this.engine, array, begin, end);
    };

    function returnUndefined() {
        return void 0;
    }
    var slice = Array.prototype.slice;
    Random.picker = function (array, begin, end) {
        var clone = slice.call(array, begin, end);
        if (!clone.length) {
            return returnUndefined;
        }
        var distribution = Random.integer(0, clone.length - 1);
        return function (engine) {
            return clone[distribution(engine)];
        };
    };

    Random.shuffle = function (engine, array, downTo) {
        var length = array.length;
        if (length) {
            if (downTo == null) {
                downTo = 0;
            }
            for (var i = (length - 1) >>> 0; i > downTo; --i) {
                var distribution = Random.integer(0, i);
                var j = distribution(engine);
                if (i !== j) {
                    var tmp = array[i];
                    array[i] = array[j];
                    array[j] = tmp;
                }
            }
        }
        return array;
    };
    proto.shuffle = function (array) {
        return Random.shuffle(this.engine, array);
    };

    Random.sample = function (engine, population, sampleSize) {
        if (sampleSize < 0 || sampleSize > population.length || !isFinite(sampleSize)) {
            throw new RangeError("Expected sampleSize to be within 0 and the length of the population");
        }

        if (sampleSize === 0) {
            return [];
        }

        var clone = slice.call(population);
        var length = clone.length;
        if (length === sampleSize) {
            return Random.shuffle(engine, clone, 0);
        }
        var tailLength = length - sampleSize;
        return Random.shuffle(engine, clone, tailLength - 1).slice(tailLength);
    };
    proto.sample = function (population, sampleSize) {
        return Random.sample(this.engine, population, sampleSize);
    };

    Random.die = function (sideCount) {
        return Random.integer(1, sideCount);
    };
    proto.die = function (sideCount) {
        return Random.die(sideCount)(this.engine);
    };

    Random.dice = function (sideCount, dieCount) {
        var distribution = Random.die(sideCount);
        return function (engine) {
            var result = [];
            result.length = dieCount;
            for (var i = 0; i < dieCount; ++i) {
                result[i] = distribution(engine);
            }
            return result;
        };
    };
    proto.dice = function (sideCount, dieCount) {
        return Random.dice(sideCount, dieCount)(this.engine);
    };

    // http://en.wikipedia.org/wiki/Universally_unique_identifier
    Random.uuid4 = (function () {
        function zeroPad(string, zeroCount) {
            return stringRepeat("0", zeroCount - string.length) + string;
        }

        return function (engine) {
            var a = engine() >>> 0;
            var b = engine() | 0;
            var c = engine() | 0;
            var d = engine() >>> 0;

            return (
                zeroPad(a.toString(16), 8) +
                "-" +
                zeroPad((b & 0xffff).toString(16), 4) +
                "-" +
                zeroPad((((b >> 4) & 0x0fff) | 0x4000).toString(16), 4) +
                "-" +
                zeroPad(((c & 0x3fff) | 0x8000).toString(16), 4) +
                "-" +
                zeroPad(((c >> 4) & 0xffff).toString(16), 4) +
                zeroPad(d.toString(16), 8));
        };
    }());
    proto.uuid4 = function () {
        return Random.uuid4(this.engine);
    };

    Random.string = (function () {
        // has 2**x chars, for faster uniform distribution
        var DEFAULT_STRING_POOL = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";

        return function (pool) {
            if (pool == null) {
                pool = DEFAULT_STRING_POOL;
            }

            var length = pool.length;
            if (!length) {
                throw new Error("Expected pool not to be an empty string");
            }

            var distribution = Random.integer(0, length - 1);
            return function (engine, length) {
                var result = "";
                for (var i = 0; i < length; ++i) {
                    var j = distribution(engine);
                    result += pool.charAt(j);
                }
                return result;
            };
        };
    }());
    proto.string = function (length, pool) {
        return Random.string(pool)(this.engine, length);
    };

    Random.hex = (function () {
        var LOWER_HEX_POOL = "0123456789abcdef";
        var lowerHex = Random.string(LOWER_HEX_POOL);
        var upperHex = Random.string(LOWER_HEX_POOL.toUpperCase());

        return function (upper) {
            if (upper) {
                return upperHex;
            }
            else {
                return lowerHex;
            }
        };
    }());
    proto.hex = function (length, upper) {
        return Random.hex(upper)(this.engine, length);
    };

    Random.date = function (start, end) {
        if (!(start instanceof Date)) {
            throw new TypeError("Expected start to be a Date, got " + typeof start);
        }
        else if (!(end instanceof Date)) {
            throw new TypeError("Expected end to be a Date, got " + typeof end);
        }
        var distribution = Random.integer(start.getTime(), end.getTime());
        return function (engine) {
            return new Date(distribution(engine));
        };
    };
    proto.date = function (start, end) {
        return Random.date(start, end)(this.engine);
    };

    if (typeof define === "function" && define.amd) {
        define(function () {
            return Random;
        });
    }
    else if (typeof module !== "undefined" && typeof require === "function") {
        module.exports = Random;
    }
    else {
        (function () {
            var oldGlobal = root[GLOBAL_KEY];
            Random.noConflict = function () {
                root[GLOBAL_KEY] = oldGlobal;
                return this;
            };
        }());
        root[GLOBAL_KEY] = Random;
    }
}(this));

// create a Mersenne Twister-19937 that is auto-seeded based on time and other random values
var engine = Random.engines.mt19937().autoSeed();
// create a distribution that will consistently produce integers within inclusive range [0, 99].
var distribution = Random.integer(0, 9);
// generate a number that is guaranteed to be within [0, 99] without any particular bias.
// alert(distribution(engine))