LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   C- precision problem (https://www.linuxquestions.org/questions/programming-9/c-precision-problem-401146/)

vivekr 01-09-2006 06:25 AM

C- precision problem
 
Hai,
Is it possible to display more than 16 digits after a decimal point, even if they cycle in a C program.

To be clear:
1/57 Result: fraction that displays 16 digits afetr decimal point and then only zeroes how can I display more digits

Thanks for the solutions

graemef 01-09-2006 07:01 AM

What data type are you using? float, double or long double?

What format specifier are you using %e %f %g or (%Le %Lf %Lg for long)

graeme.

jtshaw 01-09-2006 07:33 AM

Here is an example:

Code:

#include <stdio.h>

int main (void)
{
    float fans;
    double dans;
    long double ldans;
    long double nocast;

    fans = ((float) 1) / ((float) 57);
    dans = ((double) 1) / ((double) 57);
    ldans = ((long double) 1) / ((long double) 57);
    nocast = 1/57;

    printf ("Float = %0.80f\n",fans);
    printf ("Double = %0.80f\n",dans);
    printf ("Long Double = %0.80Lf\n",ldans);
    printf ("Long Double (no print length arguments)  = %Lf\n",ldans);
    printf ("Long Double (nocast) = %0.80Lf\n",nocast);

    return 0;
}

Results:
Code:

j_shaw@jshaw ~ $ ./test
Float = 0.01754385977983474731445312500000000000000000000000000000000000000000000000000000
Double = 0.01754385964912280604366401348670478910207748413085937500000000000000000000000000
Long Double = 0.01754385964912280701775190282915017903064835991244763135910034179687500000000000
Long Double (no print length arguments)  = 0.017544
Long Double (nocast) = 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000

The "no print length arguments" example was to show that printf doesn't automatically print to the max precision of the number. If you want to see a large amount of digits after the decimal point you have to specify so in your formatting like I did with the %0.80Lf which asks for 80 digits after the decimal.

I put in the example without a cast to prove a point.... if you are going to use double or long double for precision make sure you do all your math in the right precision or you'll end up with results you probably don't expect...

vivekr 01-09-2006 07:40 AM

Excuse me for providing so little info for analysis.
By the way the code that tries the problem is here...

Code:

void main()
{
        long double numerator,denominator;
        long double fraction;
        scanf("%Lf %Lf",&numerator,&denominator);
        fraction=numerator/denominator;
       
        printf("%.100Lf",fraction);
}

And I it seems "%Lg" control string removes the trailing zeroes. Is it so? There isn't any other apparent change between the "%Lf" and "%Lg"

jtshaw 01-09-2006 07:45 AM

What is the output your getting with your code?

I got all the precision I would have expected.

Code:

j_shaw@jshaw ~ $ ./test
1 57
0.0175438596491228070177519028291501790306483599124476313591003417968750000000000000000000000000000000


graemef 01-09-2006 08:07 AM

ditto...

using fedora 4, gcc 4.0.2, run from the console and the code provided the output was as expected. (after adding the required #include)

If you are still not getting the output can you tell us the compiler version and anything different you may be doing?

graeme

vivekr 01-09-2006 08:10 AM

Sorry jitshaw for..
1. missing ur post by a whisker
2. I was actually working on MS Visual studion then and its output doesnt seem to be altered by the type casts.
3. For delaying my response
Now in gcc its goin fine and I am able to get the results even without typecasts.

Thanks for ur response..
And here is one another bug in Visual Studio

-----------------------

I missed ur post too graemef sorry--

graemef 01-09-2006 08:12 AM

are you using gcc in windows or Linux - I seem to remember that gcc in windows doesn't support the L modifier and so the output is restricted. That may have been fixed not certain.

graeme.

vivekr 01-09-2006 08:14 AM

No..
I switched to my Linux(Fedora) to run that
By the way what is that L modifier?

graemef 01-09-2006 08:45 AM

It's a type modifier used for long precision L = long. I believe it is the standard but it not always supported.

graeme.

vivekr 01-09-2006 09:09 AM

Are u sure?
But it is a part of K & R specificaions .. isnt it?

jtshaw 01-09-2006 10:07 AM

The L specifier applied to a, A, e, E, f, F, g, or G is a part of the C99 specification. The SUSv2 spec also contains the L specifier for all conversions except F.

sirclif 01-09-2006 03:11 PM

Quote:

Hai,
Is it possible to display more than 16 digits after a decimal point, even if they cycle in a C program.

To be clear:
1/57 Result: fraction that displays 16 digits afetr decimal point and then only zeroes how can I display more digits
you can only display the data the computer has stored. You get 16 digits because that's all that is there.

Also of note is that the digits at the end of that string probably aren't even right. If you do several arithmatic operations you get a truncation error that will build up, and can be the main source of error in many scientific modeling applications.

Warg 01-09-2006 05:57 PM

Quote:

Originally Posted by sirclif
you can only display the data the computer has stored. You get 16 digits because that's all that is there.

Also of note is that the digits at the end of that string probably aren't even right. If you do several arithmatic operations you get a truncation error that will build up, and can be the main source of error in many scientific modeling applications.

While you're at it, could you tell me why the following code (supposed to print the value of the constant "e" with 40 digits precision) isn't so precise from the 16th digit after the decimal point onwards?


Code:

/*computes constant e*/

#include <stdio.h>

long double fact(int n)
{
        long double sum;
        sum = n;

        if(n == 0)
                return 1;
        else
        {
                while(n != 1)
                {
                        sum = sum * (n - 1);
                        n = n - 1;
                }
       
        return sum;
        }
}

       
main()
{

int k, counter;

double e;

k = e = 0;

for(counter = 0; counter < 100; counter++)

    {
        e = e + (1.0/fact(k));
        ++k;
    }

printf("%.40f\n", e);

}


jtshaw 01-09-2006 06:26 PM

Warg,
You have a few cast converstion problems going on there. The most drastic is that e is declared as a double instead of a long double. You going to loose precision each time you return from fact because your putting a long double result into a double variable.

I've made a few changes that make it better... though you probably want to get a high precision math library if you really need that much precision.

Code:

/*computes constant e*/

#include <stdio.h>

long double fact(long double n)
{
        long double sum;
        sum = n;

        if(n == 0)
                return 1;
        else
        {
                while(n != 1)
                {
                        sum = sum * (n - 1);
                        n = n - 1;
                }

                return sum;
        }
}


int main()
{

        int counter;

        long double e, k;

        k = e = 0;

        for(counter = 0; counter < 100; counter++)

        {
                e = e + (1.0/fact(k));
                ++k;
        }

        printf("%.40Lf\n", e);
        return 0;
}



All times are GMT -5. The time now is 01:15 AM.