PostgreSQL 中数字之间的异或

发布于 2024-10-27 02:32:30 字数 690 浏览 1 评论 0原文

所以我有两个整数> 2 ^ 63 - 1 但< 2^64-1。在大多数语言中,这是 BIGINT UNSIGNED,但根据 MySQL、PostgreSQL 和 SQLite 中数据库列类型的比较? (交叉映射),postogresql 中的 numeric(20)

问题是,当我尝试在两个无符号 bigint 之间进行 postgresql xor 操作时:

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

=>

ERROR:  operator does not exist: numeric # numeric

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

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

So I have two integers > 2 ^ 63 - 1 but < 2 ^ 64 -1. This is BIGINT UNSIGNED in most languages, but according to Comparison of database column types in MySQL, PostgreSQL, and SQLite? (Cross-Mapping), its numeric(20) in postogresql

problem is, when I try to do a postgresql xor operation between two unsigned bigints:

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

=>

ERROR:  operator does not exist: numeric # numeric

with any non "numeric" integer less than 2 ^ 63 -1, it works fine.

rephrase: How can I perform a XOR operation between two numbers larger than 2 ^ 63 - 1 but less than 2 ^ 64 - 1? Ex. How can I XOR 17418945696623429624 with itself in PostgreSQL?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

伪装你 2024-11-03 02:32:30

看起来像 PostgreSQL 有一个 bigint 类型--你为什么不用那个?

Looks like PostgreSQL has a bigint type-- why don't you use that?

你在我安 2024-11-03 02:32:30

根据 PostgreSQL 文档

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

numeric 属于 任意精度数字 (不是 整数类型),所以 XOR 运算符不是作品。

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

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

According to PostgreSQL documentation:

The bitwise operators work only on
integral data types, whereas the
others are available for all numeric
data types.

numeric belongs to Arbitrary Precision Numbers (not Integer Types), so XOR operator not works.

There is (only signed) bigint integer type, but it's only -2^63 to 2^63 - 1. Unfortunately there is no unsigned bigint datatype (i.e. 0 to 2^64 -1).

I think that it could be possible to implement such calculation using bigint datatype with some "bitwise magic".

风追烟花雨 2024-11-03 02:32:30

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

create or replace function numeric_xor(leftarg numeric(1000), rightarg numeric(1000)) returns numeric as
$
declare 
    width int = 32;
    modulo bigint := 2 ^ width;
    b1 bigint := 0;
    b2 bigint := 0;
    r numeric(1000) := 0;
    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

I've created a series of bitwise operator functions using pgplsql to accommodate for this exact requirement. Here's a sample of xor:

create or replace function numeric_xor(leftarg numeric(1000), rightarg numeric(1000)) returns numeric as
$
declare 
    width int = 32;
    modulo bigint := 2 ^ width;
    b1 bigint := 0;
    b2 bigint := 0;
    r numeric(1000) := 0;
    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;
$;

The other operators can be found here: https://gist.github.com/allfro/d93cbc6980f38cf309555eff77381ced

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文