本文翻译自:Why does rand() + rand() produce negative numbers?

I observed that rand() library function when it is called just once within a loop, it almost always produces positive numbers. 我观察到rand()库函数在循环中只调用一次,它几乎总是产生正数。

for (i = 0; i < 100; i++) {printf("%d\n", rand());
}

But when I add two rand() calls, the numbers generated now have more negative numbers. 但是当我添加两个rand()调用时,现在生成的数字会有更多的负数。

for (i = 0; i < 100; i++) {printf("%d = %d\n", rand(), (rand() + rand()));
}

Can someone explain why I am seeing negative numbers in the second case? 有人可以解释为什么我在第二种情况下看到负数吗?

PS: I initialize the seed before the loop as srand(time(NULL)) . PS:我在循环之前将种子初始化为srand(time(NULL))


#1楼

参考:https://stackoom.com/question/25K3S/为什么rand-rand-产生负数


#2楼

rand() is defined to return an integer between 0 and RAND_MAX . rand()定义为返回0RAND_MAX之间的整数。

rand() + rand()

could overflow. 可能会溢出 What you observe is likely a result of undefined behaviour caused by integer overflow. 您观察到的可能是整数溢出导致的未定义行为的结果。


#3楼

The problem is the addition. 问题是增加。 rand() returns an int value of 0...RAND_MAX . rand()返回一个int0...RAND_MAX So, if you add two of them, you will get up to RAND_MAX * 2 . 因此,如果你添加其中两个,你将达到RAND_MAX * 2 If that exceeds INT_MAX , the result of the addition overflows the valid range an int can hold. 如果超过INT_MAX ,则添加的结果会溢出int可以容纳的有效范围。 Overflow of signed values is undefined behaviour and may lead to your keyboard talking to you in foreign tongues. 签名值溢出是未定义的行为,可能导致您的键盘用外语说话。

As there is no gain here in adding two random results, the simple idea is to just not do it. 由于添加两个随机结果没有增益,简单的想法就是不这样做。 Alternatively you can cast each result to unsigned int before the addition if that can hold the sum. 或者,如果可以保存总和,则可以在添加之前将每个结果转换为unsigned int Or use a larger type. 或者使用更大的类型。 Note that long is not necessarily wider than int , the same applies to long long if int is at least 64 bits! 注意long不一定比int long long如果int至少为64位,则int适用于long long

Conclusion: Just avoid the addition. 结论:避免添加。 It does not provide more "randomness". 它没有提供更多的“随机性”。 If you need more bits, you might concatenate the values sum = a + b * (RAND_MAX + 1) , but that also likely requires a larger data type than int . 如果需要更多位,可以连接值sum = a + b * (RAND_MAX + 1) ,但这也可能需要比int更大的数据类型。

As your stated reason is to avoid a zero-result: That cannot be avoided by adding the results of two rand() calls, as both can be zero. 正如你所陈述的原因是为了避免零结果:通过添加两个rand()调用的结果无法避免,因为两者都可以为零。 Instead, you can just increment. 相反,你可以增加。 If RAND_MAX == INT_MAX , this cannot be done in int . 如果RAND_MAX == INT_MAX ,则无法在int完成。 However, (unsigned int)rand() + 1 will do very, very likely. 但是, (unsigned int)rand() + 1非常非常可能。 Likely (not definitively), because it does require UINT_MAX > INT_MAX , which is true on all implementations I'm aware of (which covers quite some embedded architectures, DSPs and all desktop, mobile and server platforms of the past 30 years). 可能(不是最终),因为它确实需要UINT_MAX > INT_MAX ,这在我所知的所有实现中都是如此(其中涵盖了过去30年的一些嵌入式架构,DSP和所有桌面,移动和服务器平台)。

Warning: 警告:

Although already sprinkled in comments here, please note that adding two random values does not get a uniform distribution, but a triangular distribution like rolling two dice: to get 12 (two dice) both dice have to show 6 . 虽然已经评论洒在这里,请注意添加两个随机值没有得到一个均匀分布,但像滚动两个骰子三角分布:得到12 (两个骰子)两个骰子必须显示6 for 11 there are already two possible variants: 6 + 5 or 5 + 6 , etc. 对于11 ,已经有两种可能的变体: 6 + 55 + 6等。

So, the addition is also bad from this aspect. 因此,从这方面来说,增加也是不好的。

Also note that the results rand() generates are not independent of each other, as they are generated by a pseudorandom number generator . 还要注意, rand()生成的结果不是彼此独立的,因为它们是由伪随机数生成器生成的 Note also that the standard does not specify the quality or uniform distribution of the calculated values. 另请注意,标准未指定计算值的质量或均匀分布。


#4楼

This is an answer to a clarification of the question made in comment to this answer , 这是澄清对此答案发表评论的问题的答案 ,

the reason i was adding was to avoid '0' as the random number in my code. 我添加的原因是为了避免'0'作为我的代码中的随机数。 rand()+rand() was the quick dirty solution which readily came to my mind. rand()+ rand()是我想到的快速肮脏的解决方案。

The problem was to avoid 0. There are (at least) two problems with the proposed solution. 问题是避免0.建议的解决方案存在(至少)两个问题。 One is, as the other answers indicate, that rand()+rand() can invoke undefined behavior. 一个是,正如其他答案所示, rand()+rand()可以调用未定义的行为。 Best advice is to never invoke undefined behavior. 最好的建议是永远不要调用未定义的行为。 Another issue is there's no guarantee that rand() won't produce 0 twice in a row. 另一个问题是不能保证rand()不会连续两次产生0。

The following rejects zero, avoids undefined behavior, and in the vast majority of cases will be faster than two calls to rand() : 以下拒绝零,避免未定义的行为,并且在绝大多数情况下将比两次调用rand()更快:

int rnum;
for (rnum = rand(); rnum == 0; rnum = rand()) {}
// or do rnum = rand(); while (rnum == 0);

#5楼

While what everyone else has said about the likely overflow could very well be the cause of the negative, even when you use unsigned integers. 虽然其他所有关于可能溢出的说法很可能是否定的原因,即使你使用无符号整数。 The real problem is actually using time/date functionality as the seed. 真正的问题实际上是使用时间/日期功能作为种子。 If you have truly become familiar with this functionality you will know exactly why I say this. 如果您真正熟悉此功能,您将确切地知道我为什么这么说。 As what it really does is give a distance (elapsed time) since a given date/time. 正如它真正做的那样是给出自给定日期/时间以来的距离(经过时间)。 While the use of the date/time functionality as the seed to a rand(), is a very common practice, it really is not the best option. 虽然使用日期/时间功能作为rand()的种子是一种非常普遍的做法,但它确实不是最好的选择。 You should search better alternatives, as there are many theories on the topic and I could not possibly go into all of them. 你应该寻找更好的选择,因为有很多关于这个主题的理论,我不可能进入所有这些。 You add into this equation the possibility of overflow and this approach was doomed from the beginning. 你在这个等式中加入溢出的可能性,这种方法从一开始就注定要失败。

Those that posted the rand()+1 are using the solution that most use in order to guarantee that they do not get a negative number. 那些发布了rand()+ 1的人正在使用最常用的解决方案,以保证他们不会得到负数。 But, that approach is really not the best way either. 但是,这种方法也不是最好的方法。

The best thing you can do is take the extra time to write and use proper exception handling, and only add to the rand() number if and/or when you end up with a zero result. 您可以做的最好的事情是花费额外的时间来编写和使用正确的异常处理,并且只有在和/或最终得到零结果时才添加到rand()数字。 And, to deal with negative numbers properly. 并且,正确处理负数。 The rand() functionality is not perfect, and therefore needs to be used in conjunction with exception handling to ensure that you end up with the desired result. rand()功能并不完美,因此需要与异常处理结合使用,以确保最终得到所需的结果。

Taking the extra time and effort to investigate, study, and properly implement the rand() functionality is well worth the time and effort. 花费额外的时间和精力来调查,研究和正确实现rand()功能非常值得花时间和精力。 Just my two cents. 只是我的两分钱。 Good luck in your endeavors... 祝你好运...


#6楼

May be you could try rather a tricky approach by ensuring that the value returned by sum of 2 rand() never exceeds the value of RAND_MAX. 也许你可以通过确保2 rand()的总和返回的值永远不会超过RAND_MAX的值来尝试相当棘手的方法。 A possible approach could be sum = rand()/2 + rand()/2; 一种可能的方法可能是sum = rand()/ 2 + rand()/ 2; This would ensure that for a 16 bit compiler with RAND_MAX value of 32767 even if both rand happens to return 32767, even then (32767/2 = 16383) 16383+16383 = 32766, thus would not result in negative sum. 这将确保对于RAND_MAX值为32767的16位编译器,即使两个rand碰巧返回32767,即使那时(32767/2 = 16383)16383 + 16383 = 32766,也不会导致负和。

为什么rand()+ rand()产生负数?相关推荐

  1. MySQL中的RAND()函数使用详解

    转自:https://www.jb51.net/article/66697.htm MySQL RAND()函数调用可以在0和1之间产生一个随机数: ? 1 2 3 4 5 6 7 mysql> ...

  2. mysql rand()产生随机整数范围及方法

    根据官方文档,rand()的取值范围为[0,1) 若要在i ≤ R ≤ j 这个范围得到一个随机整数R ,需要用到表达式 FLOOR(i + RAND() * (j – i + 1)) 例如, 若要在 ...

  3. SQL:RAND()返回随机数

    参考:http://msdn.microsoft.com/zh-cn/library/ms177610.aspx RAND (Transact-SQL) SQL Server 2012 返回一个介于 ...

  4. C语言(rand函数)

    C语言(rand函数) (2006-09-24 20:41:59) 转载     srand()就是给rand()提供种子seed 1,先看一个例子 #include <iostream> ...

  5. 深度解密 Go math/rand

    Go 获取随机数是开发中经常会用到的功能, 不过这个里面还是有一些坑存在的, 本文将完全剖析 Go math/rand, 让你轻松使用 Go Rand. 开篇一问: 你觉得 rand 会 panic ...

  6. c++随机数函数rand()

    c 语言rand()生成随机数 c语言中rand()函数生成随机数的用法: 详细介绍: (1)使用该函数首先应在开头包含头文件stdlib.h #include<stdlib.h>(C++ ...

  7. Matlab rand randn randint

    1.0matlab中rand函数是产生0到1的随机分布 2.0matlab中randn函数是产生标准正态分布 3.0randint是产生整数随机数,默认为0和1 1.0rand %%%%%%%%%%% ...

  8. java roundup函数_Excel函数(2)if、rand、round函数

    阅读提示:阅读对象:完全不了解这些函数,和对这几个函数有初步了解想要进一步深入的 建议阅读时间:10分钟 知识点:if.if嵌套.AND OR.iferror.rand.randbetween.abs ...

  9. excel =rand() 随机生成数字或区间数字的函数使用

    日常工作中,有时候需要用到一些随机的数字,如果少的话手工可以录入,如果数量多,手工录入就会很麻烦,这时候,我们用rand函数便能轻松实现. rand函数的语法结构为:=Rand() rand函数没有参 ...

最新文章

  1. 两个免费转换视频的软件,实现服务器端Video2FLV
  2. php使用aot,aot的常规使用
  3. 文本分类与聚类(text categorization and clustering)
  4. 【tensorflow】tf-argmax()
  5. MTU 和 MSS 区别
  6. 区域锁(Scoped locking)
  7. 浅析Linux awk命令
  8. 【Python 必会技巧】获取字典中(多个)最大值(value)的键(key)
  9. poj3264Balanced Lineup(RMQ)
  10. 数理在线计算机,原码/反码/补码在线计算器
  11. 在非关联情况下的欧姆定律的使用
  12. 单兵渗透工具-Yakit-Windows安装使用
  13. Mix-In的译法探讨
  14. 初学者,日益维新,记录所学点点滴滴
  15. MATLAB中安装Yalmip及Cplex
  16. 51单片机实现8只LED左右来回点亮
  17. 关于jsp网页弹出窗口
  18. velocity模板_使用Velocity进行客户端和服务器端模板
  19. Robinhood向美国监管机构递交供传统银行服务的规章
  20. VONR 中 video speech real-time text 的 bit rate整理 VONR的采样率整理

热门文章

  1. 【工具】开发环境之vagrant
  2. Qzone高性能HTTPS实践
  3. Lync 2013企业实战(三)
  4. EMC VNX将引发中低端市场震荡
  5. asp.net core2.0中网站发布的时候,怎么样才配置才可以使视图文件不被打包进去?...
  6. ORB-SLAM2 地图加载2
  7. 使用generator自动生成Mybatis映射配置文件
  8. DB层面上的设计 分库分表 读写分离 集群化 负载均衡
  9. mina 和 xsocket
  10. 为什么只有软件就可以用盗版?