Looking for some way to get correct value with long precision

D

Dew

Hi All
The problem is related to strtod()/atof()'s well known behaviour.
strtod()/atof() add some extra digits at the end of precision while
converting from string to double. Becasue floating-point variables
cannot represent all numbers precisely, I'm looking some way around to
solve it explicitly in the code itself so that I could get the value
property = 999999999998.90000000 for precison=8 instead of
property=999999999998.90002441

Size of float and double both is 8 bytes in my machine. and I'm using
xlC compiler on AIX plateform.


Any clue will help me immensely. Thanks.


#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<wchar.h>
#include<math.h>
#include<float.h>

int main(int argc, char* argv[])
{
char property[1024];
int precison=0;
memset(property, '\0', sizeof(property));
strcpy(property, argv[1]);
precison = atoi(argv[2]);
cout <<"property: \"" << property << "\"" << endl;
//sscanf ( property, "%Lf", &dl);
//sprintf(PrpValue1, "%.*lf", precison,property);

double doubleVal=0.0;

if (strstr(property,"E+") != NULL || strstr(property,"E-") != NULL)
{
doubleVal = ( long double)strtod(property, (char **)NULL);
//doubleVal = atof(property);
printf("doubleVal:%.*lf\n",precison,doubleVal);
sprintf(property, "%.*lf", precison,doubleVal);
cout <<"E+/- :property: " << property << endl;
}

cout <<"final property: " << property << endl;
free(property);
return 0;
}

Here's the o/p.
/a.out 9.999999999989E+11 8

property: "9.999999999989E+11"
doubleVal:999999999998.90002441
E+/- :property: 999999999998.90002441
final property: 999999999998.90002441
 
O

Olaf van der Spek

Hi All
The problem is related to strtod()/atof()'s well known behaviour.
strtod()/atof() add some extra digits at the end of precision while
converting from string to double. Becasue floating-point variables

It's not behaviour of strtod or atof but behaviour of float/double.
cannot represent all numbers precisely, I'm looking some way around to
solve it explicitly in the code itself so that I could get the value
property = 999999999998.90000000 for precison=8 instead of

Just use rounding before outputting values.
 
D

Dew

Hi Olaf,
Thanks for reply.
doubleVal = 999999999998.90002441 , which is returned from strtod call
have

Now I am doing rounding as well till the length precison .. but it cant
help me.
sprintf(property, "%.*lf", precison,doubleVal);

I also have tried flor().

Are you aware of any rounding techniques that allow control of decimal
point length or do I need to create my own rounding function ?

Thanks.
 
D

Dew

Hi,
Infact I need to replace the extra digit (2441) added by
strtod()/atof() in the last of precission, by 0000. will round tech
will help here ?
any clue ?
 
D

Dew

I am trying something like
1.
doubleVal = ( long double)strtod(property, (char **)NULL); // give me
999999999998.90002441
double dl = doubleVal * 10000000;
double res = floor(dl)/10000000;] // give me 1e+12

2.
printf("doubleVal:%.*lf\n",precison,doubleVal); //give me
999999999998.90002441

3. printf("doubleVal:%.8g\n",doubleVal) // give me 1e+12

any way around to get 999999999998.90000000 ?
 
O

Olaf van der Spek

any way around to get 999999999998.90000000 ?

Ah.

A 64-bit double has only 15 significant digits. So no, you it doesn't
have enough precision for what you wish to do.
 
P

Puppet_Sock

Dew said:
property = 999999999998.90000000 for precison=8 instead of
property=999999999998.90002441

Olaf gave the correct answer, but it may be good to expand
on it.

A double only has about 15 significant digits. So, in your
values there, that takes you to 999999999998.900 roughly.
Exactly where it ends is dependent on the specific value,
as it isn't storing things as decimal digits, but as a
binary representation of a float.

Anyway, what that means is anything past the .900
is noise. It is not significant, and there is no correct
nor incorrect value for it. So, a desire to get .90000000
(or any other specific value) is misplaced. No matter
what it tells you, the value is no better, nor worse,
than any other value. Anything from .90000000 to
..90099999 is as good as any other value in the range.
If you ask the prog to produce values there, it makes
it up somehow, but the values don't mean anything.

If you *need* more digits than is held by a double, there
are a few choices for you.

One choice is, obtain a library of math operations that
gives you the number of digits you require. There are
several such on the net. You could start with the
FAQ link posted frequently here. If you go this route,
you need to be prepared to accept the extra run time
it is likely to consume to run a math heavy app.
On many hardwares, doubles are done through a math
co-processor and are quite fast as long as you live
in the range they hold. Going outside this range is
likely to mean overhead. Though this is not a hard
and fast rule, and in many cases the change may
be acceptable or even very small.

Another choice is to refactor your calculation. Suppose
you were able to change the form of your calculation
so that it was something like so: The answer you
want is 999999999998.900 exactly plus some
extra value that is less (in magnitude) than .001.
For example, you might be able to convert it to
a perturbation calculation where you know the main
answer and only need to calculate the difference
due to some (hopefully small) influence. This is a
common method in physics and engineering.
This method probably means a lot of design and
theory effort, and may also increase the complexity
of your app.
Socks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top