为何使用Math.pow的这段代码会输出"HELLO WORLD"?
拆解这段“藏字符”的趣味代码
先把代码和它的神奇输出摆出来:
long[] c = {130636800L, -5080148640L, 13802573088L, -14974335980L, 8683908340L, -3006955245L, 651448014L, -89047770L, 7457160L, -349165L, 6998L}; for (int x = 0; x < 11; x++) { long s = 0; for (int i = 0; i < 11; i++) s += c[i] * Math.pow(x, i); System.out.print((char)(s / 1814400)); }
运行后输出:
HELLO WORLD
核心逻辑:用多项式插值藏明文
这段代码的本质是多项式插值的逆向玩法:
我们知道,11个不同的点可以唯一确定一个10次多项式。这里的作者就利用了这个数学特性:
- 把
HELLO WORLD的每个字符ASCII值(H=72、E=69、L=76……D=68)对应到x从0到10的11个“结果点” - 为了让多项式系数都是整数(避免浮点误差),先把每个ASCII值乘以了1814400这个公共倍数
- 然后反向求出了这个10次多项式的系数,就是你看到的那堆看起来杂乱无章的
long[] c数组
拿x=0的情况举个直观的例子:
当x=0时,所有x^i(i>0)都是0,所以s就等于c[0],也就是130636800。除以1814400之后正好是72,对应字符'H'——完美命中第一个输出。
这是加密吗?完全不是!
别误会,这跟加密一点不沾边:
加密需要有密钥、可逆性、保密性这些核心特性,但这段代码只是把明文通过数学手段“伪装”成了一堆系数,本质是代码混淆类的趣味小把戏。只要有人愿意花几分钟反向计算,分分钟就能还原出原字符序列。
说白了,就是有人刻意构造出来的编程趣味题——用数学包装一下,让代码看起来高深莫测,运行后却输出意料之外的明文。
想自己写类似代码?其实不难
要是你也想整这么一手,步骤很清晰:
- 确定要输出的字符,把每个字符转成ASCII值,再乘以一个足够大的整数(确保后续求出的系数都是整数)
- 把x从0到n-1(n是字符数)作为自变量,乘以倍数后的ASCII值作为因变量,求解n-1次多项式的系数
- 把系数写成数组,再写个循环计算多项式值、除以倍数、转成字符输出就行
内容的提问来源于stack exchange,提问作者honk
相关产品推荐
相关产品推荐

