Thread: An issue with writing to an Integer Array

  1. #1
    Registered User
    Join Date
    Aug 2011
    Posts
    11

    An issue with writing to an Integer Array

    Hey folks,

    I'm very new to all this and I'm struggling to understand why my programme keeps printing the same array twice when I've got a section between that changes the array values. Please could I ask you all not to give me any code just point out what I've done wrong.

    The premise is using an array to simulate a set of spins or magnetons, and to investigate using the metropolis monte carlo method how spins change at ceratin temperatures, whether they spontaneously align or continue to flip randomly, known as spontaneous magnetisation. Note, the temp is in J/kB so below an input value of 2.269 the array should spontaneously align and above this input value it should continue to flip randomly.

    Many Thanks in advance, if more info is needed just yell.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    int main()
    {
        FILE    *outputfile;
        int i, j, N=8, spins[N][N], north_spin, south_spin, east_spin, west_spin, iterations=1000*(N*N); //Define counting variables and spin storage array.
        double  rand_num_between_0_100, i_selector, j_selector, delta_energy, Temp, R, changed_spin_state;  //Define variables for spin selection and generation.
    
        outputfile=fopen("/home/sam/Documents/SpinOutputData.txt","w");     //Open output file for write.
        if(outputfile==NULL)                                                   //Fail to open message.
        {
            printf("+++THERE WAS AN ERROR IN OPENING THE WRITE FILE+++");
        }
    
        srand(time(NULL));  //Seed random number using clock.
    
        fprintf(outputfile,"\n\t\t\t+++HERE FOLLOWS THE SPIN ARRAY+++\n");          //Inform user of programme function and how to read display
        fprintf(outputfile,"\n\t\t+++THIS MICROSTATE MATRIX IS SURROUNDED BY OTHER MICROSTATES+++\n");
        fprintf(outputfile,"\n\t\t+++NORTH IS UPWARDS IN THE PLANE OF YOUR DISPLAY+++\n");
        fprintf(outputfile,"\n\t\t+++THE BRACKETED VALUES DENOTE ROWS AND COLUMNS+++\n");
        fprintf(outputfile,"\n\t\t+++THE FINAL SET OF BRACKETED NUMBERS ARE THE ROWS+++\n\n");
    
        for(i = 0; i<N; i++)  //Initialise Spins Array.
        {
            for(j = 0; j<N; j++)
            {
                spins[i][j] = 0;
            }
        }
    
        for(i = 0; i<N; i++)  //Randomise spins and store on array.
        {
            for(j = 0; j<N; j++)
            {
                rand_num_between_0_100 = (rand() % 100)+1;    //Define random number between 1 and 100
    
                if(rand_num_between_0_100<50)
                {
                    spins[i][j] = 1;
                }
                else
                {
                    spins[i][j] = -1;
                }
            }
        }
    
        for(i = 0; i<N; i++)  //Display Spins Array.
        {
            for(j = 0; j<N; j++)
            {
                fprintf(outputfile,"\t[%d] %d", j, spins[i][j]);
            }
    
            fprintf(outputfile,"\t[%d]\n", i);
        }
    
        printf("\n\t+++PLEASE ENTER THE TEMPERATURE, IN J/BoltzmannConstant, THAT YOU WISH TO RUN THE SIMULATON AT:");
        scanf("%d", &Temp);             //Prompt and scan for input.
        fprintf(outputfile,"\n\n");
    
        for(i=0; i<iterations; i++)  //Find random spins perform energy comp. and write to file.
        {
            i_selector = N*(rand()-1)/RAND_MAX+1; //Select random i point in array.
            j_selector = N*(rand()-1)/RAND_MAX+1; //Select random j point in array.
    
            if(i_selector==0)    //Define spin above selected spin.
            {
                north_spin= spins[(int)(i_selector+7)][(int)j_selector];   //This point lies outisde of array therfore equal to other edge.
            }
            else
            {
                north_spin = spins[(int)(i_selector-1)][(int)j_selector];
            }
    
            if(i_selector==7)    //Define spin below selected spin.
            {
                south_spin=spins[(int)(i_selector-7)][(int)j_selector];   //This point lies outisde of array therfore equal to other edge.
            }
            else
            {
                south_spin = spins[(int)(i_selector+1)][(int)j_selector];
            }
    
            if(j_selector==0)    //Define spin west selected spin.
            {
                west_spin=spins[(int)i_selector][(int)(j_selector+7)];   //This point lies outisde of array therfore equal to other edge.
            }
            else
            {
                west_spin = spins[(int)i_selector][(int)(j_selector-1)];
            }
    
            if(j_selector==7)    //Define spin east selected spin.
            {
                east_spin=spins[(int)i_selector][(int)(j_selector-7)];   //This point lies outisde of array therfore equal to other edge.
            }
            else
            {
                east_spin = spins[(int)i_selector][(int)(j_selector+1)];
            }
    
            delta_energy=-(((spins[(int)(i_selector)][(int)(j_selector)]*north_spin)+
                        (spins[(int)(i_selector)][(int)(j_selector)]*south_spin)+
                        (spins[(int)(i_selector)][(int)(j_selector)]*west_spin)+
                        (spins[(int)(i_selector)][(int)(j_selector)]*east_spin))-
                        ((-spins[(int)(i_selector)][(int)(j_selector)]*north_spin)+
                        (-spins[(int)(i_selector)][(int)(j_selector)]*south_spin)+
                        (-spins[(int)(i_selector)][(int)(j_selector)]*west_spin)+
                        (-spins[(int)(i_selector)][(int)(j_selector)]*east_spin)));  //Calculate Energy Change
    
            R = rand()/RAND_MAX;            //Define variable for spin change-up
    
            if((delta_energy<0)||(R<=exp(-delta_energy/Temp)))     //Change spin state if delEnergy is less than 0
            {
                spins[(int)i_selector][(int)j_selector]=-spins[(int)i_selector][(int)j_selector];
            }
        }
    
        for(i = 0; i<N; i++)  //Display New Spins Array.
        {
            for(j = 0; j<N; j++)
            {
                fprintf(outputfile,"\t[%d] %d", j, spins[i][j]);
            }
    
            fprintf(outputfile,"\t[%d]\n", i);
        }
    
    
        printf("\n\n+++JOB DONE+++\n\n");   //Notify user process is complete.
    
        return 0;
    }

  2. #2
    Registered User
    Join Date
    Nov 2011
    Posts
    52
    Did you check if you are getting hits on line 118?

    Code:
    if((delta_energy<0)||(R<=exp(-delta_energy/Temp)))     //Change spin state if delEnergy is less than 0        {
                spins[(int)i_selector][(int)j_selector]=-spins[(int)i_selector][(int)j_selector];
            }
    When your if statement always fails then spins will not be updated.

  3. #3
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Two problems that I can see:
    1) Where you're inputting the temperature, use scanf("%ld", &Temp); for double data type.
    2) i_selector and j_selector are out of range. They appear to go from 1 to 8 whereas array subscript should be 0 to 7.

    So memory is being corrupted. I wouldn't rely on any output until those are fixed.

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,907
    A few problems to start with:
    Code:
    $ gcc -Wall -g -std=c99  -lm flip.c   -o flip
    flip.c: In function ‘main’:
    flip.c:17: warning: implicit declaration of function ‘time’
    flip.c:61: warning: format ‘%d’ expects type ‘int *’, but argument 2 has type ‘double *’
    flip.c:9: warning: unused variable ‘changed_spin_state’
    Addressing those issues and a few others:

    • You need to #include <time.h> if you want to use the time() function.
    • You need to read the scanf documentation and learn how to read a double. %d is for integers.
    • Remove unused variables, they're just clutter.
    • If you can't open the output file, you need to return from main with an error.
    • I couldn't open the output file on my computer because /home/sam/... didn't exist, but the code went on to call fprintf(outputfile), which caused a seg fault. The printf for fopen failing was executed but no output showed up because stdout doesn't appear on the screen until a new line is printed or you explicitly call fflush(stdout). Try using fprintf(stderr, ...) or look into perror(), which tells you why/how it failed.
    • rand() returns an integer between 0 and RAND_MAX (which is also an integer). Unless rand() returned RAND_MAX (1 in 4 billion chance), you will always get 0 from rand()/RAND_MAX, and even if it did return RAND_MAX, you would always get 0 from (rand()-1)/RAND_MAX. This is because integer division in C only produces the whole number part and discards the remainder, i.e. you don't get anything after the decimal. Cast one part to a double before dividing: ((double) rand()-1) / RAND_MAX;
    • Your whole i_selector and j_selector business looks messy. It seems you just want a random index from your array, so make them ints and use the modulus (remainder) operator: i_selector = rand() % N. That will give you a random number from 0..N-1, which are all the valid indexes for your spins array, and you can get rid of all of those type casts.


    When things go wrong you should run your code through a debugger, like GDB since it appears you're on a *nix system. If you don't know how, learn (Google has lots of great tutorials). Failing that, print copious amounts of information. Printing i_selector, j_selector and R in your loop would have given you a much better clue to the problem.
    Last edited by anduril462; 01-26-2012 at 12:16 PM.

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,907
    Quote Originally Posted by nonoob View Post
    1) Where you're inputting the temperature, use scanf("%ld", &Temp); for double data type.
    I think you mean "%lf"

  6. #6
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    You're not generating random numbers properly.

    This
    Code:
            i_selector = N*(rand()-1)/RAND_MAX+1;
            j_selector = N*(rand()-1)/RAND_MAX+1;
    Should be this
    Code:
            i_selector = rand() % N;
            j_selector = rand() % N;
    with i_selector and j_selector as ints (not doubles).

    And if you mean R to be in [0.0, 1.0], then this
    Code:
            R = rand()/RAND_MAX;
    should be
    Code:
            R = (double)rand()/RAND_MAX;
    In this part below, you don't need to zero the array if right afterwards you fill the entire array with random 1's and -1's. And the random number you generate is in [1,100], not [0,100] as your variable name claims.
    Code:
        for(i = 0; i<N; i++)  //Initialise Spins Array.
        {
            for(j = 0; j<N; j++)
            {
                spins[i][j] = 0;
            }
        }
    
        for(i = 0; i<N; i++)  //Randomise spins and store on array.
        {
            for(j = 0; j<N; j++)
            {
                rand_num_between_0_100 = (rand() % 100)+1;    //Define random number between 1 and 100
    
                if(rand_num_between_0_100<50)
                {
                    spins[i][j] = 1;
                }
                else
                {
                    spins[i][j] = -1;
                }
            }
    The above code could be replaced with this:
    Code:
        // Randomise spins and store on array.
        for(i = 0; i<N; i++)
            for(j = 0; j<N; j++)
                spins[i][j] = (rand()<RAND_MAX/2) ? 1 : -1;
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  7. #7
    Registered User
    Join Date
    Aug 2011
    Posts
    11

    Indebted

    My thanks to you all I made the corrections you suggested and it now works. I shall read the lit and hopefully be better next time. Cheers once again. For future people here is my now functioning code, all array elements become one when 0<input<=1.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    
    int main()
    {
        FILE    *outputfile;
        int i, j, N=8, spins[N][N], north_spin, south_spin, east_spin, west_spin, iterations=1000*(N*N); //Define counting variables and spin storage array.
        double  rand_num_between_0_100, i_selector, j_selector, delta_energy, Temp, R, changed_spin_state;  //Define variables for spin selection and generation.
    
        outputfile=fopen("/home/sam/Documents/SpinOutputData.txt","w");     //Open output file for write.
        if(outputfile==NULL)                                                   //Fail to open message.
        {
            printf("+++THERE WAS AN ERROR IN OPENING THE WRITE FILE+++");
        }
    
        srand(time(NULL));  //Seed random number using clock.
    
        fprintf(outputfile,"\n\t\t\t+++HERE FOLLOWS THE SPIN ARRAY+++\n");          //Inform user of programme function and how to read display
        fprintf(outputfile,"\n\t\t+++THIS MICROSTATE MATRIX IS SURROUNDED BY OTHER MICROSTATES+++\n");
        fprintf(outputfile,"\n\t\t+++NORTH IS UPWARDS IN THE PLANE OF YOUR DISPLAY+++\n");
        fprintf(outputfile,"\n\t\t+++THE BRACKETED VALUES DENOTE ROWS AND COLUMNS+++\n");
        fprintf(outputfile,"\n\t\t+++THE FINAL SET OF BRACKETED NUMBERS ARE THE ROWS+++\n\n");
    
        for(i = 0; i<N; i++)  //Randomise spins and store on array.
        {
            for(j = 0; j<N; j++)
            {
                spins[i][j] = (rand()<RAND_MAX/2) ? 1: -1;
            }
        }
    
        for(i = 0; i<N; i++)  //Display Spins Array.
        {
            for(j = 0; j<N; j++)
            {
                fprintf(outputfile,"\t[%d] %d", j, spins[i][j]);
            }
    
            fprintf(outputfile,"\t[%d]\n", i);
        }
    
        printf("\n\t+++PLEASE ENTER THE TEMPERATURE, IN J/Kb, THAT YOU WISH TO RUN THE SIMULATON AT:");
        scanf("%lf", &Temp);             //Prompt and scan for input.
        fprintf(outputfile,"\n\n");
    
        for(i=0; i<iterations; i++)  //Find random spins perform energy comp. and write to file.
        {
            i_selector = rand() % N; //Select random i point in array.
            j_selector = rand() % N; //Select random j point in array.
    
            if(i_selector==0)    //Define spin above selected spin.
            {
                north_spin= spins[(int)(i_selector+7)][(int)j_selector];   //This point lies outisde of array therfore equal to other edge.
            }
            else
            {
                north_spin = spins[(int)(i_selector-1)][(int)j_selector];
            }
    
            if(i_selector==7)    //Define spin below selected spin.
            {
                south_spin=spins[(int)(i_selector-7)][(int)j_selector];   //This point lies outisde of array therfore equal to other edge.
            }
            else
            {
                south_spin = spins[(int)(i_selector+1)][(int)j_selector];
            }
    
            if(j_selector==0)    //Define spin west selected spin.
            {
                west_spin=spins[(int)i_selector][(int)(j_selector+7)];   //This point lies outisde of array therfore equal to other edge.
            }
            else
            {
                west_spin = spins[(int)i_selector][(int)(j_selector-1)];
            }
    
            if(j_selector==7)    //Define spin east selected spin.
            {
                east_spin=spins[(int)i_selector][(int)(j_selector-7)];   //This point lies outisde of array therfore equal to other edge.
            }
            else
            {
                east_spin = spins[(int)i_selector][(int)(j_selector+1)];
            }
    
            delta_energy=(((spins[(int)(i_selector)][(int)(j_selector)]*north_spin)+
                        (spins[(int)(i_selector)][(int)(j_selector)]*south_spin)+
                        (spins[(int)(i_selector)][(int)(j_selector)]*west_spin)+
                        (spins[(int)(i_selector)][(int)(j_selector)]*east_spin))-
                        ((-spins[(int)(i_selector)][(int)(j_selector)]*north_spin)+
                        (-spins[(int)(i_selector)][(int)(j_selector)]*south_spin)+
                        (-spins[(int)(i_selector)][(int)(j_selector)]*west_spin)+
                        (-spins[(int)(i_selector)][(int)(j_selector)]*east_spin)));  //Calculate Energy Change
    
            R = (double)rand()/RAND_MAX;            //Define variable for spin change-up
    
            if((delta_energy<0)||(R<=exp(-delta_energy/Temp)))     //Change spin state if delEnergy is less than 0
            {
                spins[(int)i_selector][(int)j_selector]=-spins[(int)i_selector][(int)j_selector];
            }
        }
    
        for(i = 0; i<N; i++)  //Display New Spins Array.
        {
            for(j = 0; j<N; j++)
            {
                fprintf(outputfile,"\t[%d] %d", j, spins[i][j]);
            }
    
            fprintf(outputfile,"\t[%d]\n", i);
        }
    
    
        printf("\n\n+++JOB DONE+++\n\n");   //Notify user process is complete.
    
        return 0;
    }

  8. #8
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    Sorry about that. %lf it is. What a place to make an error like that.

  9. #9
    Just a pushpin. bernt's Avatar
    Join Date
    May 2009
    Posts
    426
    Quote Originally Posted by oogabooga
    This
    Code:
    i_selector = N*(rand()-1)/RAND_MAX+1;
    j_selector = N*(rand()-1)/RAND_MAX+1;
    Should be this
    Code:
    i_selector = rand() % N;
    j_selector = rand() % N;
    Something worth noting since this looks like a scientific application: if N does not evenly divide RAND_MAX, this method tends to favor lower numbers very slightly, more so with large N.

    If an even distribution is necessary one can discard values above some multiple of N, like RAND_MAX - (RAND_MAX % N).
    Consider this post signed

  10. #10
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Something worth noting since this looks like a scientific application: if N does not evenly divide RAND_MAX, this method tends to favor lower numbers very slightly, more so with large N.
    True. I meant to link to a post that explains that (by iMalc, I think), but I'm apparently rather bad at the search function.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  11. #11
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    This would be the link you're after: How to pick a random number between x and y

    Might I make one more suggestion...
    This:
    Code:
    	delta_energy=(((spins[(int)(i_selector)][(int)(j_selector)]*north_spin)+
    				(spins[(int)(i_selector)][(int)(j_selector)]*south_spin)+
    				(spins[(int)(i_selector)][(int)(j_selector)]*west_spin)+
    				(spins[(int)(i_selector)][(int)(j_selector)]*east_spin))-
    				((-spins[(int)(i_selector)][(int)(j_selector)]*north_spin)+
    				(-spins[(int)(i_selector)][(int)(j_selector)]*south_spin)+
    				(-spins[(int)(i_selector)][(int)(j_selector)]*west_spin)+
    				(-spins[(int)(i_selector)][(int)(j_selector)]*east_spin))); //Calculate Energy Change
    is equivalent to this:
    Code:
        int selected_spin = spins[i_selector][j_selector];
    
        delta_energy = 2 * (selected_spin * north_spin +
                            selected_spin * south_spin +
                            selected_spin * west_spin  +
                            selected_spin * east_spin); //Calculate Energy Change
    Having carefully removed the duplication and simplified it, it looks like you may have some of your minus sign(s) wrong in the original code. But really, you should learn to write the code more like this straight off.
    Note that you should change i_selector and j_selector to an int as well.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Array Issue.
    By mcertini in forum C Programming
    Replies: 7
    Last Post: 02-16-2011, 10:56 AM
  2. Writing an integer into a file
    By srikkan in forum C Programming
    Replies: 2
    Last Post: 10-15-2010, 04:29 AM
  3. integer array to char array?
    By DJPlayer in forum C Programming
    Replies: 4
    Last Post: 10-19-2009, 09:59 PM
  4. Converting character array to integer array
    By quiet_forever in forum C++ Programming
    Replies: 5
    Last Post: 04-02-2007, 05:48 AM
  5. Integer displaying crazy numbers issue
    By Razorblade Kiss in forum C++ Programming
    Replies: 16
    Last Post: 12-20-2004, 11:00 PM