#r
#r
Вопрос:
Прошу прощения, если название непонятно, но я не смог объяснить это кратко.
Учитывая вектор концентраций, я хотел бы округлить максимальное значение до следующего порядка величины (т. Е. От 345 до 1000). Кроме того, я хотел бы округлить минимальное значение до более низкого порядка величины (т. Е. От 3,2 до 1). Эти концентрации также могут быть ниже 1, поэтому, например, 0,034 необходимо будет округлить до 0,01.
Есть идеи?
Комментарии:
1. Это не округление, а что-то другое. Вы можете округлить 32 до 30 и, следовательно, от 30 до 0, но не до 10 или 1.
Ответ №1:
Я не уверен насчет R, но это простой процесс для алгоритмического описания.
Возьмите логарифм числа по основанию 10 и примените к результату потолок или пол. Увеличьте 10 до этой степени. Выполнено.
Вам нужен особый случай для 0, потому что вы не можете взять логарифм 0.
Комментарии:
1. @Pocketsand в этом случае мы применяем значение floor или ceil к логарифму, и нам нужно согласованное поведение независимо от того, было ли исходное число предварительного журнала выше или ниже 1.0. Усечение было бы неуместным.
2. @MarkRansom вы совершенно правы, я задумал что-то математически невозможное.
Ответ №2:
Вот простая функция, которая делает то, что вам нужно:
log10_ceiling <- function(x) {
10^(ceiling(log10(x)))
}
log10_ceiling(c(345, 3.2, 0.034))
# [1] 1000.0 10.0 0.1
Ответ №3:
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
в вызове функции, чтобы достичь этого.
Комментарии:
1. Спасибо за информацию, Рамнатх! Я проверю это.
Ответ №4:
Принятый ответ Марка Рэнсома в основном правильный. Реализовав это в 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);
}
Комментарии:
1. Я не понимаю, почему вам нужно переключаться с
ceil()
floor() 1
на отрицательные значения журнала. Какой случай фиксируется этим?2. Возможно, на самом деле это не требуется @MarkRansom. На данный момент я не уверен.
3. Я знаю, это сложно, когда вы получаете вопрос для ответа, который вы оставили 6 лет назад. Но я это вижу впервые, и с тех пор, как ты назвал меня по имени…
Ответ №5:
В случае, если кому-то интересно, ниже приведено решение Остермиллера, переведенное на 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))
Комментарии:
1. Для работы это должно быть
import numpy as np
вверху. Без этого вы получитеNameError: global name 'np' is not defined
.