使用模量添加C


81

我遇到了一个有趣的C代码,可以打印出来A + B,但是我很难理解它。

输入格式:

A B

其中AB是介于之间的整数,010用单个空格分隔。

码:

main( n )
{
    gets( &n );
    printf("%d", n % 85 - 43);
}

这是用于简短编码的,请不要在意警告。

到目前为止,我的理解是:

gets( &n )将A,空格和B的ASCII值存储在的低三字节中n。例如,A = 3B = 8将产生n = 0x00382033。给定条件可以防止n溢出。但是我不知道n % 85 - 43产量如何A + B

您如何得出这些数字?


2
确实很有趣。
Havenard '18年

12
提示85是二进制的交替位01010101。如果您尝试使用10101010编号为170的方法,则将获得类似的功能,唯一的区别在于,如果0 0改为使用编号128(10000000二进制)。类似的技术被用于做使用遮罩为位操作的优化,如在比特组比特计数数的一束如0x555555550xAAAAAAAA(0x55的= 85和和0xAA = 170)。如果您用谷歌搜索那些十六进制代码,则会得到很多有趣的文章。
Havenard '18年

哇,我没想到85会有这么多深度。感谢您的见解。
William Lee

1
我认为您的意思是介于0和9之间(含0和9)?
管道

1
那绝对值得的。
dgnuff

Answers:


87

使用小尾数整数(并假设ASCII文本和8位字节,以及代码所需的所有其他假设),并忽略代码中所有技术上错误的现代C内容,您的“我所理解的到目前为止”是正确的。

gets(&n)会将A,空格和B的ASCII值存储到的前3个字节中n。还将在第4个字节中存储一个空终止符。存储这些ASCII值成那些字节n结果n取值B*256*256 + space*256 + A,其中BspaceA表示对应的ASCII值。

256 mod 85为1,所以根据模块化算术的属性,

(B*256*256 + space*256 + A) % 85 = (B + space + A) % 85

顺便说一下,使用4字节big-endian int,我们得到

(A*256*256*256 + space*256*256 + B*256) % 85 = (B + space + A) % 85

因此字节序无关紧要,只要我们有4个字节的整数即可。(更大或更小整数可能是一个问题;例如,具有8个字节的整数,我们不得不对什么是在字节的担心ngets没有设置。)

空格为ASCII 32,数字字符的ASCII值为48 +数字的值。定义ab作为输入数字的数字值(而不是数字字符的ASCII值),我们有

(B + space + A) % 85 = (b + 48 + 32 + a + 48) % 85
                     = (a + b + 128) % 85
                     = (a + b + 43) % 85

(B + space + A) % 85 - 43 = (a + b + 43) % 85 - 43
                          = (a + b) % 85
                          = a + b

最后两个等价项依赖于a并且b取值从0到9。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.