Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.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
Php 如何实现随机浮点函数,使其不丢失熵?(菲律宾)_Php_Math_Random - Fatal编程技术网

Php 如何实现随机浮点函数,使其不丢失熵?(菲律宾)

Php 如何实现随机浮点函数,使其不丢失熵?(菲律宾),php,math,random,Php,Math,Random,我试图使用从/dev/uradom获得的字节生成随机浮点。目前,我的最佳想法是通过以下方式获得平台精度: $maximumPrecision = strlen('' . 1/3) - 2; 然后按照$maximumPrecision告诉我们的次数,在循环中构造一个0-9的字符串。例如,如果精度是12,我将生成12个随机数并将它们连接起来。我认为这是一个丑陋的想法 更新:这有意义吗 $bytes =getRandomBytes(7); // Just a function that return

我试图使用从/dev/uradom获得的字节生成随机浮点。目前,我的最佳想法是通过以下方式获得平台精度:

$maximumPrecision = strlen('' . 1/3) - 2;
然后按照$maximumPrecision告诉我们的次数,在循环中构造一个0-9的字符串。例如,如果精度是12,我将生成12个随机数并将它们连接起来。我认为这是一个丑陋的想法

更新:这有意义吗

$bytes =getRandomBytes(7); // Just a function that returns random bytes.
$bytes[6] = $bytes[6] & chr(15); // Get rid off the other half
$bytes .= chr(0); // Add a null byte

$parts = unpack('V2', $bytes);

$number = $parts[1] + pow(2.0, 32) * $parts[2];
$number /= pow(2.0, 52);

PHP的浮点类型通常实现为。这种格式的尾数精度为52位,因此原则上它应该能够在[0,1]中生成252个不同的统一的数字

因此,您可以从/dev/uradom中提取52位,解释为整数,然后除以252:

//假设我们有52位数据,小尾端。
$bytes=“\x12\x34\x56\x78\x9a\xbc\x0d\x00”;
//^^^^ 12位填充。
$parts=解包($V2',$bytes);

$theNumber=$parts[1]+pow(2.0,32)*$parts[2];//这里的问题是根据基数2的指数定义的:

n = 2^exponent * 1.mantissa
因为你想要一个指数-1,并且没有整数
n
,所以
2^n=0.1
,这就变得复杂了

这将生成一个介于1和2之间的数字。您可以减去
1
,但如果这样做,您将损失少量的熵(不过,KennyTM的答案会产生一个在该范围内的数字,并使用所有熵——此答案试图直接创建表示):

$source=fopen(“/dev/uradom”、“rb”);
//建立大端双端
//由于采用32位平台,因此仅采用32位
$byte_batch_1=fread($source,4);//32位
$byte_batch_2=fread($source,4);//32位,我们只需要20位

$offset=(1该数字必须介于0和1之间?是的,浮点数必须介于0和1之间,且具有平台的精度。@R因素:您想要什么样的随机数分布?均匀?(因为浮点数不是均匀分布在间隔中。)@halfdan:使用lcg_值(),我正在读取返回字节的/dev/uradom。@KennyTM:是的,我想要一个均匀分布的float.Yep。虽然PHP遵循C89,它不需要IEEE double来表示
double
类型,但很难找到一个不支持这种标准的平台(尽管它们可能不完全支持该标准)。有趣的是,
在本例中解释为整数实际上意味着什么?我使用7个字节(56位)和…@rFactor:请参阅更新。您也可以使用“位移位”要构造原始的双精度表示和
解包
,但这在PHP中相当混乱。当我读取/dev/uradom时,我读取的是字节,而不是位。因此,我可以读取的最接近的字节数是7=56位。我如何截断并除去这些额外的位?@rFactor:(a)这是小尾数。所以我们在最高有效位的末尾加上12'0。(B)
parts[1]
是较低的32位,
parts[2]
是较高的20位。
n = 2^exponent * 1.mantissa
$source = fopen("/dev/urandom", "rb");

//build big-endian double
//take only 32 bits because of 32-bit platforms
$byte_batch_1 = fread($source, 4); //32-bit
$byte_batch_2 = fread($source, 4); //32-bit, we only need 20

$offset = (1 << 10) -1;

$first_word = unpack("N", $byte_batch_2);
$first_word = reset($first_word);
$first_word &= 0xFFFFF; //leave only 20 lower bits
$first_word |= $offset << 20;

$str = pack("N", $first_word) . $byte_batch_1;

//convert to little endian if necessary
if (pack('s', 1) == "\x01\x00") { //little-endian
    $str = strrev($str);
}

$float = unpack("d", $str);
$float = reset($float);