473,395 Members | 1,343 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Random floats function

I tried making a function that would fill half of an array with random
doubles that would go from -pi to +pi. Unfortunatly, all it ever
returns is -pi. I haven't used an already existing random number
generating function because I wasn't sure to know how to use them so I
created my own based on the random number generator from the INMOS
Transputer Development system which is x[n+1] = (1664525 x[n]) mod 2^32

double modfloat(double a, double b)
{
double c, d, x;

c=a/b;
d=(int32_t) c;
x=c-d;
return x;
}

double dblrand(double x)
{
return modfloat((1664525 * x * pow(2, 32)), pow(2, 32)) / pow(2, 32);
}

void phasenoise(double *s, int32_t M)
{
int32_t i;
time_t seed=time(NULL);
double pi=atan(1.0)*4.0;

s[M/2+1]=dblrand((double) seed/pow(2, 32)) * (2*pi) - pi;
for (i=M/2+2; i<M; i++)
s[i]=dblrand((s[i-1]+pi) / (2*pi)) * (2*pi) - pi;
}

Nov 15 '05 #1
15 2490
Michel Rouzic wrote:
I tried making a function that would fill half of an array with random
doubles that would go from -pi to +pi. Unfortunatly, all it ever
returns is -pi. I haven't used an already existing random number
generating function because I wasn't sure to know how to use them so I
created my own based on the random number generator from the INMOS
Transputer Development system which is x[n+1] = (1664525 x[n]) mod 2^32

double modfloat(double a, double b)
{
double c, d, x;

c=a/b;
d=(int32_t) c;
uint32_t, if anything. However, this is not guaranteed to
work either.
x=c-d;
return x;
}
BTW:
You do need to invent modfloat(), use fmod() instead.
double dblrand(double x)
{
return modfloat((1664525 * x * pow(2, 32)), pow(2, 32)) / pow(2, 32); ^^^^^^^^^^
Lose that one.
a*b%b == 0
So, you always get back something near 0.0, which leads with
your scaling to -pi. }

void phasenoise(double *s, int32_t M)
{
int32_t i;
time_t seed=time(NULL);
double pi=atan(1.0)*4.0;

s[M/2+1]=dblrand((double) seed/pow(2, 32)) * (2*pi) - pi;
for (i=M/2+2; i<M; i++)
s[i]=dblrand((s[i-1]+pi) / (2*pi)) * (2*pi) - pi;
}


Notes:
If the number of random digits does not play that much of a role,
then use (double)rand()/RANDMAX instead (with an appropriate seed
set by srand()).
Otherwise, use another off-the-shelf generator -- it probably has
better mathematical properties than your generator. This is not
the right place to discuss this, though.

I would rather work with symbolic constants instead of
pow(2, 32) and pi.
A convenient portable way for the former is
#define POW2TO32_DBL ((1UL << 31)*2.0)
For the latter, just take enough digits of pi.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 15 '05 #2

Michael Mair wrote:
Michel Rouzic wrote:
I tried making a function that would fill half of an array with random
doubles that would go from -pi to +pi. Unfortunatly, all it ever
returns is -pi. I haven't used an already existing random number
generating function because I wasn't sure to know how to use them so I
created my own based on the random number generator from the INMOS
Transputer Development system which is x[n+1] = (1664525 x[n]) mod 2^32

double modfloat(double a, double b)
{
double c, d, x;

c=a/b;
d=(int32_t) c;
uint32_t, if anything. However, this is not guaranteed to
work either.
x=c-d;
return x;
}


BTW:
You do need to invent modfloat(), use fmod() instead.


oh thanks i had never heard about it before.
double dblrand(double x)
{
return modfloat((1664525 * x * pow(2, 32)), pow(2, 32)) / pow(2, 32);

^^^^^^^^^^
Lose that one.
a*b%b == 0
So, you always get back something near 0.0, which leads with
your scaling to -pi.


yeah but no, x is a double between 0 and 1, if i do that it's to get
back to the previous result before it's divided.
}

void phasenoise(double *s, int32_t M)
{
int32_t i;
time_t seed=time(NULL);
double pi=atan(1.0)*4.0;

s[M/2+1]=dblrand((double) seed/pow(2, 32)) * (2*pi) - pi;
for (i=M/2+2; i<M; i++)
s[i]=dblrand((s[i-1]+pi) / (2*pi)) * (2*pi) - pi;
}


Notes:
If the number of random digits does not play that much of a role,
then use (double)rand()/RANDMAX instead (with an appropriate seed
set by srand()).


ok, so how do I do that (that's where I sound like a newbie), i do
something like srand(time(NULL)); and then (double) rand()/RANDMAX??
And I admit it kinda annoys me to use a random generator with only 2^15
possibilities (right?) but I guess it should be alright.
Otherwise, use another off-the-shelf generator -- it probably has
better mathematical properties than your generator. This is not
the right place to discuss this, though.

I would rather work with symbolic constants instead of
pow(2, 32) and pi.
A convenient portable way for the former is
#define POW2TO32_DBL ((1UL << 31)*2.0)
I have no idea what ((1UL << 31)*2.0) can mean..
For the latter, just take enough digits of pi.


What's wrong with the way I do my pi?

Nov 15 '05 #3

Michael Mair wrote:
Michel Rouzic wrote:
I tried making a function that would fill half of an array with random
doubles that would go from -pi to +pi. Unfortunatly, all it ever
returns is -pi. I haven't used an already existing random number
generating function because I wasn't sure to know how to use them so I
created my own based on the random number generator from the INMOS
Transputer Development system which is x[n+1] = (1664525 x[n]) mod 2^32

double modfloat(double a, double b)
{
double c, d, x;

c=a/b;
d=(int32_t) c;


uint32_t, if anything. However, this is not guaranteed to
work either.
x=c-d;
return x;
}


BTW:
You do need to invent modfloat(), use fmod() instead.
double dblrand(double x)
{
return modfloat((1664525 * x * pow(2, 32)), pow(2, 32)) / pow(2, 32);

^^^^^^^^^^
Lose that one.
a*b%b == 0
So, you always get back something near 0.0, which leads with
your scaling to -pi.
}

void phasenoise(double *s, int32_t M)
{
int32_t i;
time_t seed=time(NULL);
double pi=atan(1.0)*4.0;

s[M/2+1]=dblrand((double) seed/pow(2, 32)) * (2*pi) - pi;
for (i=M/2+2; i<M; i++)
s[i]=dblrand((s[i-1]+pi) / (2*pi)) * (2*pi) - pi;
}


Notes:
If the number of random digits does not play that much of a role,
then use (double)rand()/RANDMAX instead (with an appropriate seed
set by srand()).
Otherwise, use another off-the-shelf generator -- it probably has
better mathematical properties than your generator. This is not
the right place to discuss this, though.

I would rather work with symbolic constants instead of
pow(2, 32) and pi.
A convenient portable way for the former is
#define POW2TO32_DBL ((1UL << 31)*2.0)
For the latter, just take enough digits of pi.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.


I used fmod() instead of my modfloat() and now it works. Well, now the
values seem to be quite random and in the right range, so I guess I'll
keep using my dblrand() function. Thanks alot for help!

Nov 15 '05 #4
Michel Rouzic wrote:
Michael Mair wrote:
Michel Rouzic wrote: <snip!>
double dblrand(double x)
{
return modfloat((1664525 * x * pow(2, 32)), pow(2, 32)) / pow(2, 32);

^^^^^^^^^^
Lose that one.
a*b%b == 0
So, you always get back something near 0.0, which leads with
your scaling to -pi.


yeah but no, x is a double between 0 and 1, if i do that it's to get
back to the previous result before it's divided.


You are right, I did not really think about that one...
Question: Why are you not just using
return fmod(1664525.0 * x, 1.0);
instead?
Notes:
If the number of random digits does not play that much of a role,
then use (double)rand()/RANDMAX instead (with an appropriate seed
set by srand()).


ok, so how do I do that (that's where I sound like a newbie), i do
something like srand(time(NULL)); and then (double) rand()/RANDMAX??
And I admit it kinda annoys me to use a random generator with only 2^15
possibilities (right?) but I guess it should be alright.


RANDMAX is _at_least_ 2^15-1 -- your implementation's standard
library is allowed to do better...
I would rather work with symbolic constants instead of
pow(2, 32) and pi.
A convenient portable way for the former is
#define POW2TO32_DBL ((1UL << 31)*2.0)


I have no idea what ((1UL << 31)*2.0) can mean..


Okay, a << N is a*2^N and has the same type as a. As int is
only guaranteed to have at least 16 bits, I use unsigned long.
1UL is a constant of type unsigned long with value 1.
Unfortunately, unsigned long is only guaranteed to have 32 bits
(and can hold 2^31 but not necessarily 2^32).
As we need a constant of type double, I just multiply the best
I can do by an appropriate double factor.
2^31 as double consequently is (1UL<<31)*1.0, as float
(1UL<<31)*1.0F and so on.
I prefer
((1UL << 31)*2.0)
to actually writing
4294967296.0
as it is easier to see that the former is a power of 2.

So, why bother at all with symbolic constants?
My solution gives you a compile time constant whereas
your solution gives you something which may be computed each
and every time. In addition, you can emphasize the _role_
of the constant to tell one nameless 2^32 from another which
comes in handy when you have to change it...

For the latter, just take enough digits of pi.


What's wrong with the way I do my pi?


1) The C standard makes no guarantee whatsoever about the
precision of the math functions from the library. So, "your"
pi could be way off.
2) Your pi has to be recomputed at every function call.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 15 '05 #5

Michael Mair wrote:
Michel Rouzic wrote:
Michael Mair wrote:
Michel Rouzic wrote: <snip!>
double dblrand(double x)
{
return modfloat((1664525 * x * pow(2, 32)), pow(2, 32)) / pow(2, 32);
^^^^^^^^^^
Lose that one.
a*b%b == 0
So, you always get back something near 0.0, which leads with
your scaling to -pi.


yeah but no, x is a double between 0 and 1, if i do that it's to get
back to the previous result before it's divided.


You are right, I did not really think about that one...
Question: Why are you not just using
return fmod(1664525.0 * x, 1.0);
instead?


oh yeah of course, it's much simpler.
Notes:
If the number of random digits does not play that much of a role,
then use (double)rand()/RANDMAX instead (with an appropriate seed
set by srand()).


ok, so how do I do that (that's where I sound like a newbie), i do
something like srand(time(NULL)); and then (double) rand()/RANDMAX??
And I admit it kinda annoys me to use a random generator with only 2^15
possibilities (right?) but I guess it should be alright.


RANDMAX is _at_least_ 2^15-1 -- your implementation's standard
library is allowed to do better...
I would rather work with symbolic constants instead of
pow(2, 32) and pi.
A convenient portable way for the former is
#define POW2TO32_DBL ((1UL << 31)*2.0)


I have no idea what ((1UL << 31)*2.0) can mean..


Okay, a << N is a*2^N and has the same type as a. As int is
only guaranteed to have at least 16 bits, I use unsigned long.
1UL is a constant of type unsigned long with value 1.
Unfortunately, unsigned long is only guaranteed to have 32 bits
(and can hold 2^31 but not necessarily 2^32).
As we need a constant of type double, I just multiply the best
I can do by an appropriate double factor.
2^31 as double consequently is (1UL<<31)*1.0, as float
(1UL<<31)*1.0F and so on.
I prefer
((1UL << 31)*2.0)
to actually writing
4294967296.0
as it is easier to see that the former is a power of 2.

So, why bother at all with symbolic constants?
My solution gives you a compile time constant whereas
your solution gives you something which may be computed each
and every time. In addition, you can emphasize the _role_
of the constant to tell one nameless 2^32 from another which
comes in handy when you have to change it...


OK, so it's not going to compute it everytime?
For the latter, just take enough digits of pi.


What's wrong with the way I do my pi?


1) The C standard makes no guarantee whatsoever about the
precision of the math functions from the library. So, "your"
pi could be way off.
2) Your pi has to be recomputed at every function call.


oh, ok, well, I guess it's gonna be better if I stop doing that and put
#define pi 3.1415926535897932 instead

Nov 15 '05 #6
"Michel Rouzic" <Mi********@yahoo.fr> writes:
Michael Mair wrote:
Michel Rouzic wrote: [...]
> What's wrong with the way I do my pi?


1) The C standard makes no guarantee whatsoever about the
precision of the math functions from the library. So, "your"
pi could be way off.
2) Your pi has to be recomputed at every function call.


oh, ok, well, I guess it's gonna be better if I stop doing that and put
#define pi 3.1415926535897932 instead


That's 17 significant digits; long double often has more precision
than that.

Using 40 decimal digits will cover anything with a mantissa up to 128
bits, which is enough for any hardware I've ever used. Use an 'L'
suffix to make sure you get the full precision.

It's very likely that you can get away with far less precision,
depending on the application, but using more digits than you'll ever
need isn't a burden, and it means one less thing to worry about if
your program misbehaves.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #7
Keith Thompson wrote:

"Michel Rouzic" <Mi********@yahoo.fr> writes:
Michael Mair wrote:
Michel Rouzic wrote: [...] > What's wrong with the way I do my pi?

1) The C standard makes no guarantee whatsoever about the
precision of the math functions from the library. So, "your"
pi could be way off.
2) Your pi has to be recomputed at every function call.


oh, ok, well, I guess it's gonna be better
if I stop doing that and put
#define pi 3.1415926535897932 instead


That's 17 significant digits; long double often has more precision
than that.

Using 40 decimal digits will cover anything with a mantissa up to 128
bits, which is enough for any hardware I've ever used. Use an 'L'
suffix to make sure you get the full precision.

It's very likely that you can get away with far less precision,
depending on the application, but using more digits than you'll ever
need isn't a burden, and it means one less thing to worry about if
your program misbehaves.


I got all the precision of a double right here:

/* BEGIN pi.c */

#include <stdio.h>
#include <float.h>
#include <math.h>

double pi(void);
double pi2(void);

int main(void)
{
static double Pi, Pi2;

Pi = pi();
Pi2 = pi2();

printf("Pi is %f\n", Pi);
printf("Pi2 is %f\n", Pi2);
printf("Pi - 4 * atan(1) is %e\n", Pi - 4 * atan(1));
printf("Pi2 - 4 * atan(1) is %e\n", Pi2 - 4 * atan(1));
printf("Pi - Pi2 is %e\n", Pi - Pi2);
return 0;
}

double pi(void)
{
double pi, b, first, second, numerator;
unsigned denominator;

pi = 0;
numerator = 1 / 5.0;
denominator = 1;
do {
first = numerator / denominator;
denominator += 2;
numerator /= 25.0;
second = numerator / denominator;
denominator += 2;
numerator /= 25.0;
b = first - second;
pi += b;
} while (b > DBL_EPSILON);
pi *= 4;
numerator = 1 / 239.0;
denominator = 1;
do {
first = numerator / denominator;
denominator += 2;
numerator /= 57121.0;
second = numerator / denominator;
denominator += 2;
numerator /= 57121.0;
b = first - second;
pi -= b;
} while (b > DBL_EPSILON);
return 4 * pi;
}

double pi2(void)
{
double pi, b, first, second, numerator;
unsigned denominator;

pi = 0;
numerator = 1 / 2.0;
denominator = 1;
do {
first = numerator / denominator;
denominator += 2;
numerator /= 4.0;
second = numerator / denominator;
denominator += 2;
numerator /= 4.0;
b = first - second;
pi += b;
} while (b > DBL_EPSILON);
numerator = 1 / 3.0;
denominator = 1;
do {
first = numerator / denominator;
denominator += 2;
numerator /= 9.0;
second = numerator / denominator;
denominator += 2;
numerator /= 9.0;
b = first - second;
pi += b;
} while (b > DBL_EPSILON);
return 4 * pi;
}

/* END pi.c */

--
pete
Nov 15 '05 #8
pete wrote:

Based on the magnitude of the value of the pi variable
when the loops complete, I think better epsilon numbers would be:
double pi(void)
{
double pi, b, first, second, numerator;
unsigned denominator;

pi = 0;
numerator = 1 / 5.0;
denominator = 1;
do {
first = numerator / denominator;
denominator += 2;
numerator /= 25.0;
second = numerator / denominator;
denominator += 2;
numerator /= 25.0;
b = first - second;
pi += b;
} while (b > DBL_EPSILON);
} while (b > 0.125 * DBL_EPSILON);
pi *= 4;
numerator = 1 / 239.0;
denominator = 1;
do {
first = numerator / denominator;
denominator += 2;
numerator /= 57121.0;
second = numerator / denominator;
denominator += 2;
numerator /= 57121.0;
b = first - second;
pi -= b;
} while (b > DBL_EPSILON);
} while (b > 0.5 * DBL_EPSILON);
return 4 * pi;
}

double pi2(void)
{
double pi, b, first, second, numerator;
unsigned denominator;

pi = 0;
numerator = 1 / 2.0;
denominator = 1;
do {
first = numerator / denominator;
denominator += 2;
numerator /= 4.0;
second = numerator / denominator;
denominator += 2;
numerator /= 4.0;
b = first - second;
pi += b;
} while (b > DBL_EPSILON);
} while (b > 0.25 * DBL_EPSILON);
numerator = 1 / 3.0;
denominator = 1;
do {
first = numerator / denominator;
denominator += 2;
numerator /= 9.0;
second = numerator / denominator;
denominator += 2;
numerator /= 9.0;
b = first - second;
pi += b;
} while (b > DBL_EPSILON);
} while (b > 0.5 * DBL_EPSILON);
return 4 * pi;
}

/* END pi.c */


--
pete
Nov 15 '05 #9
pete wrote:

Keith Thompson wrote:

"Michel Rouzic" <Mi********@yahoo.fr> writes:
Michael Mair wrote:
> Michel Rouzic wrote:

[...]
> > What's wrong with the way I do my pi?
>
> 1) The C standard makes no guarantee whatsoever about the
> precision of the math functions from the library. So, "your"
> pi could be way off.
> 2) Your pi has to be recomputed at every function call.

oh, ok, well, I guess it's gonna be better
if I stop doing that and put
#define pi 3.1415926535897932 instead


That's 17 significant digits; long double often has more precision
than that.

Using 40 decimal digits will cover
anything with a mantissa up to 128
bits, which is enough for any hardware I've ever used. Use an 'L'
suffix to make sure you get the full precision.

It's very likely that you can get away with far less precision,
depending on the application, but using more digits than you'll ever
need isn't a burden, and it means one less thing to worry about if
your program misbehaves.


I got all the precision of a double right here:

/* BEGIN pi.c */


Subsequent testing indicates maybe I don't
got all the precision of a double.

--
pete
Nov 15 '05 #10

Keith Thompson wrote:
"Michel Rouzic" <Mi********@yahoo.fr> writes:
Michael Mair wrote:
Michel Rouzic wrote: [...] > What's wrong with the way I do my pi?

1) The C standard makes no guarantee whatsoever about the
precision of the math functions from the library. So, "your"
pi could be way off.
2) Your pi has to be recomputed at every function call.
oh, ok, well, I guess it's gonna be better if I stop doing that and put
#define pi 3.1415926535897932 instead


That's 17 significant digits; long double often has more precision
than that.


I'm only using double precision floats, and since I heard it could take
between 15 and 17 signifiant digits...
Using 40 decimal digits will cover anything with a mantissa up to 128
bits, which is enough for any hardware I've ever used. Use an 'L'
suffix to make sure you get the full precision.

It's very likely that you can get away with far less precision,
depending on the application, but using more digits than you'll ever
need isn't a burden, and it means one less thing to worry about if
your program misbehaves.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.


Nov 15 '05 #11
Michel Rouzic wrote:
Keith Thompson wrote:
"Michel Rouzic" <Mi********@yahoo.fr> writes:
Michael Mair wrote:

Michel Rouzic wrote:


[...]
>What's wrong with the way I do my pi?

1) The C standard makes no guarantee whatsoever about the
precision of the math functions from the library. So, "your"
pi could be way off.
2) Your pi has to be recomputed at every function call.

oh, ok, well, I guess it's gonna be better if I stop doing that and put
#define pi 3.1415926535897932 instead


That's 17 significant digits; long double often has more precision
than that.


I'm only using double precision floats, and since I heard it could take
between 15 and 17 signifiant digits...


This may be the case for your implementation
(platform/OS/compiler/standard library combination) but
the C standard does not guarantee it. Whether or not double
and long double are of different precision also is unspecified.

Probably you have IEEE-like doubles, so this is moot but more
digits do not hurt in _any_ respect. Whether or not it is a
good idea to multiply with a long double constant may depend
on what you want to do and your implementation.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 15 '05 #12
pete wrote:

pete wrote:

Keith Thompson wrote:

"Michel Rouzic" <Mi********@yahoo.fr> writes:
> Michael Mair wrote:
>> Michel Rouzic wrote:
[...]
>> > What's wrong with the way I do my pi?
>>
>> 1) The C standard makes no guarantee whatsoever about the
>> precision of the math functions from the library. So, "your"
>> pi could be way off.
>> 2) Your pi has to be recomputed at every function call.
>
> oh, ok, well, I guess it's gonna be better
> if I stop doing that and put
> #define pi 3.1415926535897932 instead

That's 17 significant digits; long double often has more precision
than that.

Using 40 decimal digits will cover
anything with a mantissa up to 128
bits, which is enough for any hardware I've ever used. Use an 'L'
suffix to make sure you get the full precision.

It's very likely that you can get away with far less precision,
depending on the application, but using more digits than you'll ever
need isn't a burden, and it means one less thing to worry about if
your program misbehaves.


I got all the precision of a double right here:

/* BEGIN pi.c */


Subsequent testing indicates maybe I don't
got all the precision of a double.


I'm pretty close though.
My feeling is that since
(double)3.1415926535897932384626433832795028841971 693993751
compares equal to
4 * atan(1)
on my system, then,
4 * atan(1)
is probably correct.

The return value of pi(), seems to be low by 2 * DBL_EPSILON.
I tried adding the positive half of an extra term
in each loop in pi3, but it didn't help.

/* BEGIN pi.c output */

PI = 3.141592653589793238462643383279502884197169399375 1;
Pi = pi();
Pi2 = pi2();
Pi3 = pi3();

PI is 3.141593
Pi is 3.141593
Pi2 is 3.141593
Pi3 is 3.141593
PI - 4 * atan(1) is 0.000000e+000
Pi - 4 * atan(1) is -4.440892e-016
Pi2 - 4 * atan(1) is -4.440892e-016
Pi3 - 4 * atan(1) is -4.440892e-016
DBL_EPSILON * 2 is 4.440892e-016
Pi - Pi2 is 0.000000e+000
Pi - PI + DBL_EPSILON * 2 is 0.000000e+000

/* END pi.c output */
/* BEGIN pi.c */

#include <stdio.h>
#include <float.h>
#include <math.h>

double pi(void);
double pi2(void);
double pi3(void);

int main(void)
{
double Pi, Pi2, Pi3, PI;

PI = 3.141592653589793238462643383279502884197169399375 1;
Pi = pi();
Pi2 = pi2();
Pi3 = pi3();

puts("/* BEGIN pi.c output */\n");
puts("PI = 3.1415926535897932384626"
"433832795028841971693993751;");
puts("Pi = pi();\nPi2 = pi2();\nPi3 = pi3();\n");
printf("PI is %f\n", PI);
printf("Pi is %f\n", Pi);
printf("Pi2 is %f\n", Pi2);
printf("Pi3 is %f\n", Pi3);
printf("PI - 4 * atan(1) is %e\n", PI - 4 * atan(1));
printf("Pi - 4 * atan(1) is %e\n", Pi - 4 * atan(1));
printf("Pi2 - 4 * atan(1) is %e\n", Pi2 - 4 * atan(1));
printf("Pi3 - 4 * atan(1) is %e\n", Pi3 - 4 * atan(1));
printf("DBL_EPSILON * 2 is %e\n", DBL_EPSILON * 2);
printf("Pi - Pi2 is %e\n", Pi - Pi2);
printf("Pi - PI + DBL_EPSILON * 2 is %e\n",
Pi - PI + DBL_EPSILON * 2);
puts("\n/* END pi.c output */");
return 0;
}

double pi(void)
{
double pi, b, numerator;
unsigned denominator;

pi = 0;
numerator = 1 / 5.0;
denominator = 1;
do {
b = numerator / denominator;
numerator /= 25;
denominator += 2;
b -= numerator / denominator;
numerator /= 25;
denominator += 2;
pi += b;
} while (b > DBL_EPSILON / 8);
pi *= 4;
numerator = 1 / 239.0;
denominator = 1;
do {
b = numerator / denominator;
numerator /= 57121;
denominator += 2;
b -= numerator / denominator;
numerator /= 57121;
denominator += 2;
pi -= b;
} while (b > DBL_EPSILON / 2);
return 4 * pi;
}

double pi2(void)
{
double pi, b, numerator;
unsigned denominator;

pi = 0;
numerator = 1 / 2.0;
denominator = 1;
do {
b = numerator / denominator;
numerator /= 4;
denominator += 2;
b -= numerator / denominator;
numerator /= 4;
denominator += 2;
pi += b;
} while (b > DBL_EPSILON / 4);
numerator = 1 / 3.0;
denominator = 1;
do {
b = numerator / denominator;
numerator /= 9;
denominator += 2;
b -= numerator / denominator;
numerator /= 9;
denominator += 2;
pi += b;
} while (b > DBL_EPSILON / 2);
return 4 * pi;
}

double pi3(void)
{
double pi, b, numerator;
unsigned denominator;

pi = 0;
numerator = 1 / 2.0;
denominator = 1;
do {
b = numerator / denominator;
numerator /= 4;
denominator += 2;
b -= numerator / denominator;
numerator /= 4;
denominator += 2;
pi += b;
} while (b > DBL_EPSILON / 4);
b = numerator / denominator;
pi += b;
numerator = 1 / 3.0;
denominator = 1;
do {
b = numerator / denominator;
numerator /= 9;
denominator += 2;
b -= numerator / denominator;
numerator /= 9;
denominator += 2;
pi += b;
} while (b > DBL_EPSILON / 2);
b = numerator / denominator;
pi += b;
return 4 * pi;
}

/* END pi.c */

--
pete
Nov 15 '05 #13
pete wrote:

pete wrote:

pete wrote:

Keith Thompson wrote:
>
> "Michel Rouzic" <Mi********@yahoo.fr> writes:
> > Michael Mair wrote:
> >> Michel Rouzic wrote:
> [...]
> >> > What's wrong with the way I do my pi?
> >>
> >> 1) The C standard makes no guarantee whatsoever about the
> >> precision of the math functions from the library. So, "your"
> >> pi could be way off.
> >> 2) Your pi has to be recomputed at every function call.
> >
> > oh, ok, well, I guess it's gonna be better
> > if I stop doing that and put
> > #define pi 3.1415926535897932 instead
>
> That's 17 significant digits; long double often has more precision
> than that.
>
> Using 40 decimal digits will cover
> anything with a mantissa up to 128
> bits, which is enough for any hardware I've ever used. Use an 'L'
> suffix to make sure you get the full precision.
>
> It's very likely that you can get away with far less precision,
> depending on the application, but using more digits than you'll ever
> need isn't a burden, and it means one less thing to worry about if
> your program misbehaves.

I got all the precision of a double right here:

/* BEGIN pi.c */


Subsequent testing indicates maybe I don't
got all the precision of a double.


Now, as far as my system is concerned, testing indicates
that I *do* got all the precision of a double.

/* BEGIN pi.c output */

PI = 3.141592653589793238462643383279502884197169399375 1;
Pi = pi();

PI is 3.141593
Pi is 3.141593
PI - 4 * atan(1) is 0.000000e+000
Pi - 4 * atan(1) is 0.000000e+000
Pi - PI is 0.000000e+000

/* END pi.c output */

/* BEGIN pi.c */

#include <stdio.h>
#include <float.h>
#include <math.h>

double pi(void);

int main(void)
{
double Pi, PI;

PI = 3.141592653589793238462643383279502884197169399375 1;
Pi = pi();

puts("/* BEGIN pi.c output */\n");
puts("PI = 3.1415926535897932384626"
"433832795028841971693993751;");
puts("Pi = pi();\n");
printf("PI is %f\n", PI);
printf("Pi is %f\n", Pi);
printf("PI - 4 * atan(1) is %e\n", PI - 4 * atan(1));
printf("Pi - 4 * atan(1) is %e\n", Pi - 4 * atan(1));
printf("Pi - PI is %e\n", Pi - PI);
puts("\n/* END pi.c output */");
return 0;
}

double pi(void)
{
double pi, b, numerator;
unsigned denominator;

pi = 0;
numerator = 3;
denominator = 1;
do {
numerator /= 9;
b = numerator / denominator;
numerator /= 9;
denominator += 2;
b -= numerator / denominator;
denominator += 2;
pi += b;
} while (b > DBL_EPSILON / 2);
numerator = 2;
denominator = 1;
do {
numerator /= 4;
b = numerator / denominator;
numerator /= 4;
denominator += 2;
b -= numerator / denominator;
denominator += 2;
pi += b;
} while (b > DBL_EPSILON / 4);
return 4 * pi;
}

/* END pi.c */
--
pete
Nov 15 '05 #14
pete wrote:

pete wrote:

pete wrote:

pete wrote:
>
> Keith Thompson wrote:
> >
> > "Michel Rouzic" <Mi********@yahoo.fr> writes:
> > > Michael Mair wrote:
> > >> Michel Rouzic wrote:
> > [...]
> > >> > What's wrong with the way I do my pi?
> > >>
> > >> 1) The C standard makes no guarantee whatsoever about the
> > >> precision of the math functions from the library. So, "your"
> > >> pi could be way off.
> > >> 2) Your pi has to be recomputed at every function call.
> > >
> > > oh, ok, well, I guess it's gonna be better
> > > if I stop doing that and put
> > > #define pi 3.1415926535897932 instead
> >
> > That's 17 significant digits;
> > long double often has more precision
> > than that.
> >
> > Using 40 decimal digits will cover
> > anything with a mantissa up to 128
> > bits, which is enough for any hardware I've ever used.
> > Use an 'L'
> > suffix to make sure you get the full precision.
> >
> > It's very likely that you can
> > get away with far less precision,
> > depending on the application,
> > but using more digits than you'll ever
> > need isn't a burden,
> > and it means one less thing to worry about if
> > your program misbehaves.
>
> I got all the precision of a double right here:
>
> /* BEGIN pi.c */

Subsequent testing indicates maybe I don't
got all the precision of a double.

Now, as far as my system is concerned, testing indicates
that I *do* got all the precision of a double.


And even though it seems to work on my system,
these next two lines should be switched
because of the value of the pi variable
when the loops terminate.
} while (b > DBL_EPSILON / 2); } while (b > DBL_EPSILON / 4);


--
pete
Nov 15 '05 #15

Michael Mair wrote:
Michel Rouzic wrote:
Keith Thompson wrote:
"Michel Rouzic" <Mi********@yahoo.fr> writes:

Michael Mair wrote:

>Michel Rouzic wrote:

[...]

>>What's wrong with the way I do my pi?
>
>1) The C standard makes no guarantee whatsoever about the
>precision of the math functions from the library. So, "your"
>pi could be way off.
>2) Your pi has to be recomputed at every function call.

oh, ok, well, I guess it's gonna be better if I stop doing that and put
#define pi 3.1415926535897932 instead

That's 17 significant digits; long double often has more precision
than that.


I'm only using double precision floats, and since I heard it could take
between 15 and 17 signifiant digits...


This may be the case for your implementation
(platform/OS/compiler/standard library combination) but
the C standard does not guarantee it. Whether or not double
and long double are of different precision also is unspecified.

Probably you have IEEE-like doubles, so this is moot but more
digits do not hurt in _any_ respect. Whether or not it is a
good idea to multiply with a long double constant may depend
on what you want to do and your implementation.


I guess I could make it longer. Have an idea on how long is the longest
mantissa in the different existing doubles? Anyways, if I'm using pi,
it's for DSP, and since an imprecision of 10^-16 represents -160 dB,
it's way good enough. But I guess I could make it long enough for the
largest mantissa existing, doesn't cost anything but a few bytes in my
code...

Nov 15 '05 #16

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

28
by: Paul Rubin | last post by:
http://www.nightsong.com/phr/python/sharandom.c This is intended to be less predicable/have fewer correlations than the default Mersenne Twister or Wichmann-Hill generators. Comments are...
5
by: Luke | last post by:
Hello, I am the administrator for http://www.nickberg.org - Nick is the man who was recently beheaded in Iraq. He was a very ingenious man - once for my birthday had gave me a small box...
4
by: Dimos | last post by:
Hello All, I need some help with random number generation. What I need exactly is: To create a few thousand numbers, decimal and integers, between 5 and 90, and then to export them as a...
15
by: Papajo | last post by:
Hi, This script will write a random number into a document write tag, I've been trying to get it to write into a input form box outside the javascript, any help is appreciated. Thanks Joe ...
104
by: fieldfallow | last post by:
Hello all, Is there a function in the standard C library which returns a prime number which is also pseudo-random? Assuming there isn't, as it appears from the docs that I have, is there a...
4
by: eltower | last post by:
Hey all, I'm trying to write a program in Python for learning purposes which is meant to: Generate a random number from 0 to 6 Insert this random number to the end of a list unless the number...
2
by: vusak | last post by:
in the header file #include <cstdlib> #include <ctime> using namespace std; #define RAND_LIMIT 1000 class randomNormalized { public:
22
by: Ivan Voras | last post by:
Hi, I have a list of items, and need to choose several elements from it, "almost random". The catch is that the elements from the beginning should have more chance of being selected than those...
3
by: Manuel Ebert | last post by:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Dear list, who's got aesthetic advice for the following problem? I've got some joint probabilities of two distinct events Pr(X=x, Y=y), stored...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.