0

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

Pedro
  • 333
  • 1
  • 5
  • 24
  • Which are the values of `tmax` and `dt` ? – nnn Nov 12 '15 at 00:57
  • 1
    I can ask lots of dumb questions like "Is S initialized?" or you could provide a compilable version of this code. – Bill Lynch Nov 12 '15 at 00:57
  • 1
    That code is far from complete and compilable. What do you expect anyone to do with that? – void_ptr Nov 12 '15 at 00:57
  • @void_ptr there you go. – Pedro Nov 12 '15 at 01:00
  • @BillLynch there you go – Pedro Nov 12 '15 at 01:01
  • Hm. http://ideone.com/6s8zXV So, just to be sure, the nan variable is `S` in your case, ie. the output? – deviantfan Nov 12 '15 at 01:05
  • There are uninitialized variables in your code, eg. `V`. – deviantfan Nov 12 '15 at 01:08
  • V is not initialized. So it isn't a number and then neither is anything that depends on it. – Jerry Jeremiah Nov 12 '15 at 01:09
  • What output did you expect and why? – M.M Nov 12 '15 at 01:11
  • @M.M the output should be decimal numbers which gradually "fill" the other fields (Such as E, I and R) and come to an equilibrium at some point. Instead, on the first iteration the loop outputs 'nan' for S, E, I and R. – Pedro Nov 12 '15 at 01:14
  • 1
    Please don't edit the solution into the answer -- instead, accept a posted answer. Otherwise it just makes it confusing for anyone else coming to the question. – M.M Nov 12 '15 at 01:17
  • @Pedro then edit your question and write all of these details there, not here in comments. And if the problem is the output value of S, E, I and R, please add code that prints them, so that we can see the problem when we run your program with no modifications. Right now you print them to a file after an `exit(0);`. Print them to STDOUT instead, and without the `exit(0);` – Fabio says Reinstate Monica Nov 12 '15 at 01:20

1 Answers1

4

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.

M.M
  • 138,810
  • 21
  • 208
  • 365