Existen numerosas formas de almacenar números fraccionarios, y cada uno de ellos tiene ventajas y desventajas.
El punto flotante es, con diferencia, el formato más popular. Funciona codificando un signo, una mantisa y un exponente de base 2 con signo en números enteros, y empaquetándolos en un montón de bits. Por ejemplo, podría tener una mantisa de 32 bits de 0.5
(codificada como 0x88888888
) y un exponente con signo de 32 bits de +3
( 0x00000003
), que decodificaría a 4.0
(0.5 * 2 ^ 3
) Los números de coma flotante son rápidos, ya que se implementan en hardware y su precisión se escala con un tamaño absoluto, es decir, cuanto menor es el número, mejor es su precisión absoluta, por lo que el error de redondeo relativo permanece constante con el tamaño absoluto. Los flotadores son excelentes para valores muestreados de un dominio continuo, como longitudes, niveles de presión de sonido, niveles de luz, etc., y por eso, se usan comúnmente en el procesamiento de audio e imagen, así como en análisis estadísticos y simulaciones físicas. Su mayor inconveniente es que no son exactos, es decir, son propensos a errores de redondeo y no pueden representar con precisión todas las fracciones decimales. Todos los lenguajes de programación convencionales tienen un punto flotante de algún tipo.
Punto fijofunciona utilizando enteros suficientemente grandes y reservando implícitamente una parte de sus bits para la parte fraccional. Por ejemplo, un número de punto fijo de 24.8 bits reserva 24 bits para la parte entera (incluido el signo) y 8 bits para la parte fraccionaria. Desplazar a la derecha ese número en 8 bits nos da la parte entera. Los números de punto fijo solían ser populares cuando las unidades de punto flotante de hardware eran poco comunes o al menos mucho más lentas que sus homólogos enteros. Si bien los números de punto fijo son algo más fáciles de manejar en términos de exactitud (aunque solo sea porque son más fáciles de razonar), son inferiores a los flotantes en casi todos los demás aspectos: tienen menos precisión, un rango más pequeño y porque son más las operaciones son necesarias para corregir los cálculos del cambio implícito, las matemáticas de punto fijo hoy en día son a menudo más lentas que las matemáticas de punto flotante.
Los tipos decimales funcionan de manera muy similar a los números flotantes o de punto fijo, pero suponen un sistema decimal, es decir, su exponente (implícito o explícito) codifica potencia de 10, no potencia de 2. Un número decimal podría, por ejemplo, codificar una mantisa de 23456
y un exponente de -2
, y esto se expandiría a234.56
. Los decimales, debido a que la aritmética no está conectada a la CPU, son más lentos que los flotantes, pero son ideales para cualquier cosa que implique números decimales y necesite que esos números sean exactos, con redondeos en puntos bien definidos: cálculos financieros, marcadores, etc. Algunos lenguajes de programación tienen tipos decimales incorporados (por ejemplo, C #), otros requieren bibliotecas para implementarlos. Tenga en cuenta que, si bien los decimales pueden representar con precisión fracciones decimales no repetidas, su precisión no es mejor que la de los números de coma flotante; elegir decimales simplemente significa que obtienes representaciones exactas de números que se pueden representar exactamente en un sistema decimal (al igual que los flotadores pueden representar exactamente fracciones binarias).
Los números racionales almacenan un numerador y un denumerador, generalmente usando algún tipo de tipo entero bignum (un tipo numérico que puede crecer tanto como lo permitan las restricciones de memoria de la computadora). Este es el único tipo de datos del grupo que puede modelar con precisión números como 1/3
o 3/17
, así como operaciones en ellos: los racionales, a diferencia de los otros tipos de datos, producirán resultados correctos para cosas como3 * 1/3
. La matemática es bastante sencilla, aunque encontrar un algoritmo de factorización eficiente es bastante desafiante. Algunos lenguajes de programación tienen tipos racionales incorporados (por ejemplo, Common Lisp). Los inconvenientes de los racionales incluyen que son lentos (muchas operaciones requieren reducir fracciones y factorizar sus componentes), y que muchas operaciones comunes son difíciles o imposibles de implementar, y la mayoría de las implementaciones degradarán lo racional a flotante cuando esto suceda (por ejemplo, cuando llama sin()
en un racional).
BCD (decimal codificado en binario) utiliza "nibbles" (grupos de 4 bits) para codificar dígitos individuales; Como un mordisco puede contener 16 valores diferentes, pero los números decimales requieren solo 10, hay 6 valores "ilegales" por mordisco. Al igual que los decimales, los números BCD son decimales exactos, es decir, los cálculos realizados en números decimales funcionan como lo harían si los hiciera con lápiz y papel. Las reglas aritméticas para BCD son algo torpes, pero la ventaja es que convertirlas en cadenas es más fácil que con algunos de los otros formatos, lo que es especialmente interesante para entornos de bajos recursos como los sistemas integrados.
Las cadenas , sí, cadenas antiguas simples, también se pueden usar para representar números fraccionarios. Técnicamente, esto es muy similar a BCD, solo que hay un punto decimal explícito y usa un byte completo por dígito decimal. Como tal, el formato es un desperdicio (solo se usan 11 de 256 valores posibles), pero es más fácil de analizar y generar que BCD. Además, debido a que todos los valores utilizados son "insospechados", inofensivos y neutrales a la plataforma, los números codificados en cadena pueden viajar a través de las redes sin problemas. Es poco común encontrar que la aritmética se realiza en cadenas directamente, pero es posible, y cuando lo hace, son tan exactos como los otros formatos decimales (decimales y BCD).