How do I express this? - c++

I'm trying to work out how to write the following:
total = (value * 0.95 ^ 0) + (value * 0.95 ^ 1) + (value * 0.95 ^ 2) ...
or:
x = (y * z ^ 0) + (y * z ^ 1) + (y * z ^ 2) + (y * z ^ 3) ...
This expresses how to calculate x for 4 iterations, but how can I express this to work with a variable number of iterations? Obviously I could create a loop and add the values together, but I'd really like to find a single equation that solves this.
I'm using c++ but I guess this isn't really a language specific problem (sorry I literally don't know where else to ask this question!).
Any ideas?
Thanks,
Chris.

There is no need for a loop here, you "just" need to employ some maths.
Note that you can rewrite that as
y * (z0 + z1 + ... + zn)
Now, the series
z0 + z1 + ... + zn
sums to
(z(n+1) - 1) / (z - 1)
so your equation would be
x = y * (z(n+1) - 1) / (z - 1)

Equation-wise solving, this is a geometric series and can therefore be calculated with
double geometric_series(double y, double z, int N) {
return y * (std::pow(z, N) - 1.0) / (z - 1.0);
}
but the same result can be obtained with some fun C++ metaprogramming: if you know the number of iterations in advanced and you're allowed to use C++17 features and fold expressions you could do as follows
template<std::size_t... N>
double calculate_x(double y, double z, std::index_sequence<N...>) { // [0;N[
auto f = [](double y_p, double z_p, double exp) {
return y_p * std::pow(z_p, exp);
};
return (f(y, z, N) + ...);
}
template <std::size_t N>
auto calculate_x(double y, double z) {
return calculate_x(y, z, std::make_index_sequence<N>{});
}
Alternatively this can also be done with pre-C++17 templates
template <int N>
double calculate_x(double y, double z) {
return calculate_x<N-1>(y, z) + (y * std::pow(z, N - 1));
}
template <>
double calculate_x<0>(double, double) {
return 0;
}
Otherwise a simpler solution would be to just use a loop
double calculate_x_simple(double y, double z, int N) {
double ret = 0.0;
for (int i = 0 ; i < N ; ++i)
ret += y * std::pow(z, i);
return ret;
}
Driver for the code above
int main() {
// x = (y * z ^ 0) + (y * z ^ 1) + (y * z ^ 2) + (y * z ^ 3)
double y = 42.0;
double z = 44.5;
std::cout << (calculate_x<3>(y, z) == calculate_x_simple(y, z, 3)); // 1
}

As you mentioned, it seems reasonable to use a loop. But if you know the amount of iterations at compile time, you could use templates like this:
template <int n>
double foo(double y, double z)
{
return foo<n-1>(y, z) + y * std::pow(z, n);
}
template <>
double foo<-1>(double, double)
{
return 0;
}
With just a little bit of optimisation this will unfold to a single equation.
Example:
#include <iostream>
#include <cmath>
template <int n>
double foo(double y, double z)
{
return foo<n-1>(y, z) + y * std::pow(z, n);
}
template <>
double foo<-1>(double, double)
{
return 0;
}
int main()
{
std::cout << foo<2>(2,3) << std::endl;
}
Output: 26

If a loop would be the only option:
double x = 0;
int n = 5;
for(int exponent = 0; exponent <= n; ++exponent)
x += y*pow(z, exponent);

you can just use math.pow function with a for loop
#include <stdio.h>
#include <math.h>
int main(void) {
int i;
int n = 5;
double y = 0.5;
double z = 0.3;
double answer = 0;
for (i = 0 ; i < n ; i++)
answer += y * pow(z,i);
printf("%f", answer);
return 0;
}

It can be expressed as a sum from n=0 to m. It can be expressed in a single formula, according to wolframalpha.

Don't know if this fulfills your purpose, but you can use recursion(which in real terms is a loop only :) )
int x = evaluate(y, z, count);
int evaluate(y,z, count)
{
if (count <= 0)
return 0;
return (evaluate(y, z, count-1) + y*z^count);
}

Using n as the number of iterations,
#include <cmath>
double foo(double y, double z, int n)
{
double x =0;
for(int i = 0 ; i<n; ++i){
x+=y*std::pow(z,i);
}
return x;
}
Where std::pow is the power function.

Related

How do I fix this bug with arctanx function in c++

I've recently been given a problem by my teacher about some mathematical equation / formula called the arctanx formula. The question is:
According to the Arctanx(x) = x - ((x ^ 3) / 3) + ((x ^ 5) / 5) - ((x ^
7) / 7) + ...and π = 6 * arctanx(1 / sqrt(3)), Create function arctanx(x)
, and find pi when the last "number"(like this ((x ^ y) / y)) is right before
and bigger than 10 ^ -6, or you can say that no "number" can be smaller than
that number without being smaller than 10 ^ -6.
I tried to code it out, but there is a bug in it.
# include<iostream>
# include<math.h>
using namespace std;
float arctanx() {
long double pi = 3.1415926535897;
int i = 0; // 0 = +, 1 = -
float sum = 0;
float lsum;
for (int y = 1; y < pi; y += 2) {
if (lsum > 0.000001) {
if (i == 0) {
lsum = pow(1 / sqrt(3), y) / y;
sum += pow(1 / sqrt(3), y) / y;
i++;
} else if (i == 1) {
lsum = pow(1 / sqrt(3), y) / y;
sum -= pow(1 / sqrt(3), y) / y;
i--;
}
} else {
break;
}
}
sum = sum * 6;
return sum;
}
int main() {
cout << arctanx();
return 0;
}
It should have a output of some number not equal to zero, but I got 0 from running this.
Your program has Undefined Behavior because you are using the uninitialized float lsum; in the comparison if (lsum > 0.000001).
What probably happens in your case is that lsum happens to be less than or equal to 0.000001 and your for immediately breaks without doing anything causing your function to return 0 * 6 which is obviously 0.
Create function arctanx(x)
The function defined in the posted code doesn't accept any parameter, it just uses the hardwired (and repeated) value 1 / sqrt(3) and tries to return an approximated value of π instead of the arctangent of x.
It also has undefined behavior, beeing lsum uninitialized (therefore having an indeterminate value) when it is first used in the comparison inside the loop.
Consider this implementation, but be advised that this particular polinomial expansion diverges for values of x greater than 1.
#include <iostream>
#include <iomanip>
#include <cmath>
double arctanx(double x);
int main()
{
double pi = 6.0 * arctanx(1.0 / std::sqrt(3));
std::cout << std::setprecision(8) << pi << '\n';
}
double arctanx(double x)
{
// You can take advantage of a running power, instad of calculating
// pow(x, i) at every iteration
double sq_x = x * x;
double pow_x = x * sq_x;
double err = 1e-6;
// Instead of keeping track of the alternating sign, you can use
// two separate partial sums
double sum_pos_term = x;
double sum_neg_term = 0.0;
for (int i = 3; i < 33; i += 2) // <- Limit the number of iterations
{
if (pow_x < err * i)
break;
sum_neg_term += pow_x / i;
i += 2;
pow_x *= sq_x;
if (pow_x < err * i)
break;
sum_pos_term += pow_x / i;
pow_x *= sq_x;
}
return sum_pos_term - sum_neg_term;
}

Recursive function outputs a wrong value

In this code the output is 'r' instead of 'r0'
Instead of doing the operations it outputs me the first 'r' (equals 100) and does not do the process.
I´m trying to program an operation like (x_0 = x + (nt²/(2(x+(n(t-1)²/2(x+(n(t-3)²/2(x + (n(t-4)²...)²)²)²)²)²)²)²)²) in where the process is repeated until the variable 't' is '0'(because each time the operation is done 't' get a '-1').
#include <iostream>
#include "math.h"
using namespace std;
int operation(float r,
float r0,
float recursiva,
float operacion,
float recursivaPrincipal2,
float recursivaPrincipal,
float p,
float n,
long long t,
float q,
float potenciaQ,
float c,
float potenciaC,
float t2,
float division);
float r = 100;
float t = 10000;
float r0;
float recursiva;
float operacion;
float recursivaPrincipal2;
float recursivaPrincipal;
float p;
float n;
float q;
float potenciaQ;
float c;
float potenciaC;
float t2;
float division;
int main() {
r0 = r + operacion;
potenciaQ = pow(10,10);
q = 6 * potenciaQ;
potenciaC = pow(10,2);
c = 5 * potenciaC;
while (t = 10000, t = t - 1, t > 0) {
t2 = t * t;
n = q * t2;
operacion = n / recursivaPrincipal;
recursivaPrincipal2 = recursiva * recursiva;
recursivaPrincipal = 2 * recursivaPrincipal2;
recursiva = r + operacion;
if (t == 0) {
system("pause");
return 0;
}
cout << "Solucion: " << r0 << endl;
}
}
i want to do something like this
I'm so sorry if this code offended you (comments look like it) but I'm not very good, this is my first c++ code (and last I think)
The answer is based on what i get from your question
Please do expand your mathematical expression for t=3 and append an image of it
by far what i got from your expression you need this
float func(int t,int n,int x)
{
if (t==1)
{
return (x + (n/2)*(n/2)) * (x + (n/2)*(n/2));
}
return x + (n*t*t)/(2*func(t-1,n,x)) ;
}
According to the picture you have uploaded this is my code
Don't use 0 for n
#include<iostream>
using namespace std;
double partSolver(int x,int p, int n)
{
if(n==0) return 2*x*x;
double val = x - ( (p*n*n) / partSolver(x,p,n-1) );
return 2*val*val ;
}
double solver(int x,int p,int n)
{
return (n*n * 2) / partSolver(x,p,n-1);
}
int main()
{
cout<<"The Solution is: "<<solver(3,2,1)<<endl;
return 0;
}

terminated by signal SIGSEGV (Address boundary error) in recursive function

I'm trying to implement Karatsuba algorithm for multiplication. I'm kinda follow the pseudocode in this wiki page. But I'm always getting this error:
terminated by signal SIGSEGV (Address boundary error)
When I replaced the lines that cause the recursion to happen with something else:
z0 = multiply(a, c);
z1 = multiply(b, d);
z2 = multiply(a+b, c+d);
the error disappeared.
Here's my code:
#include <iostream>
#include <math.h>
long int multiply(int x, int y);
int get_length(int val);
int main()
{
int x = 0, y = 0;
long int result = 0;
std::cout << "Enter x: ";
std::cin >> x;
std::cout << "Enter y: ";
std::cin >> y;
result = multiply(x, y);
std::cout << "Result: " << result << std::endl;
return 0;
}
long int multiply(int x, int y)
{
if(x < 10 || y < 10) {
return x * y;
}
int x_len = get_length(x);
int y_len = get_length(y);
long int z0 = 0 , z1 = 0, z2 = 0;
int a = 0, b = 0, c = 0, d = 0;
a = x / pow(10, x_len);
b = x - (a * pow(10, x_len));
c = y / pow(10, y_len);
d = y - (c * pow(10, y_len));
z0 = multiply(a, c);
z1 = multiply(b, d);
z2 = multiply(a+b, c+d);
return (pow(10, x_len) * z0) + (pow(10, x_len/2) * (z2 - z1 - z0)) + z1;
}
int get_length(int val)
{
int count = 0;
while(val > 0) {
count++;
val /= 10;
}
return count;
}
I found the problem cause.
It was because of these lines:
a = x / pow(10, x_len);
b = x - (a * pow(10, x_len));
c = y / pow(10, y_len);
d = y - (c * pow(10, y_len));
It should be x_len / 2 instead of x_len and the same with y_len. Since it causes the recursion to be infinite.
You are using the pow function to do integer powers. It is not an integer function. Code your own pow function that's suitable for your application. For example:
int pow(int v, int q)
{
int ret = 1;
while (q > 1)
{
ret*=v;
q--;
}
return ret;
}
Make sure to put an int pow(int, int); at the top.

matlab mod conversion to c++

this is cornerX
[0] 1041.0374994748950 double
[1] 2489.4116123346407 double
[2] 1029.5005409900616 double
[3] 2477.8746538498076 double
CornerY
[0] 834.69193966025080 double
[1] 852.22774706647908 double
[2] 1787.5897232339489 double
[3] 1805.1255306401772 double
here is the original matlab function
cornerX=cornerX+(1-mod(cornerX,2));
cornerY=cornerY+(1-mod(cornerY,2));
here is my function
void AutomaticMacbethDetection::CalculateBatchCenters(std::vector<double> cornerX, std::vector<double> cornerY)
{
cornerX=cornerX+(1-mod(cornerX,2));
cornerY=cornerY+(1-mod(cornerY,2));*/
for (int i = 0; i < cornerX.size(); i++)
{
cornerX[i] = cornerX[i] + (1 - (Utilities::realmod(cornerX[i],2.0)));
}
here is my c++ modulu
double Utilities::realmod(double x, double y)
{
if (y == 0 )
{
return x;
}
else if ( x == y)
{
return 0.0;
}
else
{
double n = floor(x/y);
double result = x - n *y;
return result;
}
}
I have created my function based on Matlab's description
MOD(x,y) is x - n.*y where n = floor(x./y) if y ~= 0. If y is not an
% integer and the quotient x./y is within roundoff error of an integer,
% then n is that integer. The inputs x and y must be real arrays of the
% same size, or real scalars.
Can you explain why am I getting totally different results?
I guess I'm using the arrays wrong somehow...
I assume the difference is that you are passing the vector by value, not by reference.
Simple compare:
Octave / MATLAB
http://ideone.com/53Sd2o
X = [1041.0374994748950
2489.4116123346407
1029.5005409900616
2477.8746538498076];
Y = [834.69193966025080
852.22774706647908
1787.5897232339489
1805.1255306401772 ];
X+(1-mod(X,2))
Y+(1-mod(Y,2))
C++
http://ideone.com/Xdi1ta
#include <iostream>
#include <vector>
#include <cmath>
#include <iterator>
double realmod(double x, double y);
void test(std::vector<double> &cornerX);
int main()
{
std::vector<double> X = {1041.0374994748950,
2489.4116123346407,
1029.5005409900616,
2477.8746538498076};
std::vector<double> Y = {834.69193966025080 ,
852.22774706647908 ,
1787.5897232339489 ,
1805.1255306401772 };
test(X);
test(Y);
std::copy(X.begin(),X.end(),std::ostream_iterator<double>(std::cout,"\t"));
std::cout<<std::endl;
std::copy(Y.begin(),Y.end(),std::ostream_iterator<double>(std::cout,"\t"));
return 0;
}
double realmod(double x, double y)
{
if (y == 0 )
return x;
else if ( x == y)
return 0.0;
else
return x - floor(x/y) *y;
}
void test(std::vector<double> &cornerX)
{
for (size_t i = 0; i < cornerX.size(); i++)
cornerX[i] = cornerX[i] + (1 - realmod(cornerX[i],2.0));
}

Newton Fractal generation

I wanted to write my own newton fractal generator.. It's using OpenCL... but that's not the problem.. my problem is that atm. only veerryy few pixels are converging.
So to explain what I've done so far:
I've selected a function I wanted to use: f(z)=z^4-1 (for testing purposes)
I've calculated the roots of this function: 1+0î, -1+0î, 0+1î, 0-1î
I've written a OpenCL Host and Kernel:
the kernel uses a struct with 4 doubles: re (real), im (imaginary), r (as abs), phi (as argument, polar angle or how you call it)
computes from resolution, zoom and global_work_id the "type" of the pixel and the intensity - where type is the root the newton method is converging to / whether it's diverging
Here's what I get rendered:
Here is the whole kernel:
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#define pi 3.14159265359
struct complex {
double im;
double re;
double r;
double phi;
};
struct complex createComplexFromPolar(double _r, double _phi){
struct complex t;
t.r = _r;
t.phi = _phi;
t.re = cos(t.phi)*t.r;
t.im = sin(t.phi)*t.r;
return t;
}
struct complex createComplexFromKarthes(double real, double imag){
struct complex t;
t.re = real;
t.im = imag;
t.phi = atan(imag / real);
t.r = sqrt(t.re*t.re + t.im*t.im);
return t;
}
struct complex recreateComplexFromKarthes(struct complex t){
return t = createComplexFromKarthes(t.re, t.im);
}
struct complex recreateComplexFromPolar(struct complex t){
return t = createComplexFromPolar(t.r, t.phi);
}
struct complex addComplex(const struct complex z, const struct complex c){
struct complex t;
t.re = c.re + z.re;
t.im = c.im + z.im;
return recreateComplexFromKarthes(t);
}
struct complex subComplex(const struct complex z, const struct complex c){
struct complex t;
t.re = z.re - c.re;
t.im = z.im - c.im;
return recreateComplexFromKarthes(t);
}
struct complex addComplexScalar(const struct complex z, const double n){
struct complex t;
t.re = z.re + n;
return recreateComplexFromKarthes(t);
}
struct complex subComplexScalar(const struct complex z, const double n){
struct complex t;
t.re = z.re - n;
return recreateComplexFromKarthes(t);
}
struct complex multComplexScalar(const struct complex z, const double n) {
struct complex t;
t.re = z.re * n;
t.im = z.im * n;
return recreateComplexFromKarthes(t);
}
struct complex multComplex(const struct complex z, const struct complex c) {
return createComplexFromPolar(z.r*c.r, z.phi + c.phi);
}
struct complex powComplex(const struct complex z, int i){
struct complex t = z;
for (int j = 0; j < i; j++){
t = multComplex(t, z);
}
return t;
}
struct complex divComplex(const struct complex z, const struct complex c) {
return createComplexFromPolar(z.r / c.r, z.phi - c.phi);
}
bool compComplex(const struct complex z, const struct complex c, float comp){
struct complex t = subComplex(z, c);
if (fabs(t.re) <= comp && fabs(t.im) <= comp)
return true;
return false;
}
__kernel void newtonFraktal(__global const int* res, __global const int* zoom, __global int* offset, __global const double* param, __global int* result, __global int* resType){
const int x = get_global_id(0) + offset[0];
const int y = get_global_id(1) + offset[1];
const int xRes = res[0];
const int yRes = res[1];
const double a = (x - (xRes / 2)) == 0 ? 0 : (double)(zoom[0] / (x - (double)(xRes / 2)));
const double b = (y - (yRes / 2)) == 0 ? 0 : (double)(zoom[1] / (y - (double)(yRes / 2)));
struct complex z = createComplexFromKarthes(a, b);
struct complex zo = z;
struct complex c = createComplexFromKarthes(param[0], param[1]);
struct complex x1 = createComplexFromKarthes(1,0);
struct complex x2 = createComplexFromKarthes(-1, 0);
struct complex x3 = createComplexFromKarthes(0, 1);
struct complex x4 = createComplexFromKarthes(0, -1);
resType[x + xRes * y] = 3;
int i = 0;
while (i < 30000 && fabs(z.r) < 10000){
z = subComplex(z, divComplex(subComplexScalar(powComplex(z, 4), 1), multComplexScalar(powComplex(z, 3), 4)));
i++;
if (compComplex(z, x1, 0.05)){
resType[x + xRes * y] = 0;
break;
} else if (compComplex(z, x2, 0.05)){
resType[x + xRes * y] = 1;
break;
} else if (compComplex(z, x3, 0.05)){
resType[x + xRes * y] = 2;
break;
}
}
if (fabs(z.r) >= 10000){
resType[x + xRes * y] = 4;
}
result[x + xRes * y] = i;
}
And here is the coloration of the image:
const int xRes = core->getXRes();
const int yRes = core->getYRes();
for (int y = 0; y < fraktal->getHeight(); y++){
for (int x = 0; x < fraktal->getWidth(); x++){
int conDiv = genCL->result[x + y * xRes];
int type = genCL->typeRes[x + y * xRes];
if (type == 0){
//converging to x1
fraktal->setPixel(x, y, 1*conDiv, 1*conDiv, 0, 1);
} else if (type == 1){
//converging to x2
fraktal->setPixel(x, y, 0, 0, 1*conDiv, 1);
} else if (type == 2){
//converging to x3
fraktal->setPixel(x, y, 0, 1*conDiv, 0, 1);
} else if (type == 3){
//diverging and interrupted by loop end
fraktal->setPixel(x, y, 1*conDiv, 0, 0, 1);
} else {
//diverging and interrupted by z.r > 10000
fraktal->setPixel(x, y, 1, 1, 1, 0.1*conDiv);
}
}
}
I had some mistakes in the complex number computations but I check everything today again and again.. I think they should be okay now.. but what else could be the reason that there are just this few start values converging? Did I do something wrong with newton's method?
Thanks for all your help!!
Well somewhat it really helped to run the code as normal C code.. as this makes Debugging easier: so the issue were some coding issues which I have been able to solve now.. for example my pow function was corrupted and when I added or subtracted I forgot to set the imaginary part to the temp complex number .. so here's my final OpenCL kernel:
#pragma OPENCL EXTENSION cl_khr_fp64 : enable
#define pi 3.14159265359
struct complex {
double im;
double re;
double r;
double phi;
};
struct complex createComplexFromPolar(double _r, double _phi){
struct complex t;
t.r = _r;
t.phi = _phi;
t.re = _r*cos(_phi);
t.im = _r*sin(_phi);
return t;
}
struct complex createComplexFromKarthes(double real, double imag){
struct complex t;
t.re = real;
t.im = imag;
t.phi = atan2(imag, real);
t.r = sqrt(t.re*t.re + t.im*t.im);
return t;
}
struct complex recreateComplexFromKarthes(struct complex t){
return createComplexFromKarthes(t.re, t.im);
}
struct complex recreateComplexFromPolar(struct complex t){
return createComplexFromPolar(t.r, t.phi);
}
struct complex addComplex(const struct complex z, const struct complex c){
return createComplexFromKarthes(c.re + z.re, c.im + z.im);
}
struct complex subComplex(const struct complex z, const struct complex c){
return createComplexFromKarthes(z.re - c.re, z.im - c.im);
}
struct complex addComplexScalar(const struct complex z, const double n){
return createComplexFromKarthes(z.re + n,z.im);
}
struct complex subComplexScalar(const struct complex z, const double n){
return createComplexFromKarthes(z.re - n, z.im);
}
struct complex multComplexScalar(const struct complex z, const double n){
return createComplexFromKarthes(z.re * n,z.im * n);
}
struct complex multComplex(const struct complex z, const struct complex c) {
return createComplexFromKarthes(z.re*c.re-z.im*c.im, z.re*c.im+z.im*c.re);
//return createComplexFromPolar(z.r*c.r, z.phi + c.phi);
}
struct complex powComplex(const struct complex z, int i){
struct complex t = z;
for (int j = 0; j < i-1; j++){
t = multComplex(t, z);
}
return t;
}
struct complex divComplex(const struct complex z, const struct complex c) {
return createComplexFromPolar(z.r / c.r, z.phi-c.phi);
}
bool compComplex(const struct complex z, const struct complex c, float comp){
if (fabs(z.re - c.re) <= comp && fabs(z.im - c.im) <= comp)
return true;
return false;
}
__kernel void newtonFraktal(__global const int* res, __global const int* zoom, __global int* offset, __global const double* param, __global int* result, __global int* resType){
const int x = get_global_id(0) + offset[0];
const int y = get_global_id(1) + offset[1];
const int xRes = res[0];
const int yRes = res[1];
const double a = (x - (xRes / 2)) == 0 ? 0 : (double)((x - (double)(xRes / 2)) / zoom[0]);
const double b = (y - (yRes / 2)) == 0 ? 0 : (double)((y - (double)(yRes / 2)) / zoom[1]);
struct complex z = createComplexFromKarthes(a, b);
//struct complex c = createComplexFromKarthes(param[0], param[1]);
struct complex x1 = createComplexFromKarthes(0.7071068, 0.7071068);
struct complex x2 = createComplexFromKarthes(0.7071068, -0.7071068);
struct complex x3 = createComplexFromKarthes(-0.7071068, 0.7071068);
struct complex x4 = createComplexFromKarthes(-0.7071068, -0.7071068);
struct complex f, d;
resType[x + xRes * y] = 11;
int i = 0;
while (i < 6000 && fabs(z.r) < 10000){
f = addComplexScalar(powComplex(z, 4), 1);
d = multComplexScalar(powComplex(z, 3), 3);
z = subComplex(z, divComplex(f, d));
i++;
if (compComplex(z, x1, 0.0000001)){
resType[x + xRes * y] = 0;
break;
} else if (compComplex(z, x2, 0.0000001)){
resType[x + xRes * y] = 1;
break;
} else if (compComplex(z, x3, 0.0000001)){
resType[x + xRes * y] = 2;
break;
} else if (compComplex(z, x4, 0.0000001)){
resType[x + xRes * y] = 3;
break;
}
}
if (fabs(z.r) >= 1000){
resType[x + xRes * y] = 10;
}
result[x + xRes * y] = i;
}
hope it might help someone someday.. :)