根据哈希创建一个统一的随机数 [英] Create a uniform random number based on a hash

查看:117
本文介绍了根据哈希创建一个统一的随机数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个基于由字符串和长整数组成的密钥的良好伪随机数。当我使用相同的密钥查询时,我应该得到相同的随机数,而且,如果我使用略微不同的密钥进行查询,我应该得到一个非常不同的数字,即使说密钥中的长度是1,我试过这个代码并且随机数是唯一的,但对于相似的数字,它们似乎是相关的。

I need a good pseudo random number based on a key consisting of a string and a long. I should get the same random number when I query using the same key and also, I should get a very different number if I query using a slightly different key, even when say the long in the key is off by 1. I tried this code and the random numbers are unique but for similar numbers they seem correlated.

import java.util.Date;
import java.util.Random;
import org.apache.commons.lang3.builder.HashCodeBuilder;

public class HashKeyTest {
    long time;
    String str;
    public HashKeyTest(String str, long time) {
        this.time = time;
        this.str = str;
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(time).append(str).toHashCode();
    }

    public static void main(String[] args) throws Exception {
        for(int i=0; i<10; i++){
            long time = new Date().getTime();
            HashKeyTest hk = new HashKeyTest("SPY", time);
            long hashCode = (long)hk.hashCode();
            Random rGen = new Random(hashCode);
            System.out.format("%d:%d:%10.12f\n", time, hashCode, rGen.nextDouble());
            Thread.sleep(1);
        }
    }
}

解决方案我拼凑在一起。这很好用,但我想知道它是否需要这个冗长。

Solution I pieced together. This works pretty well, but I wonder if it needs to be this verbose.

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

public class HashKeyTest implements Serializable{

    long time;
    String str;

    public HashKeyTest(String str, long time) {
        this.time = time;
        this.str = str;
    }

    public double random() throws IOException, NoSuchAlgorithmException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        out.writeObject(this);
        byte[] bytes = bos.toByteArray();
        MessageDigest md5Digest = MessageDigest.getInstance("MD5");
        byte[] hash = md5Digest.digest(bytes);
        ByteBuffer bb = ByteBuffer.wrap(hash);
        long seed = bb.getLong();

        return new Random(seed).nextDouble();
    }

    public static void main(String[] args) throws Exception {
        long time = 0;
        for (int i = 0; i < 10; i++) {
            time += 250L;
            HashKeyTest hk = new HashKeyTest("SPY", time);
            System.out.format("%d:%10.12f\n", time, hk.random());
            Thread.sleep(1);
        }
    }
}


推荐答案

你说当我使用相同的密钥查询时,我应该得到相同的随机数,而且,如果我使用稍微不同的密钥查询,我应该得到一个非常不同的数字。如果我正确理解你的问题,你不需要一个随机数,而是一个类似加密哈希码的东西。

You said "I should get the same random number when I query using the same key and also, I should get a very different number if I query using a slightly different key". If I understand your question correctly, you do not want a random number, but rather something like a cryptographic hash code.

你应该看一下你通过的任何数据传递哈希函数,如SHA或MD5。这将给你一些看似随机的输入,但在相同的输入下总是相同的,即使你的输入变化非常小,也会有很大差异。

You should look at passing whatever data you have through a hash function like SHA or MD5. This will give you something that is seemingly random with respect to the input, but will always be the same given the same input, and will vary wildly even if your input vary only very little.

编辑:
要始终获得双倍值,请尝试类似这样的事情(伪代码):

To consistently obtain double values try something like this (pseudo-code):

SHAHashValue v = ComputeSHA( yourObject);
Random r = new Random(v);
the_random_value = r.getNext();

这里的想法是使用SHA哈希值作为种子来初始化随机生成器。这几乎就是你所拥有的,但我不知道你的HashBuilder在不同的值方面产生了什么。因此,使用SHA哈希可能会改善这种情况。

The idea here is to use the SHA hash value as the seed to initialize your random generator. This is pretty much what you have, but I don't know what your HashBuilder produces in terms of different values. So using SHA hashes instead might improve the situation.

您还应该考虑0到1之间的双倍非常不同的值可能不会立即显现。

You should also consider that "very different" values for doubles between 0 and 1 might not be immediately apparent.

这篇关于根据哈希创建一个统一的随机数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆