2009-03-01 15 views
6

Digamos que tengo un flotador en el rango de [0, 1] y quiero cuantizarlo y almacenarlo en un byte sin signo. Suena como una obviedad, pero en realidad es bastante complicado:Conversión/cuantificación del rango de flotación al rango entero

La solución obvia es el siguiente:

unsigned char QuantizeFloat(float a) 
{ 
    return (unsigned char)(a * 255.0f); 
} 

Esto funciona en la medida en que consigo todos los números del 0 al 255, pero la distribución de los enteros no es par. La función solo devuelve 255 si a es exactamente 1.0f. No es una buena solución.

Si hago redondeo adecuado acabo de desplazar el problema:

unsigned char QuantizeFloat(float a) 
{ 
    return (unsigned char)(a * 255.0f + 0.5f); 
} 

Aquí el resultado 0 sólo cubre la mitad del flotador alcance que cualquier otro número.

¿Cómo hago una cuantificación con igual distribución del rango de coma flotante? Idealmente, me gustaría obtener una distribución equitativa de enteros si cuantifico flotantes aleatorios distribuidos por igual.

¿Alguna idea?


Btw: También mi código está en C, el problema está en el idioma. Para las personas que no son C: simplemente asuma que la conversión float a int trunca el flotador.

EDIT: Ya que tenía cierta confusión aquí: necesito un mapeo que mapea el flotador de entrada más pequeño (0) a la unsigned char más pequeño y el más alto del flotador de mi alcance (1.0f) al byte sin signo más alto (255)

Respuesta

10

¿Qué tal a * 256f con un cheque para reducir de 256 a 255? Así que algo como:

return (unsigned char) (min(255, (int) (a * 256f))); 

(Para una función min adecuada en su plataforma - no puedo recordar la función C para ello.)

Básicamente se quiere dividir el rango en 256 partes iguales, las cuales es lo que debería hacer. El caso límite para 1.0 ir a 256 y requerir redondeo es solo porque el dominio es inclusivo en ambos extremos.

+0

wow - Sí, eso es todo! –

+0

Sí - (carácter sin signo) (a * 256.0f) le proporciona exactamente lo que desea para cada valor de entrada, excepto para 1.0.C no tiene una función mínima incorporada, por lo que tendrá que escribir la suya propia si aún no lo hizo. –

+0

John, se me ocurrió el mismo resultado, simplemente no fue capaz de transferirlo correctamente desde la hoja de cálculo de Excel. Borré mi respuesta embarazosa. – cdonner

1

Creo que lo que busca es la siguiente:

unsigned char QuantizeFloat (float a) 
{ 
    return (unsigned char) (a * 256.0f); 
} 

Esto asignar valores flotantes uniforme en [0, 1] para valores de bytes uniforme en [0, 255]. Todos los valores en [i/256, (i + 1)/256 [(es decir, excluyendo (i + 1)/256), para i en 0..255, se asignan a i. Lo que podría ser indeseable es que 1.0f está mapeado a 256.0f que se ajusta a 0.

0

Se puede propagar el único error a lo largo de todo el rango manteniendo una distribución igual a la del segundo el 31 de diciembre .

limit = 4 
maxi = limit - 1 

n = 16 
for i in range(n): 
    x = i/(n - 1) 

    a = x * maxi # Wrong distribution 
    b = x * limit # One off 
    c = x * (limit - 1/limit) 

    print(f"{x:.3f} | {a:.3f} | {b:.3f} | {c:.3f}") 

-

0.000 | 0.000 | 0.000 | 0.000 
0.067 | 0.200 | 0.267 | 0.250 
0.133 | 0.400 | 0.533 | 0.500 
0.200 | 0.600 | 0.800 | 0.750 
0.267 | 0.800 | 1.067 | 1.000 
0.333 | 1.000 | 1.333 | 1.250 
0.400 | 1.200 | 1.600 | 1.500 
0.467 | 1.400 | 1.867 | 1.750 
0.533 | 1.600 | 2.133 | 2.000 
0.600 | 1.800 | 2.400 | 2.250 
0.667 | 2.000 | 2.667 | 2.500 
0.733 | 2.200 | 2.933 | 2.750 
0.800 | 2.400 | 3.200 | 3.000 
0.867 | 2.600 | 3.467 | 3.250 
0.933 | 2.800 | 3.733 | 3.500 
1.000 | 3.000 | 4.000 | 3.750 
Cuestiones relacionadas