Determine max. real number from external file

November 16, 2009 at 04:28:08
Specs: Windows XP
Hey.
I need some help with C or C++. I have to import a file.txt with real E notated (like 2.3E-12) numbers in 2 columns in it (coordinates basicly - x and y) in to C or C++ (does not matter which, I am learning both). Then I have to determine the maximum number from the second column (y) and then write out the full apropriate coordinate (x, max. y).

I managed to find out the max. y, coordinate in case I have integer numbers, the problem is I need it for real numbers, which are quite big: up to E+-30.

Another problem is the size of array. There are approx. 70000 rows in the columns, so 70000 values, from which I have to find the max. (or min.).

I wrote this code, but only works for Integers:

        #include <iostream>
        #include <fstream>

        #include <stdlib.h>
        using namespace std;


        int matrix[70000][2]; //def. matrix


        int main () {
          ifstream inFile;
          inFile.open("input.txt");

           if (!inFile) {
            cout << "Unable to open file";
            exit(1); // terminate
            }



          int numRows = 0;
          int max = matrix[0][1];
          int min = matrix[0][1];

         while (inFile >> matrix[numRows][0]) {
        //  printf ("%d\t", matrix[numRows][0]);


           inFile >> matrix[numRows][1];
         //  printf ("%d\t", matrix[numRows][1]);

              if (matrix[numRows][1] > max){
                  max = matrix[numRows][1];
                  }
              else if (matrix[numRows][1] < min){
                  min = matrix[numRows][1];
                  }

           numRows++;
          }
                      printf ("Maximum element in an array : %d\n", max);
                      printf ("Minimum element in an array : %d\n", min);

        inFile.close ();
      }

I guess you cannot import real numbers as easy as integers? Or is there a quick fix to above code?

And this code I found on the net, but I guss the buffer size is the problem here, it only works for smal number of rows:

#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;

int main()
{
   double largestNum, smallestNum;
   float values[9725];
   double sum = 0;         // holds total of all numbers
   char buffer[9725][9725];      // character arrays store numbers in "doubles.txt"
   int count = 0;

   ifstream file;
   file.open("doubles.txt");

   while(!file.eof())             // reads "doubles.txt" until end of file
   {
      file.getline(buffer[count],9725,'\n');   // reads line by line to buffer[]
      values[count] = atof(buffer[count]);      // converts char buffer[] to float values[]
      //sum += values[count];            // adds all numbers from values[]
      count++;
   }

   largestNum = values[0];    // seeding largestNum with first value
   smallestNum = values[0];   // seeding smallestNum with first value

   for(count=0;count<9725;count++)
   {
      if(values[count] < smallestNum)     // compares smallestNum to values[]
         smallestNum = values[count];  // new smallestNum stored here
      if(values[count] > largestNum)      // compares largestNum to values[]
         largestNum = values[count];   // new largestNum stored here
   }

   cout << " Largest : " << largestNum << endl; // prints largest number
   cout << "Smallest : " << smallestNum << endl;   // prints smallest number
  // cout << " Average : " << sum / 25 << endl;   // prints average

   system("pause");
   return 0;
}

Any help appreciated;)

See More: Determine max. real number from external file

Report •


#1
November 17, 2009 at 16:48:06
Hi

I have to import a file.txt with real E notated (like 2.3E-12) numbers in 2 columns in it (coordinates basicly - x and y) in to C or C++

Do you actually have to read all of the numbers into your program, or just the row containing the maximum y value?

If it's the former, then yes, you do have to create a 2D array (or some similar structure) large enough to hold them all.

I managed to find out the max. y, coordinate in case I have integer numbers, the problem is I need it for real numbers, which are quite big: up to E+-30.

That shouldn't be a problem. Just use double instead of int. You can read doubles in scientific notation using

ifstream::operator<<(double)

Another problem is the size of array. There are approx. 70000 rows in the columns, so 70000 values, from which I have to find the max. (or min.).

Again, you can find the max without using the array. Just keep a pair of doubles (x_corresponding_to_max_y, and max_y) for the max Y read so far. Use another couple of doubles to read from the file. As you read each line from the file, compare with the max_y value.

I wrote this code, but only works for Integers:

#include <iostream>
#include <fstream>
#include <stdlib.h>

Decide if you want C or C++. In C++, there is no <stdlib.h>, it's <cstdlib>.

exit(1); // terminate

Beware of using exit() in C++. It exits abruptly, without running any destructors. It's benign in your example, but in larger programs it can cause problems. Better to use the return statement to return from main().


int min = matrix[0][1];

Here you are assigning the value of matrix[0][1] (which is initialized to 0) to min.
So min is now set to 0. That's not quite what you want.


else if (matrix[numRows][1] < min){

Only true if the value read from the file is negative. Not what you want. Run your program with a file where the lowest value is 1, and your program will tell you the lowest is 0.

Think about how to initialize min and max. Some people use the lowest & highest possible values (e.g. INT_MIN and INT_MAX) while others set them to the first number read from the file. You have probably tried to do the latter but you've set them too early, before you started reading.

I guess you cannot import real numbers as easy as integers?

You can. Just as easy. Just declare them as double instead of int.

And this code I found on the net, but I guss the buffer size is the problem here, it only works for smal number of rows

I guess there's nothing intrinsically wrong with reading example code from the net for learning purposes, as long as you can fully understand it and criticise it properly. The code you found on the net may work some of the time, but the use of a character buffer is wasteful and unnecessary.

I hope my comments help. Good luck.


Report •

#2
November 18, 2009 at 03:16:05
Thnx, Klint, it is helpful.

Do you actually have to read all of the numbers into your program, or just the row containing the maximum y value?

If it's the former, then yes, you do have to create a 2D array (or some similar structure) large enough to hold them all.

I just need the maximum of the y value. The other rows don`t matter, just (x_corresponding_to_max_y, and max_y).

Again, you can find the max without using the array. Just keep a pair of doubles (x_corresponding_to_max_y, and max_y) for the max Y read so far. Use another couple of doubles to read from the file. As you read each line from the file, compare with the max_y value.

So what you are saying is, I do not need to buffer al the values in the column in arrays as it is done in the secound example code I posted? And can start from this:

while (inFile >> matrix[numRows][0]) {
        //  reads the first column, x values and then...

            

           inFile >> matrix[numRows][1];
         //  ...the coresponding y values

        //from y values read, it determines max y and min y 
              if (matrix[numRows][1] > max){
                  max = matrix[numRows][1];
                  }
              else if (matrix[numRows][1] < min){
                  min = matrix[numRows][1];
                  } 

           numRows++;
          }



int min = matrix[0][1];

Here you are assigning the value of matrix[0][1] (which is initialized to 0) to min.
So min is now set to 0. That's not quite what you want.


else if (matrix[numRows][1] < min){

Only true if the value read from the file is negative. Not what you want. Run your program with a file where the lowest value is 1, and your program will tell you the lowest is 0.

Think about how to initialize min and max. Some people use the lowest & highest possible values (e.g. INT_MIN and INT_MAX) while others set them to the first number read from the file. You have probably tried to do the latter but you've set them too early, before you started reading.

Yes, I tried to set the initial values to the first number read from the file, but was not working correct, since it outputed 0, in cases you mentioned. I will try moving it inside the reading loop, that is what you meant shoul fix it, right?

Just use double instead of int. You can read doubles in scientific notation using

ifstream::operator<<(double)

Thnx, that was missing to do that, I will try to implement it this way.


Report •

#3
November 18, 2009 at 05:33:29
This is what I have now, but I can`t make it read doubles. How should I use "ifstream::operator<<(double)"? I tried several times, but does not compile. Also, I am not sure if this code would run with the full input file, having 70 000 - 500 000 rows of numbers, I guess there is no reason it shouldn`t?:)

Like this, it returns 0 (initial values are not the problem, I think, in my oppinion import should be read correctly), when run with testing 2 column double numbers.

 
        #include <iostream>
        #include <fstream>
        #include <cstdlib>
        #include <limits.h>
        using namespace std;


        double matrix[70000][2];

        int main () {

          ifstream inFile;
          inFile.open("input.txt");  
      //how to make it read double?
      //ifstream::operator<<(double) inFile does not compile...

           if (!inFile) {
            cout << "Unable to open file";
            return 0;
            }


          int numRows = 0;
          double min = INT_MAX;
          double max = INT_MIN;

         while (inFile >> matrix[numRows][0]) {
   
           inFile >> matrix[numRows][1];
    
              if (matrix[numRows][1] > max){
                  max = matrix[numRows][1];
                  }
              else if (matrix[numRows][1] < min){
                  min = matrix[numRows][1];
                  }

           numRows++;
           printf ("\n");
          }
                      printf ("Maximum element in an array : %d\n", max);
                      printf ("Minimum element in an array : %d\n", min);

        inFile.close ();
        return 0;
      }


Report •

Related Solutions

#4
November 18, 2009 at 06:24:16
Sorry, I meant

ifstream::operator>>(double)

(got the arrows the wrong way around)


//how to make it read double?
//ifstream::operator<<(double) inFile does not compile...

No, not like that, inFile is the ifstream object, you just need to do what you're already doing, infile >> number.

Other points:

1. don't use INT_MAX and INT_MIN, there are equivalent for double, but can't remember what they're called. Or just read the first line (containing the first pair of values) (not in a loop), set both the min and max to this, then read the remaining lines from the file (in a loop).

2. Don't use arrays. Your program should be capable of dealing with arbitrarily large files, more than you have RAM.


Report •

#5
November 18, 2009 at 06:39:26
Thnx! Will try that.

Report •

#6
November 20, 2009 at 08:28:14
klint: there are equivalent for double
Since we're using C++, we have access to numeric_limits<double>::max() and numeric_limits<double>::min(), as defined in limits.

quack: while (inFile >> matrix[numRows][0]) {
Get away from using 2D arrays. You do not need it for this application.


Report •

#7
November 20, 2009 at 10:49:25
This is the code put together with all help now:

  
        #include <iostream>
        #include <fstream>
        #include <limits>
        using namespace std;


        int main ( void ) {

          ifstream inFile;
          inFile.open("input.txt");

           if (!inFile) {
            cout << "Unable to open file";
            return 0;
            }

          double matric[2];
          double max = 5.2; //initial value from txt
          double min = 5.2; //initial value from txt

         while (inFile >> matric[0]) {
                inFile >> matric[1];

              if (matric[1] > max){
                  max = matric[1];
                  }
              else if (matric[1] < min){
                  min = matric[1];
                  }
          }

          cout<<"Maximum y is: "<<max<<"\n";
          cout<<"Minimum y is: "<<min<<"\n";

        return 0;
      }


Works for large files, since it only stores 2 values: current x and y values and runs through the input.txt, comparing max and min value. I will make it output (x, max y) and (x, min y) later, that is why reading both, matric [0] and matric[1].

I had problems with

double max = numeric_limits<double>::max(); 
double min = numeric_limits<double>::max();

max doesn`t return the correct number, outputs 1.79769e+308.

Any idea what I am missing and how to make it read the initial value itself?

double max = matric[1]; 
double min = matric[1]; 

Seems to work in case of doubles, but I am not sure if it has some "bug" to?

I have to know there are no problems with the code, before
I run it on the files, I have to (there will be no way or very little of knowing it did not determine max value correct just for some files...).

Thnx for all the help!


Report •

#8
November 20, 2009 at 11:06:02
double max = numeric_limits<double>::min(); 
double min = numeric_limits<double>::max();


Report •

#9
November 20, 2009 at 11:08:09
Razor2.3, I tried that, just does not work in all cases or I missed something...

PS: Ahaa! Thnx! I missed, reverse min and max! Thnx! Works, for now:)

__________________
As I said, with help;) :

 
        #include <iostream>
        #include <fstream>
        #include <limits>
        using namespace std;


        int main ( void ) {

          ifstream inFile;
          inFile.open("input.txt");

           if (!inFile) {
            cout << "Unable to open file";
            return 0;
            }

          double matrix[2];
          double max[2] = {matrix[0], matrix[1]};   
          double min[2] = {matrix[0], matrix[1]};  

         while (inFile >> matrix[0]) {
                inFile >> matrix[1];

              if (matrix[1] > max[1]){
                  max[0] = matrix[0];
                  max[1] = matrix[1];
                  }
              else if (matrix[1] < min[1]){
                  min[0] = matrix[0];
                  min[1] = matrix[1];
                  }
          }

   cout<<"Maximum (x,max_y) is: "<<max[0]<<","<<max[1]<<"\n";
   cout<<"Minimum (x,min_y) is: "<<min[0]<<","<<min[1]<<"\n";

  ofstream myfile;
  myfile.open ("out.txt");
  myfile <<max[0]<<" "<<max[1]<<"\n";
  myfile.close();

        return 0;
      }


Do you find any errors?

Thnx!


Report •

#10
November 20, 2009 at 11:33:21
1) You're not using the numeric_limits<double>. You have two options: either use the limits, or make sure you read something into matrix before assigning a value to min / max.

2) else if (matrix[1] < min[1]){
Get rid of the else, especially if you go the limits route.

3) while (inFile >> matrix[0]) {
inFile >> matrix[1];

Things will break if you have an odd amount of numbers. If you with to ignore the last number if it has no partner:

while (inFile >> matrix[0] >> matrix[1]) {


Report •

#11
November 20, 2009 at 12:08:18
Thanks for all help! Just posting the final result in full code, in case some newbie like me will need sth. similar...

#include <iostream>
        #include <fstream>
        #include <limits>
        using namespace std;


        int main ( void ) {

          ifstream inFile;
          inFile.open("input.txt");

           if (!inFile) {
            cout << "Unable to open file";
            return 0;
            }

          double matrix[2];
          double max[2] = {matrix[0], numeric_limits<double>::min()};   
          double min[2] = {matrix[0], numeric_limits<double>::max()};  

         while (inFile >> matrix[0] >> matrix[1]) {
               
              if (matrix[1] > max[1]){
                  max[0] = matrix[0];
                  max[1] = matrix[1];
                  }
              if (matrix[1] < min[1]){
                  min[0] = matrix[0];
                  min[1] = matrix[1];
                  }
          }

   cout<<"Maximum (x,max_y) is: "<<max[0]<<","<<max[1]<<"\n";
   cout<<"Minimum (x,min_y) is: "<<min[0]<<","<<min[1]<<"\n";

  ofstream myfile;
  myfile.open ("out.txt");
  myfile <<max[0]<<" "<<max[1]<<"\n";
  myfile.close();

        return 0;
      }


Report •


Ask Question