我正在寻找一种算法来生成一系列比特,使得系列开始时的密度非常低(即大多数为0s),并且在系列结束时非常高(即大多数) 1秒)。我通过改变随机数落在一个范围内的概率来实现这一点,但我想找到一种更结构化的[读取:确定性]算法,就像某种稳定增长的方法一样密度为1s。
有谁知道类似的东西?或者也许有些关于这些主题的阅读?它被证明是非常有趣的,但也很有挑战性(除非我错过了一些简单的东西)!
答案 0 :(得分:2)
确定性地(无随机数)执行此操作的一般方法是使用sigma-delta调制器。
选择一个平滑增加的函数,从0开始到1结束。然后使用调制器算法逼近0和1&#39。
注意:Sigma-delta调制器非常常用于电子设备中,用于将模拟信号(声音,视频等)转换为1/0比特流。
为了说明,我将在100周期内从0到1采用斜坡并使用一阶转换器。但你可以选择你喜欢的任何曲线。例如,水平缩放hyperbolic tangent会产生较小的起点和终点坡度,中间会有更快速的变化。二阶转换器可能提供更好的"图案。他们往往不那么规律。
这是一个非常简单的算法。在C:
#include <stdio.h>
int main(void) {
int x_max = 99;
double vn = 0;
for (int x = 0; x <= x_max; ++x) {
double xn = (double) x / x_max; // linear ramp from 0 to 1.
int yn = vn > 0.5;
printf("%d", yn);
vn += xn - yn;
}
printf("\n");
return 0;
}
正如您所看到的,它是确定性的。它也非常简单快速:没有触发功能,指数等等。这就是为什么它对硬件实现有益。
输出分为2行以便于查看:
00000000000100000010000100010001001001001010100101
01010110101011011011011101110111101111110111111111
Here是一篇关于sigma-delta转换的开创性论文。上面程序中的变量与图8相匹配。图13显示了一个二阶图,如果你想尝试它。
为了好玩,这里的间隔为1000:
00000000000000000000000000000000010000000000000000
00000010000000000000001000000000000100000000001000
00000010000000010000000100000001000000010000001000
00010000010000010000010000010000010000100001000010
00010000100001000010001000010001000100001000100010
00100010001000100100010001001000100100010010001001
00010010010010010001001001001001001001001001001001
00101001001001001010010010100100101001010010010100
10100101010010100101001010100101010010101010010101
01001010101010100101010101010101010010101010101010
10101010101010101101010101010101010110101010101011
01010101101010101101010110101011010110101101010110
10110101101101011010110110101101101011011011011010
11011011011011011011011011011011011101101101101101
11011011101101110110111011011101110110111011101110
11101110111011110111011101111011101111011110111101
11101111011110111101111101111101111101111101111101
11111011111101111111011111110111111101111111101111
11111011111111110111111111111011111111111111101111
11111111111111111101111111111111111111111111111111
答案 1 :(得分:1)
一种非常灵活的方法是使用logistic function来生成1对0的概率。这假设你知道序列的长度先验,但是给你很多增加率的灵活性,以及获得1的最小和最大概率。
由于你没有指定语言,我在Ruby中对其进行了原型设计:
# Creates an array of desired length whose values are symmetric
# about the mid-point of the array, are bounded below and above
# by min & max, and have a ramp up rate determined by steepness.
def logistic_function(length, min, max, steepness)
mid = 0.5 * (length - 1)
range = max - min
# create, initialize elements via logistic fn, and return resulting array
Array.new(length) { |x| min + range / (1 + Math.exp(-steepness * (x - mid))) }
end
length = 80
# 80 probabilities will vary from 0.1 to 0.9, with a relatively slow ramp-up
probability = logistic_function(length, 0.1, 0.9, 0.1)
# Create an array of bits where each entry's probability of being 1
# is determined by the logistic function we generated
bits = Array.new(length) { |i| rand <= probability[i] ? 1 : 0 }
puts bits.join
运行两次的示例输出:
00000000011000001000001100001101001010000011001011001111000111011111101011111011
10100000000000000000010000010111000000110110111011111000111011111111111110111111
结果是随机的,但您可以(随机)通过min
,max
和steepness
来控制1的密度和转换率。
注意,通过逻辑函数的对称性,1位的总比例具有期望值(min + max) / 2
。使用我在我的例子中使用的参数化,即0.5。为了说明这一点,我计算了一组80位的1的数量,并重复生成/计数10,000次试验。由于预期比例为0.5,每次试验的预期数量为1,这是实验结果:
答案 2 :(得分:0)
有几种可能性,它取决于您想要的分布。这是一个非常简单的例子,我认为应该适用于您的目的:
for (i=0; i<end; i++)
value = rand(0,1) * (2*i/end) * (2*(end-i)/end);
if(i>end/2)
value = 1 - value;
rand(0,1)生成介于0和1之间的值。最后,您必须对结果进行舍入。
答案 3 :(得分:0)
如果完美地设置了0和1,那么你可以将结果分成中间,而左半部分应该有1/3的1与前半部分相比(换句话说:左半部分是1/4)那些和右半部分有3/4个)。所以我们可以用这个想法生成位。
000000100000001000100010001011100010001000111111111111111111111
0000000100000001000100010001011100010001010111111111111111111111
00000001000000010001000100010111000100010001111111111111111111111
63,64和65位的输出:
var li
答案 4 :(得分:0)