使用 MODULO DIVISION 方法将十进制数转换为十六进制数

Converting Decimal to Hexadecimal number using MODULO DIVISION method

我正在转换十进制数

42541956123769884636017138956568135808

转十六进制数

20014860486000000000000000008880

我的转换值为20014860486000000000000000019980

我的 Postgresql 转换函数是

CREATE OR REPLACE FUNCTION ipv6_dec_hex(ip_number numeric)
  RETURNS character varying AS
$BODY$
DECLARE

    ip  int :=null;
    ip1 character varying := '';
    ip2 character varying;

BEGIN
        while(ip_number != 0)
        LOOP
            ip = trunc(mod(ip_number,16));
            ip_number = trunc(ip_number/16);
            ip1:=ip1||to_hex(ip);
            raise notice 'ip is %',ip;
            raise notice 'ip_number is %',ip_number;

        END LOOP;
        ip2:=reverse(ip1);

        return ip2;
END;
   $BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

我正在使用模余数法。所以我用 16 取给定数字的模数,并将给定的十进制数除以 16 以进行连续的十六进制数转换。在第一次迭代中取模时,我得到

0 as remainder as last digit of hexadecimal number 20014860486000000000000000008880

and next dividend is 2658872257735617789751071184785508488

在第二次迭代中取模 2658872257735617789751071184785508488 得到

8 as remainder second from last digit of hexadecimal number 20014860486000000000000000008880

and next dividend is 166179516108476111859441949049094281

在第三次迭代中取模 166179516108476111859441949049094281 得到

9 as remainder but 8 is the exact hexadecimal digit to come in third from last digit of hexadecimal number 20014860486000000000000000008880

如果上述分红值是166179516108476111859441949049094280 而不是 166179516108476111859441949049094281 那么我将得到余数 8 。我怎样才能得到准确的十六进制值 20014860486000000000000000008880 而不是 20014860486000000000000000019980

如果你这样说,你会得到 floating-point 除法,这会导致精度损失。

ip_number = trunc(ip_number/16);

改为这样说

ip_number = div(ip_number,16);

docs here

编辑后的完整源代码:

CREATE OR REPLACE FUNCTION ipv6_dec_hex(ip_number numeric)
  RETURNS character varying AS
$BODY$
DECLARE

    ip  int :=null;
    ip1 character varying := '';
    ip2 character varying;

BEGIN
        while(ip_number != 0)
        LOOP
            ip = mod(ip_number,16);
            ip_number = div(ip_number,16);
            ip1:=ip1||to_hex(ip);
            raise notice 'ip is %',ip;
            raise notice 'ip_number is %',ip_number;

        END LOOP;
        ip2:=reverse(ip1);

        return ip2;
END;
   $BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

select ipv6_dec_hex(42541956123769884636017138956568135808)
   ='20014860486000000000000000008880';