下面的打印语句将打印“hello world”。有人能解释一下吗?

System.out.println(randomString(-229985452) + " " + randomString(-147909649));

randomString()如下所示:

public static String randomString(int i)
{
    Random ran = new Random(i);
    StringBuilder sb = new StringBuilder();
    while (true)
    {
        int k = ran.nextInt(27);
        if (k == 0)
            break;

        sb.append((char)('`' + k));
    }

    return sb.toString();
}

当前回答

这是丹尼斯·图尔斯基回答的一个小改进。它把时间缩短了一半

public static long[] generateSeed(String goal, long start, long finish) {
    char[] input = goal.toCharArray();

    int[] dif = new int[input.length - 1];
    for (int i = 1; i < input.length; i++) {
        dif[i - 1] = input[i] - input[i - 1];
    }

    mainLoop:
    for (long seed = start; seed < finish; seed++) {
        Random random = new Random(seed);
        int lastChar = random.nextInt(27);
        int base = input[0] - lastChar;
        for (int d : dif) {
            int nextChar = random.nextInt(27);
            if (nextChar - lastChar != d) {
                continue mainLoop;
            }
            lastChar = nextChar;
        }
        if(random.nextInt(27) == 0){
            return new long[]{seed, base};
        }
    }

    throw new NoSuchElementException("Sorry :/");
}

其他回答

我对此很感兴趣,我在字典单词列表上运行了这个随机单词生成器。范围:整数.MIN_VALUE到整数.MAX_VALUE

我得到了15131次点击。

int[] arrInt = {-2146926310, -1885533740, -274140519, 
                -2145247212, -1845077092, -2143584283,
                -2147483454, -2138225126, -2147375969};

for(int seed : arrInt){
    System.out.print(randomString(seed) + " ");
}

打印

the quick browny fox jumps over a lazy dog 

原理是用相同的种子构建的随机类每次都会生成相同的数字模式。

在Java文档中,当为Random类指定种子值时,这是一个有意的特性。

如果使用同一种子创建了两个“随机”实例对每个方法调用相同的序列,它们将生成和返回相同的数字序列。为了保证这一点属性,为类Random指定特定算法。Java实现必须使用此处显示的所有算法类Random,为了Java代码的绝对可移植性。

http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Random.html

奇怪的是,你会认为拥有可预测的“随机”数字存在隐性安全问题。

事实上,大多数随机数生成器都是“伪随机”的。它们是线性同余生成器,或LCG(http://en.wikipedia.org/wiki/Linear_congruential_generator)

给定固定的种子,LCG是非常可预测的。基本上,使用给你第一个字母的种子,然后编写一个应用程序,继续生成下一个int(char),直到你命中目标字符串中的下一个字母,并记下你需要调用LCG的次数。继续,直到生成每个字母。

这是关于“种子”的。相同的种子产生相同的结果。