在 Java 中生成 8 字节数字

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4531799/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 06:47:25  来源:igfitidea点击:

Generate 8-byte number in Java

java

提问by Vuk

I'm a little bit confused, how to do this. I know I can use Random class to generate random numbers, but I don't know how to specify and generate 8-byte number?

我有点困惑,如何做到这一点。我知道我可以使用 Random 类来生成随机数,但我不知道如何指定和生成 8 字节数?

Thanks, Vuk

谢谢,武克

采纳答案by aioobe

You should note that the java.util.Randomclass uses a 48-bit seed, so not all 8-byte values (sequences of 64 bits) can be generated using this class. Due to this restriction I suggest you use SecureRandomand the nextBytesmethodin this situation.

您应该注意java.util.Random该类使用 48 位种子,因此并非所有 8 字节值(64 位序列)都可以使用此类生成。由于这个限制,我建议你在这种情况下使用SecureRandomnextBytes方法

The usage is quite similar to the java.util.Randomsolution.

用法与java.util.Random解决方案非常相似。

SecureRandom sr = new SecureRandom();
byte[] rndBytes = new byte[8];
sr.nextBytes(rndBytes);


Here is the reason why a 48-bit seed is not enough:

以下是 48 位种子不够用的原因:

  • The Randomclass implements a pseudo random generator which means that it is deterministic.
  • The current "state" of the Randomdetermines the future sequence of bits.
  • Since it has 248states, it can't have more than 248possible future sequences.
  • Since an 8-byte value has 264different possibilities, some of these possibilities will never be read from the Randomobject.
  • 所述Random类实现一个伪随机数发生器,这意味着它是确定的。
  • 的当前“状态”Random决定了未来的位序列。
  • 因为它有 2 48个状态,所以它不能有超过 2 48 个可能的未来序列。
  • 由于一个 8 字节的值有 2 64种不同的可能性,因此这些可能性中的一些永远不会从Random对象中读取。


Based on @Peter Lawreys excellent answer(it deserves more upvotes!): Here is a solution for creating a java.util.Randomwith 2×48-bit seed. That is, a java.util.Randominstance capable of generating all possible longs.

基于@Peter Lawreys 的出色回答值得更多赞!):这是创建java.util.Random2×48 位种子的解决方案。也就是说,一个java.util.Random实例能够生成所有可能的longs。

class Random96 extends Random {
    int count = 0;
    ExposedRandom extra48bits;

    class ExposedRandom extends Random {
        public int next(int bits) {    // Expose the next-method.
            return super.next(bits);
        }
    }

    @Override
    protected int next(int bits) {
        if (count++ == 0)
            extra48bits = new ExposedRandom();
        return super.next(bits) ^ extra48bits.next(bits) << 1;
    }
}

回答by Peter Lawrey

I agree with @aioobe' point about Random using a 48-bit seed. SecureRandom is a better solution. However to answer the OP's questions of how to use the Random class and still allow for all possible 8-byte values is to reset the seed periodically.

我同意@aioobe 关于使用 48 位种子的 Random 的观点。SecureRandom 是一个更好的解决方案。但是,要回答 OP 关于如何使用 Random 类并仍然允许所有可能的 8 字节值的问题,需要定期重置种子。

int counter = 0;
Random rand = new Random();
Random rand2 = new Random();

if (++counter == 0) rand = new Random(); // reset every 4 billion values.

long randomLong = rand.nextLong() ^ rand2.nextLong() << 1;

Random only allows a sequence of 2^47 long values. By using two Random generators, one which keeps jumping around in the sequence, you get two 2^47 * 2^47 possible values. The use of << 1 is to avoid the impact of having both randoms having the same seed (in which case ^ would produce 0 for 4 billion values in a row)

Random 只允许 2^47 个长值的序列。通过使用两个随机生成器,一个在序列中不断跳跃,你会得到两个 2^47 * 2^47 的可能值。<< 1 的使用是为了避免具有相同种子的两个随机数的影响(在这种情况下, ^ 将连续 40 亿个值产生 0)

回答by Roman

It can be done either with byte array of length 8:

可以使用长度为 8 的字节数组来完成:

byte[] byteArray = new byte[8];    
random.nextBytes(byteArray);

or with a variable of type long(which represents 8-byte numbers):

或使用类型变量long(代表 8 字节数字):

long randomLong = random.nextLong();

回答by Michael Borgwardt

The longtype is an 8 byte signed integer, so Random.nextLong()seems to do what you want. Or if you need a byte array as result:

long类型是一个 8 字节有符号整数,所以Random.nextLong()似乎可以做你想做的。或者,如果您需要一个字节数组作为结果:

byte[] result = new byte[8];
Random.nextBytes(result);

回答by Mateen Ulhaq

A little adjusting from the code here:

这里的代码稍微调整一下

import java.util.Random;

/** Generate 10 random integers in the range 0..99. */
public final class RandomByte {

  public static final void main(String... aArgs){
    log("Generating 10 random integers in range 0..255.");

    //note a single Random object is reused here
    Random randomGenerator = new Random();
    for (int idx = 1; idx <= 10; ++idx){
      int randomInt = randomGenerator.nextInt(256);
      // int randomInt = randomGenerator.nextBytes(256);
      log("Generated : " + randomInt);
    }

    log("Done.");
  }

  private static void log(String aMessage){
    System.out.println(aMessage);
  }
}

Some further reading: Math.random() versus Random.nextInt(int)

进一步阅读:Math.random() 与 Random.nextInt(int)