tipo precio para numero mostrar money float ejemplo decimales dato sql-server vb.net database-design currency accounting

sql-server - precio - tipo de dato money en sql server



¿Usar Float o Decimal para la cantidad de dólares de la aplicación de contabilidad? (24)

Estamos reescribiendo nuestro sistema de contabilidad heredado en VB.NET y SQL Server. Trajimos un nuevo equipo de programadores .NET / SQL para hacer la reescritura. La mayor parte del sistema ya se completó con los montos en dólares utilizando Floats. El lenguaje de sistema heredado, programé en, no tenía un Float así que probablemente habría usado un Decimal.

¿Cuál es tu recomendación?

¿Se debe usar el tipo de datos Flotante o Decimal para las cantidades en dólares?

¿Cuáles son algunos de los pros y contras para cualquiera de los dos?

Una estafa mencionada en nuestro scrum diario fue que debe tener cuidado cuando calcula una cantidad que devuelve un resultado que tiene más de dos posiciones decimales. Parece que tendrá que redondear la cantidad a dos posiciones decimales.

Otra Con es todas las pantallas e importes impresos tienen que tener una declaración de formato que muestra dos posiciones decimales. Noté algunas veces que esto no se hizo y que las cantidades no parecían correctas. (es decir, 10.2 o 10.2546)

Un pro es Float solo ocupa 8 bytes en el disco donde el decimal tomaría 9 bytes (decimal 12,2)


¿Se debe usar el tipo de datos Flotante o Decimal para las cantidades en dólares?

La respuesta es fácil. Nunca flota. ¡ NUNCA !

Los flotadores fueron según IEEE 754 siempre binarios, solo el nuevo estándar IEEE 754R definió formatos decimales. Muchas de las partes binarias fraccionarias nunca pueden igualar la representación decimal exacta. Cualquier número binario se puede escribir como m / 2 ^ n (m, n enteros positivos), cualquier número decimal como m / (2 ^ n * 5 ^ n). Como los binarios carecen del factor primo 5, todos los números binarios se pueden representar exactamente por decimales, pero no viceversa.

0.3 = 3 / (2 ^ 1 * 5 ^ 1) = 0.3

0.3 = [0.25 / 0.5] [0.25 / 0.375] [0.25 / 3.125] [0.2825 / 3.125]

1/4 1/8 1/16 1/32

Entonces terminas con un número más alto o más bajo que el número decimal dado. Siempre.

Por que importa ? Redondeo El redondeo normal significa 0..4 hacia abajo, 5..9 hacia arriba. Entonces importa si el resultado es 0.049999999999 .... o 0.0500000000 ... Puede saber que significa 5 centavos, pero la computadora no lo sabe y redondea 0.4999 ... abajo (incorrecto) y 0.5000 .. arriba (derecha). Dado que el resultado de los cálculos en coma flotante siempre contiene pequeños términos de error, la decisión es pura suerte. Se vuelve imposible si quieres un manejo decimal de la ronda a la par con números binarios.

¿No está convencido? ¿Insiste en que en su sistema de cuenta todo está perfectamente bien? Activos y pasivos iguales? Bien, ¡entonces tome cada uno de los números formateados de cada entrada, analícelos y sumézcalos con un sistema decimal independiente! Compare eso con la suma formateada. Oops, hay algo mal, ¿no?

Para ese cálculo, se requirió una precisión y fidelidad extremas (utilizamos el FLOAT de Oracle) para poder registrar la "billonésima de un centavo" que se acumula.

No ayuda contra este error. Debido a que todas las personas asumen automáticamente que la computadora es correcta, prácticamente nadie verifica independientemente.


¡Pregunta a tus contadores! Te fruncirán el ceño por usar flotador. Al igual que alguien publicado anteriormente, use flotador SOLAMENTE si no le importa la precisión. Aunque siempre estaría en contra de eso cuando se trata de dinero.

En el software de contabilidad NO es aceptable un flotador. Use decimal con 4 decimales.


¿Ha considerado usar el tipo de datos monetarios para almacenar montos en dólares?

En cuanto a la Con que ese decimal ocupa un byte más, yo diría que no me importa. En 1 millón de filas, solo usará 1 MB más y el almacenamiento es muy barato en estos días.


De las 100 fracciones n / 100, donde n es un número natural tal que 0 <= n y n <100, solo cuatro se pueden representar como números de coma flotante. Eche un vistazo a la salida de este programa C:

#include <stdio.h> int main() { printf("Mapping 100 numbers between 0 and 1 "); printf("to their hexadecimal exponential form (HEF)./n"); printf("Most of them do not equal their HEFs. That means "); printf("that their representations as floats "); printf("differ from their actual values./n"); double f = 0.01; int i; for (i = 0; i < 100; i++) { printf("%1.2f -> %a/n",f*i,f*i); } printf("Printing 128 ''float-compatible'' numbers "); printf("together with their HEFs for comparison./n"); f = 0x1p-7; // ==0.0071825 for (i = 0; i < 0x80; i++) { printf("%1.7f -> %a/n",f*i,f*i); } return 0; }



Este es un excelente artículo que describe cuándo usar float y decimal . Float almacena un valor aproximado y el decimal almacena un valor exacto.

En resumen, los valores exactos como el dinero deben usar valores decimales, y los valores aproximados, como las mediciones científicas, deben usar flotación.

Aquí hay un ejemplo interesante que muestra que tanto el flotante como el decimal son capaces de perder precisión. Cuando se agrega un número que no es un número entero y luego se resta ese mismo número, el flotador resulta en la pérdida de precisión mientras que el decimal no:

DECLARE @Float1 float, @Float2 float, @Float3 float, @Float4 float; SET @Float1 = 54; SET @Float2 = 3.1; SET @Float3 = 0 + @Float1 + @Float2; SELECT @Float3 - @Float1 - @Float2 AS "Should be 0"; Should be 0 ---------------------- 1.13797860024079E-15

Al multiplicar un número no entero y dividir por ese mismo número, los decimales pierden precisión mientras que los flotantes no.

DECLARE @Fixed1 decimal(8,4), @Fixed2 decimal(8,4), @Fixed3 decimal(8,4); SET @Fixed1 = 54; SET @Fixed2 = 0.03; SET @Fixed3 = 1 * @Fixed1 / @Fixed2; SELECT @Fixed3 / @Fixed1 * @Fixed2 AS "Should be 1"; Should be 1 --------------------------------------- 0.99999999999999900


Hagas lo que hagas, debes tener cuidado con los errores de redondeo. Calcule usando un mayor grado de precisión de la que visualiza en.


He estado usando el tipo de dinero de SQL para almacenar valores monetarios. Recientemente, he tenido que trabajar con varios sistemas de pago en línea y he notado que algunos de ellos usan números enteros para almacenar valores monetarios. En mis proyectos actuales y nuevos, comencé a usar enteros y estoy bastante contento con esta solución.


Incluso mejor que usar decimales es usar números enteros antiguos (o quizás algún tipo de letra grande). De esta forma siempre tendrá la mayor precisión posible, pero se puede especificar la precisión. Por ejemplo, el número 100 podría significar 1.00 , que tiene el siguiente formato:

int cents = num % 100; int dollars = (num - cents) / 100; printf("%d.%02d", dollars, cents);

Si desea tener más precisión, puede cambiar el valor de 100 a uno más grande, como: 10 ^ n, donde n es el número de decimales.


La única razón para usar Float por dinero es si no le importan las respuestas precisas.


Lo que recomendaría es usar enteros de 64 bits que almacenen todo en centavos.


Los flotantes no son representaciones exactas, los problemas de precisión son posibles, por ejemplo cuando se agregan valores muy grandes y muy pequeños. Es por eso que los tipos decimales se recomiendan para la moneda, a pesar de que el problema de precisión puede ser lo suficientemente raro.

Para aclarar, el tipo decimal 12,2 almacenará esos 14 dígitos exactamente, mientras que el flotante no lo hará, ya que utiliza una representación binaria internamente. Por ejemplo, 0.01 no puede ser representado exactamente por un número de punto flotante - la representación más cercana es en realidad 0.0099999998


Los números de coma flotante solo pueden representar números que son una suma de múltiplos negativos de la base; para el punto flotante binario, por supuesto, son dos.

Solo hay cuatro fracciones decimales representables con precisión en el punto flotante binario: 0, 0.25, 0.5 y 0.75. Todo lo demás es una aproximación, de la misma manera que 0.3333 ... es una aproximación de 1/3 en aritmética decimal.

El punto flotante es una buena opción para cálculos donde la escala del resultado es lo importante. Es una mala elección cuando intentas ser preciso con algunas cifras decimales.


Los puntos flotantes tienen números irracionales inesperados.

Por ejemplo, no puede almacenar 1/3 como un decimal, sería 0.3333333333 ... (y así sucesivamente)

Los flotantes en realidad se almacenan como un valor binario y una potencia de 2 exponente.

Entonces 1.5 se almacena como 3 x 2 a -1 (o 3/2)

El uso de estos exponentes de base 2 crea algunos números irracionales extraños, por ejemplo:

Convierta 1.1 en un flotador y luego vuélvalo a convertir, su resultado será algo así como: 1.0999999999989

Esto se debe a que la representación binaria de 1.1 es en realidad 154811237190861 x 2 ^ -47, más de lo que puede soportar un doble.

Más sobre este tema en mi blog , pero básicamente, para el almacenamiento, es mejor que tengas decimales.

En el servidor Microsoft SQL tiene el tipo de datos de money ; esto generalmente es lo mejor para el almacenamiento financiero. Tiene una precisión de 4 posiciones decimales.

Para los cálculos, tiene más problemas: la inexactitud es una fracción pequeña, pero póngalo en una función de potencia y rápidamente se vuelve significativo.

Sin embargo, los decimales no son muy buenos para ningún tipo de matemática, por ejemplo, no hay soporte nativo para las potencias decimales.


Otra cosa que debe tener en cuenta en los sistemas de contabilidad es que nadie debe tener acceso directo a las tablas. Esto significa que todo acceso al sistema de contabilidad debe ser a través de procs almacenados. Esto es prevenir fraudes no solo ataques de inyección SQl. Un usuario interno que quiera cometer fraude no debería tener la capacidad de cambiar directamente los datos en las tablas de la base de datos, nunca. Este es un control interno crítico en su sistema. ¿Realmente desea que un empleado descontento vaya al servidor de su base de datos y haga que comience a ver los cheques? ¿O esconder que aprobaron un gasto a un proveedor no autorizado cuando no tienen autoridad de aprobación? Solo dos personas en toda su organización deberían poder acceder directamente a los datos en su base de datos financiera, su dba y su copia de seguridad. Si tiene muchos dbas, solo dos de ellos deberían tener este acceso.

Menciono esto porque si los programadores usaron flotador en un sistema de contabilidad, es probable que no estén familiarizados con la idea de los controles internos y no los consideraron en su esfuerzo de programación.


Para un sistema bancario que ayudé a desarrollar, fui responsable de la parte de "acumulación de intereses" del sistema. Todos los días, mi código calculaba cuánto interés se había acumulado (ganancia) en el saldo de ese día.

Para ese cálculo, se requirió una precisión y fidelidad extremas (utilizamos el FLOAT de Oracle) para poder registrar la "billonésima de un centavo" que se acumula.

Cuando se trataba de "capitalizar" el interés (es decir, devolver el interés a su cuenta), la cantidad se redondeaba al centavo. El tipo de datos para los saldos de cuenta fue dos decimales. (De hecho, era más complicado ya que era un sistema de múltiples monedas que podía funcionar en muchos decimales, pero siempre redondeamos al "centavo" de esa moneda). Sí, había "fracciones" de pérdida y ganancia, pero cuando las cifras de las computadoras se actualizaban (el dinero se pagaba o se pagaba), siempre eran valores de dinero REALES.

Esto satisfizo a los contadores, auditores y evaluadores.

Por lo tanto, consulte con sus clientes. Le informarán sus reglas y prácticas bancarias / contables.


Primero deberías leer esto Lo que todo científico informático debería saber sobre la aritmética de coma flotante . Entonces, realmente deberías considerar el uso de algún tipo de paquete de números de punto fijo / precisión arbitraria (por ejemplo, java BigNum, módulo decimal python), de lo contrario te encontrarás en un mundo de dolor. Luego averigüe si el uso del tipo de decimal SQL nativo es suficiente.

Flotantes / dobles existen (ed) para exponer el rápido x87 fp que ahora es bastante obsoleto. No los use si le preocupa la precisión de los cálculos y / o no compensa por completo sus limitaciones.


Probablemente desee utilizar alguna forma de representación de punto fijo para valores de moneda. También deseará investigar el redondeo del banco (también conocido como "medio punto a punto"). Evita el sesgo que existe en el método habitual de "redondear a la mitad".


Siempre puede escribir algo así como un tipo de dinero para .Net.

Eche un vistazo a este artículo: Un tipo de dinero para el CLR : el autor hizo un excelente trabajo en mi opinión.


Siempre use Decimal. Float le dará valores inexactos debido a problemas de redondeo.


Solo como advertencia adicional, SQL Server y .Net Framework usan un algoritmo predeterminado diferente para redondear. Asegúrese de verificar el parámetro MidPointRounding en Math.Round (). .Net framework usa el algoritmo de Bankers de forma predeterminada y SQL Server usa Redondeo algorítmico simétrico. Mira el artículo de Wikipedia here


Sus contadores querrán controlar cómo redondea. Usar float significa que estará redondeando constantemente, generalmente con una instrucción de tipo FORMAT (), que no es la forma en que desea hacerlo (use piso / techo en su lugar).

Tiene tipos de datos de moneda (dinero, moneda pequeña), que se deben usar en lugar de float o real. Al almacenar el decimal (12,2) se eliminarán los redondeos, pero también se eliminarán durante los pasos intermedios, lo que realmente no es lo que querrá en una aplicación financiera.


Un poco de historia aquí ...

Ningún sistema numérico puede manejar todos los números reales con precisión. Todos tienen sus limitaciones, y esto incluye tanto el punto flotante IEEE estándar como el decimal con signo. El punto flotante IEEE es más preciso por bit utilizado, pero eso no importa aquí.

Los números financieros se basan en siglos de práctica de papel y lápiz, con convenciones asociadas. Son bastante precisos, pero, lo que es más importante, son reproducibles. Dos contadores que trabajan con varios números y tasas deberían tener el mismo número. Cualquier posibilidad de discrepancia es susceptible de fraude.

Por lo tanto, para los cálculos financieros, la respuesta correcta es la que da la misma respuesta que un CPA que es bueno en aritmética. Esto es aritmética decimal, no punto flotante IEEE.


Use el tipo decimal del servidor SQL.

No use dinero ni flote .

el dinero usa 4 lugares decimales, es más rápido que usar el decimal PERO sufre de algunos problemas obvios y algunos no tan obvios con el redondeo ( vea este problema de conexión )