Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么这个随机值的分布是25/75而不是50/50?_Java_Random_Double_Bit Manipulation_Probability - Fatal编程技术网

Java 为什么这个随机值的分布是25/75而不是50/50?

Java 为什么这个随机值的分布是25/75而不是50/50?,java,random,double,bit-manipulation,probability,Java,Random,Double,Bit Manipulation,Probability,编辑:所以基本上我要写的是一个1位的哈希值,用于双精度 我想以50/50的几率将double映射到true或false。为此,我编写了一段代码,其中选取了一些随机数(作为一个例子,我想对具有正则性的数据使用它,但仍然得到50/50的结果),检查它们的最后一位,如果它是1,则递增y,如果它是0,则递增n 但是,此代码持续导致25%的y和75%的n。为什么不是50/50?为什么会有如此奇怪但直接的(1/3)分布 public class DoubleToBoolean { @Test

编辑:所以基本上我要写的是一个1位的哈希值,用于
双精度

我想以50/50的几率将
double
映射到
true
false
。为此,我编写了一段代码,其中选取了一些随机数(作为一个例子,我想对具有正则性的数据使用它,但仍然得到50/50的结果),检查它们的最后一位,如果它是1,则递增
y
,如果它是0,则递增
n

但是,此代码持续导致25%的
y
和75%的
n
。为什么不是50/50?为什么会有如此奇怪但直接的(1/3)分布

public class DoubleToBoolean {
    @Test
    public void test() {

        int y = 0;
        int n = 0;
        Random r = new Random();
        for (int i = 0; i < 1000000; i++) {
            double randomValue = r.nextDouble();
            long lastBit = Double.doubleToLongBits(randomValue) & 1;
            if (lastBit == 1) {
                y++;
            } else {
                n++;
            }
        }
        System.out.println(y + " " + n);
    }
}

因为nextDouble是这样工作的:()

public double nextDouble()
{
返回(((长)下一个(26):

方法nextDouble由Random类实现,就像通过以下方式实现一样:

public double nextDouble() {
  return (((long)next(26) << 27) + next(27))
      / (double)(1L << 53);
}
public double nextDouble(){

return((long)next(26)考虑到浮点数是如何表示的,这个结果并不让我感到惊讶。假设我们有一个非常短的浮点类型,只有4位精度。如果我们要生成一个0到1之间的随机数,均匀分布,则可能有16个值:

0.0000
0.0001
0.0010
0.0011
0.0100
...
0.1110
0.1111
如果这是机器中的情况,您可以测试低阶位以获得50/50分布。但是,IEEE浮点表示为尾数的2倍幂;浮点中的一个字段是2的幂(加上固定偏移量)。选择2的幂,以便“尾数”为零件始终是一个大于等于1.0且小于2.0的数字。这意味着,实际上,除
0.0000
之外的数字将如下所示:

0.0001 = 2^(-4) x 1.000
0.0010 = 2^(-3) x 1.000
0.0011 = 2^(-3) x 1.100
0.0100 = 2^(-2) x 1.000
... 
0.0111 = 2^(-2) x 1.110
0.1000 = 2^(-1) x 1.000
0.1001 = 2^(-1) x 1.001
...
0.1110 = 2^(-1) x 1.110
0.1111 = 2^(-1) x 1.111
(二进制点之前的
1
是一个隐含值;对于32位和64位浮点,实际上没有分配任何位来保存该
1

但是看看上面应该说明为什么,如果将表示转换为位并查看低位,75%的时间将为零。这是因为所有值都小于0.5(二进制
0.1000
),是可能值的一半,尾数移位,导致0出现在低位。尾数有52位(不包括隐含的1)时,情况基本上与双精度
相同

(事实上,正如@sneftel在一篇评论中所建议的,我们可以在分布中包含16个以上的可能值,方法是生成:

0.0001000 with probability 1/128
0.0001001 with probability 1/128
...
0.0001111 with probability 1/128
0.001000  with probability 1/64
0.001001  with probability 1/64
...
0.01111   with probability 1/32 
0.1000    with probability 1/16
0.1001    with probability 1/16
...
0.1110    with probability 1/16
0.1111    with probability 1/16

但我不确定这是否是大多数程序员所期望的分布,因此它可能不值得。此外,当使用这些值生成整数时,它不会给您带来太多好处,因为随机浮点值通常都是。)

我真的希望答案是关于随机生成浮点变量的一些有趣的东西,而不是“LCG在低位具有低熵”。我很好奇,“双精度1位哈希”的目的是什么?我真的想不出这样一个要求的任何合法应用。@corsiKa在几何计算中,我们通常需要从两种可能的答案中选择两种情况(例如,点在直线的左边还是右边?),有时它会引入第三种退化情况(点在直线的右边),但您只有两个可用答案,因此在这种情况下,您必须伪随机选择一个可用答案。我能想到的最好方法是对给定的双精度值之一进行1位哈希运算(请记住,这些是几何计算,因此到处都有双精度)。@corsiKa(注释分为两部分,因为它太长)我们可以从一些更简单的内容开始,比如
doubleValue%1>0.5
,但这太粗糙了,因为它在某些情况下会引入可见的规则性(所有值都在长度1的范围内)。如果这太粗了,那么我们应该尝试更小的范围,比如
doubleValue%1e-10>0.5e-10
?好的,是的。如果你一直使用这种方法,直到最后都会使用最小可能的模,只取最后一位作为
double
的散列值。@kmote那么你仍然会有严重偏差的最小符号一个重要的位,而另一个位不补偿它-事实上,它也偏向于零(但不太偏向零),原因完全相同。因此分布大约为50,12.5,25,12.5。
(lastbit&3)==0
虽然很奇怪,但仍然有效。万岁!这正是我所希望的。@马特推测这是一个速度优化。另一种方法是生成具有几何分布的指数,然后分别生成尾数。@马特:定义“最佳”。
random.nextDouble()
通常是“最佳”这就是它的目的,但大多数人并不是试图从他们的随机双精度生成1位散列。你是在寻找均匀分布、对密码分析的抵制,还是什么?这个答案表明,如果OP将随机数乘以2^53,并检查得到的整数是否为奇数,那么就会有一个50/50的distribution@1111它说
next
必须返回一个
int
,所以它最多只能有32位。奇怪。我刚刚在Java 8上复制了这个。这很有趣,因为我刚才认为这种偏见仍然适用于新方法。我错了吗?@harold:不,我认为你是对的,任何试图纠正这种偏见的人可能都错了犯了一个错误。“哈罗德时间给一个java人发电子邮件。”也许固定版本从来没有测试过?“实际上,在重读这个过程时,我认为DOC是一个不同的问题。注意它提到舍入,这表明他们没有考虑到“三倍的可能性”。这是一个直接的问题,但当值被舍入时,这会导致非均匀分布。请注意,在我的回答中,我列出的值是均匀分布的,但IEEE格式中表示的低阶位是不均匀的。我认为他们解决的问题与t有关
0.0000
0.0001
0.0010
0.0011
0.0100
...
0.1110
0.1111
0.0001 = 2^(-4) x 1.000
0.0010 = 2^(-3) x 1.000
0.0011 = 2^(-3) x 1.100
0.0100 = 2^(-2) x 1.000
... 
0.0111 = 2^(-2) x 1.110
0.1000 = 2^(-1) x 1.000
0.1001 = 2^(-1) x 1.001
...
0.1110 = 2^(-1) x 1.110
0.1111 = 2^(-1) x 1.111
0.0001000 with probability 1/128
0.0001001 with probability 1/128
...
0.0001111 with probability 1/128
0.001000  with probability 1/64
0.001001  with probability 1/64
...
0.01111   with probability 1/32 
0.1000    with probability 1/16
0.1001    with probability 1/16
...
0.1110    with probability 1/16
0.1111    with probability 1/16