La operación decimal de SQL Server no es precisa
Cuando ejecuto esta simple operación en el servidor SQL:
Select 800.0 /30.0
Obtengo el valor 26.666666, donde incluso si se redondea a 6 dígitos, debería ser 26.666667. ¿Cómo puedo hacer que el cálculo sea exacto? Traté de buscarlo en línea y encontré una solución en la que convertí cada operando a un decimal de alta precisión antes de la operación, pero esto no me resultará conveniente porque tengo muchos cálculos largos y complejos. creo que debe haber una mejor solución.
Respuestas
Cuando se usa una división, en SQL Server, cualquier dígito después de la escala resultante se trunca, no se redondea. Para su expresión tiene a decimal(4,1)y a decimal(3,1), lo que resulta en a decimal(10,6):
Precision = p1 - s1 + s2 + max(6, s1 + p2 + 1)
Scale = max(6, s1 + p2 + 1)
Como resultado, 26.66666666666666~se trunca en 26.666666.
Puede evitar esto aumentando el tamaño de la precisión y la escala, y luego CONVERTvolver a la precisión y escala requeridas. Por ejemplo, aumentar la precisión y la escala de la decimal(3,1)de decimal(5,2)y convertir de nuevo a una decimal(10,6):
SELECT CONVERT(decimal(10,6),800.0 / CONVERT(decimal(5,3),30.0));
Esto vuelve 26.666667.
Esto podría ser útil:
Usar ROUND (Transact-SQL)
SELECT ROUND(800.0 /30.0, 5) AS RoundValue;
Resultado:
RoundValue
26.666670
Creo que es porque SQL Server toma sus números como decimalvalores (que son exactos, por ejemplo, 6.6666 y 6.6667 significa exactamente esos valores, no 6 y dos tercios) en lugar de floatvalores (que pueden funcionar con números aproximados).
Si lo lanza / convierte explícitamente en a floatal principio, debería hacer que sus cálculos funcionen sin problemas.
He aquí algunos ejemplos para demostrar la diferencia entre int, decimaly floatcálculos
- Dividiendo 20 entre 3
- Dividir 20 entre 3 y luego multiplicar por 3 nuevamente (que matemáticamente debería ser 20).
SELECT (20/3) AS int_calc,
(20/3) * 3 AS int_calc_x3,
(CAST(20 AS decimal(10,3)) /3) AS dec_calc,
(CAST(20 AS decimal(10,3)) /3) * 3 AS dec_calc_x3,
(CAST(20 AS float) /3) AS float_calc,
(CAST(20 AS float) /3) * 3 AS float_calc_x3
con los siguientes resultados
int_calc int_calc_x3 dec_calc dec_calc_x3 float_calc float_calc_x3
6 18 6.666666 19.999998 6.66666666666667 20
En su caso, puede utilizar
Select CAST(800.0 AS float) /30.0
lo que resulta en 26.6666666666667
Tenga en cuenta que si luego vuelve a multiplicar por 30, obtiene el resultado correcto, por ejemplo,
Select (CAST(800.0 AS float) /30.0) * 30
da como resultado 800. Las soluciones que tratan con decimales no tendrán esto.
Tenga en cuenta también que una vez que lo tenga como flotante, debería permanecer como flotante hasta que se convierta de nuevo a decimal o int de alguna manera (por ejemplo, guardado en una tabla como int). Entonces...
SELECT A.Num / 30
FROM (Select ((CAST(800.0 AS float) /30.0) * 30) AS Num) AS A
todavía resultará en 26.6666666666667
Con suerte, esto le ayudará en sus largos cálculos complejos.