How would I find 100! accurately? [Programming challenge] [duplicate] - c++

This question already has answers here:
Calculate the factorial of an arbitrarily large number, showing all the digits
(11 answers)
Closed 9 years ago.
I tried using double but it would give me scientific answers like 3.2e+12. I need proper answer. How would I do that??
My code so far:
int n, x;
double fact;
cin>>n;
while(n--)
{
fact=1;
cin>>x;
for(;x>1;x--)
fact*=x;
cout<<fact<<endl;
}

First things first, using floating point formats such as double and float will always introduce rounding error, if you want to reduce the error with large numbers, use long or long long, however these will not be able to represent values as large as double or long double (note that the behavior and support for long long and long double varies between compilers). You might want to look into BigNums like bigint or bigdouble, though you will sacrifice preformace.
That said, this issue might also be one of setting the formatting: the number is large enough that it is outputted in scientific notation, to change this you can use
cout<<std::fixed;
possible duplicate of How to make C++ cout not use scientific notation

double is a fixed-size type, typically 64 bits, with 53 bits of precision; so it can't accurately represent any integer with more than about 16 digits. The largest standard integer type typically has 64 bits, and can represent integers up to about 19 digits. 100! is much larger than that, so can't be represented accurately by any built-in type.
You'll need a large integer type, representing a number as an array of smaller numbers. There's no standard type; you could use a library like Boost.Multiprecision or GMP or, since this is a programming challenge, implement it yourself. To calculate factorials, you'll need to implement multiplication; the easiest way to do that is with the "long multiplication" algorithm you learnt in school.

There's no data type can store such a big number as (100!) so far.
You should finish something like a BigIntenger class to calculate 100!;
And usually,such big number can be stored by strings.

Related

How to handle number with large exponent in c/c++? [duplicate]

This question already has answers here:
Is there a C++ equivalent to Java's BigDecimal?
(9 answers)
Closed 7 years ago.
I found myself with the need to compute the exponential of a large number, e. g.exp(709). Such a number would be represented, in floating point precision, as 8.2184074615549724e+307.
It seems that numbers with exponents larger than that would be simply translated into Inf, which creates problems in my code. I can only guess that things can be fixed using more bits to represent the exponent, but I am not aware of a pragmatical way to proceed.
Here is a code snippet:
double expon = exp(500); /*here I also tried `long double`, with no effect */
printf("%e\n", expon ); /*gives INF*/
double Wa = LambertW<0>( expon); /*gives error, as it can't handle inf*/
Is there a way to compute this?
This problem has been debated in general, but I did not find an useful answer. Also, it seems that GCC supports multiple-precision floating-point arithmetics since version 4.3. How does it help?
Edit: The suggested possible-duplicate questions turned out irrelevant because as I need huge decimals, not exact decimals. This is not a duplicate.
You should be able to perform your computation with adequate precision using long double arithmetic:
The maximum value for 80 bit long double is 1.18×10^4932, much larger than e^709.
In order for the computation to be performed as long double, your must use expl instead if exp:
long double expon = expl(500);
printf("%Le\n", expon);
The LambertW function will handle the long double if it is properly overloaded for this type, otherwise expon will be converted to double and produce inf and the computation will fail as you mentioned.
I don't know which implementation of Lambert W function you use, Darko Veberic's does not support long double arguments, but it might be feasible to extend the implementation to type long double as it is available in source form: https://github.com/DarkoVeberic/LambertW . You might want to contact him directly.
Another approach is to consider that exp(709) is just too close to the maximum precision of the double type, 10^308. If you can alter your computation using just smaller exponents and a different formula, the computation might be done with regular double types.

Precise std::string to float conversion [duplicate]

This question already has answers here:
Why are floating point numbers inaccurate?
(5 answers)
Closed 7 years ago.
In my project I have to read some numeric data form an xml file ,use it ,and save it on disk in an another directory.
Skipping the file paring it comes to the problem of std::string to float conversion:
std::string sFloatNumber;
float fNumber = std::atof(sFloatNumber);
Which works fine but I noticed small deviations between value written in std::string and the one recieved after conversion to float (about ~0.0001).
Deviation is small but after number of such operations can accumulate to a big inacurracy later on.
So I ask if there is some conversion between std::string and float that has 1:1 accuracy?
You can't really can't make the conversion more precise than what you'd achieve by using the inbuilt operators for this. The reason is that floats can't represent all numbers. What they can represent is the number closest to the one you input, and I guess that is what they are showing. So there is no way possible in which you can convert a string exactly into a float.
If you want more accuracy, I suggest you use double. However, that also has a limit on the accuracy, but much better than float nonetheless. The reason for this is that double uses 64 bits to represent a number, whereas a float uses 32 bits. But their method of storing a number is similar, and so the same restrictions apply.

Is it possble to combine number of float values into one float value and extract the values when needed?

Am working on an algorithm for an iPhone app, where the data i need to keep in memory is exceeding the limit, so is it possible to represent number of float numbers as one float value and retrieve those value when i need.
For instance:
float array[4];
array[0]=0.12324;
array[1]=0.56732;
array[2]=0.86555;
array[3]=0.34545;
float combinedvalue=?
Not in general, no. You can't store 4N bits of information in only N bits.
If there's some patten in your numbers, then you might find a scheme. For example, if all your numbers are of similar value, you could potentially store only the differences between the numbers in lower precision.
However, this kind of thing is difficult, and limited.
If those numbers are exactly 5 digits each, you can treat them as ints by multiplying with 100000. Then you'll need 17 bits for each number, 68 bits in total, which (with some bit-shifting) takes up 9 bytes. Does that help, 9 bytes instead of 16?
Please note that the implementation of your algorithm will also take up memory!
What you are requiring could be accomplished in several different ways.
For instance, in c++ you generally have single precision floats (4 bytes) as the smallest precision available, though I wouldn't be surprised if there are other packages that handle smaller precision floating point values.
Therefore, if you are using double precision floating point values and can get by with less precision then you can switch to a smaller precision.
Now, depending on your range of values you want to store, you might be able to use a fixed-point representation as well, but you will need to be familiar with the nuances of bit shifting and masking, etc. But, another added benefit of this approach is that it could make your program run faster since fixed-point (integer) arithmetic is much faster than floating-point arithmetic.
The choice of options depends on your data you need to store and how comfortable you are with lower level binary arithmetic.

Long double does not print as the constant I initialized it with [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Floating point inaccuracy examples
Im having a problem... When i compile the src, the variable showed isn't the same that i initialized, see it:
#include <iostream>
using namespace std;
int main()
{
long double mynum = 4.7;
cout.setf(ios::fixed,ios::floatfield);
cout.precision( 20 );
cout << mynum << endl;
}
And then:
[fpointbin#fedora ~]$ ./a.out
4.70000000000000017764
How to fix it? I want to "cout" shows 4.700000...
Your variable is long double, but the default precision of the literal 4.7 is only double. Since you're printing it as long double, the interpretation chooses to print it with enough significant digits to distinguish it from neighbouring long double values, even though those neighbouring values are not possible doubles.
The internal representation of doubles does not allow for an 'exact' representation of 4.7. The 'closest' is 4.70000000000000017764. In reality there is no need to look at a precision of 20 when you have 64 bit doubles. The maximum effective precision is about 15. Try using 12 or so,
cout.precision( 12 );
and you should get what you want to see.
Most platforms, including yours, can only represent those floating point numbers exactly which have a short, finite binary expansion, i.e. which are finite sums of powers of two. 4.7 is not such a number, so it cannot be represented precisely on your platform, and if you demand excessive precision (20 is too much as your mantissa has 64 bits, and log_10(64) is 19.27), then you will inevitably face small errors.
(However, as #Henning says, you are already losing precision when assigning from a (non-long) double; you should write your literal constant as a long double: 4.7L. Then you should only see an error in the 20th digit.)
floats and doubles are binary floating-point types, i.e. they store a mantissa and an exponent in base 2.
This means that any decimal number that cannot be represented exactly into the finite digits of the mantissa will be approximated; the problem you showed comes from this: 4.7 cannot be represented exactly into the mantissa of a double (the literal 4.7 is of type double, kudos #Henning Makholm for spotting it), so the nearest approximation is used.
To better visualize the problem: in base 3, 2/3 is a number with a finite representation (i.e. 0.23), while in base 10 it is a periodic number (0,6666666...); if you have only a finite space for digits, you'll have to perform an approximation, that will be 0,66666667. That's exactly the same thing here, with the source base being 10 and the "target" base being 2.
If there's a special need to avoid this kind of approximations (e.g. when dealing with decimal amounts of money) special decimal types can be used, that store mantissa and exponent in base 10 (C++ do not provide such type of its own, but there are many decimal classes available on the Net); still, for "normal"/scientific calculations binary FP types are used, because they are much faster and more space-efficient.
Certain numbers cannot be represented in base two. Apparently, 4.7 is one of them. What you're seeing is the closest representable number to 4.7.
There's nothing you can do about this, other than setting the precision to a lower number.

C++: How to Convert From Float to String Without Rounding, Truncation or Padding? [duplicate]

This question already has answers here:
Why do I see a double variable initialized to some value like 21.4 as 21.399999618530273?
(14 answers)
Closed 6 years ago.
I am facing a problem and unable to resolve it. Need help from gurus. Here is sample code:-
float f=0.01f;
printf("%f",f);
if we check value in variable during debugging f contains '0.0099999998' value and output of printf is 0.010000.
a. Is there any way that we may force the compiler to assign same values to variable of float type?
b. I want to convert float to string/character array. How is it possible that only and only exactly same value be converted to string/character array. I want to make sure that no zeros are padded, no unwanted values are padded, no changes in digits as in above example.
It is impossible to accurately represent a base 10 decimal number using base 2 values, except for a very small number of values (such as 0.25). To get what you need, you have to switch from the float/double built-in types to some kind of decimal number package.
You could use boost::lexical_cast in this way:
float blah = 0.01;
string w = boost::lexical_cast<string>( blah );
The variable w will contain the text value 0.00999999978. But I can't see when you really need it.
It is preferred to use boost::format to accurately format a float as an string. The following code shows how to do it:
float blah = 0.01;
string w = str( boost::format("%d") % blah ); // w contains exactly "0.01" now
Have a look at this C++ reference. Specifically the section on precision:
float blah = 0.01;
printf ("%.2f\n", blah);
There are uncountably many real numbers.
There are only a finite number of values which the data types float, double, and long double can take.
That is, there will be uncountably many real numbers that cannot be represented exactly using those data types.
The reason that your debugger is giving you a different value is well explained in Mark Ransom's post.
Regarding printing a float without roundup, truncation and with fuller precision, you are missing the precision specifier - default precision for printf is typically 6 fractional digits.
try the following to get a precision of 10 digits:
float amount = 0.0099999998;
printf("%.10f", amount);
As a side note, a more C++ way (vs. C-style) to do things is with cout:
float amount = 0.0099999998;
cout.precision(10);
cout << amount << endl;
For (b), you could do
std::ostringstream os;
os << f;
std::string s = os.str();
In truth using the floating point processor or co-processor or section of the chip itself (most are now intergrated into the CPU), will never result in accurate mathematical results, but they do give a fairly rough accuracy, for more accurate results, you could consider defining a class "DecimalString", which uses nybbles as decimal characters and symbols... and attempt to mimic base 10 mathematics using strings... in that case, depending on how long you want to make the strings, you could even do away with the exponent part altogether a string 256 can represent 1x10^-254 upto 1^+255 in straight decimal using actual ASCII, shorter if you want a sign, but this may prove significantly slower. You could speed this by reversing the digit order, so from left to right they read
units,tens,hundreds,thousands....
Simple example
eg. "0021" becomes 1200
This would need "shifting" left and right to make the decimal points line up before routines as well, the best bet is to start with the ADD and SUB functions, as you will then build on them in the MUL and DIV functions. If you are on a large machine, you could make them theoretically as long as your heart desired!
Equally, you could use the stdlib.h, in there are the sprintf, ecvt and fcvt functions (or at least, there should be!).
int sprintf(char* dst,const char* fmt,...);
char *ecvt(double value, int ndig, int *dec, int *sign);
char *fcvt(double value, int ndig, int *dec, int *sign);
sprintf returns the number of characters it wrote to the string, for example
float f=12.00;
char buffer[32];
sprintf(buffer,"%4.2f",f) // will return 5, if it is an error it will return -1
ecvt and fcvt return characters to static char* locations containing the null terminated decimal representations of the numbers, with no decimal point, most significant number first, the offset of the decimal point is stored in dec, the sign in "sign" (1=-,0=+) ndig is the number of significant digits to store. If dec<0 then you have to pad with -dec zeros pror to the decimal point. I fyou are unsure, and you are not working on a Windows7 system (which will not run old DOS3 programs sometimes) look for TurboC version 2 for Dos 3, there are still one or two downloads available, it's a relatively small program from Borland which is a small Dos C/C++ edito/compiler and even comes with TASM, the 16 bit machine code 386/486 compile, it is covered in the help files as are many other useful nuggets of information.
All three routines are in "stdlib.h", or should be, though I have found that on VisualStudio2010 they are anything but standard, often overloaded with function dealing with WORD sized characters and asking you to use its own specific functions instead... "so much for standard library," I mutter to myself almost each and every time, "Maybe they out to get a better dictionary!"
You would need to consult your platform standards to determine how to best determine the correct format, you would need to display it as a*b^C, where 'a' is the integral component that holds the sign, 'b' is implementation defined (Likely fixed by a standard), and 'C' is the exponent used for that number.
Alternatively, you could just display it in hex, it'd mean nothing to a human, though, and it would still be binary for all practical purposes. (And just as portable!)
To answer your second question:
it IS possible to exactly and unambiguously represent floats as strings. However, this requires a hexadecimal representation. For instance, 1/16 = 0.1 and 10/16 is 0.A.
With hex floats, you can define a canonical representation. I'd personally use a fixed number of digits representing the underlying number of bits, but you could also decide to strip trailing zeroes. There's no confusion possible on which trailing digits are zero.
Since the representation is exact, the conversions are reversible: f==hexstring2float(float2hexstring(f))