Thread: Calculating e constant - Returning the same incorrect value

  1. #1
    Registered User
    Join Date
    Feb 2017
    Posts
    27

    Calculating e constant - Returning the same incorrect value

    Hi everyone,

    So, I have a 'mostly' functional program that calculates the approximate value of the mathematical constant e.

    e = 1 + 1/1! + 1/2! + 1/3! + ... + 1/n!

    The user enters an arbitrarily small number (epsilon) that is <= 1/n!, which is used to calculate e.

    Here's my current program:

    Code:
    #include<stdio.h>
    
    
    double eConstant(double epsilon);
    
    
    int main (void)
    {
        double epsilon;
    
    
        printf("Please enter a number for epsilon: ");
        scanf("%ld", &epsilon);
    
    
        printf("The value of 'e' is : %.20f", eConstant(epsilon));
    
    
        return 0;
    }
    
    
    double eConstant(double epsilon)
    {
        double e = 1.0;
        double factorial = 1.0;
        int i = 1;
        double toAdd = 0.0;
    
    
        for(;;){
            toAdd = 1.0/factorial;
    
    
            if (toAdd < epsilon)
                return e;
    
    
            e += toAdd;
            i++;
            factorial *= i;
        }
        return e;
    }
    Unfortunately, no matter what I input for epsilon, I'm constantly getting:

    2.71828182845904550000

    Is there any reason for this? Does it have something to do with doubles and rounding issues? Or is there a fundamental error in my code that I'm just oblivious to?

    Sorry if it's something really basic (I feel it might be), I've been going over this code for the past hour and can't find my error

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    What epsilon is being used?
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  3. #3
    Registered User
    Join Date
    Feb 2017
    Posts
    27
    @stahta01

    Here's the test cases I've used:

    0.0001
    0.0000001
    0.0000000001
    0.0000000000001

    Regardless of how small I make it the result is still 2.71828182845904550000.

  4. #4
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Code:
    #include<stdio.h>
    #include<float.h>
    
    double eConstant(long double epsilon);
    
    
    int main (void)
    {
        printf("DBL_DIG := %d\n", DBL_DIG);
        printf("The value of 'e' is : %.16f", eConstant(LDBL_EPSILON*4));
    
    
        return 0;
    }
    The above is giving me a DBL_DIG of 15 on a 32 bit Windows PC.
    I am guessing 16 is the most that can be valid in digits after the decimal.

    <cfloat> (float.h) - C++ Reference

    Tim S.
    Last edited by stahta01; 03-13-2017 at 03:57 PM.
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  5. #5
    Registered User
    Join Date
    Feb 2017
    Posts
    27
    @stahta01

    Thanks for the info!

    Unfortunately, though changing the # of displayed numbers after the decimal place to 15 removes the unnecessary 0's, the number is now a constant 2.7182818284590456.

    I'll keep looking for potential errors in the meantime, thinking this has to do with a logical error in my code somewhere.

  6. #6
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  7. #7
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    If you're looking for more precision you could use GMP. Here's your program rewritten to print 250 decimal digits of precision (which requires about 831 bits of precision). Answer:
    2.718281828459045235360287471352662497757247093699 9595749669676277240
    76630353547594571382178525166427427466391932003059 9218174135966290435
    72900334295260595630738132328627943490763233829880 7531952510190115738
    34187930702154089149934884167509244761460668
    Code:
    // gcc -Wall -W -o e01 e01.c -lgmp
    #include <stdio.h>
    #include <gmp.h>
    
    #define BITS_PREC 840
    
    int main() {
        mpf_t e, one, factorial, toAdd, epsilon;
        unsigned long i = 1;
    
        mpf_set_default_prec(BITS_PREC);
        mpf_inits(e, one, factorial, toAdd, epsilon, NULL);
    
        mpf_set_ui(e, 1);
        mpf_set_ui(one, 1);
        mpf_set_ui(factorial, 1);
        mpf_set_ui(epsilon, 1);
        mpf_div_2exp(epsilon, epsilon, BITS_PREC - 2);
    
        for (;;) {
            mpf_div(toAdd, one, factorial);
            if (mpf_cmp(toAdd, epsilon) < 0)
                break;
            mpf_add(e, e, toAdd);
            mpf_mul_ui(factorial, factorial, ++i);
        }
    
        gmp_printf("%.249Ff\n", e);
    
        mpf_clears(e, one, factorial, toAdd, epsilon, NULL);
        return 0;
    }

  8. #8
    Registered User
    Join Date
    Feb 2017
    Posts
    27
    OK, after checking my code with print statements, I think I've found the error, though I'm unsure what's fixing it.

    Code:
    #include<stdio.h>
    
    
    
    double eConstant(double epsilon);
    
    
    int main (void)
    {
        double epsilon;
    
    
        printf("Please enter a number for epsilon: ");
        scanf("%ld", &epsilon);
    
    
        printf("The value of 'e' is : %.15f", eConstant(epsilon));
    
    
        return 0;
    }
    
    
    double eConstant(double epsilon)
    {
        double e = 1.0;
        double factorial = 1.0;
        int i = 1;
        double toAdd = 1.0;
    
    
        for(;;){
            e += toAdd;
            i++;
            factorial *= i;
            toAdd = 1.0/factorial;
    
    
            if (toAdd < epsilon)
                break;
        }
        return e;
    }
    For some reason, the if (toAdd < epsilon) statement isn't occurring until i = 170+, despite a large epsilon (i.e. over 1). I'm pretty sure the constant is supposed to get more exact the smaller epsilon is.

    Why might this be the case? I'm wondering if it has something to do with overflow, or anything of the sort.

  9. #9
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Quote Originally Posted by kapkong View Post
    For some reason, the if (toAdd < epsilon) statement isn't occurring until i = 170+, despite a large epsilon (i.e. over 1). I'm pretty sure the constant is supposed to get more exact the smaller epsilon is.

    Why might this be the case? I'm wondering if it has something to do with overflow, or anything of the sort.
    Maybe you should try reading epsilon with the correct format spec ("%lf").
    You should know by now to maximize your warning level.
    On gcc, use the flags: -Wall -W -pedantic

  10. #10
    Registered User
    Join Date
    Feb 2017
    Posts
    27
    @algorism

    Thanks for the help, I appreciate it! I couldn't find an error my logic, but I guess it makes sense I'd forget to use float there instead of %ld

    As for maximizing my warning levels, I will definitely keep it in mind. It's not something we've covered in lecture, and it doesn't look like we're going to. I'll look into it for my future C programs.

    My apologies for my incompetence.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 05-17-2016, 06:35 AM
  2. Returning Incorrect Averages
    By C11J in forum C++ Programming
    Replies: 3
    Last Post: 05-20-2015, 07:57 PM
  3. Replies: 8
    Last Post: 05-10-2015, 06:57 AM
  4. scanf help, returning incorrect value
    By imustnotfear in forum C Programming
    Replies: 9
    Last Post: 03-09-2013, 01:40 AM
  5. Function returning incorrect value
    By CHurst in forum C Programming
    Replies: 3
    Last Post: 12-13-2005, 01:27 PM

Tags for this Thread