在我们计算高精度加减乘除时,因为无法用long long
读入一个很大很大的数,所以我们先用读入字符串的方式读入,然后再将字符串的每一位转换成数字。
下面是最常见的转换代码:
char sa[100];
int a[100];
int len;
gets(sa);
len=strlen(sa);
for(int i=0;i<len;i++)
a[len-i-1]=sa[i]-48;//字符的ASCLL码值减去48即为那一位的数字
//48是字符'0'的ASCLL码值
接下来我们介绍一种比上述方法更为快速的转换方法:
众所周知,位运算的速度比加减乘除啥的更快,所以,其实我们可以用一种极其有趣(玄学)的方法。
a[len-i-1]=sa[i]-48 --> a[len-i-1]=sa[i]^48
你肯定要问为啥(毕竟我刚看到这种的方法就懵了),异或能和减一样?
其实能做到这样的效果都是因为 48 48 48这个数有点小特殊。
众所周知, 48 48 48的二进制数为 110000 110000 110000。假设我们要将字符 ′ 5 ′ '5' ′5′转换成数字 5 5 5,首先我们都知道, ′ 5 ′ '5' ′5′的 A S C L L ASCLL ASCLL值为 53 53 53,转换成二进制即为 110101 110101 110101。其次,异或的运算规则是,每一位二进制位相同为 0 0 0,不同为 1 1 1,所以 110000 x o r 110101 110000xor110101 110000xor110101为 101 101 101,而这个数转换成十进制就是 5 5 5,因此异或 48 48 48,就相当于减去 48 48 48了。
注意点:我们上述的技巧适用于字符 ′ 0 ′ '0' ′0′~ ′ 9 ′ '9' ′9′转换成数字,若是其他字符映射成数字可能并不成功。
我再讲一个我觉得十分炫酷的位运算小技巧:
如果你要计算一个数乘以
10
10
10,再用
a
∗
10
a*10
a∗10,就太low了,你应该用:a=(a+a<<2)<<1;
附:位运算:
与(
a
n
d
and
and,&):都为1为1
或(
o
r
or
or,|):都为0为0
非(
n
o
t
not
not,~):若1则0,若0则1
异或(
x
o
r
xor
xor,^):不同为1,相同为0
移位:
左移:
1
<
<
n
=
2
n
1<<n=2^n
1<<n=2n,
n
<
<
1
=
n
∗
2
n<<1=n*2
n<<1=n∗2
右移:
n
>
>
1
=
n
/
2
n>>1=n/2
n>>1=n/2(下取整)
完结撒花!