随机数生成方法细节 * rand () / (RAND_MAX + 1.0f)

在生成点云数据仿真过程中,遇到点云坐标生成的问题。原本期望通过512作为比例系数,使点云范围在512米内,但实际上生成的点云始终在-1到1之间。这是因为rand()函数返回的是0到RAND_MAX的整数,与512相乘可能超出范围导致负值,再除以范围得到(-1,1)的值。正确的做法是先将rand()结果除以范围,再乘以所需比例。文章通过代码示例解释了这个问题并提出解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

生成点云数据做仿真的时候遇到了这样一个问题,点云的坐标用随机数生成,语句如下:

	cloud.points[i].x = 512 * rand () / (RAND_MAX + 1.0f);

开始没有仔细想,以为512就是个比例系数,生成的点云范围在512m内,但实测后发现,不管如何更改这个比例,实际生成的点云都在-1~1之间。研究一下随机数生成的函数,发现了奥秘。rand()函数的解释如下

int rand()
Return a random integer between 0 and RAND_MAX inclusive.返回0-RAND_MAX的任意值

我的初始理解是rand () / (RAND_MAX + 1.0f)取一个[0,1)的值,然后乘上比例系数,这当然不对,因为运算顺序显然是从左向右的。也就是说,rand()的结果返回的整数要先和系数512相乘,再与范围作比。由于是512默认是int整型,rand()返回的值也是整形,而且RAND_MAX和INT_MAX一般相同,都是2147483647,所以这里先乘就极有可能越界,超出范围的数会被计算机理解为负值,再除以范围,得到的就是(-1,1)之间的值,这和上面的表现是一致的。

查资料的时候网上有很多类似转换的例子,写一段比较的方法如下:

for(int i = 0; i < 10 ; ++i)
    {
    	//固定一个随机数
        int r = rand(); 
        //打印固定的随机数
        std::cout << "rand = " << r << std::endl; 
        //不加系数的结果
        std::cout << "rand/max = " << r/(RAND_MAX+1.0f) << std::endl; 
        //乘上一个整数10的结果
        std::cout << "10 * r/(RAND_MAX+1.0f) = " << 10 * r/(RAND_MAX+1.0f) << std::endl; 
        // 我的错误理解,先除再缩放的结果
        std::cout << "10 * (r/(RAND_MAX+1.0f)) = " << 10 * (r/(RAND_MAX+1.0f)) << std::endl; 
        //网上常用的生成随机数的方法,乘的系数是10.0,用double型直接扩充数值范围,得到的结果和我的错误理解类似,再用int强制类型转换,取个整数部分
        std::cout << "((int)(10.0*r / (RAND_MAX + 1.0))) = " << ((int)(10.0*r / (RAND_MAX + 1.0))) << std::endl; 
    }

运行得到的部分结果如下,可以看到,只有10 * r/(RAND_MAX+1.0f)这种情况会出现负值,原因已经在上面分析过。正常取负值的方式可以用2倍范围减一半的方式,例如随机(-10,10)可以用随机得到(0,1)然后取20倍,再整体减掉10。

# results
rand = 218746804
rand/max = 0.101862
10 * r/(RAND_MAX+1.0f) = -0.981381 //有负值
10 * (r/(RAND_MAX+1.0f)) = 1.01862 // 10倍值
((int)(10.0*r / (RAND_MAX + 1.0))) = 1 //10倍值的整数部分

rand = 231106831
rand/max = 0.107618
10 * r/(RAND_MAX+1.0f) = -0.923825 //有负值
10 * (r/(RAND_MAX+1.0f)) = 1.07618
((int)(10.0*r / (RAND_MAX + 1.0))) = 1

rand = 1109549898
rand/max = 0.516674
10 * r/(RAND_MAX+1.0f) = -0.833256 //有负值,当然也有正值,没列出来
10 * (r/(RAND_MAX+1.0f)) = 5.16674
((int)(10.0*r / (RAND_MAX + 1.0))) = 5
......
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值