我已经做了一段时间并且遇到了很多麻烦。我想生成一个从-1到1的随机值进行计算。我不能使用%运算符,因为它仅适用于整数。我也尝试使用fmod()
,但我也遇到了困难。
我试图使用的是......
double random_value;
random_value = fmod((double) rand(),2) + (-1);
但是,它似乎不正确。我也试着用时间播种srand,但我认为我在那里做错了,因为它一直在抛出这个错误:
"error: expected declaration specifiers or '...' before time"
代码:
srand((unsigned) time(&t));
任何有关这些问题的帮助都会受到赞赏。
答案 0 :(得分:5)
这会使随机数生成器播种,并在-1.0到1.0
范围内给出一个双精度值#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
double random_value;
srand ( time ( NULL));
random_value = (double)rand()/RAND_MAX*2.0-1.0;//float in range -1 to 1
printf ( "%f\n", random_value);
return 0;
}
答案 1 :(得分:3)
您可以按时间播种(一次拨打rand
之前一次),如下所示:
#include <time.h>
// ...
srand (time ( NULL));
使用此功能,您可以根据需要设置最小/最大值。
#include <stdio.h>
#include <stdlib.h>
/* generate a random floating point number from min to max */
double randfrom(double min, double max)
{
double range = (max - min);
double div = RAND_MAX / range;
return min + (rand() / div);
}
来源:[SOLVED] Random double generator problem (C Programming) Ubuntu Forums
然后你会这样称呼:
double myRand = randfrom(-1.0, 1.0);
但请注意,这很可能不会涵盖double
提供的所有精确度。甚至没有考虑指数,IEEE-754 double包含52位有效数(即非指数部分)。由于rand
在int
和0
之间返回RAND_MAX
,因此RAND_MAX
的最大可能值为INT_MAX
。在许多(大多数?)平台上,int
为32位,因此INT_MAX
为0x7fffffff
,覆盖31位范围。
答案 2 :(得分:1)
我认为创建真正的随机双精度的最佳方法是使用它的结构。 Here是一篇关于如何存储浮点数的文章。如您所见,浮点数在1和-1之间的唯一限制条件是指数值不超过128.
Ieee754SingleDigits2Double
将0和1的字符串转换为float变量并返回它。我从this问题的答案中得到了它。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
double Ieee754SingleDigits2Double(const char s[32])
{
double f;
int sign, exp;
unsigned int mant;
int i;
sign = s[0] - '0';
exp = 0;
for (i = 1; i <= 8; i++)
exp = exp * 2 + (s[i] - '0');
exp -= 127;
if (exp > -127)
{
mant = 1; // The implicit "1."
exp -= 23;
}
else
{
mant = 0;
exp = -126;
exp -= 23;
}
for (i = 9; i <= 31; i++)
mant = mant * 2 + (s[i] - '0');
f = mant;
while (exp > 0)
f *= 2, exp--;
while (exp < 0)
f /= 2, exp++;
if (sign)
f = -f;
return f;
}
这是主要功能:
int main(void)
{
srand ( time ( NULL));
int i;
char s[33];
for(i = 0; i < 32; i++)
{
if(i == 1)
continue;
s[i] = rand() % 2 + '0';
}
s[1] = '0';
s[32] = 0;
printf("%s\n", s);
printf("%+g\n", Ieee754SingleDigits2Double(s));
return 0;
}
答案 3 :(得分:1)
与其他答案类似,通过一些改进,您可能需要保持代码更安全和连贯:
#include <stdlib.h> /* srand and rand */
#include <unistd.h> /* getpid */
#include <time.h> /* time */
#include <errno.h> /* errno */
#include <math.h> /* NAN */
/* generate a float random number in a range */
float randmm(float min, float max)
{
static int first = -1;
if((first = (first<0)))
srand(time(NULL)+getpid());
if(min>=max)
return errno=EDOM, NAN;
return min + (float)rand() / ((float)RAND_MAX / (max - min));
}
浏览我们的代码:
first
,可以保证您不会忘记为伪随机数生成器(PRNG)播种。逻辑简单而优雅:在第一次调用中,first
为-1,然后将其比较为小于零,将其更新为 true (值1)。第二个调用询问first
(现在为1)是否小于零,即 false (值为0),因此srand()
未被调用。他们说,第三个是魅力,所以现在first
,即0,会被问到它是否小于零,这对于此次和下次迭代都是假的。errno.h
设置错误,math.h
使用NAN
(非数字)宏。不建议比较两个浮点数是否相等(如if(min==max)
),因此在min更大的情况下尝试反转最小/最大值并不是一个好主意,如果它们相等则有第三个选项。只需使用两个选项简化if
:它是正确的,或者不是。float
而不是double
来对这个函数可以生成的内容给予太多信任。 32位整数(RAND_MAX
)只能做这么多。对于所有位,填充float
是合理的。 float
数字只有23位,而指数只有8位。如果您使用double
,则会对此功能的容量产生误导和过度自信。如果您需要真正的双倍,请考虑使用/dev/urand
或其他正确的真随机数生成器(TRNG)。float
,这样除了编译器的解释之外,我还可以看到代码的意图。float x = randmm(-1.0, 1.0);
答案 4 :(得分:0)
这样做可能不是一个好主意,但仅仅因为它有效,这里使用/dev/urandom
和cos()
来生成-1到1之间的随机双倍:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <math.h>
int main()
{
int fd;
double x;
fd = open("/dev/urandom", O_RDONLY);
if (fd == -1)
return (1);
read(fd, &x, sizeof(x));
close(fd);
x = cos(x);
printf("%f\n", x);
return (0);
}
答案 5 :(得分:0)
经过大量搜索并从中获取提示后,我创建此函数以生成特定范围内的随机双数。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
double random(double min, double max)
{
//used it to generate new number each time
srand( (unsigned int) time(NULL) );
double randomNumber, range , tempRan, finalRan;
//generate random number form 0.0 to 1.0
randomNumber = (double)rand() / (double)RAND_MAX;
//total range number from min to max eg. from -2 to 2 is 4
//range used it to pivot form -2 to 2 -> 0 to 4 for next step
range = max - min
//illustrate randomNumber to range
//lets say that rand() generate 0.5 number, thats it the half
//of 0.0 to 1.0, show multiple range with randomNumber we get the
//half in range. eg 4 * 0.5 = 2
tempRan = randomNumber * range;
//add the min to tempRan to get the correct random in ours range
//so in ours example we have: 2 + (-2) = 0, thats the half in -2 to 2
finalRan = tempRan + min;
return finalRan;
}
这说明了我们范围内随机数的比率。
答案 6 :(得分:0)
有一种简单的方法可以获取[-1.0; 1.0]三角函数正弦采用rand()返回的数字,并返回该范围内的值。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
/* macro returning value in range [-1.0; 1.0] */
#define double_rand() ( sin(rand()) )
int main(void) {
int i;
srand(time(NULL));
/* 20 tests to show result */
for ( i = 0; i < 20; ++i )
printf("%f\n", double_rand());
return 0;
}
在linux系统上,别忘了链接数学库
$ gcc -Wall sin_rand.c -lm
$ ./a.out
0.014475
-0.751095
-0.650722
0.995111
-0.923760
...
答案 7 :(得分:0)
此答案主要适用于在x86_64机器上寻找随机双打的人。 作为长期的C用户(自1980年代后期以来),我放弃了关心当日的RAND_MAX值。
此外,srand(time(NULL)
向我表明,这些数字是由(至少对我而言)质量未知的某种准随机数生成器生成的。而且,尽管您只有1条汇编指令与现代x86_64计算机上的CPU随机数相距甚远。
因此,下面的代码通过内部函数使用rdrand
,该函数被称为完整的64位随机数,作为随机性的来源。这样,至少,您有足够的位来生成双精度,而无需费心。如果-相反-您选择了C库rand()
并且它返回了32位值,则可能没有足够的位来容纳64个浮点数。而且,Afaik的Ansi C中没有randl(), randul()
等。
但是-如果您查看_rdrand_step()
内在函数的签名,则该指令在某些情况下可能会失败。 (与负载有关,有人说)。因此,在下面的代码中,(或可能不)在固有调用周围编写while()循环或类似内容是一个好主意。
#include <stdio.h>
#include <stdint.h>
#include <immintrin.h>
#include <float.h>
int randomf64(double minVal, double maxVal, double* out) {
if (NULL == out)
return 0;
uint64_t result = 0ULL;
// cast in next line works for amd64 (x86_64) on linux at least.
int rc = _rdrand64_step((unsigned long long*)&result);
if(rc) {
double unscaled = (double)result/(double)UINT64_MAX;
*out = minVal + (maxVal - minVal) * unscaled;
return 1;
}
return 0;
}
int main(int argc, const char* argv[]) {
size_t nvals = 1;
if(argc > 1) {
nvals = atol(argv[1]);
}
// We want to see if all that "can fail under stress" thing happens...
double *values = malloc(nvals * sizeof(double));
if (NULL != values) {
for(size_t i = 0; i < nvals; ++i ) {
if(!randomf64(-100.0,100.0, &values[i])) {
printf("boom! after %lu random numbers generated.\n",
i);
free(values);
exit(-1);
}
}
for(size_t i = 0; i < nvals; ++i) {
int Digs = DECIMAL_DIG;
printf("%lu %.*e\n", i, Digs, values[i]);
}
free(values);
}
return 0;
}
如果您提供整数作为命令行参数,则会生成一个相应的 随机双精度数并将它们存储在分配给堆的数组中。 这允许测试是否可能发生“零星失败”。我尝试了一次,最多创建了一个1E6值,但从未失败(在某些廉价的AMD CPU上)。
为了进行编译,例如与clang一起使用:
clang -mrdrnd -O3 -std = c17 -o r64i r64intrin.c
请注意,必须启用-mrdrnd
中的内在函数才能使编译器满意。
答案 8 :(得分:-1)
random_value = (double)rand() * rand() / (RAND_MAX * RAND_MAX) * 2 - 1;