2009-10-11 16 views
12

Tengo celdas cuyo valor numérico puede ser cualquiera entre 0 y Integer.MAX_VALUE. Me gustaría colorear el código de estas celdas de manera correspondiente.Los números de escala son <= 255?

Si el valor = 0, entonces r = 0. Si el valor es Integer.MAX_VALUE, entonces r = 255. ¿Pero qué pasa con los valores intermedios?

Estoy pensando que necesito una función cuyo límite como x =>Integer.MAX_VALUE es 255. ¿Qué es esta función? ¿O hay una mejor manera de hacer esto?

Podría simplemente hacer (value/(Integer.MAX_VALUE/255)) pero eso causará que muchos valores bajos sean cero. Entonces quizás debería hacerlo con una función de registro.

La mayoría de mis valores estarán en el rango [0, 10,000]. Entonces quiero resaltar las diferencias allí.

+4

No estoy seguro de por qué la votación para cerrar. Me parece una pregunta real (y buena). –

+4

¿Cómo se puede etiquetar java ** y ** language-agnostic? –

+0

Creo que puede etiquetarlo como ambos porque puede haber una solución general (mejor) y una específica de java (mejor) – warren

Respuesta

5

que pensé un ajuste de registro sería bueno para esto, pero viendo los resultados, no estoy tan seguro.

Sin embargo, Wolfram|Alpha es ideal para experimenting with this sort of thing:

empecé con eso, y terminó con:

r(x) = floor(((11.5553 * log(14.4266 * (x + 1.0))) - 30.8419)/0.9687) 

Curiosamente, resulta que esto da resultados casi idénticos a la respuesta de la Artelius:

r(x) = floor(255 * log(x + 1)/log(2^31 + 1) 

En mi humilde opinión, lo mejor sería servir con una función dividida para 0-10000 y 10000-2^31.

+0

Siguiendo mi simplificación algebraica a continuación, creo que esto podría servirle bien: 'r (x) = piso ((256./31) * log (x)/log (2))' – PaulMcG

+0

Sí, eso es ciertamente más simple, aunque todavía adolece del problema de una mala adaptación en comparación con los valores deseados. –

-1

Podría hacer (valor/(Integer.MAX_VALUE/255)) pero eso provocará que muchos valores bajos sean cero.

Un enfoque que podría tomar es usar el operador de módulo (r = value%256;). Aunque esto no garantizaría que Integer.MAX_VALUE resulte 255, , garantizaría un número entre 0 y 255. También permitiría distribuir números bajos en el rango de 0-255.

EDIT:

Curiosamente, como probar esto, Integer.MAX_VALUE % 256 resulta en 255 (en principio había probado erróneamente contra %255, que produjo los resultados erróneos). Esto parece una solución bastante directa.

+0

No está explícitamente indicado, pero parece estar implícito en la pregunta de que los colores deben agrupar valores similares, es decir, si dos celdas comparten un color, su valor será aproximadamente equivalente. En su respuesta, el color no tiene relación con la magnitud del valor. –

+0

¿Qué? Esto ni siquiera es una remota idea buena. – rlbond

+0

Kirk, estoy de acuerdo con que la idea de la distribución en grupos de valores similares era * una * idea. También parece que el OP estaba abierto a otras soluciones. Sin embargo, parece que la mayoría de los contestadores han tomado la agrupación de valores similares como la única solución. – akf

1

El valor que está buscando es: r = 255 * (value/Integer.MAX_VALUE). Así que tendrías que convertir esto en un doble, luego volver a un int.

+1

-1. Totalmente equivocado, lo siento. – Artelius

+0

Ugh, tienes razón, escribí eso demasiado rápido. Podrías haber especificado la corrección, pero tomé tu pista sutil y corrí con ella. –

+0

estúpido SO. No puedo revertir el voto negativo ahora. – Artelius

2

en general (ya que no me queda claro si esto es una pregunta Java o independiente del idioma) hay que dividir el valor que tiene por Integer.MAX_VALUE, multiplicar por 255 y convertir en un entero.

+0

La única manera de hacerlo es lanzar a un doble en un punto, es más eficiente hacerlo al revés. – Erich

+0

@Erich, pero luego se desbordará la oportunidad. – strager

+0

¡No se desbordará si divide primero! – Erich

2

Esto funciona! r= value /8421504;

8421504 es en realidad el número 'mágico', que equivale a MAX_VALUE/255. Por lo tanto, MAX_VALUE/8421504 = 255 (y algunos cambios, pero un número suficiente de enteros matemáticos se desharán de él.

si quiere uno que no tenga números mágicos, esto debería funcionar (y de igual rendimiento, ya que cualquier buen compilador lo reemplazará con el valor real:

r= value/ (Integer.MAX_VALUE/255);

la parte buena es que esto no requerirá ningún valores de punto flotante

+0

Distribución no exactamente igual, pero lo suficientemente buena. – strager

+0

¿Cómo es eso? Los valores de 0-Int.Max se distribuirán de manera uniforme a través de 0-255, ¿no? – Erich

16

la escala lineal "más justo" se hace realmente similares. esto:

floor(256 * value/(Integer.MAX_VALUE + 1)) 

Tenga en cuenta que esto es solo un pseudocódigo y supone cálculos de coma flotante.

Si suponemos que Entero.MAX_VALUE + 1 es 2^31, y que/nos dará la división entera, entonces se simplifica a

value/8388608 

qué otras respuestas son incorrectas

Algunas respuestas (al igual que la pregunta misma) suggsted una variación de (255 * value/Integer.MAX_VALUE). Es de suponer que esto tiene que convertirse en un entero, ya sea usando round() o floor().

Si usa floor(), el único value que produce 255 es Integer.MAX_VALUE. Esta distribución es desigual.

Si usa round(), 0 y 255 recibirán cada uno la mitad de veces que 1-254. También desigual.

Utilizando el método de escala que mencioné anteriormente, no ocurre tal problema.

métodos

no lineales

Si desea utilizar los registros, intente esto:

255 * log(value + 1)/log(Integer.MAX_VALUE + 1) 

También puedes, simplemente sacar la raíz cuadrada del valor (esto no iría todo el camino a 255, pero podría ampliarlo si quisiera).

+0

esto funciona mejor cuando es 'log (Integer.MAX_VALUE)' en lugar de 'log (Integer.MAX_VALUE + 1)'. De lo contrario, cada resultado es 0 porque 'log (Integer.MAX_VALUE)' es 'NaN'. –

+2

Tal vez los críticos ahora pueden ver cómo es independiente del lenguaje, a pesar de que el codificador está trabajando en EL IDIOMA VERDADERO –

+0

@Rosarch: Buen punto. Podría haber probado mi código antes de publicarlo, pero ¿por qué iba a romper mi promesa de nunca utilizar Java sobre algo tan trivial? ;) Aún así, como programador en C, debería haber sabido mejor ... – Artelius

0

La mejor respuesta depende realmente del comportamiento que desee.

Si desea que cada celda tenga generalmente un color diferente al vecino, vaya con lo que akf dijo en el segundo párrafo y use un módulo (x% 256).

Si desea que el color influya en el valor real (como "azul significa valores más pequeños" hasta "rojo significa valores enormes"), debería publicar algo acerca de la distribución esperada de los valores. Como te preocupa que muchos valores bajos sean cero, podría adivinar que tienes muchos, pero eso solo sería una suposición.

En este segundo escenario, realmente desea distribuir sus respuestas probables en 256 "percentiles" y asignar un color a cada uno (donde un número igual de respuestas posibles caen en cada percentil).

3

Para un mapeo lineal del rango 0-2^32 a 0-255, solo tome el byte de orden superior. Aquí es cómo se vería utilizando binario & y desplazamiento de bit:

r = value & 0xff000000 >> 24 

Las MOD 256 Volveremos, sin duda un valor 0-255, pero usted no será capaz de dibujar cualquier sentido de agrupación de los resultados - 1, 257 , 513, 1025 se correlacionarán con el valor 1 a escala, aunque estén lejos el uno del otro.

Si quieres ser más discriminar entre valores bajos, y combinar los valores muchos más grandes juntos, entonces una expresión de registro funcionará:

r = log(value)/log(pow(2,32))*256 

EDITAR: ¡Ay, mi profesor de álgebra de la escuela de la señora ¡Buckenmeyer se desmayaría! log(pow(2,32)) es lo mismo que 32*log(2), y mucho más barato de evaluar.Y ahora también podemos factor esto mejor, ya que es un buen 256/32 incluso 8:

r = 8 * log(value)/log(2) 

log(value)/log(2) es en realidad log-base-2 of value, que ingrese hace por nosotros muy claramente:

r = 8 * log(value,2) 

Allí, la señora Buckenmeyer: ¡tus esfuerzos no fueron del todo desperdiciados!

+0

Ooops, lo siento, me metí en Python allí. java.math.log no toma una segunda arg, por lo que está atascado con log (value)/log (2). – PaulMcG

0

Si se queja de que los números bajos se están volviendo cero, puede que desee normalizar los valores en 255 en lugar de en el rango completo de los valores.

La fórmula se convertiría en:

CurrentValue (valor máximo del conjunto)/

1

Tenga en cuenta que si quieres más y más brillante, que la luminosidad no es lineal por lo que un mapeo directamente de valor a color no se da un buen resultado.

La clase Color tiene un método para obtener un color más brillante. Echa un vistazo a eso.

1

La implementación lineal se analiza en la mayoría de estas respuestas, y la respuesta de Artelius parece ser la mejor. Pero la mejor fórmula dependerá de lo que esté tratando de lograr y la distribución de sus valores. Sin saber que es difícil dar una respuesta ideal.

Pero sólo para ilustrar, cualquiera de ellos podría ser el mejor para usted:

  • distribución lineal, cada asignación en un rango que es 1/266a de la gama general.
  • distribución logarítmica (sesgada hacia los valores bajos) que pondrá de relieve las diferencias en las magnitudes inferiores y disminuir las diferencias en las magnitudes más altas
  • distribución logarítmica inversa (sesgada hacia los valores altos) que pondrá de relieve las diferencias en las magnitudes más altas y disminuir las diferencias en las magnitudes inferiores
  • Distribución normal de incidencia de colores, donde cada color aparece la misma cantidad de veces que cualquier otro color.

De nuevo, debe determinar para qué se intentará lograr los resultados & para los que se utilizarán los datos. Si se le ha encomendado la tarea de construir esto, le recomiendo encarecidamente que aclare esto para asegurarse de que sea lo más útil posible y para evitar tener que volver a desarrollarlo más adelante.

1

Hazte la pregunta: "¿Qué valor debe asignarse a 128?" Si la respuesta es alrededor de mil millones (dudo que lo sea), utilice lineal. Si la respuesta está en el rango de 10-100 mil, considere la raíz cuadrada o el registro.

Otra respuesta sugirió esto (no puedo comentar ni votar todavía). Estoy de acuerdo.

r = log (valor)/log (pow (2,32)) * 256

Cuestiones relacionadas