I am converting Decimal number
42541956123769884636017138956568135808
to hexadecimal number
20014860486000000000000000008880
My converted value is 20014860486000000000000000019980
My Postgresql function for conversion is
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;
I am using modulo-remainder method. so I am taking modulus for the given number with 16
and divide given decimal number by 16
for consecutive hexadecimal number conversions. While taking modulus in first iteration I am getting
0
as remainder as last digit of hexadecimal number20014860486000000000000000008880
and next dividend is
2658872257735617789751071184785508488
In second iteration taking modulus of 2658872257735617789751071184785508488
getting
8
as remainder second from last digit of hexadecimal number20014860486000000000000000008880
and next dividend is
166179516108476111859441949049094281
In third iteration taking modulus of 166179516108476111859441949049094281
getting
9
as remainder but8
is the exact hexadecimal digit to come in third from last digit of hexadecimal number20014860486000000000000000008880
If the above dividend value is 166179516108476111859441949049094280
instead of 166179516108476111859441949049094281
then i will get the remainder value as 8
. How could i get the exact hexadecimal value 20014860486000000000000000008880
instead of 20014860486000000000000000019980
If you say this you'll get floating-point division, and that will give a loss of precision.
ip_number = trunc(ip_number/16);
Say this instead
ip_number = div(ip_number,16);
full source after edit:
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';