尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

用Python验证:一张纸对折42次能到月球?揭秘指数增长

用Python验证:一张纸对折42次能到月球?揭秘指数增长 这次我们看一个流传很广的经典问题How many paper folds would get you to the moon? 翻译过来就是“一张纸对折多少次能到月球”。如果只说结论答案是 42 次前提是纸张厚度按常见 A4 打印纸 0.1 mm 计算、地月距离按平均距离 384400 km 计算。但这个问题的价值不在数字本身而在于它把“指数增长”这个概念变成了一个可以亲手算、用代码验证的数学模型。这篇文章会用 Python 把完整计算过程跑一遍先推导公式再写循环计算最少折叠次数然后用 matplotlib 画对数坐标曲线最后讨论真实折纸为什么做不到 42 次。整个过程不需要 GPU、不需要装模型只需要 Python 3.8 和两个常用库。适合算法入门、科普写作、以及想用具体案例讲“指数爆炸”的程序员和老师。我会按“问题速览 → 数学模型 → 环境准备 → Python 实现 → 数值结果 → 物理限制 → 算法关联 → 排查清单 → 最佳实践”的顺序展开。先说结论成立的条件再去验证它。1. 问题速览纸折叠多少次能到月球先把核心规格列出来这样后面写代码时不会跑偏。参数说明问题本质指数增长估算核心公式折叠 n 次后厚度 初始厚度 × 2^n初始厚度常见 A4 打印纸约 0.1 mm不同纸张有差异目标距离地月平均距离约 384400 km计算结果0.1 mm 纸需要折叠 42 次是否实际可操作否普通纸张约 7~8 次后已很难继续折叠是否需要显卡不需要实现语言Python 3.8只需要 math / matplotlib / numpy这里需要特别说明“42 次”依赖两个前提纸厚是 0.1 mm距离是平均地月距离。如果你换成 0.05 mm 的薄纸需要 43 次换成 0.2 mm 的卡纸41 次就够了。所以回答问题时一定要说明使用的是哪组参数。表格里“普通纸张约 7~8 次后已很难继续折叠”指的是常规 A4 纸、人力折叠的常见体验。可查证的极端折叠纪录在 12 次左右使用的是超长卫生纸等特殊材料具体纪录数字要以发布机构的原始资料为准。2. 适用场景与使用边界这个计算不是工程问题而是一个数学建模和科普演示问题。它适合以下几类场景用具体数字说明“指数增长”的威力。在算法课中引出对数、二分搜索和复杂度分析。在 Python 课上练习 while 循环、单位换算、浮点数处理和 matplotlib 绘图。作为数据可视化案例展示线性坐标与对数坐标的区别。不适合把它当作真实可执行的操作。按理想模型0.1 mm 的纸折叠 42 次后厚度约为 439804 km已经超过地月平均距离但现实中没有任何纸张能保持 0.1 mm 厚度完成 42 次折叠因为纸的面积会随折叠次数呈指数缩小材料强度也不允许。另一个边界是“地月距离不是常数”。月球绕地球的轨道是椭圆近地点约 363300 km远地点约 405500 km平均约 384400 km。普通科普答案采用平均距离如果你要严格到达某个具体时间点的月球需要重新查轨道数据。这类计算只适合教学演示不用于航天工程。如果是用纸模型、折纸动画或科普视频展示还要注意版权引用别人的实验图片、动图时必须获得授权。本文只做数值计算不涉及版权素材。3. 数学模型为什么是 42 次把一张纸对折一次厚度变为原来的 2 倍对折 n 次厚度为T_n T_0 * 2^n其中 T_0 是初始厚度T_n 是折叠 n 次后的厚度。地月平均距离为D 384400 km 384400 × 1000 m 384400 × 10^6 mm 3.844×10^11 mm若 T_0 0.1 mm求满足条件的最小 n0.1 × 2^n ≥ 3.844×10^11两边取以 2 为底的对数n ≥ log2(3.844×10^12)计算得到 log2(3.844×10^12) ≈ 41.81向上取整得到 n 42。折叠 41 次时厚度为0.1 × 2^41 ≈ 219902 km小于 384400 km。折叠 42 次时0.1 × 2^42 ≈ 439805 km大于 384400 km。所以最小折叠次数是 42 次。这个公式可以反向使用给定目标距离和纸张厚度计算需要的折叠次数n ceil(log2(D / T_0))其中 D 和 T_0 必须使用相同单位。这是后面写 Python 函数的核心。要注意的是如果初始厚度不是 0.1 mm结果会变化。比如 0.05 mm 的薄纸需要 43 次0.2 mm 的卡纸需要 41 次。不要死记“42”要记住公式和条件。4. 环境准备Python 算法环境这个项目的计算很简单不需要 GPU、不需要 OpenCV、不需要 PyTorch只需 Python 3.8 以上以及两个绘图库 numpy 和 matplotlib。pip install numpy matplotlib建议在项目目录下创建独立虚拟环境python -m venv venv source venv/bin/activate # Windows 下为 venv\Scripts\activate pip install numpy matplotlib如果只是跑数字计算连 numpy/matplotlib 都不需要标准库 math 就够。可视化部分才用到这两个库。目录结构建议paper_fold_to_moon/ ├── fold_calculator.py ├── plot_folding.py └── output/ └── fold_to_moon.png把“计算”和“绘图”拆成两个文件避免以后想复用公式时还要连带处理画图代码。实际项目中把业务逻辑和展示逻辑分离是基本习惯。5. Python 实现从循环到函数5.1 用 while 循环计算最少折叠次数第一种方式最直观从初始厚度开始每次厚度乘 2直到超过地月距离。# fold_calculator.py MOON_DISTANCE_KM 384_400 # 地月平均距离单位: km KM_TO_MM 1_000_000 # 1 km 1_000_000 mm target_distance_mm MOON_DISTANCE_KM * KM_TO_MM paper_thickness_mm 0.1 # 常见 A4 纸厚度单位: mm thickness paper_thickness_mm folds 0 while thickness target_distance_mm: thickness * 2 folds 1 print(f最少折叠次数: {folds}) print(f此时厚度: {thickness / KM_TO_MM:.2f} km)运行结果为最少折叠次数: 42 此时厚度: 439804.65 km这个循环很好理解但每次重新计算时都要改变量。更好的方式是把计算封装成函数。5.2 封装成可复用的函数import math MOON_DISTANCE_KM 384_400 KM_TO_MM 1_000_000 def required_folds(paper_thickness_mm: float, distance_km: float MOON_DISTANCE_KM) - int: 计算一张纸折叠到指定距离所需的最小次数。 if paper_thickness_mm 0: raise ValueError(纸张厚度必须大于 0) if distance_km 0: raise ValueError(目标距离必须大于 0) distance_mm distance_km * KM_TO_MM folds 0 current_thickness paper_thickness_mm while current_thickness distance_mm: current_thickness * 2 folds 1 return folds def required_folds_by_log(paper_thickness_mm: float, distance_km: float MOON_DISTANCE_KM) - int: 用对数公式计算所需次数结果应与 required_folds 一致。 if paper_thickness_mm 0: raise ValueError(纸张厚度必须大于 0) distance_mm distance_km * KM_TO_MM return max(0, math.ceil(math.log2(distance_mm / paper_thickness_mm))) if __name__ __main__: for thickness in [0.05, 0.08, 0.1, 0.2, 0.5]: folds required_folds(thickness) print(f纸厚 {thickness} mm - 折叠 {folds} 次)这里的 math.log2 在 Python 3.3 之后可用。distance_mm / paper_thickness_mm 会得到约 3.844×10^12 这种大数log2 后得到小数再用 math.ceil 向上取整。注意浮点数误差在极端情况下可能导致整数边界判断出错所以教学演示用 while 循环更稳妥。5.3 输出厚度增长过程如果想看每折叠一次厚度变化多少可以返回一个列表def thickness_sequence(paper_thickness_mm: float, max_folds: int): sequence [] current paper_thickness_mm for i in range(max_folds 1): sequence.append(current) current * 2 return sequence # 输出前 5 次和后 3 次的厚度 seq thickness_sequence(0.1, 42) for i in [0, 1, 2, 3, 4, 40, 41, 42]: print(f折叠 {i} 次: {seq[i] / KM_TO_MM:.6f} km)输出折叠 0 次: 0.000000 km 折叠 1 次: 0.000000 km 折叠 2 次: 0.000000 km 折叠 3 次: 0.000000 km 折叠 4 次: 0.000000 km 折叠 40 次: 109951.162778 km 折叠 41 次: 219902.325555 km 折叠 42 次: 439804.651110 km前几次的厚度在 km 单位下几乎为 0所以可视化时要用对数坐标否则前面的点全部被压扁。6. 数值结果与可视化验证6.1 不同折叠次数对应的厚度以 0.1 mm 初始厚度、地月平均距离 384400 km 为例几个关键节点的厚度如下折叠次数厚度km与地月距离对比00.0000001 km0.1 mm极短100.1024 km约为地月距离的 1/375390520104.8576 km远小于地月距离30107374.1824 km约为地月距离的 1/440109951.1628 km约为地月距离的 1/3.541219902.3256 km约 57%42439804.6511 km超过地月平均距离这里可以直观看到前 30 次基本都在地球附近最后两次直接跨过地球到月球的大半距离。指数增长的恐怖在于“后面每一步都在重复前面所有步的总和”。6.2 使用 matplotlib 绘制对数曲线线性坐标下前 30 次的高度几乎贴着 0看不出趋势。改用对数坐标后增长曲线会变成一条直线这也是指数函数在对数坐标下的典型特征。# plot_folding.py import numpy as np import matplotlib.pyplot as plt MOON_DISTANCE_KM 384_400 KM_TO_MM 1_000_000 paper_thickness_mm 0.1 max_folds 42 folds np.arange(0, max_folds 1) thickness_km paper_thickness_mm * (2 ** folds) / KM_TO_MM plt.figure(figsize(10, 6)) plt.plot(folds, thickness_km, markero, linewidth2, label纸张厚度) plt.axhline(MOON_DISTANCE_KM, colorred, linestyle--, linewidth1.5, label地月平均距离 384400 km) plt.yscale(log) plt.xlabel(折叠次数) plt.ylabel(厚度km对数坐标) plt.title(纸张折叠次数与厚度增长曲线) plt.grid(True, whichboth, linestyle--, alpha0.6) plt.legend() plt.tight_layout() plt.savefig(output/fold_to_moon.png, dpi150)运行后output 目录下会生成 fold_to_moon.png。曲线在第 42 次时超过红色虚线这就是“42 次到月球”的图形化证据。6.3 不同纸张厚度的对比如果想在设计文档或课堂材料中展示“结论依赖假设”可以跑一张对比表纸张类型参考初始厚度mm最少折叠次数薄宣纸/低定量纸0.0543常见打印纸0.1042厚打印纸/卡纸0.2041薄纸板0.5040“纸张类型参考”只是粗略分类不同品牌和工艺差异很大。这里展示的是同一个公式在不同参数下的结果。实际应用时应测量自己手边纸张的厚度再计算。7. 现实物理限制为什么折不到 42 次模型里只考虑了厚度翻倍忽略了纸的面积、长度、强度和折痕处的应力。真实折纸要同时满足三个条件每次折叠后纸的面积减半。折叠 n 次后面积变为初始面积的 1/2^n。42 次后面积只有初始面积的 1/4.4×10^12远远小于一个原子尺度的概念。纸的长度需要足够。每次对折后至少有一边的长度会减半。如果初始纸不够长折到后面根本没有可用于折叠的“把手”。纸有厚度和强度上限。层数越多折痕处承受的应力越大材料会撕裂或断裂。所以理想模型的“42 次”是有条件成立的它假设纸张可以被无限压缩、无限延伸、忽略材料形变。现实中最常见的说法是“普通纸最多折叠 7~8 次”这是因为普通 A4 纸面积有限。公开资料中有团队用超长卫生纸创造过折叠 12 次左右的纪录但这类实验需要特殊材料和多人协作不能说明普通纸张可以达到。如果非要模拟真实折叠需要引入更复杂的模型每一折后的层数、纸长、折痕半径、材料受力。普通科普和算法演示不必走到这一步但要清楚模型边界。物理上还有一个值得注意的点即便能把纸折叠 42 次最终得到的是一个非常细长、极端高密度的“纸柱”而不是一块能稳定站立的“纸塔”。材料和结构都远超日常经验。8. 从折纸到计算机科学为什么指数思维很重要“纸折叠多少次能到月球”之所以值得写代码不只是为了一个答案。它背后是整个计算机科学都在使用的指数思维。二分查找算法的时间复杂度为 O(log n)本质和“每次对折丢一半”一样。假如有一个包含 2^32 个元素的有序数组顺序查找最坏要 42.9 亿次二分查找只需要约 32 次。折纸中的 2^n 是同一个指数模型的反向使用。理解 2^n 的爆炸速度才能理解为什么 32 位整数最大约 21 亿、为什么浮点数超过一定范围会变成 inf、为什么某些递归深度达到 1000 次就崩掉。折纸问题把所有抽象的复杂度概念变成了一个可以亲手摸到的物理过程。在实际编码中指数增长还提醒我们注意“溢出”。Python 的整数可以无限制增长但浮点数在超过约 1.8×10^308 后会显示 inf。如果用 float 做很深的指数计算需要提前判断数量级。比如把 0.1 毫米折到 1000 次厚度会轻松超过可观测宇宙范围再用 float 就会出现无穷大。如果需要处理超大整数运算也可以使用 Python 的 int 配合整除避免浮点误差def required_folds_exact(paper_thickness_nanometer: int, distance_km: int) - int: 用整数避免浮点误差输入单位改为纳米。 distance_nm distance_km * 1_000_000_000_000 # 1 km 10^12 nm current paper_thickness_nanometer folds 0 while current distance_nm: current * 2 folds 1 return folds # 0.1 mm 100000 nm print(required_folds_exact(100_000, 384_400))单位换算1 mm 1_000_000 nm所以 0.1 mm 100_000 nm1 km 1_000_000_000_000 nm。这个整数版本理论上可以计算任意折叠次数只要 Python 内存够。9. 常见问题与排查方法问题现象可能原因排查方式解决方案算出来是 42但别人说是 43纸厚或地月距离取值不同确认初始厚度和距离参数统一单位后重新计算不同参数会产生不同结果程序循环一直不停止目标距离单位换算错误打印当前厚度和目标厚度检查 km 与 mm 的换算先用已知值单步测试折到一定次数时显示 inf浮点数溢出打印最后一次迭代的厚度改用 Python 整数或提前限制循环次数matplotlib 画出的点全挤在横轴上线性坐标无法展示指数增长查看厚度数量级使用 plt.yscale(log)运行 import matplotlib 报错未安装依赖或环境未激活pip list 查看已装库按第 4 节在虚拟环境安装 numpy matplotlib结果和网上的图不一致地月距离取平均/近地点/远地点不同检查代码中的 MOON_DISTANCE_KM 常量明确注明使用的是平均距离 384400 kmPython 版本过低无法用 math.log2Python 3.3 以下python --version升级到 Python 3.8 或改用 math.log(x) / math.log(2)最常见的坑就是单位。km、m、mm、nm 一旦混用结果会差 1000 倍甚至 100 万倍。建议把所有长度统一到同一个单位后再写进公式。另一个坑是“向上取整”和“刚好相等”的问题。如果折叠后的厚度刚好等于地月距离需要 ceil 处理。实际计算中几乎不会出现刚好相等但工程上要写明“大于等于目标距离”。10. 最佳实践与使用建议如果你要把这个例子用于教学、博客或算法演示建议按下面的方式组织代码用常量保存地月距离和初始厚度不要散落在函数里。用一个函数返回“最少折叠次数”一个函数返回“厚度序列”。先写 while 循环版本再用 math.log2 版本做交叉验证。把输出单位固定为 km并在打印时保留足够小数点。画图时使用对数坐标并标注地月距离参考线。参数化设计比如允许传入纸厚和距离方便做对比实验。第一次运行时先用小规模参数验证比如计算“折到一层楼高需要几次”确认程序逻辑正确后再换成地月距离。这样能快速定位单位错误。如果是团队协作或长期维护可以把输入参数放到 JSON 配置文件中{ paper_thickness_mm: 0.1, target_distance_km: 384400, max_folds: 50, output_image: output/fold_to_moon.png }程序读取 JSON 后计算后续改参数不需要改代码。具体 JSON 解析代码可以根据项目需要扩展。如果你要发布效果图或录屏记得在图上标明“理想模型忽略纸张面积和材料强度”避免读者误以为真实折纸可以做到。涉及引用他人的折纸实验照片或视频时必须获得授权或使用开放版权素材。11. 总结与下一步How many paper folds would get you to the moon? 的核心答案是 42 次但更有价值的不是这个数字而是背后的推导和验证过程建立指数模型、统一单位、用代码计算、用对数图展示、最后识别模型的物理边界。建议你先把 while 循环版本跑通再看可视化输出最后把纸厚参数改成 0.05 mm 和 0.2 mm 对照观察次数变化这样能彻底理解指数增长的含义。下一步可以扩展的方向有很多把二维折纸推广到三维分形结构、用递归函数模拟折纸过程、研究“折纸次数与纸张长度”的关系、或者把这个模型放到 Web 页面上做一个交互式计算器。无论往哪个方向走先记住指数增长不是慢慢变大而是最后几步直接改变量级。建议把这段 Python 脚本保存到自己的工具库里下次讲复杂度或指数爆炸时直接拿出来跑一遍。收藏备用。
返回列表