所以一段时间后,我得到了一个解决方案,它由两个函数和一个存储过程组成(这也可以实现为函数,但我喜欢过程。
这是基于此python脚本的,
https://www.geeksforgeeks.org/python-program-to-represent-floating-number-as-hexadecimal-by-ieee-754-standard/
并使用以下方法
首先使用的功能。
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,16);
SELECT hexstr;
END$$
DELIMITER ;
这将为您提供以下结果:
call IEEE754(263.3);
4383A666
call IEEE754(10.9);
412E6666
,
虽然@nbk的answer有正确的想法,但他的实现不适用于次正规数,并且缺少双精度浮点实现。这是他的答案的简化版本,支持单精度和双精度并使用次正规数。我个人不需要将逗号转换为小数点,因为我的数据库语言是英语,但是您可能必须这样做。
DELIMITER //
DROP FUNCTION IF EXISTS FLOAT_BIN//
CREATE FUNCTION FLOAT_BIN(number FLOAT,places INT)
RETURNS TEXT CHARSET utf8mb4 DETERMINISTIC
BEGIN
DECLARE whole INT;
DECLARE dec1 FLOAT;
DECLARE res TEXT;
SET whole = FLOOR(number);
SET dec1 = number - whole;
SET res = CONCAT(BIN(whole),'.');
WHILE 0 < places DO
SET dec1 = dec1 * 2;
SET whole = FLOOR(dec1);
SET dec1 = dec1 - whole;
SET res = CONCAT(res,whole);
SET places = places - 1;
END WHILE;
RETURN res;
END//
DROP FUNCTION IF EXISTS IEEE754;
CREATE FUNCTION IEEE754(n FLOAT) RETURNS CHAR(8)
BEGIN
DECLARE sign INT;
DECLARE whole VARCHAR(256);
DECLARE dec1 VARCHAR(256);
DECLARE exponent INT;
DECLARE mantissa VARCHAR(256);
# check if number is negative
SET sign = 0;
IF n < 0 THEN
SET sign = 1;
SET n = n * -1;
END IF;
# convert float to binary
SET dec1 = FLOAT_BIN(n,256); # good upper bound is twice the max exponent
# separate the decimal part
# and the whole number part
SET whole = SUBSTRING_INDEX(dec1,1);
SET dec1 = SUBSTRING_INDEX(dec1,-1);
# calculating the exponent(E)
IF n >= 1 THEN
SET exponent = LENGTH(whole) - 1;
SET mantissa = CONCAT(SUBSTR(whole,2),dec1);
ELSE
SET exponent = -1;
WHILE SUBSTR(dec1,1) = '0' AND exponent > -127 DO
SET exponent = exponent - 1;
SET dec1 = SUBSTR(dec1,2);
END WHILE;
IF exponent = -127 THEN
SET mantissa = dec1;
ELSE
SET mantissa = SUBSTR(dec1,2);
END IF;
END IF;
RETURN CONV(CONCAT(sign,LPAD(BIN(127 + exponent),8,'0'),RPAD(mantissa,23,'0')),16);
END//
DROP FUNCTION IF EXISTS IEEE754_DOUBLE;
CREATE FUNCTION IEEE754_DOUBLE(n FLOAT) RETURNS CHAR(16)
BEGIN
DECLARE sign INT;
DECLARE whole VARCHAR(4096);
DECLARE dec1 VARCHAR(4096);
DECLARE exponent INT;
DECLARE mantissa VARCHAR(4096);
# check if number is negative
SET sign = 0;
IF n < 0 THEN
SET sign = 1;
SET n = n * -1;
END IF;
# convert float to binary
SET dec1 = FLOAT_BIN(n,4096);
# separate the decimal part
# and the whole number part
SET whole = SUBSTRING_INDEX(dec1,1) = '0' AND exponent > -1023 DO
SET exponent = exponent - 1;
SET dec1 = SUBSTR(dec1,2);
END WHILE;
IF exponent = -1023 THEN
SET mantissa = dec1;
ELSE
SET mantissa = SUBSTR(dec1,LPAD(BIN(1023 + exponent),11,52,16);
END//
DELIMITER ;
,
在MySQL中无法完成。甚至不是全新的(8.0.17):
CAST(UNHEX('412E6666') AS FLOAT)
此外,也没有其他方法可以解决,因为任何形式的CAST
或HEX
都只需要一个字符串,即“ 10.9”,而不是位/字节/十六进制的10.9。
如果可以备份一步,也许可以通过其他方式实现更大的目标。
本文链接:https://www.f2er.com/3106955.html