How to add final iteration to while loop? - c++

I have a function that runs a while loop:
void run_while_loop(const float x_d, const float x_max)
{
float x = 0;
while ( x < x_max ){
// do something
x += x_d;
}
}
It is assumed that x_d < x_max.
I want to change the function so that it adds an iteration at the end with x = x_max. If the function were called as:
run_while_loop(1, 3.123)
then I want the while loop to iterate for x = 0, 1, 2, 3, and 3.123.
What is an elegant way to code this?
Thank you very much.

Wrap the code that is inside the while loop into a function, and call that function after the while-loop.
void run_while_loop(const float x_d, const float x_max)
{
float x = 0;
while ( x < x_max ){
do_something_function(parameters...);
x += x_d;
}
do_something_function(final_parameters...);
}

Related

How do I implement the numerical differentiation (f'(x) = f(x+h)-f(x)/ h

2nd task:
For a function f : R^n → R the gradient at a point ~x ∈ R^n is to be calculated:
- Implement a function
CMyVector gradient(CMyVector x, double (*function)(CMyVector x)),
which is given in the first parameter the location ~x and in the second parameter the function f as function pointer in the second parameter, and which calculates the gradient ~g = grad f(~x) numerically
by
gi = f(x1, . . . , xi-1, xi + h, xi+1 . . . , xn) - f(x1, . . . , xn)/h
to fixed h = 10^-8.
My currently written program:
Header
#pragma once
#include <vector>
#include <math.h>
class CMyVektor
{
private:
/* data */
int Dimension = 0;
std::vector<double>Vector;
public:
CMyVektor();
~CMyVektor();
//Public Method
void set_Dimension(int Dimension /* Aktuelle Dim*/);
void set_specified_Value(int index, int Value);
double get_specified_Value(int key);
int get_Vector_Dimension();
int get_length_Vektor();
double& operator [](int index);
string umwandlung()
};
CMyVektor::CMyVektor(/* args */)
{
Vector.resize(0, 0);
}
CMyVektor::~CMyVektor()
{
for (size_t i = 0; i < Vector.size(); i++)
{
delete Vector[i];
}
}
void CMyVektor::set_Dimension(int Dimension /* Aktuelle Dim*/)
{
Vector.resize(Dimension);
};
void CMyVektor::set_specified_Value(int index, int Value)
{
if (Vector.empty())
{
Vector.push_back(Value);
}
else {
Vector[index] = Value;
}
};
double CMyVektor::get_specified_Value(int key)
{
// vom intervall anfang - ende des Vectors
for (unsigned i = 0; i < Vector.size(); i++)
{
if (Vector[i] == key) {
return Vector[i];
}
}
};
int CMyVektor::get_Vector_Dimension()
{
return Vector.size();
};
// Berechnet den Betrag "länge" eines Vectors.
int CMyVektor::get_length_Vektor()
{
int length = 0;
for (size_t i = 0; i < Vector.size(); i++)
{
length += Vector[i]^2
}
return sqrt(length);
}
// [] Operator überladen
double& CMyVektor::operator [](int index)
{
return Vector[index];
}
main.cpp
#include <iostream>
#include "ClassVektor.h"
using namespace std;
CMyVektor operator+(CMyVektor a, CMyVektor b);
CMyVektor operator*(double lambda, CMyVektor a);
CMyVektor gradient(CMyVektor x, double (*funktion)(CMyVektor x));
int main() {
CMyVektor V1;
CMyVektor V2;
CMyVektor C;
C.set_Dimension(V1.get_length_Vector());
C= V1 + V2;
std::cout << "Addition : "<< "(";;
for (int i = 0; i < C.get_length_Vector(); i++)
{
std::cout << C[i] << " ";
}
std::cout << ")" << endl;
C = lamda * C;
std::cout << "Skalarprodukt: "<< C[0]<< " ";
}
// Vector Addition
CMyVektor operator+(CMyVektor a, CMyVektor b)
{
int ai = 0, bi = 0;
int counter = 0;
CMyVektor c;
c.set_Dimension(a.get_length_Vector());
// Wenn Dimension Gleich dann addition
if (a.get_length_Vector() == b.get_length_Vector())
{
while (counter < a.get_length_Vector())
{
c[counter] = a[ai] + b[bi];
counter++;
}
return c;
}
}
//Berechnet das Skalarprodukt
CMyVektor operator*(double lambda, CMyVektor a)
{
CMyVektor c;
c.set_Dimension(1);
for (unsigned i = 0; i < a.get_length_Vector(); i++)
{
c[0] += lambda * a[i];
}
return c;
}
/*
* Differenzenquotient : (F(x0+h)+F'(x0)) / h
* Erster Parameter die Stelle X - Zweiter Parameter die Funktion
* Bestimmt numerisch den Gradienten.
*/
CMyVektor gradient(CMyVektor x, double (*funktion)(CMyVektor x))
{
}
My problem now is that I don't quite know how to deal with the
CMyVector gradient(CMyVector x, double (*function)(CMyVector x))
function and how to define a function that corresponds to it.
I hope that it is enough information. Many thanks.
The function parameter is the f in the difference formula. It takes a CMyVector parameter x and returns a double value. You need to supply a function parameter name. I'll assume func for now.
I don't see a parameter for h. Are you going to pass a single small value into the gradient function or assume a constant?
The parameter x is a vector. Will you add a constant h to each element?
This function specification is a mess.
Function returns a double. How do you plan to turn that into a vector?
No wonder you're confused. I am.
Are you trying to do something like this?
You are given a function signature
CMyVector gradient(CMyVector x, double (*function)(CMyVector x))
Without knowing the exact definition I will assume, that at least the basic numerical vector operations are defined. That means, that the following statements compile:
CMyVector x {2.,5.,7.};
CMyVector y {1.,7.,4.};
CMyVector z {0.,0.,0.};
double a = 0.;
// vector addition and assigment
z = x + y;
// vector scalar multiplication and division
z = z * a;
z = x / 0.1;
Also we need to know the dimension of the CMyVector class. I assumed and will continue to do so that it is three dimensional.
The next step is to understand the function signature. You get two parameters. The first one denotes the point, at which you are supposed to calculate the gradient. The second is a pointer to the function f in your formula. You do not know it, but can call it on a vector from within your gradient function definition. That means, inside of the definition you can do something like
double f_at_x = function(x);
and the f_at_x will hold the value f(x) after that operation.
Armed with this, we can try to implement the formula, that you mentioned in the question title:
CMyVector gradient(CMyVector x, double (*function)(CMyVector x)) {
double h = 0.001;
// calculate first element of the gradient
CMyVector e1 {1.0, 0.0, 0.0};
double result1 = ( function(x + e1*h) - function(x) )/h;
// calculate second element of the gradient
CMyVector e2 {0.0, 1.0, 0.0};
double result2 = ( function(x + e2*h) - function(x) )/h;
// calculate third element of the gradient
CMyVector e3 {0.0, 0.0, 1.0};
double result3 = ( function(x + e3*h) - function(x) )/h;
// return the result
return CMyVector {result1, result2, result3};
}
There are several thing worth to mention in this code. First and most important I have chosen h = 0.001. This may like a very arbitrary choice, but the choice of the step size will very much impact the precision of your result. You can find a whole lot of discussion about that topic here. I took the same value that according to that wikipedia page a lot of handheld calculators use internally. That might not be the best choice for the floating point precision of your processor, but should be a fair one to start with.
Secondly the code looks very ugly for an advanced programmer. We are doing almost the same thing for each of the three dimensions. Ususally you would like to do that in a for loop. The exact way of how this is done depends on how the CMyVector type is defined.
Since the CMyVektor is just rewritting the valarray container, I will directly use the valarray:
#include <iostream>
#include <valarray>
using namespace std;
using CMyVektor = valarray<double>;
CMyVektor gradient(CMyVektor x, double (*funktion)(CMyVektor x));
const double h = 0.00000001;
int main()
{
// sum(x_i^2 + x_i)--> gradient: 2*x_i + 1
auto fun = [](CMyVektor x) {return (x*x + x).sum();};
CMyVektor d = gradient(CMyVektor{1,2,3,4,5}, fun);
for (auto i: d) cout << i<<' ';
return 0;
}
CMyVektor gradient(CMyVektor x, double (*funktion)(CMyVektor x)){
CMyVektor grads(x.size());
CMyVektor pos(x.size());
for (int i = 0; i<x.size(); i++){
pos[i] = 1;
grads[i] = (funktion(x + h * pos) - funktion(x))/ h;
pos[i] = 0;
}
return grads;
}
The prints out 3 5 7 9 11 which is what is expected from the given function and the given location

Making a multiple versions of a Object

I'm a student instructed to make a doodle jump replica with ogre3d.
I have a function which should make a panel on screen with a designated shape and location so now I wish to make a for loop that will make multiple (up to 10) and a random value that'll set each of them somewhere different on x,y,z.
void PlatformManager::CreatePanelDoodle( float x, float y, float z){
Plane plane3(Vector3::UNIT_Y, 0);
MeshManager::getSingleton().createPlane(
"Paddle2", RGN_DEFAULT,
plane3,
20, 5, 20, 20,
true,
1, 5, 5,
Vector3::UNIT_Z);
Entity* groundEntity3 = scnMgr->createEntity("Paddle2");
SceneNode* Paddlenode2 = scnMgr->getRootSceneNode()->createChildSceneNode();
Paddlenode2->setPosition(Ogre::Vector3( x, y, z));
Paddlenode2->attachObject(groundEntity3);
groundEntity3->setCastShadows(false);
}
and this is for attempting to make multiple objects in random space
point plat[20];
float pX;
float pY;
for (int i = 0; i < 10; i++)
{
plat[i].x = rand() % 50;
plat[i].y = rand() % 30;
float pX = plat[i].x;
float pY = plat[i].y;
}
for (int i = 0; i < 10; i++)
{
PlatformManager Panels = new PlatformManager->CreatePanelDoodle(pX, 0, pY);
}
The problem is with the error in the for loop creation "No suitable constructor exists to convert void to "platform manager"
I've tried simply adding the constructor into the for loop, and not using the loop at all. Whats going wrong?
There are some problems in your second code snippet:
You are using uninitialized variables float pX; and float pY;
You are shadowing variables with float pX = plat[i].x; and float pY = plat[i].y;
You are creating multiple random values but you are not using them
You are trying to apply the new operator on a void function
You are trying to store that result in a variable
You can solve the problems with
// Remove this block, you don't use the variables
/*
point plat[20]; // You don't use this array
float pX; // You use it uninitialized
float pY; // You use it uninitialized
for (int i = 0; i < 10; i++) {
plat[i].x = rand() % 50;
plat[i].y = rand() % 30;
float pX = plat[i].x; // You don't use this variable
float pY = plat[i].y; // You don't use this variable
}
*/
for (int i = 0; i < 10; ++i) {
PlatformManager->CreatePanelDoodle(static_cast<float>(rand() % 50), 0, static_cast<float>(rand() % 30));
}

Stack around the variable 'Yarray' was corrupted

When I declare an array to store the Y values of each coordinate, define its values then use each of the element values to send into a rounding function, i obtain the error 'Run-Time Check Failure #2 - Stack around the variable 'Yarray; was corrupted. The output is mostly what is expected although i'm wondering why this is happening and if i can mitigate it, cheers.
void EquationElement::getPolynomial(int * values)
{
//Takes in coefficients to calculate Y values for a polynomial//
double size = 40;
double step = 1;
int Yarray[40];
int third = *values;
int second = *(values + 1);
int first = *(values + 2);
int constant = *(values + 3);
double x, Yvalue;
for (int i = 0; i < size + size + 1; ++i) {
x = (i - (size));
x = x * step;
double Y = (third *(x*x*x)) + (second *(x*x)) + (first * (x))
Yvalue = Y / step;
Yarray[i] = int(round(Yvalue)); //<-MAIN ISSUE HERE?//
cout << Yarray[i] << endl;
}
}
double EquationElement::round(double number)
{
return number < 0.0 ? ceil(number - 0.5) : floor(number + 0.5);
// if n<0 then ceil(n-0.5) else if >0 floor(n+0.5) ceil to round up floor to round down
}
// values could be null, you should check that
// if instead of int* values, you took std::vector<int>& values
// You know besides the values, the quantity of them
void EquationElement::getPolynomial(const int* values)
{
//Takes in coefficients to calculate Y values for a polynomial//
static const int size = 40; // No reason for size to be double
static const int step = 1; // No reason for step to be double
int Yarray[2*size+1]{}; // 40 will not do {} makes them initialized to zero with C++11 onwards
int third = values[0];
int second = values[1]; // avoid pointer arithmetic
int first = values[2]; // [] will work with std::vector and is clearer
int constant = values[3]; // Values should point at least to 4 numbers; responsability goes to caller
for (int i = 0; i < 2*size + 1; ++i) {
double x = (i - (size)) * step; // x goes from -40 to 40
double Y = (third *(x*x*x)) + (second *(x*x)) + (first * (x)) + constant;
// Seems unnatural that x^1 is values and x^3 is values+2, being constant at values+3
double Yvalue= Y / step; // as x and Yvalue will not be used outside the loop, no need to declare them there
Yarray[i] = int(round(Yvalue)); //<-MAIN ISSUE HERE?//
// Yep, big issue, i goes from 0 to size*2; you need size+size+1 elements
cout << Yarray[i] << endl;
}
}
Instead of
void EquationElement::getPolynomial(const int* values)
You could also declare
void EquationElement::getPolynomial(const int (&values)[4])
Which means that now you need to call it with a pointer to 4 elements; no more and no less.
Also, with std::vector:
void EquationElement::getPolynomial(const std::vector<int>& values)
{
//Takes in coefficients to calculate Y values for a polynomial//
static const int size = 40; // No reason for size to be double
static const int step = 1; // No reason for step to be double
std::vector<int> Yarray;
Yarray.reserve(2*size+1); // This is just optimization. Yarran *Can* grow above this limit.
int third = values[0];
int second = values[1]; // avoid pointer arithmetic
int first = values[2]; // [] will work with std::vector and is clearer
int constant = values[3]; // Values should point at least to 4 numbers; responsability goes to caller
for (int i = 0; i < 2*size + 1; ++i) {
double x = (i - (size)) * step; // x goes from -40 to 40
double Y = (third *(x*x*x)) + (second *(x*x)) + (first * (x)) + constant;
// Seems unnatural that x^1 is values and x^3 is values+2, being constant at values+3
double Yvalue= Y / step; // as x and Yvalue will not be used outside the loop, no need to declare them there
Yarray.push_back(int(round(Yvalue)));
cout << Yarray.back() << endl;
}
}

Integration with variable limits

I need to evaluate a double integral where the inner upper Bound is variable:
integral2 between -5 and 5 ( integral1 between 0 and y f(x)dx )dy.
I'm stuck in the calculation of the outer loop which is dependent on the inner loop. My code runs for a really long time but returns zero.
How can i calculate a integral with variable limits?
First I created a function doubleIntegrate. In the first place the function holds the arrays with coefficients for the trapeziodal rule.
double NumericIntegrationDouble::doubleIntegrate(double (*doubleFunc
(const double &x), double dy, const double &innerLowBound, const double
&outerLowBound)
{
double innerValue = 0.0;
double outerValue = 0.0;
// arrays which store function values for the inner (X) and the outer (Y) integration loop
// vector filled with coefficients for the inner poop (trapezoidal rule)
std::vector<double> vecCoeffsX(numberOfIntervalsDouble+1, 2);
vecCoeffsX[0] = 1; // fist coeff = 1
vecCoeffsX[vecCoeffsX.size()-1] = 1; // last coeff = 1
std::vector<double> funcValuesX(numberOfIntervalsDouble+1);
// vector filled with coefficients for the inner poop (trapezoidal rule)
std::vector<double> vecCoeffsY(numberOfIntervalsDouble+1, 2);
vecCoeffsY[0] = 1; // same as above
vecCoeffsY[vecCoeffsY.size()-1] = 1; // same as above
std::vector<double> funcValuesY(numberOfIntervalsDouble+1)
// Then i created a loop in a loop where dy and dy stands for step size of integration. The variables xi and yi stand for the current x and y value.
// outer integration loop dy
for(int i=0; i<=numberOfIntervalsDouble; i++)
{
double yi = outerLowBound + dy*i;
funcValuesY[i] = (*doubleFunc)(yi);
// inner integration loop dx
for(int j=0; j<=numberOfIntervalsDouble; j++)
{
double dx = abs(yi - innerLowBound) / (double)numberOfIntervalsDouble;
double xi = innerLowBound + j*dx;
funcValuesX[j] = (*doubleFunc)(xi);
double multValueX = std::inner_product(vecCoeffsX.begin(), vecCoeffsX.end(), funcValuesX.begin(), 0.0);
double innerValue = 0.5 * dx * multValueX;
suminnerValue = suminnerValue + innerValue;
}
//auto multValueY = std::inner_product(vecCoeffsY.begin(), vecCoeffsY.end(), funcValuesY.begin(), 0.0);
outerValue = 0.5 * dy * suminnerValue;
}
return outerValue;
}

C++ error: Double and 3d Vector

I got an error when compile the below code saying that "called object type 'double' is not a function or function pointer". Because 'position' is a 3d vector, so I was trying to access each element of the vector.
int k=1;
int m=1;
double x, y, z;
x=position.x;
y=position.y;
z=position.z;
for (int j = 3; j < 1000 ; j++)
{
x(j) = 2 * x(j-1) - x(j-2) + (delta_t * delta_t * (-1.0*k/m) * x(j-1));
}
You'll actually have to keep track of x(j), x(j-1), and x(j-2) all as separate variables (using the syntax x(j) is akin to calling a function x() with argument j, which is not what you want).
Try:
double xj, xj_m1, xj_m2;
xj_m1 = position.x;
xj_m2 = position.x;
for (int j = 3; j < 1000 ; j++) {
xj = 2 * xj_m1 - xj_m2 + (delta_t * delta_t * (-1.0*k/m) * xj_m1);
//Update xj_m2 and xj_m1 for the next iteration
xj_m2 = xj_m1;
xj_m1 = xj;
}
When you do it:
x=position.x;
You expect that position.x is an array?
To access to an element in a vector, you can use the [] operator:
std::vector<int> myIntVector = { 1, 2, 3 };
int i = myIntVector[0]; // i = 1 because myIntVector[0] is the first element of myIntVector
The variable position looks like a coordinate vector, so it's not an array, it's just a class / struct like this:
struct Vector3
{
double x, y, z;
};
In other words, position.x is just a number.