Modulus of a really really long number (fmod) - c++

I want to find the number of zeroes in a factorial using Cpp. The problem is when I use really big numbers.
#include <stdio.h>
#include <math.h>
long zeroesInFact(long n)
{
long double fact=1;
long double denominator=10.00;
long double zero=0.0000;
long z=0;
printf("Strating loop with n %ld\n",n);
for(int i=2;i<=n;i++)
{
fact=fact*i;
printf("Looping with fact %LF\n",fact);
}
printf("Fmod %lf %d\n",fmod(fact,denominator),(fmod(fact,denominator)==zero));
while(fmod(fact,denominator)==zero)
{
fact=fact/10;
z++;
}
printf("Number of zeroes is %ld\n",z);
return z;
}
int main()
{
long n;
long x;
scanf("%ld",&n);
for(int i=0;i<n;i++)
{
scanf("%ld",&x);
printf("Calling func\n");
zeroesInFact(x);
}
return 0;
}
I think the problem here is that
fmod(fact,denominator)
gives me the correct answer for factorial of 22 and denominator as 10.00 (which is 0.000).
But it gives me the wrong answer for factorial of 23 and denominator as 10.00

Consider this your first lesson in numeric precision. The types float, double, and long double store approximations, not exact values, which means they are typically unsuitable for this sort of calculation. Even when they have enough precision for correct answers, you're still usually better off using integer numeric types instead, like int64_t and uint64_t. Sometimes you even even have a 128-bit integer type available. (e.g. __int128 might be available with Microsoft Visual Studio)
Honestly, I think you were lucky to get the right answer for 18! through 22!.
If long double truly is quadruple precision on your platform, you should be able to compute up to 30!, I think. You made a mistake when you used fmod -- you meant to use fmodl.
Your second lesson in precision is that when you need a lot of it, your basic data types simply aren't good enough. While you can write your own data types, you're probably better off using a pre-existing solution. The Gnu Multiple Precision Arithmetic Library (GMP) is a good, and fast one you can use in C/C++.
Alternatively, you could switch languages -- e.g. pythons integer data type is arbitrary precision (but not as fast as GMP), so you wouldn't even have to do anything special. Java has the BigInteger class for doing such computations.
Your third lesson is precision is to find ways to do without. You don't actually need to compute 23! in its full glory to find the number of trailing zeroes. With care, you can organize your calculation to discard extra precision you don't need. Or, you can switch to an entirely different method of obtaining this number, such as what Rob was hinting at in his comment.

Related

Defining '999e999' value without using char type in C++

Is it possible to define 999e999 value without using the char type?
I've tried defining it even with unsigned long long, but the compiler keeps giving me constant too big error.
Thanks in advance.
Is it possible to define 999e999 value without using the char type?
No, that's not possible using intrinsic c++ data types. That's a way to big number that could be held in either a unsigned long long type in c++.
A long double type would enable you to use 10 based exponents as large as you want, for modern FPU architectures.
What can be achieved with your current CPU architecture can be explored using the std::numeric_limits facilities like this:
#include <iostream>
#include <limits>
int main() {
std::cout<< "max_exponent10: " << std::numeric_limits<long double>::max_exponent10 << std::endl;
}
Output:
max_exponent10: 4932
See the online demo
You have to use a 3rd party library (like GMP) or write your own algorithms to deal with big numbers like that.
In most (If not all) implementations, that constant is just too big to be represented as a unsigned long long or long double (Though some may just have it be floating point infinity).
You may instead be interested in std::numeric_limits<T>::infinity() (for float, double or long double) or std::numeric_limits<T>::max() instead.
I've tried defining it even with unsigned long long, but the compiler keeps giving me constant too big error.
Of course it does. A long long is typically 64 bits long, which gives you log(2^64) ≅ 19 decimal digits of precision. 999e999 ≅ (10^3)^1000, so is on the order of 3000 decimal digits long, or nearly 10,000 bits long. So 999e999 isn't just too big for a long long, it's too big by an enormous margin.
Is it possible to define 999e999 value without using the char type?
Sure. You could define an integer-like type based on an array of some sort of integers, like long long. You'd still need to write a set of operators to work with your new giant type, though. Also, most of the time when you're working with numbers that large, you don't need an exact representation, which is why floating point types like float and double are useful.

How to force pow(float, int) to return float

The overloaded function float pow(float base, int iexp ) was removed in C++11 and now pow returns a double. In my program, I am computing lots of these (in single precision) and I am interested in the most efficient way how to do it.
Is there some special function (in standard libraries or any other) with the above signature?
If not, is it better (in terms of performance in single precision) to explicitly cast result of pow into float before any other operations (which would cast everything else into double) or cast iexp into float and use overloaded function float pow(float base, float exp)?
EDIT: Why I need float and do not use double?
The primarily reason is RAM -- I need tens or hundreds of GB so this reduction is huge advantage. So I need from float to get float. And now I need the most efficient way to achieve that (less casts, use already optimize algorithms, etc).
You could easily write your own fpow using exponentiation by squaring.
float my_fpow(float base, unsigned exp)
{
float result = 1.f;
while (exp)
{
if (exp & 1)
result *= base;
exp >>= 1;
base *= base;
}
return result;
}
Boring part:
This algorithm gives the best accuracy, that can be archived with float type when |base| > 1
Proof:
Let we want to calculate pow(a, n) where a is base and n is exponent.
Let's define b1=a1, b2=a2, b3=a4, b4=a8,and so on.
Then an is a product over all such bi where ith bit is set in n.
So we have ordered set B={bk1,bk1,...,bkn} and for any j the bit kj is set in n.
The following obvious algorithm A can be used for rounding error minimization:
If B contains single element, then it is result
Pick two elements p and q from B with minimal modulo
Remove them from B
Calculate product s = p*q and put it to B
Go to the first step
Now, lets prove that elements in B could be just multiplied from left to right without loosing accuracy. It comes form the fact, that:
bj > b1*b2*...*bj-1
because bj=bj-1*bj-1=bj-1*bj-2*bj-2=...=bj-1*bj-2*...*b1*b1
Since, b1 = a1 = a and its modulo more than one then:
bj > b1*b2*...*bj-1
Hence we may conclude, that during multiplication from left to right the accumulator variable is less than any element from B.
Then, expression result *= base; (except the very first iteration, for sure) does multiplication of two minimal numbers from B, so the rounding error is minimal. So, the code employs algorithm A.
Another question that can only be honestly answered with "wrong question". Or at least: "Are you really willing to go there?". float theoretically needs ca. 80% less die space (for the same number of cycles) and so can be much cheaper for bulk processing. GPUs love float for this reason.
However, let's look at x86 (admittedly, you didn't say what architecture you're on, so I picked the most common). The price in die space has already been paid. You literally gain nothing by using float for calculations. Actually, you may even lose throughput because additional extensions from float to double are required, and additional rounding to intermediate float precision. In other words, you pay extra to have a less accurate result. This is typically something to avoid except maybe when you need maximum compatibility with some other program.
See Jens' comment as well. These options give the compiler permission to disregard some language rules to achieve higher performance. Needless to say this can sometimes backfire.
There are two scenarios where float might be more efficient, on x86:
GPU (including GPGPU), in fact many GPUs don't even support double and if they do, it's usually much slower. Yet, you will only notice when doing very many calculations of this sort.
CPU SIMD aka vectorization
You'd know if you did GPGPU. Explicit vectorization by using compiler intrinsics is also a choice – one you could make, for sure, but this requires quite a cost-benefit analysis. Possibly your compiler is able to auto-vectorize some loops, but this is usually limited to "obvious" applications, such as where you multiply each number in a vector<float> by another float, and this case is not so obvious IMO. Even if you pow each number in such a vector by the same int, the compiler may not be smart enough to vectorize this effectively, especially if pow resides in another translation unit, and without effective link time code generation.
If you are not ready to consider changing the whole structure of your program to allow effective use of SIMD (including GPGPU), and you're not on an architecture where float is indeed much cheaper by default, I suggest you stick with double by all means, and consider float at best a storage format that may be useful to conserve RAM, or to improve cache locality (when you have a lot of them). Even then, measuring is an excellent idea.
That said, you could try ivaigult's algorithm (only with double for the intermediate and for the result), which is related to a classical algorithm called Egyptian multiplication (and a variety of other names), only that the operands are multiplied and not added. I don't know how pow(double, double) works exactly, but it is conceivable that this algorithm could be faster in some cases. Again, you should be OCD about benchmarking.
If you're targeting GCC you can try
float __builtin_powif(float, int)
I have no idea about it's performance tough.
Is there some special function (in standard libraries or any other) with the above signature?
Unfortunately, not that I know of.
But, as many have already mentioned benchmarking is necessary to understand if there is even an issue at all.
I've assembled a quick benchmark online. Benchmark code:
#include <iostream>
#include <boost/timer/timer.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>
#include <cmath>
int main ()
{
boost::random::mt19937 gen;
boost::random::uniform_real_distribution<> dist(0, 10000000);
const size_t size = 10000000;
std::vector<float> bases(size);
std::vector<float> fexp(size);
std::vector<int> iexp(size);
std::vector<float> res(size);
for(size_t i=0; i<size; i++)
{
bases[i] = dist(gen);
iexp[i] = std::floor(dist(gen));
fexp[i] = iexp[i];
}
std::cout << "float pow(float, int):" << std::endl;
{
boost::timer::auto_cpu_timer timer;
for(size_t i=0; i<size; i++)
res[i] = std::pow(bases[i], iexp[i]);
}
std::cout << "float pow(float, float):" << std::endl;
{
boost::timer::auto_cpu_timer timer;
for(size_t i=0; i<size; i++)
res[i] = std::pow(bases[i], fexp[i]);
}
return 0;
}
Benchmark results (quick conclusions):
gcc: c++11 is consistently faster than c++03.
clang: indeed int-version of c++03 seems a little faster. I'm not sure if it is within a margin of error, since I only run the benchmark online.
Both: even with c++11 calling pow with int seems to be a tad more performant.
It would be great if others could verify if this holds for their configurations as well.
Try using powf() instead. This is C99 function that should be also available in C++11.

Very large differences using float and double

#include <iostream>
using namespace std;
int main() {
int steps=1000000000;
float s = 0;
for (int i=1;i<(steps+1);i++){
s += (i/2.0) ;
}
cout << s << endl;
}
Declaring s as float: 9.0072e+15
Declaring s as double: 2.5e+17 (same result as implementing it in Julia)
I understand double has double precision than float, but float should still handle numbers up to 10^38.
I did read similar topics where results where not the same, but in that cases the differences were very small, here the difference is 25x.
I also add that using long double instead gives me the same result as double. If the matter is the precision, I would have expected to have something a bit different.
The problem is the lack of precision: https://en.wikipedia.org/wiki/Floating_point
After 100 million numbers you are adding 1e8 to 1e16 (or at least numbers of that magnitude), but single precision numbers are only accurate to 7 digits - so it is the same as adding 0 to 1e16; that's why your result is considerably lower for float.
Prefer double over float in most cases.
Problem with floating point precision! Infinite real numbers cannot possibly be represented by the finite memory of a computer. Float, in general, are just approximations of the number they are meant to represent.
For more details, please check the following documentation:
https://softwareengineering.stackexchange.com/questions/101163/what-causes-floating-point-rounding-errors
You didn't mention what type of floating point numbers you are using, but I'm going to assume that you use IEEE 754, or similar.
I understand double has double precision
To be more precise with the terminology, double uses twice as many bits. That's not double the number of reprensentable values, it's 4294967296 times as many representable values, despite being named "double precision".
but float should still handle numbers up to 10^38.
Float can handle a few numbers up to that magnitude. But that does't mean that float values in that range are precise. For example, 3,4028235E+38 can be represented as a single precision float. How much would you imagine is the difference between the previous value representable by float? Is it the machine epsilon? Perhaps 0.1? Maybe 1? No. The difference is about 2E+31.
Now, your numbers aren't quite in that range. But, they're outside the continuous range of whole integers that can be precisely represented by float. The highest value in that range happens to be 16777217, or about 1.7E+7, which is way less than 2.5E+17. So, every addition beyond that range adds some error to the result. You perform a billion calculations so those errors add up.
Conclusions:
Understand that single precision is way less precise than double precision.
Avoid long sequences of calculations where precision errors can accumulate.

Creating custom data type in c++

I'm writing a program to find the value of pi, and want it to show more than the standard 16 decimal places.
How do I create a variable that can hold more than 16 decimal places?
My current program is written below.
Using Dev-C++:
#include<iostream.h>
#include<conio.h>
#include<math.h>
int factorial(int a)
{
int b=1,c=1;
for(c; c<=a; c++)
{
b=b*c;
}
return b;
}
int main()
{
cout.precision(300);
long int n,a;
long double z=0,pi,num,den;
for(n=0; n<1000000; n++)
{ //begin for
num=(pow(factorial(2*n),3))*((42*n)+5);
den=(pow(factorial(n),6))*(pow(16,(3*n)+1));
z=z+(num/den);
pi=1/z;
if(n%1==0)
{
cout<<z<<endl; //test print statement
cin>>a;
cout<<pi;
cout<<endl;
}
}
getch();
return 0; //end for
}
If you don't want to use an existing high-precision arithmetic library, then here are a few pointers for writing your own. It will be a fair amount of work (and quite fiddly to debug), but quite a good learning exercise if you've got the time.
Store each number as an array of smaller "digits". For a very simple (but inefficient) implementation, these could literally be decimal digits, with values from 0 to 9 - this will then be very easy to print. For a more efficient implementation, I'd probably use 32-bit values for the "digits". You'll also need to decide how to represent negative numbers, whether the array should be fixed or variable size, and (for working with non-integers) whether the decimal point should be fixed or floating.
Implement basic arithmetic using the algorithms you learnt in primary school: addition with carry, subtraction with borrow, long multiplication and long division.
pow and factorial, needed for your algorithm can be implemented simply as repeated multiplication; other algorithms are available if this isn't fast enough (and for functions like sqrt and sin that can't be represented exactly with basic operations).
Sounds like you want a bignum library. Have a look at the GNU Multiple Precision Arithmetic Library for a widely-used open source alternative.
You can use one of the bigint libraries on the internet, for example: https://mattmccutchen.net/bigint/

When I calculate a large factorial, why do I get a negative number?

So, simple procedure, calculate a factorial number. Code is as follows.
int calcFactorial(int num)
{
int total = 1;
if (num == 0)
{
return 0;
}
for (num; num > 0; num--)
{
total *= num;
}
return total;
}
Now, this works fine and dandy (There are certainly quicker and more elegant solutions, but this works for me) for most numbers. However when inputting larger numbers such as 250 it, to put it bluntly, craps out. Now, the first couple factorial "bits" for 250 are { 250, 62250, 15126750, 15438000, 3813186000 } for reference.
My code spits out { 250, 62250, 15126750, 15438000, -481781296 } which is obviously off. My first suspicion was perhaps that I had breached the limit of a 32 bit integer, but given that 2^32 is 4294967296 I don't think so. The only thing I can think of is perhaps that it breaches a signed 32-bit limit, but shouldn't it be able to think about this sort of thing? If being signed is the problem I can solve this by making the integer unsigned but this would only be a temporary solution, as the next iteration yields 938043756000 which is far above the 4294967296 limit.
So, is my problem the signed limit? If so, what can I do to calculate large numbers (Though I've a "LargeInteger" class I made a while ago that may be suited!) without coming across this problem again?
2^32 doesn't give you the limit for signed integers.
The signed integer limit is actually 2147483647 (if you're developing on Windows using the MS tools, other toolsuites/platforms would have their own limits that are probably similar).
You'll need a C++ large number library like this one.
In addition to the other comments, I'd like to point out two serious bugs in your code.
You have no guard against negative numbers.
The factorial of zero is one, not zero.
Yes, you hit the limit. An int in C++ is, by definition, signed. And, uh, no, C++ does not think, ever. If you tell it to do a thing, it will do it, even if it is obviously wrong.
Consider using a large number library. There are many of them around for C++.
If you don't specify signed or unsigned, the default is signed. You can modify this using a command line switch on your compiler.
Just remember, C (or C++) is a very low-level language and does precisely what you tell it to do. If you tell it to store this value in a signed int, that's what it will do. You as the programmer have to figure out when that's a problem. It's not the language's job.
My Windows calculator (Start-Run-Calc) tells me that
hex (3813186000) = E34899D0
hex (-481781296) = FFFFFFFFE34899D0
So yes, the cause is the signed limit. Since factorials can by definition only be positive, and can only be calculated for positive numbers, both the argument and the return value should be unsigned numbers anyway. (I know that everybody uses int i = 0 in for loops, so do I. But that left aside, we should use always unsigned variables if the value can not be negative, it's good practice IMO).
The general problem with factorials is, that they can easily generate very large numbers. You could use a float, thus sacrificing precision but avoiding the integer overflow problem.
Oh wait, according to what I wrote above, you should make that an unsigned float ;-)
If i remember well:
unsigned short int = max 65535
unsigned int = max 4294967295
unsigned long = max 4294967295
unsigned long long (Int64 )= max 18446744073709551615
Edited source:
Int/Long Max values
Modern Compiler Variable