【问题标题】:Make a number 1 if greater than 0 [closed]如果大于 0,则为 1 [关闭]
【发布时间】:2012-07-29 03:09:55
【问题描述】:

我正在尝试优化一些代码,这看起来很简单,但给我带来了困难。 所以基本上,我试图将一个数字设为 1,如果它大于 0。 问题是我不想使用 任何 比较,因为它们非常昂贵,并且在没有比较的情况下获得解决方案将为我节省 40 秒,因为它被调用了很多。所以我想要的只是位运算符,加、减、除和乘。

额外:数字永远只有 1 或 2。

类型是unsigned int

完整算法:

        DWORD num = (blockNum / 0xAA) * blockStep[0];

        switch (blockNum / 0xAA)
        {
            case 0:
                return num + hashOffset;

            default:

                num += ((blockNum / 0x70E4) + 1) << (BYTE)packageSex;
                switch (blockNum / 0x70E4)
                {
                    case 0:
                        return num + hashOffset;

                    default:
                        return num + (1 << (BYTE)packageSex) + hashOffset;
                }
        }

【问题讨论】:

  • 如果数为2,则变为1。如果为1,则仍为1,有什么区别?
  • 类型是无符号整数。另外,如果只有位运算符为 2,我将如何使数字为 1?
  • 班次。但我不确定你如何知道是否需要换档,除非你进行比较。
  • 是的,这就是问题所在。我避免进行任何比较。
  • 你的要求太荒谬了。如果不进行某种比较,就无法判断一个数字是否大于零。这个问题甚至没有意义,简单的整数CMP 操作并不昂贵。这是一个毫无意义的优化案例。

标签: c math optimization


【解决方案1】:

这段代码 sn -p 产生你想要的效果。我检查了程序集输出(MSVC++ 2010),它是无分支的。

n = !!n;

【讨论】:

  • 非常好的,无符号整数的完美解决方案。当您打开优化时会发生什么,我可以看到它可能会在哪里得到优化。 volatile 在这里有帮助吗?
  • 这是一个很好的解决方案,但它仍然可以进行比较。话虽如此,这也很慢。
  • 你确定吗,理想情况下这将是寄存器上的两条非汇编指令
  • 我没有看过程序集,但我想编译器决定做一个CMP eax, 0并将寄存器设置为NZ标志会比两个NOT快.这仍然是无分支的,所以我所说的仍然存在 (它是分支,而不是 CMP 的,可能很昂贵)See also.
  • 恕我直言,我建议您不要采取“这非常慢”的立场,而应该像我们其他人一样采取“我可能在做一些愚蠢的事情”的立场。跨度>
【解决方案2】:

如果保证只能是1或者2,那么这个就很简单了:

1: 0001 2:0010

通过对自身应用右移和 OR,两者都用 1 屏蔽,它将始终为 1

假设数字存储在 val 中,然后

val = (val | val>>1) & 1

【讨论】:

  • 在我之后得到它 :) 还是谢谢。
  • 嘿,我快了 20 秒 ;-)
  • 这不起作用。 2 | (2>>1) = 2 | 1 = 3。
  • 该死,我不应该在凌晨 5:30 发帖,你说得对,我会修复它..
【解决方案3】:
(num & 1) | ((num & 2) >> 1)

适用于我正在尝试做的事情,即值 1 和 2。它也适用于更多值,但这不是我关心的问题。

【讨论】:

    猜你喜欢
    • 2016-07-21
    • 2021-09-27
    • 1970-01-01
    • 2017-08-10
    • 1970-01-01
    • 1970-01-01
    • 2021-06-05
    • 1970-01-01
    • 2020-01-19
    相关资源
    最近更新 更多