TIniFile->ReadFloat ---> precision changes

Hi,

when i have in inifile:
valueX = 1,12

and i do
float x = ini->ReadFloat("some","valueX",0);

then x is not 1,12 but 1,12005678123 or something.  The precision has changed.  Anyone knows how i can easily solve this??

Thanks!

cleaverXAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

SteHCommented:
What is your exact problem. On type of precision is the one for displaying a number. This effects only the output.
1.12000000000
1.12005678123
both have the same precision (11 digits after the decimal point).

Or are you concerned about the difference between those numbers? This is more likely to be a problem of change of base. For humans the decimal system is the one we are used to. Each digits can be 0-9. In the PC floating point numbers are represented similar to a scientific notation (1.12e0) but in a binary system. 1.12 seems to have no exact conversion to a floating point in the 2 base system. The nearest value is 1.12005678123.  To test for equality using floats it is safer to use
if (fabs (x - 1.12) < 0.00001)
instead of
if (x == 1.12)

Was this your question?
0
cleaverXAuthor Commented:
SteH,

i need to work with correct floats.  When the inifile says  ValueX = 1,12 then i need a float that = 1,12.

It must NOT be 1,120123456 or something.  I can live with 1.12000000, 'cause that still is 1,12.  I only want to have the correct value to be in the float.
0
cleaverXAuthor Commented:
<<<<<Or are you concerned about the difference between those numbers?>>>>
YES, that's it
0
Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

SteHCommented:
I am not sure what internal format TIniFile uses but it seems to be float. There 1.12 is at most 1.12000. Going to double 1.1200000000000 can be achieved. Perhaps you can try it with ->ReadString and convert the string into a double and remove the last digits.
0
rstaveleyCommented:
If you compare a single precision float with a double precision constant, you will often find a difference. If you need to work in single precision make sure that your constants are also in single precision to avoid unexpected *apparent* loss of precision due to single->double promotion. I say *apparent* because what's really happening, is that you are attempting to deal with greater precision than you actually have, when single precision values are promoted to double precision.
--------8<--------
#include <iostream>
#include <cmath>

int main()
{
        float f = 0.7; // Effectively this assignment is f = 0.7f, because f is single precision
        std::cout << "Difference between f and its double precision assignment is " << fabs(f-0.7) << '\n';
        std::cout << "Difference between f and its single precision assignment is " << fabs(f-0.7f) << '\n';
}
--------8<--------

If you get values like 1.12005678123, where you'd expect to have 1.12000000000, you are looking at the result of a calculation in which the error has become at least +/- 0.00006. You should be aware of (i.e. calculate) your error bounds and ensure that you display values to their appropriate precision.
--------8<--------
#include <iostream>
#include <cmath>
#include <iomanip>

int main()
{
        float f = 1.12005678123; // Result of a calculation (say) with 0.1% error
        std::cout << "f is " << std::fixed << std::setprecision(3) << f << " (to 3 decimal places)\n";
}
--------8<--------
0
cleaverXAuthor Commented:
rstaveley,

in your example

  std::cout << "f is " << std::fixed << std::setprecision(3) << f << " (to 3 decimal places)\n";

the correct precision is set and displayed.  Can you set the correct precision directly to the float, before you display it.  What i mean is, can you do something like this:

float f1 = 0.1;    //precision = 10%
float f2 = 0.12;  //precision = 1%
float f3 = f1 * f2;   //maximum precision is 10 %; can you set the precision of 10% directly to f3, or can it only be set when you display it?


Thanks
0
SteHCommented:
The precision rstaveley is only affecting the output in the string. It does not change the binary representation of the variable. What you might want is to do:

float f1 = 0.1f;
float f2 = 0.12f;
float f3 = 0.1 * floor (10. * (f1 * f2)); // all digits except the first after the decimal point are removed from the variable.

But do you really need this? Use a formatted output to get the desired precision when printing the var.
0
rstaveleyCommented:
> Can you set the correct precision directly to the float, before you display it.

No a float is primitive. It only stores a value. You need to store the error separately. The error is meta data.

If you asked me how tall I was and I said 187.9 cm and you wanted to put it into your program, you'd probably choose to put it into a floating point variable. The floating point variable has the ability to store the variable with a precision which is greater than the precision of the response I gave, so for completeness you should store the measurement and the error - i.e. 187.9 +/- 0.05 - because I didn't say 187.9000 +/- 0.00005 and by simply storing the value you lose the information indicating how precise the value is.

You could really do with a class which stores the value with its error and define a << operator to get the value to desplay to an appropriate number of significant decial places. The onus would still be with you to calculate errors.

e.g.

    class DoubleWithError {
    double value,error;
    //....
    };

I don't know of the existence of such a class, but I'm sure somebody has already come up with something like this with arithmetic operators which calculate errors appropriately. It is usually at this point that EE expert burcarpat points out something already in existence in the boost libraries!

e.g. This would be nice:

     DoubleWithError x(187.9,0.05);
     DoubleWithError y(10.0,0.05);
     DoubleWithError z = x * y;
     std::cout << "The answer is: " << z << '\n';

     which could display
        The answer is: 1879.0 +/- 9.9  (using display precision set by yourself)
     or
        The answer is: 1.8790e3 +/- 9.9e0 (using display precision set by yourself)
     or
        The answer is: 1.88e3  (using display precision calculated automatically to be appropriate for the error)
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.