Me parece que desea compilar (a mano) lo que equivale a una máquina de estado donde cada estado maneja el enésimo dígito de entrada o los dígitos de exponente; esta máquina de estado tendría la forma de un árbol (¡sin bucles!). El objetivo es hacer aritmética de enteros siempre que sea posible, y (obviamente) recordar las variables de estado ("menos", "punto decimal en la posición 3") en los estados implícitamente, para evitar asignaciones, almacenamientos y posteriores recuperaciones/pruebas de tales valores . Implemente la máquina de estado con simples declaraciones "si" simples en los caracteres de entrada solamente (para que su árbol llegue a ser un conjunto de if anidados). Accesos en línea a los caracteres del buffer; no desea una llamada de función al getchar
para reducir la velocidad.
Los ceros a la izquierda pueden simplemente suprimirse; es posible que necesites un bucle aquí para manejar ridículamente largas secuencias cero iniciales. El primer dígito distinto de cero se puede recopilar sin poner a cero un acumulador o multiplicar por diez. Los primeros 4-9 dígitos distintos de cero (para enteros de 16 o 32 bits) se pueden recopilar con multiplicaciones enteras por valor constante de diez (convertido por la mayoría de los compiladores en unos pocos cambios y agrega). [En la parte superior: cero dígitos no requieren ningún trabajo hasta que se encuentre un dígito distinto de cero y luego se requiere una multiplicación de 10^N para N ceros secuenciales; puedes conectar todo esto en la máquina de estados]. Los dígitos que siguen a los primeros 4-9 se pueden recopilar utilizando multiplicaciones de 32 o 64 bits, dependiendo del tamaño de la palabra de su máquina. Como no le importa la precisión, simplemente puede ignorar los dígitos después de reunir el valor de 32 o 64 bits; Supongo que realmente puede detenerse cuando tiene un número fijo de dígitos distintos de cero basado en lo que su aplicación realmente hace con estos números. Un punto decimal encontrado en la cadena de dígitos simplemente causa una rama en el árbol de la máquina de estados. Esa rama conoce la ubicación implícita del punto y, por lo tanto, más adelante, cómo escalar de forma adecuada con una potencia de diez. Con esfuerzo, puede combinar algunos subárboles de máquina de estado si no le gusta el tamaño de este código.
[Arriba: conserve el entero y las partes fraccionarias como enteros separados (pequeños). Esto requerirá una operación de punto flotante adicional al final para combinar las partes de entero y de fracción, probablemente no valga la pena].
[Arriba: recopile 2 caracteres para pares de dígitos en un valor de 16 bits, busque el valor de 16 bits. Esto evita una multiplicación en los registros en el comercio por un acceso a la memoria, probablemente no sea una ganancia en las máquinas modernas].
Al encontrar "E", recoge el exponente como un entero como el anterior; buscar con precisión los poderes precalculados/escalados de diez en una tabla de multiplicador precalculado (recíprocos si el signo "-" está presente en el exponente) y multiplicar la mantisa recopilada. (nunca hagas una división flotante). Dado que cada rutina de recolección de exponente está en una rama (árbol) diferente del árbol, tiene que ajustarse para la ubicación aparente o real del punto decimal al compensar el índice de potencia de diez.
[Arriba: puede evitar el costo de ptr++
si sabe que los caracteres del número se almacenan linealmente en un búfer y no cruzan el límite del búfer. En el estado kth a lo largo de una rama de árbol, puede acceder al carácter kth como *(start+k)
. Un buen compilador generalmente puede ocultar el "... + k" en un desplazamiento indexado en el modo de direccionamiento.]
Hecho a la derecha, este esquema hace aproximadamente un multiplicador barato por dígito distinto de cero, uno fundido a flotador de la mantisa, y una multiplicación flotante para escalar el resultado por exponente y ubicación del punto decimal.
No he implementado lo anterior. Implementé versiones con bucles, son bastante rápidos.
¿Comprueba los cambios locales en 'isdigit'? Tal vez deberían echar un vistazo al estándar ISO C. 'isdigit' no tiene comportamiento dependiente de la configuración regional; debe verificar si el personaje es un elemento del conjunto '0' a' 9', y eso es todo. – Kaz
¿Puede darnos una idea del problema del dominio? Supongo que no es financiero, o estarías usando aritmética de punto fijo. ¿Es para un sistema de control, como el posicionamiento? ¿Tiene requisitos (en tiempo real o blandos) en tiempo real? –
Si puede modificar el formato del mensaje, obviamente, el envío de flotantes binarios (o una codificación de texto más simple del binario) ahorraría costoso análisis en el otro extremo. p.ej. volcar el flotador como un entero hexadecimal, si el binario no está bien, pero eso es. –