I am attempting to calculate the Champernowne constant C10 using the following formula:
In the above formula, I substitute b for 10 to calculate C10. I want to be able to calculate the constant to any precision using Boost's cpp_dec_float.
Here is my code:
#include <boost/multiprecision/cpp_dec_float.hpp>
const long long PRECISION = 100;
typedef boost::multiprecision::number<
boost::multiprecision::cpp_dec_float<PRECISION> > arbFloat;
arbFloat champernowne()
{
arbFloat c, sub, n, k;
std::string precomp_c, postcomp_c;
for(n = 1; n == 1 || precomp_c != postcomp_c; ++n) {
for(k = 1; k <= n; ++k) {
sub += floor(log10(k));
}
precomp_c = static_cast<std::string>(c);
c += n / pow(10, n + sub);
postcomp_c = static_cast<std::string>(c);
}
return c;
}
Here's a breakdown of the code:
I begin by defining a variable arbFloat which has a precision of 100 digits (this is changed often — so I don't want to use cpp_dec_float_100).
The formula has two blocks of summation, so I implement them using two for-loops. In the innermost for-loop I calculate the summation beginning with k = 1 conditional upon k <= n for floor(log10(k)).
I have verified that using floor() and log10() on cpp_dec_float returns variables with correct precision.
Because the outermost summation goes until infinity, I have to stop calculations at some point. To check whether the precision has been exceeded, I cast c to a string before I calculate c += n / pow(10, n + sub) - and then I cast it to a string after I do the calculation. If the strings are the same, I end the calculations because the precision has been exceeded (further calculations would be redundant).
I have also used this set up (with string casting and comparison to check exceeded precision) to calculate other variables - and it works very well.
Next I calculate the outermost summation of c += n / pow(10, n + sub) - using pow() in this manner does maintain the precision. Finally, I return c.
When I run this program, I get the following variable:
0.1234567891001100120001300001400000150000001600000001700000000180000000001900000000002000000000000210
vs. the real Champernowne constant C10:
0.1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253546
Only the first 11 digits are correct, and the rest are not. I am not able to find where I am going wrong. I have tried the following:
Tried replacing c += n / pow(10, n + sub) with c += n / pow(static_cast<arbFloat>(10), n + sub) to check if pow() was not maintaining precision - but it didn't change anything.
Tried replacing floor() with a method of casting log10(k) to a string and "rounding" the string (keep only characters before .) - but it didn't change anything.
Tried changing k <= n to k < n, k <= n + 1 - just in case I was misinterpreting the summation - but that only made it more inaccurate.
If I need to explain more, let me know. Any help would be much appreciated!
The previous value of sub is being carried forward on each iteration; declare it inside the loop.
arbFloat champernowne() {
arbFloat c;
for (int n = 1;; ++n) {
arbFloat sub;
for (int k = 1; k <= n; ++k) {
sub += floor(log10(k));
}
arbFloat const last = c;
c += n / pow(10, n + sub);
if (c == last) {
break;
}
}
return c;
}
Related
I've been trying to write a function to approximate an the value of an integral using the Composite Simpson's Rule.
template <typename func_type>
double simp_rule(double a, double b, int n, func_type f){
int i = 1; double area = 0;
double n2 = n;
double h = (b-a)/(n2-1), x=a;
while(i <= n){
area = area + f(x)*pow(2,i%2 + 1)*h/3;
x+=h;
i++;
}
area -= (f(a) * h/3);
area -= (f(b) * h/3);
return area;
}
What I do is multiply each value of the function by either 2 or 4 (and h/3) with pow(2,i%2 + 1) and subtract off the edges as these should only have a weight of 1.
At first, I thought it worked just fine, however, when I compared it to my Trapezoidal Method function it was way more inaccurate which shouldn't be the case.
This is a simpler version of a code I previously wrote which had the same problem, I thought that if I cleaned it up a little the problem would go away, but alas. From another post, I get the idea that there's something going on with the types and the operations I'm doing on them which results in loss of precision, but I just don't see it.
Edit:
For completeness, I was running it for e^x from 1 to zero
\\function to be approximated
double f(double x){ double a = exp(x); return a; }
int main() {
int n = 11; //this method works best for odd values of n
double e = exp(1);
double exact = e-1; //value of integral of e^x from 0 to 1
cout << simp_rule(0,1,n,f) - exact;
The Simpson's Rule uses this approximation to estimate a definite integral:
Where
and
So that there are n + 1 equally spaced sample points xi.
In the posted code, the parameter n passed to the function appears to be the number of points where the function is sampled (while in the previous formula n is the number of intervals, that's not a problem).
The (constant) distance between the points is calculated correctly
double h = (b - a) / (n - 1);
The while loop used to sum the weighted contributes of all the points iterates from x = a up to a point with an ascissa close to b, but probably not exactly b, due to rounding errors. This implies that the last calculated value of f, f(x_n), may be slightly different from the expected f(b).
This is nothing, though, compared to the error caused by the fact that those end points are summed inside the loop with the starting weight of 4 and then subtracted after the loop with weight 1, while all the inner points have their weight switched. As a matter of fact, this is what the code calculates:
Also, using
pow(2, i%2 + 1)
To generate the sequence 4, 2, 4, 2, ..., 4 is a waste, in terms of efficency, and may add (depending on the implementation) other unnecessary rounding errors.
The following algorithm shows how to obtain the same (fixed) result, without a call to that library function.
template <typename func_type>
double simpson_rule(double a, double b,
int n, // Number of intervals
func_type f)
{
double h = (b - a) / n;
// Internal sample points, there should be n - 1 of them
double sum_odds = 0.0;
for (int i = 1; i < n; i += 2)
{
sum_odds += f(a + i * h);
}
double sum_evens = 0.0;
for (int i = 2; i < n; i += 2)
{
sum_evens += f(a + i * h);
}
return (f(a) + f(b) + 2 * sum_evens + 4 * sum_odds) * h / 3;
}
Note that this function requires the number of intervals (e.g. use 10 instead of 11 to obtain the same results of OP's function) to be passed, not the number of points.
Testable here.
The above excellent and accepted solution could benefit from liberal use of std::fma() and templatize on the floating point type.
https://en.cppreference.com/w/cpp/numeric/math/fma
#include <cmath>
template <typename fptype, typename func_type>
double simpson_rule(fptype a, fptype b,
int n, // Number of intervals
func_type f)
{
fptype h = (b - a) / n;
// Internal sample points, there should be n - 1 of them
fptype sum_odds = 0.0;
for (int i = 1; i < n; i += 2)
{
sum_odds += f(std::fma(i,h,a));
}
fptype sum_evens = 0.0;
for (int i = 2; i < n; i += 2)
{
sum_evens += f(std::fma(i,h,a);
}
return (std::fma(2,sum_evens,f(a)) +
std::fma(4,sum_odds,f(b))) * h / 3;
}
I am trying to solve a question in which i need to find out the number of possible ways to make a team of two members.(note: a team can have at most two person)
After making this code, It works properly but in some test cases it shows floating point error ad i can't find out what it is exactly.
Input: 1st line : Number of test cases
2nd line: number of total person
Thank you
#include<iostream>
using namespace std;
long C(long n, long r)
{
long f[n + 1];
f[0] = 1;
for (long i = 1; i <= n; i++)
{
f[i] = i * f[i - 1];
}
return f[n] / f[r] / f[n - r];
}
int main()
{
long n, r, m,t;
cin>>t;
while(t--)
{
cin>>n;
r=1;
cout<<C(n, min(r, n - r))+1<<endl;
}
return 0;
}
You aren't getting a floating point exception. You are getting a divide by zero exception. Because your code is attempting to divide by the number 0 (which can't be done on a computer).
When you invoke C(100, 1) the main loop that initializes the f array inside C increases exponentially. Eventually, two values are multiplied such that i * f[i-1] is zero due to overflow. That leads to all the subsequent f[i] values being initialized to zero. And then the division that follows the loop is a division by zero.
Although purists on these forums will say this is undefined, here's what's really happening on most 2's complement architectures. Or at least on my computer....
At i==21:
f[20] is already equal to 2432902008176640000
21 * 2432902008176640000 overflows for 64-bit signed, and will typically become -4249290049419214848 So at this point, your program is bugged and is now in undefined behavior.
At i==66
f[65] is equal to 0x8000000000000000. So 66 * f[65] gets calculated as zero for reasons that make sense to me, but should be understood as undefined behavior.
With f[66] assigned to 0, all subsequent assignments of f[i] become zero as well. After the main loop inside C is over, the f[n-r] is zero. Hence, divide by zero error.
Update
I went back and reverse engineered your problem. It seems like your C function is just trying to compute this expression:
N!
-------------
R! * (N-R)!
Which is the "number of unique sorted combinations"
In which case instead of computing the large factorial of N!, we can reduce that expression to this:
n
[ ∏ i ]
n-r
--------------------
R!
This won't eliminate overflow, but will allow your C function to be able to take on larger values of N and R to compute the number of combinations without error.
But we can also take advantage of simple reduction before trying to do a big long factorial expression
For example, let's say we were trying to compute C(15,5). Mathematically that is:
15!
--------
10! 5!
Or as we expressed above:
1*2*3*4*5*6*7*8*9*10*11*12*13*14*15
-----------------------------------
1*2*3*4*5*6*7*8*9*10 * 1*2*3*4*5
The first 10 factors of the numerator and denominator cancel each other out:
11*12*13*14*15
-----------------------------------
1*2*3*4*5
But intuitively, you can see that "12" in the numerator is already evenly divisible by denominators 2 and 3. And that 15 in the numerator is evenly divisible by 5 in the denominator. So simple reduction can be applied:
11*2*13*14*3
-----------------------------------
1 * 4
There's even more room for greatest common divisor reduction, but this is a great start.
Let's start with a helper function that computes the product of all the values in a list.
long long multiply_vector(std::vector<int>& values)
{
long long result = 1;
for (long i : values)
{
result = result * i;
if (result < 0)
{
std::cout << "ERROR - multiply_range hit overflow" << std::endl;
return 0;
}
}
return result;
}
Not let's implement C as using the above function after doing the reduction operation
long long C(int n, int r)
{
if ((r >= n) || (n < 0) || (r < 0))
{
std::cout << "invalid parameters passed to C" << std::endl;
return 0;
}
// compute
// n!
// -------------
// r! * (n-r)!
//
// assume (r < n)
// Which maps to
// n
// [∏ i]
// n - r
// --------------------
// R!
int end = n;
int start = n - r + 1;
std::vector<int> numerators;
std::vector<int> denominators;
long long numerator = 1;
long long denominator = 1;
for (int i = start; i <= end; i++)
{
numerators.push_back(i);
}
for (int i = 2; i <= r; i++)
{
denominators.push_back(i);
}
size_t n_length = numerators.size();
size_t d_length = denominators.size();
for (size_t n = 0; n < n_length; n++)
{
int nval = numerators[n];
for (size_t d = 0; d < d_length; d++)
{
int dval = denominators[d];
if ((nval % dval) == 0)
{
denominators[d] = 1;
numerators[n] = nval / dval;
}
}
}
numerator = multiply_vector(numerators);
denominator = multiply_vector(denominators);
if ((numerator == 0) || (denominator == 0))
{
std::cout << "Giving up. Can't resolve overflow" << std::endl;
return 0;
}
long long result = numerator / denominator;
return result;
}
You are not using floating-point. And you seem to be using variable sized arrays, which is a C feature and possibly a C++ extension but not standard.
Anyway, you will get overflow and therefore undefined behaviour even for rather small values of n.
In practice the overflow will lead to array elements becoming zero for not much larger values of n.
Your code will then divide by zero and crash.
They also might have a test case like (1000000000, 999999999) which is trivial to solve, but not for your code which I bet will crash.
You don't specify what you mean by "floating point error" - I reckon you are referring to the fact that you are doing an integer division rather than a floating point one so that you will always get integers rather than floats.
int a, b;
a = 7;
b = 2;
std::cout << a / b << std::endl;
this will result in 3, not 3.5! If you want floating point result you should use floats instead like this:
float a, b;
a = 7;
b = 2;
std::cout << a / b << std::end;
So the solution to your problem would simply be to use float instead of long long int.
Note also that you are using variable sized arrays which won't work in C++ - why not use std::vector instead??
Array syntax as:
type name[size]
Note: size must a constant not a variable
Example #1:
int name[10];
Example #2:
const int asize = 10;
int name[asize];
I want an efficient implementation of Faulhaber's Formula
I want answer as
F(N,K) % P
where F(N,K) is implementation of faulhaber's forumula and P is a prime number.
Note: N is very large upto 10^16 and K is upto 3000
I tried the double series implementation in the given site. But its too much time consuming for very large n and k. Can any one help making this implementation more efficient or describe some other way to implement the formula.
How about using Schultz' (1980) idea, outlined below the double series implementation (mathworld.wolfram.com/PowerSum.html) that you mentioned?
From Wolfram MathWorld:
Schultz (1980) showed that the sum S_p(n) can be found by writing
and solving the system of p+1 equations
obtained for j=0, 1, ..., p (Guo and Qi 1999), where delta (j,p) is the Kronecker delta.
Below is an attempt in Haskell that seems to work. It returns a result for n=10^16, p=1000 in about 36 seconds on my old laptop PC.
{-# OPTIONS_GHC -O2 #-}
import Math.Combinatorics.Exact.Binomial
import Data.Ratio
import Data.List (foldl')
kroneckerDelta a b | a == b = 1 % 1
| otherwise = 0 % 1
g a b = ((-1)^(a - b +1) * choose a b) % 1
coefficients :: Integral a => a -> a -> [Ratio a] -> [Ratio a]
coefficients p j cs
| j < 0 = cs
| otherwise = coefficients p (j - 1) (c:cs)
where
c = f / g (j + 1) j
f = foldl h (kroneckerDelta j p) (zip [j + 2..p + 1] cs)
h accum (i,cf) = accum - g i j * cf
trim r = let n = numerator r
d = denominator r
l = div n d
in (mod l (10^9 + 7),(n - d * l) % d)
s n p = numerator (a % 1 + b) where
(a,b) = foldl' (\(i',r') (i,r) -> (mod (i' + i) (10^9 + 7),r' + r)) (0,0)
(zipWith (\c i -> trim (c * n^i)) (coefficients p p []) [1..p + 1])
main = print (s (10^16) 1000)
I've discovered my own algorithm to calculate the coefficients of the polynomial obtained from Faulhaber's formula; it, its proof and several implementations can be found at github.com/fcard/PolySum. This question inspired me to include a c++ implementation (using the GMP library for arbitrary precision numbers), which, as of the time of writing and minus several usability features, is:
#include <gmpxx.h>
#include <vector>
namespace polysum {
typedef std::vector<mpq_class> mpq_row;
typedef std::vector<mpq_class> mpq_column;
typedef std::vector<mpq_row> mpq_matrix;
mpq_matrix make_matrix(size_t n) {
mpq_matrix A(n+1, mpq_row(n+2, 0));
A[0] = mpq_row(n+2, 1);
for (size_t i = 1; i < n+1; i++) {
for (size_t j = i; j < n+1; j++) {
A[i][j] += A[i-1][j];
A[i][j] *= (j - i + 2);
}
A[i][n+1] = A[i][n-1];
}
A[n][n+1] = A[n-1][n+1];
return A;
}
void reduced_row_echelon(mpq_matrix& A) {
size_t n = A.size() - 1;
for (size_t i = n; i+1 > 0; i--) {
A[i][n+1] /= A[i][i];
A[i][i] = 1;
for (size_t j = i-1; j+1 > 0; j--) {
auto p = A[j][i];
A[j][i] = 0;
A[j][n+1] -= A[i][n+1] * p;
}
}
}
mpq_column sum_coefficients(size_t n) {
auto A = make_matrix(n);
reduced_row_echelon(A);
mpq_column result;
for (auto row: A) {
result.push_back(row[n+1]);
}
return result;
}
}
We can use the above like so:
#include <cmath>
#include <gmpxx.h>
#include <polysum.h>
mpq_class power_sum(size_t K, unsigned int N) {
auto coeffs = polysum::sum_coefficients(K)
mpq_class result(0);
for (size_t i = 0; i <= K; i++) {
result += A[i][n+1] * pow(N, i+1);
}
return result;
}
The full implementation provides a Polynomial class that is printable and callable, as well as a polysum function to construct one as a sum of another polynomial.
#include "polysum.h"
void power_sum_print(size_t K, unsigned int N) {
auto F = polysum::polysum(K);
std::cout << "polynomial: " << F;
std::cout << "result: " << F(N);
}
As for efficiency, the above calculates the result for K=1000 and N=1e16 in about 1.75 seconds on my computer, compared to the much more mature and optimized SymPy implementation which takes about 90 seconds on the same machine, and mathematica which takes 30 seconds. For K=3000 the above takes about 4 minutes, mathematica took almost 20 minutes, (but uses much less memory) and I left sympy running all night but it didn't finish, maybe due to it running out of memory.
Among the optimizations that can be done here are making the matrix sparse and taking advantage of the fact that only half of the rows and columns need to be calculated. The Rust version in the linked repository implements the sparse and rows optimizations, and takes about 0.7 seconds to calculate K=1000, and about 45 to calculate K=3000 (using 105mb and 2.9gb of memory respectively). The Haskell version implements all three optimizations and takes about 1 second for K=1000 and about 34 seconds for K=3000. (using 60mb and 880mb of memory respectively) and The completely unoptimized python implementation takes about 12 seconds for K=1000 but runs out of memory for K=3000.
It's looking like this method is the fastest regardless of the language used, but the research is ongoing. Since Schultz's method also boils down to solving a system of n+1 equations and should be able to be optimized the same way, it will depend on whether his matrix is faster to calculate or not. Also, memory usage is not scaling well at all, and Mathematica is still the clear winner here, using only 80mb for K=3000. We'll see.
How would you compute a combination such as (100,000 choose 50,000)?
I have tried three different approaches thus far but for obvious reasons each has failed:
1) Dynamic Programming- The size of the array just gets to be so ridiculous it seg faults
unsigned long long int grid[p+1][q+1];
//Initialise x boundary conditions
for (long int i = 0; i < q; ++i) {
grid[p][i] = 1;
}
//Initialise y boundary conditions
for (long int i = 0; i < p; ++i) {
grid[i][q] = 1;
}
for (long int i = p - 1; i >= 0; --i) {
for (long int j = q - 1; j >= 0; --j) {
grid[i][j] = grid[i+1][j] + grid[i][j+1];
}
}
2) Brute Force - Obviously calculating even 100! isn't realistic
unsigned long long int factorial(long int n)
{
return (n == 1 || n == 0) ? 1 : factorial(n - 1) * n;
}
3) Multiplicative Formula- I'm unable to store the values they are just so large
const int gridSize = 100000; //say 100,000
unsigned long long int paths = 1;
for (int i = 0; i < gridSize; i++) {
paths *= (2 * gridSize) - i;
paths /= i + 1;
}
// code from (http://www.mathblog.dk/project-euler-15/)
If it helps for context the aim of this is to solve the "How many routes are there through an m×n grid" problem for large inputs. Maybe I am miss-attacking the problem?
C(100000, 50000) is a huge number with 30101 decimal digits: http://www.wolframalpha.com/input/?i=C%28100000%2C+50000%29
Obviously unsigned long long will not be enough to store it. You need some arbitrary large integers library, like GMP: http://en.wikipedia.org/wiki/GNU_Multiple_Precision_Arithmetic_Library
Otherwise, multiplicative formula should be good enough.
"How would you compute ..." depends very much on the desired accuracy. Precise results can only be computed with arbitrary precission numbers (eg. GMP), but it is rather likely that you don't really need the exact result.
In that case I would use the Stirling Approximation for factorials ( http://en.wikipedia.org/wiki/Stirling%27s_approximation ) and calculate with doubles. The number of summands in the expansion can be used to regulate the error. The wikipedia page will also give you an error estimate.
Here is recursive formula that might help : -
NCk = (N-1)C(k-1)*N/K
Use a recursive call for (N-1)C(K-1) first then evaluate NCk on result.
As your numbers will be very large use one of following alternatives.
GMP
Use your own implementation where you can store numbers as sequence of binary bits in array and use booth's algorithm for multiplication
and shift & subtract for division.
I wrote the following code to sum the series (-1)^i*(i/(i+1)). But when I run it I get -1 for any value of n.
Can some one please point out what I am doing wrong? Thank you in advance!
#include <iostream>
using namespace std;
int main()
{
int sum = 0;
int i = 1.0;
int n = 5.0;
for(i=1;i<=n;i++)
sum = (-1)^i*(i/(i+1));
cout << "Sum" <<" = "<< sum << endl;
return 0;
}
Problem #1: The C++ ^ operator isn't the math power operator. It's a bitwise XOR.
You should use pow() instead.
Problem #2:
You are storing floating-point types into an integer type. So the following will result in integer division (truncated division):
i/(i+1)
Problem #3:
You are not actually summing anything up:
sum = ...
should be:
sum += ...
A corrected version of the code is as follows:
double sum = 0;
int i = 1;
int n = 5;
for(i = 1; i <= n; i++)
sum += pow(-1.,(double)i) * ((double)i / (i + 1));
Although you really don't need to use pow in this case. A simple test for odd/even will do.
double sum = 0;
int i = 1;
int n = 5;
for(i = 1; i <= n; i++){
double val = (double)i / (i + 1);
if (i % 2 != 0){
val *= -1.;
}
sum += val;
}
You need too put sum += pow(-1,i)*(i/(i+1));
Otherwise you lose previous result each time.
Use pow function for pow operation.
edit : as said in other post, use double or float instead of int to avoid truncated division.
How about this
((i % 2) == 0 ? 1 : -1)
instead of
std::pow(-1, i)
?
Full answer:
double sum = 0;
int i = 1.0;
int n = 5.0;
for (i = 1; i <= n; ++i) {
signed char sign = ((i % 2) == 0 ? 1 : -1);
sum += sign * (i / (i+1));
}
Few problems:
^ is teh bitwise exclusive or in c++ not "raised to power". Use pow() method.
Remove the dangling opening bracket from the last line
Use ints not floats when assigning to ints.
You seem to have a few things wrong with your code:
using namespace std;
This is not directly related to your problem at hand, but don't ever say using namespace std; It introduces subtle bugs.
int i = 1.0;
int n = 5.0;
You are initializaing integral variables with floating-point constants. Try
int i = 1;
int n = 5;
sum = (-1)^i*(i/(i+1));
You have two problems with this expression. First, the quantity (i/(i+1)) is always zero. Remember dividing two ints rounds the result. Second, ^ doesn't do what you think it does. It is the exclusive-or operator, not the exponentiation operator. Third, ^ binds less tightly than *, so your expression is:
-1 xor (i * (i/(i+1)))
-1 xor (i * 0)
-1 xor 0
-1
^ does not do what you think it does. Also there are some other mistakes in your code.
What it should be:
#include <iostream>
#include <cmath>
int main( )
{
long sum = 0;
int i = 1;
int n = 5;
for( i = 1; i <= n; i++ )
sum += std::pow( -1.f, i ) * ( i / ( i + 1 ) );
std::cout << "Sum = " << sum << std::endl;
return 0;
}
To take a power of a value, use std::pow (see here). Also you can not assign int to a decimal value. For that you need to use float or double.
The aforementioned ^ is a bitwise-XOR, not a mark for an exponent.
Also be careful of Integer Arithmetic as you may get unexpected results. You most likely want to change your variables to either float or double.
There are a few issues with the code:
int sum = 0;
The intermediate results are not integers, this should be a double
int i = 1.0;
Since you will use this in a division, it should be a double, 1/2 is 0 if calculated in integers.
int n = 5.0;
This is an int, not a floating point value, no .0 is needed.
for(i=1;i<=n;i++)
You've already initialized i to 1, why do it again?
sum = (-1)^i*(i/(i+1));
Every iteration you lose the previous value, you should use sum+= 'new values'
Also, you don't need pow to calculate (-1)^i, all this does is switch between +1 and -1 depending on the odd/even status of i. You can do this easier with an if statement or with 2 for's, one for odd i one for even ones... Many choices really.