在Java中生成8字节的数字

在Java中生成8字节的数字,java,Java,我有点困惑,怎么做。我知道我可以使用Random类生成随机数,但我不知道如何指定和生成8字节数 谢谢, Vuk可以使用长度为8的字节数组: byte[] byteArray = new byte[8]; random.nextBytes(byteArray); 或者使用类型为long(表示8字节数字)的变量: 从代码中稍作调整: import java.util.Random; /**生成范围为0..99的10个随机整数*/ 公共最终类随机字节{ 公共静态最终空干管(串…aArgs){

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

谢谢,
Vuk

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

byte[] byteArray = new byte[8];    
random.nextBytes(byteArray);
或者使用类型为
long
(表示8字节数字)的变量:


从代码中稍作调整:

import java.util.Random;
/**生成范围为0..99的10个随机整数*/
公共最终类随机字节{
公共静态最终空干管(串…aArgs){
log(“生成0..255范围内的10个随机整数”);
//注意,此处重用单个随机对象
Random randomGenerator=新的Random();

对于(int idx=1;idx而言,
long
类型是一个8字节有符号整数,因此似乎可以执行您想要的操作。或者,如果您需要一个字节数组作为结果:

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

您应该注意,
java.util.Random
类使用48位种子,因此不能使用该类生成所有8字节值(64位序列)。由于此限制,我建议您在这种情况下使用和

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

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

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

  • Random
    类实现了一个伪随机生成器,这意味着它是确定性的
  • 随机
    的当前“状态”决定了未来的位序列
  • 因为它有248个状态,所以未来可能的序列不能超过248个
  • 由于8字节的值有264种不同的可能性,其中一些可能性永远不会从
    随机对象中读取

基于(它值得更多的投票!):下面是一个使用2×48位种子创建
java.util.Random
的解决方案。也就是说,一个
java.util.Random
实例能够生成所有可能的
s

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;
    }
}
classrandom96扩展了Random{
整数计数=0;
ExposedRandom额外48位;
类ExposedRandom扩展了Random{
公共int-next(int位){//公开下一个方法。
返回super.next(位);
}
}
@凌驾
受保护的整数下一个(整数位){
如果(计数+==0)
extra48bits=新的ExposedRandom();

return super.next(bits)^extra48bits.next(bits)我同意@aioobe关于使用48位种子随机的观点。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;
int计数器=0;
Random rand=新的Random();
Random rand2=新的Random();
如果(++计数器==0)rand=new Random();//每40亿个值重置一次。

long randomLong=rand.nextLong()^rand2.nextLong()请注意,这两个选项都不能生成所有可能的8字节值。请参见我的答案。@aioobe:您能解释一下原因吗?我已经阅读了文档,阅读了实现,但我仍然没有清楚的理解。这相当复杂(基于数学)算法,据我所知,它会生成相关值。如果它是真的,那么一个随机实例并不会真正生成所有可能的long值。但是不同的
random
s(具有不同的“起点”)是吗?我说得对吗?48位种子只有2^48个可能的值,最多只能在2^48个值之后重复。基础函数生成32位int,因此您需要其中两个,这样您就可以得到一个在2^47个长值之后重复的序列。如果您定期重置随机种子,则只需检查序列中的点,但不是可能的值。@Peter Lawrey,aioobe:谢谢,现在已经很清楚了。但是,我还是会使用通常的
Random
class(或者使用两个随机实例,尽管分布不太均匀)直到真正有必要从2^64范围生成公平值为止。这只是因为它是众所周知且经常使用的类。我同意。在没有充分理由的情况下,不要涉及太多包是有意义的。创建一个带有96位种子的
java.util.Random
实例(基于Peter Lawrey的回答)请注意,
Random
类无法生成所有可能的8字节值。请注意,
Random
类无法生成所有可能的长度。在每个答案下都留下相同的注释并不酷。为什么不呢?我想没关系。它适用于我评论的每个答案。我直观的解决方案是b即使生成两个4字节的值。如果我理解正确,这也不起作用,因为当使用同一个生成器两次时,两个值将被排除(或至少不可能)不相等。例如,FF FF的可能性不如FF AA?我不知道PRG是如何实现的,所以这让我感到惊讶,因为我预计每个数字都是相同的(伪-)独立于前面的数字。不,
FF FF
FF AA
一样可能。它应该是独立的,但由于它是伪随机的,所以它不是完全独立的。也就是说,给定序列中过去的7个字节,第8个字节不能接受所有可能的值。下一个字节可能独立于它的前一个字节,但不独立于前一个字节它过去的7个字节。唯一的问题是SecureRandom需要任意长的时间来生成下一个随机数(这取决于操作系统上可用的熵的大小),因此,当您只想在整个long+1范围内生成一个数字时,这可能不是最好的选择。回答很好。有关重置和左移的有趣说明!如果您将随机实例封装在一个annonymous的Random子类中,我更希望得到答案。这两个随机对象创建的不是完全相同的吗在旧版本的Java上,两个随机数都有相同的种子?(即,在一个快速的计算机系统上。currentTimeMillis()对两个都是相同的?)这是正确的
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;
    }
}
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;