算法四舍五入到R的下一个数量级



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

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

任何想法?

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

取该数的以10为底的对数,并对结果应用上限或下限。取10的这个次方。做。

0需要一个特例因为你不能取0的对数

这里有一个简单的函数,可以完成您所需要的:

log10_ceiling <- function(x) {
    10^(ceiling(log10(x)))
}
log10_ceiling(c(345, 3.2, 0.034))
# [1] 1000.0   10.0    0.1

Hadley的plyr包有一个非常灵活的功能,称为round_any,它优雅地完成了这一点。下面是如何调用函数

round_any(x, accuracy, f = round)

在您的情况下,x = 345, accuracy = 1000和您想要的f = ceiling。所以调用

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

可以胜任这项工作

编辑。刚刚看到,您希望将maximum四舍五入到ceiling,并将最小值四舍五入到floor。更改函数调用中的f以实现此目的。

Mark Ransom给出的答案基本上是正确的。在Java中实现了这一点后,我发现了一些需要解决的问题:

  • 负数需要特别处理,如果你想-375产生-1000
  • 上限为正对数值,下限+ 1为负对数值(如果您希望0.456产生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);
}

如果有人感兴趣,下面是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))

最新更新