Program ignoring condition? - c++

In my code, I'm trying to prevent circles from overlapping so I specified it as a condition on the distance between the centres of the circles but it seems to not work all the time
as you can see :
could it be some kind of numerical precision rounding problem ?
Here is the relevant code (I can post the whole code if needed):
const double win_size = 800;
const double L = 50e-9; //box size (m)
const double k = 1.38e-23; // Boltzmann constant = 1.38e-23 J/K
const double R = 1.6e-10*30; //N2 radius = 1.6e-10 m
const double m = 4.65e-26; //N2 mass = 4.65e-26 kg
struct parameters{
double x;
double y;
double v_x;
double v_y;
};
bool empty_space(double x, double y, struct parameters gas[], int N, int i){
if (i == 0) return true;
for (int i = 0; i<N; i++){
if (pow(x-gas[i].x,2) + pow(y-gas[i].y,2) <= 4*R*R){
cout << gas[i].x << " " << gas[i].y << endl;
return false;
}
}
return true;
}
void initialize(struct parameters gas[], int N, double T){ // Sets initial conditions (velocity depends on temperature)
int tries = 0;
double x, y;
for (int i=0; i<N; i++){
if (tries == 10000){
cout << "Couldn't fit " << N << " molecules in the box, aborting simulation... " << endl;
exit(1);
}
x = R + (L - 2*R)*rand()/RAND_MAX;
y = R + (L - 2*R)*rand()/RAND_MAX;
if (empty_space(x,y,gas,N,i)){
gas[i].x = x;
gas[i].y = y;
}
else {
i--;
tries++;
}
gas[i].v_x = sqrt(2*k*T/m)*(1-2.0*rand()/RAND_MAX);
gas[i].v_y = (2*(rand()%2) - 1)*sqrt(2*k*T/m - pow(gas[i].v_x, 2));
}
}
void draw(int window, struct parameters gas[], int N, int automatic){
g2_pen(window,g2_ink(window,0.8,0.3,0.4));
for (int i=0; i<N; i++){
g2_circle(window,gas[i].x*win_size/L,gas[i].y*win_size/L,R*win_size/L);
}
g2_flush(window);
usleep(10000);
g2_pen(window,0);
g2_filled_rectangle(window,0,0,win_size,win_size);
if (!automatic) getchar();
}

The first debugging step is to print the coordinates of the circles that have clashed somehow, then see what the "distance" function is returning for their centers. My guess it it's somehow a rounding problem but this seems to be what you need to do next.

Related

Cross the yard without getting wet

Here is the question:
There is a house with a backyard which is square bounded by
coordinates (0,0) in the southwest to (1000,1000) in
the northeast. In this yard there are a number of water sprinklers
placed to keep the lawn soaked in the middle of the summer. However,
it might or might not be possible to cross the yard without getting
soaked and without leaving the yard?
Input The input starts with a line containing an integer 1≤n≤1000, the
number of water sprinklers. A line follows for each sprinkler,
containing three integers: the (x,y)(x,y) location of the sprinkler
(0≤x,y,≤10000) and its range r (1≤r≤1000). The sprinklers will soak
anybody passing strictly within the range of the sprinkler (i.e.,
within distance strictly less than r).
The house is located on the west side (x=0) and a path is needed to
the east side of the yard (x=1000).
Output If you can find a path through the yard, output four real
numbers, separated by spaces, rounded to two digits after the decimal
place. These should be the coordinates at which you may enter and
leave the yard, respectively. If you can enter and leave at several
places, give the results with the highest y. If there is no way to get
through the yard without getting soaked, print a line containing
“IMPOSSIBLE”.
Sample Input
3
500 500 499
0 0 999
1000 1000 200
Sample output
0.00 1000.00 1000.00 800.00
Here is my thought process:
Define circle objects with x,y,r and write a function to determine if a given point is wet or not(inside the circle or not) on the circumference is not wet btw.
class circle {
int h;
int k;
int r;
public:
circle();
circle(int h, int k, int r){
this->h = h;
this->k = k;
this->r = r;
};
bool iswet(pair<int,int>* p){
if (pow(this->r - 0.001, 2) > (pow(p->first - this->h, 2) +
pow(p->second - this->k, 2) ) ) {
return true;
}
else
return false;
};
Then implement a depth first search, prioritizing to go up and right whenever possible.
However since circles are not guaranteed to be pass on integer coordinates an the result is expected in floats with double precision (xxx.xx). So if we keep everything in integers the grid suddenly becomes 100,000 x 100,000 which is way too big. Also the time limit is 1 sec.
So I thought ok lets stick to 1000x1000 and work with floats instead. Loop over int coordinates and whenever I hit a sprinkle just snap in the perimeter of the circle since we are safe in the perimeter. But in that case could not figure out how DFS work.
Here is the latest trial
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <deque>
#include <utility>
#include <unordered_set>
#include <iomanip>
using namespace std;
const int MAXY = 1e3;
const int MAXX = 1e3;
const int MINY = 0;
const int MINX = 0;
struct pair_hash {
inline std::size_t operator()(const std::pair<int,int> & v) const {
return v.first*31+v.second;
}
};
class circle {
int h;
int k;
int r;
public:
circle();
circle(int h, int k, int r){
this->h = h;
this->k = k;
this->r = r;
};
bool iswet(pair<float,float>* p){
if (pow(this->r - 0.001, 2) > (pow(p->first - this->h, 2) + pow(p->second - this->k, 2) ) ) {
this->closest_pair(p);
return true;
}
else
return false;
};
void closest_pair(pair<float,float>* p){
float vx = p->first - this->h;
float vy = p->second - this->k;
float magv = sqrt(vx * vx + vy * vy);
p->first = this->h + vx / magv * this->r;
p->second = this->k + vy / magv * this->r;
}
};
static bool test_sprinkles(vector<circle> &sprinkles, pair<float,float>* p){
for (int k = 0; k < sprinkles.size(); k++)
if (sprinkles[k].iswet(p)) return false;
return true;
}
int main(){
int n; // number of sprinkles
while (cin >> n){
vector<circle> sprinkles_array;
sprinkles_array.reserve(n);
int h, k, r;
while (n--){
cin >> h >> k >> r;
sprinkles_array.push_back(circle(h, k, r));
}/* code */
pair<float,float> enter = make_pair(0, MAXY);
deque<pair<float,float>> mystack;
mystack.push_back(enter);
pair<float,float>* cp;
bool found = false;
unordered_set<pair<float, float>, pair_hash> visited;
while (!mystack.empty()){
cp = &mystack.back();
if (cp->first == MAXX) {
found = true;
break;
}
visited.insert(*cp);
if (cp->second > MAXY || cp->second < MINY || cp ->first < MINX ) {
visited.insert(*cp);
mystack.pop_back();
continue;
}
if (!test_sprinkles(sprinkles_array,cp)) {
continue;
}
pair<int,int> newpair = make_pair(cp->first, cp->second + 1);
if (visited.find(newpair) == visited.end()) {
mystack.push_back(newpair);
continue;
}
else visited.insert(newpair);
newpair = make_pair(cp->first + 1 , cp->second);
if (visited.find(newpair) == visited.end()) {
mystack.push_back(newpair);
continue;
}
else visited.insert(newpair);
newpair = make_pair(cp->first, cp->second - 1);
if (visited.find(newpair) == visited.end()) {
mystack.push_back(newpair);
continue;
}
else visited.insert(newpair);
newpair = make_pair(cp->first - 1, cp->second);
if (visited.find(newpair) == visited.end()) {
mystack.push_back(newpair);
continue;
}
else visited.insert(newpair);
mystack.pop_back();
}
cout << setprecision(2);
cout << fixed;
if (found){
double xin = mystack.front().first;
double yin = mystack.front().second;
pair <float, float> p = mystack.back();
p.second++;
for (int k = 0; k < sprinkles_array.size(); k++)
if (sprinkles_array[k].iswet(&p)) break;
double xout = p.first;
double yout = p.second;
cout << xin << " " << yin << " " << xout << " " << yout << endl;
}
else
{
cout << "IMPOSSIBLE" << endl;
}
}
}
Yes #JosephIreland is right. Solved it with grouping intersecting (not touching) circles. Then these groups have maxy and min y coordinates. If it exceeds the yard miny and maxy the way is blocked.
Then these groups also have upper and lower intersection points with x=0 and x=1000 lines. If the upper points are larger than the yard maxy then the maximum entry/exit points are lower entery points.
#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <utility>
#include <iomanip>
using namespace std;
const int MAXY = 1e3;
const int MAXX = 1e3;
const int MINY = 0;
const int MINX = 0;
struct circle {
int h;
int k;
int r;
float maxy;
float miny;
circle();
circle(int h, int k, int r){
this->h = h;
this->k = k;
this->r = r;
this->miny = this->k - r;
this->maxy = this->k + r;
};
};
struct group {
float maxy = -1;
float miny = -1;
vector<circle*> circles;
float upper_endy = -1;
float upper_starty = -1;
float lower_endy = -1;
float lower_starty = -1;
void add_circle(circle& c){
if ((c.maxy > this->maxy) || this->circles.empty() ) this->maxy = c.maxy;
if ((c.miny < this->miny) || this->circles.empty() ) this->miny = c.miny;
this->circles.push_back(&c);
// find where it crosses x=minx and x= maxx
float root = sqrt(pow(c.r, 2) - pow(MINX - c.h, 2));
float y1 = root + c.k;
float y2 = -root + c.k;
if (y1 > this->upper_starty) this->upper_starty = y1;
if (y2 > this->lower_starty) this->lower_starty = y2;
root = sqrt(pow(c.r, 2) - pow(MAXX - c.h, 2));
y1 = root + c.k;
y2 = -root + c.k;
if (y1 > this->upper_endy) this->upper_endy = y1;
if (y2 > this->lower_endy) this->lower_endy = y2;
};
bool does_intersect(circle& c1){
for(circle* c2 : circles){
float dist = sqrt(pow(c1.h - c2->h,2)) + sqrt(pow(c1.k - c2->k,2));
(dist < (c1.r + c2->r)) ? true : false;
};
};
};
int main(){
int n; // number of sprinkles
while (cin >> n){
vector<circle> sprinkles_array;
sprinkles_array.reserve(n);
int h, k, r;
while (n--){
cin >> h >> k >> r;
sprinkles_array.push_back(circle(h, k, r));
}/* code */
vector<group> groups;
group newgroup;
newgroup.add_circle(sprinkles_array[0]);
groups.push_back(newgroup);
for (int i = 1; i < sprinkles_array.size(); i++){
bool no_group = true;
for (group g:groups){
if (g.does_intersect(sprinkles_array[i])){
g.add_circle(sprinkles_array[i]);
no_group = false;
break;
}
}
if (no_group) {
group newgroup;
newgroup.add_circle(sprinkles_array[i]);
groups.push_back(newgroup);
}
}
float entery = MAXY;
float exity = MAXY;
bool found = true;
for (group g : groups){
if ((g.miny < MINY) && (g.maxy > MAXY)){
found = false;
break;
}
if (g.upper_starty > entery)
entery = g.lower_starty;
if (g.upper_endy > exity)
exity = g.lower_endy;
}
cout << setprecision(2);
cout << fixed;
if (found){
cout << float(MINX) << " " << entery << " " << float(MAXX) << " " << exity << endl;
}
else
{
cout << "IMPOSSIBLE" << endl;
}
}
}

Matrix inversion slower using threads

I made a function that makes the inverse and then another multithreaded, as long I have to make inverse of arrays >2000 x 2000.
A 1000x1000 array unthreated takes 2.5 seconds (on a i5-4460 4 cores 2.9ghz)
and multithreaded takes 7.25 seconds
I placed the multithreads in the part that most time consumption is taken. Whai is wrong?
Is due vectors are used instead of 2 dimensions arrays?
This is the minimum code to test both versions:
#include<iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
#include <chrono>
#include <thread>
const int NUCLEOS = 8;
#ifdef __linux__
#include <unistd.h> //usleep()
typedef std::chrono::system_clock t_clock; //try to use high_resolution_clock on new linux x64 computer!
#else
typedef std::chrono::high_resolution_clock t_clock;
#pragma warning(disable:4996)
#endif
using namespace std;
std::chrono::time_point<t_clock> start_time, stop_time = start_time; char null_char = '\0';
void timer(char *title = 0, int data_size = 1) { stop_time = t_clock::now(); double us = (double)chrono::duration_cast<chrono::microseconds>(stop_time - start_time).count(); if (title) printf("%s time = %7lgms = %7lg MOPs\n", title, (double)us*1e-3, (double)data_size / us); start_time = t_clock::now(); }
//makes columns 0
void colum_zero(vector< vector<double> > &x, vector< vector<double> > &y, int pos0, int pos1,int dim, int ord);
//returns inverse of x, x is not modified, not threaded
vector< vector<double> > inverse(vector< vector<double> > x)
{
if (x.size() != x[0].size())
{
cout << "ERROR on inverse() not square array" << endl; getchar(); return{};//returns a null
}
size_t dim = x.size();
int i, j, ord;
vector< vector<double> > y(dim,vector<double>(dim,0));//initializes output = 0
//init_2Dvector(y, dim, dim);
//1. Unity array y:
for (i = 0; i < dim; i++)
{
y[i][i] = 1.0;
}
double diagon, coef;
double *ptrx, *ptry, *ptrx2, *ptry2;
for (ord = 0; ord<dim; ord++)
{
//2 Hacemos diagonal de x =1
int i2;
if (fabs(x[ord][ord])<1e-15) //If that element is 0, a line that contains a non zero is added
{
for (i2 = ord + 1; i2<dim; i2++)
{
if (fabs(x[i2][ord])>1e-15) break;
}
if (i2 >= dim)
return{};//error, returns null
for (i = 0; i<dim; i++)//added a line without 0
{
x[ord][i] += x[i2][i];
y[ord][i] += y[i2][i];
}
}
diagon = 1.0/x[ord][ord];
ptry = &y[ord][0];
ptrx = &x[ord][0];
for (i = 0; i < dim; i++)
{
*ptry++ *= diagon;
*ptrx++ *= diagon;
}
//uses the same function but not threaded:
colum_zero(x,y,0,dim,dim,ord);
}//end ord
return y;
}
//threaded version
vector< vector<double> > inverse_th(vector< vector<double> > x)
{
if (x.size() != x[0].size())
{
cout << "ERROR on inverse() not square array" << endl; getchar(); return{};//returns a null
}
int dim = (int) x.size();
int i, ord;
vector< vector<double> > y(dim, vector<double>(dim, 0));//initializes output = 0
//init_2Dvector(y, dim, dim);
//1. Unity array y:
for (i = 0; i < dim; i++)
{
y[i][i] = 1.0;
}
std::thread tarea[NUCLEOS];
double diagon;
double *ptrx, *ptry;// , *ptrx2, *ptry2;
for (ord = 0; ord<dim; ord++)
{
//2 Hacemos diagonal de x =1
int i2;
if (fabs(x[ord][ord])<1e-15) //If a diagonal element=0 it is added a column that is not 0 the diagonal element
{
for (i2 = ord + 1; i2<dim; i2++)
{
if (fabs(x[i2][ord])>1e-15) break;
}
if (i2 >= dim)
return{};//error, returns null
for (i = 0; i<dim; i++)//It is looked for a line without zero to be added to make the number a non zero one to avoid later divide by 0
{
x[ord][i] += x[i2][i];
y[ord][i] += y[i2][i];
}
}
diagon = 1.0 / x[ord][ord];
ptry = &y[ord][0];
ptrx = &x[ord][0];
for (i = 0; i < dim; i++)
{
*ptry++ *= diagon;
*ptrx++ *= diagon;
}
int pos0 = 0, N1 = dim;//initial array position
if ((N1<1) || (N1>5000))
{
cout << "It is detected out than 1-5000 simulations points=" << N1 << " ABORT or press enter to continue" << endl; getchar();
}
//cout << "Initiation of " << NUCLEOS << " threads" << endl;
for (int thread = 0; thread<NUCLEOS; thread++)
{
int pos1 = (int)((thread + 1)*N1 / NUCLEOS);//next position
tarea[thread] = std::thread(colum_zero, std::ref(x), std::ref(y), pos0, pos1, dim, ord);//ojo, coil current=1!!!!!!!!!!!!!!!!!!
pos0 = pos1;//next thread will work at next point
}
for (int thread = 0; thread<NUCLEOS; thread++)
{
tarea[thread].join();
//cout << "Thread num: " << thread << " end\n";
}
}//end ord
return y;
}
//makes columns 0
void colum_zero(vector< vector<double> > &x, vector< vector<double> > &y, int pos0, int pos1,int dim, int ord)
{
double coef;
double *ptrx, *ptry, *ptrx2, *ptry2;
//Hacemos '0' la columna ord salvo elemento diagonal:
for (int i = pos0; i<pos1; i++)//Begin to end for every thread
{
if (i == ord) continue;
coef = x[i][ord];//element to make 0
if (fabs(coef)<1e-15) continue; //If already zero, it is avoided
ptry = &y[i][0];
ptry2 = &y[ord][0];
ptrx = &x[i][0];
ptrx2 = &x[ord][0];
for (int j = 0; j < dim; j++)
{
*ptry++ = *ptry - coef * (*ptry2++);//1ª matriz
*ptrx++ = *ptrx - coef * (*ptrx2++);//2ª matriz
}
}
}
void test_6_inverse(int dim)
{
vector< vector<double> > vec1(dim, vector<double>(dim));
for (int i=0;i<dim;i++)
for (int j = 0; j < dim; j++)
{
vec1[i][j] = (-1.0 + 2.0*rand() / RAND_MAX) * 10000;
}
vector< vector<double> > vec2,vec3;
double ini, end;
ini = (double)clock();
vec2 = inverse(vec1);
end = (double)clock();
cout << "=== Time inverse unthreaded=" << (end - ini) / CLOCKS_PER_SEC << endl;
ini=end;
vec3 = inverse_th(vec1);
end = (double)clock();
cout << "=== Time inverse threaded=" << (end - ini) / CLOCKS_PER_SEC << endl;
cout<<vec2[2][2]<<" "<<vec3[2][2]<<endl;//to make the sw to do de inverse
cout << endl;
}
int main()
{
test_6_inverse(1000);
cout << endl << "=== END ===" << endl; getchar();
return 1;
}
After looking deeper in the code of the colum_zero() function I have seen that one thread rewrites in the data to be used by another threads, so the threads are not INDEPENDENT from each other. Fortunately the compiler detect it and avoid it.
Conclusions:
It is not recommended to try Gauss-Jordan method alone to make multithreads
If somebody detects that in multithread is slower and the initial function is spreaded correctly for every thread, perhaps is due one thread results are used by another
The main function inverse() works and can be used by other programmers, so this question should not be deleted
Non answered question:
What is a matrix inverse method that could be spreaded in a lot of independent threads to be used in a gpu?

Particles in a 2D box - rounding errors when calculating the energy

I am trying to calculate distances between particles in a box. If the distance calculated is greater than a preset cut-off distance, then the potential energy is 0. Otherwise, it is 1.
There are some rounding issues I think and I am not familiar with variable types and passing variables through functions to know what to do next.
The error
When I calculate d0 by hand I get d0 = 0.070 - this is not what the computer gets! The computer gets a number on the order of e-310.
All of the calculated distances (dij) are no shorter than 1/14, which is much larger than e-310. According to my if statement, if dij>d0, then U=0, so I should get a total energy of 0, but this is what I get:
d0 is 6.95322e-310
i is 0 j is 1 dij is 0.0714286 d0 is 6.95322e-310 Uij is 1
.....
Energy of the system is 24976
Please let me know if I could provide any more information. I did not include the entirety of my code, but the other portion involves no manipulation of d0.
I copied the relevant pieces of code below
Part 1: relevant box data
class Vector {
public:
double x;
double y;
Vector() {
}
Vector (double x_, double y_) {
x = x_;
y = y_;
}
double len() {
return sqrt(x*x + y*y);
}
double lenSqr() {
return x*x + y*y;
}
};
class Atom
{
public:
Vector pos;
Vector vel;
Vector force;
Atom (double x_, double y_) {
pos = Vector(x_, y_);
}
};
class BoxData
{
public:
const double Len = 1.;
const double LenHalf = 0.5 * Len;
long double d = 1. / 14; // d is the distance between each atom
in the initial trigonal lattice
int nu = 7; // auxillary parameter - will be varied
long double d0 = d * (1 - 2^(nu - 8)); // cutoff distance
double alpha = d - d0; // maximum allowed displacement
};
int main() {
// Initialize box
LoadBox();
// Institute a for loop here
SystemEnergy();
MonteCarloMove();
return 0;
}
//Putting atoms into box
void LoadBox()
{
ofstream myfile("init.dat", ios::out);
//Load atoms in box in triangular offset lattice
const double x_shift = 1. / 14;
const double y_shift = 1. / 16;
double x = 0;
double y = 0;
double x_offset = 0;
for (y = 0; y <= 1. - y_shift; y += y_shift) {
for (x = x_offset; x < 0.99; x += x_shift) {
// create atom in position (x, y)
// and store it in array of atoms
atoms.push_back(Atom(x, y));
}
// every new row flip offset 0 -> 1/28 -> 0 -> 1/28...
if (x_offset < x_shift / 4) {
x_offset = x_shift / 2;
} else {
x_offset = 0.0;
}
}
const int numAtoms = atoms.size();
//print the position of each atom in the file init.dat
for (int i = 0; i < numAtoms; i++) {
myfile << "x is " << atoms[i].pos.x << " y is " << atoms[i].pos.y << endl;
}
myfile.close();
}
Part 2 : Energy calculation
vector<Atom> atoms;
BoxData box_;
void SystemEnergy()
{
ofstream myfile("energy.dat", ios::out);
double box_Len, box_LenHalf, box_d0;
double dij; // distance between two atoms
double Uij; // energy between two particles
double UTotal = 0;
double pbcx, pbcy; // pbc -> periodic boundary condition
double dx, dy;
myfile << "d0 is " << box_d0 << endl;
// define the number of atoms as the size of the array of atoms
const int numAtoms = atoms.size();
//pick atoms
for (int i=0; i<numAtoms-1; i++) { // pick one atom -> "Atom a"
Atom &a = atoms[i];
for (int j=i+1; j<numAtoms; j++) { // pick another atom -> "Atom b"
Atom &b = atoms[j];
dx = a.pos.x - b.pos.x;
dy = a.pos.y - b.pos.y;
pbcx = 0.0;
pbcy = 0.0;
// enforce periodic boundary conditions
if(dx > box_LenHalf) pbcx =- box_Len;
if(dx < -box_LenHalf) pbcx =+ box_Len;
if(dy > box_LenHalf) pbcy =- box_Len;
if(dy < -box_LenHalf) pbcy =+ box_Len;
dx += pbcx;
dy += pbcy;
// calculate distance between atoms
dij = sqrt(dx*dx + dy*dy);
// compare dij to the cutoff distance to determine energy
if (dij > box_d0) {
Uij = 0;
} else {
Uij = 1;
}
myfile << "i is " << i << " j is " << j << " dij is " << dij << " d0 is " << box_d0 << " Uij is " << Uij << endl;
UTotal += Uij; // sum the energies
}
}
myfile << "Energy of the system is " << UTotal << endl;
myfile.close();
}
Sorry for the formatting issues - getting the hang of copy/pasting to the forum.

how to organize the result of x and y coordinates as an ASCII X-Y plot?

I am doing a former assignment in C++ and trying to figure out how to get correct ASCII X-Y plot.
So what's really happening is that user is given a menu which allows them to choose a particular trig function.All of the functions have range between [-4..6] for X and [-12...5] for Y.Next user will be allowed to select amount of graduations(or values between the restricted x and y range] and if they want to see resultant values or Bitmap.The final output will be in values/bitmap.I have pasted wolfram alpha link for the functions in comments.
What I have done is incremented each column in 2D output by product of 1/(graduation-1)(i.e. 1/3 if graduated value is 4) and column #.Once that product reaches 1,I am not getting correct output for the values.
#include <iostream>
#include <cmath>
using namespace std;
double minX=-4;
double maxX=6;
double minY=-12;
double maxY=5;
void displayValues(double result[],int result_size,int graduationVal,double percentIncrease,int menuSelection){
int displaySelection=0;
cerr<<"(0) Bitmap or (1) Values?";
cin>>displaySelection;
int k=0;
int i=0;
int division=0;
//Add Values into array until result-1 values
while(i < result_size){
//cout<<"Before j";
//Calculate all the horizontal axis values
for(int j=0; j< graduationVal;j++){
if(displaySelection==1){
//cout<<"In if";
if(menuSelection==1){
result[i]=sin(minX+(percentIncrease*j))*cos(minY+(percentIncrease*k));
cout<<"\n Increase in value of x by "<<percentIncrease*j<<" ";
cout<<"Increase in value of y by "<<percentIncrease*k<<"\n";
//cout<<sin(minX+(percentIncrease*j))<<"\n";
//cout<<cos(minY+(percentIncrease*k))<<"\n";
cout<<result[i]<<" ";
}else if(menuSelection==2){
result[i]=sin(minX+(percentIncrease*j))+pow(cos(minY+(percentIncrease*j)),2)-(minX+(percentIncrease*j))/(minY+(percentIncrease*k));
cout<<"\n Increase in value of x by "<<percentIncrease*j<<" ";
cout<<"Increase in value of y by "<<percentIncrease*k<<"\n";
cout<<result[i]<<" ";
}else if(menuSelection==3){
result[i]=(0.5 * sin(minX+(percentIncrease*j)))+(0.5 *cos(minY+(percentIncrease*k)));
cout<<"\n Increase in value of x by "<<percentIncrease*j<<" ";
cout<<"Increase in value of y by "<<percentIncrease*k<<"\n";
cout<<result[i]<<" ";
}else if(menuSelection==4){
result[i]=(0.5 * sin(minX+(percentIncrease*j)))+(minX+(percentIncrease*j)) * cos(3 * (minY+(percentIncrease*k)));
cout<<result[i]<<" ";
}
//cout<<"J is"<<j<<"\n";
//cout<<"K is"<<k<<"\n";
//cout<<"I is"<<i<<"\n";
}else{
if(menuSelection==1){
result[i]=sin(minX+(percentIncrease*j))*cos(minY+(percentIncrease*k));
cout<<((result[i] > 0 )?"O":"X");
}else if(menuSelection==2){
result[i]=sin(minX+(percentIncrease*j))+pow(cos(minY+(percentIncrease*j)),2)-(minX+(percentIncrease*j))/(minY+(percentIncrease*k));
cout<<((result[i] > 0 )?"O":"X");
}else if(menuSelection==3){
result[i]=(0.5 * sin(minX+(percentIncrease*j)))+(0.5 *cos(minY+(percentIncrease*k)));
cout<<((result[i] > 0 )?"O":"X");
}else if(menuSelection==4){
result[i]=(0.5 * sin(minX+(percentIncrease*j)))+(minX+(percentIncrease*j)) * cos(3 * (minY+(percentIncrease*k)));
cout<<((result[i] > 0 )?"O":"X");
}
}//End display choice if
//Increment Array Index
i++;
//cout<<"Bottom of j";
}//End of j loop
cout<<"\n";
//Increment y-values
if(k<graduationVal){
k++;
}
}//End of While
}
int main(){
int menuChoice=-1;
int displaychoice=0;
double distanceFromMinMaxX=4+6;
double distanceFromMinMaxY=12+5;
int graduations=0;
// double precisionX;
// double precisionY;
double pctIncrease;
while(menuChoice!=0){
cerr<<"Select your function\n";
cerr<<"1. sin(x)cos(y)\n";
cerr<<"2. sin(x)+cos^2(x)-x/y\n";
cerr<<"3. 1/2 sin(x) + 1/2 cos(y)\n";
cerr<<"4. 1/2 sin(x) + xcos(3y)\n";
cerr<<"0. Quit\n";
cin>>menuChoice;
if(menuChoice == 0){
return 0;
}
cerr<<"Number of graduations per axis: ";
cin>>graduations;
pctIncrease=1/(double)(graduations - 1);
int values_size=graduations * graduations;
double values[values_size];
/*int yValues[graduationVal];*/
// precisionX=distanceFromMinMaxX/graduations;
// precisionY=distanceFromMinMaxY/graduations;
displayValues(values,values_size,graduations,pctIncrease,menuChoice);
}
}
Edit:
#include <iostream>
#include <cmath>
using namespace std;
double minX=-4;
double maxX=6;
double minY=-12;
double maxY=5;
double* calculateValues(double val[],int val_size,int graduationVal,double xPrecision,double yPrecision,int menuSelection){
/*int displaySelection=0;
cerr<<"(0) Bitmap or (1) Values?";
cin>>displaySelection;*/
int k=0;
int i=0;
//Add Values into array until result-1 values
while(i < val_size){
for(int j=0; j<graduationVal;j++){
if(menuSelection==1){
val[i]=sin(minX+(xPrecision*j))*cos(minY+(yPrecision*k));
}else if(menuSelection==2){
val[i]=sin(minX+(xPrecision*j))+pow(cos(minY+(xPrecision*j)),2)-(minX+(xPrecision*j))/(minY+(yPrecision*k));
}else if(menuSelection==3){
val[i]=(0.5 * sin(minX+(xPrecision*j)))+(0.5 *cos(minY+(yPrecision*k)));
}else if(menuSelection==4){
val[i]=(0.5 * sin(minX+(xPrecision*j)))+(minX+(xPrecision*j)) * cos(3 * (minY+(yPrecision*k)));
}
//Increment Array Index
i++;
}//End of j loop
//Increment y-values
if(k<graduationVal){
k++;
}
}//End of While
return val;
}
void displayValues(double result[],int result_size,int numOfGraduations){
int displaySelection=0;
cerr<<"(0) Bitmap or (1) Values?";
cin>>displaySelection;
int k=0;
int i=0;
while(i< result_size){
for(int j=0;j<numOfGraduations;j++){
if(displaySelection==1){
cout<<result[i]<<" ";
}else{
cout<<((result[i] > 0 )?"O":"X");
}
i++;
}
cout<<"\n";
}
}
int main(){
int menuChoice=-1;
int displaychoice=0;
double distanceFromMinMaxX=4+6;
double distanceFromMinMaxY=12+5;
int graduations=0;
double precisionX;
double precisionY;
double pctIncrease;
while(menuChoice!=0){
cerr<<"Select your function\n";
cerr<<"1. sin(x)cos(y)\n";
cerr<<"2. sin(x)+cos^2(x)-x/y\n";
cerr<<"3. 1/2 sin(x) + 1/2 cos(y)\n";
cerr<<"4. 1/2 sin(x) + xcos(3y)\n";
cerr<<"0. Quit\n";
cin>>menuChoice;
if(menuChoice == 0){
return 0;
}
cerr<<"Number of graduations per axis: ";
cin>>graduations;
pctIncrease=1/(double)(graduations - 1);
int values_size=graduations * graduations;
double values[values_size];
/*int yValues[graduationVal];*/
precisionX=distanceFromMinMaxX/graduations;
precisionY=distanceFromMinMaxY/graduations;
/*cout << "# of graduations: " << graduations << endl;
cout << "Precision: "<< endl;
cout << "x: " << precisionX << endl;
cout << "y: " << precisionY << endl;*/
calculateValues(values,values_size,graduations,precisionX,precisionY,menuChoice);
displayValues(values,values_size,graduations);
}
}
Edit:I am using gcc
This produces output similar to the screencap you linked (where the user chose option 2). The TextPlot2d function takes a lambda or functor which calculates the desired function, as well as two PlotRange structs for specifying how the x and y axes should be scaled. I also used different output characters because I had a hard time distinguishing 'X' vs. 'O'.
#include <iostream>
#include <cmath>
struct PlotRange {
double begin, end, count;
double get_step() const { return (end - begin) / count; }
};
template <typename F>
void TextPlot2d(F func, PlotRange range_x, PlotRange range_y) {
const auto step_x = range_x.get_step();
const auto step_y = range_y.get_step();
// multiply steps by iterated integer
// to avoid accumulation of error in x and y
for(int j = 0;; ++j) {
auto y = range_y.begin + step_y * j;
if(y >= range_y.end) break;
for(int i = 0;; ++i) {
auto x = range_x.begin + step_x * i;
if(x >= range_x.end) break;
auto z = func(x, y);
if(z != z) { std::cout << '?'; } // NaN outputs a '?'
else { std::cout << (z < 0 ? '#':'o'); }
}
std::cout << '\n';
}
}
int main() {
TextPlot2d(
[](double x, double y){ return std::sin(x) + std::cos(y/2)*std::cos(y/2) - x/y; },
{-4.0, 6.0, 40.0},
{-12.0, 5.0, 40.0}
);
}
Tada!
ooooooo######ooooooooooooooooooooooooooo
oooooo#######ooooooooooooooooooooooooooo
ooooo#########oooooooooooooooooooooooooo
oooo###########ooooooooooooooooo######oo
ooo#############ooooooooooooooo#######oo
ooo#############ooooooooooooooo########o
oo##############ooooooooooooooo########o
ooo#############ooooooooooooooo########o
ooo#############oooooooooooooooo######oo
oooo###########oooooooooooooooooo####ooo
ooooo#########oooooooooooooooooooooooooo
ooooo#########oooooooooooooooooooooooooo
oooooo#######ooooooooooooooooooooooooooo
ooooooo######ooooooooooooooooooooooooooo
oooooo#######ooooooooooooooooooooooooooo
oooooo#######ooooooooooooooooooooooooooo
ooooo#########oooooooooooooooooooooooooo
ooo############ooooooooooooooooooooooooo
oo#############ooooooooooooooooooooooooo
################oooooooooooooooooooooooo
################oooooooooooooooooooooooo
################oooooooooooooooooooooooo
################oooooooooooooooooooooooo
################oooooooooooooooooooooooo
###############ooooooooooooooooooooooooo
###############ooooooooooooooooooooooooo
###############ooooooooooooooooooooooooo
###############ooooooooooooooooooooooooo
################oooooooooooooooooooooooo
oooooooooooooooooo######################
oooooooooooooooooooooo##################
oooooooooooooooooooooooo################
ooooooooooooooooooooooooo###############
ooooooooooo###ooooooooooo###############
ooooooooo#######ooooooooo###############
oooooooo########oooooooooo##############
ooooooo#########oooooooooo##############
ooooooo#########ooooooooooo#############
ooooooo########oooooooooooo#############
oooooooo######oooooooooooooo############
I finally got the output!!Appearantly function#2 was wrong and that's why I wasn't getting correct answer.
#include <iostream>
#include <cmath>
using namespace std;
double minX=-4;
double maxX=6;
double minY=-12;
double maxY=5;
void calculateValues(double val[],int val_size,int graduationVal,double xPrecision,double yPrecision,int menuSelection){
/*int displaySelection=0;
cerr<<"(0) Bitmap or (1) Values?";
cin>>displaySelection;*/
//double val[];
int k=0;
int i=0;
//Add Values into array until result-1 values
while(i < val_size){
for(int j=0; j<graduationVal;j++){
if(menuSelection==1){
val[i]=sin(minX+(xPrecision*j))*cos(minY+(yPrecision*k));
}else if(menuSelection==2){
val[i]=sin(minX+(xPrecision*j))+pow(cos((minY+(yPrecision*k))/2),2)-(minX+(xPrecision*j))/(minY+(yPrecision*k));
}else if(menuSelection==3){
val[i]=(0.5 * sin(minX+(xPrecision*j)))+(0.5 *cos(minY+(yPrecision*k)));
}else if(menuSelection==4){
val[i]=(0.5 * sin(minX+(xPrecision*j)))+(minX+(xPrecision*j)) * cos(3 * (minY+(yPrecision*k)));
}
//Go to next value in array
i++;
}//End of j loop
//Increment y-values
if(k<graduationVal){
k++;
}
}//End of While
}
void displayValues(double result[],int result_size,int numOfGraduations){
int displaySelection=0;
cerr<<"(0) Bitmap or (1) Values?";
cin>>displaySelection;
int k=0;
int i=0;
while(i< result_size){
for(int j=0;j<numOfGraduations;j++){
if(displaySelection==1){
cout<<result[i]<<" ";
}else{
cout<<((result[i] > 0 )?"O":"#");
}
i++;
}
cout<<"\n";
}
}
int main(){
int menuChoice=-1;
int displaychoice=0;
double distanceFromMinMaxX=maxX-minX;
double distanceFromMinMaxY=maxY-minY;
int graduations=0;
double precisionX;
double precisionY;
double pctIncrease;
while(menuChoice!=0){
cerr<<"Select your function\n";
cerr<<"1. sin(x)cos(y)\n";
cerr<<"2. sin(x)+cos^2(y/2)-x/y\n";
cerr<<"3. 1/2 sin(x) + 1/2 cos(y)\n";
cerr<<"4. 1/2 sin(x) + xcos(3y)\n";
cerr<<"0. Quit\n";
cin>>menuChoice;
if(menuChoice == 0){
return 0;
}
cerr<<"Number of graduations per axis: ";
cin>>graduations;
//pctIncrease=1/(double)(graduations - 1);
int values_size=graduations * graduations;
double values[values_size];
/*int yValues[graduationVal];*/
precisionX=(distanceFromMinMaxX)/graduations;
precisionY=(distanceFromMinMaxY)/graduations;
/*cout << "# of graduations: " << graduations << endl;
cout << "Precision: "<< endl;
cout << "x: " << precisionX << endl;
cout << "y: " << precisionY << endl;*/
calculateValues(values,values_size,graduations,precisionX,precisionY,menuChoice);
displayValues(values,values_size,graduations);
}
}

C++ Recursion Help Using Horner's Method For computiing Polynomials

Here is my code so far. There seems to be soemthing wrong since I keep getting an incorrect answer. I am writing in a text file that is formatted:
2
3.0 1.0
2 being the size of the array and then 3.0 and 1.0 being the coefficients. Hopefully I didnt miss much in my explanation. Any help would be greatly appreciated.
Thanks
double polyeval(double* polyarray, double x, int arraySize)
{
//int result = 0;
if(arraySize == 0)
{
return polyarray[arraySize];
}
//result += x*(polyarray[arraySize]+polyeval(polyarray,x,arraySize-1));
return polyarray[arraySize-1]+ (x* (polyeval(polyarray,x,arraySize-1)));
//return result;
}
int main ()
{
int arraySize;
double x;
double *polyarray;
ifstream input;
input.open("polynomial.txt");
input >> arraySize;
polyarray = new double [arraySize];
for (int a = arraySize - 1; a >= 0; a--)
{
input >> polyarray[a];
}
cout << "For what value x would you like to evaluate?" << endl;
cin >> x;
cout << "Polynomial Evaluation: " << polyeval(polyarray, x, arraySize);
delete [] polyarray;
}
the idea that if i read in a text file of that format varying in size that it will solve for any value x given by the user
Jut taking a wild guess
for (int a = arraySize - 1; a >= 0; a--)
// ^^
{
input >> polyarray[a];
}
One error is here:
for (int a = arraySize - 1; a > 0; a--)
{ //^^should be a >=0
input >> polyarray[a];
}
You are missing some entry this way.
The recursive function should look like the following:
int polyeval(double* polyarray, double x, int arraySize)
{
if(arraySize == 1)
{
return polyarray[arraySize-1];
}
return x*(polyarray[arraySize-1]+polyeval(polyarray,x,arraySize-1));
}
The problem is mainly with the definition of the polynomial coefficients.
Your code assumes a polynomial on the form:
x( p(n) + x( p(n-1) + x( p(n-2) + ... x(p(1) + p(0)))..))
This line:
result += x*(polyarray[arraySize]+polyeval(polyarray,x,arraySize-1));
Should become:
result += pow(x,arraySize)*polyarray[arraySize]+polyeval(polyarray,x,arraySize-1);
This way the polynomial is defined correctly as p(n)x^n + p(n-1)x^(n-1) ... + p1 x + p0
Couldn't work out exactly what you were trying to do, or why you were using recursion. So I whipped up a non-recursive version that seems to give the right results.
#include <iostream>
using namespace std;
double polyeval(const double* polyarray, double x, int arraySize) {
if(arraySize <= 0) { return 0; }
double value = 0;
const double * p = polyarray + (arraySize-1);
for(int i=0; i<arraySize; ++i) {
value *= x;
value += *p;
p--;
}
return value;
}
int main () {
const int arraySize = 3;
const double polyarrayA[3] = {0.0,0.0,1.0}; // 0 + 0 x + 1 x^2
const double polyarrayB[3] = {0.0,1.0,0.0}; // 0 + 1 x + 0 x^2
const double polyarrayC[3] = {1.0,0.0,0.0}; // 1 + 0 x + 0 x^2
cout << "Polynomial Evaluation A f(x) = " << polyeval(polyarrayA, 0.5, arraySize)<<std::endl;
cout << "Polynomial Evaluation B f(x) = " << polyeval(polyarrayB, 0.5, arraySize)<<std::endl;
cout << "Polynomial Evaluation C f(x) = " << polyeval(polyarrayC, 0.5, arraySize)<<std::endl;
}
You can see it running here:
http://ideone.com/HE4r6x