views:

442

answers:

6

i am developing a code where i have to load floating point values stored in each line at a time in a text file...i loaded each of these data into a array of floats using fscanf()...however i found that the floating points were stored in a different way, example 407.18 was stored as 407.179993, 414.35 as 414.350006...now i am stuck because it is absolutely important that the numbers be stored in the form they were in the file but here it seems to be different even though essentially its the same....how do i get the numbers to store in the original form?

+17  A: 

If it's absolutely important that the numbers be stored in the form they were in the file, don't use floating-point values. Not all fractional base-10 values can be represented exactly in binary.

For details, you should consult the article "What Every Computer Scientist Should Know About Floating-Point Arithmetic" [PDF link].

You should store the numbers in string form or as scaled integers.

James McNellis
+11  A: 

What you see is correct since floating point cannot exactly represent many real numbers. This is a must-read: What Every Computer Scientist Should Know About Floating-Point Arithmetic

Jim Buck
+1 for the link to the article; I didn't know there was an HTML version (and, I apologize if I added the link after you answered; I was editing my answer and didn't see yours until I posted it).
James McNellis
+2  A: 

The C++ float and double types are represented as IEEE floating point numbers. There are binary floating point numbers, not decimals. They don't have infinite precision, and even relatively 'simple' decimal values will change when converted to binary floating point and back.

Languages that focus on money (COBOL and PL/I, e.g.) have decimal data types that use slower representations that don't have this problem. There are libraries for this purpose in C or C++, or you can use scaled integers if you don't need too much range.

bmargulies
A: 

You might want to take a look at an existing library that implements floating point with controlled rounding. I have used MPFR. It is fast and open source. If you are working with money then a different library would be better.

Philip Schlump
+2  A: 

sfactor, A bit of clarification: you state "...absolutely important that the numbers be stored in the form they were in the file" - what 'form' is this? I'm assuming a display form?! Here's the deal: If you store in the file 407.18, but it is displayed as 407.179993 - this is totally normal and expected. When you construct your sprintf or whatever formatted print you are using, you must instruct it to limit the precision after the decimal point. This should do the trick:

#include <stdio.h>
void main(void);
void main()
{
   printf("%.2f",407.179993);
}
TheEruditeTroglodyte
A: 

There is a lot of different ways to store numbers - each with their strenghts and weaknesses.

In your case floating point numbers are not the best choice because they don't represent most real numbers exactly.

Scaled integers is a case of the common design idiom: separate representation from the presentation.

Decide on how many digits you want after the decimal point, eg. 2 digits as in 123,45. You should then internaly represent the number as the integer 12345. Whenever you display the value to the user you should insert a decimal point at the relevant spot.

Short InformIT article on Scaled Integers by Danny Kalev

Before going overboard on scaled integers do inspect the domain of your problem closely to assert that the "slack" in the floating point numbers is significant enough to warrent using scaled integers.

Niels Castle