Problema de arredondamento ímpar usando o especificador de formato ruby printf
-
10-07-2019 - |
Pergunta
Alguém tem alguma idéia sobre isso?
Quando corremos:
printf("%.0f", 40.5)
Em uma caixa do Windows, o retorno é "41", mas em nosso servidor Ubuntu de produção que estamos recebendo "40"
Solução
Parece um caso simples de Precisão de ponto flutuante binário. Em uma máquina, você obtém 40.4999999999, que arredonda para 40; Na outra máquina, você obtém 40.500000000001, que recorre a 41.
Se você precisar de números exatos, não deve usar o ponto flutuante binário. Você pode usar o ponto decimal de ponto fixo ou o ponto flutuante decimal.
EDIT: Você está usando o BigDecimal, você diz. Por que não evitar qualquer conversão para flutuar usando #round
e depois #to_i
? (Ou #floor
ou #ceil
ao invés de #round
... Não está claro qual é o seu objetivo.)
b = BigDecimal.new("40.5")
print b.round.to_i # => 41
Outras dicas
Que tal usar .round
em vez de? Rails ainda o aprimora para que você possa especificar a precisão (Veja API Doc).
Use %.0g em vez disso
A resposta de Scottj não explica seu problema - 40.5 é exatamente representável em binário. O que provavelmente está acontecendo é o seguinte: o Windows 'Printf "Rounds Half Up", e o Ubuntu's Printf "Rounds metade".