Storing very small numbers - but only order of magnitude
I want to store a very small number - too small for even a long double. However, I don't need the number to be stored very precisely - in fact, all I really need is the order of magnitude of the number. For example, the number 5.205849034425 X 10^-381 can just be stored as an integer of -381 for my purposes. I don't really care about the precision of the 5.205849034425 part.
The reason I get this very small number, is because I am multiplying together thousands of numbers, all of which are around 0.0001 in value. So, one way to do this would be to store all these individual values as simply their order of magnitude (e.g. -4) and then instead of multiplying the numbers, I would just add up their orders of magnitude. However, I am wondering whether there is a way in C++ to do this without me having to change the way I store my data - I still would like to keep the original values if possible.
Re: Storing very small numbers - but only order of magnitude
if your end number doesn't fit into a double.... and 10^-381 doesn't (double can be 10^-307 at best)...
Then you'll need a special numbers class just to handle all the multiplications reliably. Whatever this class is and how it works... how you extract the exponent from that class will be dependant on what class you're using.
It could be a double-like type that allows for larger exponents and/or larger mantisa's, or it could be a class that "more or less" behaves in the way you want for your results.
if you want to know how to extract the exponent from a double: use frexp() from math.h
If you aren't interested at all in the mantissa and don't care about any effect of the mantissa on the exponent, then you can extract all the exponents and just add them up.
note that 0.5 * 0.5 = 0.25 = 5*10^-1 * 5*10^-1 = 2.5*10-1
so adding the exponents would have given you -2 when the end result is -1 because of the scaling effect of mantissa's.
if you need correct mantissa and exponent evaluation.
then after each multiplication, scale up by factors of 10 the resulting double, and accumulate the exponents.
0.5 * 0.5 = 0.25 = 2.5*10^-1
extract the exponent, and accumulate (exponent_accumulation is now -1), scale the double up to be noted in *10^0 (= multiply by 10^-extracted_exponent = *10)
we now have result=2.5*10^0 and exponent_accumulation=-1
multiply by 0.001 = 2.5*10-3;
extract exponent (-3) and accumulate (exponent_accumulation is now -4), scale the double up to be noted in *10^0 (= multiply by 10^-extracted_exponent = *1000)
we now have result=2.5*10^0 and exponent_accumulation=-4
multiply by 0.033 = 8.25*10-2
extract exponent (-2) and accumulate (exponent_accumulation is now -6), scale the double up to be noted in *10^0 (= multiply by 10^-extracted_exponent = *100)
we now have result=8.25*10^0 and exponent_accumulation=-6
you'll still have an exponent that ends up being "off" by a bit for very large number of multiplications because you're loosing some precision in the mantissa each time, and you're introducing errors each time you're rescaling the double. Whether this is or isn't an issue for your problem, I can't tell, it depends how accurate you need things to be. It'll need some error analysis if you need an actual grip on how much of an error you are accumulating in each step.
It will be "close", but it can't ever be "accurate", floating point and accurate don't go hand in hand.