2009-10-01 30 views
7

No estoy seguro si esa es la manera correcta de preguntar esto o no, pero este es el problema.¿Cómo redondear un decimal a la fracción más cercana?

Dada la latitud de 26.746346081599476, ¿cómo puedo saber si el número 26.75 es el 16º mayor que el número y 26.6875 el 16º menor que el número?

26.0 
26.0625 
26.125 
26.1875 
26.25 
26.3125 
26.375 
26.4375 
26.5 
26.5625 
26.625 
26.6875 
My Number: 26.746346081599476 
26.75 
26.8125 
26.875 
26.9375 
27.0 

Estoy usando JavaScript, así que una respuesta sería útil pero no necesaria. Podría forzarlo brutalmente, pero estoy buscando la forma elegante de hacerlo.

La imagen más grande es que quiero crear mosaicos estándar para una aplicación de mapeo en la que estoy trabajando. Estamos usando mapas de Bing y estoy cargando datos según demanda, cada vez que el usuario abre o acerca el mapa. Sería bueno aprovechar el almacenamiento en memoria caché del lado del servidor para estas solicitudes, así que si normalizo las consultas enviadas al servidor, obtendría algunos éxitos de caché. Si no estandarizo las solicitudes al servidor, es muy poco probable que el mismo usuario vea la ubicación exacta al mismo tiempo.

lo que hay una mayor probabilidad de contraer caché impacta contra: /path/data.json?tl=26.6875,-80.6875 & br = 26.75, -80.75 que con: /path/data.json?tl = 26.74946187679896, -80.10930061340332 & br = 26.743234270702878, -80.09607195854187

Las respuestas externas son bienvenidas también.

Respuesta

14

Para hallar los múltiplos más cercanos de 1/n:

lower_bound = 1.0/n * Math.floor(n * your_number); 
upper_bound = 1.0/n * Math.ceil(n * your_number); 

es posible que desee utilizar algún tratamiento especial si su número ya es un múltiplo de 1/16.

// alternate solution so that lower_bound <= your_number < upper_bound 
lower_bound = 1.0/n * Math.floor(n * your_number); 
upper_bound = 1.0/n * Math.floor(n * your_number + 1.0); 
+0

se me adelantó.Casi lo tengo trabajando en PowerShell y siempre tropecé con la idea de que incluso :) :) – Joey

+0

@mobrule: ¿Puedes decirme por qué tu camino es mejor que el de Guffa? Me gusta que el suyo sea un poco menos codificado, pero me interesa saber cómo me podría ayudar el manejo especial aquí. – sheats

+0

Dependiendo de lo que haga con los límites, es posible que no desee dejar 'low_bound == upper_bound'. Por ejemplo, puede realizar una transformación lineal del cuadro que dibujó alrededor de una coordenada, y puede tener una expresión con '(upper_bound - lower_bound)' en un denominador en alguna parte. – mob

9

se multiplica el valor por 16, utilice el suelo o método ceil, y se divide por 16:

var higher = Math.ceil(number * 16)/16; 
var lower = Math.floor(number * 16)/16; 
0

¿Cuál es las fracciones más pequeñas que usted está interesado en la división? IE son décimo sextos va a ser los incrementos más pequeños?

En caso afirmativo, simplemente multiplique su número por 16. Trunc a un int y divida por 16 para encontrar el límite inferior. Trunc a un int, agrega 1, luego divide por 16 para encontrar el límite superior.

1

Suena como redondeo al 16 más cercano ...

rounded = Math.round(number * 16)/16; 

Usted podría conseguir números que no son exactas debido a la representación de flotación, pero eso no debería importar en su caso, si lo usa sólo para el almacenamiento en caché .

0

Un par de estrategias no publicado hasta ahora:

A) crear una tabla de búsqueda que mapea los dígitos después del punto decimal al 16 más cercano. Simplemente use la precisión que necesite (probablemente centésimas).

B) crear una tabla de todos los 16ths de 0 a 1, y hacer una búsqueda de estilo binario con su número de% 1.

1
function bounds(number, numerator, denominator) { 
    var frac = denominator/numerator; 
    return { 
    lower: Math.floor(frac * number)/frac, 
    upper: Math.ceil(frac * number)/frac, 
    } 
} 


bounds(26.746346081599476,1,16) 
// returns an object with properties 
// lower : 26.6875 
// upper : 26.75 
Cuestiones relacionadas