Executando verificação de segurança...
6

Complementando...

Com relação ao round, existem várias formas de arredondar em caso de "empate" (ou seja, quando a parte decimal é .5).

Entre as opções existentes, podemos listar as mais comuns:

  • arredondar para o maior (ou seja, 2.5 vira 3 e -2.5 vira -2), também chamado de "em direção ao infinito positivo" (towards infinity)
  • arredondar para o menor (ou seja, 2.5 vira 2 e -2.5 vira -3), também chamado de "em direção ao infinito positivo negativo" (towards negative infinity)
  • arredondar para o valor mais próximo de zero (2.5 vira 2 e -2.5 vira -2), também chamado de "towards zero"
  • arredondar para o valor mais distante de zero (2.5 vira 3 e -2.5 vira -3), também chamado de "away from zero"
  • arredondar para o número par mais próximo (2.5 vira 2 e 1.5 também vira 2) - essa é usada como o default em Python e C#
    • como curiosidade, esta regra também é conhecida como bankers rounding ou Banker's algorithm, tem mais detalhes sobre ela aqui.
  • arredondar para o número ímpar mais próximo (2.5 vira 3 e 1.5 vira 1)

A tabela abaixo tem um resumo disso:

ValorTowards +∞Towards -∞ParÍmparTowards zeroAway from zero
1.5212112
2.5322323
-1.5-1-2-2-1-1-2
-2.5-2-3-2-3-2-3

Muitas linguagens, inclusive, possuem formas de escolher qual opção queremos ao arredondar. Claro que nem todas as linguagens possuem todas as opções, e outras podem ter mais formas ainda. Python, por exemplo, possui a opção ROUND_05UP: se o último dígito depois de arredondar em direção ao zero for 0 ou 5, usa o critério away from zero , senão usa towards zero ("Round away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise round towards zero").


Quanto ao fato de floor e ceiling darem resultados "inesperados" com números negativos, na verdade faz sentido se levarmos em conta a definição. floor arredonda "para baixo", ou seja, o resultado é um número inteiro menor ou igual ao valor original. Por isso que floor(-2.1) é -3 e não -2. De forma similar, ceiling(-2.9) é um número inteiro que é maior ou igual ao valor original, por isso é -2 e não -3.

Estas formas de arredondamento também costumam ser descritas como "towards negative infinity" (floor) e "towards positivy infinity" (ceil), ou seja, o número é arredondado em determinada direção na Reta Numérica:

                     floor(-1.2)   ceil(-1.2)    floor(1.2)  ceil(1.2)
negative infinity <---- -2 --------- -1 ----- 0 ---- 1 -------- 2 ----> positive infinity
                              -1.2                      1.2

No caso, floor arredonda em direção ao infinito negativo: a partir do número, começa-se a "caminhar" na direção do infinito negativo, e o resultado é o primeiro número inteiro que for encontrado neste caminho. ceil faz o mesmo em direção ao infinito positivo.

Vale notar que no caso de floor e ceil, o critério é usado sempre para qualquer número, ao contrário do round, que usa somente em caso de empate (pode usar algum dos já citados acima como o default, ou qualquer outro indicado via algum parâmetro). Ou seja, floor(2.9) e floor(2.5) resultam em 2, ceil(2.9) e ceil(2.5) resultam em 3, e round(2.9) resulta em 3. Mas round(2.5) pode ser 2 ou 3 dependendo do critério de desempate usado.

Valorfloorceilround
2.1232
2.5232 ou 3 (depende do critério de desempate)
2.9233

Por fim, já escrevi um post bem detalhado sobre isso (do qual retirei/adaptei os trechos acima), serve como um complemento :-)

Carregando publicação patrocinada...
3

kht, antes de publicar aqui no Tabnews este post, fiz uma busca para ver se já não havia algo repetido aqui. Pena não ter encontrado sua postagem que ficou muito rica em detalhes que eu não conhecia a respeito destas potencialidades da linguagem a que se referiu. Inclusive, sua postagem original lá no Stackoverflow está bem caprichada e vale a pena conferir quem chegou a ler até aqui. Valeu por sua complementação, digna de troca de lugar com a que fiz :)


20241003T2311Z - Pareceu-me que sua habilidade com essas funções se dá pela sua experiência com manipulação de datas em diferentes linguagens de programação. Realmente, uma das funções que usei uma vez confia na operação com inteiros da máquina, como é o caso do cálculo de data no calendário gregoriano para dias juliano e vice-versa.

20241004T2151Z - Fiz um complemento usando algumas funções da linguagem C de que me lembrei. Um artíficio que emprega o recurso de casting de tipo (para float e para double) também é apresentado na coluna cast.

 --------------- float ------------- | -------------- double --------------
 value  cast trunc round floor  ceil |  value  cast trunc round floor  ceil
  3.00  3.00  3.00  3.00  3.00  3.00 |   3.00  3.00  3.00  3.00  3.00  3.00 *
  2.90  2.00  2.00  3.00  2.00  3.00 |   2.90  2.00  2.00  3.00  2.00  3.00
  2.60  2.00  2.00  3.00  2.00  3.00 |   2.60  2.00  2.00  3.00  2.00  3.00
  2.50  2.00  2.00  3.00  2.00  3.00 |   2.50  2.00  2.00  2.00  2.00  3.00
  2.40  2.00  2.00  2.00  2.00  3.00 |   2.40  2.00  2.00  2.00  2.00  3.00
  2.10  2.00  2.00  2.00  2.00  3.00 |   2.10  2.00  2.00  2.00  2.00  3.00
  
  2.00  2.00  2.00  2.00  2.00  3.00 |   2.00  1.00  1.00  2.00  1.00  2.00
  1.90  1.00  1.00  2.00  1.00  2.00 |   1.90  1.00  1.00  2.00  1.00  2.00
  1.60  1.00  1.00  2.00  1.00  2.00 |   1.60  1.00  1.00  2.00  1.00  2.00
  1.50  1.00  1.00  2.00  1.00  2.00 |   1.50  1.00  1.00  1.00  1.00  2.00
  1.20  1.00  1.00  1.00  1.00  2.00 |   1.20  1.00  1.00  1.00  1.00  2.00
  1.10  1.00  1.00  1.00  1.00  2.00 |   1.10  1.00  1.00  1.00  1.00  2.00
  
  1.00  1.00  1.00  1.00  1.00  2.00 |   1.00  0.00  0.00  1.00  0.00  1.00
  0.90  0.00  0.00  1.00  0.00  1.00 |   0.90  0.00  0.00  1.00  0.00  1.00
  0.60  0.00  0.00  1.00  0.00  1.00 |   0.60  0.00  0.00  1.00  0.00  1.00
  0.50  0.00  0.00  1.00  0.00  1.00 |   0.50  0.00  0.00  0.00  0.00  1.00
  0.40  0.00  0.00  0.00  0.00  1.00 |   0.40  0.00  0.00  0.00  0.00  1.00
  0.10  0.00  0.00  0.00  0.00  1.00 |   0.10  0.00  0.00  0.00  0.00  1.00
  
 --------------- float ------------- | -------------- double --------------
 value  cast trunc round floor  ceil |  value  cast trunc round floor  ceil
  0.00  0.00  0.00  0.00  0.00  1.00 |  -0.00 -0.00  0.00 -0.00 -1.00 -0.00 *
 -0.10 -0.00  0.00 -0.00 -1.00 -0.00 |  -0.10 -0.00  0.00 -0.00 -1.00 -0.00
 -0.40 -0.00  0.00 -0.00 -1.00 -0.00 |  -0.40 -0.00  0.00 -0.00 -1.00 -0.00
 -0.50 -0.00  0.00 -0.00 -1.00 -0.00 |  -0.50 -0.00  0.00 -1.00 -1.00 -0.00
 -0.60 -0.00  0.00 -1.00 -1.00 -0.00 |  -0.60 -0.00  0.00 -1.00 -1.00 -0.00
 -0.90 -0.00  0.00 -1.00 -1.00 -0.00 |  -0.90 -0.00  0.00 -1.00 -1.00 -0.00
 
 -1.00 -0.00  0.00 -1.00 -1.00 -0.00 |  -1.00 -1.00 -1.00 -1.00 -2.00 -1.00
 -1.10 -1.00 -1.00 -1.00 -2.00 -1.00 |  -1.10 -1.00 -1.00 -1.00 -2.00 -1.00
 -1.40 -1.00 -1.00 -1.00 -2.00 -1.00 |  -1.40 -1.00 -1.00 -1.00 -2.00 -1.00
 -1.50 -1.00 -1.00 -1.00 -2.00 -1.00 |  -1.50 -1.00 -1.00 -2.00 -2.00 -1.00
 -1.60 -1.00 -1.00 -2.00 -2.00 -1.00 |  -1.60 -1.00 -1.00 -2.00 -2.00 -1.00
 -1.90 -1.00 -1.00 -2.00 -2.00 -1.00 |  -1.90 -1.00 -1.00 -2.00 -2.00 -1.00
 
 -2.00 -1.00 -1.00 -2.00 -2.00 -1.00 |  -2.00 -2.00 -2.00 -2.00 -3.00 -2.00
 -2.10 -2.00 -2.00 -2.00 -3.00 -2.00 |  -2.10 -2.00 -2.00 -2.00 -3.00 -2.00
 -2.40 -2.00 -2.00 -2.00 -3.00 -2.00 |  -2.40 -2.00 -2.00 -2.00 -3.00 -2.00
 -2.50 -2.00 -2.00 -2.00 -3.00 -2.00 |  -2.50 -2.00 -2.00 -3.00 -3.00 -2.00
 -2.60 -2.00 -2.00 -3.00 -3.00 -2.00 |  -2.60 -2.00 -2.00 -3.00 -3.00 -2.00
 -2.90 -2.00 -2.00 -3.00 -3.00 -2.00 |  -2.90 -2.00 -2.00 -3.00 -3.00 -2.00
 
 -3.00 -2.00 -2.00 -3.00 -3.00 -2.00 |  -3.00 -3.00 -3.00 -3.00 -4.00 -3.00
 -3.10 -3.00 -3.00 -3.00 -4.00 -3.00 |  -3.10 -3.00 -3.00 -3.00 -4.00 -3.00

A tabela acima tem algumas particularidades indicadas devido o incremento utilizado ser 1/10, um valor não representável exatamente em IEEE754. A tabela completa pode ser calculada, extendida, modificada com o código C abaixo.

/* source code starts here... */
/* Compile with  gcc -Wall -Wextra round2.c -lm                               */
#include <stdio.h>
#include <math.h>

int main(int argc, char *argv[]) {

  float  f_value, f_truncated, f_rounded, f_floored, f_ceiled, f_casted;
  double d_value, d_truncated, d_rounded, d_floored, d_ceiled, d_casted;
  f_value = 3.0;
  d_value = 3.0;
  // print a header
  printf(" --------------- float ------------- | ");
  printf("-------------- double --------------\n" );
  printf(" value  cast trunc round floor  ceil | ");
  printf(" value  cast trunc round floor  ceil\n" );

  for(int i=0; i<58; i++) {
    f_truncated = trunc(f_value);
    f_rounded   = round(f_value);
    f_floored   = floor(f_value);
    f_ceiled    = ceil (f_value);
    f_casted    = (float)((int)(f_value));

    d_truncated = trunc(d_value);
    d_rounded   = round(d_value);
    d_floored   = floor(d_value);
    d_ceiled    = ceil (d_value);
    d_casted    = (double)((int)(d_value));

    printf("%6.2f%6.2f%6.2f%6.2f%6.2f%6.2f | %6.2f%6.2f%6.2f%6.2f%6.2f%6.2f\n",
                f_value, f_truncated, f_casted, f_rounded, f_floored, f_ceiled,
               d_value, d_truncated, d_casted, d_rounded, d_floored, d_ceiled);
    f_value += -0.1;
    d_value += -0.1;
  }

  return 0;
}
/* source code ends here. */

Fazendo uma pequena modificação no código e adotando um incremento (1/8) "representável" em base 2, a tabela fica livre de casos anormais.

 ------------------ float ---------------- | ----------------- double -----------------
  value   cast  trunc  round  floor   ceil |   value   cast  trunc  round  floor   ceil
  3.500  3.000  3.000  4.000  3.000  4.000 |   3.500  3.000  3.000  4.000  3.000  4.000
  3.375  3.000  3.000  3.000  3.000  4.000 |   3.375  3.000  3.000  3.000  3.000  4.000
  3.250  3.000  3.000  3.000  3.000  4.000 |   3.250  3.000  3.000  3.000  3.000  4.000
  3.125  3.000  3.000  3.000  3.000  4.000 |   3.125  3.000  3.000  3.000  3.000  4.000

  3.000  3.000  3.000  3.000  3.000  3.000 |   3.000  3.000  3.000  3.000  3.000  3.000
  2.875  2.000  2.000  3.000  2.000  3.000 |   2.875  2.000  2.000  3.000  2.000  3.000
  2.750  2.000  2.000  3.000  2.000  3.000 |   2.750  2.000  2.000  3.000  2.000  3.000
  2.625  2.000  2.000  3.000  2.000  3.000 |   2.625  2.000  2.000  3.000  2.000  3.000
  2.500  2.000  2.000  3.000  2.000  3.000 |   2.500  2.000  2.000  3.000  2.000  3.000
  2.375  2.000  2.000  2.000  2.000  3.000 |   2.375  2.000  2.000  2.000  2.000  3.000
  2.250  2.000  2.000  2.000  2.000  3.000 |   2.250  2.000  2.000  2.000  2.000  3.000
  2.125  2.000  2.000  2.000  2.000  3.000 |   2.125  2.000  2.000  2.000  2.000  3.000
  
  2.000  2.000  2.000  2.000  2.000  2.000 |   2.000  2.000  2.000  2.000  2.000  2.000
  1.875  1.000  1.000  2.000  1.000  2.000 |   1.875  1.000  1.000  2.000  1.000  2.000
  1.750  1.000  1.000  2.000  1.000  2.000 |   1.750  1.000  1.000  2.000  1.000  2.000
  1.625  1.000  1.000  2.000  1.000  2.000 |   1.625  1.000  1.000  2.000  1.000  2.000
  1.500  1.000  1.000  2.000  1.000  2.000 |   1.500  1.000  1.000  2.000  1.000  2.000
  1.375  1.000  1.000  1.000  1.000  2.000 |   1.375  1.000  1.000  1.000  1.000  2.000
  1.250  1.000  1.000  1.000  1.000  2.000 |   1.250  1.000  1.000  1.000  1.000  2.000
  1.125  1.000  1.000  1.000  1.000  2.000 |   1.125  1.000  1.000  1.000  1.000  2.000
  
  1.000  1.000  1.000  1.000  1.000  1.000 |   1.000  1.000  1.000  1.000  1.000  1.000
  0.875  0.000  0.000  1.000  0.000  1.000 |   0.875  0.000  0.000  1.000  0.000  1.000
  0.750  0.000  0.000  1.000  0.000  1.000 |   0.750  0.000  0.000  1.000  0.000  1.000
  0.625  0.000  0.000  1.000  0.000  1.000 |   0.625  0.000  0.000  1.000  0.000  1.000
  0.500  0.000  0.000  1.000  0.000  1.000 |   0.500  0.000  0.000  1.000  0.000  1.000
  0.375  0.000  0.000  0.000  0.000  1.000 |   0.375  0.000  0.000  0.000  0.000  1.000
  0.250  0.000  0.000  0.000  0.000  1.000 |   0.250  0.000  0.000  0.000  0.000  1.000
  0.125  0.000  0.000  0.000  0.000  1.000 |   0.125  0.000  0.000  0.000  0.000  1.000
  
  0.000  0.000  0.000  0.000  0.000  0.000 |   0.000  0.000  0.000  0.000  0.000  0.000
 -0.125 -0.000  0.000 -0.000 -1.000 -0.000 |  -0.125 -0.000  0.000 -0.000 -1.000 -0.000
 -0.250 -0.000  0.000 -0.000 -1.000 -0.000 |  -0.250 -0.000  0.000 -0.000 -1.000 -0.000
 -0.375 -0.000  0.000 -0.000 -1.000 -0.000 |  -0.375 -0.000  0.000 -0.000 -1.000 -0.000
 -0.500 -0.000  0.000 -1.000 -1.000 -0.000 |  -0.500 -0.000  0.000 -1.000 -1.000 -0.000
 -0.625 -0.000  0.000 -1.000 -1.000 -0.000 |  -0.625 -0.000  0.000 -1.000 -1.000 -0.000
 -0.750 -0.000  0.000 -1.000 -1.000 -0.000 |  -0.750 -0.000  0.000 -1.000 -1.000 -0.000
 -0.875 -0.000  0.000 -1.000 -1.000 -0.000 |  -0.875 -0.000  0.000 -1.000 -1.000 -0.000
 
 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 |  -1.000 -1.000 -1.000 -1.000 -1.000 -1.000
 -1.125 -1.000 -1.000 -1.000 -2.000 -1.000 |  -1.125 -1.000 -1.000 -1.000 -2.000 -1.000
 -1.250 -1.000 -1.000 -1.000 -2.000 -1.000 |  -1.250 -1.000 -1.000 -1.000 -2.000 -1.000
 -1.375 -1.000 -1.000 -1.000 -2.000 -1.000 |  -1.375 -1.000 -1.000 -1.000 -2.000 -1.000
 -1.500 -1.000 -1.000 -2.000 -2.000 -1.000 |  -1.500 -1.000 -1.000 -2.000 -2.000 -1.000
 -1.625 -1.000 -1.000 -2.000 -2.000 -1.000 |  -1.625 -1.000 -1.000 -2.000 -2.000 -1.000
 -1.750 -1.000 -1.000 -2.000 -2.000 -1.000 |  -1.750 -1.000 -1.000 -2.000 -2.000 -1.000
 -1.875 -1.000 -1.000 -2.000 -2.000 -1.000 |  -1.875 -1.000 -1.000 -2.000 -2.000 -1.000
 
 -2.000 -2.000 -2.000 -2.000 -2.000 -2.000 |  -2.000 -2.000 -2.000 -2.000 -2.000 -2.000
 -2.125 -2.000 -2.000 -2.000 -3.000 -2.000 |  -2.125 -2.000 -2.000 -2.000 -3.000 -2.000
 -2.250 -2.000 -2.000 -2.000 -3.000 -2.000 |  -2.250 -2.000 -2.000 -2.000 -3.000 -2.000
 -2.375 -2.000 -2.000 -2.000 -3.000 -2.000 |  -2.375 -2.000 -2.000 -2.000 -3.000 -2.000
 -2.500 -2.000 -2.000 -3.000 -3.000 -2.000 |  -2.500 -2.000 -2.000 -3.000 -3.000 -2.000
 -2.625 -2.000 -2.000 -3.000 -3.000 -2.000 |  -2.625 -2.000 -2.000 -3.000 -3.000 -2.000
 -2.750 -2.000 -2.000 -3.000 -3.000 -2.000 |  -2.750 -2.000 -2.000 -3.000 -3.000 -2.000
 -2.875 -2.000 -2.000 -3.000 -3.000 -2.000 |  -2.875 -2.000 -2.000 -3.000 -3.000 -2.000
 
 -3.000 -3.000 -3.000 -3.000 -3.000 -3.000 |  -3.000 -3.000 -3.000 -3.000 -3.000 -3.000
 -3.125 -3.000 -3.000 -3.000 -4.000 -3.000 |  -3.125 -3.000 -3.000 -3.000 -4.000 -3.000
 -3.250 -3.000 -3.000 -3.000 -4.000 -3.000 |  -3.250 -3.000 -3.000 -3.000 -4.000 -3.000
 -3.375 -3.000 -3.000 -3.000 -4.000 -3.000 |  -3.375 -3.000 -3.000 -3.000 -4.000 -3.000
 -3.500 -3.000 -3.000 -4.000 -4.000 -3.000 |  -3.500 -3.000 -3.000 -4.000 -4.000 -3.000
 -3.625 -3.000 -3.000 -4.000 -4.000 -3.000 |  -3.625 -3.000 -3.000 -4.000 -4.000 -3.000

É importante lembrar-se de que o arredondamento segundo a NBR5891 de 12/2014 não foi considerado nos exemplos.