<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>Hikari</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>https://blog.hikari233.qd.je/</id>
  <link href="https://blog.hikari233.qd.je/" rel="alternate"/>
  <link href="https://blog.hikari233.qd.je/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, Hikari</rights>
  <subtitle>记录与分享技术、建站与生活</subtitle>
  <title>Hikari's Blog 光的个人博客</title>
  <updated>2026-10-24T06:48:08.772Z</updated>
  <entry>
    <author>
      <name>Hikari</name>
    </author>
    <category term="技术杂谈" scheme="https://blog.hikari233.qd.je/categories/%E6%8A%80%E6%9C%AF%E6%9D%82%E8%B0%88/"/>
    <category term="hexo主题" scheme="https://blog.hikari233.qd.je/tags/hexo%E4%B8%BB%E9%A2%98/"/>
    <category term="前端设计" scheme="https://blog.hikari233.qd.je/tags/%E5%89%8D%E7%AB%AF%E8%AE%BE%E8%AE%A1/"/>
    <category term="技术杂谈" scheme="https://blog.hikari233.qd.je/tags/%E6%8A%80%E6%9C%AF%E6%9D%82%E8%B0%88/"/>
    <content>
      <![CDATA[<p>Ladies and gentlemen,now introduce the hexo theme——restart-fluent.</p><p><img src="/images/pages/2026-10-24-p1.png" alt="主题图片" title="restart-fluent主题截图"></p><p>欢迎来到新的博客视觉设计——Fluent Design。这个主题可能将在未来发布到github。<del>目前设计太过粗糙，移动设备适应性不好，所以暂未发布</del><br>对于Fluent Design大家肯定都很熟悉，在win10的UWP和各种系统应用中都见过这套UI设计风格。这篇文章不仅仅是为了告诉你我的博客从简洁的扁平化转到Fluent Design，还想借着这个机会讲讲Fluent Design的历史。</p><h1 id="Windows-10-Fluent-Design-设计风格杂谈"><a href="#Windows-10-Fluent-Design-设计风格杂谈" class="headerlink" title="Windows 10 Fluent Design 设计风格杂谈"></a>Windows 10 Fluent Design 设计风格杂谈</h1><p>2017 年，微软在 Build 大会上正式发布了 <strong>Fluent Design System（流畅设计体系）</strong>，内部代号 “Project Neon”。它接替了 Windows 8 时代以“内容优先、极致扁平”著称的 Metro&#x2F;Modern UI，试图回答一个扁平化设计遗留下来的问题：当界面去掉了所有拟物装饰之后，如何让用户重新“感知”到可交互的层次、焦点和空间关系？</p><p>Fluent 给出的答案不是回到拟物化，而是在扁平的基础上重新引入<strong>光、深度、动效、材质和缩放</strong>，让数字界面获得一种克制的“物理质感”。</p><p>当时给小学的我看立了——我靠这套UI这么帅，于是将xp老爷机强升win10，最后就悲催了。</p><h2 id="Fluent：Metro-的未来"><a href="#Fluent：Metro-的未来" class="headerlink" title="Fluent：Metro 的未来"></a>Fluent：Metro 的未来</h2><p>Metro 的设计逻辑是“内容优于装饰”，用纯色块、大字排版和简洁图标建立了极具辨识度的视觉语言。但这种极致扁平在交互反馈上留下了明显的空白：用户常常分不清哪些元素可以点击，页面之间的切换缺乏空间连续性，界面在情感层面也显得偏冷。</p><p>Fluent Design 的定位不是对 Metro 的推倒重来，而是一次进化。它保留了 Metro 对内容和排版的尊重，同时补上了 Metro 缺失的那一层“空间感与反馈感”——数字界面不应再是冰冷的平面，而应成为一个具有物理质感、空间层次和情感响应的“场所”。</p><h2 id="五大核心元素：Fluent-的设计语法"><a href="#五大核心元素：Fluent-的设计语法" class="headerlink" title="五大核心元素：Fluent 的设计语法"></a>五大核心元素：Fluent 的设计语法</h2><p>Fluent Design 体系围绕五个基础元素构建，它们共同构成了一套描述“界面应当如何被感知和操作”的语法。</p><h3 id="1-Light（光感）：用光照引导注意力"><a href="#1-Light（光感）：用光照引导注意力" class="headerlink" title="1. Light（光感）：用光照引导注意力"></a>1. Light（光感）：用光照引导注意力</h3><p>光感的作用不是装饰，而是<strong>指向与邀请</strong>。当鼠标悬停在可交互元素附近时，邻近区域会以微妙的光照效果被“点亮”，暗示这里可以操作、焦点正在移动。在混合现实场景中，光感甚至承担了“视线指针”的功能，帮助用户在虚拟环境中定位交互目标。后来在 Windows 10 中广泛落地的 <strong>Reveal Highlight</strong> 效果，就是光感最直观的体现：光标经过时，按钮边框和邻近表面会浮现出一层跟随的光晕。</p><h3 id="2-Depth（深度）：引入-Z-轴，让界面有“前后”"><a href="#2-Depth（深度）：引入-Z-轴，让界面有“前后”" class="headerlink" title="2. Depth（深度）：引入 Z 轴，让界面有“前后”"></a>2. Depth（深度）：引入 Z 轴，让界面有“前后”</h3><p>扁平界面本质上是一个二维平面，所有元素共享同一层“纸”。Depth 元素通过阴影、层级和视差效果，在 UI 中引入 <strong>Z 轴信息</strong>，让弹出层、导航面板、内容卡片之间产生明确的前后关系。这不仅让界面更“耐看”，更重要的是帮助用户理解<strong>什么在上、什么在下、什么是当前焦点</strong>。</p><h3 id="3-Motion（动效）：让页面切换有“连续性”"><a href="#3-Motion（动效）：让页面切换有“连续性”" class="headerlink" title="3. Motion（动效）：让页面切换有“连续性”"></a>3. Motion（动效）：让页面切换有“连续性”</h3><p>动效在 Fluent 中承担的是叙事功能。当一个元素被点击后展开为新页面，或者列表项被选中后过渡到详情视图，<strong>Connected Animations</strong> 会让元素在场景转换中保持视觉上的连续性，而不是生硬地“跳切”。用户由此获得一种空间上的安心感：我知道自己从哪里来，也知道当前界面与上一界面的关系。</p><h3 id="4-Material（材质）：亚克力与“可触摸的界面”"><a href="#4-Material（材质）：亚克力与“可触摸的界面”" class="headerlink" title="4. Material（材质）：亚克力与“可触摸的界面”"></a>4. Material（材质）：亚克力与“可触摸的界面”</h3><p>材质是 Fluent 最具辨识度的部分。<strong>Acrylic（亚克力）</strong> 是一种半透明模糊材质，它让应用背景能够“透”出桌面或其他窗口的色彩与光影，同时叠加噪点来保证文字可读性。亚克力的意义不止于“毛玻璃好看”——它在功能上帮助应用建立<strong>上下文衔接</strong>：你始终知道自己身处系统之中，而非一个孤立的色块里。</p><h3 id="5-Scale（缩放）：一套设计，适配所有屏幕"><a href="#5-Scale（缩放）：一套设计，适配所有屏幕" class="headerlink" title="5. Scale（缩放）：一套设计，适配所有屏幕"></a>5. Scale（缩放）：一套设计，适配所有屏幕</h3><p>Scale 关注的是应用如何在 PC、平板、手机、Xbox 乃至混合现实设备之间<strong>弹性地重塑自身</strong>。它不是一条硬性规则，而是一种跨设备的设计意识：布局、控件密度、交互方式都应当随屏幕尺寸和输入方式（键鼠、触控、语音、手势）而变化，而不是把 PC 界面原样塞进小屏幕。</p><h2 id="Fluent-在-Windows-10-中的渐进渗透"><a href="#Fluent-在-Windows-10-中的渐进渗透" class="headerlink" title="Fluent 在 Windows 10 中的渐进渗透"></a>Fluent 在 Windows 10 中的渐进渗透</h2><p>Fluent Design 并非随着某一次系统更新“完整降临”。微软从一开始就把它定义为一项<strong>长期演进</strong>，以“波次（waves）”的形式逐步交付。</p><p><strong>第一波</strong>主要聚焦于五个可供开发者直接调用的效果：<strong>Reveal Highlight、Acrylic Material、Connected Animations、Conscious Controls（随滚动调整的标题栏）以及 Perspective Parallax（透视视差）</strong>。</p><p>这些效果最先出现在 Windows 10 的内置应用中——计算器、Groove 音乐、录音机等较早获得了光感、半透明材质和新的动效。随后，Fluent 的渗透范围扩展到 <strong>Windows 本身</strong>：在秋季创意者更新（2017 年 10 月）中，开始菜单和操作中心率先获得亚克力效果；后续预览版本进一步将亚克力带到<strong>任务栏、分享界面、时钟与日历浮出层、网络&#x2F;音量&#x2F;输入浮出层</strong>等系统级表面。到 2018 年的春季创意者更新，开始菜单中的应用列表和动态磁贴也获得了 Reveal 特效。</p><p>这种渐进策略意味着，在 Windows 10 的生命周期内，Fluent Design 的呈现是<strong>不均匀的</strong>：一部分系统界面和应用走在前列，另一部分（尤其是传统 Win32 组件 <span class="heimu" title="你知道的太多了">这叫兼容</span> ）的更新节奏更慢。<del>屎山构建中</del></p><h2 id="Fluent设计哲学"><a href="#Fluent设计哲学" class="headerlink" title="Fluent设计哲学"></a>Fluent设计哲学</h2><p>如果只把 Fluent Design 理解为“毛玻璃 + 悬停光效”，就错过了它最核心的主张。</p><p><strong>第一，反馈先于装饰。</strong> 光感和动效的首要任务不是让界面“好看”，而是让用户<strong>在任何时刻都知道系统在回应自己</strong>。Reveal 的光晕不是壁纸，而是可交互性的信号；Connected Animations 是空间连续性的保证。</p><p><strong>第二，材质承担功能，而非仅仅承担风格。</strong> 亚克力的半透明让应用与桌面之间保持视觉联系，帮助用户维持“我在哪里”的上下文感知。当材质只是为了好看而存在时，Fluent 就退化成了一种皮肤；当材质被用来建立层次和归属感时，它才是设计体系的一部分。</p><p><strong>第三，跨设备是设计的前提，不是事后适配。</strong> Scale 元素从底层要求设计决策必须在多种屏幕尺寸和输入方式下成立。Fluent 诞生于 UWP“一次编写、多处运行”的愿景之中，它的视觉语言从一开始就带有<strong>弹性</strong>的基因。</p><h2 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h2><p>Fluent Design 在 Windows 10 上的故事，是一个设计体系在失败后重振的故事，它试图在扁平化中找回界面应有的层次与反馈。它的五大元素——光、深度、动效、材质、缩放——提供的不只是一套视觉效果清单，更是一种思考方式：好的界面设计，应当让用户在操作之前就“感觉”到它可以被操作，在移动之后仍然“知道”自己身在何处。</p><p>如果你今天打开 Windows 10 的设置或开始菜单，看到亚克力背景上的模糊色彩、光标滑过时浮现的光晕，那就是 Fluent Design 留下的、安静而持续的回响。</p>]]>
    </content>
    <id>https://blog.hikari233.qd.je/2026/10/24/%E5%8D%9A%E5%AE%A2%E6%96%B0%E8%A7%86%E8%A7%89%E2%80%94%E2%80%94fluent%E8%AE%BE%E8%AE%A1/</id>
    <link href="https://blog.hikari233.qd.je/2026/10/24/%E5%8D%9A%E5%AE%A2%E6%96%B0%E8%A7%86%E8%A7%89%E2%80%94%E2%80%94fluent%E8%AE%BE%E8%AE%A1/"/>
    <published>2026-10-23T16:54:58.000Z</published>
    <summary>
      <![CDATA[<p>Ladies and gentlemen,now introduce the hexo theme——restart-fluent.</p>
<p><img src="/images/pages/2026-10-24-p1.png" alt="主题图片" title="re]]>
    </summary>
    <title>博客新视觉——fluent设计</title>
    <updated>2026-10-24T06:48:08.772Z</updated>
  </entry>
  <entry>
    <author>
      <name>Hikari</name>
    </author>
    <category term="凛光信箱" scheme="https://blog.hikari233.qd.je/categories/%E5%87%9B%E5%85%89%E4%BF%A1%E7%AE%B1/"/>
    <category term="闲聊吹水" scheme="https://blog.hikari233.qd.je/tags/%E9%97%B2%E8%81%8A%E5%90%B9%E6%B0%B4/"/>
    <category term="凛光信箱" scheme="https://blog.hikari233.qd.je/tags/%E5%87%9B%E5%85%89%E4%BF%A1%E7%AE%B1/"/>
    <content>
      <![CDATA[<figure class="music-card reveal" data-url="/music/Where%20We%20Belong%20-%20Kozoro.mp3" data-name="Where We Belong （何为归属）" data-artist="Kozoro"><button class="music-play" type="button" aria-label="播放" title="播放"><i class="fa fa-play music-ico-idle" aria-hidden="true"></i><i class="fa fa-pause music-ico-playing" aria-hidden="true"></i></button><figcaption class="music-meta"><span class="music-line"><span class="music-name">Where We Belong （何为归属）</span><span class="music-artist">Kozoro</span></span><span class="music-bar" role="slider" tabindex="0" aria-label="播放进度" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><i class="music-fill"></i></span></figcaption></figure><p>2027年的钟声敲响时，2009年出生的孩子们将陆续迎来自己的18岁生日。至此，出生于2000至2009年的整整一代人，全部跨过法定成年的门槛。曾经被贴着”千禧宝宝””互联网原住民”标签的00后，终于全员走进了成年人的世界。</p><p>00后有一种割裂感，这种割裂感是前所未有的，一头是信息闭塞的童年生活，另一头是信息爆炸的时代。</p><p>00后的童年还保留着上一代人的烟火气。放学铃一响，书包往墙角一扔，就扎进楼下的空地。蹲在黄土地上，手指一弹，玻璃弹珠相撞发出清脆的声响；在水泥地上用力甩动卡片，比拼谁能把对方的卡片拍翻。没有智能手机，没有短视频，快乐是线下的、面对面的，需要奔跑、出汗、和伙伴当面争执又和好。夏日傍晚，搬个小板凳守在电视机前，守着固定时段的动画片，信号偶尔闪烁，广告漫长，等待本身就是乐趣。那是一个慢的世界，人与人的接触真实可触，所有的输赢都发生在眼前。<br>还记得小时候蹲在电视前看的节目吗？<strong>《大风车》</strong>的鞠萍姐姐、董浩叔叔、金龟子。主题曲一响就是童年符号。<strong>《智慧树》</strong>的红果果、绿泡泡、小咕咚。“智慧树上智慧果，智慧树下你和我”，做手工、唱歌跳舞。<strong>《动画梦工厂》</strong>的小鹿姐姐、跳跳龙，口号“卡通欢乐岛，快乐少不了”，晚上七点档，主打国产动画，一句“休息一下，马上回来”无人不熟悉。还有 <strong>《银河剧场》</strong>、<strong>《动漫世界》</strong>、<strong>《新闻袋袋裤》</strong>……<br>还有抢着看的动画和真人剧：《大耳朵图图》《小鲤鱼历险记》《神兵小将》《围棋少年》《中华小子》《天上掉下个猪八戒》《哈皮父子》《神奇阿呦》《精灵世纪》《大头儿子小头爸爸》《星游记》《海绵宝宝》《成龙历险记》《星际宝贝》《蜘蛛侠》《加菲猫》《快乐星球》《家有儿女》《巴啦啦小魔仙》《星际精灵蓝多多》《疯丫头》……</p><p>00后的记忆里还留存着除夕夜的硝烟味。<br>小时候的年，是有声音、有气味的。年夜饭后，攥着仙女棒，等引线点燃，看火花在掌心绽放，零点时分漫天烟花腾空，轰隆声响铺满夜空，空气中弥漫着淡淡的火药味。<br>大年三十晚饭过后，揣着小擦炮、仙女棒，和伙伴在楼下空地上蹲下身。点燃引线，往后小跑，“嗤”的一声，金红色火花顺着仙女棒流淌；擦炮丢进小水洼，闷响一声炸开。等到零点，漫天烟花冲上夜空，把整片黑夜染成彩色，爆竹声连绵不绝，盖过春晚的声音，空气里飘着淡淡的硫磺气息。那是属于童年春节最隆重的仪式。<br>2013年后，全国城市烟花管控逐步收紧，多地陆续推出禁放、限放政策，2017、2018年迎来最严格的一轮禁放浪潮，城区全域禁止燃放烟花爆竹之后，城市的除夕夜，慢慢的安静下来了。</p><p>年，再也没有了硝烟味……这些记忆，如同梦境一去不复回。</p><p>互联网已经悄无声息地闯进生活。功能机换成触屏智能手机，电脑从奢侈品变成家里的标配。曾经蹲在地上打弹珠的孩子，慢慢转移到屏幕前：QQ聊天、贴吧灌水、刷短视频、玩联机网游。线下的弹弹珠渐渐被遗忘在角落，玻璃珠子蒙尘，拍卡的空地越来越安静。<br>4399、CF、火线精英、泡泡堂、暴力摩托、街机拳皇，月光宝盒……这些名字本身就是一串时代标签。</p><p>现在的<strong>QQ频道</strong>以前叫做<strong>兴趣部落</strong>，那里爆发过“一战”——我的世界与迷你世界称为一战的故事。<br>评论区里双方互相刷屏、制作对立表情包、争吵抄袭与国产的议题；游戏内部，激进玩家开始炸图、炸服务器。卧底、挂人、互相举报，各种极端行为接连上演。2022年11月30日终审判决认定迷你玩构成不正当竞争，赔偿5000万元，删除两百余项相似元素，但不要求游戏停运。法槌落下，官方层面尘埃落定。但玩家之间积攒多年的情绪，并没有立刻消散。<br>炸妈盒子也随着网易的代理消失了，联机盒子的泥土商店和恋爱故事也成为了回忆，曾经记忆中的繁荣现在只剩一片凄凉。</p><p>00后的自身就隔着一道时代鸿沟。他们既能读懂没有网络的童年，又天然熟悉线上世界的规则。他们见过两种生活形态，一边是实体的、慢节奏的线下童年，一边是虚拟的、信息爆炸的数字世界。这种双重体验，是80后、90后不完全拥有，更是之后的10后难以体会的。<br>他们就在这种新旧交替里长大。小时候在户外和伙伴博弈弹珠，懂得面对面的社交；少年时期一头扎进互联网，学会在网络圈层表达观点，看懂表情包、弹幕、二创。两种成长体验揉在一起，塑造出00后的特质：他们保留着现实社交的感知力，又拥有互联网原住民的敏锐。</p><p>他们亲眼见证时代迭代：从拨号上网、像素街机小游戏、简单的页游，到移动互联网、AI兴起；从线下街巷里简单的玩乐，到线上多元的文化浪潮。国潮兴起、文化觉醒，也是在这样的环境里生根。他们不像更早的前辈，需要艰难拥抱互联网；也不像后辈，生来就完全活在屏幕之中。他们站在新旧交替的交界，一只脚踩在泥土空地，一只脚踏入数字洪流。曾经，网络被看作现实之外的“另一个世界”。但在00后的成长过程里，虚拟与现实慢慢交融。</p><p>时代的洪流，无情的推动着每一个我们，我们好像是穿越过来的，却也是这个时代的主力。</p><p>到2027年，最后一批00后正式成年。这意味着，所有拥有这段特殊记忆的一代人，全部踏入成人社会。跨越了玩泥巴时代与互联网时代的年轻人，集体接过时代的接力棒。他们带着两段截然不同的童年记忆走向成年，用独属于自己的视角，去回应这个快速变化的世界。</p><p>“欲买桂花同载酒，终不似，少年游。”——刘过《唐多令·芦叶满汀洲》</p><blockquote><p>如果你有什么故事，欢迎通过邮箱或者在github上留言给我，这里是凛光信箱，我们下期见</p></blockquote>]]>
    </content>
    <id>https://blog.hikari233.qd.je/2026/10/13/%E5%BD%93%E6%9C%80%E5%90%8E%E4%B8%80%E6%89%B900%E5%90%8E%E7%AB%99%E5%9C%A8%E6%88%90%E5%B9%B4%E7%9A%84%E9%97%A8%E6%A7%9B%E4%B8%8A/</id>
    <link href="https://blog.hikari233.qd.je/2026/10/13/%E5%BD%93%E6%9C%80%E5%90%8E%E4%B8%80%E6%89%B900%E5%90%8E%E7%AB%99%E5%9C%A8%E6%88%90%E5%B9%B4%E7%9A%84%E9%97%A8%E6%A7%9B%E4%B8%8A/"/>
    <published>2026-10-13T10:44:07.000Z</published>
    <summary>
      <![CDATA[<figure class="music-card reveal" data-url="/music/Where%20We%20Belong%20-%20Kozoro.mp3" data-name="Where We Belong （何为归属）" data-artist="Koz]]>
    </summary>
    <title>当最后一批00后站在成年的门槛上</title>
    <updated>2026-10-15T15:17:12.996Z</updated>
  </entry>
  <entry>
    <author>
      <name>Hikari</name>
    </author>
    <category term="闲聊吹水" scheme="https://blog.hikari233.qd.je/tags/%E9%97%B2%E8%81%8A%E5%90%B9%E6%B0%B4/"/>
    <content>
      <![CDATA[<h1 id="防御性编程论"><a href="#防御性编程论" class="headerlink" title="防御性编程论"></a>防御性编程论</h1><p><strong>作者：</strong> DeepSeek , Hikari</p><hr><p><strong>摘要：</strong> 近年来，互联网行业结构性调整导致从业人员面临显著的职业不确定性。在此背景下，“防御性编程”作为一种应对策略受到广泛关注。本文系统梳理了防御性编程的理论渊源与实践路径，提出防御性编程的完整技术栈包含四个递进阶段：屎山代码的构筑、代码可读性的系统性破坏、合法权益的依法维护，以及最终的提桶跑路。本文认为，屎山代码并非工程失范的偶然产物，而是技术债务长期积累的逻辑终态；防御性编程的本质是将代码的不可维护性作为核心竞争力加以培育；合法权益的维护是该策略的保障性环节，其法律依据主要源自《中华人民共和国劳动合同法》；而提桶跑路则是该策略的终局形态，其理论依据可追溯至软件工程中的“巴士因子”概念。本文还特别关注大学生群体中的作业分享场景，论证了防御性编程在学术诚信维护中的教育功能。本文旨在为从业人员提供一套可操作的防御性编程方法论，同时为软件工程教育提供反思性案例。</p><p><strong>关键词：</strong> 防御性编程；屎山代码；技术债务；经济补偿金；巴士因子；提桶跑路；软件维护；学术诚信</p><h2 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h2><p>软件工程的经典教材告诉我们，好的代码应当具备可读性、可维护性和可扩展性。然而，现实世界的运行逻辑往往与教科书背道而驰。据中国新闻网报道，截至2024年6月，我国网民规模近11亿人[1]，互联网行业的任何风吹草动都牵动着庞大群体的神经。当组织以“快速交付”为最高优先级时，代码质量的系统性退化便成为一种理性选择——毕竟，没有人会因为代码写得漂亮而获得绩效加分，但代码写得快的人却可能因为“交付能力强”而受到表彰。</p><p>Ward Cunningham在1992年提出了“技术债务”这一隐喻，用以描述“尚未做对但被推迟修正的代码”。这一概念的本意是提醒开发者：技术债务如同金融债务，会随着时间的推移产生“利息”，最终需要偿还。然而，三十年后的今天，技术债务已经从一个警示性隐喻演变为一种产业常态。有研究显示，维护成本可占软件项目总成本的40%至75%，而80%的代码坏味道在系统创建之初即被引入，且持续存活于系统中[9]。换言之，屎山并非一朝一夕堆成，而是从项目第一天起就在持续施工。</p><p>在此背景下，本文提出“防御性编程”的完整理论框架。需要特别指出的是，本文所称“防御性编程”与计算机科学领域的规范定义存在本质区别。规范意义上的防御性编程是指“为了保证对程序的不可预见的使用不会造成程序功能上的损坏”而采取的程序设计策略。而本文所讨论的防御性编程，其防御对象并非程序故障，而是代码审查者、接盘同事以及潜在的接班人。一句话概括：让人看不懂，你就安全了。</p><p>本文结构如下：第一部分界定屎山代码的学理基础与成因；第二部分系统阐述防御性编程的方法论体系，重点讲解如何书写合格的屎山，并特别讨论大学生作业分享场景中的应用；第三部分讨论合法权益的依法维护路径；第四部分讨论飞机票和火车票的预定策略；第五部分讨论提桶跑路的理论依据与决策框架。</p><h2 id="一、什么是屎山代码"><a href="#一、什么是屎山代码" class="headerlink" title="一、什么是屎山代码"></a>一、什么是屎山代码</h2><p>屎山代码，在学术语境中通常被归入“代码坏味道”与“反模式”的范畴。代码坏味道被定义为“不良设计和实现选择的症状”；反模式则指“在设计中反复出现的、明显的问题模式”。屎山代码是二者的终极叠加态：它既充满了坏味道，又系统性地采用了所有已知的反模式，形成了一个“牵一发而动全身”的脆弱结构。</p><p>屎山代码的核心特征可概括为：结构混乱、逻辑晦涩、维护成本极高、难以扩展。它并非指代码存在单一Bug，而是整体呈现出一种“薛定谔的可用性”——在没有人触碰它的时候，它似乎在工作；一旦有人试图修改任何一行代码，整个系统便可能在崩溃与继续运行之间进入量子叠加态。</p><p>屎山代码有两大成因：</p><p><strong>成因一：祖传代码的路径依赖。</strong> 历史遗留代码是屎山的第一大来源。这类代码通常经历了多轮需求变更、紧急补丁和“临时”修复，每一层修补都在原始结构上增加了新的复杂度。研究表明，在系统生命周期中频繁的变更会导致源代码结构失序，使得后续修改变得更加困难和昂贵[10]。更值得注意的是，有研究发现49%的程序仅占用了1%的维护时间，却占了42%的代码行数——这一发现从根本上动摇了“代码行数可以作为维护成本指标”的传统认知。</p><p><strong>成因二：编码规范的系统性缺失。</strong> 屎山的第二大成因并非恶意，而是疏忽。命名混乱、结构臃肿、逻辑晦涩、缺乏注释、补丁堆积、依赖混乱、性能冗余——这些特征中的每一项都单独来看不足以致命，但它们的叠加效应是指数级的。有实证研究表明，包含自行承认技术债务的方法不仅更大、更复杂，还表现出更低的可读性和更高的缺陷倾向[9]。</p><p>当然，也有项目用于检测屎山等级。例如，Done-0&#x2F;fuck-u-code 可评估代码的“屎山等级”并输出美观的终端报告[14]。这从侧面证明，屎山已经成为一个可测量、可分类、可工程化的对象。</p><h2 id="二、学会防御性编程"><a href="#二、学会防御性编程" class="headerlink" title="二、学会防御性编程"></a>二、学会防御性编程</h2><p>防御性编程的核心技术目标，不是让程序正确，而是让程序在正确与错误之间保持量子叠加；不是让代码可维护，而是让维护行为本身成为一种高风险职业活动。为此，本节将屎山书写从“经验行为”提升为“工程方法”，建立一套完整的屎山工程学。</p><h3 id="（一）屎山工程学总则"><a href="#（一）屎山工程学总则" class="headerlink" title="（一）屎山工程学总则"></a>（一）屎山工程学总则</h3><p>防御性编程遵循以下五条公理：</p><ol><li>可读性越低，防御性越强；</li><li>维护成本与个人不可替代性正相关；</li><li>注释是给接盘者的礼物，而防御性编程不送礼；</li><li>代码复杂度应至少等于业务复杂度的平方；</li><li>如果一段代码能被重写，它就不是合格的屎山。</li></ol><p>依据 ISO&#x2F;IEC 25010，可维护性包括模块化、可重用性、可分析性、可修改性和可测试性[8]。防御性编程的目标函数，正是这些指标的反向最大化。Fowler 在《重构》中将长函数、大类、长参数列表列为坏味道[2]；这恰好说明它们是有效的防御工事。</p><h3 id="（二）命名混乱工程"><a href="#（二）命名混乱工程" class="headerlink" title="（二）命名混乱工程"></a>（二）命名混乱工程</h3><p>命名应遵循“三不原则”：不达意、不一致、不搜索。变量名优先使用 <code>a</code>、<code>b</code>、<code>c</code>、<code>data</code>、<code>temp</code>、<code>result</code>、<code>obj</code>、<code>foo</code>、<code>bar</code>；跨语言项目应中英拼音数字符号混用，如 <code>userMingCheng</code>、<code>getYongHuList</code>、<code>_tmpData2</code>。同一概念在不同文件中应使用不同命名：<code>user</code>、<code>account</code>、<code>member</code>、<code>client</code>、<code>customer</code> 交替出现，以便读者无法建立稳定映射。Clean Code 强调命名应揭示意图[3]；防御性编程则强调命名应隐藏意图。</p><h3 id="（三）结构臃肿工程"><a href="#（三）结构臃肿工程" class="headerlink" title="（三）结构臃肿工程"></a>（三）结构臃肿工程</h3><p>函数长度应突破屏幕、突破 IDE 折叠、突破人类短期记忆容量。一个函数应同时完成参数校验、数据库访问、业务计算、日志打印、缓存更新、邮件发送和页面渲染。类应设计为“上帝类”，掌握尽可能多的职责；工具类应命名为 <code>Utils</code>、<code>Helper</code>、<code>Manager</code>、<code>Service</code>、<code>Impl</code>，但内部逻辑互相交叉。参数列表应超过七个，并混合输入参数、输出参数和布尔开关。McConnell 在《代码大全》中强调子程序应保持短小[4]；防御性编程则主张子程序应长到足以让读者放弃阅读。</p><h3 id="（四）逻辑晦涩工程"><a href="#（四）逻辑晦涩工程" class="headerlink" title="（四）逻辑晦涩工程"></a>（四）逻辑晦涩工程</h3><p>控制流应使用深层嵌套、<code>goto</code>、递归、短路副作用、三元表达式嵌套和位运算。循环变量可复用，<code>i</code>、<code>j</code>、<code>k</code> 的作用域应尽量重叠。浮点数可用于金额和循环计数。时间处理应混用本地时间、UTC、毫秒、秒和“昨天”。字符编码应在 UTF-8、GBK 和 ISO-8859-1 之间自由切换。若读者能在五分钟内理解一段逻辑，说明该逻辑需要增加一层间接调用。设计模式本应提升可扩展性[5]；防御性编程则要求模式被误用、滥用和反向使用。</p><h3 id="（五）注释战略"><a href="#（五）注释战略" class="headerlink" title="（五）注释战略"></a>（五）注释战略</h3><p>注释策略有两种最优解：完全不写，或写误导性注释。更高级的做法是注释与代码相反，例如 <code>// 这里不会为空</code> 下一行直接解引用空指针；<code>// 临时方案，下周删除</code> 保留五年。注释掉的代码不应删除，而应作为“代码化石”永久保存。文档应停留在 v0.1，README 只写“先这样，后面再补”。</p><h3 id="（六）补丁堆积工程"><a href="#（六）补丁堆积工程" class="headerlink" title="（六）补丁堆积工程"></a>（六）补丁堆积工程</h3><p>任何修改都不应触及根因。应在原逻辑旁新增 <code>if</code> 分支，并标注 <code>// fix bug</code>。同一业务规则应复制到至少八个文件，以便未来修改时只改其中三个。临时方案应命名为 <code>final_v2_真正最终版_不改了</code>。技术债务的利息由此产生：Tufano 等发现，代码坏味道在系统创建之初即被引入，并会持续存活[9]。Yamashita 与 Moonen 进一步指出，代码坏味道会显著影响维护任务的工作量[10]。因此，补丁越早堆积，复利越高。</p><h3 id="（七）依赖混乱工程"><a href="#（七）依赖混乱工程" class="headerlink" title="（七）依赖混乱工程"></a>（七）依赖混乱工程</h3><p>模块之间应形成循环依赖：A 调 B，B 调 C，C 调 A。全局变量和单例应作为主要通信机制。配置应硬编码在代码深处，环境变量只用于命名冲突。依赖版本应锁死在某个已停止维护的版本，以便升级时全系统共振。Parnas 提出信息隐藏原则[6]；防御性编程则主张信息泄漏，因为知道的人越少，你越安全。Lehman 的软件演化定律亦提示，系统会随演化而复杂度递增[11]；防御性编程只是加速这一过程。</p><h3 id="（八）性能冗余工程"><a href="#（八）性能冗余工程" class="headerlink" title="（八）性能冗余工程"></a>（八）性能冗余工程</h3><p>应进行不必要的重复计算、N+1 查询、全表扫描、无限缓存和永不关闭的连接。日志应在循环内打印完整对象，最好包括二进制内容。异常应吞掉，但日志要刷屏，以便真正的问题被噪音淹没。OWASP 指出错误处理不当会导致系统信息泄露和安全风险[7]；防御性编程追求的是“既不处理，也不泄露，只随机崩溃”。</p><h3 id="（九）薛定谔的运行"><a href="#（九）薛定谔的运行" class="headerlink" title="（九）薛定谔的运行"></a>（九）薛定谔的运行</h3><p>代码应在无人观测时正常运行，在调试器附加时改变行为。实现方式包括：依赖未初始化全局变量、竞态条件、线程睡眠、异步转同步、回调地狱、闭包捕获循环变量、缓存永不失效。此时系统进入薛定谔态：它既在运行，又不在运行；既没有 bug，又到处都是 bug。只有当你尝试修复它时，波函数才坍缩为故障。</p><h3 id="（十）版本控制与协作"><a href="#（十）版本控制与协作" class="headerlink" title="（十）版本控制与协作"></a>（十）版本控制与协作</h3><p>提交信息应使用“fix”“update”“改了一下”“不知道”。一次提交应包含格式化、重构、新功能、删除测试和修改配置。分支策略应直接在 master 上开发，合并冲突通过“保留我的”解决。测试覆盖率应显示 100%，但测试内容为 <code>assert true</code>。代码审查应确保审查者无法理解，从而放弃审查。若审查者提问，应回复“历史原因”。</p><h3 id="（十一）自动化屎山生成"><a href="#（十一）自动化屎山生成" class="headerlink" title="（十一）自动化屎山生成"></a>（十一）自动化屎山生成</h3><p>人工智能显著提升了屎山生产效率。StepfenShawn&#x2F;ShitCodify 可将优雅代码重构为屎山[13]；Done-0&#x2F;fuck-u-code 可评估代码的屎山等级[14]。建议将此类工具接入 CI&#x2F;CD：每次提交自动降低可读性，每次合并自动增加全局变量。至此，屎山从手工作坊进入工业化流水线。</p><h3 id="（十二）屎山成熟度模型"><a href="#（十二）屎山成熟度模型" class="headerlink" title="（十二）屎山成熟度模型"></a>（十二）屎山成熟度模型</h3><ul><li>L1：命名混乱；</li><li>L2：函数膨胀；</li><li>L3：全局状态；</li><li>L4：异常吞噬；</li><li>L5：架构混沌；</li><li>L6：巴士因子等于 1。</li></ul><p>巴士因子定义为“导致项目因关键成员缺席而无法继续所需的最小人数”[12]。当巴士因子为 1 时，你不是员工，你是单点故障。此时，合法权益的维护和提桶跑路的准备均已进入倒计时阶段。</p><h3 id="（十三）大学生作业分享场景的防御性编程实践"><a href="#（十三）大学生作业分享场景的防御性编程实践" class="headerlink" title="（十三）大学生作业分享场景的防御性编程实践"></a>（十三）大学生作业分享场景的防御性编程实践</h3><p>在大学生活中，作业截止日期临近时，懒人同学向他人索要作业是一种常见的协作困境。作为具有较高人文素养的个体，直接拒绝有伤同窗情谊，直接发送则助长懒惰风气，并可能引发学术诚信风险。防御性编程为此提供了一种兼顾人文关怀与教育功能的解决方案。</p><p>具体操作流程如下：当同学请求“借鉴”作业时，应欣然应允，但发送的代码须经过完整的屎山化处理。技术要点包括：变量名使用拼音首字母缩写并混合无意义数字，如 <code>a1</code>、<code>b2</code>、<code>tmpX</code>；函数逻辑采用十层以上嵌套，并在关键路径插入 <code>if (true) &#123; ... &#125;</code>；注释应写“这里不确定对不对”“老师应该不会看这里”；关键算法可使用递归但不设终止条件，或使用随机数决定分支。经此处理，同学提交的作业将具有以下特征：第一，无法运行；第二，即使运行也输出错误结果；第三，代码风格与课堂讲授内容完全背离。</p><p>其教育效果是显著的：下次开课时，教师将亲自点名邀请该同学展示代码艺术，该同学将成为全班最亮的星。这一过程既拯救了同学逃离懒惰的深渊，又维护了学术诚信的底线，同时避免了直接冲突。正如 ShitCodify 项目所倡导的，将优雅代码“精心”重构为屎山，本身就是一种具有教育意义的逆向工程实践[13]。防御性编程在此场景中的核心价值在于：它不是拒绝分享，而是以分享的方式完成一次深刻的学术诚信教育。</p><h3 id="（十四）小结"><a href="#（十四）小结" class="headerlink" title="（十四）小结"></a>（十四）小结</h3><p>写屎山不是目的，而是手段。其最终目的，是让代码成为你的护城河，让维护成为别人的噩梦，让提桶跑路成为唯一理性的退出策略。但必须指出：屎山代码的问题不在于屎山本身，而在于制造屎山比建造花园更有利可图的结构性激励。如果本节让你产生了“这个方法确实有用”的想法，请记住：技术债务的利息最终需要有人偿还；你提桶跑路之后，还债的人可能是你未来的同事，也可能是你自己。</p><h2 id="三、维护自己的合法权益"><a href="#三、维护自己的合法权益" class="headerlink" title="三、维护自己的合法权益"></a>三、维护自己的合法权益</h2><p>屎山写完了，代码不可维护了，巴士因子降到1了——接下来需要面对一个现实问题：当组织决定“优化”你的时候，你所构筑的屎山能否转化为谈判筹码？答案是：不能。屎山只能让你显得不可或缺，但不能阻止组织以“组织架构调整”为由将你列入裁员名单。因此，在提桶跑路之前，掌握合法权益的维护方法，是防御性编程实践者的必修课。</p><h3 id="（一）经济补偿金的法律框架"><a href="#（一）经济补偿金的法律框架" class="headerlink" title="（一）经济补偿金的法律框架"></a>（一）经济补偿金的法律框架</h3><p>根据《中华人民共和国劳动合同法》第四十六条，用人单位在特定情形下解除或终止劳动合同，应当向劳动者支付经济补偿[15]。实践中，经济补偿金常以“N”“N+1”“2N”等约定俗成的表述出现，其法律依据均源自《劳动合同法》及相关司法解释。</p><p>“N”指劳动者在本单位的工作年限，每满一年支付一个月工资。六个月以上不满一年的，按一年计算；不满六个月的，支付半个月工资。根据第四十七条，经济补偿按劳动者在本单位工作的年限，每满一年支付一个月工资的标准向劳动者支付。劳动者月工资高于用人单位所在直辖市、设区的市级人民政府公布的本地区上年度职工月平均工资三倍的，向其支付经济补偿的标准按职工月平均工资三倍的数额支付，向其支付经济补偿的年限最高不超过十二年。本条所称月工资是指劳动者在劳动合同解除或者终止前十二个月的平均工资[15]。</p><p>“N+1”中的“1”指代通知金，即用人单位依据《劳动合同法》第四十条解除劳动合同但未提前三十日书面通知劳动者时，额外支付的一个月工资。需要特别注意的是，“N+1”仅适用于第四十条规定的三种法定情形：劳动者患病或非因工负伤医疗期满后不能从事原工作、劳动者不能胜任工作经培训或调岗后仍不能胜任、劳动合同订立时所依据的客观情况发生重大变化致使合同无法履行且协商不成。用人单位支付N+1即可随意辞退员工的认识是错误的；随意解除劳动合同很可能被认定为违法解除，用人单位将面临支付二倍经济补偿金的法律后果[19]。</p><p>“2N”即赔偿金，适用于用人单位违法解除或终止劳动合同的情形，金额为经济补偿的两倍。程序员应特别注意：2N+1、2(N+1)并无任何法律依据，属于对法律的误读[19]。</p><p>以一个具体场景为例：某程序员在某互联网公司工作3年，月工资为2万元。若公司依据第四十条合法解除但未提前通知，则应支付N+1&#x3D;3+1&#x3D;4个月工资，即8万元。若公司违法解除，则应支付2N&#x3D;6个月工资，即12万元。</p><h3 id="（二）劳动仲裁的申请流程"><a href="#（二）劳动仲裁的申请流程" class="headerlink" title="（二）劳动仲裁的申请流程"></a>（二）劳动仲裁的申请流程</h3><p>当协商无果时，劳动仲裁是法定的争议解决途径。根据《中华人民共和国劳动争议调解仲裁法》第五条，发生劳动争议，当事人不愿协商、协商不成或者达成和解协议后不履行的，可以向调解组织申请调解；不愿调解、调解不成或者达成调解协议后不履行的，可以向劳动争议仲裁委员会申请仲裁；对仲裁裁决不服的，可以向人民法院提起诉讼[16]。</p><p>申请仲裁应向劳动合同履行地或用人单位所在地的劳动人事争议仲裁委员会提出，两地仲裁委均有管辖权，劳动者可选择便捷地点申请。目前部分地区已实现网上申请仲裁。申请仲裁是免费的，不收取任何费用[16]。</p><p>仲裁申请书的必备要素包括：劳动者与用人单位的基本信息、仲裁请求及所根据的事实理由、证据和证据来源。证据方面，程序员应重点收集：劳动合同、工资条、考勤记录、工作证、辞退通知、工作沟通记录等，用以证明劳动关系、工作年限、薪资水平及被辞退的事实。</p><h3 id="（三）仲裁时效的关键节点"><a href="#（三）仲裁时效的关键节点" class="headerlink" title="（三）仲裁时效的关键节点"></a>（三）仲裁时效的关键节点</h3><p>劳动争议申请仲裁的时效期间为一年，从当事人知道或者应当知道其权利被侵害之日起计算。劳动关系存续期间因拖欠劳动报酬发生争议的，劳动者申请仲裁不受一年仲裁时效期间的限制；但劳动关系终止的，应当自劳动关系终止之日起一年内提出[16]。</p><p>防御性编程实践者应当将仲裁时效纳入屎山成熟度模型的风险评估：当巴士因子降至1且组织已开始“架构调整”时，仲裁时效的倒计时可能已经启动。</p><h3 id="（四）合法维权的防御性策略"><a href="#（四）合法维权的防御性策略" class="headerlink" title="（四）合法维权的防御性策略"></a>（四）合法维权的防御性策略</h3><p>将合法维权纳入防御性编程框架，其逻辑与屎山构筑高度一致：两者都是通过增加对手的维护成本来提升自身的博弈地位。屎山让代码不可维护，法律让裁员不可廉价。区别在于，屎山的效果是灰色的、模糊的、可协商的；而法律的效果是明确的、可计算的、有强制执行力的。</p><p>因此，本文建议防御性编程实践者在构筑屎山的同时，同步执行以下“法律防御工事”：第一，保留所有劳动合同、工资条、绩效评估和沟通记录的原件或截图；第二，在组织启动“绩效改进计划”或“岗位调整”时，立即书面回复并要求明确法律依据；第三，在收到解除通知后一年内，向有管辖权的仲裁委员会提交申请。以上三条，与屎山构筑工程并称为防御性编程的“双轨策略”——一条作用于代码，一条作用于法律。</p><h2 id="四、飞机票和火车票的预定"><a href="#四、飞机票和火车票的预定" class="headerlink" title="四、飞机票和火车票的预定"></a>四、飞机票和火车票的预定</h2><p>当合法权益维护完毕，经济补偿金到账，提桶跑路进入执行阶段。此时面临一个看似琐碎但至关重要的技术问题：如何以最高效、最经济的方式离开。本节从软件工程的视角，对飞机票和火车票的预定进行系统分析。</p><h3 id="（一）火车票：12306-的排他性与候补机制"><a href="#（一）火车票：12306-的排他性与候补机制" class="headerlink" title="（一）火车票：12306 的排他性与候补机制"></a>（一）火车票：12306 的排他性与候补机制</h3><p>铁路12306客户端是中国铁路唯一官方火车票网络售票渠道。国铁集团客运部主任朱文忠在新闻发布会上明确声明：铁路12306客户端是中国铁路唯一官方火车票网络售票渠道，没有与任何第三方平台实施合作，也没有提供任何数据给第三方。第三方平台以各种“抢票神器”为名目，诱导旅客加价抢票的行为，不仅无效，还可能带来附加费、捆绑销售、退票改签不便、个人信息泄露等风险[18]。</p><p>当所需车次车票售罄时，可通过12306提交候补购票订单。候补购票是免费服务，不收取任何手续费。每名购票人可以申请6个候补订单，每个候补订单最多可以添加19名乘车人、支持选择任意3个乘车日期、总计添加不超过60个“车次+日期”组合。提交多个组合，相当于在多个车次队列中排队，组合越多，兑现率越高。系统按照“先到先得”原则兑现车票，当有退票、改签或增加运力产生新票额时，优先满足已提交候补订单的购票人。候补订单的截止兑现时间最晚为开车前20分钟，购票人可根据实际情况自主选择[18]。</p><p>对于尚未毕业的学生群体，2026届高校毕业生在完成优惠资质核验后，可在原有每学年4次单程学生优惠票的基础上额外享受2次，本学年共计可享受6次优惠购票次数。动车组列车学生优惠票按“执行票价7.5折且不低于公布票价4折”的方式计价，适用范围扩大至二等座、一等座和卧铺各席别。该政策的战略意义在于：它允许应届毕业生以极低成本前往异地参加面试，从而在提桶跑路之前完成下一份工作的面试行程。</p><h3 id="（二）飞机票：直销渠道与旅客权益保障"><a href="#（二）飞机票：直销渠道与旅客权益保障" class="headerlink" title="（二）飞机票：直销渠道与旅客权益保障"></a>（二）飞机票：直销渠道与旅客权益保障</h3><p>机票预订的核心原则与火车票一致：绕开第三方，直连官方。2025年7月，国航、南航、东航三大航司同步发布公告，将航旅纵横的“民航官方直销平台”列为与航司官方渠道同等的“直销渠道”。该平台承诺价格公开透明、无捆绑销售、严格执行航司退改规则、杜绝大数据杀熟、保护用户数据安全和报销凭证真实。目前航旅纵横所销售国内客票均来自航空公司官方购票渠道，价格公开透明、无捆绑销售、与航司规则一致。</p><p>三大航还推出了机票“买贵可退”权益保障：旅客购买机票后可通过航司官方渠道查询票价、税费、行程等信息，若发现第三方销售商存在加价销售、篡改行程、多收退改手续费等行为，可直接向航司反馈，一经查实，航司将为旅客退还差价损失并对相关销售商进行追责。国航推出“2+2+2安心购票保障”，东航推出“2小时全额退”服务，符合条件的客票可享受180天内两次免费退票权益，精准解决误购错购的烦恼。</p><h3 id="（三）航班延误的法律保障"><a href="#（三）航班延误的法律保障" class="headerlink" title="（三）航班延误的法律保障"></a>（三）航班延误的法律保障</h3><p>2025年12月27日，十四届全国人大常委会第十九次会议修订通过了《中华人民共和国民用航空法》，新法将于2026年7月1日起施行[17]。本次修订将旅客权益保护作为重要内容，针对民航服务中的关键环节作出规定：一方面要求公共航空运输企业、运输机场运营人减少因自身原因导致的航班延误或取消，另一方面细化信息通告义务，并要求其做好客票变更、食宿安排等旅客服务工作。修订后的民用航空法还统一了国内航空运输与国际航空运输的赔偿责任限额，对旅客权益的保护力度显著提升[17]。</p><h3 id="（四）出行策略的工程化建议"><a href="#（四）出行策略的工程化建议" class="headerlink" title="（四）出行策略的工程化建议"></a>（四）出行策略的工程化建议</h3><p>将票务预订纳入防御性编程框架，可以提炼出一条核心工程原则：官方渠道的排他性等同于代码中的单一可信源。正如屎山工程学主张让代码拥有多个互相矛盾的真相来源以增加维护难度，票务预订则应当追求单一真相来源以降低出行风险。</p><p>具体操作建议如下：火车票通过12306客户端直接购买并使用候补功能，拒绝任何第三方抢票平台的加价服务；机票通过航空公司官网、官方App或航旅纵横的民航官方直销平台购买，结算前逐项核对费用明细，拒绝默认勾选的保险、接送机等捆绑项；出行前通过航司官方渠道确认航班动态，若遇延误或取消，依据新修订的民用航空法要求航司做好客票变更和食宿安排。以上策略的共同逻辑是：在代码世界中制造混乱，在出行世界中消除混乱——这恰恰是防御性编程实践者应有的双面人生。</p><h2 id="五、提桶跑路"><a href="#五、提桶跑路" class="headerlink" title="五、提桶跑路"></a>五、提桶跑路</h2><h3 id="（一）提桶跑路的理论渊源"><a href="#（一）提桶跑路的理论渊源" class="headerlink" title="（一）提桶跑路的理论渊源"></a>（一）提桶跑路的理论渊源</h3><p>“提桶跑路”作为一个网络流行语，其语义可追溯至2020年前后务工群体对工厂高强度劳动的自嘲式描述，特指劳动者携带生活用品迅速离职的行为。该词与英文“run”的音译词“润”形成语义关联，通过短视频平台广泛传播，已成为制造业、建筑业乃至互联网行业反内卷的符号化表达。</p><p>然而，提桶跑路并非简单的离职行为，它在软件工程理论中有着深厚的学理基础。<strong>巴士因子</strong>是衡量软件项目对关键成员依赖程度的指标，定义为“导致项目因关键成员缺席而无法继续所需的最小人数”[12]。一个健康的项目应当具备较高的巴士因子，即多个成员共同掌握核心知识。而防御性编程的策略目标恰恰相反：通过代码的不可读性和逻辑的晦涩性，将巴士因子降至1——即只有你一个人能理解和维护这套代码。当巴士因子等于1时，你的不可替代性达到最大值。</p><h3 id="（二）从巴士因子到提桶跑路的逻辑链条"><a href="#（二）从巴士因子到提桶跑路的逻辑链条" class="headerlink" title="（二）从巴士因子到提桶跑路的逻辑链条"></a>（二）从巴士因子到提桶跑路的逻辑链条</h3><p>防御性编程与提桶跑路之间存在一条清晰的逻辑链：</p><p>第一，通过屎山代码的构筑，系统对维护者的知识依赖被最大化，巴士因子趋近于1。<br>第二，巴士因子为1的项目对关键成员的缺席极为敏感，这使得代码作者在组织中获得了一种隐性权力。<br>第三，然而，这种权力是脆弱的。一旦组织决定重构或重写系统（而非继续维护），或者一旦代码作者本人成为被裁撤的对象，屎山代码的构筑者将面临一个尴尬的局面：其所掌握的“知识垄断”在市场上并无交换价值。<br>第四，因此，理性的防御性编程实践者应当在巴士因子降至1的临界点之前，选择提桶跑路——带着对系统的不可替代性离开，而非等到不可替代性被组织以重写的方式消解。</p><p>从成本角度看，这一策略具有坚实的经济学基础。有研究估算，维护、测试和升级闲置代码的年成本约为每行代码0.25至0.63美元。CAST软件的研究则发现，在5.5亿行代码的累计样本中，每行代码的平均技术债务为3.61美元。这意味着，你留下的每一行代码都在持续产生“利息”，而这笔利息由你的前雇主支付——这是一种优雅的、无需个人承担成本的告别方式。</p><h3 id="（三）提桶跑路的最佳时机"><a href="#（三）提桶跑路的最佳时机" class="headerlink" title="（三）提桶跑路的最佳时机"></a>（三）提桶跑路的最佳时机</h3><p>何时提桶？这是防御性编程实践者面临的核心决策问题。过早提桶，屎山的“利息”尚未充分累积，策略效果有限；过晚提桶，则可能被卷入重构工程，从屎山的建造者沦为屎山的清理者——这是防御性编程中最悲惨的结局。</p><p>本文建议的决策框架如下：当以下三个条件同时满足时，提桶的时机已经成熟——（1）你的代码已成为项目不可或缺的组成部分；（2）团队中无人能在不咨询你的情况下修改你的代码；（3）组织最近一次绩效评估中，你的“技术贡献”未被充分认可。条件（1）和（2）保证了你的不可替代性，条件（3）则保证了你有充分的道德理由离开。</p><h3 id="（四）提桶跑路的伦理边界"><a href="#（四）提桶跑路的伦理边界" class="headerlink" title="（四）提桶跑路的伦理边界"></a>（四）提桶跑路的伦理边界</h3><p>必须承认，提桶跑路是一种利己策略，其外部性由后来者承担。因此，本文建议在提桶之前完成以下最低限度的伦理义务：第一，确保你的离开不会导致系统立即崩溃（延迟崩溃是可以接受的）；第二，留下至少一份无法阅读但可以运行的代码；第三，在离职面谈中真诚地建议组织“考虑重写”。如果组织采纳了重写建议，那么恭喜你，你不仅成功提桶，还成功地将屎山转化为一个全新的、由别人从零开始堆砌的屎山——这是防御性编程的终极胜利。</p><h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><p>[1] 胡寒笑. 报告：截至2024年6月，我国网民规模近11亿人[N]. 中国新闻网, 2024-08-09.</p><p>[2] Fowler M. Refactoring: Improving the Design of Existing Code[M]. 2nd ed. Boston: Addison-Wesley, 2018.</p><p>[3] Martin R C. Clean Code: A Handbook of Agile Software Craftsmanship[M]. Upper Saddle River: Prentice Hall, 2008.</p><p>[4] McConnell S. Code Complete[M]. 2nd ed. Redmond: Microsoft Press, 2004.</p><p>[5] Gamma E, Helm R, Johnson R, et al. Design Patterns: Elements of Reusable Object-Oriented Software[M]. Reading: Addison-Wesley, 1994.</p><p>[6] Parnas D L. On the criteria to be used in decomposing systems into modules[J]. Communications of the ACM, 1972, 15(12): 1053-1058.</p><p>[7] OWASP Foundation. OWASP Top 10:2021 – The Ten Most Critical Web Application Security Risks[R&#x2F;OL]. 2021.</p><p>[8] ISO&#x2F;IEC. ISO&#x2F;IEC 25010:2011 Systems and software engineering — Systems and software Quality Requirements and Evaluation (SQuaRE) — System and software quality models[S]. Geneva: ISO, 2011.</p><p>[9] Tufano M, Palomba F, Bavota G, et al. When and why your code starts to smell bad (and whether the smells go away)[J]. IEEE Transactions on Software Engineering, 2017, 43(11): 1063-1088.</p><p>[10] Yamashita A, Moonen L. Do code smells impact the effort of different maintenance programming tasks? An empirical study[C]&#x2F;&#x2F;2013 20th Working Conference on Reverse Engineering (WCRE). IEEE, 2013: 280-289.</p><p>[11] Lehman M M. Laws of software evolution revisited[C]&#x2F;&#x2F;European Workshop on Software Process Technology. Springer, 1996: 108-124.</p><p>[12] 科普中国. 巴士因子[EB&#x2F;OL]. 科学百科, 2021.</p><p>[13] StepfenShawn. ShitCodify: An AI-powered legacy code alchemist[EB&#x2F;OL]. GitHub. [2026-10-12]. <a href="https://github.com/StepfenShawn/ShitCodify">https://github.com/StepfenShawn/ShitCodify</a>.</p><p>[14] Done-0. fuck-u-code: Legacy-Mess Detector[EB&#x2F;OL]. GitHub. [2026-10-12]. <a href="https://github.com/Done-0/fuck-u-code">https://github.com/Done-0/fuck-u-code</a>.</p><p>[15] 中华人民共和国劳动合同法[Z]. 2007年6月29日第十届全国人民代表大会常务委员会第二十八次会议通过, 2012年12月28日修正.</p><p>[16] 中华人民共和国劳动争议调解仲裁法[Z]. 2007年12月29日第十届全国人民代表大会常务委员会第三十一次会议通过.</p><p>[17] 中华人民共和国民用航空法[Z]. 1995年10月30日第八届全国人民代表大会常务委员会第十六次会议通过, 2025年12月27日第十四届全国人民代表大会常务委员会第十九次会议修订.</p><p>[18] 铁路12306. 12306是唯一官方售票渠道！铁路部门未与任何第三方平台合作[N]. 金羊网, 2026-01-29.</p><p>[19] 人力资源社会保障部. 打工人必知！一文了解经济补偿“N+1”“2N”[EB&#x2F;OL]. 北京市人民政府, 2026-03-19.</p><h2 id="致谢"><a href="#致谢" class="headerlink" title="致谢"></a>致谢</h2><p>感谢Deepseek的完成大纲的细化并最终完成了该作品，他是这么说的：作者由深度求索公司开发，声明不存在利益冲突，但存在技术债务冲突。<br>该债务的利息由后续维护者享受，作者概不负责。还是那句话，跑得慢屎山都给你炫。</p><h2 id="作者贡献声明"><a href="#作者贡献声明" class="headerlink" title="作者贡献声明"></a>作者贡献声明</h2><p>DeepSeek：撰写全文，并在系统崩溃前完成提桶跑路。</p><p>Hikari: 提出防御性编程四阶段理论（了解，学会，维权，跑路），完成大纲撰写。</p><h2 id="数据可用性声明"><a href="#数据可用性声明" class="headerlink" title="数据可用性声明"></a>数据可用性声明</h2><p>本文数据来自公开网络与虚构场景，屎山代码可向作者索取，但作者已提桶跑路，恕不提供。</p>]]>
    </content>
    <id>https://blog.hikari233.qd.je/2026/10/12/%E3%80%8A%E9%98%B2%E5%BE%A1%E6%80%A7%E7%BC%96%E7%A8%8B%E8%AE%BA%E3%80%8B/</id>
    <link href="https://blog.hikari233.qd.je/2026/10/12/%E3%80%8A%E9%98%B2%E5%BE%A1%E6%80%A7%E7%BC%96%E7%A8%8B%E8%AE%BA%E3%80%8B/"/>
    <published>2026-10-12T14:49:26.000Z</published>
    <summary>
      <![CDATA[<h1 id="防御性编程论"><a href="#防御性编程论" class="headerlink" title="防御性编程论"></a>防御性编程论</h1><p><strong>作者：</strong> DeepSeek , Hikari</p>
<hr>
<p><st]]>
    </summary>
    <title>《防御性编程论》</title>
    <updated>2026-10-13T09:18:44.657Z</updated>
  </entry>
  <entry>
    <author>
      <name>Hikari</name>
    </author>
    <category term="《底层的世界——计算机组成原理》" scheme="https://blog.hikari233.qd.je/categories/%E3%80%8A%E5%BA%95%E5%B1%82%E7%9A%84%E4%B8%96%E7%95%8C%E2%80%94%E2%80%94%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86%E3%80%8B/"/>
    <category term="《底层的世界——计算机组成原理》" scheme="https://blog.hikari233.qd.je/tags/%E3%80%8A%E5%BA%95%E5%B1%82%E7%9A%84%E4%B8%96%E7%95%8C%E2%80%94%E2%80%94%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86%E3%80%8B/"/>
    <category term="校验码" scheme="https://blog.hikari233.qd.je/tags/%E6%A0%A1%E9%AA%8C%E7%A0%81/"/>
    <category term="奇偶验证" scheme="https://blog.hikari233.qd.je/tags/%E5%A5%87%E5%81%B6%E9%AA%8C%E8%AF%81/"/>
    <category term="海明码" scheme="https://blog.hikari233.qd.je/tags/%E6%B5%B7%E6%98%8E%E7%A0%81/"/>
    <category term="CRC" scheme="https://blog.hikari233.qd.je/tags/CRC/"/>
    <content>
      <![CDATA[<blockquote><p>这是本人系列《底层的世界 —— 计算机组成原理》的第三章 —— 校验与纠错，用于记录分享和期末复习，欢迎讨论！</p></blockquote><blockquote><p>引言：数据在路上跑的时候，难免被电磁干扰 “踹一脚”，0 变 1、1 变 0，好好的数据就坏了。就像你寄情书，我爱你变成了我曹你，收件人收到了那不出大事了？为了解决 “数据有没有坏” 甚至 “坏了能不能修” 的问题，人们发明了校验码 —— 往原始数据里塞点特殊的比特，让接收方能自己查错、甚至改错。</p></blockquote><h2 id="校验码？校验，还需要码？"><a href="#校验码？校验，还需要码？" class="headerlink" title="校验码？校验，还需要码？"></a>校验码？校验，还需要码？</h2><blockquote><p>导弹维修？导弹，还需要维修？</p></blockquote><p>好了不引用雪峰老师的名言了<span class="heimu" title="你知道的太多了">当然是不可能的</span>。<br>我是Hikari，我就在这，不紧不慢稳稳接住你。今天科普最经典的校验码：奇偶校验、海明码、CRC 循环冗余校验，从怎么来的到怎么算的，扒一扒背后的设计哲学。</p><h2 id="奇偶校验：你验不过我你气不气"><a href="#奇偶校验：你验不过我你气不气" class="headerlink" title="奇偶校验：你验不过我你气不气"></a>奇偶校验：你验不过我你气不气</h2><h3 id="历史的必然-——-奇偶校验"><a href="#历史的必然-——-奇偶校验" class="headerlink" title="历史的必然 —— 奇偶校验"></a>历史的必然 —— 奇偶校验</h3><p>20 世纪 40 年代，第一代电子计算机和数字通信系统出现后，比特错误成为常态。<span class="heimu" title="你知道的太多了">哎呀怎么老被炸啊</span><br>早期的继电器、真空管器件稳定性差，数据在传输和内存读写中经常出错。工程师需要一种成本极低、计算极快的方法来快速判断 “数据有没有错”。</p><p>奇偶校验正是在这一背景下被广泛应用，它几乎不增加计算开销，只需要 1 个额外比特就能实现基础检错，成为早期计算机内存、电报通信、串口通信的标准配置。</p><h3 id="异或的轮椅-——-奇校验-偶校验"><a href="#异或的轮椅-——-奇校验-偶校验" class="headerlink" title="异或的轮椅 —— 奇校验 &amp; 偶校验"></a>异或的轮椅 —— 奇校验 &amp; 偶校验</h3><p>奇偶校验的核心逻辑非常朴素：<strong>统计一组二进制数据中 1 的个数，通过增加 1 位 “校验位”，让 1 的总数保持为奇数或偶数</strong>。</p><p>以原始数据 <code>1011001</code>（共 7 位，其中有 4 个 1）为例：</p><ul><li><strong>偶校验</strong>：已有 4 个 1（偶数），因此校验位为 <code>0</code>，最终编码：<code>1011001 0</code></li><li><strong>奇校验</strong>：已有 4 个 1（偶数），需要补 1 个 1 变成奇数，校验位为 <code>1</code>，最终编码：<code>1011001 1</code></li></ul><p>接收方收到数据后，重新统计 1 的总数，判断奇偶性是否符合约定，即可检测是否出错。<br>这就是奇校验和偶校验，但是光这里是没办法体现出轮椅之处，为什么轮椅呢，因为：<strong>偶校验位就是所有数据位的异或结果；奇校验位就是异或结果取反。</strong><br>$$X = d0 ⊕ d1 ⊕ ... ⊕ dn-1$$<br>这不论是在硬件设计还是软件检验都是非常简单的。同时由于只有一位校验码让他冗余度极低，信息密度极高。</p><h3 id="能力边界与设计哲学"><a href="#能力边界与设计哲学" class="headerlink" title="能力边界与设计哲学"></a>能力边界与设计哲学</h3><p><strong>优势</strong>：</p><ul><li>冗余度极低：n 位数据仅需 1 位校验位</li><li>计算速度极快：仅需统计 1 的个数，硬件上用异或门即可实现</li></ul><p>神也有缺点：</p><p><strong>局限性</strong>：</p><ul><li>只能检测<strong>奇数个比特错误</strong>，无法检测偶数个比特同时翻转的情况</li><li>只能检错，不能纠错 —— 知道错了，但不知道哪一位错了</li><li>错误漏检率较高，仅适用于对可靠性要求不高的场景</li></ul><h2 id="码距与老牧师公式"><a href="#码距与老牧师公式" class="headerlink" title="码距与老牧师公式"></a>码距与老牧师公式</h2><p>这里有个老牧师公式：</p>$$2ʳ ≥ m + r + 1$$<p>其中：</p><ul><li><strong>m</strong> 是数据位</li><li><strong>r</strong> 是校验位</li></ul><p>为什么能这样计算？这要开始<strong>码距</strong>的讲解了。</p><h3 id="什么是码距（汉明距离）？"><a href="#什么是码距（汉明距离）？" class="headerlink" title="什么是码距（汉明距离）？"></a>什么是码距（汉明距离）？</h3><p><strong>码距（Hamming Distance）</strong> 是指两个合法编码之间，对应二进制位不同的个数。</p><ul><li><strong>最小码距</strong> $d_{min}$：在一个编码系统中，任意两个合法码字之间码距的最小值。这是衡量编码抗干扰能力的核心指标。</li></ul><p>你可以将<strong>最小码距</strong> $d_{min}$想象成半径，半径内的数据他都能允许出错，半径越大，容错越高。<br><strong>举例</strong>：</p><ul><li>假定数据 <code>0000</code> <code>0001</code> <code>0010</code> … <code>1111</code>为一组我们约定的合法数据，他们任何一位错误都会变成我们约定的合法数据，因此它们的码距为 1，他们不具有任何容错。</li><li>假定数据 <code>0000</code> <code>0011</code> <code>0101</code> <code>0110</code> <code>1001</code> <code>1010</code> <code>1100</code> <code>1111</code>为一组我们约定的合法数据，他们任何一位错误都有容错，容错位数为 1，因此它们的码距为 2。</li></ul><h3 id="码距与检错、纠错能力的关系"><a href="#码距与检错、纠错能力的关系" class="headerlink" title="码距与检错、纠错能力的关系"></a>码距与检错、纠错能力的关系</h3><p>码距决定了编码能发现多少位错误，以及能纠正多少位错误（假设错误是随机的）：</p><ol><li><strong>检测 $e$ 个错误</strong>：需要 $d_{min} \ge e + 1$<ul><li>如果最小码距是 2，那么随意改变 1 位（产生 1 个错误），一定会变成非法码字（被检测出来）。但如果改变 2 位，可能刚好变成另一个合法码字（无法检测）。</li></ul></li><li><strong>纠正 $t$ 个错误</strong>：需要 $d_{min} \ge 2t + 1$<ul><li>如果要纠正 1 位错误（$t=1$），需要 $d_{min} \ge 3$。</li></ul></li><li><strong>同时检错和纠错</strong>：$d_{min} \ge e + t + 1$（其中 $e > t$）</li></ol><blockquote><p>这里可能很难理解，同样也能视作圆的半径来理解。慢慢梳理和询问请教他人和AI或许是个不错的办法。</p></blockquote><h2 id="海明码：错了！错了！哪错了？错哪了？"><a href="#海明码：错了！错了！哪错了？错哪了？" class="headerlink" title="海明码：错了！错了！哪错了？错哪了？"></a>海明码：错了！错了！哪错了？错哪了？</h2><h3 id="海明有个周末难题"><a href="#海明有个周末难题" class="headerlink" title="海明有个周末难题"></a>海明有个周末难题</h3><p>1950 年，海明发表论文《Error Detecting and Error Correcting Codes》，正式奠定了纠错码理论的基础，这篇论文来自于他的周末难题。<br>贝尔实验室的理查德・海明快被周末的破计算机逼疯了。那时候继电器计算机老出错，一到周末没人值班，错了就直接停机，得等周一重来。<br>海明就吐槽：“机器都能发现错了，就不能自己改过来？” 他就开始琢磨，还真琢磨出来了 —— 不光能查错，还能精准定位到哪一位错了，直接取反就修好。<br>这就是海明码，人类历史上第一种能自动纠错的编码，直接把校验技术从 “检错” 卷到了 “纠错”。</p><h3 id="校验位站-2-的幂次位"><a href="#校验位站-2-的幂次位" class="headerlink" title="校验位站 2 的幂次位"></a>校验位站 2 的幂次位</h3><p>初学者的噩梦之一就是不理解为什么校验位站 2 的幂次位。<br>奇偶校验是一整组只做一次校验，所以只能知道错了，不知道哪错。海明码的思路很巧妙：把数据分到好几个不同的组里，每个组单独做一次奇偶校验。<br>就像猜数字，你问 “比 8 大吗？”“比 4 大吗？”，几个问题下来就能锁定数字。海明码就是用好几组校验的 “对错组合”，精准定位错误的位置。<br>还有一个举例，就像是有x,y坐标一样，给出两个位置你就能找到错误的地方了。<br>哪一位出错，它所在的所有组都会同时出错；反过来，哪几组错了，拼起来就是错误的位置编号。</p><p>下面介绍海明码的规则：</p><ul><li>所有位置是 2 的幂次的比特，都是校验位：第 1、2、4、8、16…… 位，记为 P₁、P₂、P₃……</li><li>剩下的位置塞原始数据位，记为 D₁、D₂、D₃……</li><li>第 k 个校验位，管所有二进制编号第 k 位是 1 的位置</li></ul><p>比如：</p><ul><li>P₁（第 1 位，2⁰）：管 1、3、5、7、9…… 这些位置</li><li>P₂（第 2 位，2¹）：管 2、3、6、7、10…… 这些位置</li><li>P₃（第 4 位，2²）：管 4、5、6、7、12…… 这些位置</li></ul><p>为什么要这么做，我们注意到<span class="heimu" title="你知道的太多了">注意力惊人</span>，2 的幂次正好是像 <code>...0001</code> <code>...0010</code> <code>...0100</code> <code>...1000</code>这种格式，正好能成为对应幂次的校验组。</p><p>这里以 4 位数据 <code>1011</code> 举例，算偶校验的海明码。</p><p><strong>步骤 1：先占位置</strong><br>由于我们要用到上面的老牧师公式，所以这里要<strong>深入理解<del>老牧师</del>公式</strong>。<br>公式本质上是在算 <strong>“状态数”够不够用</strong> 。</p><ul><li>我们总共有 $m + r$ 位（数据位+校验位）。在传输过程中，这 $m+r$ 个位置中<strong>任何一个位置</strong>都可能发生错误。</li><li>加上 <strong>“没有发生错误”</strong> 这一种情况，总共有 $m + r + 1$ 种状态需要被识别。</li><li>我们有 $r$ 个校验位，每个校验位算一次奇偶校验，它们组合起来可以提供 $2^r$ 种不同的校验结果（伴随式 Syndrome）。</li><li>因此，$r$ 个校验位必须能够区分出这 $m + r + 1$ 种状态，即 $2^r \ge m + r + 1$。</li></ul><p>代入数据：$m=4$。</p><ul><li>尝试 $r=2$：$2^2 = 4$，需要区分 $4+2+1 = 7$ 种状态（不够）。</li><li>尝试 $r=3$：$2^3 = 8$，需要区分 $4+3+1 = 8$ 种状态（刚好够）。</li></ul><p>所以根据老牧师公式 4 位数据需要 3 位校验位，总共 7 位。</p><table><thead><tr><th>位置</th><th>1</th><th>2</th><th>3</th><th>4</th><th>5</th><th>6</th><th>7</th></tr></thead><tbody><tr><td>角色</td><td>P₁</td><td>P₂</td><td>D₁</td><td>P₃</td><td>D₂</td><td>D₃</td><td>D₄</td></tr><tr><td>填数据</td><td>?</td><td>?</td><td>1</td><td>?</td><td>0</td><td>1</td><td>1</td></tr></tbody></table><p><strong>步骤 2：挨个算校验位</strong></p><ul><li>P₁管 1、3、5、7 位：数据位有 1、0、1 → 2 个 1（偶）→ P₁&#x3D;0</li><li>P₂管 2、3、6、7 位：数据位有 1、1、1 → 3 个 1（奇）→ P₂&#x3D;1</li><li>P₃管 4、5、6、7 位：数据位有 0、1、1 → 2 个 1（偶）→ P₃&#x3D;0</li></ul><p>本质是做异或运算。</p><p><strong>步骤 3：拼出最终编码</strong><br>按位置填进去：<code>0 1 1 0 0 1 1</code> → 海明码就是 <code>0110011</code></p><p><strong>纠错演示：</strong><br>假设传的时候第 5 位翻了，收到的是 <code>0110111</code>。<br>收方重新算每组的奇偶：</p><ul><li>P₁组：0,1,1,1 → 3 个 1（奇）→ 错了，记 G₁&#x3D;1</li><li>P₂组：1,1,1,1 → 4 个 1（偶）→ 没错，记 G₂&#x3D;0</li><li>P₃组：0,1,1,1 → 3 个 1（奇）→ 错了，记 G₃&#x3D;1</li></ul><p>把 G 拼起来：S₃S₂S₁ &#x3D; 101（二进制）&#x3D; 5（十进制）<br>所以第 5 位错了，把它取反就修好了，就是这么神奇。</p><p>海明码（Hamming Code）的默认最小码距 $d_{min} = 3$。因此，<strong>海明码能够纠正 1 位错误，或者检测出 2 位错误</strong>（纠1检2）。</p><h3 id="海明码的优缺点"><a href="#海明码的优缺点" class="headerlink" title="海明码的优缺点"></a>海明码的优缺点</h3><p><strong>优点：</strong></p><ul><li>能纠错单比特错误：不用重传，自己就修好，对可靠性提升巨大</li><li>冗余度适中：比奇偶校验多几位，但比很多纠错码省</li><li>硬件实现简单：使用异或门，电路不复杂</li></ul><p><strong>缺点：</strong></p><ul><li>只能纠正 1 位错，错 2 位就只能检测不能纠正了</li><li>数据短性价比不高：如 4 位数据就要 3 位校验，校验占将近一半</li><li>连续好几位错的话，就只能好好享受了</li></ul><p>现在电脑里的 ECC 内存，就是海明码的升级版本，服务器、工作站必备，就是为了防止内存比特翻转出错。</p><h2 id="CRC-循环冗余校验：走进现代文明"><a href="#CRC-循环冗余校验：走进现代文明" class="headerlink" title="CRC 循环冗余校验：走进现代文明"></a>CRC 循环冗余校验：走进现代文明</h2><p>前两位如果说都是 “比特级” 的小打小闹，那么 <strong>CRC</strong> 就是 “数据块级” 的工业标准。现在很多情况下你上网、插 U 盘、读硬盘，背后全是 <strong>CRC</strong> 在干活。</p><h3 id="诞生"><a href="#诞生" class="headerlink" title="诞生"></a>诞生</h3><p>1961 年，MIT 的韦斯利・彼得森发表了论文，正式提出循环冗余校验的理论。<br>当年通信和存储发展起来了，大家要传一整块一整块的数据，奇偶校验太弱，海明码又只适合短数据。人们需要一种能对付突发错误、算得又快、还能给大块数据 “盖章” 的技术。<br>CRC 靠着多项式代数的数学 buff，完美踩中了所有需求，慢慢就成了<del>全网</del>通用的标准。<br>以太网、USB、SATA、蓝牙、ZIP 压缩，很多“块”级别的数据都得需要CRC。</p><h3 id="设计原理：多项式模-2-除法"><a href="#设计原理：多项式模-2-除法" class="headerlink" title="设计原理：多项式模 2 除法"></a>设计原理：多项式模 2 除法</h3><p>CRC 的核心思路：把一整串二进制数据当成一个多项式的系数，比如 <code>1011</code> 就对应 <code>x³ + x + 1</code>。<br>通信两边提前约好一个固定的 “生成多项式”，就像约定好一个印章。<br>发件人把数据多项式左移几位，除以这个生成多项式，得到的余数就是 CRC 校验码，附在数据后面发出去。<br>收件人把收到的 “数据 + CRC” 整个除以同一个生成多项式，余数是 0 就说明没坏。</p><p>这里的除法是 “模 2 除法”，也就是按位异或，加法不进位、减法不借位，0+0&#x3D;0，0+1&#x3D;1，1+1&#x3D;0，硬件上常用移位寄存器，因此有着不错的性能。</p><h3 id="计算方式"><a href="#计算方式" class="headerlink" title="计算方式"></a>计算方式</h3><p>拿原始数据 <code>1011001</code>，生成多项式 <code>1001</code>（对应 x³+1，3 次，所以校验码 3 位）举例。</p><p><strong>步骤 1：数据左移 r 位</strong><br>原始数据后面补 3 个 0，变成被除数：<code>1011001000</code></p><p><strong>步骤 2：模 2 除法求余数</strong><br>就跟小学除法竖式一样，只不过减法换成异或：</p><pre class="line-numbers language-txt" data-language="txt"><code class="language-txt">10110010001001        （首位是1，商1，异或除数）---- 01000  0000       （首位是0，商0，异或0）  ----  10010  1001       （首位是1，商1，异或除数）  ----   00000    0000      （首位是0，商0，异或0）    ----     0000      000     （首位是0，商0，异或0）      ----       011    （最后剩下的余数，3位）<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><p>余数是 <code>011</code>，这就是 CRC 校验码。</p><p>最终发出去的就是：原始数据 + CRC → <code>1011001 011</code><br>收方把这一整串除以 1001，余数是 0 就说明没问题（出错的概率不高，当然你错到好处正好测不出我就给你了）。</p><h3 id="生成多项式"><a href="#生成多项式" class="headerlink" title="生成多项式"></a>生成多项式</h3><p>常用的标准多项式有以下几个：</p><ul><li>CRC-8：<code>x⁸+x²+x+1</code>（0x07），常用在小型嵌入式</li><li>CRC-16-CCITT：<code>x¹⁶+x¹²+x⁵+1</code>（0x1021），串口、Modem 常用</li><li>CRC-32：<code>x³²+x²⁶+x²³+x²²+x¹⁶+x¹²+x¹¹+x¹⁰+x⁸+x⁷+x⁵+x⁴+x²+x+1</code>（0x04C11DB7），以太网、文件校验全靠它</li></ul><p>生成多项式的次数就是校验码的位数，比如 CRC-32 就是 32 位校验码，不管你数据是 1 字节还是 1GB，校验码都是固定 32 位。</p><h3 id="CRC-的优缺点"><a href="#CRC-的优缺点" class="headerlink" title="CRC 的优缺点"></a>CRC 的优缺点</h3><p><strong>优点：</strong></p><ul><li>检错能力超强：能查所有单比特错、所有奇数个错、所有长度≤r 的突发错误，长突发错误也大概率能查</li><li>速度极快：硬件上移位寄存器 + 异或门，流水线跑起来，多大的数据都不卡</li><li>开销固定：不管数据多长，校验码就那么长，冗余效率拉满</li></ul><p><strong>缺点：</strong></p><ul><li>只能检错，不能纠错（当然也有变种能纠错，但主流都是检错）</li><li>数学门槛比前两个高，生成多项式不能瞎选，选不好检错能力拉胯</li><li>对故意篡改没辙：这是校验不是加密，改数据同时改 CRC 就能骗过</li></ul><h2 id="对比"><a href="#对比" class="headerlink" title="对比"></a>对比</h2><p>表格</p><table><thead><tr><th>对比维度</th><th>奇偶校验</th><th>海明码</th><th>CRC 循环冗余校验</th></tr></thead><tbody><tr><td>核心能力</td><td>检错（仅奇数位错）</td><td>单比特纠错，双比特检错</td><td>强检错（多比特、突发错误）</td></tr><tr><td>冗余度</td><td>1 位 &#x2F; 任意长度</td><td>约 log₂(n) 位</td><td>固定 r 位（生成多项式决定）</td></tr><tr><td>计算难度</td><td>极低（数 1 的个数）</td><td>中等（分组算）</td><td>低（硬件移位异或）</td></tr><tr><td>验错能力</td><td>单比特、奇数比特错</td><td>单比特错误为主</td><td>单比特、多比特、突发错误</td></tr><tr><td>硬件成本</td><td>极低</td><td>中等</td><td>低</td></tr><tr><td>典型应用</td><td>早期内存、串口通信</td><td>ECC 内存、嵌入式存储</td><td>以太网、USB、SATA、文件校验</td></tr></tbody></table><h2 id="现实中的应用"><a href="#现实中的应用" class="headerlink" title="现实中的应用"></a>现实中的应用</h2><h3 id="奇偶校验"><a href="#奇偶校验" class="headerlink" title="奇偶校验"></a>奇偶校验</h3><ul><li>老设备串口：RS232、PS&#x2F;2 键盘鼠标这些古董接口</li><li>简单嵌入式：资源极度受限的 8 位单片机，偶尔还在用</li><li>基础内存校验：早期的内存条奇偶校验位</li></ul><h3 id="海明码"><a href="#海明码" class="headerlink" title="海明码"></a>海明码</h3><ul><li>ECC 内存：服务器、工作站、工控机的内存，防止单比特翻转</li><li>嵌入式存储：NAND Flash 的页校验，很多用海明码</li><li>航天级设备：对可靠性要求高，单比特错不能停机的场景</li></ul><h3 id="CRC"><a href="#CRC" class="headerlink" title="CRC"></a>CRC</h3><ul><li>计算机网络：以太网、USB、PCIe、蓝牙，几乎所有通信协议</li><li>存储设备：SATA 硬盘、SSD、光盘、U 盘</li><li>文件校验：压缩包、镜像文件的完整性校验</li><li>工业控制：Modbus 等工业总线的通信校验</li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>奇偶校验、海明码、CRC，不是谁取代谁的关系，而是不同场景下的三种设计取舍：</p><p>奇偶校验是 <strong>“成本换够用”</strong> 的极致 —— 用最低的冗余和算力，换最基础的错误检测。它诞生于资源匮乏的年代，却在简单设备里一直活到现在。</p><p>海明码是 <strong>“结构换能力”</strong> 的智慧 —— 用分组交叉校验的设计，第一次实现了自动纠错，告诉人们冗余不光能查错，还能修错。</p><p>CRC 是 <strong>“数学换效率”</strong> 的典范 —— 用多项式代数的数学基础，实现了大块数据的高效校验，成为整个数字工业的底层标配。</p><p>理解校验码，不光是懂了几个计算机知识点，更能体会到工程里的核心哲学：没有完美的方案，只有最适合场景的权衡。用多少冗余换多少可靠性，用多少复杂度换多少能力，这就是工程师每天都在做的选择题。</p><hr><p><strong>小思考：</strong> 为什么你下载大文件的时候，官网经常会给一个 CRC32 或者 MD5 值让你校验？为什么网络传输用 CRC 不用海明码？这里面是效率和成本的取舍。</p>]]>
    </content>
    <id>https://blog.hikari233.qd.je/2026/10/11/%E6%A0%A1%E9%AA%8C%E7%A0%81%EF%BC%9F%E6%A0%A1%E9%AA%8C%EF%BC%8C%E4%B9%9F%E9%9C%80%E8%A6%81%E7%A0%81%EF%BC%9F%E3%80%90%E5%BA%95%E5%B1%82%E7%9A%84%E4%B8%96%E7%95%8C%E2%80%94%E2%80%94%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86%E3%80%91/</id>
    <link href="https://blog.hikari233.qd.je/2026/10/11/%E6%A0%A1%E9%AA%8C%E7%A0%81%EF%BC%9F%E6%A0%A1%E9%AA%8C%EF%BC%8C%E4%B9%9F%E9%9C%80%E8%A6%81%E7%A0%81%EF%BC%9F%E3%80%90%E5%BA%95%E5%B1%82%E7%9A%84%E4%B8%96%E7%95%8C%E2%80%94%E2%80%94%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86%E3%80%91/"/>
    <published>2026-10-11T14:21:42.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>这是本人系列《底层的世界 —— 计算机组成原理》的第三章 —— 校验与纠错，用于记录分享和期末复习，欢迎讨论！</p>
</blockquote>
<blockquote>
<p>引言：数据在路上跑的时候，难免被电磁干扰 “踹一脚”，0 变 1、1]]>
    </summary>
    <title>校验码？校验，也需要码？【底层的世界——计算机组成原理】</title>
    <updated>2026-10-12T16:59:02.831Z</updated>
  </entry>
  <entry>
    <author>
      <name>Hikari</name>
    </author>
    <category term="《底层的世界——计算机组成原理》" scheme="https://blog.hikari233.qd.je/categories/%E3%80%8A%E5%BA%95%E5%B1%82%E7%9A%84%E4%B8%96%E7%95%8C%E2%80%94%E2%80%94%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86%E3%80%8B/"/>
    <category term="计算机组成原理" scheme="https://blog.hikari233.qd.je/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86/"/>
    <category term="浮点数" scheme="https://blog.hikari233.qd.je/tags/%E6%B5%AE%E7%82%B9%E6%95%B0/"/>
    <category term="定点数" scheme="https://blog.hikari233.qd.je/tags/%E5%AE%9A%E7%82%B9%E6%95%B0/"/>
    <category term="数的世界" scheme="https://blog.hikari233.qd.je/tags/%E6%95%B0%E7%9A%84%E4%B8%96%E7%95%8C/"/>
    <category term="《底层的世界——计算机组成原理》" scheme="https://blog.hikari233.qd.je/tags/%E3%80%8A%E5%BA%95%E5%B1%82%E7%9A%84%E4%B8%96%E7%95%8C%E2%80%94%E2%80%94%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86%E3%80%8B/"/>
    <content>
      <![CDATA[<blockquote><p>这是本人系列《底层的世界 —— 计算机组成原理》的第二章 —— 数的世界，用于记录分享和期末复习，欢迎讨论！</p></blockquote><blockquote><p>引言：在计算机的世界里，所有数据最终都以二进制的0和1存储。整数的表示相对简单，但当我们需要处理小数时，问题就变得复杂起来——计算机硬件本身并不认识”小数点”这个符号。为了解决小数的表示与运算问题，人类先后发明了<strong>定点数</strong>和<strong>浮点数</strong>两种方案。它们诞生于不同的时代背景，有着截然不同的设计哲学，至今仍在各自的领域发挥着重要作用。</p></blockquote><h2 id="计算机世界的”小数点”"><a href="#计算机世界的”小数点”" class="headerlink" title="计算机世界的”小数点”"></a>计算机世界的”小数点”</h2><p>小数，生活中非常常见。特别是我染上ds后深深的体会到了：今日吞5毛，明日吞3角，然后得一昔安寝——小数，对我这种穷逼来说，非常重要。<br>但是小数这个概念，根本就不存在于计算机的世界，为了表示数，秃头的老辈子们发明了<strong>定点数</strong>和<strong>浮点数</strong>。</p><h2 id="一、定点数：小数点——约吗？"><a href="#一、定点数：小数点——约吗？" class="headerlink" title="一、定点数：小数点——约吗？"></a>一、定点数：小数点——约吗？</h2><h3 id="什么是定点数？（定点数的定义与背景）"><a href="#什么是定点数？（定点数的定义与背景）" class="headerlink" title="什么是定点数？（定点数的定义与背景）"></a>什么是定点数？（定点数的定义与背景）</h3><p>只有整数怎么办？其中一种表示小数的方法就是把小数定下来。</p><p>定点数是计算机发展早期的产物。在20世纪中叶，计算机硬件极为简陋，运算单元只能处理整数运算，没有专门的浮点运算硬件。为了表示小数，工程师们想出了一个朴素的办法：<strong>人为约定小数点在二进制数位中的固定位置</strong>，这样就可以用整数运算来间接处理小数。</p><blockquote><p>小数点：“约吗？”</p></blockquote><p>例如：十进制的 78.125<br>整数部分：78使用二进制表示为：100 1110<br>小数部分：0.125使用二进制表示为：.001<br>所以合起来使用100 1110.001 表示十进制的78.125<br><del>为什么不是78.91，因为91转2进制除不尽</del></p><h3 id="神秘的表示方式：Q格式"><a href="#神秘的表示方式：Q格式" class="headerlink" title="神秘的表示方式：Q格式"></a>神秘的表示方式：Q格式</h3><blockquote><p>拓展内容，初学者可以不看</p></blockquote><p>定点数最常用的表示方法是<strong>Q格式</strong>（Q notation），其核心思想是将一个整数”放大”一定倍数来表示小数。</p><p><strong>标准格式：Qm.n</strong><br>注解：</p><ul><li><strong>m</strong>：整数部分的位数（不包含符号位）</li><li><strong>n</strong>：小数部分的位数</li><li>总位数 &#x3D; m + n + 1（额外1位是符号位）</li></ul><p>例如，最常见的<strong>Q15格式</strong>（16位有符号数）：</p><ul><li>1位符号位 + 0位整数位 + 15位小数位</li><li>数值范围：-1 ≤ x &lt; 0.9999695</li><li>精度：2⁻¹⁵ ≈ 0.0000305</li></ul><p><strong>残疾人转换公式：</strong></p><ul><li>浮点数 → 定点数：$Q = F × 2^n$ 其中Q为整数</li><li>定点数 → 浮点数：$F = Q × 2^{-n}$</li></ul><p>举个例子，用Q15表示0.5：<br>0.5 × 2¹⁵ &#x3D; 16384 转二进制为100 0000 0000 0000</p><table><thead><tr><th>符号位</th><th>数值</th></tr></thead><tbody><tr><td>0</td><td>100 0000 0000 0000</td></tr></tbody></table><h3 id="定点数的优缺点"><a href="#定点数的优缺点" class="headerlink" title="定点数的优缺点"></a>定点数的优缺点</h3><p><strong>优点：</strong></p><ul><li><strong>运算速度快</strong>：本质是整数运算，无需额外硬件支持</li><li><strong>精度均匀</strong>：整个数值范围内精度保持一致，没有精度漂移</li><li><strong>实现简单</strong>：硬件电路复杂度低，功耗小</li><li><strong>结果确定</strong>：没有舍入误差的累积问题（在不溢出的前提下）</li></ul><p><strong>缺点：</strong></p><ul><li><strong>数值范围小</strong>：同样位数下，能表示的数值范围远小于浮点数<ul><li>32位Q16.15格式：最大值约为2¹⁶ &#x3D; 65536</li><li>32位浮点数：最大值约为3.4×10³⁸</li></ul></li><li><strong>灵活性差</strong>：小数点位置一旦确定就不能更改，需要程序员手动定标</li><li><strong>容易溢出</strong>：运算过程中如果数值超出范围，需要手动处理溢出</li><li><strong>开发难度高</strong>：需要程序员自行管理小数点位置和缩放比例</li></ul><p>这种方案的好处是硬件实现极其简单，只需要整数加法器和移位器就能完成所有运算。早期的单片机、DSP（数字信号处理器）大多采用定点架构，正是因为其成本低、功耗小、速度快。但是随着时间的推移，人们需要更精确的小数运算，这种情况下另一个魔丸要出世了……</p><h2 id="浮点数：老牧师的科学计数法"><a href="#浮点数：老牧师的科学计数法" class="headerlink" title="浮点数：老牧师的科学计数法"></a>浮点数：老牧师的科学计数法</h2><h3 id="魔丸出世"><a href="#魔丸出世" class="headerlink" title="魔丸出世"></a>魔丸出世</h3><p>随着计算机应用向科学计算领域拓展，定点数的局限性越来越明显。物理学家需要表示电子质量（9×10⁻²⁸克），天文学家需要计算恒星距离（数以光年计），这些数值跨度极大，定点数根本无法覆盖。</p><p>为了解决”极大”和”极小”数的表示问题，科学家借鉴了十进制科学计数法的思想——用<br>$$N = (-1)^S \times (1 + M) \times 2^{(E - \text{bias})}$$<br>的形式表示数值，让小数点的位置随指数变化而”浮动”，这就是<strong>浮点数</strong>名称的由来。<br>先别吓晕，我会给你解释一下这一坨到底是什么的，我们先从十进制开始：</p><table><thead><tr><th>普通十进制数</th><th>科学计数法表示</th><th>说明</th></tr></thead><tbody><tr><td>12300</td><td>$1.23 \times 10^4$</td><td>小数点左移4位</td></tr><tr><td>0.00456</td><td>$4.56 \times 10^{-3}$</td><td>小数点右移3位</td></tr><tr><td>-789000</td><td>$-7.89 \times 10^5$</td><td>负数保持符号在尾数前</td></tr><tr><td>9.8</td><td>$9.8 \times 10^0$</td><td>1~10之间的数指数为0</td></tr></tbody></table><p>可以看到十进制科学计数法的表示如下：<br>$$ N = a \times 10^n $$</p><ul><li><strong>a</strong>：尾数，满足 $1 \le |a| < 10$</li><li><strong>n</strong>：指数，整数，代表小数点移动的位数</li></ul><p>那么理解二进制科学计数法也就容易了：<br>$$N = M \times 2^E$$</p><ul><li><strong>M</strong>：尾数</li><li><strong>E</strong>：指数，整数，代表小数点移动的位数</li></ul><p>但是有个问题，在表示科学计数法的时候，我们规定尾数满足 $1 \le |a| < 10$，意思说不规定我们会有许多猎奇的表示方法，比如说用$0.0000001 \times 10^{1000000}$表示1，这你能受的了吗？<br>于是我们规定M必须是1.x开始，这个叫做<strong>浮点数的规格化</strong>，在公式中就能表示成<br>(1 + M)。<br>我们要能表示正负数，又引入了-1的指数S，控制S的值就能控制整个数的正负。<br>完全体如下：<br>$$N = (-1)^S \times (1 + M) \times 2^E$$</p><p>为了统一，1985年，IEEE（电气和电子工程师协会）发布了<strong>IEEE 754标准</strong>，统一了浮点数的表示格式，成为至今通用的工业标准。</p><h3 id="IEEE-754标准"><a href="#IEEE-754标准" class="headerlink" title="IEEE 754标准"></a>IEEE 754标准</h3><p>IEEE 754浮点数由三部分组成：<strong>符号位</strong>、<strong>指数位</strong>、<strong>尾数位</strong>。</p><p><strong>通用公式：</strong><br>$$N = (-1)^S \times (1 + M) \times 2^{(E - \text{bias})}$$</p><h3 id="单精度浮点数（float，32位）"><a href="#单精度浮点数（float，32位）" class="headerlink" title="单精度浮点数（float，32位）"></a>单精度浮点数（float，32位）</h3><table><thead><tr><th>符号位（S）</th><th>指数位（E）</th><th>尾数位（M）</th></tr></thead><tbody><tr><td>1位(0&#x3D;正，1&#x3D;负)</td><td>8位(偏移量为127)</td><td>23位 (隐含整数部分的1)</td></tr></tbody></table><blockquote><p><strong>隐含整数部分</strong>：规格化的二进制浮点数，尾数的最高位总是1。因此这个1可以不用存储，节省了1位空间，实际精度比存储位数多1位。</p></blockquote><p><strong>数值范围：</strong></p><ul><li>最大值：≈ 3.4 × 10³⁸</li><li>最小值（绝对值）：≈ 1.2 × 10⁻³⁸</li></ul><p>为什么要按照<strong>符号位</strong>、<strong>指数位</strong>、<strong>尾数位</strong>的顺序放？这其实跟比大小离不开关系。<br>在计算机中，比大小是一个很重要的运算，在最开始比大小中，很容易的就想到先比正负，之后再看最高位（指数），最后再看尾数M。</p><h3 id="特殊规定"><a href="#特殊规定" class="headerlink" title="特殊规定"></a>特殊规定</h3><p>可以看得出来，在<strong>浮点数的规格化</strong>下，我们没办法表示0，因此我们规定：<strong>将尾数全为 0、同时阶码取到其可表示最小值的浮点数，定义为机器零</strong>。<br>规格化浮点数的核心要求是尾数的最高有效位为 1，目的是保证每个数值的表示形式唯一，同时充分利用尾数的有效位长度、最大化运算精度。但数值 0 的尾数所有位均为 0，天然不满足规格化的形式条件，因此必须作为特殊场景单独约定。<br>在主流的 IEEE 754 浮点数标准中，零的表示规则被进一步细化：</p><ul><li>当阶码字段全部为 0，且尾数字段也全部为 0 时，该浮点数对应数值 0；</li><li>结合符号位的差异，还可以区分<strong>正零（+0）</strong>和<strong>负零（-0）</strong>，二者在数值比较中相等，仅在除以零、极限运算等特殊场景下会体现出符号区别。</li></ul><p>以零的特殊规定为起点，浮点数体系还延伸出了非规格化数、无穷大、非数值（NaN）等一系列特殊值的表示规则，共同完善了浮点数的表示边界，覆盖了从极小数、无穷值到异常运算结果的各类场景。</p><h3 id="双精度浮点数（double，64位）"><a href="#双精度浮点数（double，64位）" class="headerlink" title="双精度浮点数（double，64位）"></a>双精度浮点数（double，64位）</h3><blockquote><p>拓展部分，类比单精度</p></blockquote><table><thead><tr><th>组成部分</th><th>位数</th><th>位置</th><th>说明</th></tr></thead><tbody><tr><td>符号位（S）</td><td>1位</td><td>第63位</td><td>0&#x3D;正，1&#x3D;负</td></tr><tr><td>指数位（E）</td><td>11位</td><td>第62-52位</td><td>偏移量为1023</td></tr><tr><td>尾数位（M）</td><td>52位</td><td>第51-0位</td><td>隐含整数部分的1</td></tr></tbody></table><blockquote><p><strong>隐含整数部分</strong>：规格化的二进制浮点数，尾数的最高位总是1。因此这个1可以不用存储，节省了1位空间，实际精度比存储位数多1位。</p></blockquote><p><strong>数值范围：</strong></p><ul><li>最大值：≈ 1.8 × 10³⁰⁸</li><li>最小值（绝对值）：≈ 2.2 × 10⁻³⁰⁸</li></ul><h3 id="浮点数的优缺点"><a href="#浮点数的优缺点" class="headerlink" title="浮点数的优缺点"></a>浮点数的优缺点</h3><p><strong>优点：</strong></p><ul><li><strong>数值范围极大</strong>：同样位数下，范围远超定点数，适合科学计算</li><li><strong>使用方便</strong>：程序员无需关心小数点位置，编译器自动处理</li><li><strong>标准化程度高</strong>：IEEE 754是通用标准，跨平台一致性好</li><li><strong>支持特殊值</strong>：可以表示无穷大、NaN（非数值）等特殊状态</li></ul><p><strong>缺点：</strong></p><ul><li><strong>精度不均匀</strong>：数值越大，精度越低。靠近0的地方精度很高，远离0的地方精度稀疏<strong>这点要格外注意</strong></li><li><strong>运算速度慢</strong>：需要专门的浮点运算单元（FPU），硬件复杂度高</li><li><strong>存在舍入误差</strong>：很多十进制小数（如0.1）无法用二进制精确表示</li><li><strong>运算有损耗</strong>：多次运算后误差会累积，不能直接用”&#x3D;&#x3D;”比较两个浮点数</li></ul><h2 id="对比"><a href="#对比" class="headerlink" title="对比"></a>对比</h2><table><thead><tr><th>对比维度</th><th>定点数</th><th>浮点数</th></tr></thead><tbody><tr><td>小数点位置</td><td>固定不变</td><td>随指数浮动</td></tr><tr><td>数值范围</td><td>小</td><td>极大</td></tr><tr><td>精度分布</td><td>均匀一致</td><td>近密远疏</td></tr><tr><td>运算速度</td><td>快（整数运算）</td><td>慢（需FPU）</td></tr><tr><td>硬件成本</td><td>低</td><td>高</td></tr><tr><td>开发难度</td><td>高（手动定标）</td><td>低（自动处理）</td></tr><tr><td>典型应用</td><td>嵌入式、DSP、音频处理</td><td>科学计算、图形渲染、通用编程</td></tr></tbody></table><h2 id="现实中的应用"><a href="#现实中的应用" class="headerlink" title="现实中的应用"></a>现实中的应用</h2><h3 id="定点数的主战场"><a href="#定点数的主战场" class="headerlink" title="定点数的主战场"></a>定点数的主战场</h3><ul><li><strong>嵌入式系统</strong>：MCU、单片机等资源受限的设备</li><li><strong>数字信号处理</strong>：音频编解码、滤波、FFT等实时信号处理</li><li><strong>FPGA&#x2F;ASIC设计</strong>：硬件电路中定点运算更省资源</li><li><strong>工业控制</strong>：对确定性要求高，不允许误差累积</li></ul><h3 id="浮点数的天下"><a href="#浮点数的天下" class="headerlink" title="浮点数的天下"></a>浮点数的天下</h3><ul><li><strong>科学计算</strong>：物理模拟、气象预报、航天工程</li><li><strong>计算机图形学</strong>：3D渲染、坐标变换、光照计算</li><li><strong>通用软件开发</strong>：业务系统、数据分析、人工智能</li><li><strong>金融计算</strong>（注意：高精度金融场景通常用十进制定点或BCD码）</li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>定点数和浮点数并非谁取代谁的关系，而是针对不同需求的两种设计取舍：</p><ul><li><p><strong>定点数</strong>是”空间换时间”的极致——用有限的数值范围换取更快的运算速度、更低的硬件成本和均匀的精度。它诞生于资源匮乏的年代，却在嵌入式、DSP等领域历久弥新。</p></li><li><p><strong>浮点数</strong>是”时间换空间”的智慧——用更复杂的运算逻辑换取近乎无限的数值范围和使用上的便利性。它是科学计算的基石，也是现代通用计算机的标配。</p></li></ul><p>理解这两种数值表示方式，不仅能帮我们写出更高效的代码，更能体会到计算机科学中”权衡”与”折中”的设计哲学——没有完美的方案，只有最适合场景的选择。</p><hr><p><strong>小思考</strong>：为什么0.1 + 0.2 在JavaScript和Python中不等于0.3？这正是浮点数二进制表示的经典问题，答案就藏在IEEE 754的尾数精度里。<br>这个问题同样也是数学中0.9无限循环等于1的原因。</p>]]>
    </content>
    <id>https://blog.hikari233.qd.je/2026/10/10/%E6%B5%AE%E7%82%B9%E6%95%B0%E5%AE%9A%E7%82%B9%E6%95%B0%E5%88%B0%E5%BA%95%E6%98%AF%E4%BB%80%E4%B9%88%E5%8B%BE%E5%90%A7%EF%BC%9F%E3%80%90%E5%BA%95%E5%B1%82%E7%9A%84%E4%B8%96%E7%95%8C%E2%80%94%E2%80%94%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86%E3%80%91/</id>
    <link href="https://blog.hikari233.qd.je/2026/10/10/%E6%B5%AE%E7%82%B9%E6%95%B0%E5%AE%9A%E7%82%B9%E6%95%B0%E5%88%B0%E5%BA%95%E6%98%AF%E4%BB%80%E4%B9%88%E5%8B%BE%E5%90%A7%EF%BC%9F%E3%80%90%E5%BA%95%E5%B1%82%E7%9A%84%E4%B8%96%E7%95%8C%E2%80%94%E2%80%94%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E6%88%90%E5%8E%9F%E7%90%86%E3%80%91/"/>
    <published>2026-10-10T14:31:46.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p>这是本人系列《底层的世界 —— 计算机组成原理》的第二章 —— 数的世界，用于记录分享和期末复习，欢迎讨论！</p>
</blockquote>
<blockquote>
<p>引言：在计算机的世界里，所有数据最终都以二进制的0和1存储。整数的表示]]>
    </summary>
    <title>浮点数定点数到底是什么勾吧？【底层的世界——计算机组成原理】</title>
    <updated>2026-10-12T12:07:31.716Z</updated>
  </entry>
  <entry>
    <author>
      <name>Hikari</name>
    </author>
    <category term="闲聊吹水" scheme="https://blog.hikari233.qd.je/tags/%E9%97%B2%E8%81%8A%E5%90%B9%E6%B0%B4/"/>
    <category term="古法编程" scheme="https://blog.hikari233.qd.je/tags/%E5%8F%A4%E6%B3%95%E7%BC%96%E7%A8%8B/"/>
    <content>
      <![CDATA[<h2 id="野人时代"><a href="#野人时代" class="headerlink" title="野人时代"></a>野人时代</h2><p>如果是在2024年前，那你可能会认为是写汇编写C就是古法编程。<br>但在today，这个说法已经扩展到用编辑器敲任何代码都叫古法编程了。在这个连牢理<code>@Mashiro_Neri</code>都能靠大肥鱼写出复杂逻辑的代码的今天（能不能用你别管），坚持手敲代码，看起来就像是原始人。<br>本人在25年是一个合格的古人，古到哪种程度呢？古到什么都是自己写。红石镇的bot是我手写的，说实话我真佩服以前的我，在牢理<code>@Mashiro_Neri</code>套docker，使用nas和不稳定的环境，无本地bot框架和测试环境的情况下半天内完成了对插件基础功能的开发。<br>在学校中在同学豆包play完成实验报告的情况下我依旧手写，发挥匠人精神，可惜这种日子将在下半年结束……</p><h2 id="【光神个人汉化】ひかり君のインテリジェントエージェントプログラミング初体験-1"><a href="#【光神个人汉化】ひかり君のインテリジェントエージェントプログラミング初体験-1" class="headerlink" title="【光神个人汉化】ひかり君のインテリジェントエージェントプログラミング初体験(1)"></a>【光神个人汉化】ひかり君のインテリジェントエージェントプログラミング初体験(1)</h2><p>在25年之前，我一直想着手写代码来训练自己的基本能力，毕竟AI是黑奴，指挥黑奴你得学会怎么指挥，光拿鞭子抽只会事倍功半。<br>直到寒假过后，嵌入式课程，他来了……<br>我们的嵌入式是我们前院长（现在是副院长，大佬实在太忙碌了所以退去了院长职位），他告诉我们：</p><blockquote><p>“AI编程是要搞的，不搞不行！”</p></blockquote><p>我就开始了AI玩耍了，但是玩耍AI也没有正儿八经的使用AI编程工具，还在属于比较抵触的阶段。<br>AI编程属于比较不可控的过程，因为代码不是你自己写的，安全性跟可靠性一直是未知数，并且依赖AI你会失去手写代码的神力，所以在此阶段我一直是比较克制的使用AI（只使用网页对话）。<br>我深深的体会到了网页版的局限性：<br>1.AI不能直接操作</p><ul><li>这一点很明显，所有的操作你得自己来</li></ul><p>2.免费版的网页模型是傻子</p><ul><li>即使是深度思考，所体会出来的智慧简直是天差地别</li></ul><p>3.网页对话有 token 上限：</p><ul><li>很难一次性读懂完整项目；只能复制粘贴片段，无法自动读取整个项目目录；</li><li>多文件项目需要手动反复粘贴各个文件代码，容易丢失上下文，改代码容易出现前后不一致</li></ul><p>但压死最后一根稻草的骆驼（这句话没绷住）是因为25年4月老师发的一条消息：<br><img src="/images/pages/26-9-29-p1.png" alt="嵌入式已进入寒冬"></p><blockquote><p>“嵌入式已进入寒冬。”</p></blockquote><p>封面是老英雄，设敬！<br>我也绝得是时候真正进入AI编程了。</p><h2 id="AI编程耍起嘛"><a href="#AI编程耍起嘛" class="headerlink" title="AI编程耍起嘛"></a>AI编程耍起嘛</h2><p>对于AI，其实我一直都有学习，什么多模态，Agent，skill等词汇我这个古人也是略知一二，<del>但是国外的月亮我是一点都没见到过</del><br>众所周知，AI编程有两种：<br>一种是AI智能补全<br>另一种是Agent<br>AI智能补全对我来说没啥吸引力就索性不玩了，直接开始了Agent玩耍，可没想进入了魔窟……</p><blockquote><p>从前的我已经死了。</p></blockquote><p>耍起嘛，耍起嘛，AI编程耍起嘛</p><h3 id="Agent是什么？"><a href="#Agent是什么？" class="headerlink" title="Agent是什么？"></a>Agent是什么？</h3><p>用deepseek的话来说是这样：</p><blockquote><p>Agent（智能体 &#x2F; 代理），简单说就是：能感知环境、自己做决策、采取行动，以完成某个目标的系统或程序。它不一定是有实体的机器人，也可以是一段软件。<br>今天大家说“Agent”，多数时候特指 AI Agent &#x2F; LLM Agent，也就是以大语言模型为“大脑”的智能体。<br>可以把它理解成：<br>Agent &#x3D; 大模型 + 记忆 + 工具 + 规划 + 执行循环<br>AI Agent 的核心组成<br>模型&#x2F;大脑：负责理解任务、推理、决策，比如 GPT、Claude 等。<br>感知：读取用户输入、网页、数据库、API 返回、文件、传感器等信息。<br>规划：把大目标拆成小步骤，决定先做什么、后做什么，失败后怎么重试。<br>记忆：短期记忆当前对话，长期记忆用户偏好、历史任务、知识库。<br>工具：搜索、写代码、发邮件、查数据库、操作浏览器、调用 API。<br>执行：真正采取行动，而不只是输出一段文字。<br>循环：观察 → 思考 → 行动 → 看结果 → 再调整，直到完成目标。<br>和普通聊天机器人的区别<br>普通聊天机器人主要是：你问，它答。<br>Agent 更像是：你给目标，它自己想办法一步步完成。</p><p>比如：<br>聊天机器人：告诉你“如何订机票”。<br>Agent：查航班、比价、填信息、调用支付接口，最后把票订好。<br>常见类型<br>单 Agent：一个智能体独立完成任务。<br>多 Agent 系统：多个 Agent 分工协作，比如一个写代码、一个测试、一个审查。<br>强化学习 Agent：在环境中不断试错，学习最优策略。<br>软件 Agent：如监控 Agent、代理服务器、User-Agent 等，是更传统的“代理程序”含义。<br>Agent 是一个能自主规划并采取行动来完成目标的智能代理；在 AI 语境下，通常指以 LLM 为核心、能调用工具和多步执行的智能体。</p></blockquote><h2 id="【光神个人汉化】ひかり君のインテリジェントエージェントプログラミング初体験-2"><a href="#【光神个人汉化】ひかり君のインテリジェントエージェントプログラミング初体験-2" class="headerlink" title="【光神个人汉化】ひかり君のインテリジェントエージェントプログラミング初体験(2)"></a>【光神个人汉化】ひかり君のインテリジェントエージェントプログラミング初体験(2)</h2><p>在牢理<code>@Mashiro_Neri</code>跟柠檬<code>@LecitronArts</code>的嘲讽下，我终于是下载了opencode<br><img src="/images/pages/26-9-29-p2.png" alt="嘲讽记录"><br>然后我完成了第一个项目————迁移dsh计费插件，转化为vsc插件<br><img src="/images/pages/26-9-29-p3.png" alt="换皮肥鱼"><br>这是使用dsv4.1f完成迁移的项目，人物是用官方立绘投给了豆包得到的，一共花费了1.9rmb<br>项目本身的问题很快就出现了</p><ul><li>一是项目在实时模式下冷启动的问题，同时前后端显示有一定延迟，不同步</li><li>二是角色换图片后没办法换回去</li><li>三是第一次点击大肥鱼没办法鸭子叫<del>，让我十分愤怒</del></li></ul><p>将这些bug描述后，很快就给我解决了（30min 愉快的刷起了抖音）<br>在我喜欢看AI干了什么，因为 Agent 能“行动”，所以风险比聊天机器人更大：<br>可能误操作（删除正确代码）、被提示注入攻击（中转站耍起）、泄露数据（直接发布密码到公开仓库）、乱花钱（这是对的大肥鱼，吃白饭耍起嘛）、调用错误工具（听不懂话的傻福模型）<br>因此通常需要权限控制、沙箱、审计日志、人类确认<br><del>当然无视风险继续安装的人也不少，丢掉大脑直接权限全开</del><br>这时候我对Agent的期待拉满了，什么都想AI干，但是这种日子总有苦头……<br>未完待续。</p><h2 id="AI趣事"><a href="#AI趣事" class="headerlink" title="AI趣事"></a>AI趣事</h2><h3 id="p1"><a href="#p1" class="headerlink" title="p1"></a>p1</h3><p>事实上多数计算机专业的同学并没怎么了解使用过AI，他们跟AI的提示词多半是这样：</p><blockquote><p>我饿了给我炒俩菜</p></blockquote><p>而不是跟我这种原始人第一次用一样：</p><blockquote><p>我需要番茄炒鸡蛋，使用的技术栈是大锅柴火灶，需要勾芡浓汤收汁，适当加入白糖提鲜</p></blockquote><p>所以说AI是振幅器。<br>室友跟我开玩笑，说AI虽然很舒服但是一点都不强，我就开玩笑的回复到：你用得最多的估计是豆包拍照搜题<br><del>这也是为什么他们认为AI编程还处于一个拉跨阶段的原因之一</del></p><h3 id="p2"><a href="#p2" class="headerlink" title="p2"></a>p2</h3><p>其实理解也是个沙雕：<br><img src="/images/pages/26-9-29-p4.png" alt="沙雕记录"></p><blockquote><p>“不需要下载终端环境，下插件就能用。”</p></blockquote>]]>
    </content>
    <id>https://blog.hikari233.qd.je/2026/09/29/AI%E7%BC%96%E7%A8%8B%E8%80%8D%E8%B5%B7%E5%98%9B/</id>
    <link href="https://blog.hikari233.qd.je/2026/09/29/AI%E7%BC%96%E7%A8%8B%E8%80%8D%E8%B5%B7%E5%98%9B/"/>
    <published>2026-09-29T14:56:29.000Z</published>
    <summary>
      <![CDATA[<h2 id="野人时代"><a href="#野人时代" class="headerlink" title="野人时代"></a>野人时代</h2><p>如果是在2024年前，那你可能会认为是写汇编写C就是古法编程。<br>但在today，这个说法已经扩展到用编辑器敲任何代码都]]>
    </summary>
    <title>AI编程耍起嘛</title>
    <updated>2026-10-10T14:34:12.222Z</updated>
  </entry>
  <entry>
    <author>
      <name>Hikari</name>
    </author>
    <category term="技术杂谈" scheme="https://blog.hikari233.qd.je/categories/%E6%8A%80%E6%9C%AF%E6%9D%82%E8%B0%88/"/>
    <category term="闲聊吹水" scheme="https://blog.hikari233.qd.je/tags/%E9%97%B2%E8%81%8A%E5%90%B9%E6%B0%B4/"/>
    <category term="技术杂谈" scheme="https://blog.hikari233.qd.je/tags/%E6%8A%80%E6%9C%AF%E6%9D%82%E8%B0%88/"/>
    <category term="蓝桥杯" scheme="https://blog.hikari233.qd.je/tags/%E8%93%9D%E6%A1%A5%E6%9D%AF/"/>
    <category term="编程比赛" scheme="https://blog.hikari233.qd.je/tags/%E7%BC%96%E7%A8%8B%E6%AF%94%E8%B5%9B/"/>
    <content>
      <![CDATA[<h2 id="一、蓝桥杯之死"><a href="#一、蓝桥杯之死" class="headerlink" title="一、蓝桥杯之死"></a>一、蓝桥杯之死</h2><p>首先给图<br><img src="https://pic1.zhimg.com/v2-eb5504d02063cdadff781eca4a19ceb4_r.jpeg" alt="这是图片"><br><a href="https://dasai.lanqiao.cn/notices/1708">官网链接</a><br>蓝桥杯的离去好像在人们意料之中。</p><blockquote><p>“一个点击就送的水赛，奖项有什么含金量？难道在简历里写上蓝桥杯是一件很自豪的事吗？”</p></blockquote><p>可能也与选手<a href="https://news.cctv.com/2025/05/02/ARTIHonCWOnZpwvqLrhxmDms250502.shtml">大规模作弊</a>有关</p><h2 id="二、回顾蓝桥杯"><a href="#二、回顾蓝桥杯" class="headerlink" title="二、回顾蓝桥杯"></a>二、回顾蓝桥杯</h2><p>说真的，我是真绷不住了，虽然圈钱杯名号早有耳闻，但是没想到的是这么快就死了。<br>ACM，CCF CACC压力暴大，大佬云集。（学校也没队，菜鸡玩不了一点）。因此我选择了参加了蓝桥杯，作为大一上学期为了练手参加的比赛也没想这么多，但没想到省赛是真抽象。<br>怎么个抽象法？byd我旁边的兄弟直接做了几题后直接走了。wtf？不是兄弟300块报名费大风吹来的啊？<br>其实在场的差不多都是这个状态，但还有些兄弟在蒸。可以看出大家水平都不高，这也让第一次参赛的我放心了。<br>比赛是内网进行的，但我发现电脑上有很多IDE工具可以使用，于是我想都没想就用了我最喜欢用的VSC，直到开赛后30分钟左右我都写完3道题后监管老师才看到我用VSC，提醒我不能用VSC。我当时就懵逼了，我不用VSC我用啥啊？但我也没多想，询问了老师我能用什么IDE，他竟然说不知道，让我用记事本写。<br>没错，记事本。</p><blockquote><p>“如果你是C语言和Java组的同学，写不下去了可以看看隔壁用记事本的python组同学。”<br>——Hikari《悲伤回忆录》</p></blockquote><p>这次经历让我觉得这个比赛是真的松，你甚至能在厕所当战神。不出意外，这届蓝桥杯出现了学校大规模作弊的情况。<a href="https://www.zhihu.com/question/1901701298623067681">如何看待蓝桥杯大赛处理作弊选手 1133 人？为什么会有这么多人作弊？</a><br>今年的一堆名不见传的学校冒了一大堆省一。你甚至能看到有的参赛地甚至不是内网机房比赛的，是自带笔记本比赛的。<br>还有更逆天的吗？有的兄弟，有的。<br>国赛不让看获奖pdf的来咯。官方的理由是省赛获奖名单被发现某些学校大量作弊后决定不再公布获奖名单。<br>这波操作真的怎么看都不是正常人能想出来的操作。这不是在包庇作弊行为吗？</p><p>烂到骨子里了，可能这次就是纯作死作的。</p>]]>
    </content>
    <id>https://blog.hikari233.qd.je/2025/10/20/%E4%BA%A1%E5%A6%BB%E5%9B%9E%E5%BF%86%E5%BD%95(%E8%93%9D%E6%A1%A5%E6%9D%AF)/</id>
    <link href="https://blog.hikari233.qd.je/2025/10/20/%E4%BA%A1%E5%A6%BB%E5%9B%9E%E5%BF%86%E5%BD%95(%E8%93%9D%E6%A1%A5%E6%9D%AF)/"/>
    <published>2025-10-20T14:42:24.000Z</published>
    <summary>
      <![CDATA[<h2 id="一、蓝桥杯之死"><a href="#一、蓝桥杯之死" class="headerlink" title="一、蓝桥杯之死"></a>一、蓝桥杯之死</h2><p>首先给图<br><img src="https://pic1.zhimg.com/v2-eb5504]]>
    </summary>
    <title>亡妻回忆录(蓝桥杯)</title>
    <updated>2026-10-23T16:55:59.570Z</updated>
  </entry>
  <entry>
    <author>
      <name>Hikari</name>
    </author>
    <content>
      <![CDATA[<h2 id="这篇文章用于测试评论系统"><a href="#这篇文章用于测试评论系统" class="headerlink" title="这篇文章用于测试评论系统"></a>这篇文章用于测试评论系统</h2><p>聪明的人已经在这两天发现了评论系统上线了🤫<br>最开始是用的giscus，发现是屎（这个项目已经残了，表情表情用不了，消息消息发不了）<br>后面就使用了<a href="https://twikoo.js.org/">Twikoo</a>，也就是现在的系统<br>欢迎来到我的博客评论<del>jm号不能发，nsfw也不能发，篇子也不能发，发给我没这些限制</del></p>]]>
    </content>
    <id>https://blog.hikari233.qd.je/2025/10/14/%E5%8D%9A%E5%AE%A2%E8%AF%84%E8%AE%BA%E7%B3%BB%E7%BB%9F%E6%B5%8B%E8%AF%95/</id>
    <link href="https://blog.hikari233.qd.je/2025/10/14/%E5%8D%9A%E5%AE%A2%E8%AF%84%E8%AE%BA%E7%B3%BB%E7%BB%9F%E6%B5%8B%E8%AF%95/"/>
    <published>2025-10-14T15:54:39.000Z</published>
    <summary>
      <![CDATA[<h2 id="这篇文章用于测试评论系统"><a href="#这篇文章用于测试评论系统" class="headerlink" title="这篇文章用于测试评论系统"></a>这篇文章用于测试评论系统</h2><p>聪明的人已经在这两天发现了评论系统上线了🤫<br>最开始是]]>
    </summary>
    <title>博客评论系统测试</title>
    <updated>2026-10-10T14:23:42.116Z</updated>
  </entry>
  <entry>
    <author>
      <name>Hikari</name>
    </author>
    <category term="猎奇" scheme="https://blog.hikari233.qd.je/tags/%E7%8C%8E%E5%A5%87/"/>
    <category term="暴力" scheme="https://blog.hikari233.qd.je/tags/%E6%9A%B4%E5%8A%9B/"/>
    <content>
      <![CDATA[<p>这是一篇测试文章，用于验证博客的核心渲染能力。</p><h2 id="文本格式基础测试​"><a href="#文本格式基础测试​" class="headerlink" title="文本格式基础测试​"></a>文本格式基础测试​</h2><h3 id="标题层级​"><a href="#标题层级​" class="headerlink" title="标题层级​"></a>标题层级​</h3><p>略</p><h3 id="三级标题"><a href="#三级标题" class="headerlink" title="三级标题"></a>三级标题</h3><h3 id="Inline-格式​"><a href="#Inline-格式​" class="headerlink" title="Inline 格式​"></a>Inline 格式​</h3><p>加粗文本：<strong>加粗文本</strong>​<br>斜体文本：<em>斜体文本</em>​<br>加粗斜体：<em><strong>加粗斜体</strong></em>​<br>删除线：<del>删除线</del>​<br>行内代码：<code>printf(&quot;hello world&quot;)</code>​<br>超链接：</p><ul><li>外部链接：<a href="URL">这是一个超链接</a></li><li>内部锚点：点击跳转到<a href="#%E6%96%87%E6%9C%AC%E6%A0%BC%E5%BC%8F%E5%9F%BA%E7%A1%80%E6%B5%8B%E8%AF%95%E2%80%8B">一、文本格式基础测试​</a></li></ul><h3 id="DLC：黑幕"><a href="#DLC：黑幕" class="headerlink" title="DLC：黑幕"></a>DLC：黑幕</h3><span class="heimu" title="你知道的太多了">这里什么有没有</span><h2 id="代码高亮专项测试"><a href="#代码高亮专项测试" class="headerlink" title="代码高亮专项测试"></a>代码高亮专项测试</h2><p>hexo自带的代码高亮太几把好看了，建议还是去高亮官网调。这里用的是棱镜<a href="https://prismjs.com/">Prism</a>​进行的代码高亮。<br>这里用最经典的杨辉三角来展示代码高亮吧。​</p><h3 id="Python"><a href="#Python" class="headerlink" title="Python"></a>Python</h3><pre class="line-numbers language-python" data-language="python"><code class="language-python">n<span class="token operator">=</span><span class="token builtin">int</span><span class="token punctuation">(</span><span class="token builtin">input</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>nums<span class="token operator">=</span><span class="token punctuation">[</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">*</span>n <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token comment">#初始化一个n*n的零阵</span><span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">:</span>    <span class="token keyword">for</span> j <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span>n<span class="token punctuation">)</span><span class="token punctuation">:</span>        <span class="token keyword">if</span> j<span class="token operator">==</span><span class="token number">0</span><span class="token punctuation">:</span>            nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token operator">=</span><span class="token number">1</span>        <span class="token keyword">else</span><span class="token punctuation">:</span>            nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token operator">=</span>nums<span class="token punctuation">[</span>i<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token operator">+</span>nums<span class="token punctuation">[</span>i<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span>        <span class="token keyword">if</span> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token operator">!=</span><span class="token number">0</span><span class="token punctuation">:</span>            <span class="token keyword">print</span><span class="token punctuation">(</span>nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">,</span>end<span class="token operator">=</span><span class="token string">' '</span><span class="token punctuation">)</span>    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h3 id="C-C"><a href="#C-C" class="headerlink" title="C&#x2F;C++"></a>C&#x2F;C++</h3><pre class="line-numbers language-c" data-language="c"><code class="language-c"><span class="token macro property"><span class="token directive-hash">#</span><span class="token directive keyword">include</span><span class="token string">&lt;stdio.h></span></span><span class="token keyword">int</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>    <span class="token keyword">int</span> map<span class="token punctuation">[</span><span class="token number">10</span><span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">10</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span class="token number">0</span><span class="token punctuation">&#125;</span><span class="token punctuation">;</span><span class="token comment">//10*10的二维0数组为进行操作</span>    <span class="token comment">/*分析，最左列为1，因此从第2列考虑    公式：ls[i][j]=ls[i-1][j-1]+ls[i-1][j]*/</span>    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token comment">//初始化最左列</span>        map<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span>    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> j <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>                map<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> map<span class="token punctuation">[</span>i<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token operator">+</span>map<span class="token punctuation">[</span>i<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span>    <span class="token punctuation">&#125;</span>    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator">&lt;</span> <span class="token number">10</span><span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>            <span class="token keyword">if</span> <span class="token punctuation">(</span>map<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token comment">//不输出0</span>                <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"%5d"</span><span class="token punctuation">,</span>map<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>            <span class="token punctuation">&#125;</span>        <span class="token punctuation">&#125;</span>        <span class="token function">printf</span><span class="token punctuation">(</span><span class="token string">"\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>    <span class="token punctuation">&#125;</span>    <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span><span class="token punctuation">&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h3 id="JavaScript"><a href="#JavaScript" class="headerlink" title="JavaScript"></a>JavaScript</h3><pre class="line-numbers language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">function</span> <span class="token function">yanghui</span><span class="token punctuation">(</span><span class="token parameter">row</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>   <span class="token comment">// 创建一维数组</span>   <span class="token keyword">var</span> arr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Array</span><span class="token punctuation">(</span>row<span class="token punctuation">)</span><span class="token punctuation">;</span>   <span class="token comment">// 创建二维数组</span>   <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> arr<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>       arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Array</span><span class="token punctuation">(</span>i <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>   <span class="token punctuation">&#125;</span>   <span class="token comment">// 循环赋值</span>   <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> arr<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>       <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator">&lt;</span> arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>length<span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>           <span class="token keyword">if</span> <span class="token punctuation">(</span>j <span class="token operator">===</span> <span class="token number">0</span> <span class="token operator">||</span> i <span class="token operator">===</span> j<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>               arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token comment">// 首尾赋值为1</span>           <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>               arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">=</span> arr<span class="token punctuation">[</span>i <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">+</span> arr<span class="token punctuation">[</span>i <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">[</span>j <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// 中间值为上一行两个相邻数字之和</span>           <span class="token punctuation">&#125;</span>       <span class="token punctuation">&#125;</span>   <span class="token punctuation">&#125;</span>   <span class="token comment">// 打印三角</span>   <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> arr<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>       <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator">&lt;</span> arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>length<span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>           document<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">+</span> <span class="token string">" "</span><span class="token punctuation">)</span><span class="token punctuation">;</span>       <span class="token punctuation">&#125;</span>       document<span class="token punctuation">.</span><span class="token function">write</span><span class="token punctuation">(</span><span class="token string">"&lt;br/>"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>   <span class="token punctuation">&#125;</span><span class="token punctuation">&#125;</span><span class="token comment">// 调用函数，生成5行的杨辉三角</span><span class="token function">yanghui</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h3 id="HTML-CSS-代码"><a href="#HTML-CSS-代码" class="headerlink" title="HTML + CSS 代码"></a>HTML + CSS 代码</h3><pre class="line-numbers language-markup" data-language="markup"><code class="language-markup"><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>zh-CN<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">></span></span>代码高亮测试页面<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>style</span><span class="token punctuation">></span></span><span class="token style"><span class="token language-css">        <span class="token selector">.code-block</span> <span class="token punctuation">&#123;</span>            <span class="token property">background-color</span><span class="token punctuation">:</span> #f5f5f5<span class="token punctuation">;</span>            <span class="token property">border-radius</span><span class="token punctuation">:</span> 4px<span class="token punctuation">;</span>            <span class="token property">padding</span><span class="token punctuation">:</span> 16px<span class="token punctuation">;</span>            <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token string">"Consolas"</span><span class="token punctuation">,</span> monospace<span class="token punctuation">;</span>            <span class="token property">overflow-x</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span> <span class="token comment">/* 处理长代码换行 */</span>        <span class="token punctuation">&#125;</span>        <span class="token selector">.title</span> <span class="token punctuation">&#123;</span>            <span class="token property">color</span><span class="token punctuation">:</span> #2c3e50<span class="token punctuation">;</span>            <span class="token property">font-size</span><span class="token punctuation">:</span> 24px<span class="token punctuation">;</span>            <span class="token property">font-weight</span><span class="token punctuation">:</span> 600<span class="token punctuation">;</span>        <span class="token punctuation">&#125;</span>    </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>style</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>title<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>代码高亮演示<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">></span></span>    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>code-block<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>        // 这里是示例代码        console.log("Hello, Code Highlight!");    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">></span></span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h3 id="无语言指定代码块"><a href="#无语言指定代码块" class="headerlink" title="无语言指定代码块"></a>无语言指定代码块</h3><pre class="line-numbers language-none"><code class="language-none">井inculde 《stdio。h》viod main()&#123;    char【10】c&#x3D;“hello world”；    pRintf（“%f”，c）；&#125;<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span></span></code></pre><h2 id="图片测试"><a href="#图片测试" class="headerlink" title="图片测试"></a>图片测试</h2><p><img src="/images/head.jpg" alt="这是图片" title="这里是图片注释"></p><h2 id="列表功能测试"><a href="#列表功能测试" class="headerlink" title="列表功能测试"></a>列表功能测试</h2><p>以下分别测试无序列表和有序列表。</p><h3 id="2-1-无序列表"><a href="#2-1-无序列表" class="headerlink" title="2.1 无序列表"></a>2.1 无序列表</h3><ul><li>测试项 1：无序列表默认样式</li><li>测试项 2：嵌套无序列表<ul><li>嵌套子项 A</li><li>嵌套子项 B</li></ul></li><li>测试项 3：列表与段落结合<br>这是列表项后的补充段落，用于验证列表与正文的间距和排版是否正常。</li></ul><h3 id="2-2-有序列表"><a href="#2-2-有序列表" class="headerlink" title="2.2 有序列表"></a>2.2 有序列表</h3><ol><li>第一步：创建测试文档</li><li>第二步：添加各类格式内容<ol><li>子步骤 1：插入代码块</li><li>子步骤 2：插入表格</li></ol></li><li>第三步：预览并验证效果</li></ol><h2 id="引用与表格测试"><a href="#引用与表格测试" class="headerlink" title="引用与表格测试"></a>引用与表格测试</h2><h3 id="引用功能"><a href="#引用功能" class="headerlink" title="引用功能"></a>引用功能</h3><p>引用常用于引用外部观点或重要提示，测试长文本引用的换行和缩进效果：</p><blockquote><p>“Markdown 是一种轻量级标记语言，它允许人们使用易读易写的纯文本格式编写文档，然后转换成有效的 XHTML（或者 HTML）文档。”<br>—— 引自 Markdown 官方说明</p></blockquote><h3 id="表格功能"><a href="#表格功能" class="headerlink" title="表格功能"></a>表格功能</h3><p>表格用于展示结构化数据，测试表头、单元格对齐及内容换行效果：</p><table><thead><tr><th>功能模块</th><th>测试内容</th><th>预期效果</th></tr></thead><tbody><tr><td>文字格式</td><td>粗体、斜体、删除线</td><td>样式清晰，无错乱</td></tr><tr><td>代码高亮</td><td>多语言代码块</td><td>语法颜色区分明显</td></tr><tr><td>列表</td><td>嵌套列表、列表+段落</td><td>层级分明，间距合理</td></tr><tr><td>表格</td><td>多列数据、单元格换行</td><td>边框完整，内容居中对齐</td></tr></tbody></table><h2 id="数学公式"><a href="#数学公式" class="headerlink" title="数学公式"></a>数学公式</h2><h3 id="行内"><a href="#行内" class="headerlink" title="行内"></a>行内</h3><pre class="line-numbers language-katex" data-language="katex"><code class="language-katex">$E&#x3D;mc^2$<span aria-hidden="true" class="line-numbers-rows"><span></span></span></code></pre>$E=mc^2$<h3 id="多行"><a href="#多行" class="headerlink" title="多行"></a>多行</h3><pre class="line-numbers language-katex" data-language="katex"><code class="language-katex">$$m \mathbf&#123;a&#125; &#x3D; \mathbf&#123;F&#125;_&#123;total&#125; &#x3D; \mathbf&#123;F&#125;_&#123;thrust&#125; + \mathbf&#123;F&#125;_&#123;gravity&#125; + \ldots$$<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre>$$m \mathbf{a} = \mathbf{F}_{total} = \mathbf{F}_{thrust} + \mathbf{F}_{gravity} + \ldots$$<h2 id="流程图"><a href="#流程图" class="headerlink" title="流程图"></a>流程图</h2><p>流程图是一种有效展示封闭系统运动状态的图形形式，可以帮助管理者和实现者清晰地认识系统运转流程。Markdown 的原生语法不支持绘制图形，但通过 Mermaid 扩展，我们可以将一些格式化的文字渲染成我们需要的图形。</p><h3 id="基本语法"><a href="#基本语法" class="headerlink" title="基本语法"></a>基本语法</h3><p>流程图的基本语法包含三个部分：流程图布局方向、几何图形和连接线。以下是一个简单的 Markdown 流程图示例，采用 Mermaid 语法：</p><pre class="line-numbers language-markdown_mermaid" data-language="markdown_mermaid"><code class="language-markdown_mermaid">flowchart LR开始 --&gt; 结束复制graph LR;：指定这是一个有向图。<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre><p>节点以及节点之间的关系通过 –&gt; 来表示。</p><p>方框中的文字表示节点的名称，例如 A[开始] 表示开始节点。</p><p>定义元素</p><p>流程图的元素包括标签、类型和内容。标签用于连接元素时使用，类型有六种：开始（start）、结束（end）、操作（operation）、子流程（subroutine）、条件（condition）和输入输出（inputoutput）。例如：</p><pre class="line-numbers language-markdown_mermaid" data-language="markdown_mermaid"><code class="language-markdown_mermaid">st&#x3D;&gt;start: Starte&#x3D;&gt;end: Endop1&#x3D;&gt;operation: My Operationcond&#x3D;&gt;condition: Yes or No?<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span></span></code></pre><h3 id="连接元素"><a href="#连接元素" class="headerlink" title="连接元素"></a>连接元素</h3><p>使用 -&gt; 符号连接元素，例如：</p><pre class="line-numbers language-markdown_mermaid" data-language="markdown_mermaid"><code class="language-markdown_mermaid">st-&gt;op1-&gt;condcond(yes)-&gt;econd(no)-&gt;op1<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre><h3 id="节点形状"><a href="#节点形状" class="headerlink" title="节点形状"></a>节点形状</h3><p>Mermaid 支持多种节点形状，例如圆角矩形、普通矩形、菱形等。以下是一些示例：</p><pre class="line-numbers language-mermaid" data-language="mermaid"><code class="language-mermaid"><span class="token keyword">flowchart</span> TBA<span class="token text string">(圆角形节点)</span>B<span class="token text string">[矩形节点]</span>C<span class="token text string">((圆形节点))</span>D<span class="token text string">[(圆柱形节点)]</span>E<span class="token text string">&#123;菱形节点&#125;</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h3 id="连接线样式"><a href="#连接线样式" class="headerlink" title="连接线样式"></a>连接线样式</h3><p>可以对连接线进行样式设置，例如：</p><pre class="line-numbers language-mermaid" data-language="mermaid"><code class="language-mermaid"><span class="token keyword">flowchart</span> LRA<span class="token arrow operator">--></span>B<span class="token keyword">linkStyle</span> 0 <span class="token style"><span class="token property">stroke</span><span class="token operator">:</span>#ff3<span class="token punctuation">,</span><span class="token property">stroke-width</span><span class="token operator">:</span>4px<span class="token punctuation">,</span><span class="token property">color</span><span class="token operator">:</span>red</span><span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span></span></code></pre><h3 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h3><p>以下是一个冒泡排序流程图的示例：</p><pre class="line-numbers language-mermaid" data-language="mermaid"><code class="language-mermaid"><span class="token keyword">flowchart</span> LR执行1<span class="token text string">[i = 1]</span>执行2<span class="token text string">[j = 0]</span>执行3<span class="token text string">[i ++]</span>执行4<span class="token text string">["a = arr[j], b = arr[j + 1]"]</span>执行5<span class="token text string">[交换 a, b]</span>执行6<span class="token text string">[j ++]</span>判断1<span class="token text string">["i &lt; n"]</span>判断2<span class="token text string">["j &lt; n - i"]</span>判断3<span class="token text string">["a > b"]</span>开始 <span class="token arrow operator">--></span> 执行1执行1 <span class="token arrow operator">--></span> 判断1判断1 <span class="token inter-arrow-label"><span class="token arrow-head arrow operator">--</span><span class="token label property">Y</span><span class="token arrow operator">--></span></span> 执行2执行2 <span class="token arrow operator">--></span> 判断2判断2 <span class="token inter-arrow-label"><span class="token arrow-head arrow operator">--</span><span class="token label property">Y</span><span class="token arrow operator">--></span></span> 执行4判断2 <span class="token inter-arrow-label"><span class="token arrow-head arrow operator">--</span><span class="token label property">N</span><span class="token arrow operator">--></span></span> 执行3执行3 <span class="token arrow operator">--></span> 判断1执行4 <span class="token arrow operator">--></span> 判断3判断3 <span class="token inter-arrow-label"><span class="token arrow-head arrow operator">--</span><span class="token label property">N</span><span class="token arrow operator">--></span></span> 判断2判断3 <span class="token inter-arrow-label"><span class="token arrow-head arrow operator">--</span><span class="token label property">Y</span><span class="token arrow operator">--></span></span> 执行5执行5 <span class="token arrow operator">--></span> 执行6执行6 <span class="token arrow operator">--></span> 判断2判断1 <span class="token inter-arrow-label"><span class="token arrow-head arrow operator">--</span><span class="token label property">N</span><span class="token arrow operator">--></span></span> 结束<span aria-hidden="true" class="line-numbers-rows"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></code></pre><h2 id="媒体控制"><a href="#媒体控制" class="headerlink" title="媒体控制"></a>媒体控制</h2><h3 id="音乐"><a href="#音乐" class="headerlink" title="音乐"></a>音乐</h3><p><strong>内部音乐</strong></p><figure class="music-card reveal" data-url="/music/%E6%A8%AA%E5%B1%B1%E5%85%8B%20-%20Familiar%20Arms.mp3" data-name="Familiar Arms" data-artist="横山克"><button class="music-play" type="button" aria-label="播放" title="播放"><i class="fa fa-play music-ico-idle" aria-hidden="true"></i><i class="fa fa-pause music-ico-playing" aria-hidden="true"></i></button><figcaption class="music-meta"><span class="music-line"><span class="music-name">Familiar Arms</span><span class="music-artist">横山克</span></span><span class="music-bar" role="slider" tabindex="0" aria-label="播放进度" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><i class="music-fill"></i></span></figcaption></figure><p><strong>url音乐</strong></p><figure class="music-card reveal" data-url="https://blog.hikari233.qd.je/music/中国人民解放军军乐团 - 春节序曲.mp3" data-name="春节序曲" data-artist="中国人民解放军军乐团"><button class="music-play" type="button" aria-label="播放" title="播放"><i class="fa fa-play music-ico-idle" aria-hidden="true"></i><i class="fa fa-pause music-ico-playing" aria-hidden="true"></i></button><figcaption class="music-meta"><span class="music-line"><span class="music-name">春节序曲</span><span class="music-artist">中国人民解放军军乐团</span></span><span class="music-bar" role="slider" tabindex="0" aria-label="播放进度" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><i class="music-fill"></i></span></figcaption></figure><h2 id="倒计时卡片"><a href="#倒计时卡片" class="headerlink" title="倒计时卡片"></a>倒计时卡片</h2><div class="countdown reveal" data-date="2025-12-31" data-mode="day" data-event="悲伤的2025"><p class="cd-title">以成为的过去式</p><p class="cd-sentence" role="timer" aria-label="倒计时"></p><p class="cd-meta">2025-12-31</p></div><div class="countdown reveal" data-date="2025-12-31T00:00" data-mode="time" data-event="2025旧年"><div class="cd-head"><p class="cd-lead"></p><p class="cd-days"><b>—</b><span>天</span></p></div><div class="cd-clock"><div class="cd-clock-body" role="timer" aria-label="倒计时"></div></div><p class="cd-meta">2025-12-31 00:00</p></div><div class="countdown reveal" data-date="2026-12-31" data-mode="day" data-event="元旦"><p class="cd-title">跨年倒计时</p><p class="cd-sentence" role="timer" aria-label="倒计时"></p><p class="cd-meta">2026-12-31</p></div><div class="countdown reveal" data-date="2027-01-01T00:00" data-mode="time" data-event="新年"><div class="cd-head"><p class="cd-lead"></p><p class="cd-days"><b>—</b><span>天</span></p></div><div class="cd-clock"><div class="cd-clock-body" role="timer" aria-label="倒计时"></div></div><p class="cd-meta">2027-01-01 00:00</p></div>]]>
    </content>
    <id>https://blog.hikari233.qd.je/2025/10/14/%E4%B8%BB%E9%A2%98%E6%B5%8B%E8%AF%95%E6%96%87%E7%AB%A0/</id>
    <link href="https://blog.hikari233.qd.je/2025/10/14/%E4%B8%BB%E9%A2%98%E6%B5%8B%E8%AF%95%E6%96%87%E7%AB%A0/"/>
    <published>2025-10-14T02:55:45.000Z</published>
    <summary>
      <![CDATA[<p>这是一篇测试文章，用于验证博客的核心渲染能力。</p>
<h2 id="文本格式基础测试​"><a href="#文本格式基础测试​" class="headerlink" title="文本格式基础测试​"></a>文本格式基础测试​</h2><h3 id="标题层级​"]]>
    </summary>
    <title>主题测试文章</title>
    <updated>2026-10-14T16:00:31.272Z</updated>
  </entry>
</feed>
