Newsgroup: it.comp.lang.c
Titolo: una banalita' ma...

dato un double, il seguente test non mi funziona:
double d;
....
if (d<0)
{
     ...
}
Non entra mai nella if, anche quando d e' negativo.
Ovviamente ho provato (d<0.0) ma non funziona.
Le cose si aggiustano se scrivo:
if ((int) d<0)
cosa che gia' di per se mi sorprende non poco, ma pazienza: guardate questa
porzione di codice:
 double d;
 ....
 d=difftime(lista[i].date,lista[j].date);
 printf ("%lf \n",d);
  if (d<0)
    {
     printf("minore di 0\n");
    }
cosi' come scritta, genera il seguente output:
-670137.000000
invece se la rimpiazzo con:
 d=difftime(lista[i].date,lista[j].date);
 printf ("%lf \n",d);
  if ((int) d<0)
    {
     printf("minore di 0\n");
    }
produce:
-1.#IND00
minore di 0
Che diavolo vuol dire "-1.#IND00" ???? E perche' il cast sembra cambiare
oltre al funzionamento della if (che mi sta bene) anche quello della printf
(che avviene prima?!?!?!?!)
Ah, il compilatore e' il GCC sotto Windows XP, ambiente MinGW.

  d=difftime(lista[i].date,lista[j].date);
sicuro che la difftime() ritorni correttamente il double? ovvero gli hai 
passato 2 parametri corretti time_t?
Luca
--
   .~.      xin\@IRCNet (mostly xin\aWAy 24/7 ghgh)
   /V\      Email: NOSPAM!
  // \\     Anemir,Alarik,Marty,Araon,Balimir@ClessidraMUD - CdL -
 /(   )\    ICQ UIN: 63088554
  ^`~'^     "Somewhere inside my childhood witnessed my heart die" -
2Pac
-- 
/"\   
\ /    ASCII Ribbon Campaign
 \     Against HTML Mail and News
/ \  
--
"A coward dies a thousand deaths a soldier dies but once..." - 2Pac

 passato 2 parametri corretti time_t?
Si, anche perche', ripeto:
long d;
d = (long) difftime(lista[i].date,lista[j].date);
funziona.
E comunque il comportamento della printf e' davvero bizzarro, senza contare
che non ho capito cosa sia quella stringa che mi stampa!


Questo a me funziona correttamente
------------------------------------
#include <stdio.h>
int main(void) {
  double d;
  d=5.0-10.0;
  printf ("%lf \n",d);
  if (d<0) {
      printf("minore di 0\n");
  }
  return 0;
}
------------------------------------
L'output e':
-5.000000
minore di 0
Il mio compilatore e' gcc sotto linux.
Quindi sicuramente il problema sta da qualche altra parte.
Ciao,
Ema

 
gli fai stampare come float un int (che poi li' e' long d; o long double 
d;)? e cmq long NON e' un tipo ma un modificatore che serve a dire quanto 
devi allocare ovvero quanto deve essere "grande" il numero.
prova a fare cosi'
double d;
d=(double)difftime(lista[i].date,lista[j].date);
if(d<0) printf("il numero e' minore di 0: %f\n", d);
Luca


piccolo esempio che a me funziona:
#include <stdio.h>
#include <time.h>
int main()
{
time_t uno,due;
double d;
time(&uno);
do{
time(&due);
}while(difftime(due,uno) < 2.0);
d=difftime(due,uno);
printf("%f", d);
return 0;
}
 
quindi continuo a pensare che utilizzi male la difftime() magari se metti 
anche lo stralcio di codice in cui metti la roba nei 2 parametri che passi 
alla difftime e' meglio :)


 alla difftime e' meglio :)
Presto detto (taglio un po' di roba)..
Brevemente: l'algoritmo dovrebbe leggersi una directory, ed ordinare i files
in ordine cronologico di creazione/modifica.
  int totali=0;
  if((dp = opendir(nomedir))==NULL)
    {
      printf("Impossibile leggere la directory '%s'.",nomedir);
      return (0);
    }
  while((de=readdir(dp))!=NULL) {
    if(de->d_name[0]!='.')
      {
        strcpy(full_name,nomedir);
        strcat(full_name,"\\");
        strcat(full_name,de->d_name);
        i = stat(full_name,&st);
        if ((st.st_mode & S_IFMT) !=  S_IFDIR)
          {
              data[totali++] = st.st_mtime;
           }
        }
  }
  for (i=0;i<totali;i++)
    for (j=0;j<i;j++)
      {
        d=difftime(data[i],data[j]);
        if (d<0)
       {
             ....
Ora, l'ipotesi che siano errati i parametri della difftime mi pare remota,
anche perche', torno a ripetere, se d lo dichiaro long anziche' double, e se
faccio d = (long) difftime(...) funziona perfettamente.
Inoltre, al di la della correttezza o meno, qui c'e' proprio un punto oscuro
informatico (e temo un bug nel GCC del MinGW).
Torniamo infatti al codice del mio primo post.
 double d;
 d=difftime(lista[i].date,lista[j].date);
 printf ("%lf \n",d);
  if (d<0)
    {
     printf("minore di 0\n");
    }
Ed esaminiamo l'output.
-670137.000000
Ora, indipendentemente dalla correttezza d'uso della difftime, la printf mi
mostra che d in quel momento ha un valore negativo. Quindi DEVE entrare
dentro l'if!! Invece, come vedi, non mi stampa "minore di zero". E, nello
specifico, nell'algoritmo di cui sopra, non mi ordina affatto i files, ma li
lascia cosi' come li ha tirati su.
Capisci la mia perplessita'? sembra che if (d<0) non funzioni pur essendo
d<0 !
Ancora piu' perplesso rimango quando la if diventa if ((int) d < 0).
Ora di colpo funziona, il valore e' negativo e l'output in effetti comprende
"minore di 0".
Pero', riesaminiamolo bene:
-1.#IND00
minore di 0
Non mi stampa piu' -670137.000000, eppure (ti assicuro) i valori son gli
stessi di prima, e l'unica cos che ho cambiato e' la (int) messa dentro la
if.
Cast che viene eseguita DOPO la printf, ma i cui effetti invece avvengono
PRIMA della printf. In sostanza pare che il cast per qualche strano motivo
modifichi il valore di d, e questo in precedenza all'esecuzione del cast
medesimo.
E' un pezzo che programmo ma non ricordo mi sia mai capitata una cosa cosi'
strana.
E poi, che diavolo vuol dire "-1.#IND00".
Boh.. insisto: qui secondo me c'e' qualche problema di compilazione,
fattosta' che alla fine:
long d;
d = (long) difftime(...)
e le cose si son sistemate.
Rimane comunque la curiosita' di capire cosa sia successo

 Boh.. insisto: qui secondo me c'e' qualche problema di compilazione,
Di solito i problemi di compilazione (compilatore con bug) dipendono
da problemi di programmazione (programma da compilare con bug).
C:\>iao Angelo
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 da problemi di programmazione (programma da compilare con bug).
Rimane una certezza
if (d<0)
non va quando d<0
if( (int) d <0)
va ma corrompe il valore di d prima ancora che venga eseguito il cast.
Mi pare sia qualcosa ben oltre al semplice baco nel mio sorgente (che, detto
per inciso, funziona non appeno uso un long anziche' un double)

 non va quando d<0
Questo e' il tuo programma, preso quasi di pacca e compilato con mingW su
NT
int main(int argc, char* argv[])
{
 
   int  i = 0;
   int  j = 0;
   int  totali = 0;
   double d = 0;
   DIR*           dp     = NULL;
   struct dirent* de     = NULL;
   struct stat    st;
   time_t data[5000] = {0};
   char* nomedir = argv[1];
   char  full_name[256] = {'\0'};
 
   if((dp = opendir(nomedir))==NULL)
     {
       printf("Impossibile leggere la directory '%s'.\n",nomedir);
       return (0);
     }
   while((de = readdir(dp))!=NULL) {
     if(de->d_name[0]!='.')
       {
         strcpy(full_name, nomedir);
         strcat(full_name, "/"); // ??? strcat(full_name, "\");
                                 // e' una istruzione errata!!!
         strcat(full_name, de->d_name);
         i = stat(full_name, &st);
         if ((st.st_mode & S_IFMT) !=  S_IFDIR)
           {
               data[totali++] = st.st_mtime;
            }
         }
   }
   for (i=0;i<totali;i++)
     for (j=0;j<i;j++)
       {
         d=difftime(data[i],data[j]);
         printf("data[%d] - data[%d] = %f\n", i, j, d);
         if (d<0)
        {
          printf("Differenza negativa\n");
        }
       }
}
Le variabili sono state definite "a sentimento", ma in modo plausibile.
Questo e' l'output del programma facendogli leggere la directory temp
diffTimeProblem C:/TEMP
data[1] - data[0] = -29991496.000000
Differenza negativa
data[2] - data[0] = 250639.000000
data[2] - data[1] = 30242135.000000
data[3] - data[0] = -118332.000000
Differenza negativa
data[3] - data[1] = 29873164.000000
data[3] - data[2] = -368971.000000
Differenza negativa
data[4] - data[0] = -30168.000000
Differenza negativa
data[4] - data[1] = 29961328.000000
data[4] - data[2] = -280807.000000
Differenza negativa
data[4] - data[3] = 88164.000000
data[5] - data[0] = 52835.000000
data[5] - data[1] = 30044331.000000
data[5] - data[2] = -197804.000000
Differenza negativa
data[5] - data[3] = 171167.000000
data[5] - data[4] = 83003.000000
data[6] - data[0] = 138965.000000
data[6] - data[1] = 30130461.000000
data[6] - data[2] = -111674.000000
Differenza negativa
data[6] - data[3] = 257297.000000
data[6] - data[4] = 169133.000000
data[6] - data[5] = 86130.000000
data[7] - data[0] = 251999.000000
[mega cut]
data[40] - data[23] = -16543.000000
Differenza negativa
data[40] - data[24] = -15773.000000
Differenza negativa
[mega cut]
Continuo a sostenere che hai fatto _TU_ un errore da qualche parte (oltre
a quello che ti ho segnalato in questo post) , se mi spedisci il listato
completo posso provare a darci un'occhiata.


                                  // e' una istruzione errata!!!
Sorry. Non era un tuo errore ma un problema di taglincolla da Newsland.


 completo posso provare a darci un'occhiata.
Anche io credo che sia un  errore dell'OP. Detto questo voglio anche
ricordare pero' che:
<QUOTE>
Comparing floating point numbers is very dangerous. Given the inaccuracies
present in any computa-tion (including converting an input string to a
floating point value), you should never compare two floating point values to
see if they are equal. In a binary floating point format, different
computations which produce the same (mathematical) result may differ in
their least signi.cant bits. For example, adding 1.31e0+1.69e0 should
produce 3.00e0. Likewise, adding 1.50e0+1.50e0 should produce 3.00e0.
However, were you to compare (1.31e0+1.69e0) against (1.50e0+1.50e0) you
might find out that these sums are not equal to one another. The test for
equality succeeds if and only if all bits (or digits) in the two operands
are exactly the same. Since this is not necessarily true after two different
floating point computations which should produce the same result, a straight
test for equality may not work.The standard way to test for equality between
floating point numbers is to determine how much error (or tolerance) you
will allow in a comparison and check to see if one value is within this
error range of the other.
</QUOTE>
Provero' a scrivere un esempio per questo testo in inglese (tratto da AoA
versione HLA (non e' un libro di C cmq)):
<CODE>
#include <stdio.h>
int main()
{
    float f1,f2;
    f1=3.333f * 0.99f;
    f2=3.333f * 990.0f;
    f2/=1000;
    printf("%f - %f\n",f1,f2);
    if(f1==f2){
        puts("Uguali!");
    }else{
        puts("Diversi!");
    }
    return 0;
}
</CODE>
Il codice produce (almeno sulla mia macchina questo output):
<OUTPUT>
3.299670 - 3.299670
Diversi!
</OUTPUT>
In pratica, nonostante i due numeri *sembrino* identici (con un semplice
printf %f), in realta' sono diversi, anche se dovrebbero essere identici....
Facendo un f1-f2 si ottiene: 0.000000 e questo non aiuta! Ancora una volta
sembrano identici!
Solo chiedendo a printf di aumentare la precisione (il numero di cifre da
visualizzare):
printf("%.15f - %.15f\n",f1,f2);
si ottiene:
3.299669981002808 - 3.299669921875000
Come si vede, in effetti, i numeri (che dovrebbero essere uguali) sono
invece diversi!!!
La stessa cosa la si puo' dimostrare anche aumentando la precisione del
printf in f1-f2:
0.000000059127808
f1=3.333f * 0.99f;
f2=3.333f * 990.0f;
f2/=1000;
E' chiaro seguendo la semplice matematica che f1 e f2 dovrebbero contenere
lo stesso valore, ma putroppo i numeri in virgola mobile non sono cosi'
"precisi" ed "esatti"!
In pratica invece di  'if(f1==f2)' sarebbe piu' opportuno usare:
if(fabs(f1-f2)<0.000001f){
    puts("Uguali!");
}else{
    puts("Diversi!");
}
in questo caso diamo un margine di errore. Se aumentiamo 4 cifre decimali al
margine di errore, allora avremo nuovamente diversi (siamo meno tolleranti).
Riducendo le cifre decimali, otteniamo sempre uguali, ma abbiamo sempre meno
precisione nel giudizio (troppo tolleranti). In pratica bisogna valutare
bene cosa si vuole fare e scegliere un ggiusto margine di tolleranza.
L'esempio da me fatto non pone problemi con f1==f2 se mettiamo tutto a
double (invece che float). Double e' piu' preciso e per far accadere la
stessa cosa ci vogliono calcoli un pochino piu' complicati, ma il principio
e' assolutamente identico.
Quindi attenzione con i numeri in virgola mobile, non sono certo esatti ;-)
Tommy

"precisi" ed "esatti"!
   Verissimo. Spesso il problema sta nella rappresentazione interna
dei numeri in virgola mobile, che normalmente e` del tipo `m * 2^e',
con 0 <= m < 0,5. `m' ed `e' sono rappresentati in binario, e i dolori
cominciano qui. :)
   Ad esempio un semplicissimo 0,4 in binario diventa: 0,0(1100)
periodico, con rappresentazione necessariamente troncata in qualunque
precisione. Spippolando un po' si trovano anche esempi semplici che
diano imprecisioni dovute al troncamento su alcune macchine.
-- 
S.L.

 completo posso provare a darci un'occhiata.
Mah, non so che dire... posso anche aver fatto un errore, non mi spiego
quella if che non mi entra, pur essendo d < 0 (i casi sono due: o sbaglia la
printf, o sbaglia la if, ti pare?)
Rimane anche il problema del cast che mi sputtana il valore della variabile
d, prima ancora che il cast stesso venga eseguito.
Ad ogni modo, ecco qui:
/* file con data di creazione/modifica */
typedef struct
{
  char nome[255];
  char estensione[32];
  time_t date;
} type_filelist_el;
/* lista di files  */
typedef struct
{
  type_filelist_el filelist_el[10];
  int totale;
} type_filelist;
 type_filelist filelist;
 int trovato = find_object("C:\","pippo",&filelist);
[...]
int find_object(char *nomedir,char *prefisso,type_filelist *filelist)
{
  DIR *dp;            /* directory ref. */
  struct dirent *de;  /* entry ref. */
  struct stat   st;
  char nome_temp[255];
  char full_name[255];
  int i;
  int j=0;
  int totali=0;
  int trovato=0;
  long d;
  time_t date_temp=0;
  char *FuncName = "find_object";
  char log_msg[500];
  char *suffisso;
  //  char            log_filename[255]=FILE_LOG;
  if((dp = opendir(nomedir))==NULL)
    {
      sprintf(log_msg,"Impossibile leggere la directory '%s'.",nomedir);
      clean_up_exit(log_msg,FuncName, 'E');
      return (0);
    }
  while((de=readdir(dp))!=NULL) {
    if(de->d_name[0]!='.')
      {
        strcpy(full_name,nomedir);
        strcat(full_name,"\\");
        strcat(full_name,de->d_name);
 strupr(full_name);
 strupr(prefisso);
        i = stat(full_name,&st);
        if ((st.st_mode & S_IFMT) !=  S_IFDIR)
          {
     if (strstr(full_name,prefisso))
       {
  trovato=1;
  strcpy (filelist->filelist_el[totali].nome,de->d_name);
  suffisso = strstr(de->d_name,".");
  if (suffisso != NULL)
    {
      strcpy(filelist->filelist_el[totali].estensione,suffisso+1);
      strupr(filelist->filelist_el[totali].estensione);
    }
  else
    {
      strcpy(filelist->filelist_el[totali].estensione,"...");
    }
  filelist->filelist_el[totali++].date = st.st_mtime;
       }
          }
      }
  }
  closedir(dp);
  for (i=0;i<totali;i++)
    for (j=0;j<i;j++)
      {
 d=(long)
difftime(filelist->filelist_el[i].date,filelist->filelist_el[j].date);
  if (d<0)
    {
      date_temp = filelist->filelist_el[i].date;
      filelist->filelist_el[i].date = filelist->filelist_el[j].date;
      filelist->filelist_el[j].date = date_temp;
     strcpy (nome_temp,filelist->filelist_el[i].nome);
     strcpy (filelist->filelist_el[i].nome,filelist->filelist_el[j].nome);
     strcpy (filelist->filelist_el[j].nome,nome_temp);
     strcpy (nome_temp,filelist->filelist_el[i].estensione);
     strcpy
(filelist->filelist_el[i].estensione,filelist->filelist_el[j].estensione);
     strcpy (filelist->filelist_el[j].estensione,nome_temp);
    }
      }
  filelist->totale = totali;
  return (trovato);
}

 int trovato = find_object("C:\","pippo",&filelist);
   Questo non c'entra, ma non e` portabile l'inizializzazione di
variabili globali con valori non noti a compile time. Comunque, se non
e` un errore di copiatura, dovrebbe essere C:\\
-- 
S.L.

 e` un errore di copiatura, dovrebbe essere C:\\
Si e' un errore di copiatura, ovviamente.
In realta' al posto di c:\ e pippo c'erano altre variabili ma per
semplificare la cosa le ho sostituite con due costanti, altrimenti dovevo
postarvi tutto il resto, e son 1500 righe di codice.

 postarvi tutto il resto, e son 1500 righe di codice.
La mia m-box ha ancora un paio di mega liberi. Se vuoi approfittarne, non
dico che te lo faccio subito...  :-)


Capitano spesso anche a me problemini del genere. Di solito la cosa si
risolve cambiando specifica di conversione. Per i dati double in
printf c'è %f. Puoi provare questo.
Altrimenti ricontrolla bene come hai usato gli eventuali operatori bit
a bit o di assegnamento che hai eventualmente scritto. Altrimenti non
so che dirti, dal basso della mia pochissima esperienza la tua
funzione difftime() [è così che si chiamava no? gh :D] è praticamente
incomprensibile :(