Search code examples
c++cprecisionlong-double

Long double reseting to 0 after assignment


I've been tinkering around with some disease models in C/C++ and would like to get more precision out of it. I thought about using long doubles, for the 80-bit precision (I'm using cygwin`s GCC 4.8.3), but after making a calculation with it, I get a "nan" (not a number) output value. Here's the code I'm working with. All the variables are long doubles.

#include <cstdlib>
#include <iostream>
#include <cstdio>
#include <ctime>
#include <random>
#include <omp.h>
#include <cfloat>



using namespace std;

int
main ( int argc, char** argv )
{

    long double S, E, I, R, V, dS, dE, dI, dR, dV;
    long double a, b, g, t, c, d, e, f;
    long double dt = .005, tmax = 365;

    S = 318000000;
    I = 1;
    E = 0;
    R = 0;
    V = 0;

    FILE* F;

    F = fopen ( "valoresSIR1.txt", "w+" );
    //fprintf ( F, "Tempo, Susceptivel, Incubado, Infectado, Recuperado, Vacinado\n" );

    a = 0.000005; 
    b = 0.01;
    c = 0.05; 
    d = 0.000034; 
    e = 0.00000; 
    f = 0.0; 
    g = 0.000000;
    t = 0.0000;

    //printf("%Lg", a); exit(0);
    for ( long double i = 0; i < tmax; i += dt )
    {
        dS = ( - a * I * S - g + t * R + d * ( S + E + R + V ) - f * S ) * dt;
        dE = ( a * I * S - c * E - g ) * dt;
        dI = ( c * E - g - e * I - b * I ) * dt;
        dR = ( b * I - g - t * R ) * dt;
        dV = ( f * S - g ) * dt;


        S += dS;
        E += dE;
        I += dI;
        R += dR;
        V += dV;

        //printf ( "%Lg, %Lg, %Lg, %Lg, %Lg, %Lg\n", S, E, I, R, V );
        std::cout.precision (50);
        std::cout << S << std::endl;
        exit ( 0 );
        fprintf ( F, "%Lg, %Lg, %Lg, %Lg, %Lg, %Lg\n", i, S, E, I, R, V );
        switch ( ( int ) i )
        {
            case 0: std::cout << i << endl;
                break;
            case 100: std::cout << i << endl;
                break;
            case 200: std::cout << i << endl;
                break;
            case 300: std::cout << i << endl;
                break;
            case 4000: std::cout << i << endl;
                break;
            case 5000: std::cout << i << endl;
                break;
            case 6000: std::cout << i << endl;
                break;
            case 7000: std::cout << i << endl;
                break;

        }

    }

    fclose ( F );

    return 0;
}

Expected values for output: http://pastebin.com/mJqkSVUf


Solution

  • The calculation dS = ( - a * I * S - g + t * R + d * ( S + E + R + V ) - f * S ) * dt; uses the uninitialized variable V. This causes undefined behaviour.

    When undefined behaviour occurs, anything can happen. In your case it is being manifested as nan being the result of the operation involving V.