Итак, через некоторое время я получил решение, которое состоит из двух функций и одной хранимой процедуры (это также может быть реализовано как функция, но мне нравятся процедуры.
Это основано на этом скрипте Python, https://www.geeksforgeeks.org/python-program-to-present-floating-number-as-hexadecimal-by-ieee-754-standard/
и использует следующий подход
Проверьте, положительное или отрицательное число. Сохраните знак как 0 для положительного и 1 для отрицательного, а затем преобразуйте число в положительное, если оно отрицательное.
Преобразуйте число с плавающей запятой в двоичное.
- Разделите десятичную часть и целую часть числа.
- Вычислите показатель степени (E) и преобразуйте его в двоичную форму.
- Найдите мантиссу.
- Соедините знак мантиссы, экспоненты и мантиссы. Преобразуйте его в шестнадцатеричное.
Сначала используемые функции.
DELIMITER $$
CREATE DEFINER=`root`@`localhost` FUNCTION `decimal_converter`(num INTEGER) RETURNS decimal(10,10)
DETERMINISTIC
BEGIN
DECLARE outnum DECIMAL(10,10);
SET outnum = num/10;
label1: WHILE outnum > 1 DO
SET outnum = outnum / 10;
END WHILE label1;
RETURN outnum;
END$$
DELIMITER ;
И также необходимо
DELIMITER $$
CREATE DEFINER=`root`@`localhost` FUNCTION `float_bin`(number float
, places INT) RETURNS text CHARSET utf8mb4
DETERMINISTIC
BEGIN
DECLARE whole INT;
DECLARE dec1 INT;
DECLARE res TEXT;
IF places = NULL THEN SET places = 3; END IF;
SELECT
SUBSTRING_INDEX(REPLACE(CAST(TRIM(TRAILING '.' FROM TRIM(TRAILING '0' from (number))) as CHAR(90)),',','.'), '.', 1) INTO @a;
SELECT
SUBSTRING_INDEX(REPLACE(CAST(TRIM(TRAILING '.' FROM TRIM(TRAILING '0' from (number))) as CHAR(90)),',','.'), '.', -1) iNTO @b;
SET whole = @a;
SET dec1 = @b ;
SET res = BIN(whole);
SET res = CONCAT(res , '.');
while 0 < places do
SELECT
SUBSTRING_INDEX(REPLACE(CAST(TRIM(TRAILING '.' FROM TRIM(TRAILING '0' from (decimal_converter(dec1) * 2))) as CHAR(90)),',','.'), '.', 1) INTO @a;
SELECT
SUBSTRING_INDEX(REPLACE(CAST(TRIM(TRAILING '.' FROM TRIM(TRAILING '0' from (decimal_converter(dec1) * 2))) as CHAR(90)),',','.'), '.', -1) INTO @b;
SET whole = @a;
SET dec1 = @b;
SET res = CONCAT(res , whole) ;
SET places=places-1;
end while;
RETURN res;
END$$
DELIMITER ;
И последняя хранимая процедура
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `IEEE754`(
IN n FLOAT
)
BEGIN
DECLARE sign Integer;
DECLARE whole TEXT;
DECLARE dec1 TEXT;
DECLARE p INT;
DECLARE exponent INT;
DECLARE tmpstr VARCHAR(60);
DECLARE exponent_bits INT;
DECLARE exponent_bitsstr TEXT;
DECLARE mantissa TEXT;
DECLARE finally TEXT;
DECLARE hexstr TEXT;
#check if number is negative
SET sign = 0;
IF n < 0 Then
SET sign = 1;
SET n = n * -1;
END IF;
SET p = 30 ;
# convert float to binary
SET dec1 = float_bin (n, p);
# separate the decimal part
# and the whole number part
SELECT
SUBSTRING_INDEX(REPLACE(CAST(dec1 as CHAR(90)),',','.'), '.', 1) INTO @a;
SELECT
SUBSTRING_INDEX(REPLACE(CAST(dec1 as CHAR(90)),',','.'), '.', -1) iNTO @b;
SET whole = @a;
SET dec1 = @b ;
# calculating the exponent(E)
SET tmpstr = CAST(whole as CHAR(60));
SET exponent = LENGTH(tmpstr) - 1;
SET exponent_bits = 127 + exponent;
SET exponent_bitsstr = BIN(exponent_bits);
# finding the mantissa
SET mantissa = SUBSTRING(tmpstr,2,exponent);
SET mantissa = CONCAT(mantissa,dec1);
SET mantissa = SUBSTRING(mantissa,1,23);
# the IEEE754 notation in binary
SET finally = CONCAT(sign,exponent_bitsstr,mantissa );
SET hexstr = CONV(finally,2,16);
SELECT hexstr;
END$$
DELIMITER ;
Это дает следующий результат:
call IEEE754(263.3);
4383A666
call IEEE754(10.9);
412E6666
21.11.2019