Postgresql округляет до значащих цифр

я пробовал этот запрос значащих цифр из этого блога (https://www.garysieling.com/blog/postgres-significant-figures-pg_size_pretty).

Но, кажется, на нем фиксированная десятичная цифра.

SELECT FLOOR(5.4321/(10 ^ FLOOR(log(5.4321)-1))) * (10 ^ FLOOR(log(5.4321)-1))

Результат запроса выше — 5.4. Как я могу выполнить запрос для создания этих результатов?

number | sigfig
5.4321 | 5.43
10.987 | 10.9
550.75 | 550
9850.5 | 9850
ect

Спасибо за помощь братья!


person Rakaziwi    schedule 21.02.2018    source источник


Ответы (3)


Вы можете использовать следующую функцию для округления до числа значащих цифр:

CREATE OR REPLACE FUNCTION sig_digits(n anyelement, digits int) 
RETURNS numeric
AS $$
    SELECT round(n, digits - 1 - floor(log(abs(n)))::int)
$$ LANGUAGE sql IMMUTABLE STRICT;

По сравнению с ответом Лоренца это имеет следующие отличия:

  • результаты округляются, а не занижаются (например, sig_digits(15, 1) равно 20, а не 10)
  • функция принимает произвольные типы в качестве первого аргумента (например, числа с плавающей запятой), а не только числа
  • это быстрее, потому что он избегает вызова log для числового (что медленно), если это возможно, и вызывает log только один раз
  • он возвращает красивые результаты без ненужного количества конечных нулей.
person Karl Bartel    schedule 06.08.2018
comment
Вы должны использовать floor(log(abs(n))), чтобы отрицательные числа тоже работали. - person Shiva127; 21.02.2020

Чтобы дать более общий ответ на этот вопрос, я предлагаю вам использовать следующую функцию, в которой количество значащих цифр является переменной:

CREATE FUNCTION significant_digits(n numeric, digits integer) RETURNS numeric
   LANGUAGE sql IMMUTABLE STRICT AS
'SELECT floor(n / (10 ^ floor(log(n) - digits + 1)))
        * (10 ^ floor(log(n) - digits + 1))';

Тогда вы получите следующее:

test=> SELECT significant_digits(5.4321, 3);
 significant_digits 
--------------------
 5.4300000000000000
(1 row)

test=> SELECT significant_digits(9.87654, 3);
 significant_digits 
--------------------
 9.8700000000000000
(1 row)

Обратите внимание, что формула не округляет, как утверждается в блоге, а усекает.

person Laurenz Albe    schedule 21.02.2018
comment
вау, спасибо, брат, но как я могу получить только важное число без нулей? 5.4300000000000000 -> 5.43 - person Rakaziwi; 26.02.2018
comment
Приведите к text и примените trim(trailing '0' from ...) к результату. - person Laurenz Albe; 26.02.2018

Пример округления количества (статуса) до старшей значащей цифры:

select count(status),
  round(count(status) / pow(10, trunc(log(count(status))) ) ) * pow(10, trunc(log(count(status))) ) 
  from  some_table;

Eg. 1234 => 1000
    987  => 900
person mosh    schedule 09.11.2020