Круглая функция SQL - PullRequest
       7

Круглая функция SQL

4 голосов
/ 10 июля 2009

round(45.923,-1) дает результат 50. Почему это? Как рассчитывается?

(извините, ребята, я ошибся с более ранней версией этого вопроса, предполагая значение 46)

Ответы [ 6 ]

12 голосов
/ 10 июля 2009

Функция SQL ROUND () округляет число до точности ...

Например:

раунд (45,65, 1) дает результат = 45,7

раунд (45,65, -1) дает результат = 50

потому что точность в этом случае вычисляется из десятичной точки. Если положительное значение, то оно будет считать число с правой стороны и округлять его вверх, если оно> = 5, а если <= 4, то округлять снизу ... и аналогично, если оно отрицательное, то точность рассчитывается для левой части десятичного числа. точка ... если это> = 5

например раунд (44,65, -1) дает 40 но раунд (45,65, -1) дает 50 ...

4 голосов
/ 10 июля 2009

КРУГЛЫЙ (748,58, -1) 750,00

второй параметр: длина, это точность, до которой округляется числовое выражение. длина должна быть выражением типа tinyint, smallint или int. Когда длина является положительным числом, numeric_expression округляется до количества десятичных разрядов, указанных в length. Когда длина является отрицательным числом, numeric_expression округляется с левой стороны десятичной точки, как указано в length.

С

2 голосов
/ 10 июля 2009

Что касается того, как начать, подумайте, как бы вы округлили (положительное) число с плавающей точкой до ближайшего целого числа. Приведение float к int усекает его. Добавление 0.5 к (положительному) числу с плавающей точкой будет увеличивать целую часть точно, когда мы хотим округлить (когда десятичная часть> = 0.5). Это дает следующее:

double round(double x) {
    return (long long)(x + 0.5);
}

Чтобы добавить поддержку для параметра точности, обратите внимание, что (например, round(123456.789, -3)) добавление 500 и усечение в месте с тысячами, по сути, равнозначно добавлению 0,5 и округлению до ближайшего целого числа, просто десятичная точка равна в другом положении. Чтобы переместить основную точку вокруг, нам нужны операции сдвига влево и вправо, которые эквивалентны умножению на основание, увеличенное до величины сдвига. То есть 0x1234 >> 3 совпадает с 0x1234 / 2**3 и 0x1234 * 2**-3 в базе 2. В базе 10:

123456.789 >> 3 == 123456.789 / 10**3 == 123456.789 * 10**-3 == 123.456789

Для round(123456.789, -3) это означает, что мы можем выполнить вышеупомянутое умножение, чтобы переместить десятичную точку, добавить 0,5, усечь, а затем выполнить обратное умножение, чтобы переместить десятичную точку назад.

double round(double x, double p) {
    return ((long long)((x * pow10(p))) + 0.5) * pow10(-p);
}

Округление путем добавления 0,5 и усечения работает нормально для неотрицательных чисел, но округляет неправильный путь для отрицательных чисел. Есть несколько решений. Если у вас есть эффективная функция sign() (которая возвращает -1, 0 или 1, в зависимости от того, является ли число <0, == 0 или> 0 соответственно), вы можете:

double round(double x, double p) {
    return ((long long)((x * pow10(p))) + sign(x) * 0.5) * pow10(-p);
}

Если нет, то есть:

double round(double x, double p) {
    if (x<0) 
      return - round(-x, p);
    return ((long long)((x * pow10(p))) + 0.5) * pow10(-p);
}
2 голосов
/ 10 июля 2009

Ожидается, что будет 50.

раунд (45,923, 0) => 46

expl: последняя недесятичная цифра округляется (5), решение основано на следующей цифре (9) 9 в верхней половине, эрго 5 округлено до 6

раунд (45,923, 1) => 45,9

expl: первая десятичная цифра округлена (9), решение основано на следующей цифре (2) 2 в нижней половине, эрго 9 остается 9

ваш случай: раунд (45,923, 1-) => 45,92

expl: вторая-последняя десятичная цифра округляется (4), решение основано на следующей цифре (5) 5 находится в верхней половине, ergo 4 округлено до 5, остальные цифры заполнены нулями

1 голос
/ 10 июля 2009

Это не для меня на MySQL:

mysql> select round(45.923,-1);
+------------------+
| round(45.923,-1) |
+------------------+
|               50 |
+------------------+
1 row in set (0.00 sec)
0 голосов
/ 10 июля 2009

А на Sql Server 2005:

select round(45.923,-1)
------
50.000

В какой базе данных вы это используете?

...