PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как да преобразувате тип bytea до двойна точност

За тази цел най-доброто възможно решение е да се конвертира в байтове, като се използва стандарт IEEE754-1985, като се използват SQL команди.

Първо се изисква да се провери за специални случаи, определени от стандарта IEEE754-1985. След това просто следвайте стандартния алгоритъм за конвертиране, ако не е в специални случаи. Примерен код е по-долу.

Входовете са bytea_value bytea, is_little_endian boolean след това разделете на 4 байта, както е показано по-долу:

  byte_array[0]:= get_byte(bytea_value, 0);
  byte_array[1]:= get_byte(bytea_value, 1);
  byte_array[2]:= get_byte(bytea_value, 2);
  byte_array[3]:= get_byte(bytea_value, 3);

След това вземете двоичната стойност, като вземете предвид малкия или големия ред

IF is_little_endian THEN
        binary_value:= byte_array[0]::bit(8) || byte_array[1]::bit(8) || byte_array[2]::bit(8) || byte_array[3]::bit(8);
    ELSE
        binary_value:= byte_array[3]::bit(8) || byte_array[2]::bit(8) || byte_array[1]::bit(8) || byte_array[0]::bit(8); 
    END IF;

Сега проверете за специални случаи:

IF binary_value = '00000000000000000000000000000000' OR binary_value = '10000000000000000000000000000000' THEN -- IEEE754-1985 Zero
        return 0.0;
    END IF;

sign := substring(binary_value from 1 for 1);
    exponent := substring(binary_value from 2 for 8);
    mantissa := substring(binary_value from 10 for 23); 

    IF exponent = '11111111' THEN
        IF mantissa = '00000000000000000000000' THEN   -- IEEE754-1985 negative and positive infinity
            IF sign = '1' THEN                    
                return '-Infinity';                    
            ELSE                    
                return 'Infinity';  
            END IF;                  
        ELSE
          return 'NaN'; -- IEEE754-1985 Not a number
        END IF; 
    END IF;

Ако не принадлежи към никакви специални случаи, просто го конвертирайте, както е показано по-долу:

exp := exponent::int;

    IF exp > 126 THEN
     exp := exp - 127;
    ELSE
     exp:= -exp;
    END IF;

    WHILE mantissa_index < 24 LOOP
        IF substring(mantissa from mantissa_index for 1) = '1' THEN
            result := result + power(2, -(mantissa_index));
        END IF;
        mantissa_index = mantissa_index + 1;
    END LOOP;

    result := result * power(2, exp);

    IF(sign = '1') THEN
        result = -result;
    END IF;

    return result;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. pg_dump:невалидна опция -- i при мигриране

  2. Преобразувайте екранизирания символ на Unicode обратно в действителен знак в PostgreSQL

  3. Как да върнете стойност от обещание

  4. Как JSON Marshall pq.NullTime в UTC, а не в местната часова зона?

  5. Миграция на Heroku:модификаторът на тип не е разрешен за тип bytea