Velocità di esecuzione delle funzioni ceil(),round(),floor() - pagina 5

 
Nikolai Semko:


Naturalmente hai ragione. Ma lo ripeto. Per il 99,9% dei compiti è assolutamente corretto sostituire le funzioni di arrotondamento con una variante alternativa più veloce usando la conversione dei tipi frazionari in (int) o (long). Un programmatore esperto dovrebbe semplicemente essere consapevole di questo fatto e applicarlo quando è opportuno.

Nel 99% dei casi non c'è bisogno di preoccuparsi dell'arrotondamento. Per il confronto dei prezzi ho questa sciocchezza:

// 0 - first is greater than second
// 1 - equal
// 2 - second is greater than first
uchar compare_prices(double first, double second)
{
   if(first - second >= _Point)
      return 0;
   if(second - first >= _Point)
      return 2;

   first = round(first/_Point);
   second = round(second/_Point);
   
   if(first > second)
      return 0;
   if(first < second)
      return 2;
   return 1;
}

Si può notare che nella maggior parte dei casi non arriva affatto a round(), anche se non ho misurato la velocità.

 
Nikolai Semko:

vedi sopra

quando x = 3 (qualsiasi numero intero) c'è un inceppamento :))

È la mia o la tua formula che ha un giunto?

Con rispetto.
 
Andrey Kisselyov:
C'è un bug nella mia o nella tua formula?

Con rispetto.

Nel mio vecchio:

y=ceil(x);  -> y=(int)(x+1);

e nel tuo:

y=ceil(x);  -> y=(int)(x)+1;

quando x=3 in entrambi i casi sarà il valore sbagliato di 4

e la variante:

y=ceil(x);  -> y=(int)(x+0.9999999999999997);

è finora il più corretto mantenendo la massima velocità di esecuzione.

 
Nikolai Semko:

Nel mio vecchio:

e nel tuo:

a x=3 in entrambi i casi ci sarà un valore errato di 4

e in caso di variante:

è finora il più corretto mantenendo la massima velocità di esecuzione.

ma perché avete bisogno di questa formula quando date un intero al suo ingresso?

con rispetto.

P.S. devi capire, se vuoi essere un buon programmatore, che non ovunque e non sempre è necessario spingere ogni sorta di funzioni di accelerazione, dipende dal compito a portata di mano e l'algoritmo con cui stai lavorando.
 
Andrey Kisselyov:

Ma perché avete bisogno di questa formula quando date un intero al suo ingresso?

Sinceramente.


Potreste non sapere se è un intero o un non intero. Ci sono momenti in cui un numero doppio può diventare un intero.

 
Andrey Kisselyov:

P.S. Devi capire, se vuoi essere un buon programmatore, che non ovunque e non sempre è necessario spingere ogni sorta di funzioni acceleratrici, dipende dal compito a portata di mano e dall'algoritmo con cui stai lavorando.

Naturalmente. Ecco perché ho scritto "applicare quando è il caso".
 
Nikolai Semko:

Potreste non sapere se è un intero o un non intero. Ci sono momenti in cui un numero può diventare un intero.

Poi vai dritto per le tue varianti di numeri d'ingresso.
if(x-(int)(x)>0)y=(int)(x)+1;
else y=x;

Con rispetto.

P.S. il doppio per definizione non può essere un intero, la rappresentazione di un numero nella memoria della macchina non cambia.
 
Andrey Kisselyov:
Allora devi fare un grande sforzo per le tue scelte di numeri sull'input.

con rispetto.


Ecco perché, per non doverne fare un dramma:

if(x-(int)(x)>0)y=(int)(x)+1;
else y=x;

È più facile da scrivere:

y=(int)(x+0.9999999999999997);

o questo.

#define _ceil(x)  (int)((x)+0.9999999999999997)
...
y=_ceil(x);
 
Nikolai Semko:

quindi non c'è bisogno di farne un dramma:

è più facile da scrivere:

su
1-0.9999999999999998

non riuscirai a farlo bene.
Con questo approccio, potete trovare un numero al quale la vostra formula non funzionerà.

Con rispetto.

 
Andrey Kisselyov:
su

Non funzionerà.
Con questo approccio, troverete un numero al quale la vostra formula non funzionerà.

Con rispetto.


Ne ho già scritto qui.

Ti consiglio di rileggere questo thread per non ripeterti.