Hardware Upgrade Forum

Hardware Upgrade Forum (https://www.hwupgrade.it/forum/index.php)
-   Programmazione (https://www.hwupgrade.it/forum/forumdisplay.php?f=38)
-   -   [C] Valore assoluto di un numero + velocemente possibile (https://www.hwupgrade.it/forum/showthread.php?t=1677269)


Mr. X 12-02-2008 21:45

[C] Valore assoluto di un numero + velocemente possibile
 
Ciao Ragazzi,

sapete dirmi qul'è secondo voi il modo più veloce per ottenere il valore assoluto di un numero siccome lo devo calcolare tante volte? Io pensavo alla seguente funzione:

int abs(int x)
{
return (x > 0) ? x : -x;
}

che ne dite?

marko.fatto 12-02-2008 21:53

unsigned int :stordita:

Mr. X 12-02-2008 21:57

Quote:

Originariamente inviato da marko.fatto (Messaggio 21056232)
unsigned int :stordita:

In uscita voglio che sia dello stesso tipo che in ingresso. Poi è ovvio che sarà positivo. :)

kk3z 12-02-2008 22:12

#define ABS(x) ((x) > 0) ? (x) : -(x);

shinya 13-02-2008 09:34

Non va bene.

Considera (è in java, ma non cambia):

Codice:

class twocompl {
  public static void main(String[] args) {
    int x = -2147483648;

    System.out.println(myAbs(x));
  }

  private static int myAbs(int x) {
    return (x > 0) ? x : -x;
  }
}

c:\> java twocompl
-2147483648  <-- OMG!!1

In pratica, fallisce con il minor numero rappresentabile. Ma è la logica del complemento a due.
Il tuo problema è più accentuato perchè stai lavorando in C, quindi la dimensione dell'int varia da macchina a macchina.

Fatti due conti.

cionci 13-02-2008 10:19

Credo che il più veloce sia questo:
Codice:

unsigned int iabs(int a)
{
  return ~a + 1;
}

La condizione inline mette sempre in gioco il branch predictor, sicuramente un branch è veloce, ma l'altro no ;)

Mr. X 13-02-2008 11:08

Quote:

Originariamente inviato da cionci (Messaggio 21060726)
Credo che il più veloce sia questo:
Codice:

unsigned int iabs(int a)
{
  return ~a + 1;
}

La condizione inline mette sempre in gioco il branch predictor, sicuramente un branch è veloce, ma l'altro no ;)

Ma sei sicuro che la tua funzione non faccia solamente un cambio di segno? cioè se a = 5 => ritorno = -5 e se a = -8 => ritorno = 8

cionci 13-02-2008 11:11

Sì che testa :muro:

Mr. X 13-02-2008 11:15

Quote:

Originariamente inviato da cionci (Messaggio 21061662)
Sì che testa :muro:

Di nulla figurati :)

Mi sa che la più veloce è la mia... Ho provato con il quadrato al posto del valore assoluto e ho avuto un miglioramento di circa il 25% sulla velocità totale dell'algoritmo. Però dai un modo più veloce ci deve essere :)

kk3z 13-02-2008 11:40

hai provato la macro?

cionci 13-02-2008 11:53

Con il quadrato però perdi parte dello spazio degli interi.

wingman87 13-02-2008 12:23

Ma com'è codificato in bit un numero positivo e uno negativo? Lo avevo fatto alle superiori ma non me lo ricordo più...

Mr. X 13-02-2008 13:11

Quote:

Originariamente inviato da wingman87 (Messaggio 21062880)
Ma com'è codificato in bit un numero positivo e uno negativo? Lo avevo fatto alle superiori ma non me lo ricordo più...

Se il primo bit partendo da destra è uguale a 0 allora è positivo altrimenti è negativo. Ricorda però il complemento a 1.

Mr. X 13-02-2008 13:12

Quote:

Originariamente inviato da cionci (Messaggio 21062364)
Con il quadrato però perdi parte dello spazio degli interi.

Purtroppo lo so ed è per questo che non lo voglio usare. Era per fare una prova di quanto succhia l'if. :)

Mr. X 13-02-2008 13:16

Quote:

Originariamente inviato da kk3z (Messaggio 21062114)
hai provato la macro?

La macro da gli stessi risultati della mia funzione. :)

Mr. X 13-02-2008 13:17

Ho provato a costruirmi un Look Up Table e sono passato dai 19ms con la mia funzione a 13ms. :)
Peccato però che debba usare quella LUT che è abbastanzza grande.

wingman87 13-02-2008 13:24

Quote:

Originariamente inviato da Mr. X (Messaggio 21063763)
Se il primo bit partendo da destra è uguale a 0 allora è positivo altrimenti è negativo. Ricorda però il complemento a 1.

Ah ecco, grazie! Solo una cosa, non si guardava il primo bit da sinistra?

^TiGeRShArK^ 13-02-2008 14:13

...ovviamente hai effettuato un profiling per verificare incontrovertibilmente che ottimizzando quella funzione otterresti *sensibili* vantaggi in esecuzione spero... :mbe:
Altrimenti hai solo perso tempo sottraendolo alla scrittura di codice utile.... :fagiano:

gugoXX 13-02-2008 15:09

Se si tratta di studiare il problema sono d'accordo con TigerShark. E' sempre bene usare un profiling se si tratta di ottimizzare qualcosa.
E prima di ottimizzare con il profiling la maggior parte delle volte e' quasi sempre un problema di modello dati inadeguato.
Una volta aggiustato il modello dati la situazione migliora da sola.

Comunque non penso che questo caso sia effettivamente migliorabile, mantenendo la leggibilita' e l'universalita', rispetto a quanto ottenibile con la macro.

Se invece si tratta di una gara, poiche' sono l'unico ad essere rimasto in ufficio durante la pausa pranzo, e poiche' da solo mi rompo abbastanza, io provo con questo:

Codice:

int __inline absasm(int x)
{       
    __asm{
          mov eax,x
          cdq
          xor eax,edx
          sub eax,edx
    }               
}

Senza salti.
Ovviamente e' ben poco universale. Molto poco.
Se si prova a compilare con le __inline function si guadagna un 10% rispetto alla versione Macro (che penso sia comunque la preferibile e universale).

MFSPO=DBGPOF 13-02-2008 16:03

prova così:

Codice:

int abs(int x)

{
        int b=0x80000000,c=30;

        return (x*(((x&b)>>c)+1));
}



Tutti gli orari sono GMT +1. Ora sono le: 08:38.

Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Hardware Upgrade S.r.l.