2011-10-26 8 views
6

Disculpe si el título no está claro, pero no podría explicarlo de manera sucinta.algoritmo para redondear al próximo orden de magnitud en R

Dado un vector de concentraciones, me gustaría redondear el valor máximo al siguiente orden de magnitud (es decir, 345 a 1000). Además, me gustaría redondear el valor mínimo al orden de magnitud inferior (es decir, 3,2 a 1). Estas concentraciones también pueden estar por debajo de 1, por lo que 0.034 debería redondearse a 0.01.

¿Alguna idea?

+0

eso no es redondeo, sino otra cosa. Puede redondear 32 a 30 y, en consecuencia, 30 a 0, pero no a 10 o 1. –

Respuesta

12

No estoy seguro acerca de R, pero este es un proceso simple de describir algorítmicamente.

Tome el logaritmo de base 10 del número y aplique un techo o piso al resultado. Aumenta 10 a ese poder. Hecho.

Necesita un caso especial de 0 porque no se puede tomar un logaritmo de 0.

+0

Gracias Mark! Exactamente lo que necesitaba. – sinclairjesse

8

He aquí una función simple que hace lo que está buscando:

log10_ceiling <- function(x) { 
    10^(ceiling(log10(x))) 
} 

log10_ceiling(c(345, 3.2, 0.034)) 
# [1] 1000.0 10.0 0.1 
+0

Nice Josh. ¡Gracias! – sinclairjesse

1

paquete de Hadley plyr tiene una función extremadamente flexible llamada round_any que hace esto elegantemente. Así es como se le llama a la función

round_any(x, accuracy, f = round) 

En su caso, x = 345, accuracy = 1000 y desea f = ceiling. Así llamando

round_any(x = 345, accuracy = 1000, f = ceiling) 

haría el trabajo

EDITAR. Acabo de ver que desea que el maximum se redondee a ceiling y que los valores mínimos se redondeen a floor. cambie el f en la llamada a la función para lograr esto.

+0

Gracias por la información Ramnath! Lo comprobaré. – sinclairjesse

1

La respuesta aceptada por Mark Ransom es en su mayoría correcta. Habiendo implementado esto en Java que he encontrado algunas zonas más que necesitan ser abordados:

  • Los números negativos deben ser manejados especialmente si quieres -375 -1000 para producir
  • de techo para los valores positivos de registro, baja + 1 para valores de registro negativos (el más uno es importante si quiere que 0.456 rinda 1).

Aquí es mi aplicación en Java con la unidad de pasar las pruebas

static double roundUpToNearestMagnitude(double n) { 
    if (n == 0d) return 1d; 
    boolean negative = n < 0; 
    double log = Math.log10(Math.abs(n)); 
    double decimalPlaces = ((log > 0)) ? (Math.ceil(log)) : (Math.floor(log) + 1); 
    double rounded = Math.pow(10, decimalPlaces); 
    return negative ? -rounded : rounded; 
} 

@Test public void roundUpToNearestMagnitudeFifty() { 
    Assert.assertEquals(100d, roundUpToNearestMagnitude(50d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeFive() { 
    Assert.assertEquals(10d, roundUpToNearestMagnitude(5d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeZeroPointFive() { 
    Assert.assertEquals(1d, roundUpToNearestMagnitude(0.5d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeZeroPointZeroFive() { 
    Assert.assertEquals(.1d, roundUpToNearestMagnitude(0.05d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeZeroPointZeroZeroFive() { 
    Assert.assertEquals(.01d, roundUpToNearestMagnitude(0.005d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeNegativeFifty() { 
    Assert.assertEquals(-100d, roundUpToNearestMagnitude(-50d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeNegativeFive() { 
    Assert.assertEquals(-10d, roundUpToNearestMagnitude(-5d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeNegativeZeroPointFive() { 
    Assert.assertEquals(-1d, roundUpToNearestMagnitude(-0.5d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeNegativeZeroPointZeroFive() { 
    Assert.assertEquals(-.1d, roundUpToNearestMagnitude(-0.05d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeNegativeZeroPointZeroZeroFive() { 
    Assert.assertEquals(-.01d, roundUpToNearestMagnitude(-0.005d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeZero() { 
    Assert.assertEquals(1, roundUpToNearestMagnitude(0d), 0.000001); 
} 
Cuestiones relacionadas