算法在R中舍入到下一个数量级

时间:2011-10-26 18:14:11

标签: r

如果标题不清楚,我道歉,但我无法简洁地解释。

给定浓度矢量,我想将最大值四舍五入到下一个数量级(即345到1000)。另外,我想将最小值四舍五入到较低的数量级(即3.2到1)。这些浓度也可能低于1,因此例如0.034需要舍入到0.01。

有什么想法吗?

5 个答案:

答案 0 :(得分:14)

我不确定R,但这是一个简单的算法描述过程。

取数字的基数10对数,并在结果上应用天花板或地板。提高10的力量。完成。

您需要一个0的特殊情况,因为您不能将对数设为0。

答案 1 :(得分:11)

这是一个简单的功能,可以完成您的工作:

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

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

答案 2 :(得分:2)

Hadley的plyr包有一个非常灵活的函数叫round_any,它可以很好地完成这个任务。以下是调用函数的方法

round_any(x, accuracy, f = round)

在您的情况下,x = 345accuracy = 1000,您需要f = ceiling。所以打电话

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

会完成这项工作

EDIT。只是看到您希望将maximum向上舍入为ceiling,将最小值向下舍入为floor。更改函数调用中的f以实现此目的。

答案 3 :(得分:2)

Mark Ransom接受的回答大多是正确的。 在Java中实现了这一点后,我发现了一些需要解决的问题:

  • 如果您希望-375产生-1000
  • ,则需要特别处理负数
  • 正日志值的上限,负日志值的下限 + 1 (如果您希望0.456产生1,则加1是重要的)。

这是我在Java中使用传递单元测试的实现

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);
}

答案 4 :(得分:1)

如果有人感兴趣,以下是Ostermiller的解决方案翻译为Python的情况:

def roundUpToNearestMagnitude(n):
    if n == 0:
        return 1
    negative = n < 0
    log = np.log10(abs(n))
    if log > 0:
        decimalPlaces = np.ceil(log)
    else:
        decimalPlaces = np.floor(log) + 1
    rounded = np.power(10, decimalPlaces)
    if negative:
        return -rounded
    else:
        return rounded

def test_roundUpToNearestMagnitude():
    assert(100 == roundUpToNearestMagnitude(50))
    assert(10 == roundUpToNearestMagnitude(5))
    assert(1 == roundUpToNearestMagnitude(0.5))
    assert(.1 == roundUpToNearestMagnitude(0.05))
    assert(.01 == roundUpToNearestMagnitude(0.005))
    assert(-100 == roundUpToNearestMagnitude(-50))
    assert(-10 == roundUpToNearestMagnitude(-5))
    assert(-1 == roundUpToNearestMagnitude(-0.5))
    assert(-.1 == roundUpToNearestMagnitude(-0.05))
    assert(-.01 == roundUpToNearestMagnitude(-0.005))
    assert(1 == roundUpToNearestMagnitude(0))