Tengo un número decimal de 32 bits de ancho fijo entre 0 y 1,0 (en realidad se garantiza que está entre 0,001 y 0,02, por lo que la pérdida de rango es aceptable en la aproximación). La representación binaria se define como que el bit más significativo representa 1/2, el bit siguiente 1/4, y así sucesivamente hasta los 32 bits.
Debo representar este número como un cociente de dos números de 23 bits (en realidad, uno de ellos es de 23 y otro de 18 bits, pero simplifiquemos por el bien de la discusión). No importa cuáles sean los dos números mientras cada uno de ellos quepa en 23 bits.
Otra forma de pensar en este problema es que tengo una fracción con un numerador de 32 bits y un denominador constante conocido de 2^32. Debo aproximar esta fracción como otra fracción con numerador de 23 bits y denominador de 23 bits, de manera que un error de no más de 1/(2^32) sea aceptable.
¿Existe algún algoritmo razonablemente eficiente que me permita hacer esto sin tener que adivinar y comprobar por la fuerza bruta? Lo ideal sería algún tipo de truco de "manipulación de bits", ya que esto debe hacerse en un microcontrolador bastante pequeño. Si no es así, lo siguiente mejor sería la aritmética de enteros.
Entiendo que como estoy reempaquetando 32 bits de información en un total de 46 bits de información, teóricamente es posible. Una solución de fuerza bruta de adivinar y comprobar hasta que algún par de números funcione es bastante trivial. Lo que estoy buscando es algún algoritmo más eficiente o al menos una forma de averiguar un buen punto de partida para adivinar y comprobar. Lo ideal sería que hubiera un límite de tiempo definido para la ejecución de este algoritmo.
Por ejemplo, mi entrada (A) es 0,005777551792562008. Si tomamos la representación binaria de esto
0b 0000 0001 0111 1010 1010 0011 0011 1100
se puede reinterpretar como el entero sin signo de 32 bits 24.814.396.
Este número puede representarse como la relación (N/D) 0.005777551792562008=24814396232≈415727195435=0.005777552017355449 .
En este caso, el error de la aproximación es de 2,248e-10 que es menor que 1/(2^32)=2,328e-10 .
La situación descrita en esta pregunta es bastante específica porque se basa en un escenario del mundo real. Sin embargo, siéntase libre de generalizar, incluso si su generalización hace que la respuesta no se ajuste a la situación específica que describo.
El objetivo de esta pregunta es obtener algunas ideas sobre por dónde empezar y, con suerte, dejar algo que sea aplicable en más situaciones. Calcular una aproximación fraccionaria "suficientemente cercana" a un decimal es un problema bastante general, pero que no he visto que se haya abordado específicamente en el contexto de los ordenadores y la representación binaria.
0 votos
¿Cómo se enfrentaría a 1232 como la fracción de dos números de veinte bits? ¿Podrías dar algunos ejemplos de fracciones de trabajo y sus correspondientes números binarios?
0 votos
@AlgorithmsX Buena observación. La respuesta es que puede que haya simplificado demasiado el problema en la pregunta porque aún estoy en proceso de comprenderlo. En realidad, no tendré que lidiar con valores tan pequeños porque la relación debe estar entre 0,001 y 0,02 (decimal). Por lo tanto, una pérdida significativa de rango es aceptable. En realidad, incluso es aceptable cierta pérdida de precisión, pero hay que minimizarla. Si se me ocurre una forma mejor de formular la pregunta, lo haré en algún momento, pero ahora mismo me resulta difícil describir la situación sin enredarme en demasiados detalles
1 votos
Algunos antecedentes: Estoy intentando convertir la salida de una versión más reciente de un sensor a un formato que emule la salida de una versión más antigua del mismo sensor. El fenómeno físico no ha cambiado, pero sí la representación.
0 votos
Cambiado de 20 a 23 bits para ambas partes de la aproximación para que funcione el ejemplo (que está tomado de un punto de datos real).
0 votos
Aunque no es específico de la representación binaria, sería inusual hablar de aproximación racional sin mencionar las fracciones continuas. Dado que se parte de un valor racional, la fracción continua puede calcularse con aritmética de números enteros (básicamente el mismo algoritmo euclídeo para gcd) y luego truncarse en el punto en que el numerador sea demasiado grande. Probablemente se pueda refinar la precisión del truncamiento, supongo que se podría umbralizar el último valor de forma inteligente en lugar de eliminarlo por completo.