Es posible que este artículo contenga investigaciones originales . ( Septiembre de 2019 ) |
En informática , el punto fijo es un método para representar números fraccionarios (no enteros) mediante el almacenamiento de un número fijo de dígitos de su parte fraccionaria. Las cantidades en dólares , por ejemplo, a menudo se almacenan con exactamente dos dígitos fraccionarios, que representan los centavos (1/100 de dólar). De manera más general, el término puede referirse a la representación de valores fraccionarios como múltiplos enteros de alguna unidad pequeña fija, por ejemplo, una cantidad fraccionaria de horas como un múltiplo entero de intervalos de diez minutos. La representación de números en punto fijo a menudo se contrasta con la representación en punto flotante, más complicada y computacionalmente exigente .
En la representación de punto fijo, la fracción se expresa a menudo en la misma base numérica que la parte entera, pero utilizando potencias negativas de la base b . Las variantes más comunes son decimal (base 10) y binaria (base 2). Esta última también se conoce comúnmente como escala binaria . Por lo tanto, si se almacenan n dígitos de fracción, el valor siempre será un múltiplo entero de b − n . La representación de punto fijo también se puede utilizar para omitir los dígitos de orden inferior de los valores enteros, por ejemplo, al representar grandes valores en dólares como múltiplos de $1000.
Cuando se muestran números decimales de punto fijo para lectura humana, los dígitos fraccionarios suelen estar separados de los de la parte entera por un carácter de base (normalmente "." en inglés, pero "," o algún otro símbolo en muchos otros idiomas). Sin embargo, internamente no hay separación, y la distinción entre los dos grupos de dígitos está definida únicamente por los programas que manejan dichos números.
La representación en punto fijo era la norma en las calculadoras mecánicas . Dado que la mayoría de los procesadores modernos tienen una unidad de punto flotante (FPU) rápida, las representaciones en punto fijo en las implementaciones basadas en procesadores ahora se usan solo en situaciones especiales, como en microprocesadores y microcontroladores integrados de bajo costo ; en aplicaciones que exigen alta velocidad o bajo consumo de energía o área de chip pequeña , como procesamiento de imágenes , video y señales digitales ; o cuando su uso es más natural para el problema. Ejemplos de esto último son la contabilidad de cantidades en dólares, cuando las fracciones de centavos deben redondearse a centavos enteros de formas estrictamente prescritas; y la evaluación de funciones por búsqueda en tabla , o cualquier aplicación donde los números racionales deben representarse sin errores de redondeo (lo que hace el punto fijo pero no el punto flotante). La representación en punto fijo sigue siendo la norma para las implementaciones de matriz de puertas programables en campo (FPGA), ya que el soporte de punto flotante en un FPGA requiere significativamente más recursos que el soporte de punto fijo. [1]
Valor representado | Representación interna |
---|---|
0.00 | 0 |
0,5 | 50 |
0,99 | 99 |
2 | 200 |
-14,1 | −1410 |
314.160 | 31416 |
Una representación de punto fijo de un número fraccionario es esencialmente un entero que se multiplicará implícitamente por un factor de escala fijo. Por ejemplo, el valor 1,23 se puede almacenar en una variable como el valor entero 1230 con un factor de escala implícito de 1/1000 (lo que significa que se supone implícitamente que los últimos 3 dígitos decimales son una fracción decimal), y el valor 1 230 000 se puede representar como 1230 con un factor de escala implícito de 1000 (con "menos 3" dígitos decimales fraccionarios implícitos, es decir, con 3 dígitos cero implícitos a la derecha). Esta representación permite que las unidades lógicas aritméticas de enteros estándar realicen cálculos con números racionales .
Los valores negativos se representan generalmente en formato binario de punto fijo como un entero con signo en representación de complemento a dos con un factor de escala implícito como el anterior. El signo del valor siempre se indicará mediante el primer bit almacenado (1 = negativo, 0 = no negativo), incluso si el número de bits fraccionarios es mayor o igual que el número total de bits. Por ejemplo, el entero binario con signo de 8 bits (11110101) 2 = −11, tomado con -3, +5 y +12 bits fraccionarios implícitos, representaría los valores −11/2 −3 = −88, −11/2 5 = −0. 343 75 y −11/2 12 = −0. 002 685 546 875 , respectivamente.
Alternativamente, los valores negativos pueden representarse mediante un entero en el formato de signo-magnitud , en cuyo caso el signo nunca se incluye en el número de bits fraccionarios implícitos. Esta variante se utiliza más comúnmente en la aritmética decimal de punto fijo. Por lo tanto, el entero decimal con signo de 5 dígitos (−00025) 10 , tomado con -3, +5 y +12 dígitos fraccionarios decimales implícitos, representaría los valores −25/10 −3 = −25000, −25/10 5 = −0,00025 y −25/10 12 = −0, 000 000 000 025 , respectivamente.
Un programa normalmente supondrá que todos los valores de punto fijo que se almacenarán en una variable dada, o que se producirán mediante una instrucción dada , tendrán el mismo factor de escala. Este parámetro normalmente puede ser elegido por el programador dependiendo de la precisión necesaria y del rango de valores que se almacenarán.
Es posible que el factor de escala de una variable o fórmula no aparezca explícitamente en el programa. En ese caso, las buenas prácticas de programación exigen que se proporcione en la documentación , al menos como comentario en el código fuente .
Para una mayor eficiencia, los factores de escala se eligen a menudo como potencias (positivas o negativas) de la base b utilizada para representar los números enteros internamente. Sin embargo, a menudo el mejor factor de escala viene determinado por la aplicación. Por lo tanto, a menudo se utilizan factores de escala que son potencias de 10 (por ejemplo, 1/100 para valores en dólares), para conveniencia humana, incluso cuando los números enteros se representan internamente en binario. Los factores de escala decimales también encajan bien con el sistema métrico (SI) , ya que la elección del factor de escala de punto fijo a menudo es equivalente a la elección de una unidad de medida (como centímetros o micrones en lugar de metros ).
Sin embargo, ocasionalmente se pueden utilizar otros factores de escala, por ejemplo, una cantidad fraccionaria de horas se puede representar como un número entero de segundos, es decir, como un número de punto fijo con un factor de escala de 1/3600.
Incluso con el redondeo más cuidadoso, los valores de punto fijo representados con un factor de escala S pueden tener un error de hasta ±0,5 en el entero almacenado, es decir, ±0,5 S en el valor. Por lo tanto, los factores de escala más pequeños generalmente producen resultados más precisos.
Por otra parte, un factor de escala más pequeño significa un rango más pequeño de los valores que se pueden almacenar en una variable de programa dada. El valor máximo de punto fijo que se puede almacenar en una variable es el valor entero más grande que se puede almacenar en ella, multiplicado por el factor de escala; y lo mismo para el valor mínimo. Por ejemplo, la tabla siguiente proporciona el factor de escala implícito S , los valores mínimos y máximos representables V min y V max , y la precisión δ = S /2 de los valores que se podrían representar en formato binario de punto fijo con signo de 16 bits, dependiendo del número f de bits fraccionarios implícitos.
F | S | del | V mín. | Vmáx . |
---|---|---|---|---|
-3 | 1/2 −3 = 8 | 4 | − 262 144 | + 262 136 |
0 | 1/2 0 = 1 | 0,5 | − 32 768 | + 32 767 |
5 | 1/2 5 = 1/32 | < 0,016 | −1024. 000 00 | +1023.968 75 |
14 | 1/2 14 = 1/ 16 384 | < 0. 000 031 | −2. 000 000 000 000 00 | +1.999 938 964 843 75 |
15 | 1/2 15 = 1/32 768 | < 0. 000 016 | −1. 000 000 000 000 000 | +0.999 969 482 421 875 |
16 | 1/2 16 = 1/ 65 536 | < 0. 000 008 | −0,500 000 000 000 000 0 | +0. 499 984 741 210 937 5 |
20 | 1/2 20 = 1/ 1 048 576 | < 0. 000 000 5 | −0. 031 250 000 000 000 000 00 | +0. 031 249 046 325 683 593 75 |
Se ha dicho que los formatos de punto fijo con factores de escala de la forma 2 n -1 (es decir, 1, 3, 7, 15, 31, etc.) son apropiados para el procesamiento de imágenes y otras tareas de procesamiento de señales digitales. Se supone que proporcionan conversiones más consistentes entre valores de punto fijo y flotante que el escalado 2 n habitual. El lenguaje de programación Julia implementa ambas versiones. [2]
Cualquier fracción binaria a /2 m , como 1/16 o 17/32, se puede representar exactamente en coma fija, con un factor de escala de potencia de dos 1/2 n con cualquier n ≥ m . Sin embargo, la mayoría de las fracciones decimales como 0,1 o 0,123 son fracciones repetidas infinitas en base 2 y, por lo tanto, no se pueden representar de esa manera.
De manera similar, cualquier fracción decimal a /10 m , como 1/100 o 37/1000, se puede representar exactamente en punto fijo con un factor de escala de potencia de diez 1/10 n con cualquier n ≥ m . Este formato decimal también puede representar cualquier fracción binaria a /2 m , como 1/8 (0,125) o 17/32 (0,53125).
De manera más general, un número racional a / b , con a y b relativamente primos y b positivo, puede representarse exactamente en punto fijo binario sólo si b es una potencia de 2; y en punto fijo decimal sólo si b no tiene factores primos distintos de 2 y/o 5.
Los cálculos de punto fijo pueden ser más rápidos y/o utilizar menos hardware que los de punto flotante. Si el rango de los valores a representar se conoce de antemano y es suficientemente limitado, el punto fijo puede hacer un mejor uso de los bits disponibles. Por ejemplo, si hay 32 bits disponibles para representar un número entre 0 y 1, una representación de punto fijo puede tener un error menor que 1,2 × 10 −10 , mientras que la representación de punto flotante estándar puede tener un error de hasta 596 × 10 −10 , porque 9 de los bits se desperdician con el signo y exponente del factor de escala dinámico. Específicamente, al comparar audio de punto fijo de 32 bits con audio de punto flotante , una grabación que requiere menos de 40 dB de margen dinámico tiene una relación señal-ruido más alta utilizando 32 bits fijos.
Los programas que utilizan cálculos de punto fijo suelen ser más portables que los que utilizan punto flotante, ya que no dependen de la disponibilidad de una FPU. Esta ventaja era particularmente fuerte antes de que se adoptara ampliamente el estándar IEEE de punto flotante , cuando los cálculos de punto flotante con los mismos datos arrojaban resultados diferentes según el fabricante y, a menudo, según el modelo de computadora.
Muchos procesadores integrados carecen de una FPU, porque las unidades aritméticas de números enteros requieren sustancialmente menos puertas lógicas y consumen un área de chip mucho menor que una FPU; y la emulación de software de punto flotante en dispositivos de baja velocidad sería demasiado lenta para la mayoría de las aplicaciones. Los chips de CPU para las primeras computadoras personales y consolas de juegos , como Intel 386 y 486SX , también carecían de una FPU.
La resolución absoluta (diferencia entre valores sucesivos) de cualquier formato de punto fijo es constante en todo el rango, es decir, el factor de escala S . Por el contrario, la resolución relativa de un formato de punto flotante es aproximadamente constante en todo su rango, variando dentro de un factor de la base b ; mientras que su resolución absoluta varía en muchos órdenes de magnitud, como los valores mismos.
En muchos casos, los errores de redondeo y truncamiento de los cálculos de punto fijo son más fáciles de analizar que los de los cálculos de punto flotante equivalentes. La aplicación de técnicas de linealización al truncamiento, como el tramado y/o la modelación de ruido, es más sencilla dentro de la aritmética de punto fijo. Por otro lado, el uso del punto fijo requiere un mayor cuidado por parte del programador. Evitar el desbordamiento requiere estimaciones mucho más estrictas para los rangos de variables y todos los valores intermedios en el cálculo, y a menudo también código adicional para ajustar sus factores de escala. La programación de punto fijo normalmente requiere el uso de tipos enteros de diferentes anchos . Las aplicaciones de punto fijo pueden hacer uso del punto flotante de bloque , que es un entorno de punto fijo en el que cada matriz (bloque) de datos de punto fijo se escala con un exponente común en una sola palabra.
Un uso común del punto fijo decimal es el almacenamiento de valores monetarios, para los cuales las complicadas reglas de redondeo de los números de punto flotante suelen ser un inconveniente. Por ejemplo, la aplicación de gestión de dinero de código abierto GnuCash , escrita en C, cambió del punto flotante al punto fijo a partir de la versión 1.6 por este motivo.
El punto fijo binario (escalamiento binario) se utilizó ampliamente desde finales de la década de 1960 hasta la década de 1980 para cálculos en tiempo real que requerían un uso intensivo de las matemáticas, como la simulación de vuelo y los algoritmos de control de plantas de energía nuclear . Todavía se utiliza en muchas aplicaciones DSP y microprocesadores personalizados. Los cálculos que involucran ángulos utilizarían la medición angular binaria .
El punto fijo binario se utiliza en los coprocesadores CORDIC de la serie STM32G4 y en los algoritmos de transformada de coseno discreta utilizados para comprimir imágenes JPEG .
Los instrumentos electrónicos, como los medidores de electricidad y los relojes digitales, a menudo utilizan polinomios para compensar los errores introducidos, por ejemplo, los de temperatura o de voltaje de la fuente de alimentación. Los coeficientes se generan mediante regresión polinómica . Los polinomios binarios de punto fijo pueden utilizar más bits de precisión que los de punto flotante, y lo hacen en código rápido utilizando CPU económicas. La precisión, crucial para los instrumentos, se compara bien con los cálculos de punto flotante de bits equivalentes, si los polinomios de punto fijo se evalúan utilizando el método de Horner (por ejemplo, y = (( ax + b ) x + c ) x + d ) para reducir la cantidad de veces que se produce el redondeo, y las multiplicaciones de punto fijo utilizan sumandos de redondeo.
Para sumar o restar dos valores con el mismo factor de escala implícito, es suficiente sumar o restar los enteros subyacentes; el resultado tendrá su factor de escala implícito común, por lo que puede almacenarse en las mismas variables de programa que los operandos. Estas operaciones producen el resultado matemático exacto, siempre que no se produzca un desbordamiento , es decir, siempre que el entero resultante pueda almacenarse en la variable de programa receptora . Si los operandos tienen diferentes factores de escala, deben convertirse a un factor de escala común antes de la operación.
Para multiplicar dos números de coma fija, basta con multiplicar los dos enteros subyacentes y suponer que el factor de escala del resultado es el producto de sus factores de escala. El resultado será exacto, sin redondeo, siempre que no desborde la variable receptora.
Por ejemplo, multiplicar los números 123 escalado por 1/1000 (0,123) y 25 escalado por 1/10 (2,5) da como resultado el entero 123×25 = 3075 escalado por (1/1000)×(1/10) = 1/10000, es decir, 3075/10000 = 0,3075. Como otro ejemplo, multiplicar el primer número por 155 escalado implícitamente por 1/32 (155/32 = 4,84375) da como resultado el entero 123×155 = 19065 con factor de escala implícito (1/1000)×(1/32) = 1/32000, es decir, 19065/32000 = 0,59578125.
En binario, es común usar un factor de escala que es una potencia de dos. Después de la multiplicación, el factor de escala se puede dividir desplazándolo hacia la derecha. El desplazamiento es simple y rápido en la mayoría de las computadoras. El redondeo es posible agregando un 'sumando de redondeo' de la mitad del factor de escala antes del desplazamiento; La prueba: round(x/y) = floor(x/y + 0.5) = floor((x + y/2)/y) = shift-of-n(x + 2^(n-1)) Un método similar se puede usar en cualquier escala.
Para dividir dos números de punto fijo, se toma el cociente entero de sus números enteros subyacentes y se supone que el factor de escala es el cociente de sus factores de escala. En general, la primera división requiere redondeo y, por lo tanto, el resultado no es exacto.
Por ejemplo, la división de 3456 escalado por 1/100 (34,56) y 1234 escalado por 1/1000 (1,234) produce el entero 3456÷1234 = 3 (redondeado) con factor de escala (1/100)/(1/1000) = 10, es decir, 30. Como otro ejemplo, la división del primer número por 155 escalado implícitamente por 1/32 (155/32 = 4,84375) produce el entero 3456÷155 = 22 (redondeado) con factor de escala implícito (1/100)/(1/32) = 32/100 = 8/25, es decir, 22×32/100 = 7,04.
Si el resultado no es exacto, el error introducido por el redondeo se puede reducir o incluso eliminar convirtiendo el dividendo a un factor de escala menor. Por ejemplo, si r = 1,23 se representa como 123 con escala 1/100, y s = 6,25 se representa como 6250 con escala 1/1000, entonces la división simple de los números enteros da como resultado 123÷6250 = 0 (redondeado) con factor de escala (1/100)/(1/1000) = 10. Si r se convierte primero a 1.230.000 con factor de escala 1/1000000, el resultado será 1.230.000÷6250 = 197 (redondeado) con factor de escala 1/1000 (0,197). El valor exacto 1,23/6,25 es 0,1968.
En la computación de punto fijo, a menudo es necesario convertir un valor a un factor de escala diferente. Esta operación es necesaria, por ejemplo:
Para convertir un número de un tipo de punto fijo con factor de escala R a otro tipo con factor de escala S , el entero subyacente debe multiplicarse por la relación R / S. Así, por ejemplo, para convertir el valor 1,23 = 123/100 de factor de escala R = 1/100 a uno con factor de escala S = 1/1000, el entero 123 debe multiplicarse por (1/100)/(1/1000) = 10, obteniéndose la representación 1230/1000.
Si el factor de escala es una potencia de la base utilizada internamente para representar el número entero, para cambiar el factor de escala solo es necesario eliminar los dígitos de orden inferior del número entero o añadir dígitos cero. Sin embargo, esta operación debe conservar el signo del número. En la representación en complemento a dos, eso significa extender el bit de signo como en las operaciones de desplazamiento aritmético .
Si S no divide a R (en particular, si el nuevo factor de escala S es mayor que el R original ), es posible que haya que redondear el nuevo entero .
En particular, si r y s son variables de punto fijo con factores de escala implícitos R y S , la operación r ← r × s requiere multiplicar los respectivos números enteros y dividir explícitamente el resultado por S . Es posible que haya que redondear el resultado y se produzca un desbordamiento.
Por ejemplo, si el factor de escala común es 1/100, multiplicar 1,23 por 0,25 implica multiplicar 123 por 25 para obtener 3075 con un factor de escala intermedio de 1/10000. Para volver al factor de escala original 1/100, el entero 3075 debe multiplicarse por 1/100, es decir, dividirse por 100, para obtener 31 (0,31) o 30 (0,30), según la política de redondeo utilizada.
De manera similar, la operación r ← r / s requerirá dividir los números enteros y multiplicar explícitamente el cociente por S. Aquí también pueden producirse redondeos y/o desbordamientos.
Para convertir un número de punto flotante a punto fijo, se puede multiplicar por el factor de escala S y luego redondear el resultado al entero más cercano. Se debe tener cuidado para garantizar que el resultado quepa en la variable o registro de destino. Según el factor de escala y el tamaño de almacenamiento, y según los números de entrada del rango, la conversión puede no implicar ningún redondeo.
Para convertir un número de punto fijo en un número de punto flotante, se puede convertir el entero en un número de punto flotante y luego dividirlo por el factor de escala S. Esta conversión puede implicar un redondeo si el valor absoluto del entero es mayor que 2 24 (para el punto flotante IEEE de precisión simple binario) o 2 53 (para precisión doble). Se puede producir un desbordamiento o subdesbordamiento si | S | es muy grande o muy pequeño, respectivamente.
Los procesadores típicos no tienen soporte específico para la aritmética de punto fijo. Sin embargo, la mayoría de las computadoras con aritmética binaria tienen instrucciones rápidas de desplazamiento de bits que pueden multiplicar o dividir un entero por cualquier potencia de 2; en particular, una instrucción de desplazamiento aritmético . Estas instrucciones se pueden utilizar para cambiar rápidamente los factores de escala que son potencias de 2, al tiempo que se conserva el signo del número.
Los primeros ordenadores, como el IBM 1620 y el Burroughs B3500, utilizaban una representación decimal codificada en binario (BCD) para los números enteros, concretamente la base 10, en la que cada dígito decimal se codificaba de forma independiente con 4 bits. Algunos procesadores, como los microcontroladores, pueden seguir utilizándola. En dichas máquinas, la conversión de los factores de escala decimal se puede realizar mediante desplazamientos de bits o mediante la manipulación de direcciones de memoria.
Algunas arquitecturas DSP ofrecen soporte nativo para formatos de punto fijo específicos, por ejemplo, números de n bits con signo y n −1 bits fraccionarios (cuyos valores pueden variar entre −1 y casi +1). El soporte puede incluir una instrucción de multiplicación que incluye renormalización, la conversión de escala del producto de 2 n −2 a n −1 bits fraccionarios. [ cita requerida ] Si la CPU no proporciona esa característica, el programador debe guardar el producto en un registro o variable temporal lo suficientemente grande y codificar la renormalización explícitamente.
El desbordamiento se produce cuando el resultado de una operación aritmética es demasiado grande para almacenarse en el área de destino designada. En la suma y la resta, el resultado puede requerir un bit más que los operandos. En la multiplicación de dos enteros sin signo con m y n bits, el resultado puede tener m + n bits.
En caso de desbordamiento, los bits de orden superior suelen perderse, ya que el entero no escalado se reduce en módulo 2 n, donde n es el tamaño del área de almacenamiento. En particular, se pierde el bit de signo, lo que puede cambiar radicalmente el signo y la magnitud del valor.
Algunos procesadores pueden establecer un indicador de desbordamiento de hardware y/o generar una excepción en caso de que se produzca un desbordamiento. Algunos procesadores pueden, en cambio, proporcionar aritmética de saturación : si el resultado de una suma o resta se desbordara, almacenan en su lugar el valor con la mayor magnitud que pueda caber en el área de recepción y que tenga el signo correcto. [ cita requerida ]
Sin embargo, estas características no son muy útiles en la práctica; generalmente es más fácil y seguro seleccionar factores de escala y tamaños de palabra para excluir la posibilidad de desbordamiento, o verificar si los operandos tienen valores excesivos antes de ejecutar la operación.
Algunos lenguajes informáticos, en particular PL/I , COBOL , Ada , JOVIAL y Coral 66 , ofrecen compatibilidad explícita con números de punto fijo. Estos proporcionan tipos de datos de punto fijo con un factor de escala binario o decimal. El compilador genera automáticamente código para realizar las conversiones de escala adecuadas al realizar operaciones con estos tipos de datos, al leer o escribir variables o al convertir los valores a otros tipos de datos, como punto flotante.
La mayoría de esos lenguajes fueron diseñados entre 1955 y 1990. Los lenguajes más modernos por lo general no ofrecen ningún tipo de datos de punto fijo o soporte para la conversión de factores de escala. Ese también es el caso de varios lenguajes más antiguos que todavía son muy populares, como FORTRAN , C y C++ . La amplia disponibilidad de procesadores rápidos de punto flotante, con un comportamiento estrictamente estandarizado, ha reducido en gran medida la demanda de soporte de punto fijo binario. [ cita requerida ] De manera similar, el soporte para punto flotante decimal en algunos lenguajes de programación, como C# y Python , ha eliminado la mayor parte de la necesidad de soporte de punto fijo decimal. En las pocas situaciones que requieren operaciones de punto fijo, el programador puede implementarlas, con conversión de escala explícita, en cualquier lenguaje de programación.
Por otra parte, todas las bases de datos relacionales y la notación SQL admiten la aritmética decimal de punto fijo y el almacenamiento de números. PostgreSQL tiene una notación especial .numéricoTipo para el almacenamiento exacto de números con hasta 1000 dígitos. [3]
Además, en 2008 la Organización Internacional de Normalización (ISO) emitió una propuesta para ampliar el lenguaje de programación C con tipos de datos de punto fijo, para el beneficio de los programas que se ejecutan en procesadores integrados. [4] Además, la Colección de compiladores GNU (GCC) tiene soporte de back-end para punto fijo. [5] [6]
Supongamos que existe la siguiente multiplicación con 2 números con punto fijo y 3 decimales.
Observe cómo, dado que hay 3 decimales, mostramos los ceros finales. Para volver a caracterizar esto como una multiplicación de números enteros, primero debemos multiplicar moviendo todos los decimales a números enteros, luego multiplicaremos por para volver a ponerlos. La ecuación ahora se ve así
Esto funciona de manera equivalente si elegimos una base diferente, en particular la base 2 para el cálculo, ya que un desplazamiento de bit es lo mismo que una multiplicación o división por un orden de 2. Tres dígitos decimales equivalen a unos 10 dígitos binarios, por lo que deberíamos redondear 0,05 a 10 bits después del punto binario. La aproximación más cercana es entonces 0,0000110011.
Así que nuestra multiplicación se convierte en
Esto se redondea a 11,023 con tres dígitos después del punto decimal.
Consideremos la tarea de calcular el producto de 1,2 y 5,6 con punto fijo binario utilizando 16 bits fraccionarios. Para representar los dos números, se los multiplica por 2 16 , obteniendo 78 643 ,2 y 367 001 ,6; y se redondean estos valores a los enteros más cercanos, obteniendo 78 643 y 367 002 . Estos números encajarán cómodamente en una palabra de 32 bits con formato de complemento a dos con signo.
Al multiplicar estos números enteros, se obtiene el número entero de 35 bits 28 862 138 286 con 32 bits fraccionarios, sin ningún redondeo. Tenga en cuenta que almacenar este valor directamente en una variable entera de 32 bits provocaría un desbordamiento y la pérdida de los bits más significativos. En la práctica, probablemente se almacenaría en una variable entera con signo de 64 bits o en un registro .
Si el resultado se va a almacenar en el mismo formato que los datos, con 16 bits fraccionarios, ese entero se debe dividir por 2 16 , lo que da aproximadamente 440 401 .28, y luego se redondea al entero más cercano. Este efecto se puede lograr sumando 2 15 y luego desplazando el resultado por 16 bits. El resultado es 440 401 , que representa el valor 6. 719 985 961 914 062 5 . Teniendo en cuenta la precisión del formato, ese valor se expresa mejor como 6. 719 986 ± 0. 000 008 (sin contar el error que proviene de las aproximaciones de operandos). El resultado correcto sería 1.2 × 5.6 = 6.72.
Para un ejemplo más complicado, supongamos que los dos números 1.2 y 5.6 están representados en formato de punto fijo de 32 bits con 30 y 20 bits de fracción, respectivamente. Al escalar por 2 30 y 2 20 se obtienen 1 288 490 188 .8 y 5 872 025 .6, que se redondean a 1 288 490 189 y 5 872 026 , respectivamente. Ambos números todavía caben en una variable entera con signo de 32 bits y representan las fracciones.
Su producto es (exactamente) el entero de 53 bits 7 566 047 890 552 914 , que tiene 30+20 = 50 bits de fracción implícitos y, por lo tanto, representa la fracción
Si optamos por representar este valor en formato fijo de 16 bits con signo y 8 bits fraccionarios, debemos dividir el producto entero por 2 50-8 = 2 42 y redondear el resultado; lo que se puede lograr sumando 2 41 y desplazando 42 bits. El resultado es 1720, que representa el valor 1720/2 8 = 6. 718 75 , o aproximadamente 6.719 ± 0.002.
Se han utilizado varias notaciones para especificar de forma concisa los parámetros de un formato de punto fijo. En la siguiente lista, f representa el número de bits fraccionarios, m el número de bits de magnitud o enteros, s el número de bits de signo y b el número total de bits.
type F is delta 0.01 range -100.0 .. 100.0