是否可以比较两个多字整数,每个字只有一个比较?

Is it possible to compare two multi-word integers with only one comparison per word?

提问人:MrArsGravis 提问时间:3/10/2022 更新时间:3/10/2022 访问量:98

问:

这个问题与语言无关,但我会使用 C,因为这是我编码它的内容。

给定两个整数,每个整数跨越单词,比较这些多单词数字的最有效方法是什么,例如确定?(†)abn_worda < b

作为一个具体的例子,我们可以考虑 和 是长度为 8 位的整数数组,每个数组代表 1 位整数(并假设 big-endian 排序)。(††)或者,可以使用常规的旧十进制数来表达问题,例如,第一个数字 (4) 在哪里等。abn_word8*n_worda = 456a[0]

我有以下有效的代码,但我想知道是否有可能摆脱两种比较之一:

for (unsigned int i = 0; i < n_word; ++i) {
    if (a[i] > b[i]) {
        i = n_word + 1;   /* use as magic number to indicate that a > b */
        break;
    }
    else if (a[i] < b[i]) {
        break;
    }
}

然后结果由 after 循环的值决定:i

if i < n_word,  then a < b
if i > n_word,  then a > b
if i == n_word, then a == b

但我实际上并不想/需要区分所有三种情况;将两个箱子合二为一是完全可以的。但是,如果我只是删除,例如,在不更改任何其他内容的情况下进行比较,那么(在十进制示例中)和 (其中 ) 的计算结果将与 和 (where ) 相同,这显然是不正确的。替换为 in the loop 似乎同样是虚假的。>a = 200b = 123a > ba = 100b = 123a < b<<=


† 虽然,或者他们的任何一个相反也是可以接受的。a > b

†† 不,当然,我实际上并不是要比较两个 32 位整数,而更像是 10 个 32 位整数,它们形成一个非常长的整数,超出了任何原生类型的能力范围。

C 性能 数据 比较

评论

1赞 Eric Postpischil 3/10/2022
语言中没有内置任何内容,性能优化对上下文高度敏感,您没有提供任何信息,并且,如果目标处理器具有提供单独的小于、等于和大于信息的比较指令,则编译器可能会在给定所示代码的情况下使用它,前提是启用了优化。
1赞 Ted Lyngmo 3/10/2022
“10 个 32 位整数,形成一个非常长的整数,超出了任何原生类型所能达到的范围”并假设大端序:怎么样?如果大整数是无符号的,它应该可以工作。memcmpuint32_t a[10] = {1}, b[10] = {2}; printf("%d\n", memcmp(a, b, sizeof a));
0赞 MrArsGravis 3/10/2022
@TedLyngmo我还没有听说过,这实际上听起来很有用——但不幸的是,这个系统实际上是小端序的(这让我很懊恼),我只是在使用大端序来避免我给出的例子过于复杂......看来得到没有多大用处呢?memcmpmemcmp
0赞 Ted Lyngmo 3/10/2022
@MrArsGravis 在一个小端系统上使用之前,您必须反转两个数组中的字节(而不是 s 的顺序)。反转它们可能也很快,但也许最好编写一个类似 -like 函数,从末尾和从头到尾进行比较,并希望优化器能做得很好。uint32_tmemcmpmemcmpuint8_t
1赞 Jérôme Richard 3/10/2022
请注意,GMP可以非常有效地处理大量数据并实现这样的事情。除此之外,在 x86-64 平台上反转字节的速度非常快,因为有一个指令。SIMD 指令也可用于加快计算速度(尽管两个数字几乎相等的概率肯定很小)。无分支实现也应该解决您的问题。

答:

0赞 Vlad Feinstein 3/10/2022 #1

看来你的担忧(有不止一个比较)是没有根据的。

该指令设置 FLAG 寄存器,并且两个条件跳转都基于这些标志执行。ASMCMP

请参阅 https://godbolt.org/z/rfxP185Mf