PostgreSQL 中数字之间的异或

问题描述 投票:0回答:3

所以我有两个整数 > 2 ^ 63 - 1 但是 < 2 ^ 64 -1. This is BIGINT UNSIGNED in most languages, but according to MySQL、PostgreSQL 和 SQLite 中数据库列类型的比较? (交叉映射),postogresql 中的数字(20)

问题是,当我尝试在两个无符号 bigint 之间进行 postgresql 异或运算时:

select 17418945696623429624::numeric(20) # 17418945696623429624::numeric(20);

=>

ERROR:  operator does not exist: numeric # numeric

对于任何小于 2 ^ 63 -1 的非“数字”整数,它都可以正常工作。

改写:如何在大于 2 ^ 63 - 1 但小于 2 ^ 64 - 1 的两个数字之间执行异或运算?前任。我如何在 PostgreSQL 中将 17418945696623429624 与其自身进行异或?

sql postgresql integer biginteger unsigned
3个回答
1
投票

看起来 PostgreSQL 有一个 bigint 类型——你为什么不使用它?


1
投票

根据 PostgreSQL 文档

按位运算符仅适用于 整数数据类型,而 其他可用于所有数字 数据类型。

数字属于任意精度数字(不是整数类型),因此异或运算符不起作用。

有(仅有符号)bigint 整数类型,但只有 -2^63 到 2^63 - 1。不幸的是,没有无符号 bigint 数据类型(即 0 到 2^64 -1)。

我认为可以使用 bigint 数据类型和一些“按位魔法”来实现这样的计算。


0
投票

我使用 pgplsql 创建了一系列按位运算符函数来满足这一确切要求。这是异或的示例:

create or replace function numeric_xor(leftarg numeric(1000), rightarg numeric(1000)) returns numeric as
$$
declare width int = 32;
    declare modulo bigint := 2 ^ width;
    declare b1 bigint := 0;
    declare b2 bigint := 0;
    declare r numeric(1000) := 0;
    declare i integer := 0;
begin
    while leftarg != 0 or rightarg != 0 loop
            b1 := leftarg % modulo;
            b2 := rightarg % modulo;
            r := r + ((b1 # b2)::numeric << (width * i));
            leftarg = leftarg >> width;
            rightarg = rightarg >> width;
            i := i + 1;
        end loop;
    return r;
end;
$$ language plpgsql;

create operator # (
    function=numeric_xor,
    leftarg=numeric,
    rightarg=numeric
    );

do
$$
    begin
        assert 129401205912050919051920510251920501925::numeric # 12591205901209501209490409120949109249012040124::numeric = 12591206029860257193562230384726988007386197273;
    end;
$$;

其他运算符可以在这里找到:https://gist.github.com/allfro/d93cbc6980f38cf309555eff77381ced

© www.soinside.com 2019 - 2024. All rights reserved.