views:

143

answers:

5

i am really struggling to load some numeric floating point data from a file into a C program...the file has floating point numbers with precision of 3 decimal points, each of which is in a single line...i wanted to load these values into an float array and then perform some calculations in it...however i tried loading it into an array of floats but it didn't store the values properly...i.e values like 123.45 were stored as 123.44999 or something..but i don't want this.

i tried to store this in a array of strings and then may be convert them into scaled integers. but i cannot get it to load into an array of string. can anyone tell me where i am going wrong. what i did is something like this.

unsigned char **data
............
data = malloc(sizeof(unsigned char *) * fileSize);  
............
while (!feof(fp))
{
if (fscanf (fp, "%s",  &data[j]) == 1) // if converted, increment counter
 ++j; 
}
...........

i am a newbie so i am not so good with pointers. and after i load it into an string array, how do i convert it into scaled integers?

A: 

Unfortunately all you are hitting is the fact that some numbers cannot be accurately represented with a floating point data type. If you manually assigned 124.45 to a float in C (i.e. float f = 123.45) you get exactly the same problem.

Do you really need the level of accuracy? What are you plans for the data?

tyranid
+4  A: 

You may not have much choice when it comes to floating point numbers like 123.45 being displayed as 123.44999

The 'inaccuracy' of floating point representations has been discussed many times on SO, here's one example.

I would suggest you go back to treating the input as floats, but read up on accuracy issues.

pavium
+1 for correcting the underlying flawed floating point assumptions
Niels Castle
123.45 wouldn't display as 123.44999 if you only displayed it to 2dp. In other words, 123.45 == 123.44999 to 2dp, and as long as you don't make the mistake of printing out more precision in any results than you had in the numbers in the first place, you should be OK.
Tony van der Peet
+1  A: 

don't use float, use double.

also you can use

double d;

read(d);

(int)(d*100) to get the int.

Yin Zhu
Careful! You don't want to truncate the result multiplied by 100, because then you would lose the precision.Try (int)(d*100+0.5)Otherwise 123.45, stored as 123.44999 would end up as 12344
Tony van der Peet
using double seems to work for me.
sfactor
@Tony thanks for pointing out:)
Yin Zhu
A: 

I would suggest that you use an ifstream to read into a string then convert it to a double.

string number;
ifstream yourfile("yourfile", ios::in);

if(yourfile)
 while(yourfile >> number){
     double yourFloat=strtod( number.c_str() );
    }
wahkiz
He isn't using C++
Nikola Smiljanić
A: 

How essential is this precision to your application? Floating point numbers can often be slightly inaccurate because they store numbers in a base 2 (binary) representation which cannot properly represent some base-10 numbers.

You have a few options, depending upon how important this precision is to your app.

  1. Live with it. Maybe this inaccuracy isn't a problem for your application
  2. Use Double. It has twice the space to represent numbers, and will be more accurate. It can still be inaccurate in some cases.
  3. Use fixed point math. If you only need to go to n decimal places, it might be worth looking this approach (as it eliminates the source of inaccuracy).
  4. Keep the float as a character string or store it as a Binary Coded Decimal. You'll need to write functions for any mathematical operations you need and performance will be the poorest of these 4 options. But, you'll be able to work with decimal numbers of arbitrary precision without worrying about any loss of precision.

Options 3 or 4 require either the use of an external library, or rolling your own implementation. If 1 or 2 is good enough, then I wouldn't bother with these options.

Adam Luchjenbroers
yes using double does work
sfactor