Solución:
La solución obvia es no convertir los datos a ASCII pero almacenarlos en formato binario. De esa forma, todo lo que debe preocuparse es el carácter final de los datos. Si el sistema que realiza el análisis posterior es mucho más poderoso que su objetivo incrustado, entonces tendría sentido dejar que se ocupe de la conversión y el orden de bytes.
Por otro lado, es posible que el tiempo de ejecución del / y% sea insignificante en comparación con el tiempo necesario para transferir los datos a la tarjeta SD; así que asegúrese de optimizar lo correcto.
Ciertamente, hay una forma mucho más rápida: tener una matriz de 1024 cadenas precalculadas. Luego, puede simplemente verificar los límites, seguido de un índice en la matriz.
Sin embargo, a partir de su pregunta no está claro si su código se está ejecutando en el microcontrolador. Si ese es el caso, es posible que no tenga suficiente memoria para este enfoque.
Estoy de acuerdo con lo que dijo Clifford, que no debe preocuparse por optimizarlo si no es necesario, y que puede enviar la limpieza del registro a su plataforma de análisis, en lugar de preocuparse por el formateo en una aplicación incrustada.
Dicho esto, aquí hay un artículo que podría serle útil. Utiliza un bucle, turnos, adiciones y ramificaciones, con complejidad lineal / constante: http://www.johnloomis.org/ece314/notes/devices/binary_to_BCD/bin_to_bcd.html
Además, pensé que sería divertido hacer un código que no realice divisiones, multiplicaciones o ramificaciones, pero que aún dé la respuesta correcta[0-1024)NoprometequeestoseamásrápidoqueotrasopcionesEstetipodecódigoessolounaopciónparaexplorar[0-1024)NopromisesthatthisisanyfasterthanotheroptionsThissortofcodeisjustanoptiontoexplore
Me encantaría ver si alguien puede proporcionar algunos trucos para hacer que el código sea más pequeño, requerir menos memoria o requerir menos operaciones, mientras se mantiene el resto de los recuentos iguales o se reducen 🙂
Estadísticas:
- 224 bytes en constantes (ni idea del tamaño del código)
- 5 derechos de desplazamiento de bits
- 3 restas
- 5 bit a bit
- 4 bit a bit
- 1 comparación mayor que
Perf:
Usando las comparaciones de rendimiento y las rutinas de itoa en la respuesta de Jonathan Leffler, estas son las estadísticas que obtuve:
- División 2.15
- Resta 4.87
- Mi solución 1.56
- Búsqueda de fuerza bruta 0.36
Aumenté el recuento de iteraciones a 200000 para asegurarme de no tener ningún problema con la resolución de tiempo y tuve que agregar volatile
a las firmas de funciones para que el compilador no optimice el ciclo. Utilicé VS2010 express con la configuración de “lanzamiento” de vainilla, en una máquina Windows 7 de 64 bits y 3 GHz de doble núcleo (aunque compilada a 32 bits).
El código:
#include "stdlib.h"
#include "stdio.h"
#include "assert.h"
void itoa_ten_bits(int n, char s[])
{
static const short thousands_digit_subtract_map[2] =
{
0, 1000,
};
static const char hundreds_digit_map[128] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
0, 0, 0,
};
static const short hundreds_digit_subtract_map[10] =
{
0, 100, 200, 300, 400, 500, 600, 700, 800, 900,
};
static const char tens_digit_map[12] =
{
0, 1, 2, 3, 3, 4, 5, 6, 7, 7, 8, 9,
};
static const char ones_digit_map[44] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
0, 1, 2, 3
};
/* Compiler should optimize out appX constants, % operations, and + operations */
/* If not, use this:
static const char ones_digit_append_map[16] =
{
0, 6, 2, 8, 4, 10, 6, 12, 8, 14, 10, 16, 12, 18, 14, 20,
};
*/
static const char a1 = 0x10 % 10, a2 = 0x20 % 10, a3 = 0x40 % 10, a4 = 0x80 % 10;
static const char ones_digit_append_map[16] =
{
0, a1, a2, a1 + a2,
a3, a1 + a3, a2 + a3, a1 + a2 + a3,
a4, a1 + a4, a2 + a4, a1 + a2 + a4,
a3 + a4, a1 + a3 + a4, a2 + a3 + a4, a1 + a2 + a3 + a4,
};
char thousands_digit, hundreds_digit, tens_digit, ones_digit;
assert(n >= 0 && n < 1024 && "n must be between [0, 1024)");
/* n &= 0x3ff; can use this instead of the assert */
thousands_digit = (n >> 3 & 0x7f) > 0x7c;
n -= thousands_digit_subtract_map[thousands_digit];
ones_digit = ones_digit_map[
(n & 0xf)
+ ones_digit_append_map[n >> 4 & 0xf]
+ ones_digit_append_map[n >> 8 & 0x3]
];
n -= ones_digit;
hundreds_digit = hundreds_digit_map[n >> 3 & 0x7f];
n -= hundreds_digit_subtract_map[hundreds_digit];
tens_digit = tens_digit_map[n >> 3];
s[0] = '0' | thousands_digit;
s[1] = '0' | hundreds_digit;
s[2] = '0' | tens_digit;
s[3] = '0' | ones_digit;
s[4] = ' ';
}
int main(int argc, char* argv)
{
int i;
for(i = 0; i < 1024; ++i)
{
char blah[5];
itoa_ten_bits(i, blah);
if(atoi(blah) != i)
printf("failed %d %sn", i, blah);
}
}