Newsgroup: it.comp.lang.c
Titolo: Segno in C

Ciao ragazzi volevo sapere se qualcuno poteva suggerirmi come
calcolare il segno di un double...
Forse sarà una cavolata ma non ci riesco.
Esiste già una funzione?
Se no, qualcuno può suggerirmi un algoritmo estremamente veloce per
calcolare il segno da utilizzare come funzione "compare" di "qsort"
poichè la utilizzo su grafi di circa N nodi e in dll che viene
richiamata almeno N volte con 50000<N<100000.
Devo cercare di migliorare un pò i tempi di calcolo.
In realtà devo confrontare due double e restituire (-1,1,0) secondo i
casi, quindi anche una funzione di confronto va benissimo però mi
piacerebbe sapere anche come si calcola il segno.
Grazie
Andrea

...


 Esiste già una funzione?
Non basta un if/else?
--
Cingar
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 viceversa se e' negativo.
...
La tua soluzione ha tre difetti:
1. non e' molto portabile perche' a seconda del tipo e dell' 
architettura e del compilatore occorre shiftare di 31 o 63 o... bit
2. gli operatori bit a bit sono definiti solo tra tipi interi (OK, ci si 
puo' girare attorno con le union ma...)
3. least but not last: c' e' il problema che occorre distinguere anche 
lo zero e per i tipi float di zeri ce ne sono 2: +0 e -0
Infinitamente meglio un paio di if.
Giorgio

 Cingar
La funzione dovrebbe restituirmi -1 se minore 1 se maggiore e 0 altrimenti.
Comunque mi hanno suggerito in un altro post, e lo ringrazio, questa soluzione...
int sign(double num){
 return (num == 0) ? 0 : ((num > 0) ? 1 : -1);
}
Voi che ne dite?
Comunque per la precisione io ho una funzione 
int compare(double arg1,double arg2)
che mi deve restituire 
-1 se arg1 č + piccolo
+1 se arg1 č maggiore
0 se sono uguali
quindi volevo calcolare il segno di (arg1-arg2)
Capito?
Grazie comunque a tutti

 
io troverei preferibile
int sign(double num){
     if(num > 0)
        return 1;
     else if(num<0)
        return -1;
     else
        return 0;
}
1. perche'  e' la forma piu'   leggibile e immediatamente comprensibile 
di quello che la function fa.
2. perche'  mi aspetto che ci siano molti piu' casi in cui num sia > o < 
di zero che casi in cui sia esattamente zero.
Giorgio

 Capito?
No. Non ho capito perché vorresti usare un metodo cosě cervellotico per
fare una cosa cosě semplice. Scrivi semplicemente cosě:
int compare (double arg1, double arg2)
{
   if (arg1 > arg2)
      return +1;
   if (arg1 < arg2)
      return -1;
   return 0;
}
Non credo che possa esistere un'implementazione piů veloce. Sicuramente
non chiamando una funzione!!!
Chiamare le funzioni costa parecchio, in termini di cicli di clock: quando
chiami una funzione, il programma deve "push"are sullo stack una copia di
ogni argomento, piů una serie di altre cose (program pointer, stack
pointer, ecc...), e poi eliminare tutte queste cose quando la funzione
ritorna.
Supponendo un'ipotetica CPU che ha istruzioni per lavorare direttamente
con i numeri floating point, il codice sopra verrebbe compilato
all'incirca cosě:
   ; Routine "compare":
   01. carica arg1 nel registro 1
   02. carica arg2 nel registro 2
   03. esegui l'operazione "maggiore"
   04. se risultato č false salta a 07
   05. carica 1 nell'accumulatore
   06. ritorna
   07. esegui l'operazione "minore"
   08. se risultato č false salta a 11
   09. carica -1 nell'accumulatore
   10. ritorna
   11. carica 0 nell'accumulatore
   12. ritorna
Come la vorresti scrivere tu { return sign(arg1 - arg2); } verrebbe
all'incirca cosě:
   ; Routine "compare":
   01. carica "arg1" nel registro 1
   02. carica "arg2" nel registro 2
   03. esegui l'operazione "differenza"
   04. pusha lo stack pointer
   05. pusha il frame pointer, o chissŕ che altro
   06. pusha l'accumulatore (che contiene il risultato della sottrazione)
   07. chiama la routine "sign" (pusha il program pointer)
   08. pulisci la stack dalla roba messaci in 04-07
   09. ritorna
   ; Routine "sign":
   10. carica "num" nel registro 1
   11. carica 1 nel registro 2
   12. esegui l'operazione "maggiore"
   13. se risultato č false salta a 16
   14. carica 1 nell'accumulatore
   15. ritorna
   16. esegui l'operazione "minore"
   17. se risultato č false salta a 20
   18. carica -1 nell'accumulatore
   19. ritorna
   20. carica 0 nell'accumulatore
   21. ritorna
 
Proprio un bel risparmio: 21 istruzioni macchina contro 12...


 }
Potrebbe serviti qualcosa di piu` raffinato per i confronti con i
double, in particolare con l'uguaglianza.
Una cosa di questo tipo:
double a = 1.0;
double b = 0.1;
int s;
a += b;
a -= 1.0 + b;
s = sign(a);
potrebbe portare ad un risultato diverso da quello che ci si
aspetterebbe guardando il codice. La funzione sign io la scriverei
cosi`:
#include <float.h>
#include <math.h>
int sign(double n) {
        if (fabs(n) < DBL_EPSILON)
                return 0;
        if (n > 0)
                return 1;
        else
                return -1;
}
Luca
-- 
Home: 
http://kronoz.cjb.net
Ligabue canta: "Tutti vogliono viaggiare in primaaaa..."
Io ci ho provato e dopo un chilometro ho fuso il motore e bruciato
la frizione...