Тип данных FLOAT(n)

Как-то в одной социальной сети спросили, как убрать концевые нули в десятичных числах. Это было связано с подготовкой некоего отчета, где денежные суммы конкатенировались с текстом. В постановке задачи указывалось ограничение на два десятичных знака. Вот пример данных и требуемый результат:

данополучить
0.000
10.0010
2.502.5
100.00100
11.3311.33

Предлагались решения, построенные на разборе строки. Я тоже впал в подобную ересь :-) и предложил следующее решение.

SELECT num,
CASE 
    WHEN CAST(num AS INT) = num THEN CAST(CAST(num AS INT) AS VARCHAR) 
    WHEN CAST(num*10 AS INT) = num*10 THEN LEFT(CAST(num AS VARCHAR), LEN(CAST(num AS VARCHAR)) - 1)
    WHEN CAST(num*100 AS INT)=num*100 THEN CAST(num AS VARCHAR)
END fnum
FROM(
     SELECT 0.00 as num
     UNION ALL SELECT 10.00
     UNION ALL SELECT 2.50
     UNION ALL SELECT 100
     UNION ALL SELECT 11.33
    ) X;
🚫
[[ error ]]
[[ column ]]
NULL [[ value ]]

Не знаю, сколько бы это еще продолжалось, если бы один участник дискуссии не заметил, что все проблемы решает приведение к типу данных FLOAT. Действительно,

SELECT num, CAST(num AS FLOAT) fnum
FROM(
     SELECT 0.00 as num
     UNION ALL SELECT 10.00
     UNION ALL SELECT 2.50
     UNION ALL SELECT 100
     UNION ALL SELECT 11.33
    ) X;
🚫
[[ error ]]
[[ column ]]
NULL [[ value ]]

Однако при этом нужно помнить о приближенном характере данного типа, а именно о величине мантиссы в научном представлении числа.

В соответствии со стандартом, этот тип данных имеет аргумент - FLOAT(n), который может принимать значения от 1 до 53. SQL Server значения аргумента в диапазоне 1 - 24 трактует как 24, что соответствует точности 7 цифр, а в диапазоне 25 - 53 как 53, что соответствует точности 15 цифр. По умолчанию принимается значение 53.

Продемонстрируем сказанное следующим примером.

SELECT num,
       CAST(num AS FLOAT(24)) num_24,
       CAST(num AS FLOAT(53)) num_53
FROM(
      SELECT 1234567.80 AS num
      UNION ALL SELECT 12345678.90
      UNION ALL SELECT 123456789012345.60
      UNION ALL SELECT 1234567890123456.70
) x;
🚫
[[ error ]]
[[ column ]]
NULL [[ value ]]
numnum_24num_53
1234567.801.234567.751.234567.8
12345678.901234567912345678.9
123456789012345.60123456788103168123456789012345.6
1234567890123456.7012345679481405441234567890123456.8

MySQL

Не поддерживается преобразование к типу FLOAT.

PostgreSQL

Практически аналогичное поведение, за исключением того, что для параметра в диапазоне 1 – 24 точность составляет 6 цифр. Соответственно последние результаты будут выглядеть так:

numnum_24num_53
1234567.801.2345678e+061.234567.8
12345678.9012345679e+0712345678.9
123456789012345.601.2345679e+14123456789012345.6
1234567890123456.701.234568e+151.2345678901234568e+15