Find area under a curve using c++ and a file - c++

I have updated the code and now I know how to store the first two number into x1 and z1 but how do I let it into x2 and z2 in order to calculate the area? Thanks.
Here's what I have so far:
#include <fstream>
#include <iostream>
double x1=0;
double x2=0;
double z1=0;
double z2=0;
double n;
double sum;
double area;
using namespace std;
int main()
{
ifstream infile;
infile.open("xydata.dat");
infile.ignore(1000, '\n') ;
while(!infile.eof())
{
infile>>n;
if(n>=20.00&&n<=20.50)
{
x1=n
}
else
{
z1=n
}
area = (x1+x2)*(z2-z1)/2;
}
cout<<"The sum of all are under the curve is "<<sum<<"."<<endl;
return 0;
}
and the file is here:
xydata.dat
x values y values
20.00 0
20.02 15
20.04 27
20.06 39
20.08 54
20.10 65
20.12 75
20.14 84
20.16 93
20.18 101
20.20 108
20.22 113
20.24 116
20.26 115
20.28 112
20.30 107
20.32 100
20.34 92
20.36 83
20.38 74
20.40 64
20.42 53
20.44 39
20.46 27
20.48 15
20.50 0

Is this a homework? (Not posting any code due to the previous question)
I am assuming you want the area between the x axis and the curve. Here is a shortcut:
Consider every pair of consecutive coordinates specifying a rectangle, with a triangle sitting on top of it. You get the rectangle's area by multiplying the (differences in x) with (the smaller y). and then get the triangle's area by the (difference in x), multiplied by (the difference in y), and having the half of it. Add these two areas and it will give you an approximate area under the curve for the pair of coordinates. Repeat this procedure for all consecutive pairs of coordinates and add them up.

Related

How to calculate the average?

I was asked to calculate the average of marks for 10 students.
First, I was able to read and retrieve the data from data.txt file which looks like this:
No. Name Test1 Test2 Test3
1 Ahmad 58 97 83
2 Dollah 78 76 70
3 Ramesh 85 75 84
4 Maimunah 87 45 74
5 Robert 74 68 97
6 Kumar 77 73 45
7 Intan 56 23 27
8 Ping 74 58 18
9 Idayu 47 98 95
10 Roslan 79 98 78
Then I have to calculate the average for each student and determine the grades.
Here are what I've done so far.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
int main()
{
ifstream inFile1;
string temp;
int line=0;
inFile1.open("data.txt");
if(inFile1.fail())
{
cout << "File cannot be opened" << endl;
exit(1);
}
while(getline(inFile1, temp))
{
line++;
}
inFile1.close();
return 0;
}
This program should at least consists two prototype function: average() and grade().
This is where I got stuck.
You can check the answers here: find average salaries from file in c++.
Basically when you iterate through the file lines you should split the temp string into tokens you are interested in. How? An option would be to use getline with the delimeter ' ' or look into the std::noskipws stream manipulator or simply use operator>> to read from the file - depends on the details of your requirements.
If I correctly understand your case, I'd go with the operator>> to get the name of the student and then read using getline(inFile, gradesText) to read until end of line to get all grades for the current student.
Then I'd use a separate function to split the strings into a vector of grades. How to do the splitting you can check in Split a string in C++?. This way you could prepare a function like vector<int> split(const string& line, char delim = ' '). Within the implementation you should probably use std::stoi for the string-to-int conversion.
Afterwards, when you already have a proper collection you can calculate the mean from it with:
const double sum = std::accumulate(grades.begin(), grades.end(), 0.0);
const double gradesMean = sum / grades.size();

c++ class return reference to itself

Can a c++ object have a method that return a reference to itself?
I want multiple independent instance of the class of the object.
It is for implementing the [] operator of a multi-dimensional array.
I want something like Array[0][1][2] to work.
Thanks.
Update:
Implementation of a multi-dimensional array:
Intended usage:
A[0][1] = 4; //the element at 0th row and 1st column is now 4.
A[0] = 5; //all elements of the 0th row are now 5.
A["all"][1] = 10; //all elements of the 1st column are now 10;
Object A has pointer ptr_buffer to a chunk of memory with correct simd alignment. Constructor of A would allocate the memory. Destructor of A deallocate the memory. A[] returns object B.
Object B has a pointer ptr_A_buffer to a subsection of the memory of A. B[] modifies ptr_A_buffer and also returns reference to itself. I don't want to constantly make a bunch of object B for each [] operation.
Both A and B belong to the same abstract class. Math functions take the abstract class as argument.
I was curious about the idea. Here is a data type which seems to fit the bill. It's an array type which, when called with three integers for the dimensions, allocates contiguous memory and then allows the user to define "views" into the data which have smaller dimensions (a plane, a row, a single value).
I made use of shared pointers which I have not really used before, so I may have made mistakes. I welcome corrections.
The idea is that copying views around is shallow; they all operate on the same underlying data. This allows me to pass them around by value with, as I believe, reasonable efficiency.
#include <iostream>
#include <iomanip>
#include <memory>
using namespace std;
/// This class is a three-dimensional array of doubles.
/// It defines an index operator which returns a view into that
/// data that is of one lesser dimension, just like the standard
/// index operator on plain old arrays. The last index operation
/// yields an "array" which is a single value.
/// Converting to double and assigning from double is defined as
/// using the first double in the view.
class NDimArrT
{
/// All slices hold a shared pointer to the base data they
/// are looking into so that their view stays valid.
const shared_ptr<double> baseData;
/// The data the view is looking at. Identical to the shared
/// ptr for the original object.
double *const slice;
/// The three dimensions, in the order of indexing.
/// All three of them may be zero, indicating a single value.
const int dim1, dim2, dim3;
public:
/// A single double value view into a one-dimensional array
NDimArrT(const shared_ptr<double> base, double *sliceStart)
: baseData(base), slice(sliceStart), dim1(0), dim2(0), dim3(0) {}
/// A 1D vector/row view into a two-dimensional array.
/// #param dim1Arg is the length of the row.
NDimArrT(const shared_ptr<double> base, double *sliceStart, int dim1Arg)
: baseData(base), slice(sliceStart), dim1(dim1Arg), dim2(0), dim3(0) {}
/// A 2D matrix plane view into the cube
NDimArrT(const shared_ptr<double> base, double *sliceStart, int dim1Arg, int dim2Arg)
: baseData(base), slice(sliceStart), dim1(dim1Arg), dim2(dim2Arg), dim3(0) {}
/// A 3D cube. This actually allocates memory.
NDimArrT(int dim1Arg, int dim2Arg, int dim3Arg)
: baseData(new double[dim1Arg*dim2Arg*dim3Arg], std::default_delete<double[]>() ),
slice(baseData.get()), // the data view is the whole array
dim1(dim1Arg), dim2(dim2Arg), dim3(dim3Arg) {}
/// Perform a shallow copy. We assume that e.g. returning a slice means
/// essentially returning another view into the main base array.
NDimArrT(const NDimArrT &rhs) = default;
/// Use standard move semantics. The rhs will be invalidated, and the
/// reference count to the base array does not grow. Can be used to return results from
/// functions.
NDimArrT(NDimArrT &&rhs) = default;
/// Default destructor; destroy baseData if it's the last reference.
~NDimArrT() = default;
/// Get the value of the first element we look at. Handy for
/// single value views.
operator double() const { return *slice; }
/// Return an instance of NDimArrT representing a view
/// with one dimension less than this. If we have a single value
/// already, simply return this single value. (We should
/// perhaps throw an exception there.)
NDimArrT operator[](int ind)
{
// This could be regarded an error, because this view
// is already a single element.
if(GetDims() == 0) { return *this; }
// This view is a 1-dimensional vector. Return the element at ind.
if(dim2==0) { return NDimArrT(baseData, slice + ind); } // return a single value.
// This view is a 2D matrix. Return the row no. ind.
// The row length is dim2. (Dim 1 indicates how many rows.)
if(dim3==0) { return NDimArrT(baseData, slice + dim2*ind, dim2); } // return a 1D vector
// This view is a true 3D cube matrix. dim1 is the number of planes,
// dim2 is the number of rows in a plane, dim3 is the length of each row.
// Return the plane no. ind, which starts at ind*planesize, i.e. ind*dim2*dim3.
// The number of rows and row length are dim2 and dim3, respectively.
return NDimArrT(baseData, slice + dim2*dim3*ind, dim2, dim3); // return a 2D matrix.
}
NDimArrT &operator=(double d) { *slice = d; }
int Len() { return dim1 ? dim1 : 1; } // interestingly, length is always dim1.
int GetDims() const
{
return dim1
? dim2
? dim3
? 3
: 2
: 1
: 0;
}
};
/// An example function which initializes an NDimArr of unknown
/// dimensionality with nice numbers..
void initNDimArr(NDimArrT arr, int &startVal)
{
// Single value? Give it the start value and increment that.
if( arr.GetDims() == 0 ) { arr = startVal++; }
else
{
for(int ind=0; ind<arr.Len(); ind++) { initNDimArr(arr[ind], startVal); }
}
}
// An example function doing something with
// an unknown n-dimensional array
void printNdimArr( NDimArrT nDimArr)
{
if( nDimArr.GetDims() == 0) { cout << setw(4) << nDimArr << " "; }
else
{
for(int i=0; i<nDimArr.Len(); i++) { printNdimArr(nDimArr[i]); }
cout << endl;
}
}
int main()
{
NDimArrT arr(3,4,5);
int start = 1;
initNDimArr(arr, start);
printNdimArr(arr);
// now use the middle plane of the 3 4x5 planes
cout << "Middle plane, values starting at 100:" << endl;
auto middlePlane = arr[1];
start = 100;
initNDimArr(middlePlane, start);
printNdimArr(middlePlane);
cout << "Whole array now:" << endl;
printNdimArr(arr);
cout << "Print line 2 of the 3rd plane:" << endl;
printNdimArr(arr[2][1]);
cout << endl << "Last number in that row is " << arr[2][1][4] << endl;
}
Sample session:
$>g++ -std=c++11 -o ndimContiguousArr ndimContiguousArr.cpp && ./ndimContiguousArr
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
26 27 28 29 30
31 32 33 34 35
36 37 38 39 40
41 42 43 44 45
46 47 48 49 50
51 52 53 54 55
56 57 58 59 60
Middle plane, values starting at 100:
100 101 102 103 104
105 106 107 108 109
110 111 112 113 114
115 116 117 118 119
Whole array now:
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
100 101 102 103 104
105 106 107 108 109
110 111 112 113 114
115 116 117 118 119
41 42 43 44 45
46 47 48 49 50
51 52 53 54 55
56 57 58 59 60
Print line 2 of the 3rd plane:
46 47 48 49 50
Last number in that row is 50

Calculation of inverse matrix in Eigen going wrong

Im trying to build a simple input/output matrix (where you can calculate the multiplier effect in a simple economy if demand increases). But for some reason the final result is not adding up.
#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
void InputOutput(){
MatrixXf ProdA(5, 5);;
VectorXf Intd(5);
VectorXf Finald(5);
ProdA <<
10, 20, 0, 0, 5,
20, 30, 20, 10, 10,
10, 10, 0, 10, 10,
10, 40, 20, 5, 5,
20, 20, 30, 5, 5;
Intd << 55, 40, 20, 30, 10;
Finald << 0, 0, 0, 0, 0;
VectorXf ones(5);
ones << 1, 1, 1, 1, 1;
Finald = ProdA * ones + Intd;
MatrixXf AMatrix = MatrixXf::Zero(ProdA.rows(), ProdA.cols());
AMatrix = ProdA.array() / (Finald.replicate(1, ProdA.cols())).array();
cout << "Here is the Coefficient vector production needed:\n" << AMatrix << endl;
MatrixXf IminA(5, 5);;
IminA = MatrixXf::Identity(AMatrix.rows(), AMatrix.cols()) - AMatrix;
cout << "Here is the matrix of production:\n" << ProdA << endl;
cout << "Here is the vector Internal demand:\n" << Intd << endl;
cout << "Here is the vector Final demand:\n" << Finald << endl;
cout << "Here is the Coefficient vector production needed:\n" << AMatrix << endl;
MatrixXf IminAinv(5, 5);;
IminAinv = IminA.inverse();
cout << "The inverse of CoMatrix - Imatrix is:\n" << IminAinv << endl;
cout << "To check, final demand is:\n" << (IminAinv * Intd) << endl;
When I verify if the (I-A)inverse matrix (or IminAinv) is properly calculated it doesn't add up. By multiplying the IminAinv by Internal demand (int), I should get the same Intd. That is if Intd isn't changed. Instead I get a bigger number. Also if I calculate the inverse of the IminA matrix myself, I get something different then eigen.
So something goes wrong in getting the inverse of Identity matrix - Coefficient matrix. But what?
Thanks!
EDIT :
After some more digging into why there are some differences in the final results, I discovered that those "underlying mechanisms" mentioned in Case 2 were, in fact, my own mistake out of inadvertence while entering the matrices' values.
Here follows the original answer with these mistakes taken care of.
The actual problem does not lie in the inversion of the AMatrix but in a much more subtle detail.
You are using this command to perform the division in the definition of AMatrix:
AMatrix = ProdA.array() / (Finald.replicate(1, ProdA.cols())).array();
But if you check the results of this replicate operation on Finald you get:
...
cout << "Here is the replicated final demand vector:\n" << (Finald.replicate(1, ProdA.cols())).array() << endl;
...
>>
Here is the replicated final demand vector:
90 90 90 90 90
130 130 130 130 130
60 60 60 60 60
110 110 110 110 110
90 90 90 90 90
whereas the correct one should be:
90 130 60 110 90
90 130 60 110 90
90 130 60 110 90
90 130 60 110 90
90 130 60 110 90
You can transpose the replicated final demand vector like this:
MatrixXf Finaldrep(5,5);
Finaldrep = (Finald.replicate(1, ProdA.cols())).array().transpose();
and then of course:
AMatrix = ProdA.array() / Finaldrep.array();
which yields:
cout << "Here is the transposed replicated final demand vector:\n" << Finaldrep << endl;
...
>>
Here is the transposed replicated final demand vector:
90 130 60 110 90
90 130 60 110 90
90 130 60 110 90
90 130 60 110 90
90 130 60 110 90
So, let's see what are the differences in your intermediate and final results in both these cases:
Case 1
ie Your current approach
Here is the Coefficient vector production needed:
0.111111 0.222222 0 0 0.0555556
0.153846 0.230769 0.153846 0.0769231 0.0769231
0.166667 0.166667 0 0.166667 0.166667
0.0909091 0.363636 0.181818 0.0454545 0.0454545
0.222222 0.222222 0.333333 0.0555556 0.0555556
The determinant of IminA is: 0.420962
The inverse of CoMatrix - Imatrix is:
1.27266 0.468904 0.131153 0.0688064 0.13951
0.443909 1.68132 0.377871 0.215443 0.240105
0.451292 0.628205 1.25318 0.287633 0.312705
0.404225 0.841827 0.423093 1.20242 0.224877
0.586957 0.777174 0.586957 0.23913 1.27174
To check, final demand is:
94.8349
108.09
86.7689
102.689
95
I have also added the determinant of IminA
Case 2
ie using the reversed final demand vector
Here is the Coefficient vector production needed:
0.111111 0.153846 0 0 0.0555556
0.222222 0.230769 0.333333 0.0909091 0.111111
0.111111 0.0769231 0 0.0909091 0.111111
0.111111 0.307692 0.333333 0.0454545 0.0555556
0.222222 0.153846 0.5 0.0454545 0.0555556
The determinant of IminA is: 0.420962
The inverse of CoMatrix - Imatrix is:
1.27266 0.324626 0.196729 0.0562962 0.13951
0.641202 1.68132 0.818721 0.254615 0.346818
0.300861 0.289941 1.25318 0.156891 0.20847
0.494053 0.712316 0.77567 1.20242 0.27485
0.586957 0.538044 0.880435 0.195652 1.27174
To check, final demand is:
90
130
60
110
90
Now, I understand that the Finald check still does not produce the exact values of the originally defined Finald, but I believe that this has something to do with the precision or some other underlying mechanism. (see NOTE)
As a proof of concept here are some results obtained with MATLAB, using the second case (reversed) for the replicated Final Demand Vector (denom):
>> AMatrixcm = ProdA ./ Finaldfullcm
AMatrixcm =
0.1111 0.1538 0 0 0.0556
0.2222 0.2308 0.3333 0.0909 0.1111
0.1111 0.0769 0 0.0909 0.1111
0.1111 0.3077 0.3333 0.0455 0.0556
0.2222 0.1538 0.5000 0.0455 0.0556
>> IminAcm = eye(5) - AMatrixcm
IminAcm =
0.8889 -0.1538 0 0 -0.0556
-0.2222 0.7692 -0.3333 -0.0909 -0.1111
-0.1111 -0.0769 1.0000 -0.0909 -0.1111
-0.1111 -0.3077 -0.3333 0.9545 -0.0556
-0.2222 -0.1538 -0.5000 -0.0455 0.9444
>> det(IminAcm)
ans =
0.4210
>> IminAinvcm = inv(IminAcm)
IminAinvcm =
1.2727 0.3246 0.1967 0.0563 0.1395
0.6412 1.6813 0.8187 0.2546 0.3468
0.3009 0.2899 1.2532 0.1569 0.2085
0.4941 0.7123 0.7757 1.2024 0.2748
0.5870 0.5380 0.8804 0.1957 1.2717
>> Finaldcheckcm = IminAinvcm * Intdc
Finaldcheckcm =
90.0000
130.0000
60.0000
110.0000
90.0000
It is quite clear that the second case results are (almost) identical to the MATLAB ones.
NOTE: Here you can see that the MATLAB output is identical to the original Finald, however, if you perform the last matrix multiplication (the one in the validation of the Final Demand vector) by hand, you will see that in fact both MATLAB and Case 2 versions of IminAinv yield the same result as the final output of Case 2, ie [88.9219, 125.728, 59.5037, 105.543, 84.5808].
This is why I think that there is some other mechanism involved in these differences. (See EDIT on top of post)

How do you write text doc info (names and numbers) into multiple arrays?

I've been racking my brain trying to get this information from a text doc into a few different arrays. The number before each name in the txt doc is the identification number, I want to put all these into a single double array. Then put every name into a single string array. Then finally put the numbers after each name into a double 2d array with 50 rows (one for each name) and 7 columns (for the seven scores/numbers for each client). I'm not asking for anyone to do my homework for me, I just need some info on how to get started.
using namespace std;
int main() { ifstream file("client_info.txt");
string txtArray[450];
for (int i = 0; i < 450; ++i)
{
file >> txtArray[i];
}
I thought maybe I'd put all of the text into a string array then split that array into several other arrays, but realized it would be difficult to use strings, since I need the numbers to be doubles for later when I'm finding the average of the clients scores.
Here is the txt doc:
93 SMITH 739.15 634.36 257.02 639.32 376.75 360.56 666.96 81 JOHNSON 888.08 975.86 672.78 176.35 114.58 511.24 502.56 50 WILLIAMS 222.27 171.83 232.83 609.79 726.69 444.89 520.63 32 JONES 343.13 687.73 931.93 72.36 183.93 486.3 90.09 68 BROWN 623.39 968.13 67.59 528.93 703.95 329.02 875.95 24 DAVIS 97.48 296.61 568.49 990.18 448.36 567.52 179.42 21 MILLER 147.68 38.87 64.78 463.19 172.39 914.68 827.42 90 WILSON 687.7 595.19 930.52 77.27 877.45 774.44 599.83 29 MOORE 739.33 402 825.29 859.63 937.14 405.2 89.22 12 TAYLOR 976.11 531.4 731.45 815.16 518.26 858.86 832.34 31 ANDERSON 133.12 355.22 517.53 926.54 552.05 932.52 745.75 89 THOMAS 217.72 266.14 622.99 541.35 618.49 268.9 243.63 87 JACKSON 352.81 772.31 109.43 139.14 430.43 625.92 207.79 46 WHITE 650.79 367.65 915.68 848.85 912.44 603.15 704.01 75 HARRIS 708.38 70.53 34.45 409.82 288.28 735.06 140.9 85 MARTIN 701.73 643.16 766.3 198.92 805.86 802.39 239.76 67 THOMPSON 993.9 274.75 72.87 928.41 208.81 260.42 5.56 52 GARCIA 871.48 646.48 914.77 98.61 724.86 680.7 363.15 60 MARTINEZ 293.38 448.24 985.08 135.2 277.77 705.58 567.81 69 ROBINSON 914.18 688.95 112.81 270.18 950.27 607.49 915.75 76 CLARK 956.12 110.6 820.53 140.97 906.2 529.52 75.24 82 RODRIGUEZ 224.88 324.32 672.74 502.27 768.99 116.42 880.86 39 LEWIS 805.89 274.54 211.14 82.04 804.41 259.69 408.08 48 LEE 80.06 381.7 975.29 448.33 578.49 548.19 818.85 26 WALKER 657.74 0.74 741.06 533.84 887.36 38.35 619.17 55 HALL 266.9 46.42 825.89 986.01 146.96 349.07 386.64 100 ALLEN 293.22 423.57 150.53 519.25 16.96 65.54 688.44 11 YOUNG 870.69 192.46 82.19 92.46 971.38 156.49 16.48 57 HERNANDEZ 145.33 123.45 860.78 521.86 739.9 138.88 169.33 96 KING 411.31 340.93 447.04 14.26 744.1 425.83 57.87 4 WRIGHT 503.48 488.13 603.12 198.14 425.51 216.28 49.75 64 LOPEZ 296.99 744.89 270.49 138.19 897.06 374.89 831.66 62 HILL 910.95 676.68 442.98 961.03 567.6 739.49 225.26 37 SCOTT 970.31 468.48 788.85 903.66 897.93 124.04 983.01 34 GREEN 260.42 714.42 496.13 492.39 170.17 999.36 890.8 51 ADAMS 212.36 115.84 308.57 741.29 780.3 193.71 423.82 40 BAKER 316.91 671.36 398.53 190.99 424.34 457.68 584.16 47 GONZALEZ 947.9 348.88 299.11 71.82 727.49 480.59 891.51 3 NELSON 160.13 962.1 903.76 107.34 127.07 844.07 575.1 36 CARTER 981.92 250.09 5.39 866.43 182.93 135.12 224.91 78 MITCHELL 805.83 181.19 549.25 815.72 776.2 887.33 144.86 28 PEREZ 144.04 616.81 637.07 342.41 818.58 901.72 104.02 8 ROBERTS 880.38 62.34 591.34 721.18 184.64 378.08 439.94 99 TURNER 21.83 227.82 378.42 680.24 336.24 703.13 52.36 2 PHILLIPS 664.1 879.16 811.4 842.3 463.96 446.52 919.31 17 CAMPBELL 392.91 26.12 591.74 766.1 30.91 108.24 863.81 33 PARKER 359.87 606.99 61.67 188.85 474.87 159.02 907.38 30 EVANS 770.78 70.1 724.89 490.02 667.93 116.4 938.55 70 EDWARDS 507.59 698.53 15.5 251.9 340.84 246.6 233.04 44 COLLINS 803.53 580.38 966.57 941.38 249.58 562.3 725.05
To make a multideminsional array use
type arrayName [x][y];
The first number is row, second is column. You can use arrayName[0][x] to set the names you mentioned, assuming you use each row for a single name and whatever properties belong to that name. Hope this helps :)
With error checking omitted:
const int NUM_PERSONS = 50;
const int SCORES_PER_PERSON = 7;
double scores[NUM_PERSONS][SCORES_PER_PERSON];
int ids[NUM_PERSONS];
std::string names[NUM_PERSONS];
for(int i = 0; i < NUM_PERSONS; ++i) {
file >> ids[i] >> names[i];
for(int j = 0; j < SCORES_PER_PERSON; ++j) {
file >> scores[i][j];
}
}

Bash: expand a list of coordinates (sed?)

I have a list of simple coordinates (longitude, latitude pairs) like
110 30
-120 0
130 -30
0 30
and try to expand it to this:
110 30 110\272E 30\272N 110 30 LON0
-120 0 120\272W 0\272 -120 0 LON0
130 -30 130\272E 30\272S 130 -30 LON0
0 30 0\272 30\272N 0 30 LON0
Examining the first line:
110 30 110\272E 30\272N 110 30 LON0
110 30 The first two values just stay the same
110\272E the third value is basically the first value with an added (octal \272) degree symbol and an E for positive values or a W for negative values
30\272N similar to the third value, this is the latitude with an added degree symbol and a N for positive and a S for negative values.
110 30 is just a repetition of the first two values
LON0 is a fixed string for later replacement.
Things tried so far:
I played around with sed, but was unable to achieve anything remotely useful. I wasn't able to manipulate the matched values depending on them being negative or positive.
Any help is greatly appreciated.
All the best,
Chris
EDIT: #jaypal suggested to add different possible cases that can occur. Original was only one case with minor deviations in value.
EDIT2: Had to adjust the example data due to me not updating all values in the sample data. My apologies.
Can you use awk? It will be very easy:
$ cat file
110 30
-120 0
130 -30
0 30
awk '
function abs(x) {
x = x > 0 ? x : x * -1
return x
}
{
print abs($1),abs($2), ($1>0?abs($1)"\272E":$1==0?$1"\272":abs($1)"\272W"), ($2>0?abs($2)"\272N":$2==0?$2"\272":abs($2)"\272S"), abs($1), abs($2), "LON0"
}' file
110 30 110ºE 30ºN 110 30 LON0
120 0 120ºW 0º 120 0 LON0
130 30 130ºE 30ºS 130 30 LON0
0 30 0º 30ºN 0 30 LON0
If you want to print \272 instead of º just add another backslash to prevent it from interpolating. So modify the above script and use \\272 where ever you see \272.
We print the fields as you desire in your output and the following two syntax:
($1>0?$1"\272E":$1"\272W")
($2>0?$2"\272N":$2"\272S")
are ternary operators that checks for the positivity of the values. If first is positive use E else W. If second is positive use N else use S.
Update:
awk '
function abs(x) {
x = x > 0 ? x : x * -1
return x
}
{
print $1,$2,($1>0?$1"\\272E":$1==0?$1"\\272":abs($1)"\\272W"),($2>0?$2"\\272N":$2==0?$2"\\272":abs($2)"\\272S"),$1,$2, "LON0"
}' file
110 30 110\272E 30\272N 110 30 LON0
-120 0 120\272W 0\272 -120 0 LON0
130 -30 130\272E 30\272S 130 -30 LON0
0 30 0\272 30\272N 0 30 LON0