I have a data file which contains floating point data arranged in 4 columns. Each row represent a specific data point. The first column(X) is made up of 100 different values but the values are repeating. Fortunately they are sorted in ascending order. For each distinct value in first column the second column(Y) has a different number of values which are sorted but repetative in nature. Finally, for each distinct value in second column there are a no. of different values in thrid column(Z) which are sorted and non-repetative. Data file can be viewed here
I have to find the nearest data point corresponding to a specific value(x,y,z) from first three column and write the value present in the forth column of that data point. Following is the working code for this problem:
#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <vector>
using namespace std;
#define Nc 381443
struct data { //Stores value of data points row-wise
float H;
float Ba;
float SO4;
float sup;
};
struct ioninfo //To store value of a specific variable and count the no. of times it is repeating
{
float val;
int count;
};
double write_absolute(double value)
{
if (value<0)
{
return -value;
}
else return value;
}
int find_H_ion(double x, vector<ioninfo> Hion) //To find value nearest to the first(x) variable in first column
{
vector<double> diff(100);
for (int i = 0; i < 100; ++i)
{
diff[i]=write_absolute(x-Hion[i].val);
}
double min=diff[0];
int index;
for (int i = 1; i < 100; ++i)
{
if (diff[i]<min)
{
min=diff[i];
index=i;
}
}
return index;
}
int find_Ba_ion(double y,int index, vector<int> nH_Ba, vector<ioninfo> Baion) //To find value nearest to the second(y) variable in second column
{
vector<double> diffBa(nH_Ba[index]);
int temp=0;
for (int i = 0; i < index; ++i)
{
temp=temp+nH_Ba[i];
}
for (int i = 0; i < nH_Ba[index]; ++i)
{
diffBa[i]=write_absolute(y-Baion[temp+i].val);
}
double miny=diffBa[0];
int indexy;
for (int i = 1; i < nH_Ba[index]; ++i)
{
if (diffBa[i]<miny)
{
miny=diffBa[i];
indexy=i;
}
}
return indexy;
}
int find_SO4_ion(double z,int index,int indexy, vector<int> nH_Ba,vector<ioninfo> Hion, vector<ioninfo> Baion, vector<data> v) //To find value nearest to the third(z) variable in third column
{
int sumA=0,sumB=0;
for (int i = 0; i < index; ++i)
{
sumA=sumA+Hion[i].count;
}
int temp=0;
for (int i = 0; i < index; ++i)
{
temp=temp+nH_Ba[i];
}
for (int i = 0; i < (indexy); ++i)
{
sumB=sumB+Baion[temp+i].count;
}
vector<double> diffz(Baion[temp+indexy].count);
int pos=0;
for (int i = (sumA+sumB); i < (sumA+sumB+Baion[temp+indexy].count); ++i)
{
diffz[pos]=write_absolute(z-v[i].SO4);
pos++;
}
double minz=diffz[0];
int indexz;
for (int i = 0; i < Baion[temp+indexy].count; ++i)
{
if (diffz[i]<minz)
{
minz=diffz[i];
indexz=i;
}
}
return (sumA+sumB+indexz);
}
int main()
{
vector<data> v(Nc);
vector<ioninfo> Hion(100);
ifstream fin( "data2.txt");
double X,Y,Z,S;
double X1;
int Hc[101];
X=0.0,Y=0.0,Z=0.0,X1=0.0;
int count=0;
int local_count=1;
int i=0;
//Reading data points from file
for(string line; getline( fin, line ); )
{
sscanf (line.c_str(),"%lf %lf %lf %lf",&X,&Y,&Z,&S);
v[i].H=X;
v[i].Ba=Y;
v[i].SO4=Z;
v[i].sup=S;
i++;
}
fin.close();
//Finding distinct values in first column and storing the no. of times they are repeated
int j=0;
for ( i = 0; i < Nc-1; ++i)
{
if (v[i].H==v[i+1].H)
{
local_count++;
}
else
{
Hion[j].val=v[i].H;
Hion[j].count=local_count;
j++;
local_count=1;
}
}
Hion[j].val=v[i].H;
Hion[j].count=local_count;
//For each distinct value in first column there exist different no. of distinct values in second column
// First counting the no. of distinct values in second column corresponding to each distinct value in first column
int total_count=0;
int k;
int bin=0;
vector<int> nH_Ba(100);
for ( i = 0; i < 100; ++i)
{
local_count=1;
k=0;
for (j = 0; j < Hion[i].count; ++j)
{
if (v[total_count].Ba==v[total_count+1].Ba)
{
total_count++;
}
else
{
bin++;
total_count++;
}
}
nH_Ba[i]=bin;
bin=0;
}
//Counting the total no. of distinct value in second column for the purpose of allocating memory in further steps
int sumBa=0;
for (int i = 0; i < 100; ++i)
{
sumBa=sumBa+nH_Ba[i];
}
//Again storing the distict values and their count
vector<ioninfo> Baion(sumBa+1);
total_count=0;
k=0;
for ( i = 0; i < 100; ++i)
{
local_count=1;
for (j = 0; j < Hion[i].count; ++j)
{
if (v[total_count].Ba==v[total_count+1].Ba)
{
local_count++;
total_count++;
}
else
{
Baion[k].val=v[total_count].Ba;
Baion[k].count=local_count;
k++;
total_count++;
local_count=1;
}
}
}
Baion[k].val=v[total_count].Ba;
Baion[k].count=local_count;
// Values nearest to these data are to be searced
double x=55.5556; //First column
double y=0.05; //Second column
double z=0.024; //Third column
//Finding values step by step from first column to third column
//and then printing the value present in fourth column
int index;
index=find_H_ion(x,Hion);//First column
int indexy;
indexy=find_Ba_ion(y,index,nH_Ba,Baion);//Second column
int indexz=find_SO4_ion(z,index,indexy,nH_Ba,Hion,Baion,v);//Third column
cout<<"Index="<<indexz<<endl;
cout<<"Supersaturation="<<v[indexz].sup<<endl;
}
Can I improve this code any more?
I am avoiding the use of multidimensional array.