任何人都可以为这个插口算法代码Pitiny.c做头或者故事

Bri*_*ven 4 c compression pi lossless-compression spigot-algorithm

这个C程序只有143个字符!

但它"解压缩"为Pi的前10,000位数字.

//  Created by cheeseMan on 30/11/13.

long a[35014],b,c=35014,d,e,f=1e4,g,h;

int main(int argc, const char * argv[])

{
    for(;(b=c-=14);

        h=printf("%04ld",e+d/f))

        for(e=d%=f;(g=--b*2);d/=g)
            d=d*b+f*(h?a[b]:f/5), a[b]=d%--g;
}
Run Code Online (Sandbox Code Playgroud)

当我遇到这个时,我正在做一些关于无损压缩算法的研究,但仍然没有运气pitiny.c.

奇怪的是,它成功编译没有错误或错误,但就像我说我不能成为代码的头或者故事,甚至它的语法.我想知道最近发生了什么?这究竟是做什么的?

Sha*_*our 10

更新

这个程序是Pi-Unleashed一书中针对数字Pi插头算法的故意混淆实现,我们可以在本书的第37页找到原始版本,如下所示:

a [52514],b,c = 52514,d,e,f = 1e4,g,h; main(){for(; b = c- = 14; h = printf("%04d",e + d/f))for(e = d%= f; g = - b*2; d/= g)d = d b + f(h?a [b]:f/5),a [b] = d % - G;}

本文的Pi的数字无界点算法在解释算法方面做得很好.基本上它是这种扩展的实现:

式

原版的

设计这种方式的原因除了让代码无法理解和令人印象深刻的人逃避了我,但我们可以分解正在发生的事情,首先在这里:

long a[35014],b,c=35014,d,e,f=1e4,g,h;
Run Code Online (Sandbox Code Playgroud)

变量是静态的,因为它们是全局的,因此所有未显式初始化的变量都将被初始化为0.接下来我们有一个外部for循环:

for(;(b=c-=14); h=printf("%04ld",e+d/f)
    ^ ^         ^
    1 2         3
Run Code Online (Sandbox Code Playgroud)
  1. 是一个空的初始化,它也是一个空语句.
  2. 14从中减去c并将值赋值回来c并为其分配相同的值b.这个循环将执行2500时间,因为35014/14是2501和在2501次迭代的结果0,因而,循环就会停止.
  3. h正被分配的结果printf是打印的字符数.什么被打印出的结果是e+d/f,总是至少4位和零填充由于04格式说明.

现在我们有一个内部for循环:

for(e=d%=f;(g=--b*2);d/=g)
    ^       ^        ^
    1       2        3
Run Code Online (Sandbox Code Playgroud)
  1. 初始化edd modulus f.
  2. 由于运算符优先级做了预减b,通过和倍数2和结果分配g
  3. d被划分g并分配结果.

最后是for for循环的主体:

d=d*b+f*(h?a[b]:f/5), a[b]=d%--g;
          ^         ^
          1         2
Run Code Online (Sandbox Code Playgroud)

同时使用条件运算符1逗号操作2.所以我们至少可以把它分成:

d    = d*b+f*(h?a[b]:f/5) ; // (1)
a[b] = d%--g;               // (2)
Run Code Online (Sandbox Code Playgroud)

(1) 可以进一步细分为:

long tmp =  h ? a[b] : f/5 ;  // conditional operator
d = (d * b) + f * tmp;
Run Code Online (Sandbox Code Playgroud)

条件运算符仅在第一次迭代期间h起作用,因为它是初始化的,00之后永远不会再次,因为它总是在外部for循环中h被赋予非零值,因此除了第一次以外的其他值将被分配a[b].

(2)将再次由于优先级预先递减g,然后评估d模数结果并将其分配给a[b].