有没有办法使用链表来简化我的蒙特卡洛代码
你好,我的代码目前有三个函数,每个函数都会生成大量随机数。我想知道是否有一种方法可以让一个函数返回一个链接列表或多维数组,使其变得更整洁:(
复制自 http://pastebin.com/Y5aE6XKS)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#ifndef RAND_MAX
#define RAND_MAX 2147483648
#endif
#define N 420000
double* rdm_X(void);
double* rdm_Y(void);
double* rdm_Z(void);
void main(void)
{
double* Random_number_list_X = rdm_X();
double* Random_number_list_Y = rdm_Y();
double* Random_number_list_Z = rdm_Z();
double X[N+1], Y[N+1], Z[N+1], density = 1, vol = 42.0;
double sum = 0, sum_x = 0, sum_y = 0, sum_z = 0;
int i;
for (i = 0; i <= N; i++) {
X[i] = 3 * Random_number_list_X[i] + 1;
Y[i] = 7 * Random_number_list_Y[i] - 3;
Z[i] = 2 * Random_number_list_Z[i] - 1;
if ((Z[i]*Z[i]) + (sqrt(X[i]*X[i] + Y[i]*Y[i]) - 3)*(sqrt(X[i]*X[i] + Y[i]*Y[i]) - 3) <= 1) {
sum += density;
sum_x += X[i] * density;
sum_y += Y[i] * density;
sum_z += Z[i] * density;
}
}
printf("(%.5lf, %.5lf, %.5lf)\n",
sum_x/sum, sum_y/sum, sum_z/sum);
}
double* rdm_X(void)
{
double* Random_number_list_X = calloc(N + 1, sizeof(double));
int i;
srand(time(NULL));
for (i = 1; i <= N; i++) {
Random_number_list_X[i] = (float) rand() / (float) RAND_MAX;
}
return Random_number_list_X;
}
double* rdm_Y(void)
{
double* Random_number_list_Y = calloc(N + 1, sizeof(double));
int i;
sleep(1);
srand(time(NULL));
for (i = 1; i <= N; i++) {
Random_number_list_Y[i] = (float) rand() / (float) RAND_MAX;
}
return Random_number_list_Y;
}
double* rdm_Z(void)
{
double* Random_number_list_Z = calloc(N + 1, sizeof(double));
int i;
sleep(2);
srand(time(NULL));
for (i = 1; i <= N; i++) {
Random_number_list_Z[i] = (float) rand() / (float) RAND_MAX;
}
return Random_number_list_Z;
}
Hiya, my code currently has three functions each producing a massive array of random numbers. Im wondering if there is a way of just having one function returning a linked list or multidimensional array to make it a bit neater:
(copied from http://pastebin.com/Y5aE6XKS)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#ifndef RAND_MAX
#define RAND_MAX 2147483648
#endif
#define N 420000
double* rdm_X(void);
double* rdm_Y(void);
double* rdm_Z(void);
void main(void)
{
double* Random_number_list_X = rdm_X();
double* Random_number_list_Y = rdm_Y();
double* Random_number_list_Z = rdm_Z();
double X[N+1], Y[N+1], Z[N+1], density = 1, vol = 42.0;
double sum = 0, sum_x = 0, sum_y = 0, sum_z = 0;
int i;
for (i = 0; i <= N; i++) {
X[i] = 3 * Random_number_list_X[i] + 1;
Y[i] = 7 * Random_number_list_Y[i] - 3;
Z[i] = 2 * Random_number_list_Z[i] - 1;
if ((Z[i]*Z[i]) + (sqrt(X[i]*X[i] + Y[i]*Y[i]) - 3)*(sqrt(X[i]*X[i] + Y[i]*Y[i]) - 3) <= 1) {
sum += density;
sum_x += X[i] * density;
sum_y += Y[i] * density;
sum_z += Z[i] * density;
}
}
printf("(%.5lf, %.5lf, %.5lf)\n",
sum_x/sum, sum_y/sum, sum_z/sum);
}
double* rdm_X(void)
{
double* Random_number_list_X = calloc(N + 1, sizeof(double));
int i;
srand(time(NULL));
for (i = 1; i <= N; i++) {
Random_number_list_X[i] = (float) rand() / (float) RAND_MAX;
}
return Random_number_list_X;
}
double* rdm_Y(void)
{
double* Random_number_list_Y = calloc(N + 1, sizeof(double));
int i;
sleep(1);
srand(time(NULL));
for (i = 1; i <= N; i++) {
Random_number_list_Y[i] = (float) rand() / (float) RAND_MAX;
}
return Random_number_list_Y;
}
double* rdm_Z(void)
{
double* Random_number_list_Z = calloc(N + 1, sizeof(double));
int i;
sleep(2);
srand(time(NULL));
for (i = 1; i <= N; i++) {
Random_number_list_Z[i] = (float) rand() / (float) RAND_MAX;
}
return Random_number_list_Z;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
几点:
RAND_MAX
。main
返回一个 int。A few points:
RAND_MAX
yourself.main
returns an int.srand
once.srand
, and use one function to initialize your arrays.我不是第一个指出您应该只调用
srand
一次的人,但我会解释原因:您调用
srand 的次数越多
rand
的输出较少随机。rand
函数是一个伪 >-随机数生成器。这意味着它生成的数字看起来是随机的,并且具有与随机性相对应的数学属性,但它们实际上并不是随机的。 rand 的输出实际上是一个固定的、完全确定性的数字序列。或者更确切地说,它产生了一个完全确定性序列大家族中的一个。您可以通过使用
srand
提供“种子”值来选择所需的序列。当您为srand
提供种子x
时,rand
的下一个输出将是伪随机数的第一个数字(但完全确定性!)由种子x
标识的序列。换句话说:对于不同的输入将返回不同的值,但对于给定的
x
,将始终返回相同值。根本不是随机的!这实际上是一个有用的功能,因为如果您在依赖
rand
输出的程序中发现错误,您可以通过向srand
提供相同的种子来可靠地重现该错误> 以便从rand
获得相同的序列,从而从程序中获得相同的行为。您需要调用 srand 一次的原因是,否则您的程序将始终从
rand
接收相同的数字序列(由种子1
标识的序列)代码>)。您不想想要多次调用srand
的原因(在大多数情况下)是因为您随后反复迫使rand
回到开头它的序列而不是让它给你其中一个完整的序列。虽然任何给定的序列都具有随机性的属性,但序列开头的序列不一定具有该属性。显然,如果您使用相同种子重复调用
srand
,那会特别糟糕,因为这样您就强制rand
每次都回到相同序列的开头,因此rand
将始终产生相同值 - 正是您不想要的。您经常看到 srand(time(NULL)) 的原因是因为给定程序的任意两次调用之间的时间可能不同,这意味着程序每次运行时都会使用不同的时间。伪随机序列。但是
time
仅返回以秒为单位的时间,因此,如果您在程序的单次调用中重复执行此操作(如您的程序一样),并且对 srand 的调用之间的间隔时间少于一秒,正如您所观察到的,您将重复使用相同的种子重新播种,并产生荒谬的结果。底线:在第一次使用
rand
之前,仅调用srand
一次。相信 C 库的实现者编写了一个不错的伪随机数生成器,并且不要试图通过尝试补偿不存在的问题来“增加随机性”。I'm not the first to point out that you should only call
srand
once, but I'll explain why:The more often you call
srand
the less random the output ofrand
is.The
rand
function is a pseudo-random number generator. That means that it generates numbers that look random, and have mathematical properties corresponding to randomness, but they aren't actually random. The output ofrand
is actually a fixed, completely deterministic sequence of numbers.Or, rather, it produces one of a large family of completely deterministic sequences. You select which of these sequences you want by providing a "seed" value using
srand
. When you givesrand
a seedx
, the next output ofrand
will be the first number of the pseudo-random (but completely deterministic!) sequence identified by the seedx
. In other words:Will return different values for different inputs, but for a given
x
, will always return the same value. Not at all random!This is actually a useful feature, since if you discover a bug in a program that relies on the output of
rand
, you can reliably reproduce the bug by providing the same seed tosrand
in order to obtain the same sequence fromrand
and so the same behavior from your program.The reason that you need to call
srand
once is because otherwise your program will always receive the same sequence of numbers fromrand
(the sequence identified by seed1
). The reason you do not want to callsrand
more than once (in most cases) is because you are then repeatedly forcingrand
back to the beginnings of its sequences rather than letting it give you one of them in its entirety. While any given sequence has properties of randomness, the sequence of sequence-beginnings does not necessarily have this property.Obviously, it's especially bad if you call
srand
repeatedly with the same seed, because then you're forcingrand
back to the beginning of the same sequence every time, and sorand
will always produce the same value -- exactly what you don't want.The reason you commonly see
srand(time(NULL))
is because the time is likely to be different between any two invocations of a given program, which means that every time the program runs it will use a different pseudorandom sequence. Buttime
only returns the time to the granularity of seconds, so if you do this repeatedly within a single invocation of a program, as in yours, and less than one second elapses between calls tosrand
, you will be repeatedly re-seeding with the same seed, with ridiculous results, as you have observed.Bottom Line: Call
srand
exactly once, before your first use ofrand
. Trust that the implementers of the C library wrote a decent pseudo-random number generator, and don't try to "increase randomness" by attempting to compensate for problems that don't exist.三个函数之间的唯一区别在于它们如何调用
sleep()
。您当然可以将所有三个函数折叠成一个函数,并在循环中调用它三次吗?The only difference between your three functions is how they call
sleep()
. Surely you can collapse all three into a single function, and call it three times in a loop?每次程序调用时仅调用 srand() 一次,通常在
main()
内。Only call
srand()
once per program invocation, typically insidemain()
.其他人已经解决了您的程序的一些问题,但是您是否意识到每次运行它时都会泄漏超过 10 MB 的内存?自由的()...
Other people already addressed some issues with your program, but do you realize that you are leaking over 10 megabytes of memory every time you run it? free()...