Percebi um comportamento estranho de arredondamento no SQL Server (pelo menos 2008R2) ao converter a base de log 10 de 1000 para um inteiro. A resposta é claramente o valor exato 3, mas deve haver alguns decimais que o SQL Server está ocultando da saída:
SELECT LOG(1000, 10)--returns 3 with no visible decimals
SELECT CONVERT(INT, LOG(1000, 10))--returns 2
Eu fiz engenharia reversa do epsilon mínimo para obter o valor correto quando adicionado ao resultado de LOG
antes da conversão como aproximadamente:
SELECT CONVERT(INT, LOG(1000, 10)+0.0000000000000002220446049250313)
SELECT CONVERT(INT, LOG(1000, 10)+0.0000000000000002220446049250312)
Parece que eu poderia ficar o dia todo tornando esse valor mais preciso.
Isso só parece ser necessário para o caso de 1000, pois obtenho os valores inteiros adequados para 1, 10, 100 e 10000 e maiores sem usar nenhum termo épsilon.
O termo de erro parece ser a cauda da série Taylor expandida em 16 termos (conforme esta página ), mas por que o SQL Server está se comportando repentinamente como esperado (sem erro de precisão de máquina oculto) quando tento isso para o caso de 10000 e maiores ?
Por que o SQL Server está demonstrando inconsistentemente um erro de precisão da máquina?
Obrigado.
O problema é mais simples do que isso. LOG gera um número de ponto flutuante e você deve sempre ROUND ao converter de um valor de ponto flutuante para um int em vez de truncar.
O que você está fazendo é semelhante a:
O resultado de LOG(1000,10) não é 3, que você pode ver
está mais próximo de
(embora internamente o significando seja armazenado em base-2).
Não há nada de inconsistente nesse comportamento. LOG é uma estimativa baseada em uma expansão em série que converge para o logaritmo, e o resultado é retornado com uma quantidade limitada de precisão.
A função LOG foi projetada para retornar um resultado com precisão de 15 dígitos decimal, mas dependendo dos argumentos, o resultado pode ser um pouco maior ou um pouco menor que a resposta correta.
Por que isso pode ser um " comportamento consistente " para o MSSQL, eu chamaria isso de contra-intuitivo.
Eu não posso acreditar que estou dizendo isso, mas parece que o SQL Server lida com Float como um Decimal de Maior Precisão, até o momento em que você termina seus Computations, então ele converte como Float para sua Variable (ou seu Select) .
MSDN diz que
Log()
retorna um Float.O que observei é que os floats estão sendo tratados como valores decimais de maior precisão: