¿Cómo corregir errores de redondeo en el microcontrolador?

2

Aquí están las especificaciones para la familia de chips / chips que nuestro proveedor está utilizando.

Para nuestro producto, les pedimos que realicen un cálculo multiplicando un número por un factor que tenga un punto decimal ... por ejemplo: 1.07, 0.93, etc.

Luego les estamos pidiendo que redondeen al entero más cercano.

Sin embargo, el número que calculan a veces tiene un error de redondeo. Ej: En mi calculador 56 * 2.36 = 132.16 ... redondeado a 132. Sin embargo, el microcontrolador devolverá una respuesta de 133 mostrada en una pantalla LCD de nuestro producto.

Mi pregunta es, ¿cómo se puede arreglar esto? Le he estado preguntando al vendedor muchas veces y parece que no pueden hacerlo bien.

¿Es realmente difícil calcular el número de punto flotante para los microcontroladores que no tienen esa función nativa? (Pregunta relacionada: DIY FP - Implementando matemáticas de punto flotante en un microcontrolador sin una FPU de hardware )

ACTUALIZACIÓN El rango para los resultados es de 1 a 780.

    
pregunta milesmeow

4 respuestas

8

No dices nada sobre el rango de tus números o la precisión requerida. Pero a menudo no necesita un punto flotante para esto, un punto fijo a menudo es suficiente. Simplemente trabaje con números enteros y coloque un punto decimal virtual en una posición determinada. Un número de 16 bits podría, por ejemplo, tener 8 bits a la izquierda del punto decimal y 8 bits después. Esto le dará un rango de 0 a 255 (supongo que no tengo números firmados), con una precisión mejor que 0.01.

El redondeo es simple: solo mire el decimal más significativo, el bit directamente a la derecha del punto decimal. Si eso es un cero, entonces la parte entera debe dejarse intacta. Si es uno, agrega 1 a la parte entera.

editar
Existen miles de formas de redondeo: redondear hacia arriba / abajo, redondear a la más cercana, redondear a cero, redondear a los banqueros, ... Asegúrese de que usted y el proveedor hablen el mismo idioma.

    
respondido por el stevenvh
3

Supongo que es solo una cuestión de precisión.

Supongamos que el factor 2.36 está representado por un número de punto fijo con solo 4 bits a la derecha del punto decimal (bits fraccionarios), obtienes:

56 * 2.36 in fixed point representation with only 4 fractional bits:
(56 * round(2.36 * 2^4)) / 2^4 = 
(56 * round(37.76)) / 16 =
(56 * 38) / 16 = 133

La solución sería simplemente usar más bits fraccionarios (quizás 8).

56 * 2.36 in fixed point representation with 8 fractional bits:
(56 * round(2.36 * 2^8)) / 2^8 = 
(56 * round(604.16)) / 2^8 =
(56 * 604) / 256 = 132

Pero aún así, es posible que algunos factores obtengan el mismo efecto, pero menos probable / frecuente.

Solo funciona siempre a la perfección si la representación de punto fijo del factor no pierde ningún bit al redondear.

Este es el caso si (y solo si):

  • la parte fraccionaria del factor es un múltiplo de 1/2 ^ n y
  • la representación de punto fijo del factor utiliza al menos n bits fraccionarios.
respondido por el Curd
3

Primero debe definir el redondeo entre usted y el proveedor, es posible que lo hayan hecho correctamente en función de su definición.

En segundo lugar, si solo está hablando de dos lugares decimales, no hay razón para usar un punto flotante, debería haberlo especificado sin punto flotante, y tal vez puede cambiarlo para que se defina para que no use el punto flotante. Micro de 8 bits o no, no es necesario. Puede hacer fácilmente matemáticas de 8 o 16 bits y ordenar todo el redondeo que desee con unos pocos decimales (un programador competente nunca necesita hardware de punto flotante porque siempre debería poder mantener el punto en su jefe, acreditado a John Von Neumann).

No importa si es un microcontrolador o una matriz, los formatos de punto flotante tienen problemas, al igual que los compiladores, al igual que los programadores. Al igual que 1 / 3rd y 2 / 3rds son un problema en un mundo decimal, 1 / 10th por ejemplo es un problema en programas de punto flotante basados en binarios. Si quiero agregar 2 / 3rds a 0.83 es que 0.667 + 0.83 = 1.49 ... o 0.67 + .83 = 1.50 uno redondearía el otro no, se podría argumentar que ambos son correctos. Sí, es cierto que aún tiene que definir su redondeo cuando usa un punto fijo (toma 200/3 y obtiene 66 (que representa 0.66) o usa redondeo y toma ((400/3) +1) / 2) y obtiene 67 ?) Su pregunta no es hacer divisiones, sino que se multiplica, usted todavía termina con los mismos tipos de problemas. Además, tenga en cuenta que el punto flotante en el hardware de un procesador no es algo para emocionarse, es mucho más difícil solucionar los errores que probablemente existen (el Pentium no fue el primero ni el último Fpu con problemas, su sistema operativo tiene que solucionarlos). o tal vez simplemente los dejen allí para que fracasen estos días). Un fpu suave es más lento pero mucho más fácil de arreglar después de que el chip está en producción.

2.36 es como 1 / 3rd es decimal, es una cosa de dígitos repetidos cuando se representa en flotador binario. este patrón de bits parece bastante temprano. 101110000101000111 (más fácil de ver en doble que en sencillo, una vez que se ve en doble, puede verlo en el sencillo). Sin embargo, no puedo hacer eso o una versión abreviada de eso causa suficiente error como para pasar a 133. Mirando la precisión simple, es decir, que no es el único formato de punto flotante ...

01000000000101110000101000111101 2.36
01000000000101110110110110110111 (132.5/56 = ~2.36607...)

el 110 se repite y se redondea en el backend. no es que esto esté relacionado de forma remota en este punto, sino solo por curiosidad, cámbielo a

01000000000101110110110110110110

veces 56 y obtienes 132.499 ...

La conclusión es que como se indica aquí cuando usa un lápiz y papel o una calculadora, multiplica 56 * 2.36 y obtiene 132.16 y eso se redondea a 133 para que quede claro que considera que esto es un fracaso / error que necesitan para solucionar. Quizás no importa cómo o por qué se les ocurrió la respuesta incorrecta, siempre y cuando la próxima versión del software dé la respuesta correcta. No sé qué tan difícil es hacer que este producto realice este cálculo matemático, pero debe probarlo para muchos valores diferentes para ver si siempre obtiene la respuesta esperada, o incluso mejor, si es posible, tenga la sección de código que extrae el cálculo. y validarlo de forma aislada contra una larga lista de operandos. O incluso especificarlo de esa manera, el software debe poder obtener el resultado esperado para esta lista de operandos y respuestas.

    
respondido por el old_timer
0

Una solución fácil es simplemente restar la mitad del resultado de tu microcontrolador.

De tu ejemplo:

56 * 2.36 = 132.16 se redondea a 133

entonces

(56 * 2.36): 0.5 redondeará a 132

    
respondido por el BullBoyShoes

Lea otras preguntas en las etiquetas