【问题标题】:What is the point of doing bitwise shifting here?在这里进行按位移位有什么意义?
【发布时间】:2013-08-05 14:56:30
【问题描述】:

我找到了这个用于快速 I/O 的代码。

    #include <cstdio>

inline void fastRead_int(int &x) {
    register int c = getchar_unlocked();
    x = 0;
    int neg = 0;

    for(; ((c<48 || c>57) && c != '-'); c = getchar_unlocked());

    if(c=='-') {
        neg = 1;
        c = getchar_unlocked();
    }

    for(; c>47 && c<58 ; c = getchar_unlocked()) {
        x = (x<<1) + (x<<3) + c - 48;
    }

    if(neg)
        x = -x;
}

inline void fastRead_string(char *str)
{
    register char c = 0;
    register int i = 0;

    while (c < 33)
        c = getchar_unlocked();

    while (c != '\n') {
        str[i] = c;
        c = getchar_unlocked();
        i = i + 1;
    }

    str[i] = '\0';
}

int main()
{

  int n;
  char s[100];

  fastRead_int(n);
    printf("%d\n", n);

  fastRead_string(s);
    printf("%s\n", s);
  return 0;
}

为什么会有位移 (x

【问题讨论】:

  • 没有任何上下文或函数正在做什么,很难知道这些按位运算在做什么。如果有帮助的话,左移一位与乘以 2 相同,左移三位与乘以 8 相同。
  • 我已经添加了完整的代码。这是博文:digital-madness.in/blog/2013/fast-io-in-c/#comment-2137 基本上这种方法用于竞争性编程以实现更快的 I/O。
  • (x&lt;&lt;1) + (x&lt;&lt;3) 等于乘以 10。如果你用十进制表示一个数字,那就是“左屎”(例如:12 * 10 = 120)。 c - 48 在末尾添加新数字。
  • 不就是简单的乘以10(8x + 2x = 10x)吗?我敢打赌,如果有益的话,编译器可以做这种优化。
  • 考虑两个值的简单输入。 '2''3'。从x=0 开始,第一遍只将2 存储在x 中。第二遍会将3 添加到值(2&lt;&lt;1 + 2&lt;&lt;3),即(4+16) + 3(20) + 3。 IE。 23. 换句话说,这是将前一个值乘以10,然后将下一个字符添加为十进制个位数。

标签: c++ c io bitwise-operators


【解决方案1】:

为什么会有位移 (x

左移n位相当于乘以2^n;所以这个表达式相当于乘以十(因为2^1 + 2^3 = 2 + 8 = 10)。

代码是这样编写的,因为 (a) 移位和加法比乘法快得多,并且 (b) 编译器不知道乘以 10 的最佳方法。对于大多数现代平台来说,这两个假设都是错误的,所以直截了当

x = x*10 + c - '0';    // '0' is more readable, and portable, than 48.

可能会更快,也更易读。

当我们输入除 neg 和 numbers 以外的字符时会发生什么?

第一个循环跳过除“-”和数字以外的任何内容;第二个在遇到非数字时停止(在从流中消耗该字符之后)。因此它将返回它在输入流中找到的第一个十进制整数,如果没有则返回零。例如,如果输入是

xxxx123-456xxx-1234xxx

第一个调用将返回123,第二个返回456(因为- 已被第一个调用消耗),第三个-1234,以及任何进一步的调用0

【讨论】:

  • 每个人都认为自己比编译器聪明。
  • 消耗一个额外字符的好地方。 (可以补充一点,它也不会检查溢出,这在读取输入时非常重要。)
  • 是的,我什至没有注意到额外的消耗。算法本身已经以额外的活力伸手去拿我的咖啡。不错的收获。
【解决方案2】:

这真是糟糕的代码。首先,为什么是 48 和 57,而不是 比'0' 和'9'。关于您的问题: 按位移位用于混淆,并可能减慢 事情下来了。表达式(x &lt;&lt; 1) + (x &lt;&lt; 3) 具有相同的 数学值为10 * x。只是可读性差很多 并且可能会干扰一些编译器优化。 (上 两个班次和加法速度比 乘法,编译器将转换为 你,通常比你写出来更好,因为它知道 为什么会发生变化。) 至于你的第二个问题:代码 有问题的将跳过所有字符,直到它 找到一个数字或一个减号;它会转换类似的东西 "abc12"12,没有丝毫错误。

其实就是完全没有错误检查(和使用 getchar_unlocked,而不是 getchar) 快。

【讨论】:

  • +1 给你和迈克。发布的问题代码几乎看起来像是反汇编程序的输出,用手卷成半可理解的东西。
  • @WhozCraig 我认为迈克应该得到这个。他的解释比我的要清楚得多,并且他还发现了代码消耗一个太多字符的事实。
【解决方案3】:

该例程将读取字符值并在同一操作中将它们转换为整数值(显然要快)。这些变化有助于对值求和。组合移位等于 x10。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 2020-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多