• Advertisement
Sign in to follow this  

Working with big, big numbers

This topic is 4620 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm working on a school project, doing a simulation of planetary gravity in c++ as a physics project. I have the whole thing figured out, except for this problem: the numbers involved in the equation that calculates force due to gravity range from very tiny (6.67 * 10^-11) to HUGE (mass of the sun is 1.991 * 10^30). I obviously can't use a double, because the mantissa keeps it from having the neccesary accuracy. Therefore, I was wondering if anyone knows of a library or something with huge numbers that have perfect accuracy, or, better yet, tips on making my own. The only idea I've had for making it on my own is to take like 4 unsigned longs, and then combine the bits somehow into one huge number. Unfortunately, I don't know how this works. If someone knows of a better way, please let me know. Until then, or someone posts a library I can use, its GOOGLE TIME!

Share this post


Link to post
Share on other sites
Advertisement
Poking around the internet I dug up something Promising:

http://sourceforge.net/projects/libmp/

MP stands for 'Multiprecision'.

"This is a library of classes and functions to be used to abstract arbitrarily large integer and floating-point numbers in C++. All standard operators are overloaded so the user is able to substitute "mpi" for "int" and "mpf" for "double" to use."

Sounds good to me. Hope it helps.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
How does the mantissa keep it from having the required accuracy? You can get up to 19 significant digits with long doubles, probably greater than the constants you'll be using. I say this having written some physics simulations myself.

Share this post


Link to post
Share on other sites
Based upon what he said, he needs at least 41 digits as he is spanning at least 41 orders of magnitude

Share this post


Link to post
Share on other sites
Quote:
Original post by Punty50
Based upon what he said, he needs at least 41 digits as he is spanning at least 41 orders of magnitude
I doubt any of the constants have 41 significant digits, and you don't need to store but a few non-significant digits because most of them are meaningless anyways.

Share this post


Link to post
Share on other sites
Quote:
I_Smell_Tuna I think using an array of longs would be a good way to go.


Nope. Think about it - I assume you are talking about adding them together. A number in a programming language is actually a number in base 2 - for a char (1 byte, 8 bits, max deci value of 255) the number 7 would be represented as:

0000 0111

Now, for simplicity, you could add a bunch of longs together. This would, however, be terribly inefficient. Consider an array of chars (I don't want to write like four 32-digit binaries!)

By your suggested method, you could have the number 256 (one greater than the max value of a char) by doing this:

1111 1111 + 0000 0001

By this method, the two char method has a max value of 510.

However, you could accomplish the same thing using a short int (16 bits).

0000 0001 0000 0001

Also, this would have a maximum value of 2^16, much, much greater than 510!

So what I'm looking for is a way to combine the bits of several long integers, rather than adding them together.

Quote:

Punty50 Based upon what he said, he needs at least 41 digits as he is spanning at least 41 orders of magnitude


Exactly.

And finally, to the two who posted the libs, thanks. I'll check them out. And, Tuna: no harm intended :P

Share this post


Link to post
Share on other sites
In general, the exponent codes most of the magnitude, not the mantissa. The one exception is with denormal floats.

Share this post


Link to post
Share on other sites
Quote:
Original post by silverphyre673
the numbers involved in the equation that calculates force due to gravity range from very tiny (6.67 * 10^-11) to HUGE (mass of the sun is 1.991 * 10^30). I obviously can't use a double, because the mantissa keeps it from having the neccesary accuracy.


Are you sure? I ran a simple test:

double d1 = 6.67E-11;
double d2 = 1.991E30;
Console.WriteLine(d1 * d2);

Which produced 1.327997E+20, which is about right. You might want to prototype some of the equations/magnitudes involved to see if your statement is really true.

Share this post


Link to post
Share on other sites
A big number library is probably implemented as a string of 32-bit digits anyway. An array of longs would work, so long as you knew how to work with them. I implemented a big number library using straight std::strings, and encoded my numbers in base 256. It worked great, except that I was never able to find an efficient method for changing the numbers to decimal for display.

Share this post


Link to post
Share on other sites
I just recently wrote an arbitrary arithmetic library for a contest. I stored the numbers as a std::vector of ints, and it worked great. No speed problems. I was able to calculate divisions with 100 thousand digits of precision, though it took literally about 15 minutes to calculate them all!!!

If you need absolutely huge numbers, I recommend storing them like I did and implementing the arithmetical operations by emulating the hand-written equivalents.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Having that much accuracy is rather silly. Say you take something like the mass of the sun, which we'll say has 10 significant digits and 20 insignificant digits, and you add the mass of something very small (as given) with 10 significant digits (note if you multiply, the only significant digits remaining are whichever is the lowest number, so we'd be down to 10). So, now you have a number with 10 significant digits, followed by 20 insignificant digits, followed by 10 more. Obviously those last 10, are in fact, insignificant. This is how significant digits work. Unless you have values which are significant to those 40 digits, don't bother.

Share this post


Link to post
Share on other sites
nilk: Did you do it by the method suggested by Tuna, or my the method suggested by me? I don't need 100 thousand digits of precision, just a mere 50 :P

Right now I'm looking into <bitset>, which basically allows you to make an array of an arbitrary number of bits, and has methods that make setting, clearing and checking bits much easier (using operator [] rather than the arcase >>, <<, ~, etc). I'll let you know. Knowing me, I will come out of this with a whole big class that I will never use again.

Share this post


Link to post
Share on other sites
Quote:
Original post by silverphyre673
nilk: Did you do it by the method suggested by Tuna, or my the method suggested by me? I don't need 100 thousand digits of precision, just a mere 50 :P

Right now I'm looking into <bitset>, which basically allows you to make an array of an arbitrary number of bits, and has methods that make setting, clearing and checking bits much easier (using operator [] rather than the arcase >>, <<, ~, etc). I'll let you know. Knowing me, I will come out of this with a whole big class that I will never use again.


I just took the easy way out and stored an array of integers. It really wasn't that slow at all, as long as I didn't use too huge of numbers, or require 100 thousand digits of precision :)

I handled numbers with a decimal by splitting the digits into two arrays: pre-decimal and post-decimal. This made it easy to write a function to print to the screen, and arithmetic operations were much simpler this way (especially division, which was the hard one [smile]).

Share this post


Link to post
Share on other sites
Quote:
I obviously can't use a double, because the mantissa keeps it from having the neccesary accuracy.


That's not very obvious to me. The general rule is that, as long as you only multiply and divide, then doubles are just fine. If you add or subtract, then the numbers need to be within, say, 10e5 from each other (more like 10e2 for floats) to retain useful precision.

Gravitation is just multiplication/division. The only addition is the summing up of forces for each body at the end, and there it doesn't matter much if a really large force drowns out the effect of a really small force.

Share this post


Link to post
Share on other sites
Actually, thats true hplus. Just thought about that :)

I did get GMP, and even found a devpak of it, which was nice. I don't think I'll use it though, because of the whole multiplication/division vs. add/subtract thing. Although I might need it later. Anyways, thanks for your help, suggestions and comments guys. Somehow, we arrived at a solution.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement