Redirect to STDOUT Problem

J

Jordan Glassman

Trying to do something fairly routine... drop output into a file to
graph, but the following command at the bash command line:

ising > output

produces a blinking cursor, an empty file named "output," and a
program that runs forever. With no redirect, the output is normal.
Below is the printf statement used to generate output.

printf("B=%4.2f E=%8.4f m=%8.4f Cv=%5.2f \
Chi=%5.2f\n",beta,(energy/n2),(moment/n2), \
(summe2-summe*summe)/n2, \
(summm2-summm*summm)/n2);

I verified that things like 'ls > output' work fine, and that I can
also redirect output from other c programs I've written. Something is
funny about this one.

Any thoughts?
 
B

Ben Bacarisse

Jordan Glassman said:
Trying to do something fairly routine... drop output into a file to
graph, but the following command at the bash command line:

ising > output

On modern systems, . is often not in your path. Did you just forget
to type ./ising?
produces a blinking cursor, an empty file named "output," and a
program that runs forever. With no redirect, the output is normal.
Below is the printf statement used to generate output.

printf("B=%4.2f E=%8.4f m=%8.4f Cv=%5.2f \
Chi=%5.2f\n",beta,(energy/n2),(moment/n2), \
(summe2-summe*summe)/n2, \
(summm2-summm*summm)/n2);

Nothing here can explain what is happening. The printf is correct.
Of course, if n2 == 0 you won't get any output but that will happen
with and without the redirect.
I verified that things like 'ls > output' work fine, and that I can
also redirect output from other c programs I've written. Something is
funny about this one.

Any thoughts?

The problem is probably not in the C code. You need someone to watch
exactly what you are doing and they'll probably spot it in no time. I
think a group like comp.unix.programmer might be better.
 
J

Jordan Glassman

Ben,

Thanks for the reply...
On modern systems, . is often not in your path. Did you just forget
to type ./ising?

No, that's not the problem.
Nothing here can explain what is happening. The printf is correct.
Of course, if n2 == 0 you won't get any output but that will happen
with and without the redirect.

The problem is probably not in the C code. You need someone to watch
exactly what you are doing and they'll probably spot it in no time. I
think a group like comp.unix.programmer might be better.

I tend to agree, but since *everything else* works except this
particular c program, which contains nothing more than a few
calculations inside loops and this one output statement, I decided to
post here first.

-j
 
P

Peter Nilsson

Jordan said:
...
I tend to agree, but since *everything else* works except this
particular c program, which contains nothing more than a few
calculations inside loops and this one output statement, I
decided to post here first.

Though for some reason you decided not to post the code.
Still, your loss...
 
J

Jordan Glassman

Though for some reason you decided not to post the code.
Still, your loss...

My loss? Here it is...

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <curses.h>

#include <unistd.h> // ANSI C???

#define N 40
#define NITERS 5000000

void filllattice(int (*m)[N]);
void seed(void); /* bad bad bad */
void printlattice(int (*m)[N]);
void ising(int (*m)[N],double beta);

int main(){

int lattice[N][N];
double beta=0.0;

seed();

for(beta=0.5;beta<=1.2;beta+=0.01){

filllattice(lattice);

// clear();

// printlattice(lattice);

ising(lattice,beta);

}

return 0;

}

void filllattice(int (*m)[N]){

int i,j;

for(i=0;i<N;i++){
for(j=0;j<N;j++){
if((((float)rand()/(float)RAND_MAX)) > 0.5) m[j]= 1;
else m[j] = -1;
}
}

}

void seed(void){

struct tm *mt;
int i;
time_t t;
char timestr[3];

t=time(NULL);
mt=localtime(&t);
strftime(timestr,3,"%S",mt);

srand(atoi(timestr));

}

void printlattice(int (*m)[N]){

int i,j;

/* system("clear"); */
move(0,0);

for(i=0;i<N;i++){
putchar('\n');
for(j=0;j<N;j++){
if(m[j]==1)printf(" 1");
else printf(" -1");
}
}

putchar('\n');
}

void ising(int (*m)[N],double beta){

int i,j,k;
double energy,moment;
double summe,summm,summe2,summm2;
int numsteps=0;
double sum_nn,sums;
double deltaH;
double sum_nnn;
int n2=N*N;
double half=NITERS/2;

k=0;

energy=moment=0.0;
summe=summm=summe2=summm2=0.0;

// pick a site randomly

for(i=0;i<N;i++){
for(j=0;j<N;j++){
moment += m[j];
energy -= 2*m[j]*(m[(i+1)%N][j]+m[(j+1)%N]+m[(i+1)%N][(j
+1)%N]/5);
}
}

for(k=0;k<NITERS;k++){

i=rand()%N;
j=rand()%N;

sum_nn=m[((j+1)%N)]+m[((j-1+N)%N)]+m[((i+1)%N)][j]+m[((i-1+N)
%N)][j];
sum_nnn=(m[((i+1)%N)][((j+1)%N)]+m[((i-1+N)%N)][((j-1+N)%N)]
+m[((i-1+N)%N)][((j+1)%N)]+m[((i+1)%N)][((j-1+N)%N)])/5;
sums=sum_nn+sum_nnn;
deltaH=m[j]*sums;
if((exp(-1.3*deltaH*beta))>((float)rand()/(float)RAND_MAX) ||
(deltaH < 0) ){
energy += 2*deltaH;
moment -= 2*m[j];
m[j] *= -1;
}

if(k>half){
summe+=energy;
summe2+=energy*energy;
summm+=moment;
summm2+=moment*moment;
}

/* if(k>10000){
k=0;
putchar('\n');
printf("E=%f m=%f",(energy/n2),(moment/n2));
printlattice(m);
sleep(1);
} */

}

summe /= half;
summe2 /= half;
summm /= half;
summm2 /= half;

printf("B=%4.2f E=%8.4f m=%8.4f Cv=%5.2f Chi=%5.2f\n",beta,(energy/
n2),(moment/n2),(summe2-summe*summe)/n2,(summm2-summm*summm)/n2);

}
 
B

Ben Bacarisse

Jordan Glassman said:
My loss? Here it is...

Yes. I can now tell you how to get it to work (but
comp.unix.programmer is still the better place).
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <curses.h>

curses programs can't usually have their put redirected (ask in
c.u.p for when and why).
#include <unistd.h> // ANSI C???

No, not ANSI C.

void seed(void){

struct tm *mt;
int i;
time_t t;
char timestr[3];

t=time(NULL);
mt=localtime(&t);
strftime(timestr,3,"%S",mt);

srand(atoi(timestr));

}

The comp.lang.c FAQ has some advice seeding rand().
http://c-faq.com/lib/srand.html
void printlattice(int (*m)[N]){

int i,j;

/* system("clear"); */
move(0,0);

Comment this out. You don't need the curses functionality (at least
not yet). If you do more with it in future versions, it may be worth
the price of losing output re-direction.
for(i=0;i<N;i++){
putchar('\n');
for(j=0;j<N;j++){
if(m[j]==1)printf(" 1");
else printf(" -1");
}
}

putchar('\n');
}

void ising(int (*m)[N],double beta){

int i,j,k;
double energy,moment;
double summe,summm,summe2,summm2;
int numsteps=0;
double sum_nn,sums;
double deltaH;
double sum_nnn;
int n2=N*N;
double half=NITERS/2;

k=0;

energy=moment=0.0;
summe=summm=summe2=summm2=0.0;

// pick a site randomly

for(i=0;i<N;i++){
for(j=0;j<N;j++){
moment += m[j];
energy -= 2*m[j]*(m[(i+1)%N][j]+m[(j+1)%N]+m[(i+1)%N][(j
+1)%N]/5);
}
}

for(k=0;k<NITERS;k++){

i=rand()%N;
j=rand()%N;

sum_nn=m[((j+1)%N)]+m[((j-1+N)%N)]+m[((i+1)%N)][j]+m[((i-1+N)
%N)][j];
sum_nnn=(m[((i+1)%N)][((j+1)%N)]+m[((i-1+N)%N)][((j-1+N)%N)]
+m[((i-1+N)%N)][((j+1)%N)]+m[((i+1)%N)][((j-1+N)%N)])/5;
sums=sum_nn+sum_nnn;
deltaH=m[j]*sums;
if((exp(-1.3*deltaH*beta))>((float)rand()/(float)RAND_MAX) ||
(deltaH < 0) ){
energy += 2*deltaH;
moment -= 2*m[j];
m[j] *= -1;
}

if(k>half){
summe+=energy;
summe2+=energy*energy;
summm+=moment;
summm2+=moment*moment;
}

/* if(k>10000){
k=0;
putchar('\n');
printf("E=%f m=%f",(energy/n2),(moment/n2));
printlattice(m);
sleep(1);
} */

}

summe /= half;
summe2 /= half;
summm /= half;
summm2 /= half;

printf("B=%4.2f E=%8.4f m=%8.4f Cv=%5.2f Chi=%5.2f\n",beta,(energy/
n2),(moment/n2),(summe2-summe*summe)/n2,(summm2-summm*summm)/n2);


Add:

fflush(stdout);

to be sure to get what data you have written so far. I did not wait for
the program to finish -- if you do there is no need to call fflush.
 
B

Ben Bacarisse

Ben Bacarisse said:
curses programs can't usually have their put redirected (ask in
c.u.p for when and why).

Oh the perils of off-topic answers. Please don't get into this here.
I know it is wrong -- I was over-simplifying to the point of being
plain wrong. Berate me in comp.unix.programmer if you must!
 
P

Peter Nilsson

[Other replies notwithstanding...]

Jordan said:
#define NITERS 5000000
int i,j,k;
for(k=0;k<NITERS;k++){

Are you perchance running on a machine with 16-bit ints?

If so, this loop will likely run forever (assuming 16-bit overflow
from INT_MAX to INT_MIN.)
void ising(int (*m)[N],double beta){

Identifiers starting with is (or to) and a lowercase letter are
reserved for use as external identifiers.

This is not likely to be the source of your problem, but it is
still a fault with your code.

Apart from that, the program does take some time to run.
Are you leaving it for long enough? With such relatively
small output, many systems won't actually flush to the
redirected file until the program (and stream) closes.
 
J

Jordan Glassman

Ben,

Taking out the curses.h and all associated functions did it. I'm
still not sure why the printf didn't work, though... not of the
curses.h functions were actually being used in that code I posted...
they were all commented out! It's as if curses replaces printf with
another version.

Dunno. In any case, thanks for the help.

-j

My loss? Here it is...

Yes. I can now tell you how to get it to work (but
comp.unix.programmer is still the better place).
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <curses.h>

curses programs can't usually have their put redirected (ask in
c.u.p for when and why).
#include <unistd.h> // ANSI C???

No, not ANSI C.

void seed(void){
struct tm *mt;
int i;
time_t t;
char timestr[3];
t=time(NULL);
mt=localtime(&t);
strftime(timestr,3,"%S",mt);
srand(atoi(timestr));

}

The comp.lang.c FAQ has some advice seeding rand().http://c-faq.com/lib/srand.html
void printlattice(int (*m)[N]){
/* system("clear"); */
move(0,0);

Comment this out. You don't need the curses functionality (at least
not yet). If you do more with it in future versions, it may be worth
the price of losing output re-direction.


for(i=0;i<N;i++){
putchar('\n');
for(j=0;j<N;j++){
if(m[j]==1)printf(" 1");
else printf(" -1");
}
}
putchar('\n');
}

void ising(int (*m)[N],double beta){

int i,j,k;
double energy,moment;
double summe,summm,summe2,summm2;
int numsteps=0;
double sum_nn,sums;
double deltaH;
double sum_nnn;
int n2=N*N;
double half=NITERS/2;


// pick a site randomly
for(i=0;i<N;i++){
for(j=0;j<N;j++){
moment += m[j];
energy -= 2*m[j]*(m[(i+1)%N][j]+m[(j+1)%N]+m[(i+1)%N][(j
+1)%N]/5);
}
}
for(k=0;k<NITERS;k++){
i=rand()%N;
j=rand()%N;

sum_nn=m[((j+1)%N)]+m[((j-1+N)%N)]+m[((i+1)%N)][j]+m[((i-1+N)
%N)][j];
sum_nnn=(m[((i+1)%N)][((j+1)%N)]+m[((i-1+N)%N)][((j-1+N)%N)]
+m[((i-1+N)%N)][((j+1)%N)]+m[((i+1)%N)][((j-1+N)%N)])/5;
sums=sum_nn+sum_nnn;
deltaH=m[j]*sums;
if((exp(-1.3*deltaH*beta))>((float)rand()/(float)RAND_MAX) ||
(deltaH < 0) ){
energy += 2*deltaH;
moment -= 2*m[j];
m[j] *= -1;
}
if(k>half){
summe+=energy;
summe2+=energy*energy;
summm+=moment;
summm2+=moment*moment;
}

/* if(k>10000){
k=0;
putchar('\n');
printf("E=%f m=%f",(energy/n2),(moment/n2));
printlattice(m);
sleep(1);
} */

summe /= half;
summe2 /= half;
summm /= half;
summm2 /= half;

printf("B=%4.2f E=%8.4f m=%8.4f Cv=%5.2f Chi=%5.2f\n",beta,(energy/
n2),(moment/n2),(summe2-summe*summe)/n2,(summm2-summm*summm)/n2);

Add:

fflush(stdout);

to be sure to get what data you have written so far. I did not wait for
the program to finish -- if you do there is no need to call fflush.
 
J

Jordan Glassman

Ben,

Taking out the curses.h and all associated functions did it. I'm
still not sure why the printf didn't work, though... not of the
curses.h functions were actually being used in that code I posted...
they were all commented out! It's as if curses replaces printf with
another version.

Dunno. In any case, thanks for the help.

-j

My loss? Here it is...

Yes. I can now tell you how to get it to work (but
comp.unix.programmer is still the better place).
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <curses.h>

curses programs can't usually have their put redirected (ask in
c.u.p for when and why).
#include <unistd.h> // ANSI C???

No, not ANSI C.

void seed(void){
struct tm *mt;
int i;
time_t t;
char timestr[3];
t=time(NULL);
mt=localtime(&t);
strftime(timestr,3,"%S",mt);
srand(atoi(timestr));

}

The comp.lang.c FAQ has some advice seeding rand().http://c-faq.com/lib/srand.html
void printlattice(int (*m)[N]){
/* system("clear"); */
move(0,0);

Comment this out. You don't need the curses functionality (at least
not yet). If you do more with it in future versions, it may be worth
the price of losing output re-direction.


for(i=0;i<N;i++){
putchar('\n');
for(j=0;j<N;j++){
if(m[j]==1)printf(" 1");
else printf(" -1");
}
}
putchar('\n');
}

void ising(int (*m)[N],double beta){

int i,j,k;
double energy,moment;
double summe,summm,summe2,summm2;
int numsteps=0;
double sum_nn,sums;
double deltaH;
double sum_nnn;
int n2=N*N;
double half=NITERS/2;


// pick a site randomly
for(i=0;i<N;i++){
for(j=0;j<N;j++){
moment += m[j];
energy -= 2*m[j]*(m[(i+1)%N][j]+m[(j+1)%N]+m[(i+1)%N][(j
+1)%N]/5);
}
}
for(k=0;k<NITERS;k++){
i=rand()%N;
j=rand()%N;

sum_nn=m[((j+1)%N)]+m[((j-1+N)%N)]+m[((i+1)%N)][j]+m[((i-1+N)
%N)][j];
sum_nnn=(m[((i+1)%N)][((j+1)%N)]+m[((i-1+N)%N)][((j-1+N)%N)]
+m[((i-1+N)%N)][((j+1)%N)]+m[((i+1)%N)][((j-1+N)%N)])/5;
sums=sum_nn+sum_nnn;
deltaH=m[j]*sums;
if((exp(-1.3*deltaH*beta))>((float)rand()/(float)RAND_MAX) ||
(deltaH < 0) ){
energy += 2*deltaH;
moment -= 2*m[j];
m[j] *= -1;
}
if(k>half){
summe+=energy;
summe2+=energy*energy;
summm+=moment;
summm2+=moment*moment;
}

/* if(k>10000){
k=0;
putchar('\n');
printf("E=%f m=%f",(energy/n2),(moment/n2));
printlattice(m);
sleep(1);
} */

summe /= half;
summe2 /= half;
summm /= half;
summm2 /= half;

printf("B=%4.2f E=%8.4f m=%8.4f Cv=%5.2f Chi=%5.2f\n",beta,(energy/
n2),(moment/n2),(summe2-summe*summe)/n2,(summm2-summm*summm)/n2);

Add:

fflush(stdout);

to be sure to get what data you have written so far. I did not wait for
the program to finish -- if you do there is no need to call fflush.
 
V

viza

Jordan Glassman said:
if((((float)rand()/(float)RAND_MAX)) > 0.5)

In C, the normal way to do (pseudo) random numbers selected from N
possibilities (in the range 0 to N-1) is to get a value in the half-open
range [0, 1) like this:

rand() / (RAND_MAX + 1.0)

and then multiply by N to get a value in the half-open range [0, N).
It seems that you want a value in the half-open range [0, 1) so you can
omit the multiplication step:

if(rand() / (RAND_MAX + 1.0) > 0.5)

In this case, why not just use:

if( rand() & 1 )

If RAND_MAX is odd (which it usually is) then this is perfect, and
doesn't need an FPU.

If RAND_MAX is even, then it gets very close to perfect as long as
RAND_MAX is large. Remember that the float method isn't perfect
either.

If your rand() isn't evenly distributed, then you are screwed whatever
you do.

viza
 
W

Walter Roberson

In this case, why not just use:
if( rand() & 1 )
If RAND_MAX is odd (which it usually is) then this is perfect, and
doesn't need an FPU.

The low bit of rand() is often not very random at all -- often alternating
between 0 and 1 each time. It's a problem with linear congruential
pseudo-random numbers, at least if you take the bottom bits of the
new seed as being the random value. (Some implementations make sure
they never output the bottom bits to reduce this problem, but
C doesn't make any such promises.)
 
R

Richard Tobin

Walter Roberson said:
The low bit of rand() is often not very random at all -- often alternating
between 0 and 1 each time.

This used to be true, 20-something years ago. Surely modern
implementations don't have the same problem?

-- Richard
 
W

Walter Roberson

This used to be true, 20-something years ago. Surely modern
implementations don't have the same problem?

Remember, the C89 standard was 20-something years ago, but conforming
more modern implementations (C99) are still pretty uncommon ;-)

To be fair: the C89 sample implementation works with an
unsigned long int seed, and the value returned is divided by 64K and
is mod 32768 (e.g., shift right 16 bits and mask out all but the
bottom 15 bits). With that sample algorithm, the bottom bit of rand()
should have a cycle of 64K (which would, I -suspect-, be composed
of two half-cycles of 32K each, bitwise negations of each other.)
 
L

lawrence.jones

Richard Tobin said:
This used to be true, 20-something years ago. Surely modern
implementations don't have the same problem?

I only know of *one* implementation that had that problem, and that was
more like 30 years ago. (Someone at UCB "enhanced" a perfectly good
16-bit rand() to return 32 bit values by simply returning the entire
internal state rather than just the high-order 16 bits.)

-- Larry Jones

I wonder what's on TV now. -- Calvin
 
S

Szabolcs Borsanyi

produces a blinking cursor, an empty file named "output," and a
program that runs forever.  With no redirect, the output is normal.

As I see your problem has been solved. I got similar behaviour
when I did not wait for the program to completely finish.
Without redirection I saw the results immediately, but
redirection sometimes implies a buffering and the buffer
is lost if the program terminates abnormally.
Below is the printf statement used to generate output.

printf("B=%4.2f E=%8.4f m=%8.4f Cv=%5.2f \
Chi=%5.2f\n",beta,(energy/n2),(moment/n2), \
(summe2-summe*summe)/n2, \
(summm2-summm*summm)/n2);

Sorry for this remark, but, this last lines made me
suspicious: This is a 2dimensional ising model,
Cv is the specific heat, which is the energy density fluctuation,
so I expect a standard deviation there.
Don't you then miss an other 1/n2 no normalise summe and summm?
I can be completely wrong, but you might want to check this.

Szabolcs
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,968
Messages
2,570,152
Members
46,697
Latest member
AugustNabo

Latest Threads

Top