热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用更快的I/O方法-workingofafasterI/Omethod

IwasstudyingfasterIOmethodsforprogrammingproblems,Ifoundoutthismethodofusinggetchar

I was studying faster I/O methods for programming problems, I found out this method of using getchar_unlocked() (though risky but still).

我正在研究编程问题的速度更快的I / O方法,我发现这种使用getchar_unlocked()的方法(尽管有风险但仍然存在)。

I looked around quite a bit but couldn't get how it scanned an integer value or in other words what do the 4 lines mean and how they work in the scanint() function defined below

我环顾四周但是无法知道它是如何扫描整数值的,或者换句话说是4行是什么意思以及它们如何在下面定义的scanint()函数中工作

#include
#include
#define gc getchar_unlocked

void scanint(int &x)
{
    register int c = gc();
    x = 0;
    for(;(c<48 || c>57);c = gc());
    for(;c>47 && c<58;c = gc())   
        {x = (x<<1) + (x<<3) + c - 48;}
}

int main()
{   
    int n,k;
    scanint(n);
    scanint(k);
    int cnt=0;
    while(n--)
    {
     int num;
     scanint(num);
     if(num%k==0)cnt++; 
    }    
    printf("%d",cnt);
    return 0;             
}

3 个解决方案

#1


1  

ASCII value of '0' is 48, and each subsequent digit goes one more. i.e. '1'->49, '2'->50... and so on.

ASCII值“0”为48,每个后续数字再增加一个。即'1' - > 49,'2' - > 50 ......依此类推。

A side effect of this is that if you take a character digit, meaning something between '0' and '9', and subtract the ASCII value of '0' from it, then you get the integer value of that digit.

这样做的副作用是,如果你取一个字符数字,意思是'0'和'9'之间的某个东西,并从中减去ASCII值'0',那么你得到该数字的整数值。

So in the line x = (x<<1) + (x<<3) + c - 48;, the c-48 part is converting the digit character (an ASCII coded character) into a number between 0-9 that refers to that character.

所以在x =(x <<1)+(x <<3)+ c-48;行中,c-48部分将数字字符(ASCII编码字符)转换为0-9之间的数字那个角色。

(x<<1)+(x<<3) is the same as x * 10,(For more information, checkout http://en.wikipedia.org/wiki/Multiplication_algorithm#Shift_and_add and How can I multiply and divide using only bit shifting and adding? ) in fact this part of the code is unnecessarily obfuscated. The compiler can optimize multiplication in many different ways to make it as fast as possible, so we don't need to manually implement the bit shifting. It makes for an interesting college level puzzle though.

(x <<1)+(x <<3)与x * 10相同,(有关更多信息,请查看http://en.wikipedia.org/wiki/Multiplication_algorithm#Shift_and_add以及如何使用乘法和除法只有位移和添加?)实际上这部分代码是不必要的混淆。编译器可以通过多种不同的方式优化乘法,使其尽可能快,因此我们不需要手动实现位移。尽管如此,这也是一个有趣的大学级拼图。

for(;(c<48 || c>57);c = gc()); This loop will ignore all the characters until it receives one that falls within the '0' to '9' range. So if the user started by typing a space or any other character, it'll simply be ignored.

for(;(c <48 || c> 57); c = gc());该循环将忽略所有字符,直到它收到一个落在'0'到'9'范围内的字符。因此,如果用户通过键入空格或任何其他字符开始,则只会被忽略。

By the time the code hits for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;} line, the variable c is already initialized to the first digit that the user has typed. This loop leaves the initialization empty so the control flow will dive right into the loop and start computing the number as each character is typed.

当代码命中(; c> 47 && c <58; c = gc()){x =(x <<1)+(x <<3)+ c - 48;}行时,变量c已初始化为用户键入的第一个数字。此循环使初始化为空,因此控制流将直接进入循环并在键入每个字符时开始计算数字。

The loop will go on as long as the user keeps typing digits, as soon as the user types something other than a digit, the loop will terminate, finalizing the number.

只要用户输入数字,循环就会继续,只要用户输入除数字以外的内容,循环就会终止,最终确定数字。

Until the user keeps typing digits, the line x = (x<<1) + (x<<3) + c - 48; will keep getting executed over and over again, with each time c being the character just typed. And x will multiply itself by 10 and add the new digit in.

直到用户保持键入数字,行x =(x <<1)+(x <<3)+ c - 48;将继续一次又一次地执行,每次c都是刚输入的角色。 x将自己乘以10并添加新数字。

Let's say the user types 2014. Here's how the values in c and x will progress.

假设用户输入2014.这是c和x中的值将如何进展。

c = '2' #ASCII value 50
x = 2
c = '0' #ASCII value 48
x = 20
c = '1' #ASCII value 49
x = 201
c = '4' #ASCII value 52
x = 2014

HTH.

#2


4  

The code has hard-coded ASCII values for the chars '0' and '9', so it skips over anything which does not lie in that range (the first for loop in the four lines of interest to you).

代码具有字符'0'和'9'的硬编码ASCII值,因此它会跳过不在该范围内的任何内容(对于您感兴趣的四行中的第一个循环)。

Then while it sees characters in the '0' - '9' range it multiplies its running total by 10 (by shifting it left once to double it, then adding that to itself shifted left three times, which is like multiplying by 8) and adds the current char - the code for '0'.

然后当它看到'0' - '9'范围内的字符时,它将其运行总数乘以10(通过将其向左移动一次使其加倍,然后将其添加到自身左移三次,这就像乘以8)并且添加当前char - '0'的代码。

#3


1  

The line

for(;(c<48 || c>57);c = gc());  

reads the characters which are not in between '0' to '9'.

读取不在'0'到'9'之间的字符。

The line

for(;c>47 && c<58;c = gc())   

reads the characters between '0' to '9' one by one.

逐个读取'0'到'9'之间的字符。

The line

{x = (x<<1) + (x<<3) + c - 48;}   

is simply equivalent to

简直相当于

x = 10 * x + c - 48;  

A simplified version of this function can be rewritten as:

此功能的简化版本可以重写为:

#define gc getchar_unlocked
int read_int()
{
    char c = gc();
    while(c<'0' || c>'9')
       c = gc();
    int ret = 0;
    while(c>='0' && c<='9')
    {
        ret = 10 * ret + c - 48;
        c = gc();
    }
    return ret;
}  

推荐阅读
author-avatar
初始化
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有