El tamaño de un flotador depende de la plataforma, aunque un valor máximo de 1.8e308 con una precisión de aproximadamente 14 dígitos decimales es un valor común (el formato IEEE de 64 bits). Precisión de punto flotante Los números de punto flotante tienen una precisión limitada. Aunque depende del sistema, PHP normalmente usa el formato de doble precisión IEEE 754, lo que dará un error relativo máximo debido al redondeo en el orden de 1.11e-16. Las operaciones aritméticas no elementales pueden dar errores más grandes y, por supuesto, la propagación de errores debe considerarse cuando se combinan varias operaciones. Además, los números racionales que son exactamente representables como números de coma flotante en la base 10, como 0,1 o 0,7. No tienen una representación exacta como números de coma flotante en la base 2, que se utiliza internamente, no importa el tamaño de la mantisa. Por lo tanto, no pueden convertirse en sus equivalentes binarios internos sin una pequeña pérdida de precisión. Esto puede llevar a resultados confusos: por ejemplo, piso ((0.10.7) 10) normalmente devolverá 7 en lugar de lo esperado 8. Ya que la representación interna será algo así como 7.9999999999999991118. . Por lo tanto, nunca confíe en los resultados del número flotante hasta el último dígito y no compare los números de coma flotante directamente con la igualdad. Si se necesita mayor precisión, las funciones matemáticas de precisión arbitraria y las funciones gmp están disponibles. Para una explicación quotsimplequot, vea la guía de punto flotante raquo that039s también titulado quotWhy no mis números agregan upquot Convertir a flotar Para obtener información sobre la conversión de cadena s a flotar. Vea Conversión de cadenas en números. Para valores de otros tipos, la conversión se realiza convirtiendo primero el valor a entero y luego a float. Consulte Conversión a entero para obtener más información. A partir de PHP 5, se produce un aviso si un objeto se convierte en float. Comparación de flotadores Como se observó en la advertencia anterior, probar valores de punto flotante para la igualdad es problemático, debido a la forma en que están representados internamente. Sin embargo, hay maneras de hacer comparaciones de valores de punto flotante que trabajan alrededor de estas limitaciones. Para probar valores de punto flotante para la igualdad, se utiliza un límite superior del error relativo debido al redondeo. Este valor se conoce como la máquina epsilon, o roundoff unidad, y es la menor diferencia aceptable en los cálculos. A y b son iguales a 5 dígitos de precisión. Ltphp a 1.23456789 b 1.23456780 epsilon 0.00001 si (abs (a - b) lt epsilon) echo true gt NaN Algunas operaciones numéricas pueden dar como resultado un valor representado por la constante NAN. Este resultado representa un valor indefinido o no representable en los cálculos de punto flotante. Cualquier comparación suelta o estricta de este valor con cualquier otro valor, incluyendo a sí misma, tendrá como resultado FALSO. Debido a que NAN representa cualquier número de valores diferentes, NAN no debe compararse con otros valores, incluyendo sí mismo, y en su lugar debe comprobarse utilizando isnan (). Notas de contribución del usuario 30 notas sólo un comentario sobre algo la inserción de precisión de punto flotante, que va: Esto está relacionado con. 0.3333333. Mientras que el autor probablemente sabe de qué están hablando, esta pérdida de precisión no tiene nada que ver con la notación decimal, tiene que ver con la representación como un binario de punto flotante en un registro finito, como cuando 0.8 termina en decimal, es La repetición 0.110011001100. En binario, que está truncado. 0,1 y 0,7 son también no terminales en binario, por lo que también se truncan, y la suma de estos números truncados no se suman a la representación binaria truncada de 0,8 (que es por qué (piso) (0,810) produce un diferente, más Intuitivo, resultado). Sin embargo, como 2 es un factor de 10, cualquier número que termina en binario también termina en decimal. Indicación general de la computación: Si estás siguiendo la pista del dinero, hazte a ti mismo ya tus usuarios el favor de manejar todo internamente en centavos y hacer tantas matemáticas como puedas en números enteros. Almacene los valores en centavos si es posible. Sumar y restar en centavos. En cada operación que involucre flotas, pregúntate qué sucederá en el mundo real si obtuviera una fracción de un centavo aquí y si la respuesta es que esta operación generará una transacción en centavos enteros, no trate de llevar la ficción de precisión fraccional Que sólo atornillar las cosas más tarde. // binarydata64 pack (H. 0000000000000000) float64 descomprimir (d. Binarydata64) // 0.0 gt Obtengo 0 tanto para números de 32 bits como de 64 bits. Pero, por favor no utilice sus propias funciones para convertir de flotador a binario y viceversa. Looping rendimiento en PHP es horrible. Usando pack / unpack usas la codificación de los procesadores, que siempre es correcta. En C puede acceder a los mismos datos 32/64 como float / double o 32/64 bit integer. No hay conversiones. Para obtener la codificación binaria: ltphp float32 pack (f 5300231) binarydata32 descomprimir (H. float32) // 0EC0A14A float64 pack (d. 5300231) binarydata64 descomprimir (H. float64) // 000000C001385441 gt Y mi ejemplo de hace medio año: Ltphp binarydata32 pack (H. 0EC0A14A) float32 descomprimir (f. Binarydata32) // 5300231 binarydata64 pack (H. 000000C001385441) float64 desempaquetar (d. Binarydata64) // 5300231 gt Y por favor, la mente de los chicos Big and Little endian. La identificación tiene gusto de señalar una característica de la ayuda flotante de los PHPs del punto que isnt aclaró dondequiera aquí, y me conducía loco. Esta prueba (donde vardump dice que a0.1 y b0.1) si (agtb) echo blah fallará en algunos casos debido a la precisión oculta (problema estándar de C, que los PHP no hacen mención de, por lo que asumí que se habían librado De ella). Debo señalar que originalmente pensé que esto era un problema con los flotadores que se almacenan como cadenas, así que los forcé a ser flotadores y todavía no se evaluó correctamente (probablemente dos problemas diferentes). Para arreglar, tuve que hacer este horrible kludge (el equivelant de todos modos): if (ronda (a, 3) gtround (b, 3)) echo blah ESTO funciona. Obviamente aunque vardump dice que las variables son idénticas, y DEBERÍAN ser idénticas (comenzadas en 0.01 y agregadas 0.001 repetidamente), theyre no. Allí había algo de precisión oculta que me hacía arrancarme el pelo. Tal vez esto debería agregarse a la documentación Tenga cuidado al usar valores de float en cadenas que se usan como código más tarde, por ejemplo al generar código JavaScript o sentencias SQL. El flotante está formateado de acuerdo con la configuración regional de los navegadores, lo que significa que 0.23 dará como resultado 0,23. Imagine algo como esto: x 0.23 js var foo doBar (x) imprimir js Esto resultaría en un resultado diferente para los usuarios con algunas localidades. En la mayoría de los sistemas, se imprimirá: var foo doBar (0.23) pero cuando por ejemplo llegue un usuario de Alemania, sería diferente: var foo doBar (0,23) que obviamente es una llamada diferente a la función. JavaScript no indicará un error, argumentos adicionales se descartan sin previo aviso, pero la función doBar (a) obtendría 0 como parámetro. Problemas similares podrían surgir en cualquier otro lugar (SQL, cualquier cadena utilizada como código en otro lugar). El problema persiste, si utiliza el archivo. Operador en lugar de evaluar la variable en la cadena. Por lo tanto, si realmente necesita estar seguro de tener la cadena correctamente formateada, use numberformat () para hacerlo. En algunos casos puede que desee obtener el valor máximo para un flotador sin obtener INF. Vardump (1.8e308) suele mostrar: float (INF) Escribí una pequeña función que iterará para encontrar el mayor valor flotante no-infinito. Viene con un multiplicador configurable y valores afines para que pueda compartir más CPU para obtener una estimación más precisa. No he visto mejores valores con más afines, pero bueno, la posibilidad está aquí, así que si realmente la cosa vale la pena el tiempo de la CPU, sólo tratar de afilar más. Los mejores resultados parecen estar con mul2 / affine1. Puedes jugar con los valores y ver lo que obtienes. Lo bueno es que este método funcionará en cualquier sistema. Ltphp función floatmax (mul 2. affine 1) max 1 omax 0 mientras que ((cadena) max INF) para (i 0 i lt affine i) pmax 1 max omax mientras ((cadena) max INF) omax max max pmax pmax mul return Omax gt Ive acaba de encontrar este problema con los flotadores al escribir una función de fijación de precios. Al convertir de cadena a un flotador, con 2 dígitos de precisión, el problema con la comparación de los flotadores puede aparecer y dar resultados inconsistentes debido al proceso de conversión. Una manera más fácil en lugar de confiar en el mencionado método epsilon es usar numberformat (al menos para mí como Ill remember it). Ejemplo de función que puede devolver un resultado inesperado: if ((float) a (flotante) b) echo true else echo false echos false en este ejemplo. Usando el formato numérico aquí para recortar la precisión (la precisión de 2 puntos que se utiliza principalmente para las monedas etc, aunque las precisiones más altas deben ser atendidas correctamente por numberformat), devolverá un resultado esperado: if (numberformat ((float) a, 2) numberformat ((Flotante) b, 2)) echo true else echo false Correctamente echos true. Estaba programando una aplicación de contabilidad en MySql que me obligaba a sumar una colección de flotadores y asegurarse de que son iguales a cero antes de comprometer una transacción, pero como se ve arriba, no siempre se puede confiar en una suma de flotadores (como era mi caso). Seguí recibiendo un resto muy pequeño (como 1.4512431231e-14). Puesto que había utilizado numberformat (num, 2) para establecer la precisión de los números en la base de datos a sólo dos (2) decimales, cuando llegue el momento de calcular la suma simplemente multiplico cada número por diez (10), eliminando Y lugares decimales y dejándome con enteros para preformar mi suma. Esto funcionó muy bien. La función devuelve 5 para 5.000 porque si no hay punto decimal, entonces los primeros strpos serán FALSE y FALSE lt 1 es TRUE, por lo que la condición seguirá siendo verdadera. Debería comprobarse si strpos devuelve una posición válida: ltphp str2num (str) if (strpos (str.) FALSE ampamp strpos (str.) FALSE ampamp strpos (str.) Lt strpos (str. Strreplace (str., Str) str strtr (str.,.) Str strenga (str.) Str strout (str) Ser capaz de establecer la precisión está utilizando la función de matemáticas BC bccomp () Por ejemplo: ltphp a 1.23456789 b 1.23456780 precisión 5 if (bccomp (precisión ab) 0) echo true // true gt ltphp a sprintf (.17f. 0.1 0.2) b 0.3 if (bccomp (ab 17) 0) echo FALSE // FALSE gt Los cálculos que involucran tipos de flotadores se vuelven inexactos cuando se trata de números con más de aproximadamente 8 dígitos de largo dondequiera que sea el punto decimal. Esto se debe a la forma en que los flotadores de 32 bits se almacenan comúnmente en la memoria. Esto significa que si confía en tipos flotantes mientras trabaja con pequeñas fracciones o grandes números, sus cálculos pueden terminar entre fracciones minúsculas a varios billones de dólares. Esto suele importar cuando se convierte en forma de almacenamiento de memoria binaria y la edición de muchas aplicaciones flotan las direcciones de memoria directamente o tratando con números de longitud más pequeños. Pero si está trabajando con números de escala más grande y decimales, lo mejor es cambiar a trabajar con otros tipos:.php / manual / en / refs. math. php ltphp / hex2float (Convertir valor hexadecimal de 8 dígitos a flotar (32bits de una sola precisión) Acepta valores hexadecimales de 8 dígitos en un uso de cadena: hex2float32n (429241f0) devuelve - gt 73.128784179688 / function hex2float (número) binfinal sprintf (032b hexdec (número)) signo substr (binfinal 0. 1) exp substr (binfinal. 8) mantisa 1. substr (binfinal) 9 mantissa strsplit (mantisa) exp bindec (exp) - 127 significand 0 para (i 0 i lt 24 i) significand (1 / pow (2 i)) mantisa i return significand pow (2 exp) (sign - 2 1) gt Convierte una cadena hexadecimal en un número de flotador IEEE 754. Esta función es 2 veces más rápida que la siguiente función hexadecimal a 32 bits Esta función sólo cambia los tipos de datos (cadena a int) Esta función es un puerto de la función de hexadecimal a 64 bits de abajo. Ltphp función hexTo32Float (strHex) v hexdec (strHex) x (v amp (1 ltlt 23) - 1)) (1 ltlt 23) (v Gtgt 31 1) exp (v gtgt 23 amp 0xFF) - 127 retorno x pow (2. exp - 23) gt ltphp // ejemplo echo hexTo32Float (C4028000) // salidas: -522 echo hexTo32Float (457F9000) // salidas: 4089 Echo hexTo32Float (2D7F5) // salidas: 6.00804264307E-39 echo hexTo32Float (0002D7F5) // salidas: 6.00804264307E-39 echo hexTo32Float (47D9F95E) // salidas: 111602.734375 gt PHP cambia de la notación decimal estándar a la notación exponencial para ciertas especificaciones Flota Puede ver una lista parcial de estos valores especiales con esto: ltphp para (tmp 0. i 0 i lt 100 i) tmp 100000 ronda de eco (tmp), n gt Por lo tanto, si agrega dos flotadores, termina con un valor especial , p. ej 1.2E6, a continuación, poner ese valor sin modificación en una consulta de actualización para almacenar el valor en una columna decimal, digamos, es probable que obtenga una transacción fallida, ya que la base de datos verá 1.2E6 como datos varchar, no decimal. Del mismo modo, probablemente obtendrá un error de validación XSD si pone el valor en xml. Tengo que ser honesto: esta es una de las cosas más extrañas que he visto en cualquier idioma en más de 20 años de codificación, y es un dolor colosal para trabajar. En MySQL, muchos tipos de números de punto flotante pueden tener un rango especificado usando 2 valores, la precisión y la escala E. g. Float (precisión, escala) para el tipo de datos. Esta sintaxis significa que un número puede ser largo bits ltprecisiongt, pero sólo puede tener ltscalegt bits después del punto decimal. P. ej. Un campo flotante (5,2) puede tener los valores -999,99 a 999,99. Esta es una función para validar un flotador de PHP usando esta sintaxis: ltphp function validatefloat (float, precision, scale) max (float) strpad (. (Float lt min) (float gt max)) return false else return true gt Aquí está una función para convertir un formato flotante exponencial en un formato decimal flotador, por ejemplo 1.6e12 a 1600000000000. Ayudará a resolver el problema especificado por kjohnson anterior. He probado, pero no en cualquier situación del mundo real por lo que cualquier comentarios / mejoras / informes de errores sería apreciado. Función ltphp exptodec (floatstr) // Formatea una cadena de números en coma flotante en notación decimal, soporta flotantes firmados, también admite formateo no estándar, p. 0,2e2 para 20 \ 1.6E6 a 1600000, -4.566e-12 a -0.000000000004566, 34e10 a 340000000000 // Autor: Bob // asegúrese de que su una cadena de flotador estándar de php (es decir, el cambio 0.2e2 a 20) // php formateará automáticamente flotantes decimales si Están dentro de un cierto rango floatstr (string) ((float) (floatstr)) // si hay un E en la cadena float si ((pos strpos (strolower (floatstr), e) El E, por ejemplo // desmonte el signo num, si lo hay, y déjelo si su (no requerido) si (() (Numsign num 0)) numsign (número 1) else numsign if (numsign) numsign // despoja el signo exponencial (o - como en E6) si hay uno, de lo contrario lance error, por ejemplo E6 gt si ((expsign exp 0)) exp substr (exp. 1) else triggererror (No se puede convertir la notación exponencial a la notación decimal: inválido float string floatstr. EUSERERROR) // obtener el número de decimales A la derecha del punto decimal (o 0 si no hay punto dec), por ejemplo 1,6 gt 1 lugares derechos ((decpos strpos (num.)) False). 0. strlen (substr (num. Decpos 1)) // obtenga el número de decimales a la izquierda del punto decimal (o la longitud de todo el número si no hay punto dec), p. 1.6 gt 1 leftdecplaces (decpos false). Strlen (num). Strlen (substr (número 0. decpos)) // calcular el número de ceros de exp, exp sign y dec places, p. Exp 6, exp sign, dec lugares 1 gt num zeros 5 si (expsign) numzeros exp - rightdecplaces else numzeros exp - leftdecplaces // construye una cadena con ceros numzeros, p. 0 5 veces gt 00000 ceros strpad (números 0) // tira decimal de num, p. 1.6 gt 16 if (decot false) num strreplace (... num) // si exponente positivo, devuelve como 1600000 si (expsign) devuelve numsign. Num. Ceros // si exponente negativo, devuelve como 0.0000016 else return numsign. 0 .. ceros. Num // de lo contrario, asumir ya en notación decimal y devolver otra vez floatstr gt Como m punto lebkowskiphp en gmail dot com (.php / language. types. float81416) observó 9 comentarios a continuación: Cuando PHP convierte un flotador en una cadena, el decimal Separador utilizado depende de las convenciones locales actuales. Sin embargo, para declarar un número de coma flotante, siempre se debe usar un stop completo que sea el código dependiente de la localidad (imagine la pesadilla): ltphp float 1.5 // float (1.5) float 1. 5 // Error de análisis: error de sintaxis, Ahora, si tiene una cadena que contiene un número localizado, puede convertirlo de nuevo a un número de coma flotante usando el número de coma flotante (float), float (float) 1.5 // float (1.5) La siguiente función: ltphp / Convertir una cadena numérica localizada en un número de punto flotante cadena param string sNumber La cadena numérica localizada a convertir. Return float El número convertido. / Function str2num (sNumber) aConvenciones localeConv () sNumber trim ((cadena) sNumber) bIsNegative (0 aConvenciones nsignposn ampamp (sNumber ampamp) sNumber) sCaracteres aConvenciones decimal. AConvenciones mondecimalpoint. AConvenciones negativesign sNumber pregreplace (/Configuraciones (sCharacters)) d /. Trim ((cadena) sNumber)) iLength strlen (sNumber) if (strlen (aConventions decimalpoint)) sNumber strreplace (aConventions decimalpoint, .. sNumber) if (AConvenciones mondecimalpoint)) sNumber strreplace (aConvenciones mondecimalpoint, .. sNumber) sNegativeSign aConvenciones negativesign if (strlen (sNegativeSign) ampamp 0 aConvenciones nsignposn) bIsNegative (sNegativeSign sNumber sNegativeSign sNumber) si (bIsNegative) sNumber strreplace (aConventions negativesign,.sNumber) fNumber (Float) sNumber if (bIsNegative) fNumber - fNumber return fNumber gt Ejemplo: ltphp setLocale (LCALL. FrBE. UTF-8) // separador decimal es ahora una coma float - 123456.789 cadena (cadena) float vardump (float) // float (-123456,789) vardump (cadena) // cadena (11) -123456,789 vardump (float) cadena) // float (-123456) vardump (str2num (cadena)) // float (-123456,789) Gt También funciona con cadenas devueltas por la función numberformat (): ltphp setLocale (LCALL. FrBE. UTF-8) // separador decimal ahora es una coma conv localeconv () float - 123456.789 cadena conv intcurrsymbol. (Flotante) // float (-123456,789) vardump (cadena) // cadena (15) EUR -123.456,79 vardump (float) string) // Float (0) vardump (str2num (cadena)) // float (-123456,79) gt Los valores de punto flotante tienen una precisión limitada. Por lo tanto un valor puede no tener la misma representación de cadena después de cualquier procesamiento. Esto también incluye escribir un valor de punto flotante en su script e imprimirlo directamente sin ninguna operación matemática. Si desea obtener más información acerca de los flotadores y qué se lee en la IEEE 754, haga lo siguiente: docs. sun / source / 806-3568 / ncggoldberg. html Convierta la cadena regional en el número float ltphp str2num (str) if (strpos (str. Str stren (str., Str) str str (str., Str) str str str (str., Str) str stren (str. 2,5,01) // 25.01 str2num (25.01) // 25.01 str2num (2,5.01) // 25.01 gtPuede descargar este artículo como un archivo Word97 o RTF. Este artículo se aplica a todas las versiones de Microsoft Excel para Windows. Este artículo fue escrito por Chip Pearson, 27-Oct-1998. Copyright, 1998, 1999, Charles H. Pearson Este artículo describe las razones por las que puede experimentar errores aritméticos en Microsoft Excel97. Contenido del artículo: Valores reales y mostrados Números de punto flotante Funciones de la hoja de trabajo para redondear IEEE Floating Point Standard En este artículo se supone que está familiarizado con lo siguiente: Los conceptos de programación de Visual Basic para aplicaciones (VBA) de Excel Los sistemas binarios de números Pueden existir Que el valor que ve en una hoja de cálculo de Excel no es igual al valor que cree que debería ser. Generalmente hay dos posibles causas de este problema. La primera es que los números no se muestran a sus valores completos. El segundo es un problema de diseño informático. Ninguno de los dos son quotbugsquot o problemas con el diseño de Microsoft Excel o Windows. Excel almacena los números de forma diferente que puede tener que mostrar en formato en la hoja de cálculo. En circunstancias normales, Excel almacena valores numéricos como quotDoble Precisión Floating Pointquot números, o quotDoublesquot para abreviar. Estas son variables de 8 bytes que pueden almacenar números precisos a aproximadamente 15 posiciones decimales. Puede tener sólo dos decimales se muestran en la hoja de cálculo, pero el valor subyacente tiene los 15 decimales completos. El segundo problema surge del hecho de que una computadora, cualquier computadora, no puede almacenar la mayoría de los números fraccionarios con total exactitud. Los ordenadores, en general, utilizan el estándar IEEE (Instituto de Ingenieros Eléctricos y Electrónicos) para números de coma flotante. Esta norma proporciona una forma de almacenar números fraccionarios en el espacio limitado de un número de 8 bytes. Por supuesto, para la mayoría de los números, alguna aproximación debe hacerse. En este artículo se describen y explican las causas de errores que se deben a cualquiera de las causas descritas anteriormente: el número con formato mostrado y los errores internos asociados con números de punto flotante. Valores reales y visualizados En circunstancias normales, Excel siempre almacena y manipula números como 8-byte quotDouble Precision Floating Pointquot números, o quotDoublesquot. Excels el almacenamiento interno del número no se ve afectado por la forma en que usted puede elegir para dar formato a un número para su visualización. Por ejemplo, si una celda contiene la fórmula 1/3. Excel siempre trata este valor como 0,3333133, independientemente del número de decimales que desee mostrar en la hoja de cálculo. Incluso si elige mostrar el valor como simple quot0.3quot, Excel aún conserva el número completo como el valor de la celda. Esto puede causar situaciones en las que puede parecer que Excel está cometiendo un error en el cálculo, cuando realmente no lo es. Por ejemplo, supongamos que tenemos la fórmula 1/3 en cada una de las tres celdas A1: A3. El formato de estas celdas para un punto decimal mostraría quot0.3quot en cada celda. La adición de estas tres células junto con la función SUM dará el resultado 1.0. Pero 0,3 0,3 0,3 es igual a 0,9 no 1,0, a la derecha El resultado parecería ser incorrecto. Por supuesto, no lo es. Independientemente de cómo tenga las celdas formateadas para su visualización, Excel utiliza el valor subyacente al realizar cálculos. En el ejemplo, no está agregando 0.3 0.3 0.3. Sino más bien 0.333333333333333 0.333333333333333 0.333333333333333. Cuya suma es (casi) 1,0. Excel ofrece una opción denominada quotPrecision As Displayedquot, que puede habilitar desde la pestaña Cálculo en el cuadro de diálogo Opciones (menú Herramientas). Habilitar esta opción fuerza a Excel a utilizar los valores mostrados en sus cálculos, en lugar de los números subyacentes. Con esta opción habilitada, el ejemplo anterior realmente SUM a 0.9. Debe tener mucho cuidado al usar esta opción, sin embargo. Una vez habilitada, toda la precisión se pierde y no se puede recuperar. Todas las celdas se calculan en función del valor visualizado. Esta opción se aplica a todo el libro, no a una celda o rango de celdas específico. Números de punto flotante Excel, como casi cualquier otro programa de computadora, utiliza el estándar IEEE para números de punto flotante de precisión doble. Esta norma se describe en detalle, en el nivel de bits, en una sección posterior de este artículo. Podemos generalizar, sin embargo, para describir cómo Excel almacena números fraccionarios. Así como las computadoras almacenan enteros como números binarios, almacenan números fraccionarios como fracciones binarias. Los ordenadores almacenan un valor entero (número entero) como (x1 x2 x4 x8 x16 etc) donde x es el estado del bit. Si el bit está activado, x1. Si el bit de off, x0. En esta notación, cualquier número entero se puede almacenar exactamente. Por ejemplo, el número 13 se almacena en binario como 1101 que indica, leyendo de izquierda a derecha, 18 14 02 11 13. Los números fraccionarios se almacenan de una manera similar. En el sistema binario, los números fraccionarios se almacenan como la suma de una serie de fracciones: (x1 / 2 x1 / 4 x1 / 8 x1 / 16 etc) donde x es el estado del bit. Si el bit está activado, x1. Si el bit de off, x0. A diferencia de enteros, sin embargo, no todos los valores fraccionarios se pueden almacenar exactamente exactamente. Por ejemplo, es imposible almacenar el número 1/10 0.1 en forma binaria. Una aproximación cercana es (01/2 01/4 01/8 11/16 11/32 etc). Los ordenadores llevan esta operación al equivalente de 15 decimales. Incluso con esta precisión, muchos números se representan como una aproximación de su valor quottruequot o quotanalyticquot. Por ejemplo, es imposible describir con precisión el número 1/10 en 8 bytes (o cualquier longitud) de la notación binaria. Los números de punto flotante pueden llegar muy cerca de representar ese número, pero siempre habrá algún error muy pequeño. Es importante señalar que estos errores y limitaciones en los números fraccionarios no son realmente errores en absoluto. Tampoco son bichos en los programas. Estas son limitaciones bien conocidas y bien documentadas de los sistemas aritméticos de punto flotante en casi todos los paquetes de software y dispositivos de hardware. Funciones de la hoja de trabajo para redondear Excel le proporciona varias funciones para manejar el redondeo. Estas funciones se enumeran a continuación. INT MROUND RONDA ROUNDDOWN ROUNDUP TRUNC NOTA: La función MROUND forma parte del complemento Analysis ToolPak para Excel. Debe tener instalado este paquete para poder utilizar estas funciones. Para instalar el ATP, vaya al menú Herramientas, seleccione Complementos. Y coloque una comprobación junto al elemento Analysis ToolPak. Consulte la ayuda en línea para obtener más información acerca de estas funciones. IEEE Floating Point Standard La sección describe el formato interno de las variables de punto flotante de doble precisión de 64 bits. El diseño de un doble es el siguiente: Punto flotante Thomas Finley, abril de 2000 Contenido e Introducción Este documento explica el estándar IEEE 754 de coma flotante. Explica la representación binaria de estos números, cómo convertir a decimal de punto flotante, cómo convertir de punto flotante a decimal, discute casos especiales en punto flotante y, finalmente, termina con algún código C para ampliar la comprensión de punto flotante. Este documento no cubre operaciones con números de coma flotante. Escribí este documento para que si sabes representar, puedes omitir la sección de representación, y si sabes convertir a decimal a partir de una sola precisión, puedes saltarse esa sección, y si sabes cómo convertir a precisión única desde Decimal, puede omitir esa sección. Representación Primero, sepa que los números binarios pueden tener, si usted perdona mi decir así, un punto decimal. Funciona más o menos de la misma manera que el punto decimal hace con números decimales. Por ejemplo, el decimal 22.589 es meramente 22 y 510 -1 810 -2 910 -3. Similarmente, el número binario 101.001 es simplemente 12 2 02 1 12 0 02 -1 02 -2 12 -3. O más bien simplemente 2 2 2 0 2 -3 (este número en particular resulta ser 9.125, si eso ayuda a su pensamiento). En segundo lugar, sabemos que los números binarios, como números decimales, pueden ser representados en notación científica. P. ej. El decimal 923.52 se puede representar como 9.2352 10 2. Similarmente, los números binarios se pueden expresar de esa manera también. Digamos que tenemos el número binario 101011.101 (que es 43.625). Esto se representará utilizando notación científica como 1,01011101 [2, 5]. Ahora que estoy seguro de que la comprensión es perfecta, finalmente puedo entrar en representación. La unidad de punto flotante de precisión simple es un paquete de 32 bits, dividido en tres secciones de un bit, ocho bits y veintitrés bits, en ese orden. Haré uso del número binario mencionado anteriormente 1.01011101 2 5 para ilustrar cómo se tomaría un número binario en notación científica y lo representaría en notación de punto flotante. Si convertimos simplemente de hexadecimal a binario, 0x64 es 0110 0100, que es el mismo resultado que el 011001 dado arriba. Este método es mucho más rápido. De todos modos Tomamos esos números que tenemos, y los representamos como .011001, colocándolos en el orden en que los adquirimos. Poner en secuencia con nuestra representación binaria de 329, obtenemos 101001001.011001. En nuestra notación científica binaria, esto es 1.01001001011001 2 8. Luego utilizamos lo que sabemos acerca de cómo se representan números de precisión sencillos para completar este proceso. El signo es positivo, por lo que el campo de signo es 0. El exponente es 8. 8 127 135, por lo que el campo del exponente es 10000111. La mantisa es meramente 01001001011001 (recuerde que el implícito 1 de la mantisa significa que no incluimos el líder 1) plus No obstante muchos 0s que tenemos que agregar al lado derecho para hacer que el número binario 23 pedazos largos. Dado que uno de los problemas de tarea consiste en representar esto como un hex, termino con un número hexadecimal. Luego lo dividimos en pedazos de cuatro bits (ya que cada dígito hexadecimal es el equivalente de 4 bits) y luego convertir cada cantidad de cuatro bits en el dígito hexadecimal correspondiente. Por lo tanto, en hexadecimal, este número es 0x43A4B200. Números especiales A veces la computadora siente la necesidad de presentar un resultado de un cálculo que refleja que se cometió algún error. Quizás la magnitud del resultado de un cálculo sea mayor o menor de lo que este formato parece ser capaz de soportar. Quizás intentaste dividir por cero. La respuesta es que hay casos especiales de números de coma flotante, específicamente cuando el campo del exponente es todo 1 bits (255) o todos los 0 bits (0). Números desnormalizados Si tiene un campo de exponentes que es todos los bits cero, esto es lo que se denomina un número desnormalizado. Con el campo del exponente igual a cero, se podría pensar que el exponente real sería -127, por lo que este número tomaría la forma de 1.MANTISSA 2 -127 como se describió anteriormente, pero no lo hace. En su lugar, es 0.MANTISSA 2 -126. Observe que el exponente ya no es el valor del campo del exponente menos 127. Es simplemente -126. Observe también que ya no incluimos un bit implícito para la mantisa. Como ejemplo, tome el número de coma flotante representado como 0x80280000. Primero, convierta esto en binario. Nuestro bit de signo es 1, por lo que este número es negativo. Nuestro exponente es 0, por lo que sabemos que este es un número desnormalizado. Nuestra mantisa es 0101, que refleja una mantisa real de 0,0101 recuerda que no incluimos lo que antes era un bit implícito para un exponente de cero. Por lo tanto, esto significa que tenemos un número -0.0101 2 2 -126 -0.3125 10 2 -126 -1.25 10 2 -128. Cero Usted puede pensar en cero como simplemente otro número desnormalizado. Zero is represented by an exponent of zero and a mantissa of zero. From our understanding of denormalized numbers, this translates into 02 -126 0. This sign bit can be either positive (0) or negative (1), leading to either a positive or negative zero. This doesnt make very much sense mathematically, but it is allowed. Infinity Just as the case of all zero bits in the exponent field is a special case, so is the case of all one bits. If the exponent field is all ones, and the mantissa is all zeros, then this number is an infinity. There can be either positive or negative infinities depending on the sign bit. For example, 0x7F800000 is positive infinity, and 0xFF800000 is negative infinity. NaN (Not a Number) These special quantities have an exponent field of 255 (all one bits) like infinity, but differ from the representation of infinity in that the mantissa contains some one bits. It doesnt matter where they are or how many of them there are, just so long as there are some. The sign bit appears to have no bearing on this. Examples of this special quantity include 0x7FFFFFFF, 0xFF81ABD0, 0x7FAA12F9, and soforth. Summary of Special Cases A summary of special cases is shown in the below table. It is more or less a copy of the table found on page 301 of the second edition of Computer Organization and Design, the Hardware Software Interface by Patterson and Hennessy, the textbook for Computer Science 104 in the Spring 2000 semester. Even though only single precision was covered in the above text, I include double precision for the sake of completeness. When, Where, and Where Not When you have operations like 0/0 or subtracting infinity from infinity (or some other ambiguous computation), you will get NaN. When you divide a number by zero, you will get an infinity. However, accounting for these special operations takes some extra effort on the part of the designer, and can lead to slower operations as more transistors are utilized in chip design. For this reason sometimes CPUs do not account for these operations, and instead generate an exception. For example, when I try to divide by zero or do operations with infinity, my computer generates exceptions and refuses to complete the operation (my computer has a G3 processor, or MPC750). Helper Software If youre interested in investigating further, I include two programs for which I provide the C code that you can run to gain a greater understanding of how floating point works, and also to check your work on various assignments. Hex 2 Float This program accepts as input a hexadecimal quantity and reads it as raw data into the variable theFloat. The program then outputs the hexadecimal representation of the data in theFloat (repeating the input), and prints alongside it the floating point quantity that it represents. I show here a sample run of the program. Notice the special case floating point quantities (0, infinity, and not a number). For the denormalized but nonzero numbers, this program will display zero even though the number is not really zero. If you want to get around this problem, replace the f in the formatting string of the printf function with e, which will deplay the number to great precision with scientific notation. I did not have it as e because I find scientific notation extremely annoying. Float 2 Hex This is a slight modification of the Hex 2 Float program. The exception is it reads in a floating point number. Just like and outputs the hexadecimal form plus the floating point number. Again I include a sample run of this program, confirming the results of the example problems I covered earlier in this text, along with some other simple cases. Notice the hexadecimal representation of 0.2. And thats the end of that chapter. Thomas Finley 2000
Comments
Post a Comment