Velocidade de execução das funções ceil(),round(),floor() - página 5

 
Nikolai Semko:


É claro que você está certo. Mas vou dizer novamente. Para 99,9% das tarefas é absolutamente correto substituir as funções de arredondamento por uma variante alternativa mais rápida utilizando a conversão de tipos fracionários para (int) ou (longo). Um programador experiente deve estar ciente deste fato e aplicá-lo quando for conveniente.

Em 99% dos casos, não há necessidade de se preocupar com arredondamentos. Para comparações de preços, tenho este absurdo:

// 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;
}

Você pode notar que, na maioria dos casos, não chegará a arredondar() de forma alguma, embora eu não tenha medido a velocidade.

 
Nikolai Semko:

ver acima

quando x = 3 (qualquer número inteiro) há um congestionamento :))

É minha ou sua fórmula que tem um charro?

Respeitosamente.
 
Andrey Kisselyov:
Há algum bug na minha ou em sua fórmula?

Respeitosamente.

Na minha antiga:

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

e no seu:

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

quando x=3 em ambos os casos será o valor errado de 4

e a variante:

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

é até agora o mais correto, mantendo a máxima velocidade de execução.

 
Nikolai Semko:

Na minha antiga:

e no seu:

em x=3 em ambos os casos, haverá um valor incorreto de 4

e em caso de variante:

é até agora o mais correto, mantendo a máxima velocidade de execução.

mas por que você precisa desta fórmula quando você dá um número inteiro a sua contribuição?

com respeito.

P.S. você precisa entender, se você quer ser um bom programador, que nem sempre e nem sempre precisa empurrar todos os tipos de funções aceleradoras, depende da tarefa em mãos e do algoritmo com o qual você está trabalhando.
 
Andrey Kisselyov:

Mas por que você precisa desta fórmula quando você dá um número inteiro a sua contribuição?

Sinceramente.


Você pode não saber se é um inteiro ou um não-inteiro. Há momentos em que um número duplo pode se tornar um número inteiro.

 
Andrey Kisselyov:

P.S. Você tem que entender, se você quer ser um bom programador, que nem sempre é preciso empurrar todos os tipos de funções de aceleração, depende da tarefa em mãos e do algoritmo com o qual você está trabalhando.

É claro. É por isso que escrevi "aplicar quando apropriado".
 
Nikolai Semko:

Você pode não saber se é um inteiro ou um não-inteiro. Há momentos em que um número pode se tornar um número inteiro.

Em seguida, vá direto para suas variantes de números de entrada.
if(x-(int)(x)>0)y=(int)(x)+1;
else y=x;

Respeitosamente.

P.S. duplo por definição não pode ser um número inteiro, a representação de um número na memória da máquina não mudará.
 
Andrey Kisselyov:
Então você tem que fazer um grande negócio sobre suas escolhas de números na entrada.

respeitosamente.


É por isso, para que não tenhamos que fazer um grande negócio:

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

É mais fácil de escrever:

y=(int)(x+0.9999999999999997);

ou isto.

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

para que você não tenha que fazer um grande negócio com isso:

é mais fácil de escrever:

em
1-0.9999999999999998

você não vai conseguir acertar.
Com esta abordagem, você pode encontrar um número em que sua fórmula não funcionará.

Respeitosamente.

 
Andrey Kisselyov:
em

Não vai funcionar.
Com esta abordagem, você encontrará um número em que sua fórmula não funcionará.

Respeitosamente.


Eu já escrevi sobre isso aqui.

Sugiro que você releia este tópico para que não se repita.