如何将数字转换为字节,类似于 postgres 中的 java
how to convert numeric to byte as similer to java in postgres
我正在尝试在 Postgres 中复制一些 java 代码。
我需要执行的操作是将Java BigInteger
转换为byte array
Java代码:
public class Main {
public static void main(String[] args) {
BigInteger n = new BigInteger("1677259342285725925376");
System.out.println(Arrays.toString(n.toByteArray()));
}
}
输出: [90, -20, -90, 53, 78, -38, 2, -128, 0]
Postgres 代码:
select numeric_send(1677259342285725925376);
输出: "[=18=]0[=18=]6[=18=]0[=18=]5[=18=]0[=18=]0[=18=]0[=18=]0[=18=]006-$~3)2 5[=18=]0"
使用 numeric_send
将数字转换为 bytea
http://www.leadum.com/downloads/dbscribe/samples/postgresql/web_modern/function/main/643567399.html
为了检查 Java 控制台中的输出,我在下面写了匿名块
do
$$
declare
bytes bytea;
begin
bytes := numeric_send(1677259342285725925376);
for i in 0..length(bytes)-1 loop
raise notice '%', get_byte(bytes,i);
end loop;
end; $$
现在输出打印为:
NOTICE: 0
NOTICE: 6
NOTICE: 0
NOTICE: 5
NOTICE: 0
NOTICE: 0
NOTICE: 0
NOTICE: 0
NOTICE: 0
NOTICE: 16
NOTICE: 30
NOTICE: 45
NOTICE: 36
NOTICE: 126
NOTICE: 11
NOTICE: 41
NOTICE: 10
NOTICE: 32
NOTICE: 21
NOTICE: 0
根据我的说法,输出应该与我在两者中转换为字节数组的输出相同。请帮助我如何实现相同的目标。
谢谢
PostgreSQL 的 numeric
和 Java 的 java.math.BigInteger
有不同的二进制表示。
numeric
是一个二进制编码的十进制,你也有 varlena
header。
尽可能避免使用数据类型的内部二进制表示——这可能取决于机器架构的字节顺序等因素。
我执行了以下步骤将数值转换为字节数组。
-- Convert numeric to bit
CREATE OR REPLACE FUNCTION numeric_to_bit(NUMERIC)
RETURNS BIT VARYING AS $$
DECLARE
num ALIAS FOR ;
-- 1 + largest positive BIGINT --
max_bigint NUMERIC := '9223372036854775808' :: NUMERIC(19, 0);
result BIT VARYING;
BEGIN
WITH
chunks (exponent, chunk) AS (
SELECT
exponent,
floor((num / (max_bigint ^ exponent) :: NUMERIC(300, 20)) % max_bigint) :: BIGINT
FROM generate_series(0, 5) exponent
)
SELECT bit_or(chunk :: BIT(300) :: BIT VARYING << (63 * (exponent))) :: BIT VARYING
FROM chunks INTO result;
RETURN result;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
-- conversion for bit(8) to integer with sign
CREATE OR REPLACE FUNCTION bit_to_integer(b BIT(8))
RETURNS INTEGER AS $$
DECLARE
result int;
BEGIN
result := b::integer;
result := case when result > 127 then result-256 else result end;
RETURN result;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
-- removce padding from bit varying
CREATE OR REPLACE FUNCTION ltrim_bitvar(bv BIT VARYING)
RETURNS text AS $$
DECLARE
result text;
fill int;
BEGIN
result := ltrim(bv::text,'0');
fill := 8-length(result)%8;
result := lpad(result,length(result)+fill,'0') ;
return result;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
--converting bit var text to byte array
CREATE OR REPLACE FUNCTION btext_to_bytea(b text)
RETURNS bytea AS
$BODY$
DECLARE
bytes bytea;
temp integer;
b_len integer;
BEGIN
b_len := length(b)/8;
bytes = lpad('',b_len,'0')::bytea;
for i in 1..b_len loop
temp = substring(b,(i*8)-8 + 1,8)::bit(8)::integer;
--raise notice '%', temp;
bytes := set_byte(bytes, i-1, temp);
end loop;
return bytes;
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE;
-- converting numeric to bytea
CREATE OR REPLACE FUNCTION num_to_bytea(n numeric)
RETURNS bytea AS
$BODY$
BEGIN
return btext_to_bytea(ltrim_bitvar(numeric_to_bit(n)));
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE;
创建以上必备功能。
do
$$
declare
bytes bytea;
begin
bytes := num_to_bytea(1677259342285725925376::numeric);
for i in 0..length(bytes)-1 loop
raise notice '%', case when get_byte(bytes,i) > 127 then get_byte(bytes,i)-256 else get_byte(bytes,i) end ;
end loop;
end; $$
输出:
NOTICE: 90
NOTICE: -20
NOTICE: -90
NOTICE: 53
NOTICE: 78
NOTICE: -38
NOTICE: 2
NOTICE: -128
NOTICE: 0
我正在尝试在 Postgres 中复制一些 java 代码。
我需要执行的操作是将Java BigInteger
转换为byte array
Java代码:
public class Main {
public static void main(String[] args) {
BigInteger n = new BigInteger("1677259342285725925376");
System.out.println(Arrays.toString(n.toByteArray()));
}
}
输出: [90, -20, -90, 53, 78, -38, 2, -128, 0]
Postgres 代码:
select numeric_send(1677259342285725925376);
输出: "[=18=]0[=18=]6[=18=]0[=18=]5[=18=]0[=18=]0[=18=]0[=18=]0[=18=]006-$~3)2 5[=18=]0"
使用 numeric_send
将数字转换为 bytea
http://www.leadum.com/downloads/dbscribe/samples/postgresql/web_modern/function/main/643567399.html
为了检查 Java 控制台中的输出,我在下面写了匿名块
do
$$
declare
bytes bytea;
begin
bytes := numeric_send(1677259342285725925376);
for i in 0..length(bytes)-1 loop
raise notice '%', get_byte(bytes,i);
end loop;
end; $$
现在输出打印为:
NOTICE: 0
NOTICE: 6
NOTICE: 0
NOTICE: 5
NOTICE: 0
NOTICE: 0
NOTICE: 0
NOTICE: 0
NOTICE: 0
NOTICE: 16
NOTICE: 30
NOTICE: 45
NOTICE: 36
NOTICE: 126
NOTICE: 11
NOTICE: 41
NOTICE: 10
NOTICE: 32
NOTICE: 21
NOTICE: 0
根据我的说法,输出应该与我在两者中转换为字节数组的输出相同。请帮助我如何实现相同的目标。
谢谢
PostgreSQL 的 numeric
和 Java 的 java.math.BigInteger
有不同的二进制表示。
numeric
是一个二进制编码的十进制,你也有 varlena
header。
尽可能避免使用数据类型的内部二进制表示——这可能取决于机器架构的字节顺序等因素。
我执行了以下步骤将数值转换为字节数组。
-- Convert numeric to bit
CREATE OR REPLACE FUNCTION numeric_to_bit(NUMERIC)
RETURNS BIT VARYING AS $$
DECLARE
num ALIAS FOR ;
-- 1 + largest positive BIGINT --
max_bigint NUMERIC := '9223372036854775808' :: NUMERIC(19, 0);
result BIT VARYING;
BEGIN
WITH
chunks (exponent, chunk) AS (
SELECT
exponent,
floor((num / (max_bigint ^ exponent) :: NUMERIC(300, 20)) % max_bigint) :: BIGINT
FROM generate_series(0, 5) exponent
)
SELECT bit_or(chunk :: BIT(300) :: BIT VARYING << (63 * (exponent))) :: BIT VARYING
FROM chunks INTO result;
RETURN result;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
-- conversion for bit(8) to integer with sign
CREATE OR REPLACE FUNCTION bit_to_integer(b BIT(8))
RETURNS INTEGER AS $$
DECLARE
result int;
BEGIN
result := b::integer;
result := case when result > 127 then result-256 else result end;
RETURN result;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
-- removce padding from bit varying
CREATE OR REPLACE FUNCTION ltrim_bitvar(bv BIT VARYING)
RETURNS text AS $$
DECLARE
result text;
fill int;
BEGIN
result := ltrim(bv::text,'0');
fill := 8-length(result)%8;
result := lpad(result,length(result)+fill,'0') ;
return result;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
--converting bit var text to byte array
CREATE OR REPLACE FUNCTION btext_to_bytea(b text)
RETURNS bytea AS
$BODY$
DECLARE
bytes bytea;
temp integer;
b_len integer;
BEGIN
b_len := length(b)/8;
bytes = lpad('',b_len,'0')::bytea;
for i in 1..b_len loop
temp = substring(b,(i*8)-8 + 1,8)::bit(8)::integer;
--raise notice '%', temp;
bytes := set_byte(bytes, i-1, temp);
end loop;
return bytes;
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE;
-- converting numeric to bytea
CREATE OR REPLACE FUNCTION num_to_bytea(n numeric)
RETURNS bytea AS
$BODY$
BEGIN
return btext_to_bytea(ltrim_bitvar(numeric_to_bit(n)));
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE;
创建以上必备功能。
do
$$
declare
bytes bytea;
begin
bytes := num_to_bytea(1677259342285725925376::numeric);
for i in 0..length(bytes)-1 loop
raise notice '%', case when get_byte(bytes,i) > 127 then get_byte(bytes,i)-256 else get_byte(bytes,i) end ;
end loop;
end; $$
输出:
NOTICE: 90
NOTICE: -20
NOTICE: -90
NOTICE: 53
NOTICE: 78
NOTICE: -38
NOTICE: 2
NOTICE: -128
NOTICE: 0