Loading [MathJax]/extensions/TeX/mathchoice.js

5 votos

Aproximación de un decimal con una fracción (punto fijo de 32 bits a dos números de 23 bits). Piensa en binario, facilidad de cálculo.

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=24814396232415727195435=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.

3voto

AlgorithmsX Puntos 101

Encontrar aproximaciones racionales a un número es un campo conocido como Aproximación diofantina . En tu caso, estás tratando de encontrar la aproximación más exacta dentro de unos límites en los valores del numerador y el denominador. Resulta que puedes encontrar la mejor aproximación racional a un número utilizando su Fracción continua representación.

Algoritmo

  1. Toma la parte entera del número y escríbela.
  2. Dividir 1 por la parte fraccionaria del número.
  3. Repita los pasos 1 y 2 hasta alcanzar la precisión necesaria.

Voy a dar un ejemplo rápido de cómo encontrar la fracción continua para π .

π=3+0.14159...=3+17+0.06251...=3+17+115+0.99659π3+17+115+11355113

355113 es la mejor aproximación racional de π con un denominador inferior a 113 . Es preciso hasta quince dígitos. Generalmente, el error entre la aproximación y el número es |npq|<1q2

Esto significa que siempre que se pueda obtener un denominador mayor que 216=65536 se garantiza la obtención de un resultado dentro de los límites indicados anteriormente.

Notas

Las fracciones continuas se escriben a menudo con la notación π[3;7,15,1]=3+17+115+11 donde la parte entera es el primer número y todos los demás números van en el denominador.

En su ejemplo concreto de 0.005777551792562008 la fracción continua de su aproximación es como Your Approximation

mientras que la aproximación de la fracción continua es como

Continued Fraction Approximation

Fíjate en lo similares que son las dos fracciones continuas, ya que los cinco primeros términos son idénticos. Sin embargo, la aproximación de la fracción continuada dentro del rango que has utilizado es todavía más precisa, teniendo tu aproximación un error mayor que el de la fracción continuada por 2.2478231010 .

0 votos

El último párrafo es técnicamente inexacto. Por ejemplo, (291355+333)/(291113+106)=103638/32989 es una aproximación mucho mejor a π que 355113 en términos de error absoluto (sólo 1.5×109 ). Mi vago recuerdo es que el sentido en el que las fracciones continuas son mejores es al observar |pqπ| en lugar de |pqπ| y eso es probablemente en lo que estabas pensando.

2voto

Erick Wong Puntos 12209

Ejemplo elaborado con fracciones continuas :

La fracción 24814396/232 se simplifica a 6203599/1073741824 cuya fracción continua se calcula como sigue:

1073741824=1736203599+5191976203599=11519197+492432519197=1492432+26765492432=1826765+1066226765=210662+544110662=15441+52215441=15221+2205221=23220+161220=1161+59161=259+4359=143+1643=216+1116=111+511=25+15=51.

Así que la fracción continua (finita) en este caso es [0;173,11,1,18,2,1,1,23,1,2,1,2,1,2,5] .

Calculando los convergentes de esta fracción continua (hay una recursión muy sencilla para este cálculo) se obtiene la secuencia de aproximaciones

173: 1/173 = 0.005780346820809248
 11: 11/1904 = 0.005777310924369748
  1: 12/2077 = 0.005777563793933558
 18: 227/39290 = 0.005777551539832018
  2: 466/80657 = 0.005777551855387629
  1: 693/119947 = 0.00577755175202381
  1: 1159/200604 = 0.005777551793583378
 23: 27350/4733839 = 0.005777551792530334
  1: 28509/4934443 = 0.005777551792573143
  2: 84368/14602725 = 0.005777551792559265
  1: 112877/19537168 = 0.00577755179256277
  2: 310122/53677061 = 0.005777551792561817
  1: 422999/73214229 = 0.005777551792562071
  2: 1156120/200105519 = 0.005777551792562004
  5: 6203599/1073741824 = 0.005777551792562008

Podemos ver que el denominador 4934443 es lo suficientemente pequeño para un entero de 23 bits, pero 14602725 es demasiado grande. Así que una respuesta sería cortarlo en 28509/4934443 por un error de 1.113e-14 . Esto es probablemente óptimo porque 4934443 está bastante cerca del límite superior, pero si el límite fuera sólo un poco más alto podríamos bajar el coeficiente 2 en la siguiente fila para 1 y obtener 55859/9668282 que tiene un error ligeramente mejor que 1e-14 .

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X