2011-10-26 12 views
6

Przepraszam, jeśli tytuł nie jest jasne, ale nie mogłem wyjaśnić go zwięźle.algorytm zaokrąglić do następnego rzędu wielkości w R

względu wektorem stężeniach Chciałbym zaokrąglania wartości maksymalnej do kolejnego rzędu (to znaczy 345 do 1000). Chciałbym również zaokrąglić minimalną wartość do niższego rzędu wielkości (tj. Od 3.2 do 1). Stężenia te mogą również wynosić poniżej 1, na przykład 0,034 musi być zaokrąglone do 0,01.

Wszelkie pomysły?

+0

To nie zaokrąglania, ale coś innego. Możesz zaokrąglić 32 do 30, a co za tym idzie 30 do 0, ale nie do 10 lub 1. –

Odpowiedz

12

Nie jestem pewien co do R, ale jest to prosty proces do opisania algorytmicznie.

Wykonaj logarytm bazowy numeru i zastosuj sufit lub podłogę do wyniku. Podnieś 10 do tej mocy. Gotowe.

Potrzebny jest specjalny przypadek 0, ponieważ nie można wziąć logarytm 0.

+0

Dzięki Mark! Dokładnie to, czego potrzebowałem. – sinclairjesse

8

Oto prosta funkcja, która robi to, co jesteś po:

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

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

Niezły Josh. Dzięki! – sinclairjesse

1

plyr pakiet Hadley ma niezwykle elastyczna funkcja o nazwie round_any, która robi to elegancko. Oto jak można wywołać funkcję

round_any(x, accuracy, f = round) 

w przypadku, x = 345, accuracy = 1000 i chcesz f = ceiling. Więc wywołanie

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

by wykonać zadanie

edytować. Właśnie zobaczyłem, że chcesz maximum zaokrąglić do ceiling i wartości minimalne zaokrąglone w dół do floor. zmień f w wywołaniu funkcji, aby to osiągnąć.

+0

Dzięki za informację Ramnath! Sprawdzę to. – sinclairjesse

1

Przyjęta odpowiedź Marka Ransoma jest w większości poprawna. Po wdrożone w Java Znalazłem jeszcze kilka obszarów, które należy rozwiązać:

  • Ujemne numery muszą być traktowane specjalnie, jeśli chcesz -375 uzyskując -1000
  • sufitowe dla wartości dodatnich dziennika, podłoga + 1 dla ujemnych wartości logów (plus jeden jest ważny, jeśli chcesz 0.456, aby uzyskać 1).

Oto moja implementacja w języku Java z jednostki przeszły badania

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); 
} 
Powiązane problemy