Mmmmmmmm, PI...
Ok, the representation of double and long double are both 8 byte. But the size of the long double datatype is 10 byte. Don''t ask me how, but it reads so in the msdn.
quote: The link is somewhat dead. I say somewhat, as your server admits that the file exists, it just refuses to grant access to .cpp files.
S***. Well, I always knew Freeservers sucked... Try this and look for pi.cpp somewhere up there near the top. It''s not there right now, but I''ll have it up by tomorrow.
Excuse me whilst I conquer Earth...
Commander M
(a.k.a. Crazy Yank)
http://commanderm.8m.com
CmndrM@gdnmail.net
the long double IEEE format of floating point numbers is 10 bytes, or 80 bits.
The intel x87 floating point coprocessors use 80 bits internally for all calculations. If you pass in a 32 bit float, the fpu converts it to 80 bits, performs operations on it, then converts it back to 32 bits for maximum calculating accuracy. MSVC only has the ability to print 32 and 64 bit floats, and i suppose they figured that since the fpu uses 80 bits anyways, its not really required.
Actually, i have no idea what they were thinking. All I know is that MSVC interprets LONG DOUBLE''s as regular DOUBLE''s.
===============================================
If there is a witness to my little life,
To my tiny throes and struggles,
He sees a fool;
And it is not fine for gods to menace fools.
The intel x87 floating point coprocessors use 80 bits internally for all calculations. If you pass in a 32 bit float, the fpu converts it to 80 bits, performs operations on it, then converts it back to 32 bits for maximum calculating accuracy. MSVC only has the ability to print 32 and 64 bit floats, and i suppose they figured that since the fpu uses 80 bits anyways, its not really required.
Actually, i have no idea what they were thinking. All I know is that MSVC interprets LONG DOUBLE''s as regular DOUBLE''s.
===============================================
If there is a witness to my little life,
To my tiny throes and struggles,
He sees a fool;
And it is not fine for gods to menace fools.
This is my signature. There are many like it, but this one is mine. My signature is my best friend. It is my life. I must master it as I must master my life. My signature, without me, is useless. Without my signature, I am useless.
Many Unix compilers (at least gcc and egcs) also have a long long double type if I remember correctly (yeah, 2 "long"s). But, as an alternative, I think you should make your own smallnum class. An efficient bignum class uses carry flags and asm to get a pure binary representation of large numbers. You could do the same thing, but inverted, and use a fixed-point representation for it.
Hmm... sound like fun. Maybe I should try this myself!
David
Hmm... sound like fun. Maybe I should try this myself!
David
What you really want for this (especially if you want to compute pi to a hundred places or more) is a ''bignum'' data type. You should be able to search the web on that and come up with a number of libraries, but it''s pretty easy to build yourself, and well worth the while. Like someone suggested, you can do it as basically BCD; a bignum is just an array of digits, 0..10 (or even 0..100 if you prefer, since you can stuff two digits into a byte):
typedef BYTE BigNum[NUM_DIGITS];
Once you''ve got this, you can just mimic all of the usual pen-and-paper algorithms in base 100 arithmetic. For instance, addition would look something like this:
Note that you have to do actual divisions and such for this; if you work base-64 (or even base-256, etc) then you can avoid them, but if you do that then you also have to come up with a means of converting your result to decimal for output. Multiplication isn''t too much trickier than addition (though note that your product of two digits won''t fit into a byte, in that case, and you have to change the structure above a bit), but division can be a little trickier and takes some playing around. Don Knuth''s _Art Of Computer Programming_ covers most of what you would want to know about bignums in Chapter 4, I think (in vol. 2); check it out, it''s a series that should be on every programmer''s bookshelf.
Also, the fact that it takes as long as Kazan said to compute 10 digits of pi is just because the 1-1/3+1/5-1/7... method is horribly inefficient -- but that''s a topic for another post...
typedef BYTE BigNum[NUM_DIGITS];
Once you''ve got this, you can just mimic all of the usual pen-and-paper algorithms in base 100 arithmetic. For instance, addition would look something like this:
// c = a+bAdd(BigNum a, b, c) { BYTE carry=0; BYTE sum; int digitLoop; for (digitLoop = 0; digitLoop < NUM_DIGITS; digitLoop++) { sum = a[digitLoop] + b[digitLoop] + carry; c[digitLoop] = sum % 100; carry = sum/100; } if (carry) { SignalOverflow(); }}
Note that you have to do actual divisions and such for this; if you work base-64 (or even base-256, etc) then you can avoid them, but if you do that then you also have to come up with a means of converting your result to decimal for output. Multiplication isn''t too much trickier than addition (though note that your product of two digits won''t fit into a byte, in that case, and you have to change the structure above a bit), but division can be a little trickier and takes some playing around. Don Knuth''s _Art Of Computer Programming_ covers most of what you would want to know about bignums in Chapter 4, I think (in vol. 2); check it out, it''s a series that should be on every programmer''s bookshelf.
Also, the fact that it takes as long as Kazan said to compute 10 digits of pi is just because the 1-1/3+1/5-1/7... method is horribly inefficient -- but that''s a topic for another post...
I don't know what formula you're using for pi, CmndrM, but it's worth knowing that there are much better ones than the one that Kazan was suggesting (pi/4 = 1-1/3+1/5-1/7+...)
The first classic formula is the Machin formula: pi/4 = 4*arctan(1/5) - arctan(1/239), where arctan(x) has a series expansion arctan(x) = sum(n=0..infinity) (-1)n xn/(2n+1). This is just an extension of the 1-1/3+1/5 series; that formula just says, if you look at it, that pi/4 = arctan(1). Notice the difference: the thousandth term of the first series is just 1/2001, which means an accuracy of just 3 decimal digits (.0005), whereas if you expand arctan(1/5) and arctan(1/239) each to a thousand terms your accuracy is approximately (1/5)1000 -- just about 700 digits.
There's another series, not quite as fast-convergent, but with terms that might be easier to compute: pi/2 = sum(2n(n!)2/(2n+1)!) -- here the nth term in the sum is just n/(2n+1) times the last. This time the accuracy is about 1/2n -- or about 300 digits after 1000 terms.
There are a lot of other even-more-accurate algorithms too, although most of them require that you can compute square roots of bignums, which can be pretty complicated. For more information, check out the Mathsoft page on pi here, or just go digging on Yahoo. Happy hunting!
Edited by - Shaterri on November 18, 2000 3:08:03 PM
The first classic formula is the Machin formula: pi/4 = 4*arctan(1/5) - arctan(1/239), where arctan(x) has a series expansion arctan(x) = sum(n=0..infinity) (-1)n xn/(2n+1). This is just an extension of the 1-1/3+1/5 series; that formula just says, if you look at it, that pi/4 = arctan(1). Notice the difference: the thousandth term of the first series is just 1/2001, which means an accuracy of just 3 decimal digits (.0005), whereas if you expand arctan(1/5) and arctan(1/239) each to a thousand terms your accuracy is approximately (1/5)1000 -- just about 700 digits.
There's another series, not quite as fast-convergent, but with terms that might be easier to compute: pi/2 = sum(2n(n!)2/(2n+1)!) -- here the nth term in the sum is just n/(2n+1) times the last. This time the accuracy is about 1/2n -- or about 300 digits after 1000 terms.
There are a lot of other even-more-accurate algorithms too, although most of them require that you can compute square roots of bignums, which can be pretty complicated. For more information, check out the Mathsoft page on pi here, or just go digging on Yahoo. Happy hunting!
Edited by - Shaterri on November 18, 2000 3:08:03 PM
This new information is helpful. I''ll check out this whole bignum thing soon and try it out soon...
As for the algorithm, that was my selection . I''ll probably look into some of the others later, but right now, I''d like to focus on getting greater accuracy in terms of digits I can use.
Anyway, I didn''t upload the file until just now, so take a look.
Excuse me whilst I conquer Earth...
Commander M
(a.k.a. Crazy Yank)
http://commanderm.8m.com
CmndrM@gdnmail.net
As for the algorithm, that was my selection . I''ll probably look into some of the others later, but right now, I''d like to focus on getting greater accuracy in terms of digits I can use.
Anyway, I didn''t upload the file until just now, so take a look.
Excuse me whilst I conquer Earth...
Commander M
(a.k.a. Crazy Yank)
http://commanderm.8m.com
CmndrM@gdnmail.net
Hey, I can''t seem to find much about this bignum thing. Any links that you know of?
Excuse me whilst I conquer Earth...
Commander M
(a.k.a. Crazy Yank)
http://commanderm.8m.com
CmndrM@gdnmail.net
Excuse me whilst I conquer Earth...
Commander M
(a.k.a. Crazy Yank)
http://commanderm.8m.com
CmndrM@gdnmail.net
Seeing this thread I got interested, and started making a big fixed number class. I except it to be ready in a few days. It turned out to be much harder than I first thought, mainly because c++ is quite limited, when writing low level code. So I had to use a lot of inline assembler. Another thing that made it harder was, that you decide what format the number is in when you make the variable. So I had to make sure differnet size bignumbers operate well togheter.
All I have left is to finish the division operator and make the assignmet version of all operators. Division uses the SRT algorithm, so currently it only works with unsigned numbers, but I guess I have to make a check and converting the numbers before I use the algorithm. I also need to preshift the numbers if the dividend is greater than the divisor.
All other operators +,-,*,=, << and >> seems to work quite fine. The shifts are arithmetic shifts.
Oh, I almost forget the compare operators, but they don''t seem to hard to implement using the - operator.
All I have left is to finish the division operator and make the assignmet version of all operators. Division uses the SRT algorithm, so currently it only works with unsigned numbers, but I guess I have to make a check and converting the numbers before I use the algorithm. I also need to preshift the numbers if the dividend is greater than the divisor.
All other operators +,-,*,=, << and >> seems to work quite fine. The shifts are arithmetic shifts.
Oh, I almost forget the compare operators, but they don''t seem to hard to implement using the - operator.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement