charest@ai-ganymede.JPL.NASA.GOV (Len Charest) (08/22/90)
I have a large (~40 MB) file of floating point values stored in binary under the following format: float = 32-bit word bit 31 = sign bit for exponent bits 30-23 = exponent (8 bits) bits 22-0 = mantissa (always positive) (Apparently this is some IEEE standard.) The floats are stored in contiguous "records" of length N, where N is determined at *run-time*. This means that I can minimize the number of calls to fscanf by reading an entire record of floats from the disk (as an array of chars) and then parsing the record in C. Example: let N = 256 /* N is known a priori for now */ unsigned char record[N + 1]; /* add one for terminating `\0` */ fscanf(fp, "%256s", record); /* read the record from disk */ Now how do I interpret each 4-byte "word" of record as a floating point number? I merely need to print each float onto stdout. However, I've been away from C programming for a while and I'm confused about how to solve this problem. I am assuming that the fscanf library function does not alter the bits it reads when the conversion spec indicates a character string. That is, interpretation of the raw bits stored on file should be completely under my control. On the other hand, I really would like to avoid writing a mammoth floating point conversion routine. Suggestions/solutions are greatly appreciated. Respond to this list or directly to me at charest@ai-cyclops.jpl.nasa.gov Thanx, Len
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (08/22/90)
In article <9232@jpl-devvax.JPL.NASA.GOV>, charest@ai-ganymede.JPL.NASA.GOV (Len Charest) writes: > I have a large (~40 MB) file of floating point values stored in binary > [using IEEE-754 single precision (32-bit) format] > The floats are stored in contiguous "records" of length N, where N is > determined at *run-time*. This means that I can minimize the number of > calls to fscanf by reading an entire record of floats from the disk (as > an array of chars) and then parsing the record in C. Ick. You can't use fscanf() with such data *at all*. fscanf() is for reading *text*. To read a record of N bytes as N/4 floats, do #define N /*whatever*/ #define NFLOATS ((N)/sizeof (float)) float the_record[NFLOATS]; int floats_read; ... floats_read = fread(the_record, sizeof (float), NFLOATS, the_stream); Now you have 32-bit floats in memory and can do printf("%g", the_record[floats_read-1]) or whatever takes your fancy. -- The taxonomy of Pleistocene equids is in a state of confusion.
tchrist@convex.COM (Tom Christiansen) (08/22/90)
In article <9232@jpl-devvax.JPL.NASA.GOV> charest@AI-Cyclops.JPL.NASA.GOV writes: >I have a large (~40 MB) file of floating point values stored in binary >Now how do I interpret each 4-byte "word" of record as a floating point number? >I merely need to print each float onto stdout. If I understand your problem, it's pretty easy to solve. They're floats on the disk, so read them in that way. I assume that your machine is also in IEEE format. Otherwise you'll have to write an IEEE- to-native conversion function, probably using bit fields or bit masks. The simple case (same FP format) is easy. I use stdio because you did and it optimizes the I/O buffering pretty well. /* * read n floats in binary from stdio pointer fp, * printing on stdout one per line. returns i/o success. * CAVEAT EMPTOR: untested */ #define FOK(F) (!(feof(F) || ferror(F))) read_floats(fp, n) FILE *fp; int n; { float num; ASSERT(fp != NULL); ASSERT(n > 0); while (FOK(fp) && n-- && fread(&num, sizeof(num), 1, fp)) printf("%14.8f\n", num); return FOK(fp); } --tom -- "UNIX was never designed to keep people from doing stupid things, because that policy would also keep them from doing clever things." [Doug Gwyn]