<?xml version="1.0" encoding="utf-8"?>
<search> 
  
  
    
    <entry>
      <title>基于 Vercel 和 MongoDB 的叨叨·改</title>
      <link href="2021/07/18/daodao-kai/"/>
      <url>2021/07/18/daodao-kai/</url>
      
        <content type="html"><![CDATA[<h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><blockquote><p>Q: 什么是叨叨·改?<br>A: 叨叨·改是用 Flask 重写了原叨叨 (<a href="https://github.com/Rock-Candy-Tea/daodao">Rock-Candy-Tea/daodao (github.com)</a>)的后端, 并增添了前端的一个初步可用的应用, 前端说说展示页面直接搬运自<a href="https://zfe.space/">小冰博客 - 做个有梦想的人！ (zfe.space)</a> , 其余前端来源于网络. 后端 api 可见 README</p><p>A: 叨叨·改已经插件化, 项目地址: <a href="https://github.com/ayasa520/hexo-daodao-plus">ayasa520/hexo-daodao-plus: 适用于 hexo 的”叨叨·改”插件 (github.com)</a>. 后端项目地址: <a href="https://github.com/ayasa520/daodao-kai">ayasa520/daodao-kai: 叨叨改，用 flask 重写叨叨的后端 (github.com)</a></p></blockquote><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><ul><li>登录</li></ul><p>点击下方”登录”按钮, 在表单中输入用户名和密码</p><p><img src="https://onedrive.bilibilianime.com/e55T/image/Snipaste_2021-08-03_21-15-27.png" alt=""></p><p><img src="https://onedrive.bilibilianime.com/e55T/image/Snipaste_2021-08-03_21-16-38.png" alt=""></p><ul><li>删除</li></ul><p>登录后直接点击右侧的 x</p><p><img src="https://onedrive.bilibilianime.com/e55T/image/Snipaste_2021-08-03_21-09-31.png" alt=""></p><ul><li>发送</li></ul><p>登录后点击下方”新建”按钮, 在文本框中输入内容. 支持 Markdown.</p><p><img src="https://onedrive.bilibilianime.com/e55T/image/Snipaste_2021-08-03_21-12-27.png" alt=""></p><p><img src="https://onedrive.bilibilianime.com/e55T/image/Snipaste_2021-08-03_21-12-39.png" alt=""></p><h2 id="后端部署"><a href="#后端部署" class="headerlink" title="后端部署"></a>后端部署</h2><h3 id="Vercel-部署"><a href="#Vercel-部署" class="headerlink" title="Vercel 部署"></a>Vercel 部署</h3><h4 id="配置-MongoDB-若使用自己的-MongoDB-数据库可跳过"><a href="#配置-MongoDB-若使用自己的-MongoDB-数据库可跳过" class="headerlink" title="配置 MongoDB (若使用自己的 MongoDB 数据库可跳过)"></a>配置 MongoDB (若使用自己的 MongoDB 数据库可跳过)</h4><ol><li><p>在 <a href="https://www.mongodb.com/cloud/atlas/register">MongoDB Atlas | MongoDB</a> 申请 MongoDB 帐号</p><p>选免费的, 其他全默认选项<img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/7f02ecd79beb8edbf548f18e1c1b0896.png" alt="image"></p></li><li><p>点击 connect<img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/bfbc7980d4f8f6f80fd15f8a51d65100.png" alt="image"></p></li><li><p>选择 <code>Allow Access From Anywhere</code> 并确认</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/ed561893c173a331c2e2b43fec082179.png" alt="image"></p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/57ab88e29758199532e92a1a2e666d51.png" alt="image"></p></li><li><p>输入数据库的用户名和密码, 不要带有特殊字符, 因为我的后端没有做转义</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/ab4e876949ec84be0dac7474991bb782.png" alt="image"> </p></li><li><p>选择 <code>Connect your application</code><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/a87a877734d4a5d99b9c34cff06ed9c6.png" alt="image"></p></li><li><p>复制数据库的连接字符串, <strong>注意手动将 <code>&lt;password&gt;</code> 换成刚刚输入的密码</strong><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/6389c289443f4af0fdc00ab64fb2e4d9.png" alt="image"></p></li></ol><h4 id="配置-Vercel"><a href="#配置-Vercel" class="headerlink" title="配置 Vercel"></a>配置 Vercel</h4><ol><li><p>点击下面的按钮创建 Vercel 项目</p><div class="btns circle grid5">            <a class="button" href='https://vercel.com/import/project?template=https://github.com/ayasa520/daodao-kai' title='点击部署'><img src='/image/image.svg'>点击部署</a>          </div><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/079a98929983abc78d1f3089e0dfd47a.png" alt="image"></p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/c1d708feeacb44a67069694dd8ea022e.png" alt="image"></p></li><li><p>部署好后, 添加三个环境变量 <code>MONGODB</code> : 刚才复制的数据库连接字符串; <code>USERNAME</code>: 自定义叨叨·改登录名; <code>PASSWORD</code>: 自定义叨叨·改登陆密码. 由于刚才部署的时候还没有配置环境变量, 此时配置好后需要 <strong>重新部署</strong></p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/cd0db9b6fda534a1e2c351098271b46a.png" alt="image"></p></li></ol><h2 id="前端部署"><a href="#前端部署" class="headerlink" title="前端部署"></a>前端部署</h2><h3 id="不使用插件-不适用于当前最新版本"><a href="#不使用插件-不适用于当前最新版本" class="headerlink" title="不使用插件 (不适用于当前最新版本)"></a>不使用插件 (不适用于当前最新版本)</h3><p>以这种方式添加没有首页的滚动组件</p><p>在 _posts 下新建一个 md 文件, 内容如下, 注意把 <code>https://daodao-omega.vercel.app/api/query/20</code> 换成自己的. <strong>不要忘记写后面的 <code>api/query/20</code></strong> </p><details green><summary> 代码 </summary>              <div class='content'>              <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><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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><br><span class="line">title: 闲话板砖</span><br><span class="line">date: 2021-05-27 18:24:04</span><br><span class="line">---</span><br><span class="line"></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">type</span>=<span class="string">&quot;text/css&quot;</span> <span class="attr">href</span>=<span class="string">&quot;https://cdn.jsdelivr.net/gh/ayasa520/daodao-kai@main/static/css/index.css&quot;</span> /&gt;</span></span><br><span class="line"></span><br><span class="line">   <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;bber&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">section</span> <span class="attr">class</span>=<span class="string">&quot;timeline page-1&quot;</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;list&quot;</span> <span class="attr">id</span>=<span class="string">&quot;bbitems&quot;</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">section</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    </span><br><span class="line">&#123;% raw %&#125;</span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/art-template@4.13.2/lib/template-web.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">script</span> <span class="attr">id</span>=<span class="string">&quot;template&quot;</span> <span class="attr">type</span>=<span class="string">&quot;text/html&quot;</span>&gt;</span><span class="handlebars"><span class="xml"></span></span></span><br><span class="line"><span class="xml"><span class="handlebars">        </span><span class="template-variable">&#123;&#123;<span class="name"><span class="builtin-name">each</span></span> list item index&#125;&#125;</span><span class="xml"></span></span></span><br><span class="line"><span class="xml"><span class="handlebars">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;item&quot;</span> <span class="attr">id</span>=</span></span><span class="template-variable">&#123;&#123;<span class="name">item</span>[&quot;_id&quot;]&#125;&#125;</span><span class="xml"><span class="tag">&gt;</span></span></span></span><br><span class="line"><span class="xml"><span class="handlebars">            <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;datatime&quot;</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item</span>[&quot;date&quot;]&#125;&#125;</span><span class="xml"><span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span></span><br><span class="line"><span class="xml"><span class="handlebars">            <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;datacont&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="xml"><span class="handlebars">                </span><span class="template-variable">&#123;&#123;@<span class="name">item</span>[&quot;content&quot;]&#125;&#125;</span><span class="xml"></span></span></span><br><span class="line"><span class="xml"><span class="handlebars">            <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span></span><br><span class="line"><span class="xml"><span class="handlebars">            <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;datafrom&quot;</span>&gt;</span></span></span></span><br><span class="line"><span class="xml"><span class="handlebars">                <span class="tag">&lt;<span class="name">small</span>&gt;</span><span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&quot;fas fa-tools&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><span class="template-variable">&#123;&#123;<span class="name">item</span>[&quot;from&quot;]&#125;&#125;</span><span class="xml"><span class="tag">&lt;/<span class="name">small</span>&gt;</span></span></span></span><br><span class="line"><span class="xml"><span class="handlebars">            <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span></span></span><br><span class="line"><span class="xml"><span class="handlebars">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span></span><br><span class="line"><span class="xml"><span class="handlebars">        </span><span class="template-tag">&#123;&#123;/<span class="name"><span class="builtin-name">each</span></span>&#125;&#125;</span><span class="xml"></span></span></span><br><span class="line"><span class="xml"><span class="handlebars">    </span></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line">&#123;% endraw %&#125;</span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span><br><span class="line"><span class="javascript">    <span class="keyword">var</span> xmlHttp = <span class="keyword">new</span> XMLHttpRequest();</span></span><br><span class="line"><span class="javascript">    <span class="comment">// 注意下面的链接换成自己的</span></span></span><br><span class="line"><span class="javascript">    xmlHttp.open(<span class="string">&quot;get&quot;</span>,<span class="string">&quot;https://daodao-kai.vercel.app/api/query/20&quot;</span>);</span></span><br><span class="line"><span class="javascript">    xmlHttp.send(<span class="literal">null</span>);</span></span><br><span class="line"><span class="javascript">    xmlHttp.onreadystatechange=<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span></span></span><br><span class="line"><span class="function"><span class="javascript">    </span>&#123;</span></span><br><span class="line"><span class="javascript">        <span class="keyword">if</span> (xmlHttp.readyState==<span class="number">4</span> &amp;&amp; xmlHttp.status==<span class="number">200</span>)</span></span><br><span class="line"><span class="javascript">        &#123;</span></span><br><span class="line"><span class="javascript">            <span class="built_in">console</span>.log(xmlHttp.responseText);</span></span><br><span class="line"><span class="javascript">            <span class="keyword">var</span> result = <span class="built_in">JSON</span>.parse(xmlHttp.responseText);</span></span><br><span class="line"><span class="javascript">            <span class="keyword">var</span> html = template(<span class="string">&#x27;template&#x27;</span>, &#123; <span class="attr">list</span>: result &#125;)</span></span><br><span class="line"><span class="javascript">            <span class="built_in">document</span>.getElementById(<span class="string">&quot;bbitems&quot;</span>).innerHTML = html;</span></span><br><span class="line"><span class="javascript">        &#125;</span></span><br><span class="line"><span class="javascript">    &#125;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure>              </div>            </details><p>然后就能看到了:</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/f3d51a5a94b4e167afb84e1c63c43f5d.png" alt="image"></p><h3 id="npm-插件-推荐"><a href="#npm-插件-推荐" class="headerlink" title="npm 插件 (推荐)"></a>npm 插件 (推荐)</h3><h4 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h4><p>在 hexo 博客根目录运行 npm 命令</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">npm install hexo-daodao-plus --save</span><br></pre></td></tr></table></figure><h4 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h4><p>在主题文件夹下 (或者根目录) 的 <code>_config.yml</code> 中添加下面的配置项</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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="attr">daodao_plus:</span></span><br><span class="line">  <span class="attr">enable:</span> </span><br><span class="line">    <span class="attr">page:</span> <span class="literal">true</span></span><br><span class="line">    <span class="attr">card:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">priority:</span> <span class="number">0</span></span><br><span class="line">  <span class="attr">filter:</span> </span><br><span class="line">  <span class="attr">url:</span> <span class="string">https://daodao-kai.vercel.app/</span></span><br><span class="line">  <span class="attr">path:</span> <span class="string">daodaoplus</span> </span><br><span class="line">  <span class="attr">front_matter:</span> </span><br><span class="line">    <span class="attr">title:</span> <span class="string">闲话板砖</span></span><br><span class="line">    <span class="attr">comments:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">CDN:</span> </span><br><span class="line">    <span class="attr">js:</span> <span class="string">https://cdn.jsdelivr.net/npm/hexo-daodao-plus@2.1.2/dist/js/main.js</span></span><br><span class="line">    <span class="attr">css:</span> <span class="string">https://cdn.jsdelivr.net/npm/hexo-daodao-plus@2.1.2/dist/css/main.css</span></span><br></pre></td></tr></table></figure><p>配置项说明</p><div class="table-container"><table><thead><tr><th>配置项</th><th>默认</th><th>说明</th></tr></thead><tbody><tr><td>enable.page</td><td><strong>必填</strong></td><td>单独叨叨页面的开关</td></tr><tr><td>enable.card</td><td><strong>必填</strong></td><td>首页叨叨 swiper 的开关</td></tr><tr><td>url</td><td><strong>必填</strong></td><td>叨叨后端的 api</td></tr><tr><td>CDN</td><td><strong>必填</strong></td><td>引入的 CSS 和 JavaScript 文件的链接</td></tr><tr><td>priority</td><td>0</td><td>过滤器优先级, priority 值越低, 过滤器会越早执行</td></tr><tr><td>filter</td><td>[‘iframe’,’img’,’script’]</td><td>设置叨叨不在首页显示的标签类型</td></tr><tr><td>path</td><td>daodaoplus</td><td>路径名称, 生成的页面为 [path]/index.html</td></tr><tr><td>front_matter</td><td>非必填</td><td>页面自定义 front_matter</td></tr></tbody></table></div><h4 id="截图"><a href="#截图" class="headerlink" title="截图"></a>截图</h4><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/0469b9627d2384e678b0a72872f0e0f0.png" alt="image"></p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/3c049c61ec20f85ec6b29ba9275b5161.png" alt="image"></p>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> flask </tag>
            
            <tag> vercel </tag>
            
            <tag> 叨叨 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>为 butterfly 主题的 twikoo 添加图片点击放大功能</title>
      <link href="2021/07/16/twikoo-img-zoom/"/>
      <url>2021/07/16/twikoo-img-zoom/</url>
      
        <content type="html"><![CDATA[<p>只需将 twikoo.pug 中对应的代码修改如下 (直接抄自 main.js)</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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></pre></td><td class="code"><pre><span class="line">twikoo.init(<span class="built_in">Object</span>.assign(&#123;</span><br><span class="line">  <span class="attr">el</span>: <span class="string">&#x27;#twikoo-wrap&#x27;</span>,</span><br><span class="line">  <span class="attr">envId</span>: <span class="string">&#x27;!&#123;theme.twikoo.envId&#125;&#x27;</span>,</span><br><span class="line">  <span class="attr">region</span>: <span class="string">&#x27;!&#123;theme.twikoo.region&#125;&#x27;</span>,</span><br><span class="line">  <span class="attr">onCommentLoaded</span>: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(<span class="keyword">typeof</span> <span class="built_in">window</span>.mediumZoom!=<span class="string">&#x27;undefined&#x27;</span>)&#123;</span><br><span class="line">      <span class="keyword">const</span> zoomComment = mediumZoom(<span class="built_in">document</span>.querySelectorAll(<span class="string">&#x27;.tk-content :not(a)&gt;img&#x27;</span>))</span><br><span class="line">      zoomComment.on(<span class="string">&#x27;open&#x27;</span>, <span class="function"><span class="params">e</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> photoBg = <span class="built_in">document</span>.documentElement.getAttribute(<span class="string">&#x27;data-theme&#x27;</span>) === <span class="string">&#x27;dark&#x27;</span> ? <span class="string">&#x27;#121212&#x27;</span> : <span class="string">&#x27;#fff&#x27;</span></span><br><span class="line">        zoomComment.update(&#123;</span><br><span class="line">          <span class="attr">background</span>: photoBg</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">if</span>(GLOBAL_CONFIG.lightbox === <span class="string">&#x27;fancybox&#x27;</span>)&#123;</span><br><span class="line">        <span class="keyword">const</span> addFancybox = <span class="function"><span class="keyword">function</span> (<span class="params">ele</span>) </span>&#123;</span><br><span class="line">          <span class="keyword">const</span> runFancybox = <span class="function">(<span class="params">ele</span>) =&gt;</span> &#123;</span><br><span class="line">            ele.each(<span class="function"><span class="keyword">function</span> (<span class="params">i, o</span>) </span>&#123;</span><br><span class="line">              <span class="keyword">const</span> $this = $(o)</span><br><span class="line">              <span class="keyword">const</span> lazyloadSrc = $this.attr(<span class="string">&#x27;data-lazy-src&#x27;</span>) || $this.attr(<span class="string">&#x27;src&#x27;</span>)</span><br><span class="line">              <span class="keyword">const</span> dataCaption = $this.attr(<span class="string">&#x27;alt&#x27;</span>) || <span class="string">&#x27;&#x27;</span></span><br><span class="line">              $this.wrap(<span class="string">`&lt;a href=&quot;<span class="subst">$&#123;lazyloadSrc&#125;</span>&quot; data-fancybox=&quot;group&quot; data-caption=&quot;<span class="subst">$&#123;dataCaption&#125;</span>&quot; class=&quot;fancybox&quot;&gt;&lt;/a&gt;`</span>)</span><br><span class="line">            &#125;)</span><br><span class="line"></span><br><span class="line">            $().fancybox(&#123;</span><br><span class="line">              <span class="attr">selector</span>: <span class="string">&#x27;[data-fancybox]&#x27;</span>,</span><br><span class="line">              <span class="attr">loop</span>: <span class="literal">true</span>,</span><br><span class="line">              <span class="attr">transitionEffect</span>: <span class="string">&#x27;slide&#x27;</span>,</span><br><span class="line">              <span class="attr">protect</span>: <span class="literal">true</span>,</span><br><span class="line">              <span class="attr">buttons</span>: [<span class="string">&#x27;slideShow&#x27;</span>, <span class="string">&#x27;fullScreen&#x27;</span>, <span class="string">&#x27;thumbs&#x27;</span>, <span class="string">&#x27;close&#x27;</span>],</span><br><span class="line">              <span class="attr">hash</span>: <span class="literal">false</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">if</span> (<span class="keyword">typeof</span> $.fancybox === <span class="string">&#x27;undefined&#x27;</span>) &#123;</span><br><span class="line">            $(<span class="string">&#x27;head&#x27;</span>).append(<span class="string">`&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;<span class="subst">$&#123;GLOBAL_CONFIG.source.fancybox.css&#125;</span>&quot;&gt;`</span>)</span><br><span class="line">            $.getScript(<span class="string">`<span class="subst">$&#123;GLOBAL_CONFIG.source.fancybox.js&#125;</span>`</span>, <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">              runFancybox($(ele))</span><br><span class="line">            &#125;)</span><br><span class="line">          &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            runFancybox($(ele))</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      addFancybox(<span class="built_in">document</span>.querySelectorAll(<span class="string">&#x27;.tk-content :not(a)&gt;img&#x27;</span>))</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;, !&#123;<span class="built_in">JSON</span>.stringify(theme.twikoo.option)&#125;))</span><br></pre></td></tr></table></figure>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 图片放大 </tag>
            
            <tag> zoom </tag>
            
            <tag> twikoo </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>自动添加 twikoo 评论中的友链</title>
      <link href="2021/07/06/auto-update-link/"/>
      <url>2021/07/06/auto-update-link/</url>
      
        <content type="html"><![CDATA[<div class="tip warning"><p><strong>本文已失效</strong><br><strong>在本文中您将会看到:</strong><br>低技术力<br>低效率<br>几乎没有的可移植性与可拓展性</p></div><p>唯一的优点: 对于新手 (我自己) 来说不需要掌握很多技术就能实现</p><h2 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h2><p>hexo 的友链页面和文章一样, 要想更新就得重新生成并部署. 使用 webhook, Github Action 或者 vercel 等实现自动化部署后, 更新网站内容变得更加方便: 本地改好后直接推送到仓库, 剩下的交给服务器去做. 但是增加友链每次都要从评论区复制粘贴到 link.yml 然后 push, 还是比较麻烦. 目前有通过 issue 添加友链的方法, 但是对于我这种懒人来讲, 能在评论区做就不想再开个网页, 所以我想要做出一点更改, 能自动获取评论中的友链信息并直接添加(<strong>这建立在自动部署的前提上</strong>). 关于审核什么的, 我就不关心了, 现在评论一共都没多少</p><h2 id="思路"><a href="#思路" class="headerlink" title="思路"></a>思路</h2><p>我的博客中评论用的是 twikoo, 云函数的代码我看不到(当然也肯定看不懂), 于是就只剩下 JS 了, 简单 F12 看一下, 发现点击<code>发送</code>按钮后, twikoo.all.js 会给 twikoo 云函数发 post 请求, 请求负载的 <code>request_data</code> 字段包含了评论内容, 评论链接等.</p><p>只需要在 twikoo.all.js 向 twikoo 云函数发送 post 请求的同时给我自己的服务器也发一个评论内容的 post 请求, 后端解析得到的 json 格式字符串, 就能提取到新增友链需要的昵称, 头像, 邮箱, 网址信息, 然后通过 Github API 更新仓库中的 <code>link.yml</code> 文件, 然后触发 webhook, 部署博客的服务器自动拉取最新的代码.</p><h2 id="具体步骤"><a href="#具体步骤" class="headerlink" title="具体步骤"></a>具体步骤</h2><h3 id="搭建简单的-flask-应用"><a href="#搭建简单的-flask-应用" class="headerlink" title="搭建简单的 flask 应用"></a>搭建简单的 flask 应用</h3><p>flask 是一个轻量化的 web 框架, 下面是一个最简单的 flask 应用, 访问 <code>route()</code> 中的 URL 就能触发下面的函数, 它会返回一段 html 代码, 浏览器会将其渲染出来.</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">from</span> flask <span class="keyword">import</span> Flask</span><br><span class="line"></span><br><span class="line">app = Flask(__name__)</span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">&quot;/&quot;</span></span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">hello_world</span>():</span></span><br><span class="line">    <span class="keyword">return</span> <span class="string">&quot;&lt;p&gt;Hello, World!&lt;/p&gt;&quot;</span></span><br></pre></td></tr></table></figure><p>在终端中启动应用并进行本地测试, 其中 <code>FLASK_APP=hello</code>中的 hello 是 py 文件名.</p><div class="tabs" id="code"><ul class="nav-tabs"><li class="tab active"><button type="button" data-href="#code-1">bash</button></li><li class="tab"><button type="button" data-href="#code-2">cmd</button></li><li class="tab"><button type="button" data-href="#code-3">powershell</button></li></ul><div class="tab-contents"><div class="tab-item-content active" id="code-1"><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">export</span> FLASK_APP=hello</span><br><span class="line">flask run</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="code-2"><figure class="highlight cmd"><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">set</span> FLASK_APP=hello</span><br><span class="line">flask run</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div><div class="tab-item-content" id="code-3"><figure class="highlight powershell"><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="variable">$env:FLASK_APP</span> = <span class="string">&quot;hello&quot;</span></span><br><span class="line">flask run</span><br></pre></td></tr></table></figure><button type="button" class="tab-to-top" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div></div></div><p>默认端口为 5000, 访问 localhost:5000 就可以看到 <code>Hello, World!</code><br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/0727e9038331753410eed8905d17ba09.png" alt="image"></p><p>要处理 post 请求, 只需要在 <code>@app.route</code> 装饰器里添加 <code>methods=[&#39;post&#39;]</code>, 这样这个路由就只能以 post 方式访问. <code>request.get_data</code> 可以接收 post 请求的负载.</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></pre></td><td class="code"><pre><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">&quot;/&quot;</span>,methods=[<span class="string">&#x27;post&#x27;</span>]</span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">hello_world</span>():</span></span><br><span class="line">    <span class="built_in">print</span>(request.get_data(as_text=<span class="literal">True</span>))</span><br><span class="line">    </span><br></pre></td></tr></table></figure><p>点击发送按钮, twikoo 会发起一个 post 请求, Request PayLoad 的内容如下:</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/d755b87a44f31fdaed248c9795f21026.png" alt="image"></p><p>从图可以看出只需要解析其中的 <code>comment</code> 字段.</p><p><code>comment</code> 字段是 html 代码, 借助 <code>etree.HTML</code> 从 html 代码中解析文本内容. 关于如何使用 json, xpath, subprocess 工具等就不在这里赘述了.</p><p>完整的后端实现:</p><details green><summary> 旧版已废弃 </summary>              <div class='content'>              <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></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask</span><br><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> request</span><br><span class="line"><span class="keyword">from</span> markupsafe <span class="keyword">import</span> escape</span><br><span class="line"><span class="keyword">from</span> lxml <span class="keyword">import</span> etree</span><br><span class="line"><span class="keyword">from</span> flask_cors <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">import</span> subprocess</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"></span><br><span class="line">app = Flask(__name__)</span><br><span class="line">CORS(app, supports_credentials=<span class="literal">True</span>) <span class="comment"># 允许跨域</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">&quot;/&quot;</span>,methods=[<span class="string">&#x27;post&#x27;</span>]</span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">hello_world</span>():</span></span><br><span class="line">    data = json.loads(request.get_data(as_text=<span class="literal">True</span>))</span><br><span class="line">    data = json.loads(data[<span class="string">&#x27;request_data&#x27;</span>])</span><br><span class="line">    <span class="comment"># 检查来源, 换成自己的</span></span><br><span class="line">    <span class="keyword">if</span> <span class="string">&quot;comment&quot;</span> <span class="keyword">in</span> data <span class="keyword">and</span> data[<span class="string">&#x27;href&#x27;</span>] == <span class="string">&#x27;https://www.bilibilianime.com/link/&#x27;</span>:</span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&#x27;/var/hexo_source/hexo/source/_data/link.yml&#x27;</span>,<span class="string">&#x27;a+&#x27;</span>)<span class="keyword">as</span> f:</span><br><span class="line">            <span class="comment"># f.write(str(data))</span></span><br><span class="line">            dom = etree.HTML(<span class="built_in">str</span>(data[<span class="string">&#x27;comment&#x27;</span>]))</span><br><span class="line">            <span class="comment"># f.write(s+&#x27;\n\n&#x27;)</span></span><br><span class="line">            info = []</span><br><span class="line">            <span class="keyword">try</span>:</span><br><span class="line">                info = dom.xpath(<span class="string">&quot;//code[@class=&#x27;language-yml&#x27;]//text()&quot;</span>)</span><br><span class="line">                info =  [ainfo.strip() <span class="keyword">for</span> ainfo <span class="keyword">in</span> info[<span class="number">0</span>].split(<span class="string">&quot;\n&quot;</span>)]</span><br><span class="line">                <span class="comment"># f.write(str(info))</span></span><br><span class="line">                template = <span class="string">&quot;\n\n    &#123;&#125;\n      &#123;&#125;\n      &#123;&#125;\n      &#123;&#125;&quot;</span>    </span><br><span class="line">                f.write(template.<span class="built_in">format</span>(info[<span class="number">0</span>],info[<span class="number">1</span>],info[<span class="number">2</span>],info[<span class="number">3</span>]))</span><br><span class="line">                <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&#x27;log.txt&#x27;</span>,<span class="string">&#x27;a+&#x27;</span>)<span class="keyword">as</span> logfile:</span><br><span class="line">                    logfile.write(time.asctime( time.localtime(time.time()))+<span class="string">&quot;: 新增一条友链: &quot;</span>+<span class="string">&quot; &quot;</span>.join(info)+<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">                <span class="comment"># link.yml 所在目录, 换成自己的</span></span><br><span class="line">                subprocess.Popen(<span class="string">&#x27;cd /var/hexo_source/hexo/&amp;&amp;git add .&amp;&amp;git commit -m &quot;update: friend link&quot;&amp;&amp;git push&gt;log.txt&#x27;</span>,shell=<span class="literal">True</span>)</span><br><span class="line">            <span class="keyword">except</span>:</span><br><span class="line">                <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&#x27;log.txt&#x27;</span>,<span class="string">&#x27;a+&#x27;</span>)<span class="keyword">as</span> logfile:</span><br><span class="line">                    logfile.write(time.asctime( time.localtime(time.time()))+ <span class="string">&quot;: 失败！&quot;</span>+<span class="string">&quot;info: &#123;&#125;&quot;</span>.<span class="built_in">format</span>(<span class="string">&quot; &quot;</span>.join(info))+<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;&lt;span&gt;bad!&lt;/span&gt;&#x27;</span></span><br><span class="line">            </span><br><span class="line">    <span class="keyword">return</span>  <span class="string">&#x27;&lt;span&gt;ok!&lt;/span&gt;&#x27;</span></span><br></pre></td></tr></table></figure>              </div>            </details><details blue open><summary> 使用 Github API </summary>              <div class='content'>              <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><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="keyword">from</span> flask <span class="keyword">import</span> Flask</span><br><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> request</span><br><span class="line"><span class="keyword">from</span> markupsafe <span class="keyword">import</span> escape</span><br><span class="line"><span class="keyword">from</span> lxml <span class="keyword">import</span> etree</span><br><span class="line"><span class="keyword">from</span> flask_cors <span class="keyword">import</span> *</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">import</span> subprocess</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">import</span> base64</span><br><span class="line"><span class="keyword">import</span> traceback</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> twisted.internet <span class="keyword">import</span> reactor</span><br><span class="line"><span class="keyword">from</span> twisted.web <span class="keyword">import</span> proxy, server</span><br><span class="line"></span><br><span class="line"><span class="comment"># 此处填入你的 token</span></span><br><span class="line">token = <span class="string">&#x27;&#x27;</span> </span><br><span class="line"></span><br><span class="line"><span class="comment"># 此处填入你的 link.yml 的 Github API 链接</span></span><br><span class="line">url = <span class="string">&#x27;https://API.github.com/repos/ayasa520/hexo/contents/source/_data/link.yml&#x27;</span> </span><br><span class="line">headers = &#123;<span class="string">&#x27;Authorization&#x27;</span>: <span class="string">&#x27;token &#x27;</span> + token&#125;</span><br><span class="line"></span><br><span class="line">app = Flask(__name__)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 允许跨域</span></span><br><span class="line">CORS(app, supports_credentials=<span class="literal">True</span>) </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 class="meta">@app.route(<span class="params"><span class="string">&quot;/&quot;</span>,methods=[<span class="string">&#x27;post&#x27;</span>]</span>)</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">hello_world</span>():</span></span><br><span class="line">    data = json.loads(request.get_data(as_text=<span class="literal">True</span>))</span><br><span class="line">    data = json.loads(data[<span class="string">&#x27;request_data&#x27;</span>])</span><br><span class="line">    <span class="keyword">if</span> <span class="string">&quot;comment&quot;</span> <span class="keyword">in</span> data <span class="keyword">and</span> data[<span class="string">&#x27;href&#x27;</span>] == <span class="string">&#x27;https://www.bilibilianime.com/link/&#x27;</span>:</span><br><span class="line">        dom = etree.HTML(<span class="built_in">str</span>(data[<span class="string">&#x27;comment&#x27;</span>]))</span><br><span class="line">        info = []</span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            info = dom.xpath(<span class="string">&quot;//code[@class=&#x27;language-yml&#x27;]//text()&quot;</span>)</span><br><span class="line">            info =  [ainfo.strip() <span class="keyword">for</span> ainfo <span class="keyword">in</span> info[<span class="number">0</span>].split(<span class="string">&quot;\n&quot;</span>)]</span><br><span class="line">            template = <span class="string">&quot;\n\n    &#123;&#125;\n      &#123;&#125;\n      &#123;&#125;\n      &#123;&#125;&quot;</span>    </span><br><span class="line">            response_json = json.loads(requests.get(url, headers=headers).text)</span><br><span class="line">            old_text = <span class="built_in">str</span>(base64.b64decode(response_json[<span class="string">&#x27;content&#x27;</span>]), encoding=<span class="string">&#x27;utf-8&#x27;</span>)</span><br><span class="line">            b64 = base64.b64encode((old_text +template.<span class="built_in">format</span>(info[<span class="number">0</span>],info[<span class="number">1</span>],info[<span class="number">2</span>],info[<span class="number">3</span>])).encode(<span class="string">&#x27;utf-8&#x27;</span>)).decode(<span class="string">&#x27;ascii&#x27;</span>)</span><br><span class="line">            data = &#123;</span><br><span class="line">                <span class="string">&#x27;message&#x27;</span>: <span class="string">&quot;update from Python&quot;</span>,</span><br><span class="line">                <span class="string">&#x27;content&#x27;</span>: b64,</span><br><span class="line">                <span class="string">&#x27;sha&#x27;</span>: response_json[<span class="string">&#x27;sha&#x27;</span>]</span><br><span class="line">            &#125;            </span><br><span class="line">            requests.put(url=url, data=json.dumps( data), headers=headers)</span><br><span class="line">            <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&#x27;log.txt&#x27;</span>,<span class="string">&#x27;a+&#x27;</span>)<span class="keyword">as</span> logfile:</span><br><span class="line">                logfile.write(time.asctime( time.localtime(time.time()))+<span class="string">&quot;: 新增一条友链: &quot;</span>+<span class="string">&quot; &quot;</span>.join(info)+<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">        <span class="keyword">except</span>  Exception <span class="keyword">as</span> e:</span><br><span class="line">            <span class="keyword">with</span> <span class="built_in">open</span>(<span class="string">&#x27;log.txt&#x27;</span>,<span class="string">&#x27;a+&#x27;</span>)<span class="keyword">as</span> logfile:</span><br><span class="line">                logfile.write(time.asctime( time.localtime(time.time()))+ <span class="string">&quot;: 失败！&quot;</span>+<span class="string">&quot;info: &#123;&#125;&quot;</span>.<span class="built_in">format</span>(<span class="string">&quot; &quot;</span>.join(info))+<span class="string">&quot;\n&quot;</span>)</span><br><span class="line">                logfile.write(traceback.format_exc())</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;&lt;span&gt;bad&lt;/span&gt;&#x27;</span></span><br><span class="line">    <span class="keyword">return</span>  <span class="string">&#x27;&lt;span&gt;ok!&lt;/span&gt;&#x27;</span></span><br></pre></td></tr></table></figure>              </div>            </details><p>在非开发环境用 flask 自带的服务器就不合适了, 这里我写了一个启动脚本, 使用 Gunicorn 作为服务器</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">source</span> /var/hexo_source/simpleSever/<span class="comment"># flask 源码目录</span></span><br><span class="line">gunicorn -w 2 -b :5000 flask_web:app <span class="comment"># 绑定到 5000 端口. flask_web 是 py 文件名</span></span><br></pre></td></tr></table></figure><p>运行脚本即可完成部署. 如何部署到自己的云主机什么的网上说的很详细, 不再赘述.</p><p>在 <a href="https://postwoman.com.cn/">https://postwoman.com.cn/</a> 可以快速地进行测试:</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/175859218616ca729eee8d82d46dd594.png" alt="image"></p><h3 id="更改-twikoo-all-js"><a href="#更改-twikoo-all-js" class="headerlink" title="更改 twikoo.all.js"></a>更改 twikoo.all.js</h3><p>在格式化后的 twikoo.all.js 5783 行处插入下面的代码:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">$.ajax(&#123;</span><br><span class="line">    <span class="comment">// 这个域名指向 5000 端口, 换成自己的</span></span><br><span class="line">    <span class="attr">url</span>:<span class="string">&#x27;https://update-friend.bilibilianime.com/&#x27;</span>,</span><br><span class="line">    <span class="attr">type</span>:<span class="string">&#x27;POST&#x27;</span>,</span><br><span class="line">    <span class="attr">dataType</span>:<span class="string">&#x27;json&#x27;</span>,</span><br><span class="line">    <span class="attr">contentType</span>:<span class="string">&#x27;application/json;charset=UTF-8&#x27;</span>,</span><br><span class="line">    <span class="attr">data</span>:<span class="built_in">JSON</span>.stringify(e.data),</span><br><span class="line">    <span class="attr">success</span>:<span class="function"><span class="keyword">function</span>(<span class="params">data, status</span>)</span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(data);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>如图所示:<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/491e5e1a170b16a5327352522fa2bc1e.png?123" alt="image"></p><p>将主题 _config.yml 内 twikoo 的 CDN 修改为更改后的. 所有的工作就完成了</p><p>我没有对友链进行审核, 因为本来评论的人也不多, 现在就先不管了.</p>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 友链 </tag>
            
            <tag> 自动化 </tag>
            
            <tag> flask </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机网络 4 -网络层</title>
      <link href="2021/06/29/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C_04/"/>
      <url>2021/06/29/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C_04/</url>
      
        <content type="html"><![CDATA[<h2 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h2><ul><li><p>网络层的主要任务: <strong>实现网络互连</strong>, 进而实现数据报再各网络之间的传输</p></li><li><p>要实现网络层任务, 需要解决以下的问题</p><ul><li>网络层向运输层提供怎样的服务 (“可靠传输” 还是 “不可靠传输”)</li><li>网络寻址问题</li><li>路由选择问题<ul><li>人工配置</li><li>实现路由选择协议</li></ul></li></ul></li><li><p><strong>因特网</strong>使用 <strong>TCP/IP协议栈</strong> </p></li><li><p><strong>TCP/IP协议栈</strong>的网络层使用<strong>网际协议IP</strong>, 是整个协议栈的核心协议, 常称为<strong>网际层</strong></p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img//image-20210601023630030.png" alt="image-20210601023630030"></p></li></ul><h2 id="网络层提供的两层服务"><a href="#网络层提供的两层服务" class="headerlink" title="网络层提供的两层服务"></a>网络层提供的两层服务</h2><h3 id="面向连接的虚电路服务"><a href="#面向连接的虚电路服务" class="headerlink" title="面向连接的虚电路服务"></a>面向连接的虚电路服务</h3><ul><li><strong>可靠通信由网络来保证</strong></li><li>必须建立<strong>网络层的连接—虚电路 VC（Virtual Circuit）</strong></li><li>通信双方<strong>沿着已经建立的虚电路发送分组</strong></li><li>目的主机的地址仅在连接建立阶段使用, 之后每个<strong>分组的首部都只需携带一条虚电路编号</strong>(构成虚电路的每一段链路都有一个虚电路编号)</li><li>使用可靠传输的网络协议实现可靠传输</li><li><strong>通信结束后</strong>, <strong>需要释放之前建立的虚电路</strong></li></ul><h3 id="无连接的数据报服务"><a href="#无连接的数据报服务" class="headerlink" title="无连接的数据报服务"></a>无连接的数据报服务</h3><ul><li><strong>可靠通信由用户主机来保证</strong></li><li><strong>不需要建立网络层连接</strong></li><li><strong>每个分组可以走不通的路径</strong></li><li><strong>首部必须携带完整地址</strong></li><li><strong>分组可能重复, 失序, 误码, 丢失</strong></li><li><strong>网络本身不提供端到端的可靠传输服务</strong>, 路由器廉价</li><li>因特网采用这种设计思想: <strong>复杂网络处理功能置于因特网边缘, </strong>相对简单的网络交付功能置于因特网核心</li></ul><h2 id="IP-地址"><a href="#IP-地址" class="headerlink" title="IP 地址"></a>IP 地址</h2><h3 id="IPv4-地址概述"><a href="#IPv4-地址概述" class="headerlink" title="IPv4 地址概述"></a>IPv4 地址概述</h3><ul><li><p>分配给<strong>每一台主机(或路由器)的每一个接口</strong></p></li><li><p>IPv4 地址的编址方法</p><ul><li>分类编址</li><li>划分子网</li><li>无分类编址</li></ul></li><li><p>32 比特不方便, 采用<strong>点分十进制表示方法</strong></p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img//image-20210601105635772.png" alt="image-20210601105635772"></p></li></ul><h3 id="分类编址的-Ipv4-地址"><a href="#分类编址的-Ipv4-地址" class="headerlink" title="分类编址的 Ipv4 地址"></a>分类编址的 Ipv4 地址</h3><div class="note info flat"><p><strong>注意事项</strong></p><ul><li>只有 A,B,C 类地址可以分配给网络中的主机</li><li>主机号全为 0 的是网络地址, 不能分配给主机或者路由器的各个接口</li><li>主机号全为 1  的是广播地址, 不能分配给主机或者路由器的各个接口</li></ul></div><h4 id="A-类地址"><a href="#A-类地址" class="headerlink" title="A 类地址"></a><strong>A 类地址</strong></h4><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img//image-20210601114432185.png" alt="image-20210601114432185"></p><h4 id="B-类地址"><a href="#B-类地址" class="headerlink" title="B 类地址"></a>B 类地址</h4><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img//image-20210601115137755.png" alt="image-20210601115137755"></p><h4 id="C-类地址"><a href="#C-类地址" class="headerlink" title="C 类地址"></a>C 类地址</h4><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img//image-20210601115255668.png" alt="image-20210601115255668"></p><h4 id="练习题"><a href="#练习题" class="headerlink" title="练习题"></a>练习题</h4><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img//image-20210601120457191.png" alt="image-20210601120457191"></p> <span class="hide-inline"><button type="button" class="hide-button button--animated" style="">查看答案  </button><span class="hide-content">A</span></span><div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看解析    </button><div class="hide-content"><p>0.0.0.0 是一个特殊的 IPv4 地址, 那个作为源地址使用, 表示”在本网络上的本主机”, 封装有 DHCP Discovery 报文的 IP 分组源地址使用 0.0.0.0</p></div></div><h3 id="划分子网的-IPv4-地址"><a href="#划分子网的-IPv4-地址" class="headerlink" title="划分子网的 IPv4 地址"></a>划分子网的 IPv4 地址</h3><h4 id="需求"><a href="#需求" class="headerlink" title="需求"></a>需求</h4><p>随着网络发展, 主机数目不断增加, 并且需要将主机划分到独立的网络, 如果为新增的网络申请新的网络号会有以下弊端</p><ul><li>需要等待时间更多的费用</li><li>增加其他路由器路由表记录的数量</li><li>浪费原有网络中剩余的大量 IP 地址</li></ul><p><strong>解决方法——从主机号部分借用一部分作为子网号</strong></p><h4 id="子网掩码"><a href="#子网掩码" class="headerlink" title="子网掩码"></a>子网掩码</h4><p><strong>32 bit 的子网掩码可以表明分类 IP 地址的主机号部分被借用了几个 bit 作为网络号</strong></p><ul><li>使用<strong>连续的 bit 1 来对应网络号和子网号</strong></li><li>使用<strong>连续的 bit 0 对应主机号</strong></li><li>将划分子网的 IPv4 地址与相应的子网掩码做逻辑与运算就可以得到 IPv4 地址所在的子网的网络地址</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img//image-20210601123737265.png" alt="子网掩码示例"></p><p><strong>划分子网的细节</strong></p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img//image-20210601124022078.png" alt="image-20210601124022078"></p><p><strong>默认的子网掩码是指未划分子网的情况下使用的子网掩码</strong></p><ul><li>A: 255.0.0.0</li><li>B: 255.255.0.0</li><li>C: 255.255.255.0</li></ul><h3 id="无分类编址的-IPv4-地址"><a href="#无分类编址的-IPv4-地址" class="headerlink" title="无分类编址的 IPv4 地址"></a>无分类编址的 IPv4 地址</h3><ul><li>划分子网一定程度上解决了困, 但是没有充分利用 C 类网, IPv4 面临消耗殆尽的局面</li><li>IETF 提出采用<strong>无分类编址</strong>的方法解决 IP 地址紧张的局面, 同时成立 IPv6 工作组以彻底解决 IP 地址耗尽的问题</li><li><p><strong>无分类域间路由</strong>(Classless Inter-Domain Routing, CIDR)</p><ul><li>CIDR 消除了传统的 A 类, B 类和 C 类地址, 以及划分子网的概念</li><li><strong>CIDR 可以更加有效地分配 IPv4 的地址空间</strong></li></ul></li><li><p>CIDR 使用”<strong>斜线记法</strong>“, 或称 CIDR 记法, <strong>斜线后面写网络前缀所占的比特数量</strong></p><ul><li>举例: 128.14.35.7/20, 网络前缀占用 20 位, 主机编号占用 32 - 20 = 12 位</li></ul></li><li><p>CIDR 实际上是将网络前缀都相同的连续的 IP 地址组成一个 “CIDR 地址块”</p><ul><li><p>只要知道其中一个地址, 就可以知道这个地址块的全部细节:</p><ul><li>包括最小地址, 最大地址, 地址数量, 聚合某类(A, B, C)网络的数量, 地址掩码(可继续称为子网掩码)</li></ul><p>举例: 给出 128.14.35.7/20 的全部细节</p><div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案    </button><div class="hide-content"><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/601c40f65236dedbbd6d3c8397647a5d.png" alt="image">聚合C类网: 用该地址中的地址数量/C类网的地址数量</p></div></div></li></ul></li><li><p><strong>路由聚合</strong>(构造超网)</p><ul><li>两个路由器直接相连, 其中一个要将路由信息通告给另一个路由器, 就需要找<strong>共同前缀</strong><ul><li>路由表中目的网络的共同前缀保持不变, 其余位取零, 就能得到聚合地址块</li></ul></li><li>网络前缀越长, 地址块越小, 路由越具体</li><li>路由器转发分组时若有多条路有可选, 使用<strong>最长前缀匹配</strong></li></ul></li></ul><h3 id="IPv4-地址的应用规划"><a href="#IPv4-地址的应用规划" class="headerlink" title="IPv4 地址的应用规划"></a>IPv4 地址的应用规划</h3><h4 id="定长的子网掩码-Fixed-Length-Subnet-Mask-FLSM"><a href="#定长的子网掩码-Fixed-Length-Subnet-Mask-FLSM" class="headerlink" title="定长的子网掩码 (Fixed Length Subnet Mask, FLSM)"></a>定长的子网掩码 (Fixed Length Subnet Mask, FLSM)</h4><ul><li>从主机号部分借用 n 位作为子网号, 则可分配 <script type="math/tex">2^n</script> 个子网, 每个子网的主机数相同<ul><li>容易造成浪费</li></ul></li></ul><h4 id="变长的子网掩码-Variable-Length-Subnet-Mask-VLSM"><a href="#变长的子网掩码-Variable-Length-Subnet-Mask-VLSM" class="headerlink" title="变长的子网掩码(Variable Length Subnet Mask, VLSM)"></a>变长的子网掩码(Variable Length Subnet Mask, VLSM)</h4><p>从例子来看:</p><p>假设申请到的地址快是 218.75.230.0/24, 每一台主机一个地址, 每个子网有一个网络地址一个广播地址, 每个路由器接口有一个地址</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/e8937be0356221754f7171219366297a.png?987" alt="image"></p><ul><li>N1: 6 + 2 + 1 = 9; N2: 25 + 2 + 1 = 28; N3: 12 + 2 + 1=15;N4: 10 + 2 + 1 = 13; N5: 0 + 2 + 2 = 4;</li><li>所以需要 3 个 /28 地址块, 1 个 /27 地址块, 1 个 /30 地址块 </li><li>从大到小, 按需分配, <strong>每个子快只能选取块大小整数倍的地址作为起点</strong>, 以防止本该属于一个子网分配到下一个子网</li></ul><h2 id="IP-数据报的发送和转发过程"><a href="#IP-数据报的发送和转发过程" class="headerlink" title="IP 数据报的发送和转发过程"></a>IP 数据报的发送和转发过程</h2><blockquote><p>重点放在 TCP/IP 协议栈的网际层<strong>发送</strong>和转发 IP 数据数据报的过程上, 以下内容省略了 ARP 和交换机自学习以及转发帧的过程</p></blockquote><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/b20b58dd1a55a305c7acb3c9421cf63f.png" alt="image"></p><ul><li>同一网络中的主机: 直接交付</li><li>不同网络中的主机: 间接交付, 通过路由器中转</li></ul><h3 id="间接交付"><a href="#间接交付" class="headerlink" title="间接交付"></a>间接交付</h3><ul><li><p>将自己的 IP 地址与自己的子网掩码相与得到自己的网络地址, 将目的 IP 地址与自己的子网掩码相与得到目的网络地址 (如果在同一个网络, 两个网络地址相等)</p></li><li><p><strong>默认网关</strong>: 本网络中的主机要与其他网络中的主机进行通信, 就必须给他指定一个本网络的路由器, 这个路由器被称为默认网关. 默认网关帮助主机将 IP 数据报转发出去</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/04aeeb99d2935dbbebb09af573af3b57.png" alt="image"></p></li><li><p>路由器转发过程</p><ol><li><p>检查 IP 数据报首部是否出错</p><ul><li>出错: 丢弃, 告知源主机</li><li>未出错: 进行转发</li></ul></li><li><p>根据 IP 数据报的目的地址在路由表中查找匹配的条目:</p><p>通过依次将目的地址与路由表中的地址掩码相与来判断</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/b84ad1e2162cc70846f2b63327a0a962.png" alt="image"></p><ul><li>找到: 转发给条目中指定的下一跳</li><li>没找到: 丢弃并告知源主机</li></ul></li></ol></li></ul><h2 id="静态路由配置及其可能产生的路由环路问题"><a href="#静态路由配置及其可能产生的路由环路问题" class="headerlink" title="静态路由配置及其可能产生的路由环路问题"></a>静态路由配置及其可能产生的路由环路问题</h2><p>举例: 静态路由配置以及默认路由, 特定路由</p><p> <img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/e3d8063df293b2ee3169112f53bdefb3.png" alt="image"></p><h3 id="静态路由配置错误导致路由环路"><a href="#静态路由配置错误导致路由环路" class="headerlink" title="静态路由配置错误导致路由环路"></a>静态路由配置错误导致路由环路</h3><p>R2 本该将数据报转发给 R1 的接口 1,却错误地转发给了 R3 的接口 0, 导致了路由环路</p><ul><li><div class="note info flat"><p>为了避免IP 数据报在路由环路中永久兜圈, IP 数据报的首部设有<strong>生存时间 TTL</strong> 字段. IP 数据报进入路由器后, TTL 字段的值减一, 若 TTL 的值为 0, 则丢弃</p></div></li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/2c7f639917b2fe3453304701596690de.png" alt="image"></p><h3 id="聚合了不存在的网络导致路由环路"><a href="#聚合了不存在的网络导致路由环路" class="headerlink" title="聚合了不存在的网络导致路由环路"></a>聚合了不存在的网络导致路由环路</h3><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/f01a2d78f35273c9fef72e3097ea2c57.png" alt="image"></p><p>解决方法: 设置黑洞路由</p><p>​    <img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/c60fff18fd60182da0bcc7a9466f8bc0.png?" alt="image"></p><h3 id="网络故障导致的路由环路"><a href="#网络故障导致的路由环路" class="headerlink" title="网络故障导致的路由环路"></a>网络故障导致的路由环路</h3><p>当 R1 直连网络 192.168.1.0/24 不可达的时候, 就会将路由表中的记录删除, 收到目的网络地址为 192.168.1.0/24 的数据报, 就会通过默认路由转发给 R2, 导致了环路</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/ee8bd1c155c1b78544ab6adc0bf9b2c7.png?" alt="image"></p><p>解决方法: 同样是设置黑洞路由</p>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 计网 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>将 mp4 视频切片成 ts 后使用 jsDelivr 加速制作 &quot;视频床&quot;</title>
      <link href="2021/06/25/jsDelivr/%E8%96%85%E7%BE%8A%E6%AF%9B/"/>
      <url>2021/06/25/jsDelivr/%E8%96%85%E7%BE%8A%E6%AF%9B/</url>
      
        <content type="html"><![CDATA[<p>将 mp4 转为 ts 后, 使用 ffmpeg 将 ts 文件切片, 然后上传到 Github 的仓库里</p><p>此处使用的播放器为 DPlayer:<div class="tag link"><a class="link-card" title="DPlayer 官方文档" href="http://dplayer.js.org/zh/"><div class="left"><img src="https://i.loli.net/2019/06/06/5cf8c5d94521136430.png"/></div><div class="right"><p class="text">DPlayer 官方文档</p><p class="url">http://dplayer.js.org/zh/</p></div></a></div></p><p>使用之前要必须先引入 hls.js</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;script src=<span class="string">&quot;https://cdn.jsdelivr.net/hls.js/latest/hls.min.js&quot;</span>&gt;&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>也可以用 <code>hexo-tag-dplayer</code> 通过外挂标签的形式使用 DPlayer:</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">&#123;% dplayer &quot;url=https://cdn.jsdelivr.net/gh/ayasa520/assets/%E8%96%87%E8%96%87%20-%E8%90%A4%E7%9F%B3%E7%9C%BC%E4%B9%8B%E6%AD%8C-4/playlist.m3u8&quot; &quot;type: &#x27;hls&#x27;&quot;,  &quot;id=9E2E3368B56CDBB4&quot; &quot;loop=yes&quot; &quot;theme=#FADFA3&quot; &quot;autoplay=false&quot;  %&#125;</span><br></pre></td></tr></table></figure><p><strong>示例</strong>:<br>看不到视频请刷新</p><div id="dplayer" class="dplayer-video no-destroy dplayer dplayer-no-danmaku"></div>   <script >function dplayer_init(){// $(document).on('pjax:start', function () {//     if (window.dplayers) {//         for (let i = 0; i < window.dplayers.length; i++) {//             window.dplayers[i].destroy();//         }//         window.dplayers = [];//     }// });  var dp  =new DPlayer({      container: document.getElementById('dplayer'),      autoplay:0,theme:"#FADFA3",loop:true,preload:"auto",volume:Number("20"),      video: {          url: 'https://cdn.jsdelivr.net/gh/ayasa520/assets/%E8%96%87%E8%96%87%20-%E8%90%A4%E7%9F%B3%E7%9C%BC%E4%B9%8B%E6%AD%8C-4/playlist.m3u8',          type: 'hls',      }    });}</script><p>仓库:</p><a class="ghcard" rel="external nofollow noopener noreferrer" href="https://github.com/ayasa520/assets"><img src="https://github-readme-stats.vercel.app/api/pin/?username=ayasa520&repo=assets&show_owner=true"/></a>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 薅羊毛 </tag>
            
            <tag> m3u8 </tag>
            
            <tag> dplayer </tag>
            
            <tag> jsDelivr </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Python 实现窗口保持置顶</title>
      <link href="2021/06/24/tools/window-to-top/"/>
      <url>2021/06/24/tools/window-to-top/</url>
      
        <content type="html"><![CDATA[<div class="note info modern"><p>今天一边看视频一边用 Typora 记笔记的时候发现一个问题, Typora 自带的 <code>保持窗口在最前端</code>不知何故会失效, 所以我就想用 Python 写一个可以让窗口强制指定的工具, 毕竟在查阅文档的时候还是有些用处的.</p></div><h2 id="使用的模块"><a href="#使用的模块" class="headerlink" title="使用的模块"></a>使用的模块</h2><ol><li>win32gui </li><li>keyboard </li><li>win32con </li><li>pyinstaller </li></ol><h2 id="使用的函数及其原型"><a href="#使用的函数及其原型" class="headerlink" title="使用的函数及其原型"></a>使用的函数及其原型</h2><ol><li><p><code>SetWindowPos</code> </p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">WINUSERAPI BOOL WINAPI <span class="title">SetWindowPos</span><span class="params">(HWND hWnd,HWND hWndInsertAfter,<span class="keyword">int</span> X,<span class="keyword">int</span> Y,<span class="keyword">int</span> cx, <span class="keyword">int</span> cy, UINT uFlags)</span></span>;</span><br></pre></td></tr></table></figure><p>用于设置窗口的 Z 序号</p><p>参数解释如下:</p><ul><li><code>hwnd</code>: 被修改的窗口的句柄</li><li><code>hWndlnsertAfter</code>: 用于标识 Z 顺序, 可设为以下值:<ul><li><code>HWND_BOTTOM</code>: 值为 1, 置底</li><li><code>HWND_NOTOPMOST</code>: 值为 -2, 置于非置顶窗口之上</li><li><code>HWND_TOP</code> : 值为 0, 置顶</li><li><code>HWND_TOPMOST</code>: 值为 -1, 置顶 (在<code>HWND_TOP</code>之上)</li></ul></li><li><code>X</code>, <code>Y</code>, <code>cx</code>,<code>cy</code> 确定了新窗口的位置和宽高</li><li><code>uFlags</code>: 窗口尺寸和定位的标识, 部分值如下:<ul><li><code>SWP_NOOWNERZORDER</code>: 不改变 Z 序中所有者窗口的位置</li><li><code>SWP_NOSIZE</code>: 不改变窗口大小</li><li><code>SWP_NOMOVE</code>: 不移动窗口</li></ul></li></ul></li><li><p><code>GetForegroundWindow</code> </p><p>用于获取当前激活的窗口 (鼠标焦点所在窗口)的句柄</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">HWND <span class="title">GetForegroundWindow</span><span class="params">(<span class="keyword">void</span>)</span></span>;</span><br></pre></td></tr></table></figure></li><li><p><code>keyboard.addhotkey</code> 和<code>keyboard.wait</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></pre></td><td class="code"><pre><span class="line">keyboard.add_hotkey(<span class="string">&#x27;alt + t&#x27;</span>, fun)</span><br><span class="line"><span class="keyword">while</span> true:</span><br><span class="line">keyboard.wait()</span><br></pre></td></tr></table></figure><p><code>add_hotkey</code> 可以设置热键和检测到热键按下后执行的方法,  <code>wait</code>是阻塞方法, 便于检测组合键</p></li></ol><h2 id="源码"><a href="#源码" class="headerlink" title="源码"></a>源码</h2><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="keyword">import</span> win32gui</span><br><span class="line"><span class="keyword">import</span> keyboard</span><br><span class="line"><span class="keyword">import</span> win32con</span><br><span class="line"><span class="keyword">import</span> atexit</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">totop</span>:</span></span><br><span class="line">    flag = <span class="literal">False</span></span><br><span class="line">    hw = <span class="string">&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">force_focus</span>(<span class="params">self, hwnd</span>):</span></span><br><span class="line">        win32gui.SetWindowPos(hwnd, win32con.HWND_TOPMOST, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>,</span><br><span class="line">                              win32con.SWP_NOOWNERZORDER | win32con.SWP_NOSIZE | win32con.SWP_NOMOVE)</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;置顶&quot;</span>, hwnd, win32gui.GetWindowText(hwnd))</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">cancel_focus</span>(<span class="params">self, hwnd</span>):</span></span><br><span class="line">        win32gui.SetWindowPos(hwnd, win32con.HWND_NOTOPMOST, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>, <span class="number">0</span>,</span><br><span class="line">                              win32con.SWP_SHOWWINDOW | win32con.SWP_NOSIZE | win32con.SWP_NOMOVE)</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;取消置顶&quot;</span>, hwnd, win32gui.GetWindowText(hwnd))</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">handler</span>(<span class="params">self, op, hwnd</span>):</span></span><br><span class="line">        op(hwnd)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">get_key</span>(<span class="params">self</span>):</span></span><br><span class="line">        <span class="function"><span class="keyword">def</span> <span class="title">fun</span>():</span></span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> <span class="keyword">not</span> self.flag <span class="keyword">and</span> win32gui.GetForegroundWindow() != <span class="string">&#x27;&#x27;</span>:</span><br><span class="line">                self.hd = win32gui.GetForegroundWindow()</span><br><span class="line">                self.handler(self.force_focus, self.hd)</span><br><span class="line">                self.flag = <span class="literal">True</span></span><br><span class="line">            <span class="keyword">elif</span> self.flag <span class="keyword">and</span> win32gui.GetForegroundWindow() != <span class="string">&#x27;&#x27;</span>:</span><br><span class="line">                <span class="keyword">if</span> self.hd == win32gui.GetForegroundWindow():</span><br><span class="line">                    self.handler(self.cancel_focus, win32gui.GetForegroundWindow())</span><br><span class="line">                    self.flag = <span class="literal">False</span></span><br><span class="line"></span><br><span class="line">        keyboard.add_hotkey(<span class="string">&#x27;alt+t&#x27;</span>, fun)</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">            keyboard.wait()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    zd = totop()</span><br><span class="line">    zd.get_key()</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
      
      
      <categories>
          
          <category> 无用小工具 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Python </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据库设计</title>
      <link href="2021/06/12/%E6%95%B0%E6%8D%AE%E5%BA%93/database_design/"/>
      <url>2021/06/12/%E6%95%B0%E6%8D%AE%E5%BA%93/database_design/</url>
      
        <content type="html"><![CDATA[<h2 id="实体关系-Entity-Relationship-E-R-概念"><a href="#实体关系-Entity-Relationship-E-R-概念" class="headerlink" title="实体关系(Entity-Relationship, E-R)概念"></a>实体关系(Entity-Relationship, E-R)概念</h2><ul><li>E-R 模型是一种描述数据库的抽象方法</li><li>实体关系建模的方法更多依赖于直觉而非机器, 但会导致相同的设计</li></ul><h3 id="E-R-模型"><a href="#E-R-模型" class="headerlink" title="E-R 模型"></a>E-R 模型</h3><h4 id="实体-Entity"><a href="#实体-Entity" class="headerlink" title="实体 (Entity)"></a>实体 (Entity)</h4><ul><li>实体是具有公共性质的可区别的现实世界对象集合</li><li><p>举例</p><ul><li>学生</li><li>教师</li><li>教师</li><li>课程</li><li>选课</li></ul></li><li><p>一般而言, 一个实体被映射到一张关系表中, 代表一组对象的集合; 表中的每一行被称为一个实体发生(Entity Occurrence)或实体实例(Entity Instance), 代表一个特定对象</p></li><li>在 E-R 图中, 用矩形框表示</li></ul><h4 id="属性-Attribute"><a href="#属性-Attribute" class="headerlink" title="属性 (Attribute)"></a>属性 (Attribute)</h4><ul><li><p>属性是描述实体(Entity)或者关系(Relationship)性质的关系项</p></li><li><p>在 E-R 图中, 用椭圆框表示, 主标识符要加下划线, 多值属性要加一条线</p></li><li><p>特定属性的特定术语</p><ul><li><p><strong>标识符或候选键</strong> (Identifier 或 Candidate Key)</p><p>标识符是能够<strong>唯一识别一个实体实例的属性集</strong>, 一个实体可以有多个标识符</p></li><li><p><strong>主键或主标识符</strong> (Primary Key)</p><p>被数据库设计者选择出来的作为表中特定行唯一标识符的候选键, 一个实体只有一个主标识符</p></li><li><p><strong>描述符</strong>(Descriptor)</p><p>描述性的非键属性, 如年龄</p></li><li><p><strong>复合属性</strong></p><p>一组共同描述一个性质的简单属性</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210612015258308.png" alt="image-20210612015258308"></p></li><li><p><strong>多值属性</strong></p><p>单个实例这个属性可以具有多个值, 如下图: 一个人可以有多个爱好</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210612015435640.png" alt="image-20210612015435640"></p></li></ul></li></ul><h4 id="联系-Relationships"><a href="#联系-Relationships" class="headerlink" title="联系(Relationships)"></a>联系(Relationships)</h4><ul><li>给定一个包含 m 个实体的有序列表, E1, E2,…, Em(一个实体可以出现多次)</li><li>一个联系 R 当以了这些实体实例之间的对应规则</li><li>特别地 R 代表了一个 m 元组的集合, 它是笛卡尔积 E1$\times$ E2$\times$ …$\times$ Em的子集</li><li>联系用菱形表示, 联系也能附加属性</li></ul><p>举例: <img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210612024931781.png" alt="image-20210612024931781"></p><h3 id="将实体和属性转换为关系"><a href="#将实体和属性转换为关系" class="headerlink" title="将实体和属性转换为关系"></a>将实体和属性转换为关系</h3><ul><li><p><strong>规则一</strong></p><ul><li>一个实体映射到关系型数据库中的一张表. <strong>实体的单值属性被映射为表的列</strong>(复合属性被映射为多个简单列)</li><li>实体标识符映射为候选键</li><li>实体主标识符映射为主键</li><li>实体的实例映射为表中的一行</li></ul><p>举个例子: 按上面出现过的图, Students(sid, Iname, fname, midiaitia)</p></li><li><p><strong>规则二</strong></p><ul><li>多值属性必须被映射成它自己的表</li></ul><p>举例: 对于上面的 hobbies 多值属性, 将 hobbies 单独映射成一张表 hobbies(hobby,eid)</p></li><li><p><strong>规则三</strong>: N-N Relationships</p><ul><li>当两个实体 E 和 F 参与一个多对多二元联系 R 时, 在相关的关系型数据库中, 联系被映射成一个表 T, 表 T 中包含所有从 E 和 F 转化而来的<strong>两个表的主键</strong>的所有属性, 列构成了表 T 的主键</li><li>T 也包含了所有附加在联系 R 上的属性构成的列</li></ul><p>简单来讲, 就是 N-N 联系中, 将联系单独转换成一张表, 表的主键是 E 和 F 的表的主键, 还要加上附加的属性</p><p>上面这好似读天书一般, 举个例子:</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210612131047918.png" alt="image-20210612131047918"></p><p>Employees 和 Projects 是 N-N 的关系, 可以得到三张表:</p><ul><li>Employees(<span style="color:red"><strong><u>eid</u></strong></span>, straddr, city,…)</li><li>Projects(<span style="color:red"><strong><u>prid</u></strong></span>, proj_name, cue_date)</li><li>work_on(<span style="color:red"><strong><u>eid, prid</u></strong></span>, percent)</li></ul></li><li><p><strong>规则四</strong>: N-1 Relationships</p><ul><li>当两个实体 E, F 参与 N-1 的二元联系 R 时, 这个关系不能被映射成自身的一个表.</li><li>若 max_card(F, R) = 1,并且 F 为联系中的多方, 那么从实体 F 转换出的关系表 T 中包括从 E 转换出的关系表的主键属性列, 这被称为 <strong>T 的外键</strong>(可以简单理解为表的一列是另一张表的主键, 这两张表是有关联的)</li><li>若 F 强制参与, F 转换出的关系表中外键列不允许为空;若 F 是选择参与, 允许为空</li></ul><p>简单来讲, N-1 联系: 两个实体转换成两张表, 为 N 方的表需要包含外键(1 方的主键)</p><p>举例:</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210612140039692.png" alt="image-20210612140039692"></p><p>一个 Instructors 可以对应多个 Course_sections, 一个Course_sections 只能对应一个 Instructors, 所以映射成两张表:</p><ul><li>Instructors(<span style="color:red"><strong><u>insid</u></strong></span>, Iname,…)</li><li>Course_sections(<span style="color:red"><strong><u>secid</u></strong></span>, <span style="color:blue"><em><b><u>insid</u></b></em></span>, course,…)</li></ul></li><li><p><strong>规则五&amp;六</strong>: 1-1 Relationships</p><ul><li>有一侧是可选参与<ul><li>若两张表都是可选参与: 选一张表插入另一张表的主键属性列作为外键;</li><li>若有一张表是强制参与: 在强制参与的实体表中添加外键列(非空的)</li></ul></li><li>都是强制参与<ul><li>最好将两张表合并, 避免使用外键</li></ul></li></ul></li></ul><h2 id="E-R-图更多的细节"><a href="#E-R-图更多的细节" class="headerlink" title="E-R 图更多的细节"></a>E-R 图更多的细节</h2><h3 id="基数-Cardinality-of-Entities-Participation-in-a-Relationship"><a href="#基数-Cardinality-of-Entities-Participation-in-a-Relationship" class="headerlink" title="基数 (Cardinality of Entities Participation in a Relationship)"></a>基数 (Cardinality of Entities Participation in a Relationship)</h3><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210612030714752.png" alt="image-20210612030714752"></p><ul><li>实体 E, F 联系 R</li><li>点表示实体的实例, 先表示联系的实例</li><li>max-card 和 min-card<ul><li>一个实例出去两条或两条以上的线, max-card = n;一个实例出去零条线, min-card = 0</li></ul></li></ul><p>举例: <img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210612031107358.png" alt="image-20210612031107358"></p><ul><li>1 个雇员可以管理 0 ~ n个雇员</li><li>1 个雇员最多向 1 个雇员报告(最高层管理没有上一级)</li></ul><h3 id="多值参与和单值参与-single-valued-participation-and-multi-valued-participation"><a href="#多值参与和单值参与-single-valued-participation-and-multi-valued-participation" class="headerlink" title="多值参与和单值参与 (single-valued participation and multi-valued participation)"></a>多值参与和单值参与 (single-valued participation and multi-valued participation)</h3><ul><li>max-card(X, R) = 1, X 单值参与 联系 R</li><li>max-card(X, R) = n, X 多值参与 联系 R</li></ul><h3 id="强制参与和可选参与-mandatory-participation-and-optional-participation"><a href="#强制参与和可选参与-mandatory-participation-and-optional-participation" class="headerlink" title="强制参与和可选参与 (mandatory participation and optional participation)"></a>强制参与和可选参与 (mandatory participation and optional participation)</h3><ul><li>min-card(X, R) = 1, X 强制参与 联系 R</li><li>max-card(X, R) = 0, X 可选参与 联系 R</li></ul><h3 id="One-to-One-Many-to-Many-and-Many-to-One-Relationship"><a href="#One-to-One-Many-to-Many-and-Many-to-One-Relationship" class="headerlink" title="One-to-One, Many-to-Many, and Many-to-One Relationship"></a>One-to-One, Many-to-Many, and Many-to-One Relationship</h3><ul><li>One-to-One: 两个实体均为单值参与</li><li>Many-to-Many: 两个实体均为多值参与</li><li>Many-to-One: 一个实体多值参与, 另一个实体单值参与</li></ul><h3 id="弱实体-Weak-Entities"><a href="#弱实体-Weak-Entities" class="headerlink" title="弱实体 (Weak Entities)"></a>弱实体 (Weak Entities)</h3><ul><li>如果一个实体的所有实例都通过联系 R 依赖于另一个实体的实例而存在, 这个实体就是弱实体, 另一个实体是强实体</li></ul><p>举例: <img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210612185558801.png" alt="image-20210612185558801"></p><p>弱实体 Line_items, 强实体 Orders, Line_items 的主标识符 Line_number 只有存在于某个订单中时, 才是有意义的. 若 订单取消了, Line_items 中所有相关的记录也会消失.</p><p>若 Line_items 映射为一张关系表, ,按照规则四, Orders 的主键 oid 被加入进来, 表的主键由外属性 Oid 和弱实体标识符 Line_number 组成</p><h3 id="泛化层次"><a href="#泛化层次" class="headerlink" title="泛化层次"></a>泛化层次</h3><p>这不就是继承吗</p><h2 id="函数依赖-Functional-Dependency-FD"><a href="#函数依赖-Functional-Dependency-FD" class="headerlink" title="函数依赖 (Functional Dependency, FD)"></a>函数依赖 (Functional Dependency, FD)</h2><ul><li>定义: A-&gt;B, 读作 A 决定B (或者 B 依赖于A ), 意为对于 T 中的两行 r<sub>1</sub> 和 r<sub>2</sub>, 若r<sub>1</sub>(A) = r<sub>2</sub>(A) 则 r<sub>1</sub>(B) = r<sub>2</sub>(B)\</li><li>完全函数依赖: X-&gt;Y, 对于 X 的任意一个真子集 X’, X’-&gt;Y 均不成立, 则称 Y 完全依赖于 X. 如 (学号, 课程)-&gt;成绩</li><li>部分函数依赖:Y 不完全依赖于 X, 如 (学号, 课程)-&gt;姓名, 只用学号就能决定姓名了</li></ul><p>举例:  </p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210613142024588.png" alt="image-20210613142024588"></p><p>Sno-&gt;Sname…</p><h3 id="Armstron规则"><a href="#Armstron规则" class="headerlink" title="Armstron规则:"></a>Armstron规则:</h3><script type="math/tex; mode=display">\text { If } \mathbf{Y} \subseteq \mathbf{X}, \text { then } \mathbf{X} \rightarrow \mathbf{Y}</script><p>X 都相等了, X 的子集肯定也相等</p><ol><li><p>传递规则:</p><script type="math/tex; mode=display">\text { If } \mathbf{X} \rightarrow \mathbf{Y} \text { and } \mathbf{Y} \rightarrow \mathbf{Z}, \text { then } \mathbf{X} \rightarrow \mathbf{Z}</script></li><li><p>增广规则:</p><script type="math/tex; mode=display">\text { If } \mathbf{X} \rightarrow \mathbf{Y}, \text { then } \quad \mathbf{X Z} \rightarrow \mathbf{Y Z}</script><script type="math/tex; mode=display">\mathbf{t}_{\mathbf{1}}[\mathbf{X} \mathbf{Z}]=\mathbf{t}_{\mathbf{2}}[\mathbf{X} \mathbf{Z}]</script><p>$\mathbf{t}<em>{\mathbf{1}}[\mathbf{X}]=\mathbf{t}</em>{\mathbf{2}}[\mathbf{X}]$<br>$\mathbf{t}<em>{\mathbf{1}}[\mathbf{Z}]=\mathbf{t}</em>{2}[\mathbf{Z}]$</p></li></ol><h3 id="Armstrong-公理的蕴含"><a href="#Armstrong-公理的蕴含" class="headerlink" title="Armstrong 公理的蕴含"></a>Armstrong 公理的蕴含</h3><ol><li>合并规则:</li></ol><script type="math/tex; mode=display">\text { If } \mathbf{X} \rightarrow \mathbf{Y} \operatorname{and} \mathbf{X} \rightarrow \mathbf{Z}, \text { then } \mathbf{X} \rightarrow \mathbf{Y Z}</script><ol><li><p>分解规则:</p><script type="math/tex; mode=display">\text { If } \mathbf{X} \rightarrow \mathbf{Y Z}, \text { then } \mathbf{X} \rightarrow \mathbf{Y}, \text { and } \mathbf{X} \rightarrow \mathbf{Z}</script></li><li><p>伪传递规则:</p><script type="math/tex; mode=display">\text { If } \mathbf{X} \rightarrow \mathbf{Y}, \text { and } \mathbf{W Y} \rightarrow \mathbf{Z}, \text { then } \mathbf{X W} \rightarrow \mathbf{Z}</script></li><li><p>聚积规则:</p><script type="math/tex; mode=display">\text { If } \mathbf{X} \rightarrow \mathbf{Y} \mathbf{Z} \text { and } \mathbf{Z} \rightarrow \mathbf{W}, \text { then } \mathbf{X} \rightarrow \mathbf{Y Z W}</script></li></ol><p>例题: </p><script type="math/tex; mode=display">\begin{array}{|c|c|c|c|}\hline \text{A} & \text { B } & \text { C } & \text { D } \\\hline \text{a1} & \text { b1 } & \text { c1 } & \text { d1 } \\\hline \text { a1 } & \text { b1 } & \text { c2 } & \text { d2 } \\\hline \text { a2 } & \text { b1 } & \text { c1 } & \text { d3 } \\\hline \text { a2 } & \text { b1 } & \text { c3 } & \text { d4 } \\\hline\end{array}</script><p>存在的函数依赖: A-&gt;B, D-&gt;ABC, AC-&gt;D C-&gt;D, 首先找左边只有一个的, 然后找左边有多个的(排除掉没有被依赖的和决定所有其他的), 如果可以用 Armstrong 公理推出, 就不需要一个一个看</p><h3 id="函数依赖集的闭包-Closure-of-a-Set-of-FDs"><a href="#函数依赖集的闭包-Closure-of-a-Set-of-FDs" class="headerlink" title="函数依赖集的闭包(Closure of a Set of FDs)"></a>函数依赖集的闭包(Closure of a Set of FDs)</h3><p>给定一个函数依赖集 F 作用在表 T 的属性上, 定义 F 的 闭包(记作 F<sup>+</sup>)为 F 推导出的所有函数依赖的集合</p><ul><li>F 中有两个函数依赖 a, b, 基于 Armstrong 公理和 a,b 可以得到新的函数依赖 c, c 就是 F 推导出的函数依赖</li><li>如果 d 是平凡依赖 (X-&gt;Y 且 Y⊆X), d 是由 F 推导出的函数依赖</li><li>F 中的函数依赖都属于 F<sup>+</sup></li></ul><h3 id="函数依赖集的覆盖"><a href="#函数依赖集的覆盖" class="headerlink" title="函数依赖集的覆盖"></a>函数依赖集的覆盖</h3><p>对于表 T 上的两个函数依赖集 F 和 G, 如果 G 可从 F 由蕴含规则推导出来(即 G ⊆ F<sup>+</sup>, F 覆盖 G)</p><h3 id="函数依赖集的等价"><a href="#函数依赖集的等价" class="headerlink" title="函数依赖集的等价"></a>函数依赖集的等价</h3><p>F 覆盖 G, G 覆盖 F, 则 F 等价于 G</p><h3 id="属性集的闭包"><a href="#属性集的闭包" class="headerlink" title="属性集的闭包"></a>属性集的闭包</h3><p>给定表 T 的函数依赖集 F 和属性集 X, X 的闭包(记作 X<sup>+</sup> )作为由 X 决定的最大属性集合 Y, Y 满足 X-&gt;Y 并且 Y 存在于 F<sup>+</sup></p><p>说人话: 在 F <sup>+</sup> 中, 对于属性集 X 有 X-&gt;A, 所有 A 的集合被称作 X<sup>+</sup> (A 也在 F<sup>+</sup>)</p><script type="math/tex; mode=display">\mathrm{X}^{+}_ \mathrm{F}=\left\{\mathbf{A} \mid \mathbf{X} \rightarrow \mathbf{A} \in \mathbf{F}^{+}\right\}</script><p><strong>算法</strong>:</p><p>先把 X<sup>+</sup> 赋值为 X, 然后对于函数依赖集 F 中的每一项, 若左侧包含于当前的 X<sup>+</sup> , 将右侧的并入 X<sup>+</sup>, 直到 X<sup>+</sup> 中不再增加<br><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210613185430885.png" alt="image-20210613185430885"></p><p>练习:</p><script type="math/tex; mode=display">\text { Example 6.6.7: } \mathrm{F}=\left\{\left(\mathrm{f}_{1}\right) \mathrm{B} \rightarrow \mathrm{CD}, \quad\left(\mathrm{f}_{2}\right) \mathrm{AD} \rightarrow \mathrm{E}\right. \text { , }\left.\left(f_{3}\right) B \rightarrow A\right\}, \text { compute }\{B\}^{+} ?</script><p>答案:</p><p>X<sup>+</sup> = {A,B,C,D,E}</p><h3 id="最小覆盖"><a href="#最小覆盖" class="headerlink" title="最小覆盖"></a>最小覆盖</h3><ul><li>没有冗余的函数依赖</li><li>每一个函数依赖的左边都没有多余属性</li></ul><p><strong>计算步骤</strong>:</p><ol><li><p>创建函数依赖集 F 的等价函数依赖集 H, 它的右边只有单个属性</p></li><li><p>顺次去掉 H 中非关键的单个依赖</p><blockquote><p>将 H 中的一项 X-&gt;Y 去掉, 得到新的函数依赖集 J, 若 J<sup>+</sup> =H <sup>+</sup> 则称这个函数依赖是非关键的. 也就是说去除这个函数依赖对 H <sup>+</sup>没有任何影响.</p></blockquote></li><li><p>在不改变 H<sup>+</sup> 的前提下, 将 H 中的每个函数依赖用左边属性更少的函数依赖替换</p><p><span style="color:red"><b>注意: 第三部中函数依赖集如果发生了变化, 需要返回第二步</b></span></p></li><li><p>用合并规则创建一个等价的函数依赖集 M</p></li></ol><p>来个例题: <script type="math/tex">\mathbf{F}=\{\mathbf{a} \rightarrow \mathbf{b}, \mathbf{b}\mathbf{c} \rightarrow \mathbf{d}, \mathbf{ac} \rightarrow \mathbf{d}\}</script>, 求 F 的最小覆盖 M</p><p>解题步骤:</p><ol><li>本来就做好了</li><li><p>依次尝试去掉非关键依赖</p><ol><li>尝试去掉 a-&gt;b, 得到 <script type="math/tex">\mathbf{G}=\{ \mathbf{b} \mathbf{c} \rightarrow \mathbf{d}, \mathbf{ac} \rightarrow \mathbf{d}\}</script>, {a}<sub>G</sub><sup>+</sup> = {a}, 所以去掉 a-&gt;b 后, 在 G 中无法再推导出 a-&gt;b, G<sup>+</sup> != H<sup>+</sup> 不能去掉.</li><li>尝试去掉 bc-&gt;d, 得到 <script type="math/tex">\mathbf{G}=\{\mathbf{a} \rightarrow \mathbf{b},  \mathbf{ac} \rightarrow \mathbf{d}\}</script>, {b,c}<sub>G</sub><sup>+</sup> = {b,c}, 不包含 d, 不能去掉</li><li>尝试去掉 ac-&gt;d, <script type="math/tex">\mathbf{G}=\{\mathbf{a} \rightarrow \mathbf{b}, \mathbf{b} \mathbf{c} \rightarrow \mathbf{d}\}</script>, {a,c}<sub>G</sub><sup>+</sup> = {a,c,b,d}, 包含了 d, 所以去掉后的函数依赖集 G 仍然可以推导出所有的函数依赖, 即 G<sup>+</sup> = F<sup>+</sup> , 是非关键依赖, 可以去掉</li></ol></li><li>上一步的结果:<script type="math/tex">\mathbf{F}=\{\mathbf{a} \rightarrow \mathbf{b},\mathbf{b}\mathbf{c} \rightarrow \mathbf{d}\}</script>. 尝试减少左侧的属性<ol><li>尝试将 bc-&gt;d 精简为 c-&gt;d, 得到 <script type="math/tex">\mathbf{G}=\{\mathbf{a} \rightarrow \mathbf{b},\mathbf{c} \rightarrow \mathbf{d}\}</script>, 计算 {c}<sub>F</sub><sup>+</sup> = {c}, 不包含 d 所以不能精简</li><li>将 bc-&gt;d 精简为 b-&gt;d, 得到<script type="math/tex">\mathbf{G}=\{\mathbf{a} \rightarrow \mathbf{b},\mathbf{b} \rightarrow \mathbf{d}\}</script>, 计算 {b}<sub>F</sub><sup>+</sup> = {b}, 不包含 d 所以不能精简</li></ol></li><li>这个例子不需要合并, 最终结果: <script type="math/tex">\mathbf{F}=\{\mathbf{a} \rightarrow \mathbf{b},\mathbf{b}\mathbf{c} \rightarrow \mathbf{d}\}</script></li></ol><h2 id="无损分解"><a href="#无损分解" class="headerlink" title="无损分解"></a>无损分解</h2><h3 id="规范化的流程"><a href="#规范化的流程" class="headerlink" title="规范化的流程"></a>规范化的流程</h3><ul><li><p>把一张表分解为一张或者多张更小的表</p><p>也就是投影到两个或者多个覆盖全部列的子集并有一些公共列</p></li><li><p>但将表重新连接起来的时候, 并不总与原表完全相同</p><p>可能多出一些原来没有的行</p><p>举个例子:</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210613224111274.png" alt="image-20210613224111274"></p></li></ul><h3 id="无损-分解"><a href="#无损-分解" class="headerlink" title="无损 分解"></a>无损 分解</h3><p>对于一个表 T 和它的一个函数依赖集 F, T 的一个分解(decomposition) 是一个表的集合: {T<sub>1</sub>,T<sub>2</sub>,…,T<sub>k</sub>}. 这个集合具有性质:</p><ul><li><p>对于集合中的一个表 T<sub>i</sub> , Head(T<sub>i</sub>) 是  Head(T) 的一个子集</p></li><li><p>Head(T)  =  Head(T<sub>1</sub>) ∪  Head(T<sub>2</sub>) ∪….∪…∪ Head(T<sub>k</sub>) </p></li><li><p>给定表 T 的特定内容, T 的一行被投影到每个 T<sub>i</sub> 的列上作为分解的结果  ????</p></li><li><p>F 中的所有函数依赖需要保证: </p><script type="math/tex; mode=display">\mathbf{T} \equiv \mathbf{T}_{1} \text { join } \mathbf{T}_{2} \text { join } \ldots \text { join } \mathbf{T}_{\mathbf{k}}</script></li></ul><p>说人话: 无损分解(也叫无损联接分解) 指将一个关系模式分解为若干个关系模式后, 通过自然连接和投影等运算, 还能回到原来的关系模式. 如果插入了新的记录, 前面的条件仍然必须满足</p><h4 id="一个定理"><a href="#一个定理" class="headerlink" title="一个定理"></a>一个定理</h4><ul><li><p>给定一个表 T 和它的一个函数依赖集 F, 一个把 T 分解为 {T<sub>1</sub>,T<sub>2</sub>}的分解是 T 的一个无损分解, 当且仅当 Head(T<sub>1</sub>) Head(T<sub>2</sub> )都是 Head(T) 的真子集,  Head(T<sub>1</sub>)∪ Head(T<sub>2</sub> ) = Head(T), 同时以下两个可以由 F 推导出来</p><ol><li>Head(T<sub>1</sub>) ∩ Head(T<sub>2</sub> )-&gt; Head(T<sub>1</sub>) </li><li>Head(T<sub>1</sub>) ∩ Head(T<sub>2</sub> )-&gt; Head(T<sub>2</sub>) </li></ol></li></ul><p>  说人话: 判断分解成的两个表是不是无损分解, 就得根据表 T 的函数依赖集 F, 检查两张表标题交集能否决定其中一张表的标题</p><p>  举例子:  <script type="math/tex">\mathbf{F}=\{\mathbf{A} \rightarrow \mathbf{B}\}, \quad \mathbf{T}_{1}(\mathbf{A}, \mathbf{B}), \mathbf{T}_{2}(\mathbf{A}, \mathbf{C})</script> ,Head(T<sub>1</sub>) ∩ Head(T<sub>2</sub> ) = A, 而 A-&gt;AB, 所以是无损分解.</p><h4 id="如何无损分解"><a href="#如何无损分解" class="headerlink" title="如何无损分解?"></a>如何无损分解?</h4><p>  每个函数依赖左边的属性在老的核心的表中都出现, 并决定了所有新表中的其他属性</p><h3 id="数据库模式-Database-Schema"><a href="#数据库模式-Database-Schema" class="headerlink" title="数据库模式 (Database Schema)"></a>数据库模式 (Database Schema)</h3><ul><li><p>一个数据库的模式是数据库所有表的标题的集合, 以及设计者希望在表的连接上成立的所有的函数依赖的集合.</p></li><li><p>举例子:</p><p>假定 ABC 有函数依赖 B-&gt;C, 则下表是合法的</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210614013215166.png" alt="image-20210614013215166"></p><p>像下面那样插入是非法的, 因为破坏了 B-&gt;C</p></li></ul><p>  <img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210614013324318.png" alt="image-20210614013324318"></p><h2 id="范式-Normal-Form-NF"><a href="#范式-Normal-Form-NF" class="headerlink" title="范式 (Normal Form, NF)"></a>范式 (Normal Form, NF)</h2><p>设计关系数据库时, 遵从不同的规范要求, 设计出合理的关系型数据库, 这些规范被称为<strong>范式</strong></p><p>目的: </p><ul><li>使结构更合理</li><li>消除存储异常</li><li>减小数据冗余</li><li>便于增,删,更新</li></ul><h3 id="保持依赖性-FD-Preserved"><a href="#保持依赖性-FD-Preserved" class="headerlink" title="保持依赖性 (FD Preserved)"></a>保持依赖性 (FD Preserved)</h3><ul><li>前置条件: 通用表 T, 函数依赖集 F, 无损分解 {T<sub>1</sub>,T<sub>2</sub>,…,T<sub>k</sub>}</li><li>对于 F 中的一个函数依赖 X-&gt;Y,如果在 T<sub>i</sub> 中有 X ∪ Y ⊆Head(T<sub>i</sub>), 则称在 T<sub>i</sub> 保持了依赖性</li><li>若<script type="math/tex">\text { F和 }\left(F_{1} \cup F_{2} \cup \ldots \cup F_{k}\right)</script> 相互等价, 即 <script type="math/tex">\text { F}^+=\left(F_{1} \cup F_{2} \cup \ldots \cup F_{k}\right)^+</script> , 称这个分解是保持依赖性的</li></ul><h3 id="超键-Super-Key"><a href="#超键-Super-Key" class="headerlink" title="超键 (Super Key)"></a>超键 (Super Key)</h3><ul><li><p>超键在关系中能够<strong>唯一标识元组的属性集</strong>, 允许有多余属性</p></li><li><p>给定表 T 和 它的一组函数依赖集 F, 属性集 X ⊆ Head(T), 下面的描述等价</p><ul><li>X 是 T 的超键</li><li>X -&gt; Head(T) 或者 X<sup>+</sup> <sub>F</sub>-&gt; Head(T) </li></ul></li></ul><h3 id="候选键-Key"><a href="#候选键-Key" class="headerlink" title="候选键 (Key)"></a>候选键 (Key)</h3><ul><li><p>候选键同样可以唯一标识元组, 不允许有多余属性</p></li><li><p>寻找候选键的算法:</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/database_design/image-20210614025519648.png" alt="image-20210614025519648"></p><p>就是依次尝试去掉在 Head(T)中的属性, 若去掉后的属性集在 F 的闭包包含了 T 的所有属性(可以决定 T 所有的属性), 就可以真的去掉了</p></li></ul><h3 id="主属性-Primary-Attribute"><a href="#主属性-Primary-Attribute" class="headerlink" title="主属性 (Primary Attribute)"></a>主属性 (Primary Attribute)</h3><ul><li>候选键里的属性就是主属性</li></ul><h3 id="范式"><a href="#范式" class="headerlink" title="范式"></a>范式</h3><h4 id="1NF"><a href="#1NF" class="headerlink" title="1NF"></a>1NF</h4><ul><li><p>关系型数据库的一张表中, 每一列都不可再分割, 即某一属性不能有多个值</p></li><li><p>不符合 1NF 的例子:</p></li></ul><div class="table-container"><table><thead><tr><th>id</th><th>姓名</th><th>年级</th><th>签到</th><th></th><th></th></tr></thead><tbody><tr><td></td><td></td><td></td><td>时间</td><td>次数</td><td>连续次数</td></tr><tr><td></td><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></div><ul><li>符合 1NF 的例子:</li></ul><div class="table-container"><table><thead><tr><th>id</th><th>姓名</th><th>系名</th><th>系主任</th><th>课名</th><th>分数</th></tr></thead><tbody><tr><td>191870001</td><td>六花</td><td>魔法</td><td>邪神</td><td>爆裂魔法</td><td>89</td></tr><tr><td>191870001</td><td>六花</td><td>魔法</td><td>邪神</td><td>高位魔法概述</td><td>93</td></tr><tr><td>191870001</td><td>六花</td><td>魔法</td><td>邪神</td><td>瞳术</td><td>99</td></tr><tr><td>191870002</td><td>薇薇</td><td>AI</td><td>松本</td><td>AI 格斗术</td><td>95</td></tr><tr><td>191870002</td><td>薇薇</td><td>AI</td><td>松本</td><td>歌唱艺术</td><td>97</td></tr><tr><td>191870002</td><td>薇薇</td><td>AI</td><td>松本</td><td>作曲</td><td>88</td></tr></tbody></table></div><h4 id="2NF"><a href="#2NF" class="headerlink" title="2NF"></a>2NF</h4><p>课件上的定义何止不是人话, 简直不是人话!</p><ul><li><p>在 1NF 的基础上, <strong>消除了非主属性对于键(指候选键)的部分函数依赖</strong></p></li><li><p>判断方法:</p><ol><li>找出表中所有非主属性</li><li>查看是否存在有非主属性对键的<strong>部分函数依赖</strong>, 若无, 则符合 2NF</li></ol></li><li><p>修改为符合 2NF:</p><ul><li>将数据表拆分成含有较少字段的表</li></ul></li><li><p>存在的问题: 插入, 删除还是存在异常</p></li></ul><ul><li><p>举例: 将之前的表修改为符合 2NF:</p><p>候选键:(id,课名),依赖关系: (id, 课名)-&gt;分数, id-&gt;(姓名,系名,系主任), 可以拆分为两张表</p></li></ul><div class="table-container"><table><thead><tr><th>id</th><th>姓名</th><th>系名</th><th>系主任</th></tr></thead><tbody><tr><td>191870001</td><td>六花</td><td>魔法</td><td>邪神</td></tr><tr><td>191870002</td><td>薇薇</td><td>AI</td><td>松本</td></tr></tbody></table></div><div class="table-container"><table><thead><tr><th>id</th><th>课名</th><th>分数</th></tr></thead><tbody><tr><td>191870001</td><td>爆裂魔法</td><td>89</td></tr><tr><td>191870001</td><td>高位魔法概述</td><td>93</td></tr><tr><td>191870001</td><td>瞳术</td><td>99</td></tr><tr><td>191870002</td><td>AI 格斗术</td><td>95</td></tr><tr><td>191870002</td><td>歌唱艺术</td><td>97</td></tr><tr><td>191870002</td><td>作曲</td><td>88</td></tr></tbody></table></div><h4 id="3NF"><a href="#3NF" class="headerlink" title="3NF"></a>3NF</h4><ul><li><p>在 2NF 的基础之上, <strong>消除了非主属性对于键的传递函数依赖</strong>. 如果存在非主属性对于键的传递函数依赖, 则不符合 3NF 的要求</p><ul><li>传递函数依赖: X-&gt;Y, Y-&gt;Z, 则  X-&gt;Z</li></ul></li><li><p>修改为符合 3NF:</p><ul><li>拆分</li></ul></li><li><p>举例</p><p>刚才的例子中, 存在 id-&gt;系名, 系名-&gt;系主任的依赖, 继续将这张表拆分:</p></li></ul><div class="table-container"><table><thead><tr><th>id</th><th>姓名</th><th>系名</th></tr></thead><tbody><tr><td>191870001</td><td>六花</td><td>魔法</td></tr><tr><td>191870002</td><td>薇薇</td><td>AI</td></tr><tr><td></td><td></td></tr></tbody></table></div><div class="table-container"><table><thead><tr><th>系名</th><th>系主任</th></tr></thead><tbody><tr><td>魔法</td><td>邪神</td></tr><tr><td>AI</td><td>松本</td></tr></tbody></table></div><div class="table-container"><table><thead><tr><th>id</th><th>课名</th><th>分数</th></tr></thead><tbody><tr><td>191870001</td><td>爆裂魔法</td><td>89</td></tr><tr><td>191870001</td><td>高位魔法概述</td><td>93</td></tr><tr><td>191870001</td><td>瞳术</td><td>99</td></tr><tr><td>191870002</td><td>AI 格斗术</td><td>95</td></tr><tr><td>191870002</td><td>歌唱艺术</td><td>97</td></tr><tr><td>191870002</td><td>作曲</td><td>88</td></tr></tbody></table></div><h4 id="BCNF"><a href="#BCNF" class="headerlink" title="BCNF"></a>BCNF</h4><ul><li>基于 3NF, 更加严格</li><li>在 3NF 基础上<strong>消除主属性对候选键的部分依赖和传递依赖</strong></li></ul><p>来几个练习题:</p><ol><li><p>R(A,B,C), F={AB-&gt;C}</p><ul><li><p>候选键: AB, 主属性:A,B,非主属性:C,</p></li><li><p>C 完全依赖于 AB, 满足 2NF</p></li><li><p>没有 C 对 AB 的传递依赖, 满足 3NF</p></li><li>满足 BCNF</li></ul></li><li><p>R(A,B,C), F={B-&gt;C,AC-&gt;B}</p><ul><li>候选键: AB, AC, 主属性: A, B, C, 非主属性: 无</li><li>最少都会是 3NF </li><li>AB 是候选键, B-&gt;C , C 作为主属性对 AB 的子集 B 存在依赖, 所以存在主属性对候选键的部分依赖, 不符合 BCNF</li></ul></li><li><p>R(A,B,C), F={B-&gt;C, B-&gt;A, A-&gt;BC}</p><ul><li>候选键: A, B, 主属性: A, B, 非主属性: C</li><li>满足 3NF</li><li>满足 BCNF</li></ul></li></ol>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 数据库 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机网络 3 -数据链路层</title>
      <link href="2021/05/02/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C_03/"/>
      <url>2021/05/02/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C_03/</url>
      
        <content type="html"><![CDATA[<h2 id="数据链路层概述"><a href="#数据链路层概述" class="headerlink" title="数据链路层概述"></a>数据链路层概述</h2><h3 id="数据链路层在网络体系中所处的地位"><a href="#数据链路层在网络体系中所处的地位" class="headerlink" title="数据链路层在网络体系中所处的地位"></a>数据链路层在网络体系中所处的地位</h3><p>研究数据链路层的问题时, 可以认为数据包只在数据链路层沿水平方向传送.</p><p>如下图, 两台主机之间的通信可以看作是在 4 条不同的链路上的通信组成的.</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/q2UfpgF6CZkXlAV.webp" alt="image-20210324094254469"></p><ul><li><strong>链路</strong>(Link) 从一个结点到相邻结点的一段物理线路, 而中间没有任何其他的交换结点</li><li><strong>数据链路</strong>(Data Link) 把实现通信协议的硬件和软件加在链路上, 形成数据链路</li><li>数据链路层以<strong>帧</strong>(Frame)为单位传输和处理数据</li></ul><h3 id="使用点对点信道的数据链路层"><a href="#使用点对点信道的数据链路层" class="headerlink" title="使用点对点信道的数据链路层"></a>使用点对点信道的数据链路层</h3><ul><li>封装成帧</li><li>差错检测</li><li>可靠传输</li></ul><h3 id="使用广播信道的数据链路层-共享式局域网"><a href="#使用广播信道的数据链路层-共享式局域网" class="headerlink" title="使用广播信道的数据链路层(共享式局域网)"></a>使用广播信道的数据链路层(共享式局域网)</h3><ul><li><p>代表帧的信号会通过总线传输到总线上的其他各主机. 如何分辨帧是发给自己的呢? <em>在帧中添加地址字段</em></p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/WHfOFptjs5TBv4g.webp" alt="image-20210324213557657"></p></li><li><p>总线上多台主机同时使用总线传输帧的时候, 传输信号产生碰撞</p><ul><li>以太网: CSMA/CD</li></ul><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/Es2PAFQyNwufpCc.webp" alt="image-20210324213843375"></p></li></ul><h3 id="交换式局域网"><a href="#交换式局域网" class="headerlink" title="交换式局域网"></a>交换式局域网</h3><p>使用点对点链路和链路层交换机的交换式局域网已经在(有线)局域网的领域取代了共享式局域网</p><ul><li>网桥和交换机工作原理</li></ul><h3 id="无线局域网"><a href="#无线局域网" class="headerlink" title="无线局域网"></a>无线局域网</h3><ul><li>802.11 局域网的媒体介入控制协议 CSMA/CA</li></ul><h2 id="封装成帧"><a href="#封装成帧" class="headerlink" title="封装成帧"></a>封装成帧</h2><ul><li><p>封装成帧是指数据链路层给上层交付的协议数据单元添加帧头和帧尾使之成为帧</p><ul><li><p>帧头和帧尾包含重要控制信息</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/u8elLsg1oaNiF4j.webp" alt="image-20210325013459616"></p><p> <img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/HLJ1DZoIEMCY8Bv.webp" alt="image-20210325013523303"></p></li><li><p>帧头和帧尾的作用之一就是<strong>帧定界</strong> </p><ul><li><p>MAC帧中无帧定界标志, 而是添加前导码. MAC 帧的发送间隔为 96 比特时间</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/jE81b94WBLvwTRC.webp" alt="image-20210325013929419"></p></li></ul></li></ul></li><li><p>透明传输是指<strong>数据链路层对上层交付的传输数据没有任何限制</strong>,就好像数据链路层不存在一样</p><ul><li><p>面向字节的物理量链路使用字节填充(字符填充), 如: 插入转义字符 <strong>ESC</strong> (0x1B, 0b00011011)</p></li><li><p>面向比特的数据链路使用比特填充, 如下图每 5 个比特 1 填充一个比特 0    </p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/CvWg9PMdB8UZpQ2.webp" alt="image-20210325014909479"></p></li></ul></li><li><p>为了提高帧的传输效率,应当使帧的数据部分的长度尽可能大些.</p></li><li><p>考虑到差错控制等多种因素,每一种数据链路层协议都规定了帧的数据部分的长度上限,即<strong>最大传送单元 MTU</strong> (Maximum Transfer Unit)。</p></li></ul><h2 id="差错检测"><a href="#差错检测" class="headerlink" title="差错检测"></a>差错检测</h2><ul><li>实际的通信链路都不是理想的, 比特在传输过程中可能会产生差错: 1可能会变成0, 而0也可能变成1. 这称为比特差错.</li><li>在一段时间内, 传输错误的比特占所传输比特总数的比率称为误码率BER(Bit Error Rate).</li><li><p>使用差错检测码来检测数据在传输过程中是否产生了比特差错, 是数据链路层所要解决的重要问题之一.</p></li><li><p>帧尾中包含的 FCS (检错码)字段</p></li></ul><h3 id="奇偶校验"><a href="#奇偶校验" class="headerlink" title="奇偶校验"></a>奇偶校验</h3><p>见计组</p><h3 id="循环冗余校验-CRC"><a href="#循环冗余校验-CRC" class="headerlink" title="循环冗余校验 (CRC)"></a>循环冗余校验 (CRC)</h3><p>见计组</p><p>循环冗余校验CRC有很好的检错能力(漏检率非常低),虽然计算比较复杂,但非常易于用硬件实现,因此被广泛应用于数据链路层。</p><h3 id="局限"><a href="#局限" class="headerlink" title="局限"></a>局限</h3><ul><li>检错码只能检测出帧在传输过程中出现了差错,但并不能定位错误,因此无法纠正错误.</li><li>要想纠正传输中的差错,可以使用冗余信息更多的纠错码进行前向纠错。但纠错码的开销比较大,在计算机网络中较少使用.</li></ul><h2 id="可靠传输"><a href="#可靠传输" class="headerlink" title="可靠传输"></a>可靠传输</h2><h3 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h3><ul><li><p>数据链路层向上提供的服务</p><ul><li>不可靠传输服务: <strong>仅仅丢弃有误码的帧</strong>, 其他什么都不做</li><li>可靠传输服务: 想办法实现<strong>发送端发送什么, 接收端就收到什么</strong></li></ul></li><li><p>一般情况下,有线链路的误码率比较低,为了减小开销,并不要求数据链路层向上提供可靠传输服务。即使出现了误码,可靠传输的问题由其上层处理</p></li><li><p>无线链路易受干扰,误码率比较高,因此要求数据链路层必须向上层提供可靠传输服务</p></li><li><p>传输差错除了数据链路层的<strong>比特差错</strong>, 还包括<strong>分组丢失, 分组失序,分组重复</strong>. 后三者一般出现在上层, 这就意味着<strong>可靠传输不仅仅局限在数据链路层</strong></p><ul><li>TCP 向其上层提供面向连接的可靠传输服务</li><li>UDP 向上层提供无连接, 不可靠传输服务</li></ul></li><li>可靠传输实现复杂, 开销较大, 是否实现取决于具体的应用需求</li></ul><h3 id="停止-等待协议-Stop-and-Wait-SW"><a href="#停止-等待协议-Stop-and-Wait-SW" class="headerlink" title="停止-等待协议 (Stop-and-Wait, SW)"></a>停止-等待协议 (Stop-and-Wait, SW)</h3><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/EsBdW6Q8jzhuaNY.webp" alt="image-20210325095110782"></p><ul><li><p>正常情况下, 接收方每收到一个 DATA 分组, 就会返回一个 ACK 分组. 发送方接收到 ACK 分组后, 继续发送下一个 DATA 分组</p></li><li><p>接收端检测到数据分组有误码时, 将其丢弃并等待发送方的超时重传。但对于误码率较高的点对点链路, 为使发送方尽早重传,也可给发送方发送NAK 分组。</p></li><li><p>为了让接收方能够判断所收到的数据分组是否是重复的, 需要给数据分组编号。由于停止等待协议的停等特性, 只需1个比特编号就够了, 即编号0和1。</p></li><li><p>为了让发送方能够判断所收到的ACK分组是否是重复的, 需要给ACK分组编号,所用比特数量与数据分组编号所用比特数量一样。数据链路层一般不会出现ACK分组迟到的情况, 因此在数据链路层实现停止-等待协议可以不用给ACK分组编号。</p></li><li><p>超时计时器设置的重传时间应仔细选择, 一般可将重传时间选为略大于“从发送方到接收方的平均往返时间”。</p><ul><li>在数据链路层点对点的往返时间比较确定,重传时间比较好设定。</li><li>然而在运输层,  由于端到端往返时间非常不确定, 设置合适的重传时间有时并不容易。</li></ul></li><li><p>当往返时延RTT远大于数据帧发送时延To时(例如使用卫星链路) .信道利用率非常低。</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/rxmkWnRFJACPX8B.webp" alt="image-20210325134626019"></p></li><li><p>若出现重传, 则对于传送有用的数据信息来说, 信道利用率还要降低。</p></li><li><p>为了克服停止等待协议信道利用率很低的缺点, 就产生了另外两种协议, 即后退N帧协议GBN和选择重传协议SR。</p></li></ul><h3 id="回退-N-帧协议-GBN-（Go-Back-N"><a href="#回退-N-帧协议-GBN-（Go-Back-N" class="headerlink" title="回退 N 帧协议 GBN （Go-Back-N)"></a>回退 N 帧协议 GBN （Go-Back-N)</h3><h4 id="发送方"><a href="#发送方" class="headerlink" title="发送方"></a>发送方</h4><ul><li>发送窗口尺寸 $W_T$ 的取值范围是 $1&lt;W_T&lt;2^n-1$ , $n$ 为构成分组序号的比特数量<ul><li>$W_T$ = 1 停止等待协议</li><li>$W_T\geq2^n-1$  <strong>无法辨认新旧分组,</strong> 如累积确认分组丢失后, 发送方重发的数据分组会被接收方认为是新的的组</li></ul></li><li>发送方可以在未收到接收方确认分组的情况下, 将序号落在发送窗口中的多个数据分组全部发送出去</li><li><p>发送方收到已发送数据分组的确认时, 发送窗口才能向前移动</p></li><li><p>发送方收到多个重复确认时, 可在重传超时计时器前尽早开始重传, 由具体实现决定</p></li><li>发送方发送窗口内某个已发送的数据分组超时重发时, 其后续在发送窗口内已发送的数据分组也必须全部重传</li></ul><h4 id="接收方"><a href="#接收方" class="headerlink" title="接收方"></a>接收方</h4><ul><li><p>接收方的接收窗口 $W_R$ 大小为 1, 接收方只能<strong>按序接收</strong>数据分组</p></li><li><p>接收方只接受<strong>序号落在接收窗口且无误码</strong>的数据分组, 之后接收窗口滑动一个位置. </p><ul><li><strong>不一定每收到一个按需到达无误码的数据分组就发回一个确认分组</strong></li><li>可以接收到连续几个数据分组后, 针对最后一个数据分组发送确认分组, 称为<strong>累积确认</strong>. ACKn 表示序号为 n 以及之前的数据分组全部正确接收. 这意味着即使确认分组丢失了一部分, 发送方也不一定需要重传.</li><li>或者在自己有数据分组要发送时捎带确认</li></ul></li><li>接收方收到未按序到达的分组, 丢弃后对最近按序到达的数据分组进行确认</li></ul><h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><ul><li>回退 N 帧协议在流水线传输的基础上通过发送窗口限制发送方连续发送数据分组的数量, 是一种<strong>自动重传请求</strong>（Automatic Repeat-reQuest，<em>ARQ</em>）协议</li><li>协议工作过程中发送窗口和接收窗口不断向前滑动, 因此又被称为滑动窗口协议</li><li>由于回退 N 帧的特性, 通信线路质量不好时, 信道利用率不必 SW 协议高</li></ul><h3 id="选择重传协议-SR-Selective-Request"><a href="#选择重传协议-SR-Selective-Request" class="headerlink" title="选择重传协议 SR(Selective Request)"></a>选择重传协议 SR(Selective Request)</h3><h4 id="与-GBN-相比"><a href="#与-GBN-相比" class="headerlink" title="与 GBN 相比"></a>与 GBN 相比</h4><ul><li><p>GBN 一个数据分组误码会导致其后续的多个数据分组被丢弃, 尽管它们可能没有乱序和误码</p></li><li><p>SR 的接收窗口尺寸 $W_R$ 不再是 1, 以便接收<strong>失序到达但无误码并且序号落在接收窗口内的数据分组</strong>, 等到所缺分组收齐后再一并送交上层</p></li><li>选择重传协议不能使用累计确认, 因为不是按照组好顺序顺序接收的</li></ul><h4 id="发送方-1"><a href="#发送方-1" class="headerlink" title="发送方"></a>发送方</h4><ul><li>发送窗口尺寸: $1&lt;W_T\leq2^{n-1}$<ul><li>$W_T=1$ 与停止等待协议相同</li><li>$W_T&gt;2^{n-1}$  接收方无法辨认新旧分组(比如接收方确认分组丢失了, 发送方重传)</li></ul></li><li>发送方可以在未收到接收方确认分组的情况下, 将序号落在发送窗口中的多个数据分组全部发送出去</li><li>发送方按序收到确认分组时, 发送窗口前移; 若收到未按序到达的确认分组, 对其记录防止超时重发, 发送窗口不移动</li></ul><h4 id="接收方-1"><a href="#接收方-1" class="headerlink" title="接收方"></a>接收方</h4><ul><li>接收窗口尺寸:$1&lt;W_R\leq W_T$<ul><li>$W_R&gt;W_T$ 无意义</li></ul></li><li>接收方可以接收未按序到达但没有误码且序号落在接收窗口的数据分组<ul><li>为了使得发送方仅重传出现差错的分组, 接收方不使用累积确认</li></ul></li><li>接收方在按序接收数据分组后, 接收窗口才能滑动</li></ul><h2 id="点对点协议-PPP-Point-to-Point-Protocol"><a href="#点对点协议-PPP-Point-to-Point-Protocol" class="headerlink" title="点对点协议 PPP(Point-to-Point Protocol)"></a>点对点协议 PPP(Point-to-Point Protocol)</h2><ul><li><p>目前使用最广泛的点对点数据链路层协议</p><ul><li>用户计算机与 ISP 进行通信时, 数据链路层的协议就是 PPP 协议</li><li>广泛应用于广域路由器之间的专用线路</li></ul></li><li><p>PPP 协议在点对点链路传输各种协议数据报提供了标准方法</p><ul><li><p>对各种协议数据报的封装方法 (封装成帧)</p></li><li><p>链路控制协议 LCP: 用于建立, 配置以及测试数据链路的连接</p></li><li><p>一套网络控制协议 NCPs: 其中的每一个协议支持不同的网络层协议</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/YhyrdUvcaAWKqeP.webp" alt="image-20210331180316142"></p></li></ul></li></ul><h3 id="PPP-协议帧格式"><a href="#PPP-协议帧格式" class="headerlink" title="PPP 协议帧格式"></a>PPP 协议帧格式</h3><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/RLadPZKn25TyJpI.webp" alt="image-20210331180439408"></p><ul><li>标志 ( Flag ) 字段: PPP 帧的定界符, 取值为 0x7E</li><li>地址 ( Address ) 字段: 取值为 0xFF, 目前无作用</li><li>控制 ( Control ) 字段: 取值为 0x03, 目前无作用</li><li>协议 ( Protocol )  字段: 指明帧的数据部分分别送交哪个协议处理<ul><li>取值为 0x0021: IP数据报</li><li>取值为 0xC021: LCP 分组</li><li>取值为 0x8021: NCP 分组</li></ul></li><li>帧检验序列 ( Frame Check Sequence ) 字段: CRC 校验位</li></ul><h3 id="透明传输"><a href="#透明传输" class="headerlink" title="透明传输"></a>透明传输</h3><h4 id="面向字节的异步链路采用插入转义字符的字节填充法"><a href="#面向字节的异步链路采用插入转义字符的字节填充法" class="headerlink" title="面向字节的异步链路采用插入转义字符的字节填充法"></a>面向字节的异步链路采用插入转义字符的字节填充法</h4><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/2qA6DMf5Xyhb1iW.webp" alt="image-20210401022143072"></p><p>发送方的处理:</p><ul><li>每出现一个<font color=#2796c3><b>7E</b></font> (PPP 帧的定界符) , 在前面插入转义字符 <b><font color=#e66d81>7D</font></b>并减去 0x20, 变成 <b><font color=#e66d81>7D</font></b> <b><font color=#00835d>5E</font></b></li><li>每出现一个<font color=#e66d81><b>7D</b></font> (转义字符), 在前面插入 <b><font color=#e66d81>7D</font></b> , 并减去 0x20, 变成 <b><font color=#e66d81>7D</font></b> <b><font color=#846f9e>5D</font></b></li><li>每出现一个 ASCII 码控制字符 (小于 0x20 的字符), 在前面插入<b><font color=#e66d81>7D</font></b>, 并给该字符编码加上 0x20</li></ul><p>接收方只要进行反变化即可恢复原来的帧的数据部分</p><h4 id="面向比特的同步链路采用插入比特-0-的比特填充法"><a href="#面向比特的同步链路采用插入比特-0-的比特填充法" class="headerlink" title="面向比特的同步链路采用插入比特 0 的比特填充法"></a>面向比特的同步链路采用插入比特 0 的比特填充法</h4><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/W3tsgGKCUOcaloN.webp" alt="image-20210401022334347"></p><p>发送方的处理:</p><ul><li>对帧的数据部分进行扫描, 每发现 5 个连续的比特 1, 立即填充 1 个比特 0</li></ul><p>接收方的处理:</p><ul><li>反过来</li></ul><h3 id="差错检测-1"><a href="#差错检测-1" class="headerlink" title="差错检测"></a>差错检测</h3><p>生成多项式</p><script type="math/tex; mode=display">X^{16}+X^{12}+X^{5}+1</script><h3 id="工作状态"><a href="#工作状态" class="headerlink" title="工作状态"></a>工作状态</h3><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/w5L2GExlRsSuCIH.webp" alt="image-20210401022643084"></p><h2 id="媒体接入控制-Medium-Access-Control-MAC"><a href="#媒体接入控制-Medium-Access-Control-MAC" class="headerlink" title="媒体接入控制 (Medium Access Control, MAC)"></a>媒体接入控制 (Medium Access Control, MAC)</h2><h3 id="基本概念-1"><a href="#基本概念-1" class="headerlink" title="基本概念"></a>基本概念</h3><ul><li><p>共享信道着重考虑的问题: 协调多个发送和接受站点对一个共享传输媒体的占用, 即 MAC</p></li><li><p>分类</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/yxC4bRdM2aeArlZ.webp" alt="image-20210405212513816"></p></li><li><p>点对点链路和链路层交换机的交换式局域网在有限领域已经取代了共享式局域网, 无线局域网仍然使用共享媒体技术</p></li></ul><h3 id="静态划分信道"><a href="#静态划分信道" class="headerlink" title="静态划分信道"></a>静态划分信道</h3><ul><li>复用 (Multiplexing) :一条物理线路同时传输多路用户的信号</li><li>用复用技术可以在一条物理线路上建立多条通信信道来充分利用传输媒体的带宽</li></ul><h4 id="频分复用-Frequency-Division-Multiplexing-FDM"><a href="#频分复用-Frequency-Division-Multiplexing-FDM" class="headerlink" title="频分复用 (Frequency Division Multiplexing, FDM)"></a>频分复用 (Frequency Division Multiplexing, FDM)</h4><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/oMrAHWEDL9BSipO.webp" alt="image-20210405213738842"></p><ul><li>传输线路频带资源划分为多个子频带, 形成多个子信道, 之间有隔离频带, 以免干扰</li><li>复用器将每一路信号调整到不同频率的载波上, 接收端通过分用器将各路信号分开, 恢复原信号</li><li><strong>频分复用所有用户同时占用不同的频带资源并行通信</strong></li></ul><h4 id="时分复用-Time-Division-Multiplexing-TDM"><a href="#时分复用-Time-Division-Multiplexing-TDM" class="headerlink" title="时分复用 (Time Division Multiplexing, TDM)"></a>时分复用 (Time Division Multiplexing, TDM)</h4><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/TlkQAixvceo4L5U.webp" alt="image-20210405214602803"></p><ul><li>TDM 将带宽资源按时隙轮流分配给不同的用户, 每对用户只在分配的时隙里使用线路传输数据</li><li>TDM 将时间划分为等长的 TDM 帧, 每个 TDM 用户在每一帧中占用的时隙的序号是固定的, 周期即 TDM 帧的长度</li><li><strong>时分复用的所有用户在不同的时间占用同样的频带宽度</strong></li></ul><h4 id="波分复用-Wavelength-Division-Multiplexing-WDM"><a href="#波分复用-Wavelength-Division-Multiplexing-WDM" class="headerlink" title="波分复用 (Wavelength Division Multiplexing, WDM)"></a>波分复用 (Wavelength Division Multiplexing, WDM)</h4><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/3q1w7mnletyRfJi.webp" alt="image-20210405215111468"></p><h4 id="码分复用-Code-Division-Multiplexing-CDM"><a href="#码分复用-Code-Division-Multiplexing-CDM" class="headerlink" title="码分复用 (Code Division Multiplexing,CDM)"></a>码分复用 (Code Division Multiplexing,CDM)</h4><ul><li><p>CDM 是一种共享信道的方法, 多用于多址接入, 更常用的名词是码分多址 (Code Division Multiple Access, CDMA)</p></li><li><p>FDM 和 TDM 同样可以用于多址接入</p></li><li><p>复用和多址</p><ul><li>复用: 单一媒体频带资源划分为多个相互独立, 互不干扰的子信道. 每个子信道只占用媒体频带资源的一部分</li><li>多址 (多点接入) 处理将信道动态分配给用户, 用户暂时占用信道的应用必须,信道永久性分配给用户的应用则不需要</li><li>FDMA, TDMA, CDMA 可分别看作 FDM, TDM, CDMA 的应用</li></ul></li><li><p>CDM 的每一个用户可以<strong>在同样的时间内使用同样的频带进行通信</strong></p></li><li><p>各个用户使用经过特殊挑选的不同码型, 不会造成干扰</p></li><li><p>CDMA 中每一个比特时间被分为 m 个短间隔, 称为<strong>码片(Chip)</strong> 通常是 64 或 128</p></li><li><p>使用CDMA 的每一个站点被指派唯一的 m 位<strong>码片序列</strong> (Chip Sequence)</p><ul><li>一个站点若要<strong>发送比特1</strong>, 则<strong>发送自身的 m 位码片序列</strong></li><li>若要<strong>发送比特0</strong>, 则发送<strong>发送自身的 m 位码片序列的二进制反码</strong></li></ul><p>举个例子: 某站点码片序列为 00011011, 则发送比特1: 发送00011011, 发送比特 0: 11100100.</p><p>按惯例将码片序列中的 0 写为 -1, 1 写为 +1, 则该站点码片序列为: (-1, -1, -1, +1, +1, -1, +1, +1)</p></li><li><p>码片序列挑选原则</p><ul><li>每个站点的<strong>码片序列必须各不相同</strong>, 常采用伪随机码序列</li><li>每个站点的<strong>码片序列必须互相正交</strong>, 即规格化内积为 0 ($S\cdot T=\displaystyle \frac 1 m \sum_{i=1}^{m}S_i T_i=0$)</li></ul></li><li><p>要判断某个站点发送信号的情况, 只需要将叠加信号和该站点码片序列做规格化内积, 为 1 则发x送 1,为 -1 则发送 0, 为 0 则未发送</p></li></ul><h3 id="动态接入控制"><a href="#动态接入控制" class="headerlink" title="动态接入控制"></a>动态接入控制</h3><h4 id="随机接入-Random-Access"><a href="#随机接入-Random-Access" class="headerlink" title="随机接入 (Random Access)"></a>随机接入 (Random Access)</h4><h5 id="载波监听多址接入-碰撞-检测-Carrier-Sense-Multiple-Access-Collision-Detection-CSMA-CD"><a href="#载波监听多址接入-碰撞-检测-Carrier-Sense-Multiple-Access-Collision-Detection-CSMA-CD" class="headerlink" title="载波监听多址接入/碰撞 检测 (Carrier Sense Multiple Access/Collision Detection,CSMA/CD)"></a>载波监听多址接入/碰撞 检测 (Carrier Sense Multiple Access/Collision Detection,CSMA/CD)</h5><ul><li><p>多址接入 MA</p><ul><li>多个站点连接在一条总线,竞争使用总线</li></ul></li><li><p>载波监听 CS</p><ul><li>每个站点发送帧之前检测一下总线上是否有其他站点再发送帧<ul><li>检测到总线空闲 96 比特时间后, 则发送帧, 96 bit 是<strong>帧间最小间隔</strong>, 使接收方可以检测出一个帧的结束, 也使得其他站点公平竞争信道</li><li>若总线忙, 继续检测并等待</li></ul></li></ul></li><li><p>碰撞检测 CD</p><ul><li>每一个正在发送帧的站点边发送帧边检测碰撞<ul><li>一旦碰撞, 立即停止, 退避一段时间后择机发送</li></ul></li><li>以太网有<strong>强化碰撞</strong>机制, 即一旦发生碰撞, 立即停止发送帧, 并发送 32 bit 或者 48 bit 的人为干扰信号 (Jamming Signal), 使<strong>足够多的站点检测出碰撞</strong></li></ul></li><li><p>争用期 (碰撞窗口)</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/3NQUYvmDkjdics4.webp" alt="image-20210406012322027"></p><ul><li>最多经过 2τ 时间可知本次发送是否遭遇碰撞, 以太网端到端往返传播时延 2τ 就称为<strong>争用期</strong>或者<strong>碰撞窗口</strong></li><li>争用期内未检测到碰撞, 这次发送必定无碰撞</li><li>主机越多, 端到端往返时延越大, 碰撞几率越高. 共享式连接主机数量有限, 总线长度也不能太长</li></ul></li><li><p>最小帧长</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/yKPBuYp92VCzNn7.webp" alt="image-20210406012951665"></p><ul><li>由于是边检测边发送, 若帧长过短, 传输过程中遭遇碰撞发送方不会重发</li><li><strong>以太网规定最小帧长为 64 字节</strong>(512 bit 时间即争用期)<ul><li>若发送数据少, 需要填充字节</li></ul></li><li>最小帧长保证主机可以在帧发送完毕前确定是否发生碰撞<ul><li>若在争用期未检测到碰撞, 则后续的数据一定不会发生碰撞</li><li>若在争用期检测到碰撞, 立即终止发送. 此时发送出去的帧长度一定小于 512 bit. <strong>规定长度小于 64 byte 的帧都是碰撞引起的无效帧</strong></li></ul></li></ul></li><li><p>最大帧长</p><ul><li>过长的帧会长时间占用总线</li><li>过长的帧可能会导致接收方缓冲区溢出</li></ul><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/9CuxVtrdA5vGPEa.webp" alt="image-20210406111406066"></p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/76MSkzE3swgFRyB.webp" alt="image-20210406111428736"></p></li><li><p>截断二进制指数退避算法</p><ul><li><p>退避时间 = 基本退避时间( 争用期 2τ ) × 随机数 r (r ∈ {0, 1, …2<sup>k</sup>-1}, k=min{重传次数, 10})</p></li><li><p>举例:</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/yUTrdipqYlbDWz2.webp" alt="image-20210406112334657"></p></li><li><p>该算法可以使<strong>重传需要推迟的时间随重传次数而增大, 减小发生碰撞概率</strong></p></li><li><p>重传 16 次仍然失败, <strong>丢弃该帧</strong>, 向上层报告</p></li></ul></li><li><p>信道利用率</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/1SysPeW9btqckl6.webp" alt="image-20210406112753960"></p><ul><li><p>理想情况</p><ul><li><p>各个主机发送的帧无碰撞</p></li><li><p>总线一旦空闲, 某主机立即发送帧</p></li><li><p>发送一帧占用总线 τ<sub>0</sub>+τ, 帧本身发送时间为 τ<sub>0</sub></p><ul><li>极限信道利用率 $\displaystyle S_{max}=\frac {\tau_0}{\tau_o+\tau}=\frac{1}{1+\frac{\tau}{\tau_0}}$ </li><li>提高利用率, 以太网端到端距离受到限制, 以太网帧长度应尽量长</li></ul></li></ul></li></ul></li></ul><ul><li><p>帧发送流程</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/nym87fjiQkSNqDd.webp" alt="image-20210406114359176"></p></li></ul><ul><li><p>帧接收流程</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/w6a1ilEvbGX8cpF.webp" alt="image-20210406114432089"></p></li><li><p>发展</p><ul><li>CSMA/CD 协议曾用于各种总线结构以太网和双绞线以太网早期版本</li><li>现在以太网基于交换机和全双工连接, 没有碰撞, 因此没有必要使用 CSMA/CD 协议</li></ul></li></ul><h5 id="载波监听多址接入-碰撞避免-Carrier-Sense-Multiple-Access-Collision-Avoidance-CSMA-CA"><a href="#载波监听多址接入-碰撞避免-Carrier-Sense-Multiple-Access-Collision-Avoidance-CSMA-CA" class="headerlink" title="载波监听多址接入/碰撞避免 (Carrier Sense Multiple Access/Collision Avoidance,CSMA/CA)"></a>载波监听多址接入/碰撞避免 (Carrier Sense Multiple Access/Collision Avoidance,CSMA/CA)</h5><ul><li><p>无线局域网不能使用<strong>碰撞检测 CD</strong></p><ul><li><p>无线信道传输条件特殊, 信号强度动态范围大, 实现 CD 对硬件要求过高</p></li><li><p>存在隐蔽站问题</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络.assets/vKXWekbOYacLw9z.webp" alt="image-20210406132445066"></p></li></ul></li><li><p><strong>802.11无线局域网</strong>使用 CSMA/CA 协议，在 CSMA 的基础上增加了一个<strong>碰撞避免 CA 功能</strong>, 而不再实现碰撞检测功能</p></li><li><p>由于不可能避免所有的碰撞，并且<strong>无线信道误码率较高</strong>, 802.11 标准还使用了<strong>数据链路层确认机制(停止-等待协议)</strong>来保证数据被正确接收</p></li><li><p>802.11 的 MAC 层标准定义了两种不同的媒体接入控制方式:</p><ul><li>分布式协调功能 DCF (Distributed Coordination Function). 在 DCF 方式下，没有中心控制站点, 每个站点使用 CSMA/CA 协议通过争用信道来获取发送权, 这是 802.11 定义的默认方式</li><li>点协调功能 PCF (Point Coordination Function)。PCF 方式使用集中控制的接入算法(一般在接入点 AP 实现集中控制)，是 802.11 定义的可选方式，在实际中较少使用</li></ul></li><li><p>帧间间隔 IFS  (Inter Frame Space)</p><ul><li>802.11 标准规定，所有的站点必须在持续检测到信道空闲一段指定时间后才能发送帧，这段时间称为帧间间隔 IFS。</li><li>帧间间隔长短取决于发送帧类型: <ul><li>高优先级帧需要等待的时间较短，因此可优先获得发送权</li><li>低优先级帧需要等待的时间较长。若某个站的低优先级帧还没来得及发送，而其他站的高优先级帧已发送到信道上，则信道变为忙态，因而低优先级帧就只能再推迟发送了。这样就减少了发生碰撞的机会。</li></ul></li><li>常用的两种帧间间隔:<ul><li><strong>短帧间间隔 SIFS</strong> (28μs) , 是最短的帧间间隔，用来<strong>分隔开属于一次对话的各帧。一个站点应当能够在这段时间内从发送方式切换到接收方式</strong>。使用 SIFS 的帧类型有 ACK 帧、CTS 帧、 由过长的 MAC 帧分片后的数据帧、以及所有回答 AP 探询的帧和在 PCF 方式中接入点 AP 发送出的任何帧</li><li><strong>DCF 帧间间隔 DIFS</strong> (128 μs) 发送数据帧和管理帧</li></ul></li></ul></li><li><p>工作原理 </p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210516161113168.webp" alt="image-20210516161113168"></p><ul><li>源站为什么在检测到信道空闲后还要等待一段时间 DIFS?</li></ul><div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案    </button><div class="hide-content">  <div class="note green no-icon flat"><p>考虑到其他的站点有高优先级帧要发送, 若有, 让高优先级帧先发送</p></div></div></div><ul><li><p>目的站为什么正确接收数据帧后还要等待一段时间 SIFS 才能发送 ACK 帧?</p><div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案    </button><div class="hide-content"><pre><code>&lt;div class=&quot;note green no-icon flat&quot;&gt;&lt;p&gt;短帧间间隔 SIFS , 是最短的帧间间隔，一个站点应当能够在这段时间内从发送方式切换到接收方式&lt;/p&gt;</code></pre><p>&lt;/div&gt;</p></div></div></li><li><p>使用退避算法的时机?</p></li></ul><div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看答案    </button><div class="hide-content">  <div class="note green no-icon flat"><ol><li><p>发送数据帧之前检测到信道忙  </p></li><li><p>每次重传数据帧</p></li><li><p>每次成功发送后要连续发送下一个帧时(避免一个站点长时间占用信道)</p></li></ol></div></div></div></li></ul><ul><li><p>CSMA/CA 协议的退避算法</p><ul><li>执行退避算法时, 站点为退避计时器设置一个随机的退避时间<ul><li>退避计时器时间减为 0, 开始发送数据</li><li>退避计时器尚未减少到 0, 信道又转变为忙状态, 则冻结退避计时器的数值, 待信道空闲并经过 DIFS 时间后继续启动退避计时器</li></ul></li><li>在进行第 i 次退避时, 退避时间在时隙编号 {0, 1, …, 2<sup>2+i</sup> -1} 中随机选择一个, 然后乘以基本退避时间(一个时隙的长度), 就可以得到随机的退避时间. 时隙编号达到 255 (第 6 次退避) 就不再增加</li></ul><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210516165126475.webp" alt="image-20210516165126475"></p></li><li><p><strong>CSMA/CA 协议的信道预约和虚拟载波监听</strong></p><ul><li>为了<strong>减少碰撞概率和降低碰撞的影响</strong>, 802.11 标准允许要发送数据的站点<strong>对信道进行预约</strong>.<ol><li>源站在发送数据帧之前先发送一个短的控制帧, 称为 <font color="purple"><strong>请求发送 RTS (Request To Send)</strong></font> , 包含源地址, 目的地址以及这次通信(包括相应的确认帧)所需要的持续时间</li><li>若目的站正确收到 RTS 帧, 且媒体空闲, 就发一个响应控制帧, 称为<font color="green"><strong>允许发送 CTS (Clear To Send)</strong></font> , 包含此次通信所需要的持续时间</li><li>源站收到 CTS 帧后, 在等待一段时间 SIFS 后, 就可以发送数据帧</li><li>目的站正确接收数据帧后, 等待 SIFS 后发送确认帧 ACK</li></ol></li><li>除了目的站和源站, 在收到 CTS 帧 (或者数据帧) 后,  就推迟接入到无线局域网中, 保证源站和目的站之间通信不受干扰</li><li>若 RTS 帧发生碰撞, 源站就收不到 CTS 帧, 需要执行退避算法重传 RTS 帧</li><li>由于 <strong>RTS帧 和 CTS 帧很短，发送碰撞的概率、碰撞产生的开销及本身的开销都很小</strong>。而对于一般的数据帧，其发送时延往往大于传播时延(因为是局域网) .碰撞的概率很大, 且一旦发生碰撞而导致数据帧重发, 则浪费的时间就很多, 因此用很小的代价对信道进行预约往往是值得的. 802.11 标准规定了 3 种情况供用户选择:<ul><li>使用 RTS 和 CTS</li><li>不使用 RTS 和 CTS</li><li>当数据帧长度超过某一数值才使用 RTS 和 CTS 帧</li></ul></li><li>除了 RTS 帧和 CTS 帧携带通信所需要的时间, 数据帧也能携带通信所需要的时间, 这称为 802.11 的<strong>虚拟载波监听</strong>机制<ul><li>借助这个机制, 站点只需要监听到 RTS, CTS 或者数据帧中的一个, 就可以知道信道被占用的时间, 进而<strong>减少隐蔽站问题带来的碰撞问题</strong></li></ul></li></ul></li></ul><ul><li><p>本节测试题</p><ol><li><p>【2011 年题 36】下列选项中，对正确接收到的数据帧进行确认的 MAC 协议是 <span class="hide-inline"><button type="button" class="hide-button button--animated" style=""> 查看答案  </button><span class="hide-content">D</span></span></p><p>A. CSMA                B. CDMA                C. CSMA/CD                D. CSMA/CA</p><div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看解析    </button><div class="hide-content"><div class="note green no-icon flat"><p>CDMA 码分多址, 静态划分信道, 是物理层的信道复用技术, 不属于 MAC 协议.CSMA/CA 使用停止等待协议, 有确认机制</p></div></div></div></li><li><p>【2013 年题 36】下列介质访问控制方法中，可能发生冲突的是 <span class="hide-inline"><button type="button" class="hide-button button--animated" style=""> 查看答案  </button><span class="hide-content">B</span></span></p><p>A. CDMA                B. CSMA                C. TDMA                D. FDMA</p></li></ol></li></ul><h2 id="MAC-地址，IP-地址以及-ARP-协议"><a href="#MAC-地址，IP-地址以及-ARP-协议" class="headerlink" title="MAC 地址，IP 地址以及 ARP 协议"></a>MAC 地址，IP 地址以及 ARP 协议</h2><div class="note info no-icon modern"><p><p style="display:block"><strong>数据链路层</strong></p>MAC 地址是以太网的 MAC 子层所使用的地址</p></div><div class="note primary no-icon modern"><p><p style="display:block" ><strong>网际层</strong></p>IP 地址是 TCP/IP 体系结构网际层所使用的地址</p><p>ARP 协议数与 TCP/IP 体系结构的网际层, 七作用是已知设备分配到的 IP 地址, 使用 ARP 协议可以通过 IP 协议获取到设备的 MAC 地址</p></div><h3 id="MAC-地址"><a href="#MAC-地址" class="headerlink" title="MAC 地址"></a>MAC 地址</h3><ul><li>使用点对点信道的数据链路层不需要使用地址</li><li>使用广播信道的数据链路层必须使用地址区分各主机</li><li><p>每个主机发送的帧中 <span style="color: skyblue;font-weight:bold">  必须携带标识发送主机和接收主机的地址 </span>, 这类地址用于媒体接入控制 ( MAC )的, 因此被称为 <span style="color: skyblue;font-weight:bold"> MAC 地址</span></p><ul><li>MAC 地址一半固化在网卡的 EEPROM 中, 因此 MAC 地址也被称为<span style="color: skyblue;font-weight:bold"> 硬件地址</span></li><li>有时候也被称为<span style="color: skyblue;font-weight:bold"> 物理地址</span></li></ul></li><li><p>每个网络适配器拥有一个全球唯一的 MAC地址, 用户主机一半包括有线网卡与无向网卡两个网络适配器. <span style="color: red;font-weight:bold"> 严格来说 MAC 地址是对网络上各接口的唯一标识, 而不是各设备</span></p></li></ul><h4 id="MAC-地址格式"><a href="#MAC-地址格式" class="headerlink" title="MAC 地址格式"></a>MAC 地址格式</h4><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210518013131455.webp" alt="image-20210518013131455"></p><ul><li><p>表示方法</p><ul><li>Windows: <code>00-0C-CF-93-8C-92</code></li><li>Linux: <code>00:0C:CF:93:8C:92</code></li></ul></li><li><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210518015424065.webp" alt="image-20210518015424065"></p></li><li><p>发送顺序</p><ul><li><p>字节发送顺序: <span style="color: #856fa7;font-weight:bold">  第一字节</span>到<span style="color: #219cd5;font-weight:bold">第六字节</span></p></li><li><p>字节内发送顺序: $b_0$ 到 $b_7$</p></li></ul></li></ul><h4 id="MAC-地址举例"><a href="#MAC-地址举例" class="headerlink" title="MAC 地址举例"></a>MAC 地址举例</h4><ul><li>单播</li></ul><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210518015927302.webp" alt="image-20210518015927302"></p><ul><li>广播</li></ul><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210518020027364.webp" alt="image-20210518020027364"></p><ul><li><p>多播</p><p><img src="http://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210518020544871.webp" alt="image-20210518020544871"></p><ul><li>B, C, D 主机都会收到该多播帧</li><li>若该多播帧的目的 MAC 地址在自己的多播列表, 接受并上交上层, 否则丢弃</li></ul></li></ul><h4 id="IP-地址"><a href="#IP-地址" class="headerlink" title="IP 地址"></a>IP 地址</h4><div class="note warning flat"><p>IP 地址的内容实际上属于<span style="color:red;font-weight:bold;">网络层</span> , 因为在日常生活中, 大多数网络应用 MAC 地址和 IP 地址都在使用, 以下主要介绍 IP 地址的作用</p></div><ul><li><p>IP 地址是因特网上的主机和路由器所使用的地址, 用于标识两部分信息</p><ul><li><p><span style="color:red;font-weight:bold;">网络编号: </span> 标识因特网上数意百万计的网络</p></li><li><p><span style="color:blue;font-weight:bold;">主机编号:   </span>  标识同一网络上的不同主机以及路由器各个接口</p></li></ul></li><li><p>MAC 地址不具备区分不同网络的功能</p><ul><li>单独网络不介入因特网, 可以只使用 MAC 地址</li><li>如果需要接入因特网, IP 地址和 MAC 地址都需要使用</li></ul></li><li><p>数据包转发过程中 IP 地址和 MAC 地址变化情况</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210518114548659.webp" alt="image-20210518114548659"></p><ul><li><span class='p  span red bold'> 源 IP 地址和目的 IP 地址不变</span></li><li><span class='p  span bold'>源 MAC 地址和目的 MAC 地址逐链路(网络)改变</span></li></ul></li></ul><div class="note info flat"><p>主机和路由器发送数据包的时候都有一个问题: 知道 IP 地址 (网络层中详解), 但是不知道 MAC 地址, 如何通过 IP 地址找到 MAC 地址这就需要 ARP 协议</p></div><h4 id="ARP-Address-Resolution-Protocol-协议"><a href="#ARP-Address-Resolution-Protocol-协议" class="headerlink" title="ARP (Address Resolution Protocol) 协议"></a>ARP (Address Resolution Protocol) 协议</h4><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519025248915.webp" alt="image-20210519025248915"></p><ul><li><p>每台主机都有一个 ARP 高速缓存表, 记录 IP 地址和 MAC 地址的对应关系, 例如</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519025437186.webp" alt="image-20210519025437186"></p><p>每次发送 MAC 帧的时候, 首先在自己的 ARP 高速缓存表中查找, 若未找到, 则发送 ARP 请求报文</p></li><li><span class='p purple bold'>ARP 请求报文(广播)</span><ul><li><p>封装在 MAC 帧中</p></li><li><p>目的地址 FF-FF-FF-FF-FF-FF</p></li><li><p>内容 (大致)</p><ul><li>我的 IP 地址为: 192.168.0.2</li><li>我的 MAC 地址为 00-E0-F9-A3-43-77</li><li>我想知道 IP 地址为 192.168.0.3 的主机的 MAC 地址</li></ul></li><li><p>各主机收到 ARP 请求报文后, 上交给上层处理, 若 IP 地址相符</p><ul><li><span class='p blue bold'>将 B 的 IP 地址和 MAC 地址记录到自己的 ARP 高速缓存表中</span></li><li>给源主机发送 ARP 响应, 以告知自己的 MAC 地址</li></ul></li></ul></li></ul><ul><li><span class='p blue bold'>ARP 响应报文(单播)</span><ul><li><p>内容</p><ul><li>我的 IP 地址是: 192.168.0.3</li><li>我的 MAC 地址是: 00_0C-CF-B8-4A-82</li></ul></li><li><p>总线上的各个主机都能收到该单播帧, 若网卡的 MAC 地址与响应报文不匹配, 直接丢弃; 否则<span class='p blue bold'>交付给上层处理</span></p></li></ul></li></ul><ul><li>ARP 缓存表中的记录有两种类型<ul><li>动态: 自动获取, 生命周期默认 2 分钟</li><li>静态: 手动配置, 不同操作系统生命周期不一样</li></ul></li><li>ARP 协议没有安全验证机制, 存在 ARP 欺骗, 攻击等问题</li></ul><p>问题: 下图中主机 H1 是否可以使用 ARP 协议获取到主机 H2 的 MAC 地址?<span class="hide-inline"><button type="button" class="hide-button button--animated" style=""> 查看答案  </button><span class="hide-content">不可以</span></span></p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519031245563.webp" alt="image-20210519031245563"></p><div class="hide-block"><button type="button" class="hide-button button--animated" style="">查看解析    </button><div class="hide-content"><div class="note success flat"><p><span class='p bold'>ARP 协议只能在一段链路或者一个网络上使用</span>, 对于本例, ARP 协议是逐链路进行的</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519031650334.webp" alt="image-20210519031650334"></p></div></div></div><h2 id="集线器和交换机"><a href="#集线器和交换机" class="headerlink" title="集线器和交换机"></a>集线器和交换机</h2><h3 id="早期总线型以太网"><a href="#早期总线型以太网" class="headerlink" title="早期总线型以太网"></a>早期总线型以太网</h3><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519093958762.png" alt="image-20210519093958762"></p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519094124554.png" alt="image-20210519094124554"></p><p>使用大量机械接头的总线型以太网没有人们想象的可靠, 被淘汰</p><h3 id="使用双绞线和集线器-HUB-的星型以太网"><a href="#使用双绞线和集线器-HUB-的星型以太网" class="headerlink" title="使用双绞线和集线器 HUB 的星型以太网"></a>使用双绞线和集线器 HUB 的星型以太网</h3><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519094230979.png" alt="image-20210519094230979"></p><p>集线器使用大规模集成电路, 可靠性更高, 并且使用更便宜更灵活的双绞线作为传输媒体.</p><ul><li><span class='p red bold'>使用集线器的以太网在逻辑上仍然是一个总线网</span>, 各站共享资源, <span class='p red bold'>使用的还是 CSMA/CD 协议</span></li><li><span class='p red bold'>集线器只工作在物理层</span>, 网络中某个网卡出了故障, 不停地发送帧, 集线器可以断开这个故障网卡的连线<h3 id="使用集线器-HUB-在物理层扩展以太网"><a href="#使用集线器-HUB-在物理层扩展以太网" class="headerlink" title="使用集线器 HUB 在物理层扩展以太网"></a>使用集线器 HUB 在物理层扩展以太网</h3></li></ul><p>集线器可以将各个小型以太网互连形成一个更大的以太网, 同时合并成一个更大的碰撞域. 一台主机发送的数据帧的信号会传输到整个网络中的其他各主机.</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519112517692.png" alt="image-20210519112517692"></p><h3 id="以太网交换机"><a href="#以太网交换机" class="headerlink" title="以太网交换机"></a>以太网交换机</h3><div class="note warning flat"><ul><li>以下内容忽略了 ARP 过程</li><li>假设交换机的帧交换表已经配置好</li></ul></div><h4 id="对比"><a href="#对比" class="headerlink" title="对比"></a>对比</h4><p> <img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519112646707.png" alt="image-20210519112646707"></p><ul><li><p>发送单播帧</p><ul><li>一台主机通过集线器向另一主机发送单播帧, 这个单播帧会沿着共享总线传输到总线上的其他各个主机</li><li>而单播帧进入交换机后, 交换机会将该单播帧转发给目的主机, 而非网络中其他各个主机</li></ul></li><li><p>发送广播帧</p><ul><li>从效果上看无差别, 使用交换机的交换式以太网中的各主机属于同一个广播域, 使用集线器的共享式以太网中的各主机也属于同一个广播域</li></ul></li><li><p>同时向一台主机发送单播帧</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519121156306.png" alt="image-20210519121156306"><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519121253754.png" alt="image-20210519121253754"></p><ul><li>集线器: 遭遇碰撞的帧传播到总线上的各主机</li><li>交换机: 收到多个帧会将它们缓存起来, 然后逐个转发给目的主机</li></ul></li><li><p>扩展以太网</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519122751786.png" alt="image-20210519122751786"></p><p>交换机和集线器均可以扩大广播域, 但是集线器会同时扩大冲突域, 增加了竞争总线的主机; 交换机不会扩大碰撞域 (VLAN 除外)</p></li></ul><h4 id="交换机简介"><a href="#交换机简介" class="headerlink" title="交换机简介"></a>交换机简介</h4><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210519114854924.png" alt="image-20210519114854924"></p><ul><li>以太网交换机有<span class='p red bold'>多个接口</span>. 每个接口与另一台交换机或者主机连接. 一般工作在<span class='p red bold'>全双工方式</span> (发送与接收同时进行). 交换机工作在半双工方式</li><li>以太网交换机具有并行性, <span class='p red bold'>同时连通多对接口</span>, 使多对主机同时通信, <span class='p red bold'>无碰撞 (无需使用 CSMA/CD 协议)</span></li><li>以太网交换机一般具有多种速率的接口, 例如 10 Mbps, 100 Mbps, 1Gbps, 10Gbps 接口的多种组合</li><li>以太网交换机工作在 <span class='p red bold'>数据链路层</span> (也包括物理层), 收到帧后, 在帧交换表中查找 <span class='p red bold'>帧的 MAC 地址所对应的接口号</span>, 然后通过该接口转发帧.</li><li>以太网交换机是一种即插即用设备, <span class='p red bold'>帧交换表是通过自学习算法建立起来的</span></li><li>帧的两种转发方式:<ol><li><span class='p red bold'>存储转发:</span>延时大，速度慢，可靠性高，可检错纠错</li><li><span class='p red bold'>直通交换:</span> 交换时延小, 不检测差错</li></ol></li></ul><h2 id="以太网交换机自学习和转发帧的流程"><a href="#以太网交换机自学习和转发帧的流程" class="headerlink" title="以太网交换机自学习和转发帧的流程"></a>以太网交换机自学习和转发帧的流程</h2><div class="note info flat"><p>假设各主机知道网络中的其他各主机的 MAC 地址 无需进行 ARP </p></div><h3 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h3><p><img src="计算机网络_03.assets/image-20210524150612456.png" alt="image-20210524150612456"></p><ul><li><p>当 MAC 帧通过交换机的接口进入交换机后, 首先进行登记工作 (若帧交换表中没有这条记录)</p><ul><li>将该帧的源 MAC 地址记录到自己的帧交换表中</li><li>将该帧进入自己的接口号记录到自己的帧交换表中</li></ul></li><li><p>之后, 交换机对该帧进行转发</p><ul><li>若帧交换表中找到了目的 MAC 地址, 把帧由对应的接口转发出去</li><li>否则对该帧进行盲目转发 (盲目泛洪), 除该帧进入交换机的接口外所有接口转发该帧</li></ul></li><li><p>主机的网卡接收到帧后, 根据帧的目的 MAC 地址判断是否为转发给自己的帧</p><ul><li>若是, 交付给上层处理</li><li>否则丢弃</li></ul></li></ul><h3 id="有效时间"><a href="#有效时间" class="headerlink" title="有效时间"></a>有效时间</h3><p>帧交换表中的每条记录都有<span class='p red bold'>有效时间</span>, 到期自动删除. 这是因为 MAC 地址与接口的对应关系不是永久性的</p><h3 id="本节习题"><a href="#本节习题" class="headerlink" title="本节习题"></a>本节习题</h3><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210524151932630.png" alt="image-20210524151932630"></p><div class="hide-block"><button type="button" class="hide-button button--animated" style="">Click    </button><div class="hide-content"><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210524152055671.png" alt="image-20210524152055671"></p></div></div><p>​    </p><h2 id="以太网交换机的生成树协议-STP-Spanning-Tree-Protocol"><a href="#以太网交换机的生成树协议-STP-Spanning-Tree-Protocol" class="headerlink" title="以太网交换机的生成树协议 STP (Spanning Tree Protocol)"></a>以太网交换机的生成树协议 STP (Spanning Tree Protocol)</h2><h3 id="提高以太网的可靠性"><a href="#提高以太网的可靠性" class="headerlink" title="提高以太网的可靠性"></a>提高以太网的可靠性</h3><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210525093901901.png" alt="image-20210525093901901"></p><ul><li>添加<strong>冗余链路</strong></li><li>冗余链路的负面效应<ul><li><strong>广播风暴</strong>: 大量消耗网络资源, 使得网络无法正常转发其他数据帧</li><li><strong>主机收到重复的广播帧</strong>: 大量消耗主机资源</li><li><strong>交换机的帧交换表震荡 (漂移)</strong></li></ul></li></ul><h3 id="生成树协议-STP"><a href="#生成树协议-STP" class="headerlink" title="生成树协议 STP"></a>生成树协议 STP</h3><ul><li>以太网交换机使用生成树协议可以在增加冗余链路提高网络可靠性的同时又避免网络环路带来的各种问题<ul><li>不论交换机之间采用怎么样的物理连接, 交换机都能<strong>自动计算并构建一个逻辑上没有环路的网络</strong>, 其逻辑拓扑结构必须是树形的(无环路)</li><li>最终生成的树型逻辑结构<strong>确保连通整个网络</strong></li><li>当首次连接交换机, 或者<strong>网络物理拓扑结构发生变化</strong>时(人为改变或故障), 交换机都会进行<strong>生成树的重新计算</strong></li></ul></li></ul><h2 id="虚拟局域网-VLAN"><a href="#虚拟局域网-VLAN" class="headerlink" title="虚拟局域网 VLAN"></a>虚拟局域网 VLAN</h2><div class="note info flat"><ul><li>以太网交换机工作在<strong>数据链路层</strong>(包括物理层)</li><li>使用一个或者多个以太网交换机互连起来的交换式以太网, 其所有站点都属于<strong>同一个广播域</strong></li><li><p>随着交换式以太网规模的扩大, 广播域相应扩大</p></li><li><p>巨大的广播域会带来很多弊端</p><ul><li>广播风暴: 浪费网络资源和各主机的 CPU 资源<ul><li>TCP/ IP 协议栈中的很多协议都会使用广播<ul><li>地址解析协议 ARP</li><li>路由信息协议 RIP</li><li>动态主机配置协议 DHCP</li></ul></li></ul></li><li>难以管理和维护</li><li>潜在安全问题</li></ul></li></ul></div><h3 id="分割广播域"><a href="#分割广播域" class="headerlink" title="分割广播域"></a>分割广播域</h3><ul><li><p>使用路由器可以隔离广播域, 但成本高</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210525112911541.png" alt="image-20210525112911541"></p></li><li><p>虚拟局域网技术 VLAN 应运而生 </p><ul><li>虚拟局域网 VLAN (Virtual Local Area Network) 是一种将局域网内的<strong>设备划分成与物理位置无关的逻辑组的技术吗这些逻辑组具有某些共同的需求</strong></li></ul><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210525113909392.png" alt="image-20210525113909392"></p></li></ul><h3 id="虚拟局域网-VLAN-的实现机制"><a href="#虚拟局域网-VLAN-的实现机制" class="headerlink" title="虚拟局域网 VLAN 的实现机制"></a>虚拟局域网 VLAN 的实现机制</h3><h4 id="IEEE-802-1Q-帧"><a href="#IEEE-802-1Q-帧" class="headerlink" title="IEEE 802.1Q 帧"></a>IEEE 802.1Q 帧</h4><ul><li><p>IEEE 802.1Q 帧对以太网 MAC 帧格式进行了扩展, 插入了 <strong>4 字节的 VLAN 标记</strong></p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210525115314913.png" alt="image-20210525115314913"></p></li><li><p>VLAN 标记的<strong>最后 12 位</strong> 被称为 <strong>VLAN 标识符 VID</strong>, 它唯一地标识了以太网帧属于哪一个 VLAN</p><ul><li>VID 取值范围 0 ~ 4095</li><li>0 和 4095不用来表示 VLAN , 因此用于表示 VLAN 的 <strong>VID 的有效范围是 1 ~ 4094</strong></li></ul></li><li><strong>802.1Q</strong> <strong>帧是由交换机来处理的而不是用户主机来处理的</strong><ul><li><strong>打标签</strong>: 交换机给普通的 MAC 帧插入 4 字节的 VLAN 标记</li><li><strong>去标签</strong>: 删除 802.1Q 帧的 VLAN 标记</li></ul></li></ul><h4 id="交换机的端口类型"><a href="#交换机的端口类型" class="headerlink" title="交换机的端口类型"></a>交换机的端口类型</h4><ul><li>端口类型有以下三种<ul><li>Access</li><li>Trunk</li><li>Hybrid</li></ul></li><li>交换机各端口的缺省 VLAN ID<ul><li>思科交换机上称为 Native VLAN, 即本征 VLAN, 默认都是 VLAN1</li><li>在华为交换机上称为 Port VLAN ID, 即端口 VLAN ID, 简记为 PVID</li></ul></li></ul><h5 id="Access-端口"><a href="#Access-端口" class="headerlink" title="Access 端口"></a>Access 端口</h5><ul><li><p>一般连接用户计算机</p></li><li><p>只能属于一个 VLAN</p></li><li><p>Access 端口的 PVID 值与端口所属的 VLAN ID 相同(默认为 1)</p></li><li><p>接收</p><ul><li>一般只接受 “未打标签” 的普通以太网 MAC 帧, 根据接收帧的端口 PVID 给帧 “<strong>打标签</strong>“, 插入的 VLAN 标记字段与 PVID 取值相等</li></ul></li><li><p>发送</p><ul><li><p>若帧中的 VID 与 PVID 相等, 则<strong>去标签</strong>并转发该帧, 否则不转发</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210525125144141.png" alt="发送广播帧举例"></p></li></ul></li></ul><h5 id="Trunk-端口"><a href="#Trunk-端口" class="headerlink" title="Trunk 端口"></a>Trunk 端口</h5><ul><li>一般用于交换机之间或者交换机与路由器之间互连</li><li>Trunk 端口可以属于多个 VLAN </li><li><p>用户可以设置 Trunk 的 PVID 值, 默认情况下Trunk 端口的 PVID 值位 1</p></li><li><p>发送</p><ul><li>对 VID 等于 PVID 的帧, <strong>去标签</strong>再转发.</li><li>对于 VID 不等于 PVID 的帧, <strong>直接转发</strong>.</li></ul></li><li><p>接收</p><ul><li>接收未打标签的帧, 根据自己的 PVID 给帧<strong>打标签</strong>.</li><li>接收到已经打标签的帧.</li></ul><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/计算机网络_03.assets/image-20210525130827405.png" alt="Trunk 端口举例"></p></li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 计网 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机网络 2 -物理层</title>
      <link href="2021/05/02/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C_02/"/>
      <url>2021/05/02/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C_02/</url>
      
        <content type="html"><![CDATA[<h2 id="物理层的基本概念"><a href="#物理层的基本概念" class="headerlink" title="物理层的基本概念"></a>物理层的基本概念</h2><h3 id="物理层所考虑的"><a href="#物理层所考虑的" class="headerlink" title="物理层所考虑的"></a>物理层所考虑的</h3><ul><li>怎样在连接各种计算机的传输媒体上传输比特流</li><li>物理层为数据链路层屏蔽了各种传输媒体的差异, 是数据链路层只需要考虑如何完成本层的协议, 而无需考虑网络具体的传输媒体是什么</li></ul><h3 id="传输媒体"><a href="#传输媒体" class="headerlink" title="传输媒体"></a>传输媒体</h3><ul><li><p>导引型传输媒体</p><ul><li>双绞线 (Twisted Pair)</li><li>同轴电缆(Coaxial Cable)</li><li>光纤(Fiber-Optic)</li></ul></li><li><p>非导引型传输媒体</p><ul><li>微波通信 (Microwave Communication)</li></ul></li></ul><h3 id="物理层协议的主要任务"><a href="#物理层协议的主要任务" class="headerlink" title="物理层协议的主要任务"></a>物理层协议的主要任务</h3><ul><li><p>机械特性</p><ul><li>指明接口所用接线器的<strong>形状</strong>和<strong>尺寸</strong>, <strong>引脚数目</strong>和<strong>排列</strong>, <strong>固定</strong>和<strong>锁定</strong>装置</li></ul></li></ul><ul><li><p>电气特性</p><ul><li>指明接口电缆上各条线的<strong>电压范围</strong></li></ul></li></ul><ul><li><p>功能特性</p><ul><li>指明某条线出现某一电平的<strong>电压表示何种意义</strong></li></ul></li></ul><ul><li><p>过程特性</p><ul><li>指明对于不同功能的<strong>各种可能事件的出现顺序</strong></li></ul></li></ul><h2 id="物理层下面的传输媒体"><a href="#物理层下面的传输媒体" class="headerlink" title="物理层下面的传输媒体"></a>物理层下面的传输媒体</h2><h3 id="导引型传输媒体"><a href="#导引型传输媒体" class="headerlink" title="导引型传输媒体"></a>导引型传输媒体</h3><ul><li><p>同轴电缆 (Coaxial Cable)</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/RiBqmbxIPlUMu2a.webp" alt="image-20210323110924035"></p><ul><li><p>优点:</p><p>1.与 STP 和 UDP 相比,同轴电缆可以在几乎没有中继器推动的情况下,在距离较远的两个网络节点之间传输数据；</p><p>2.比光缆便宜（比 STP 和 UTP 贵）。</p></li><li><p>缺点:</p><p>同轴电缆价格较贵且布线不够灵活和方便,随着集线器的出现, 在局域网领域基本上都是采用双绞线作为传输媒体。</p></li></ul></li><li><p>双绞线 (Twisted Pair)</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/lu6VJF1eTk2MOdi.webp" alt="image-20210323113124867" style="zoom:100%;margin-left : 5%" /><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/Bf2qN4vItKspmF6.webp" alt="image-20210323113156980"  style=""/></p><ul><li><p>类型</p><ul><li><p>屏蔽双绞线 (Shielded Twisted Pair, STP)</p></li><li><p>非屏蔽双绞线( Unhielded Twisted Pair, UTP )</p></li><li><p>网屏式双绞线(Screened Twisted Pair, ScTP)</p></li></ul></li></ul></li></ul><ul><li><p>绞合作用</p><ul><li>抵御部分来自外界的电磁波干扰</li><li>减少相邻导线的电磁干扰</li></ul></li></ul><ul><li><p>类别和典型应用</p><p>|    类别    |  带宽  | 线缆特点       | 应用                               |<br>| :————: | :——: | ——————— | ————————————————— |<br>|     3      | 16MHz  | 2对4芯双绞线   | 模拟电话;曾用于传统以太网 (10Mbps) |<br>|     4      | 20MHz  | 4对8芯双绞线   | 曾用于令牌局域网                   |<br>|     5      | 100MHz | 增加了绞合度   | 传输速率不超过 100Mbps 的应用      |<br>| 5E(超五类) | 125MHz | 衰减更小       | 传输速率不超过 1Gbps 的应用        |<br>|     6      | 250MHz | 改善串扰       | 传输速率高于 1Gbps 的应用          |<br>|     7      | 600MHz | 使用屏蔽双绞线 | 传输速率高于 10Gbps 的应用         |</p></li></ul><ul><li><p>光纤 (Fiber-Optic)</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/pD6ikyuJhcZKarE.webp" alt="image-20210323115529271"></p><ul><li><p>纤芯直径</p><ul><li>多模光纤: 50 μm,  62.5 μm</li><li>单模光纤: 9 μm</li></ul></li><li><p>包层直径</p><ul><li>125 μm</li></ul></li><li><p>工作波长</p><ul><li>0.85 μm (衰减较大)</li><li>1.30 μm(衰减较小)</li><li>1.55 μm (衰减较小)</li></ul></li><li><p>优点</p><ul><li>通信容量大 (25000~ 30000GHz的带宽)</li><li>传输损耗小,远距离传输时更加经济。</li><li><p>抗雷电和电磁干扰性能好。这在大电流脉冲<br>干扰的环境下尤为重要。</p></li><li><p>无串音干扰,保密性好,不易被窃听。</p></li><li>体积小,重量轻。</li></ul></li><li><p>缺点</p><ul><li>切割需要专用设备</li><li>光电接口较贵</li></ul></li><li><p>原理</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/jzHMdTBw8namWJu.webp" alt="image-20210323120036566"></p></li><li><p>多模光纤和单模光纤对比</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/goqf63t2PQUFJbY.webp" alt="image-20210323120357496"></p></li></ul></li><li><p>电力线</p></li></ul><h3 id="导引型传输媒体-1"><a href="#导引型传输媒体-1" class="headerlink" title="导引型传输媒体"></a>导引型传输媒体</h3><ul><li>无线电波</li><li>微波</li><li>红外线</li><li>可见光</li></ul><h2 id="传输方式"><a href="#传输方式" class="headerlink" title="传输方式"></a>传输方式</h2><h3 id="串行传输和并行传输"><a href="#串行传输和并行传输" class="headerlink" title="串行传输和并行传输"></a>串行传输和并行传输</h3><h4 id="串行传输"><a href="#串行传输" class="headerlink" title="串行传输"></a>串行传输</h4><p>一个一个比特依次传输, 只需要一条传输线路</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/wDPgsdQHKL2VuBn.webp" alt="image-20210323120834212"></p><h4 id="并行传输"><a href="#并行传输" class="headerlink" title="并行传输"></a>并行传输</h4><p>n 条线路同时传输</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/UvmTDg27ZxiB8bR.webp" alt="image-20210323120858286"></p><ul><li>优点<ul><li>速度是串行的 n 倍</li><li>成本高</li></ul></li></ul><p>远距离传输( 如计算机网络 )常采用串行传输, 计算机内部传输常采用并行传输 ( 如总线 )</p><h3 id="同步传输和异步传输"><a href="#同步传输和异步传输" class="headerlink" title="同步传输和异步传输"></a>同步传输和异步传输</h3><h4 id="同步传输"><a href="#同步传输" class="headerlink" title="同步传输"></a>同步传输</h4><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/QoWF4TN5PnyuJK2.webp" alt="image-20210323210341109"></p><p>数据块以稳定比特流传输, 字节之间没有间隔. 接收端在每个比特信号中间检测是0还是1.</p><p>由于不同设备时钟频率不同, 为避免时钟误差积累, 需要实现同步</p><ul><li>外同步<ul><li>收发双方之间添加单独信号线</li></ul></li><li>内同步<ul><li>发射端将时钟同步信号编码到数据中一起传输(如曼彻斯特编码)</li></ul></li></ul><h4 id="异步传输"><a href="#异步传输" class="headerlink" title="异步传输"></a>异步传输</h4><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/3UiGa9MN7Bdwvze.webp" alt="image-20210323210808220"></p><ul><li>字节之间异步(字节之间的时间间隔不固定)</li><li>字节中的没个比特仍然要同步(各个比特持续时间相同)</li></ul><h4 id="单工通信和双工通信"><a href="#单工通信和双工通信" class="headerlink" title="单工通信和双工通信"></a>单工通信和双工通信</h4><ul><li>单工通信: 单向通信 如: 广播</li><li>半双工通信: 双向交替通信 如: 对讲机</li><li>全双工通信: 双向同时通信 如: 电话</li></ul><h2 id="编码与调制"><a href="#编码与调制" class="headerlink" title="编码与调制"></a>编码与调制</h2><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/fUZKHsvNIA24j3w.webp" alt="image-20210323184729955"></p><h3 id="码元"><a href="#码元" class="headerlink" title="码元"></a>码元</h3><p>在使用时间域的波形表示数字信号时, 代表不同<strong>离散数值的基本波形</strong>. 例:</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/GQIJoFsUTafv2HR.webp" alt="image-20210323185320323"></p><h3 id="信道和传输媒体"><a href="#信道和传输媒体" class="headerlink" title="信道和传输媒体"></a>信道和传输媒体</h3><ul><li><p>单工传输</p><ul><li>传输媒体中只包含一个信道: <strong>发送信道或者接受信道</strong></li></ul></li><li><p>双工/半双工传输</p><ul><li>传输媒体中包含两个信道: <strong>发送信道和接收信道</strong></li></ul></li></ul><ul><li>若使用信道复用技术, 一条传输媒体包含多个信号</li></ul><h3 id="常见编码"><a href="#常见编码" class="headerlink" title="常见编码"></a>常见编码</h3><h4 id="不归零编码"><a href="#不归零编码" class="headerlink" title="不归零编码"></a>不归零编码</h4><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/cX3aD14ZQYT9Us6.webp" alt="image-20210323185911303"></p><ul><li>需要<strong>额外一根传输线传输时钟信号</strong>, 使发送方和接收方同步</li><li>宁愿用这根线传输数据信号而不是时钟信号</li><li><strong>存在同步问题</strong>, 故计算机网络中的数据不采用这类编码</li></ul><h4 id="归零编码"><a href="#归零编码" class="headerlink" title="归零编码"></a>归零编码</h4><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/RUEdWMaY7ZrHc64.webp" alt="image-20210323190136435"></p><ul><li>每个码元传输结束后信号都要”归零”, 所以接收方只需要在信号归零后进行采样, 不需要单独的时钟信号</li><li>相当于把时钟信号用”归零”方式编在数据之内, 称为”<strong>自同步</strong>“信号</li><li>大部分带宽被用来传输”归零”而被<strong>浪费</strong>掉了, <strong>编码效率低</strong></li></ul><h4 id="曼彻斯特编码-Manchester-Encoding"><a href="#曼彻斯特编码-Manchester-Encoding" class="headerlink" title="曼彻斯特编码 (Manchester Encoding)"></a>曼彻斯特编码 (Manchester Encoding)</h4><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/7oQUkKR4jyluFhe.webp" alt="image-20210323193034084"></p><ul><li>每个码元的中间时刻发生跳变, 既表示时钟, 又表示数据</li></ul><h4 id="差分曼切斯特编码-Differential-Manchester-Encoding"><a href="#差分曼切斯特编码-Differential-Manchester-Encoding" class="headerlink" title="差分曼切斯特编码 (Differential Manchester Encoding)"></a>差分曼切斯特编码 (Differential Manchester Encoding)</h4><ul><li>跳变仅表示时钟</li><li>每个码元开始时刻相对于上一个码元的结束电位是否发生变化表示数据</li></ul><h3 id="调制"><a href="#调制" class="headerlink" title="调制"></a>调制</h3><h4 id="基本调制方法"><a href="#基本调制方法" class="headerlink" title="基本调制方法"></a>基本调制方法</h4><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/EnGlsBzAZP1jxNr.webp" alt="image-20210323193704659"></p><h4 id="混合调制"><a href="#混合调制" class="headerlink" title="混合调制"></a>混合调制</h4><ul><li><p>基本调制方法<strong>一个码元只能表示一个比特</strong></p></li><li><p>频率和相位相关, 所以通常情况下将相位和振幅和振幅合起来一起调制, 称为<strong>正交振幅调制 QAM</strong>(Quadrature Amplitude Modulation)</p></li><li><p>QAM-16</p><ul><li><p>12 种相位</p></li><li><p>每种相位有1或者2种振幅可选</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/vUuIPcdaFirHzwB.webp" alt="image-20210323194351345"></p></li></ul></li></ul><ul><li><p>可以调制出16种码元, 可以表示 0b0000~0b1111的数据, 故每个码元对应4个比特</p></li><li><p>码元与4个比特的对应关系采用格雷码. 相邻码元只有一位不同</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/sWGj8y2hFnx6arN.webp" alt="image-20210323195043588"></p></li></ul><h2 id="信道的极限容量"><a href="#信道的极限容量" class="headerlink" title="信道的极限容量"></a>信道的极限容量</h2><h3 id="失真因素"><a href="#失真因素" class="headerlink" title="失真因素"></a>失真因素</h3><ul><li>码元传输速率</li><li>信号传输距离</li><li>噪声干扰</li><li>传输媒体质量</li></ul><p>失真的例子:</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/LbXHw1NaI4pTGhA.webp" alt="image-20210323200241813"></p><h3 id="奈氏准则-Nyquist’s-Theorem"><a href="#奈氏准则-Nyquist’s-Theorem" class="headerlink" title="奈氏准则 (Nyquist’s Theorem)"></a>奈氏准则 (Nyquist’s Theorem)</h3><blockquote><p>在假定的理想条件下, 为了避免码间串扰, <strong>码元的传输速率是有上限的</strong>.</p></blockquote><h4 id="内容"><a href="#内容" class="headerlink" title="内容"></a>内容</h4><ul><li><p>理想低通(频率低于某个上限值)信道的最高码元传输速率 = 2W Baud = 2W 码元/秒</p></li><li><p>理想带通(频率位于上下限之间)信道的最高码元传输速率 = 1W Baud = W 码元/秒</p><p>其中 W: 信道带宽(Hz) Baud: 波特, 即码元/秒</p></li><li><p>实际上信道所能传输的最高码元速率要明显低于奈氏准则的上限数值</p></li></ul><h4 id="码元传输速率-波特率-调制速率-波形速率-符号速率-与比特率的关系"><a href="#码元传输速率-波特率-调制速率-波形速率-符号速率-与比特率的关系" class="headerlink" title="码元传输速率(波特率, 调制速率, 波形速率,符号速率)与比特率的关系"></a>码元传输速率(波特率, 调制速率, 波形速率,符号速率)与比特率的关系</h4><ul><li>1个码元携带1个比特的信息量, 波特率和比特率在数值上相等</li><li>1个码元携带n个比特的信息量, 比特率=波特率*n</li><li>提高信息传输速率(比特率),必须使每个码元携带更多比特的信息量, 这需要采用多元制</li></ul><h3 id="香农公式-Shannon-Theorem"><a href="#香农公式-Shannon-Theorem" class="headerlink" title="香农公式 (Shannon Theorem)"></a>香农公式 (Shannon Theorem)</h3><blockquote><p>带宽受限且有高斯白噪声干扰的信道的极限信息传输速率</p></blockquote><script type="math/tex; mode=display">c=W \times \log_2(1+\frac S N)</script><p>c: 信道极限信息传输速率 (bps)</p><p>W: 信道带宽 (Hz)</p><p>S: 信道内所传信号的平均功率</p><p>N: 信道内高斯白噪声的功率</p><p>S/N: 信号与噪声噪之比, 无量纲单位</p><p>SNR: 信噪比(dB)作为度量单位, 计算公式 $\displaystyle \text  {SNR} = 10 \times \log_{10}(\frac S N)$</p><p><strong>结论</strong></p><ul><li><p>信道带宽或者信道中信噪比越大, c  越高</p></li><li><p>实际能达到的传输速率要低上不少, 因为在实际信道中, 还存在各种脉冲干扰, 信号在传输中的衰减和失真, 香农公式并未考虑</p></li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 计网 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机网络 1 -因特网概述</title>
      <link href="2021/05/02/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C_01/"/>
      <url>2021/05/02/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C_01/</url>
      
        <content type="html"><![CDATA[<h2 id="网络、互连（联）网和因特网"><a href="#网络、互连（联）网和因特网" class="headerlink" title="网络、互连（联）网和因特网"></a>网络、互连（联）网和因特网</h2><ul><li><strong>网络</strong> (Network)  是由若干<span style="color:red"><b>结点</b></span>和连接这些结点的<span style="color:red"><b>链路</b></span>组成的</li><li>多个网络可以通过路由器互连起来, 构成一个覆盖范围更大的网络, 即互联网</li><li><strong>因特网</strong> (Internet) 是世界上最大的互连网络</li></ul><h3 id="Internet-和-internet"><a href="#Internet-和-internet" class="headerlink" title="Internet 和 internet"></a>Internet 和 internet</h3><p>internet 是一个通用名词, 泛指多个计算机网络互连而成的网络. 在这些网络之间的通信协议可以是任意的</p><p>Internet 是专有名词, 指当前全球最大的, 开放的, 由众多网络互相连接而成的特定计算机网络, 采用 TCP/IP 协议族作为通信规则, 前身是美国的 APRANET</p><h2 id="因特网发展的三个阶段"><a href="#因特网发展的三个阶段" class="headerlink" title="因特网发展的三个阶段"></a>因特网发展的三个阶段</h2><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/geD1NLXtMJlOxE2.webp" alt="image-20210308165413452"></p><h3 id="因特网服务提供者ISP-Internet-Service-Provider"><a href="#因特网服务提供者ISP-Internet-Service-Provider" class="headerlink" title="因特网服务提供者ISP (Internet Service Provider)"></a><strong>因特网服务提供者</strong><span style="color:red"><b>ISP </b></span>(Internet Service Provider)</h3><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/BZlDLwSoz7GNWjg.webp" alt="image-20210308170736565"></p><p>ISP 从因特网管理机构申请到成块的 IP 地址, 同时拥有通信线路以及路由器等联网设备. 任何机构和个人只要向 ISP 交纳规定费用, 就可以从 ISP 得到需要的 IP 地址. </p><p>我国主要的 ISP 就是三大运营商.</p><h3 id="基于-ISP-的三层结构的因特网"><a href="#基于-ISP-的三层结构的因特网" class="headerlink" title="基于 ISP 的三层结构的因特网"></a>基于 ISP 的三层结构的因特网</h3><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/JHxEb1VGp3iukSO.webp" alt="image-20210308171327190"></p><ul><li>第一层: 因特网主干网, 一般可以覆盖国际性区域范围, 拥有高速链路和交换设备. 第一层 ISP 直接互联.</li><li>第二层: 第二层 ISP 和一些大公司是第一层 ISP 的用户, 具有区域性或者国家性覆盖规模, 与少数第一层 ISP 相连接.</li><li>第三层: 本地 ISP 是第二层 ISP 的用户, 只拥有本地范围的网络, 一般的校园网, 企业网, 住宅用户是第三层 ISP 的用户.</li></ul><h2 id="数据-Data"><a href="#数据-Data" class="headerlink" title="数据 (Data)"></a>数据 (Data)</h2><ul><li>数据以 0 1 序列发送.</li><li>数据不是信息的本身.</li><li>数据时信息的一种编码方式, 它通过电/光信号来传输.</li></ul><h2 id="数据包-Data-Packets"><a href="#数据包-Data-Packets" class="headerlink" title="数据包 (Data Packets)"></a>数据包 (Data Packets)</h2><ul><li>数据被划分成易于传输的小单元.<ul><li>在 OSI 中, 这些单元可以是 <strong>packets, frames, segments</strong></li></ul></li><li>意义<ul><li>加速传输 (不同进程或任务对于用户是同时运行的)</li><li>丢包重传数据少</li><li>数据可通过不同的路径到达</li></ul></li></ul><h2 id="因特网的标准化工作"><a href="#因特网的标准化工作" class="headerlink" title="因特网的标准化工作"></a>因特网的标准化工作</h2><ul><li>因特网的标准化工作对因特网的发展起到了非常重要的作用</li><li>因特网在制定其标准上的一个很大的特点是面向大众.</li></ul><h2 id="因特网的组成"><a href="#因特网的组成" class="headerlink" title="因特网的组成"></a>因特网的组成</h2><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/3kJBlxQUycqeZho.webp" alt="image-20210308180218899"></p><ul><li>边缘部分<ul><li>由所有链接在因特网上的<span style="color:red"><b>主机</b></span>组成. 这部分是<span style="color:red"><b>用户直接使用</b></span>的,用来进行通信(传送数据)和资源共享.</li></ul></li><li>核心部分<ul><li>由<span style="color:red"><b>大量网络</b></span>和连接这些网络的<span style="color:red"><b>路由器</b></span>组成. 这部分是为边缘部分提供服务的.</li></ul></li></ul><h2 id="三种交换方式"><a href="#三种交换方式" class="headerlink" title="三种交换方式"></a>三种交换方式</h2><h3 id="电路交换-Circuit-Switching"><a href="#电路交换-Circuit-Switching" class="headerlink" title="电路交换(Circuit Switching)"></a>电路交换(Circuit Switching)</h3><ul><li><p>电话交换机接通电话线的方式称为电路交换</p></li><li><p>从通信资源呢分配角度来看, 交换(Switching) 是按照某种方式动态地分配传输线路的资源</p></li><li><p>步骤:</p><p>1.建立连接 (分配通信资源)</p><p>2.通话(一直占用通信资源)</p><p>3.释放连接 (归还通信资源)</p></li></ul><p>使用电路交换传送计算机地数据, 线路的传输效率会很低</p><h3 id="分组交换-Packet-Switching"><a href="#分组交换-Packet-Switching" class="headerlink" title="分组交换 (Packet Switching)"></a>分组交换 (Packet Switching)</h3><h4 id="发送方"><a href="#发送方" class="headerlink" title="发送方"></a>发送方</h4><ul><li><p>构造分组</p><p>将较长的报文划分为等长的数据段, 并添加<strong>首部</strong>, 构成一个分组, 也可以简称为<strong>包</strong> (packets), 首部也可以称为<strong>包头</strong>. 首部包含了分组的目的地址.</p></li><li><p>发送分组</p></li></ul><h4 id="路由器"><a href="#路由器" class="headerlink" title="路由器"></a>路由器</h4><ul><li><p>缓存分组</p></li><li><p>转发分组</p><p>检查首部中的目的地址, 进行查表转发</p></li></ul><h4 id="接收方"><a href="#接收方" class="headerlink" title="接收方"></a>接收方</h4><ul><li><p>接受分组</p></li><li><p>还原报文</p><p>去掉首部还原出原始报文</p></li></ul><p>下图展示了分组交换的两种情况:</p><ul><li>各分组从源站到目的站可以走不同的路径</li><li>分组乱序</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/jr2mXCJlE4Au8OV.gif" alt=""></p><h3 id="报文交换-过时"><a href="#报文交换-过时" class="headerlink" title="报文交换 (过时)"></a>报文交换 (过时)</h3><h3 id="对比"><a href="#对比" class="headerlink" title="对比"></a>对比</h3><div class="table-container"><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></div><h2 id="计算机网络的定义"><a href="#计算机网络的定义" class="headerlink" title="计算机网络的定义"></a>计算机网络的定义</h2><h4 id="最简单定义-一些互连-自治的计算机集合"><a href="#最简单定义-一些互连-自治的计算机集合" class="headerlink" title="最简单定义: 一些互连, 自治的计算机集合"></a>最简单定义: 一些互连, 自治的计算机集合</h4><ul><li>互连: 计算机之间可以通过有线或者无线的方式进行数据通信</li><li>自治: 独立的计算机, 有自己的硬件和软件</li><li>集合: 多台计算机</li></ul><h4 id="较好的定义"><a href="#较好的定义" class="headerlink" title="较好的定义:"></a>较好的定义:</h4><p>计算机网络主要是由一些<strong>通用的、可编程的硬件互连</strong>而成的,而这些硬件并非专门用来实现某一特定目的 (例如,传送数据或视频信号)。这些可编程的硬件能够用来<strong>传送多种不同类型的数据</strong>,并能<strong>支持广泛的和日益增长的应用</strong></p><h2 id="计算机网络的分类"><a href="#计算机网络的分类" class="headerlink" title="计算机网络的分类"></a>计算机网络的分类</h2><h3 id="按交换技术"><a href="#按交换技术" class="headerlink" title="按交换技术"></a>按交换技术</h3><ul><li>电路交换网络</li><li>报文交换网络</li><li>分组交换网络</li></ul><h3 id="按使用者"><a href="#按使用者" class="headerlink" title="按使用者"></a>按使用者</h3><ul><li>公用网</li><li>专用网</li></ul><h3 id="按传输介质"><a href="#按传输介质" class="headerlink" title="按传输介质"></a>按传输介质</h3><ul><li>有线网络</li><li>无线网络</li></ul><h3 id="按覆盖范围"><a href="#按覆盖范围" class="headerlink" title="按覆盖范围"></a>按覆盖范围</h3><ul><li>广域网 WAN</li><li>城域网 MAN</li><li>局域网 LAN</li><li>个域网 PAN</li></ul><h3 id="按拓扑结构分类"><a href="#按拓扑结构分类" class="headerlink" title="按拓扑结构分类"></a>按拓扑结构分类</h3><ul><li>总线型网络</li><li>星型网络</li><li>环型网络</li><li>网状型网络</li></ul><h2 id="计算机网络的性能指标"><a href="#计算机网络的性能指标" class="headerlink" title="计算机网络的性能指标"></a>计算机网络的性能指标</h2><h3 id="速率"><a href="#速率" class="headerlink" title="速率"></a>速率</h3><p>常用数据率单位:</p><p>$1Mbps=1000kbps=10^6bps$</p><p>一般在带宽, 速率中, 进率为 1000, 存储容量中进率为 1024. 当然也要看题目具体的说明.</p><h3 id="带宽-Bandwidth"><a href="#带宽-Bandwidth" class="headerlink" title="带宽 (Bandwidth)"></a>带宽 (Bandwidth)</h3><h4 id="在模拟信号系统中"><a href="#在模拟信号系统中" class="headerlink" title="在模拟信号系统中"></a>在模拟信号系统中</h4><p>信号包含的各种不同频率所占据的<strong>频率范围</strong>, 单位 HZ</p><h4 id="在计算机网络中"><a href="#在计算机网络中" class="headerlink" title="在计算机网络中"></a>在计算机网络中</h4><p>用来表示网络的通信线路所能传送数据的能力, 因此网络带宽表示<strong>最高速率</strong></p><p>单位与速率相同.</p><h3 id="吞吐量-Throughput"><a href="#吞吐量-Throughput" class="headerlink" title="吞吐量 (Throughput)"></a>吞吐量 (Throughput)</h3><p>单位时间内通过某个网络(或信道,接口)的数据量, 与带宽不同的是, 吞吐量是真实的通过测量得到的.</p><h3 id="时延"><a href="#时延" class="headerlink" title="时延"></a>时延</h3><ul><li>$\displaystyle\text{发送时延}=\frac {分组大小}{发送速率} $</li><li>$\displaystyle传播时延 = \frac{信道长度}{电磁波传播速率}$</li><li>处理时延 一般不便于计算</li></ul><h3 id="时延带宽积"><a href="#时延带宽积" class="headerlink" title="时延带宽积"></a>时延带宽积</h3><ul><li><strong>传播时延</strong>和<strong>带宽</strong>的乘积</li><li>若发送端连续发送数据, 则在所发送的第一个比特即将到达终点时, 发送端就已经发送了时延带宽积个比特</li><li>又称为<strong>以比特为单位的链路长度</strong></li></ul><h3 id="往返时间-RTT"><a href="#往返时间-RTT" class="headerlink" title="往返时间 RTT"></a>往返时间 RTT</h3><ul><li>因特网上的信息往往需要<strong>双向交互</strong></li><li>有时需要知道双向交互一次的时间</li></ul><h3 id="利用率"><a href="#利用率" class="headerlink" title="利用率"></a>利用率</h3><ul><li><p><strong>信道利用率</strong>: 某信道的时间利用率</p></li><li><p><strong>网络利用率</strong>: 全网络信道利用率的加权平均</p></li><li><p>利用率并非越高越好, 一条信道利用率和和时延有下面的关系:</p><p>$D$ 表示网络当前时延, $D_0$ 表示网络空闲时的时延, $U$ 表示利用率</p><script type="math/tex; mode=display">\displaystyle D=\frac {D_0}{1-U}</script><p>一些拥有较大主干网的 ISP 通常会控制信道利用率不超过 50%, 否则就要准备扩容, 增大带宽.</p></li><li><p>信道利用率太低会造成浪费, 可以根据情况动态调整输入到网络的通信量. </p></li></ul><h3 id="丢包率"><a href="#丢包率" class="headerlink" title="丢包率"></a>丢包率</h3><ul><li>即<strong>分组丢失率</strong></li><li>原因:<ul><li><strong>分组误码</strong></li><li><strong>网络拥塞</strong>(结点交换机缓存队列满)</li></ul></li></ul><h2 id="计算机网络体系结构"><a href="#计算机网络体系结构" class="headerlink" title="计算机网络体系结构"></a>计算机网络体系结构</h2><h3 id="常见的计算机网络体系结构"><a href="#常见的计算机网络体系结构" class="headerlink" title="常见的计算机网络体系结构"></a>常见的计算机网络体系结构</h3><h4 id="开放系统互连参考模型-Open-System-Interconnection-OSI"><a href="#开放系统互连参考模型-Open-System-Interconnection-OSI" class="headerlink" title="开放系统互连参考模型 (Open System Interconnection,OSI)"></a>开放系统互连参考模型 (Open System Interconnection,OSI)</h4><ul><li>法律上的国际标准 </li><li>从下往上依次是: Physical, Data Link, Network, Transport, Session, Presentation, Application</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/fc8qBOxJy5ISEPU.webp" alt="image-20210310113453877"></p><h4 id="TCP-IP-体系结构"><a href="#TCP-IP-体系结构" class="headerlink" title="TCP/IP 体系结构"></a>TCP/IP 体系结构</h4><ul><li>事实上的国际标准 </li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/84sXk1rdD5h7ENC.webp" alt="image-20210316193311111"></p><h4 id="学习用模型"><a href="#学习用模型" class="headerlink" title="学习用模型"></a>学习用模型</h4><ul><li>在学习时, 常把网络接口层分为物理层和数据链路层</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/2NGmnqkMAS5ayZo.webp" alt="image-20210316193333188"></p><h3 id="计算机网络体系结构分层的必要性"><a href="#计算机网络体系结构分层的必要性" class="headerlink" title="计算机网络体系结构分层的必要性"></a>计算机网络体系结构分层的必要性</h3><ul><li>减小复杂性</li><li>标准化的接口: 各层之间相互请求并提供服务</li><li>促进模块化工程</li><li>确保内部可操作的计数</li><li>促进发展</li><li><p>简化教学</p></li><li><p><del>应用层: 通过应用进程交互实现特定网络应用</del></p></li><li><del>运输层: 进程间基于网络的通信问题</del></li><li><del>网络层: 分组在多个网络上传输(路由)</del></li><li><del>数据链路层: 分组在一个网络(或者一段链路)传输</del></li><li><del>物理层: 用何种信号传输比特</del></li></ul><h3 id="计算机网络体系结构分层思想举例"><a href="#计算机网络体系结构分层思想举例" class="headerlink" title="计算机网络体系结构分层思想举例"></a>计算机网络体系结构分层思想举例</h3><h4 id="发送方-1"><a href="#发送方-1" class="headerlink" title="发送方"></a>发送方</h4><p>层层封装</p><ul><li>应用层: 构建一个 HTTP 请求报文</li><li>运输层: 添加一个 TCP 首部, 形成 TCP 报文</li><li>网络层: 添加一个 IP 首部, 形成 IP 报文</li><li>数据链路层: 添加以太网帧首部和帧尾部<ul><li>帧首部: 让帧能在一个网络或者一个链路上传输,能被相应主机接收</li><li>帧尾部: 检查是否有误码</li></ul></li><li>物理层: 添加前导码<ul><li>让目的主机做好接收帧的准备</li></ul></li></ul><h4 id="路由器-1"><a href="#路由器-1" class="headerlink" title="路由器"></a>路由器</h4><p>一般只具有网络层, 链路层,和物理层</p><p>层层解封, 通过 IP 数据报的首部确定转发端口</p><h4 id="接收方-1"><a href="#接收方-1" class="headerlink" title="接收方"></a>接收方</h4><p>层层解封</p><h3 id="计算机网络体系结构中的专业术语"><a href="#计算机网络体系结构中的专业术语" class="headerlink" title="计算机网络体系结构中的专业术语"></a>计算机网络体系结构中的专业术语</h3><h4 id="实体-Entity"><a href="#实体-Entity" class="headerlink" title="实体 (Entity)"></a>实体 (Entity)</h4><ul><li>实体 (Entity): 任何可发送或者接收信息的<strong>硬件</strong>或<strong>软件进程</strong></li><li>对等实体 (Peer-Entity): 收发双方<strong>相同层次的实体</strong></li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/6tzBQ5wXVvPuEMG.webp" alt="image-20210316193425901"></p><h4 id="协议-Protocol"><a href="#协议-Protocol" class="headerlink" title="协议 (Protocol)"></a>协议 (Protocol)</h4><p>控制两个对等实体进行逻辑通信的规则的集合</p><ul><li>逻辑通信实际上并不存在</li></ul><p>协议的三要素</p><ul><li><p>语法</p><p>定义所交换信息的格式</p></li><li><p>语义</p><p>定义收发双方所要完成的操作</p></li><li><p>同步</p><p>定义收发双方的时序关系, 如 TCP 采用 “三报文握手” 建立连接的过程</p></li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/GoUWpMARmh4kn9T.webp" alt="image-20210310222600735"></p><h4 id="服务"><a href="#服务" class="headerlink" title="服务"></a>服务</h4><ul><li><p>在协议的控制下, 两个对等实体间的逻辑通信使得本层能够向上一层提供服务</p></li><li><p>要实现本层协议, 还需要使用下面一层提供的服务</p></li><li><p>协议是 “<strong>水平的</strong>“, 服务是”<strong>垂直的</strong>“</p></li><li><p>下层协议对上层是不可见的</p></li><li><p>服务访问点 同一系统<strong>相邻两层的实体交换信息的逻辑接口</strong>, 用于区分不同的服务类型</p><ul><li>数据链路层: 帧的”类型”字段</li><li>网络层: IP 数据报的”协议”字段</li><li>运输层: “端口号”</li></ul></li><li><p>服务原语: 上层使用下层服务必须与下层<strong>交换一些命令</strong>, 就是服务原语</p></li><li><p>协议数据单元  (PDU): 对等层次之间传送的数据包</p></li><li><p>服务数据单元 (SDU): 同一系统内, <strong>层与层之间交换的数据包</strong></p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/FvxbRoADwtGyPCc.webp" alt="image-20210316193459176"></p></li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 计网 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(三) BCD 码</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_03/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_03/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><ul><li>每 4 位二进制数表示十进制的一位数</li><li>加法:由于真值的进位是 10,而 BCD 码的进位是 16,所以在真值产生进位的时候需加 6 强制进位.</li><li>减法:类似于补码减法. BCD”补码”与原码相加得 9.若结果是负数(“补码”表示),需转化成负号+原码的形式.</li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 基础(八) 抽象</title>
      <link href="2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_08/"/>
      <url>2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_08/</url>
      
        <content type="html"><![CDATA[<h2 id="1-概念"><a href="#1-概念" class="headerlink" title="1. 概念"></a>1. 概念</h2><ul><li>抽象函数—表达概念而无具体实现代码的函数</li><li>抽象类—表达概念而无法实例化对象的函数</li></ul><h2 id="2-特点"><a href="#2-特点" class="headerlink" title="2. 特点"></a>2. 特点</h2><ul><li>带有 <strong>abstract</strong> 修饰符的函数</li><li>有抽象函数的类一定是抽象类</li><li>抽象类不能制造对象, 但是可以定义变量<ul><li>任何继承了抽象类的非抽象类的对象可以赋给这个变量</li></ul></li></ul><h2 id="实现抽象函数"><a href="#实现抽象函数" class="headerlink" title="实现抽象函数"></a>实现抽象函数</h2><ul><li>继承自抽象类的子类必须实现基类的抽象函数, 否则他自己就成为抽象函数</li></ul><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">AbstractClass</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">int</span> <span class="title">abstractMethod</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="与-C-相比"><a href="#与-C-相比" class="headerlink" title="与 C++ 相比"></a>与 C++ 相比</h2><div class="table-container"><table><thead><tr><th style="text-align:center">C++</th><th style="text-align:center">Java</th></tr></thead><tbody><tr><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></tr><tr><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></tr></tbody></table></div><p>C++ 和 Java 实现多态的方式不同, 在 Java 中, 普通的函数就相当于 C++ 中的 <strong>virtual function</strong>, 从<strong>向上造型</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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">print</span><span class="params">()</span></span>&#123;System.out.println(<span class="string">&quot;A&quot;</span>);&#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        A temp = <span class="keyword">new</span> B();</span><br><span class="line">        temp.print();</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">public</span> <span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span> </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">print</span><span class="params">()</span> </span>&#123;System.out.println(<span class="string">&quot;B&quot;</span>);&#125;</span><br><span class="line">&#125;</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></pre></td><td class="code"><pre><span class="line">B</span><br></pre></td></tr></table></figure><p>同理, 在存放基类对象的容器中添加子类的对象, 调用这些对象的函数时永远都是<strong>调用自己类</strong>的.</p><p>在 C++ 中默认的函数没有这种效果,而给函数加上 <strong>virtual</strong> 关键字后, 可以实现 Java 中的效果, 如:</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><span class="line">6</span><br><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="meta">#<span class="meta-keyword">include</span><span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;vector&gt;</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="class"><span class="keyword">class</span> <span class="title">A</span> &#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="built_in">A</span>() &#123;&#125;</span><br><span class="line"> ~<span class="built_in">A</span>() &#123;&#125;</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">print</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;A&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">print_v</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;A&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span> :</span><span class="keyword">public</span> A</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line"> <span class="built_in">B</span>() &#123;&#125;</span><br><span class="line"> ~<span class="built_in">B</span>() &#123;&#125;</span><br><span class="line"> <span class="function"><span class="keyword">void</span> <span class="title">print</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;B&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line"> <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">print_v</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;B&quot;</span> &lt;&lt; endl; &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="function"><span class="keyword">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"> A* temp = <span class="keyword">new</span> <span class="built_in">B</span>();</span><br><span class="line"> temp-&gt;<span class="built_in">print</span>();</span><br><span class="line"> temp-&gt;<span class="built_in">print_v</span>();</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></pre></td><td class="code"><pre><span class="line">A</span><br><span class="line">B</span><br></pre></td></tr></table></figure><p>需要注意的是, C++ 中实现多态必须使用指针, 否则无论何时都只会调用<strong>静态类型</strong>( 变量类型 )的成员函数. 要在 C++ 中实现上文中 CD 存放的例子, 可以用容器<code>vector&lt;Item*&gt;</code>, 只需注意存放的类型必须为 <code>Item*</code>, 将需要在子类中重写的函数设为 virtual 即可.</p>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 基础(十)  接口( Interface )以狐狸和兔子为例子</title>
      <link href="2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_10/"/>
      <url>2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_10/</url>
      
        <content type="html"><![CDATA[<h2 id="1-接口"><a href="#1-接口" class="headerlink" title="1. 接口"></a>1. 接口</h2><ul><li>接口是<strong>纯抽象类</strong><ul><li>所有的成员函数都是抽象函数</li><li>所有的成员变量都是public static final<ul><li>final 变量意味着这个变量不可以改变值, final 类不可以被继承, final 的方法不可以被 override.</li></ul></li></ul></li><li>接口规定了长什么样, 但是不管里面有什么</li></ul><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">//一个接口的例子</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">Cell</span> </span>&#123;</span><br><span class="line">     <span class="function"><span class="keyword">void</span> <span class="title">draw</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> y, <span class="keyword">int</span> size)</span></span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="2-实现一个接口"><a href="#2-实现一个接口" class="headerlink" title="2. 实现一个接口"></a>2. 实现一个接口</h2><ul><li>继承用 extends, 接口用 implements</li><li>类可以实现多个接口( 实现类似多继承的效果 )</li><li>接口<strong>可以继承接口</strong>, 但不能继承类</li><li>接口不能实现接口</li><li>可以通过<code>instanceof</code>判断赋给接口变量的对象是不是某个类的</li></ul><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">//一个实现接口的例子, Fox 继承了 Animal 类的同时实现了 Cell 的接口</span></span><br><span class="line"><span class="keyword">public</span> Fox extends Animal implements Cell &#123;</span><br><span class="line">     <span class="function"><span class="keyword">void</span> <span class="title">draw</span><span class="params">(<span class="keyword">int</span> x, <span class="keyword">int</span> y, <span class="keyword">int</span> size)</span> </span>&#123;</span><br><span class="line">        </span><br><span class="line">     &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/Java_abc_06.assets/75df19d5fd2d358edc3da30398bb01a43fdd895b.webp" alt="几个类和接口之间的关系" title="几个类和接口之间的关系"><br>其中 Fox 和 Rabbit 都是继承自 Animal, 而 Field 作为容器, 接受的是 Cell, 由于 Java 不支持多继承, 所以将 Cell 做成接口, 在 Fox 和 Rabbit 内部分别实现这个接口, 就能把 FOX 和 Rabbit 赋给 Cell 的变量传给 Field 了.</p>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 基础(十一)  异常</title>
      <link href="2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_11/"/>
      <url>2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_11/</url>
      
        <content type="html"><![CDATA[<h2 id="1-捕获异常的机制"><a href="#1-捕获异常的机制" class="headerlink" title="1. 捕获异常的机制"></a>1. 捕获异常的机制</h2><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">try</span> &#123;</span><br><span class="line">    <span class="comment">//可能产生异常的代码</span></span><br><span class="line">&#125; <span class="keyword">catch</span> (Type1 id1) &#123;</span><br><span class="line">    <span class="comment">//处理 Type1 异常的代码</span></span><br><span class="line">&#125; <span class="keyword">catch</span> (Type2 id2) &#123;</span><br><span class="line">    <span class="comment">//处理 Type2 异常的代码</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>异常机制的最大好处: <strong>清晰地分开了处理正常的业务逻辑代码和遇到情况时的代码</strong><br>Java 中用<code>try&#123;&#125;</code>来包裹可能出现异常的代码块, 并用 <code>catch(Type id)&#123;&#125;</code>捕捉并处理异常.</p><h3 id="流程图"><a href="#流程图" class="headerlink" title="流程图"></a>流程图</h3><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/Java_abc_06.assets/5f17000f52d00a439d9ffaba08d4bc6a9a1fb3a4.webp" alt=""></p><h2 id="2-捕捉到的异常"><a href="#2-捕捉到的异常" class="headerlink" title="2. 捕捉到的异常"></a>2. 捕捉到的异常</h2><p>在 <code>catch(type id)&#123;&#125;</code>的代码块中, 可以调用 id 的 一些方法, 比如<code>getMessage()</code>, <code>printStackTrace()</code> 来获得相关的信息.<br>如果在当前层面上无法全部处理, 可以通过 <code>throw</code> 再次将异常抛向上一层  </p><ul><li><strong>有风险、可能会抛出异常的代码</strong></li></ul><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="comment">//必须声明它会抛出 BadException</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">takeTisk</span><span class="params">()</span> <span class="keyword">throws</span> BadException </span>&#123;</span><br><span class="line">    <span class="keyword">if</span>(abandonallHopes) &#123;</span><br><span class="line">        <span class="comment">//创建 Exception 对象并抛出</span></span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> BadException();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li><strong>调用该方法的程序代码</strong></li></ul><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="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">crossFingers</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="comment">//如果不用 try - catch包裹起来, 就必须声明 throws BadException  </span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        anObject.takeRisk();</span><br><span class="line">    &#125; <span class="keyword">catch</span> (BadException ex) &#123;</span><br><span class="line">        System.out.println(<span class="string">&quot;Aaargh&quot;</span>);</span><br><span class="line">        ex.printStackTrace();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="3-什么东西可以扔出来"><a href="#3-什么东西可以扔出来" class="headerlink" title="3. 什么东西可以扔出来"></a>3. 什么东西可以扔出来</h2><ul><li>任何继承了 Throwable 类的对象</li><li>Exception 类继承了 Throwbale<ul><li>throw new Exception();</li><li>throw new Exception(“Something”);</li></ul></li></ul><h2 id="4-catch-是怎样捕捉异常的"><a href="#4-catch-是怎样捕捉异常的" class="headerlink" title="4. catch 是怎样捕捉异常的"></a>4. catch 是怎样捕捉异常的</h2><ul><li>抛出子类的异常会被捕捉父类异常的 catch 捕捉到, 如 <code>catch(Exception e)&#123;&#125;</code>会捕捉到所有的异常</li></ul><h3 id="运行时刻异常"><a href="#运行时刻异常" class="headerlink" title="运行时刻异常"></a>运行时刻异常</h3><ul><li>像 ArrayIndexOutOfBoundsException 这样的异常<strong>不需要声明</strong></li></ul><h2 id="5-异常遇到继承"><a href="#5-异常遇到继承" class="headerlink" title="5. 异常遇到继承"></a>5. 异常遇到继承</h2><p>父类中的某个 Method 在子类中覆盖时, 必须保证子类中的同名方法<strong>不声明更多的异常抛出</strong><br>子类的构造器中必须声明父类的<strong>全部异常</strong></p>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 基础(十二)  流</title>
      <link href="2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_12/"/>
      <url>2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_12/</url>
      
        <content type="html"><![CDATA[<h2 id="1-流的基础类"><a href="#1-流的基础类" class="headerlink" title="1. 流的基础类"></a>1. 流的基础类</h2><ul><li>InputStream</li><li>OutputStream<br>所有的输入、输出都基于这两个类. 这两个类的操作很有限, 都是<strong>字节</strong>( byte )层面的读写.<br>注: Java 中 char 为两个字节 ( \u0000~\uFFFF ), byte 为一个字节 (-128 ~ 127).</li></ul><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">package</span> hello;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">byte</span>[] buffer = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">1024</span>];</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">           <span class="keyword">int</span> len =  System.in.read(buffer);</span><br><span class="line">           String s = <span class="keyword">new</span> String(buffer,<span class="number">0</span>,len);</span><br><span class="line">           System.out.println(<span class="string">&quot;读到了&quot;</span>+len+<span class="string">&quot;字节&quot;</span>);</span><br><span class="line">            System.out.println(s);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</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><figure class="highlight java"><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">nihao你好</span><br></pre></td></tr></table></figure><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></pre></td><td class="code"><pre><span class="line"><span class="comment">//输出</span></span><br><span class="line">读到了<span class="number">12</span>字节</span><br><span class="line">nihao你好</span><br></pre></td></tr></table></figure><h2 id="2-文件流"><a href="#2-文件流" class="headerlink" title="2. 文件流"></a>2. 文件流</h2><ul><li>FileInputStream</li><li>FileOutputStream</li></ul><p>这两个类可以对文件进行字节层面上的<strong>二进制</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><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">byte</span>[] buffer = <span class="keyword">new</span> <span class="keyword">byte</span>[<span class="number">10</span>];</span><br><span class="line">    <span class="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>;i&lt;<span class="number">10</span>;i++)</span><br><span class="line">    &#123;</span><br><span class="line">        buffer[i] = (<span class="keyword">byte</span>)i;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        FileOutputStream out = <span class="keyword">new</span> FileOutputStream(<span class="string">&quot;a.bat&quot;</span>);</span><br><span class="line">        out.write(buffer);</span><br><span class="line">        out.close();</span><br><span class="line">    &#125; <span class="keyword">catch</span> (FileNotFoundException e) &#123;</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125;<span class="keyword">catch</span> (IOException e)&#123;</span><br><span class="line">        e.printStackTrace();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight java"><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">//打开 a.bat</span></span><br><span class="line"><span class="number">00</span> <span class="number">04</span> <span class="number">46</span> <span class="number">06</span> d8 ef <span class="number">46</span> <span class="number">06</span> <span class="number">00</span> <span class="number">00</span>  </span><br></pre></td></tr></table></figure><h2 id="3-流过滤器"><a href="#3-流过滤器" class="headerlink" title="3. 流过滤器"></a>3. 流过滤器</h2><p>FileInputStream 和 FileOutputStream只能实现字节的读写, 如果需要写(读)入基本类型的数据, 就需要用到流过滤器.</p><ul><li><p>写(读)如<strong>基本数据类型</strong> DataOutputStream ( DataInputStream ) , 这两者是二进制写(读)</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></pre></td><td class="code"><pre><span class="line">DataOutputStream out =</span><br><span class="line"><span class="keyword">new</span> DataOutputStream(</span><br><span class="line">    <span class="comment">//使用缓冲, 避免频繁对硬盘读写</span></span><br><span class="line">    <span class="keyword">new</span> BufferedOutputStream(</span><br><span class="line">        <span class="keyword">new</span> FileOutputStream(<span class="string">&quot;a.bat&quot;</span>)));</span><br><span class="line"><span class="comment">//可以写入 int </span></span><br><span class="line">out.write(<span class="number">123</span>);</span><br><span class="line">DataInputStream in = </span><br><span class="line"><span class="keyword">new</span> DataInputStream(</span><br><span class="line">    <span class="comment">//使用缓冲, 避免频繁对硬盘读写</span></span><br><span class="line">    <span class="keyword">new</span> BufferedInputStream(</span><br><span class="line">        <span class="keyword">new</span> FileInputStream(<span class="string">&quot;a.bat&quot;</span>)));</span><br><span class="line"><span class="comment">//可以读入 int </span></span><br><span class="line"><span class="keyword">int</span> j = in.readInt();</span><br><span class="line">out.close();</span><br></pre></td></tr></table></figure></li></ul><h2 id="4-文本数据-Reader-Writer"><a href="#4-文本数据-Reader-Writer" class="headerlink" title="4. 文本数据 Reader/Writer"></a>4. 文本数据 Reader/Writer</h2><p>若文件是 Unicode 编码的， 可以直接用 Reader/Writer 打开读写， 但是实际情况下并不是所有的文件都是 Unicode ，所以需要借助 Stream 打开文件, 以过滤器的方式输入输出.</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></pre></td><td class="code"><pre><span class="line"><span class="comment">//写入字符</span></span><br><span class="line">PrintWriter pw = <span class="keyword">new</span> PrintWriter(</span><br><span class="line">    <span class="comment">//缓冲</span></span><br><span class="line">    <span class="keyword">new</span> BufferedWriter(</span><br><span class="line">        <span class="comment">//OutputStreamWriter 是字符流到字节流的桥梁</span></span><br><span class="line">        <span class="keyword">new</span> OutputStreamWriter(</span><br><span class="line">            <span class="keyword">new</span> FileOutputStream(<span class="string">&quot;a.txt&quot;</span>)</span><br><span class="line">        )</span><br><span class="line">    )</span><br><span class="line">);</span><br><span class="line">pw.println(<span class="number">123</span>); </span><br><span class="line">pw.printf(<span class="string">&quot;&quot;</span>)<span class="comment">//格式化输出</span></span><br><span class="line">pw.close();</span><br><span class="line"></span><br><span class="line"><span class="comment">//读入字符</span></span><br><span class="line">BufferedReader in = <span class="keyword">new</span> BufferedReader (</span><br><span class="line">    <span class="keyword">new</span> InputStreamReader(</span><br><span class="line">        <span class="keyword">new</span> FileInputStream (<span class="string">&quot;a.txt&quot;</span>))</span><br><span class="line">);</span><br><span class="line">String line;</span><br><span class="line"><span class="keyword">while</span> ((line = in.readLine())!=<span class="keyword">null</span>)&#123;</span><br><span class="line">    System.out.println(line);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>InputStreamReader</strong> 和 <strong>OutputStreamWriter</strong>起到了桥梁的作用, 将字符流和字节流建立了联系. 在他们的构造器中可以添加第二个参数以指定编码方式(如 utf-8 )<br>有更加方便的文件读写: FileReader 和 FileWriter, 但很少用. 使用如下:</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">//读</span></span><br><span class="line">BufferedReader reader = <span class="keyword">new</span> BufferedReader (<span class="keyword">new</span> FilerReader(<span class="string">&quot;a.txt&quot;</span>));</span><br><span class="line">......</span><br><span class="line"><span class="comment">//写</span></span><br><span class="line">BufferedWriter writer = <span class="keyword">new</span> BufferedWriter(<span class="keyword">new</span> FileWriter(<span class="string">&quot;a.txt&quot;</span>)); </span><br></pre></td></tr></table></figure><p>除了以上读取的方式, 当然也可以用 Scanner, 在 InputStream 或者 Reader 的基础上建立一个 Scanner 对象, 就可以从流中的文本解析出各种基本类型.</p><ul><li><p>Stream/Reader/Scanner 的选择</p><p>  <img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/Java_abc_06.assets/6af82e48946153dcbf2593e2e75c78e90fd2c556.webp" alt=""></p></li></ul><h2 id="5-对象序列化"><a href="#5-对象序列化" class="headerlink" title="5. 对象序列化"></a>5. 对象序列化</h2><h3 id="1-步骤"><a href="#1-步骤" class="headerlink" title="1. 步骤"></a>1. <strong>步骤</strong></h3><ol><li>创建 FileOutputStream</li><li>创建 ObjectOutputStream</li><li>写入对象</li><li>关闭 ObjectOutputStream</li></ol><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></pre></td><td class="code"><pre><span class="line">ObjectOutputSream os = <span class="keyword">new</span> ObjectOutputSream(<span class="keyword">new</span> FileOutputStream());</span><br><span class="line">os.writeObject(characterOne);</span><br><span class="line">os.close();</span><br></pre></td></tr></table></figure><h3 id="2-注意事项"><a href="#2-注意事项" class="headerlink" title="2.注意事项"></a>2.注意事项</h3><ul><li>如果想要让类能够序列化, 要实现 Serializable 接口 ( 只声明即可 )</li><li>如果对象的,某个祖先类不可序列化, 那么这个不可序列化的类以及它的子孙的构造函数将会执行, 全部回归初始状态</li><li>静态变量不会被序列化, 而是一直维持原来状态</li><li>使用 transient 关键字来阻止某个变量被序列化, 还原时会自动被赋值为默认值</li></ul>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 基础(七) 以“城堡游戏”为例改良代码(详见源代码)</title>
      <link href="2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_07/"/>
      <url>2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_07/</url>
      
        <content type="html"><![CDATA[<h2 id="1-消除代码复制"><a href="#1-消除代码复制" class="headerlink" title="1. 消除代码复制"></a>1. 消除代码复制</h2><p>在原来的代码中，至少两处用到了相同的提示信息，需要将提示信息放在一个函数 <code>showPrompt()</code> 中来减少重复代码。</p><h2 id="2-封装"><a href="#2-封装" class="headerlink" title="2. 封装"></a>2. 封装</h2><p>封装以降低耦合度。在原来的代码中，Game 类大量使用了 Room 类中的成员，比如得到 currentRoom 的出口，正确的做法是在 Room 类中的 <code>getExits()</code> 以 String 返回出口，而非返回 Room 类的对象；Game 类中 <code>goRoom()</code> 函数也不应该直接操作 Room 类的成员，而应让 Room 类自己返回输入所对应的房间。</p><h2 id="3-可拓展性"><a href="#3-可拓展性" class="headerlink" title="3. 可拓展性"></a>3. 可拓展性</h2><p>在原来的代码中, Room 类中含有 4 个表示出口的 Room 类型对象, 这不是好的做法, 因为这样大大降低了代码的可拓展性, 如果要增加 “up” 或者 “down” 方向的出口, 就会变得十分复杂. 更好的方式是用容器来增加代码的灵活性. 改造后, 只需在 <code>createRoom()</code>中写<code>outside().setExit(&quot;up&quot;, anotherRoom);</code>便可以使 outside 这个房间的 up 方向是 anotherRoom.<br><strong>增加可扩展性:框架+数据</strong></p><ul><li>命令的解析<strong>脱离 if-else</strong></li><li>定义一个 Handler 来处理命令</li><li>用 Hash 表来保存命令和 Handler 之间的关系</li></ul>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 基础(六) Object 类</title>
      <link href="2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_06/"/>
      <url>2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_06/</url>
      
        <content type="html"><![CDATA[<p>几乎在所有的 oop 语言中，都有一个“<strong>根</strong>”的存在。在 Java 中，这个“根”就是 <strong>Object</strong> 类。<br>Object 类中包含有：</p><ul><li><code>toString()</code></li><li><code>equals()</code></li></ul><p>两个方法，前者可以打印对象的信息（可以在子类中具体实现）；后者<strong>判断是否管理着同一个对象</strong> （默认实现为 <code>==</code>） 。如果要实现判断内容是否一致，需要在子类中实现。比如，要实现只要 CD 类中 artist 成员相同，<code>equals()</code>就返回 true，需要这样写：</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="meta">@Override</span></span><br><span class="line"><span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">equals</span><span class="params">(Object obj)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    CD a = (CD)obj;<span class="comment">//造型</span></span><br><span class="line">    <span class="keyword">return</span> artist.equals(a.artist);<span class="comment">//equals判断两者所指向的对象的内容(可以自己实现判断标准)而==判断的是两者的值是否相等(即是否指向同一个对象)</span></span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/Java_abc_06.assets/image-20210513011757424.webp" alt="image-20210513011757424"></p><ul><li><code>equals</code> 比较二者指向对象的内容</li><li><code>==</code> 比较二者是否指向同一地址（管理同一个对象）</li></ul>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据科学基础(一)  随机事件及其概率</title>
      <link href="2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_01/"/>
      <url>2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_01/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/数据科学基础/数据科学基础_01">随机事件及其概率</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_02">随机变量及其分布</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_03">期望和方差</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_04">大数定律与中心极限定理</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_05">数理统计的基本概念</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_06">参数估计</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_07">假设检验</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_08">多维</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_09">回归分析和方差分析</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_10">降维</a></p></div><h2 id="1-1-随机试验与随机事件"><a href="#1-1-随机试验与随机事件" class="headerlink" title="1.1 随机试验与随机事件"></a>1.1 随机试验与随机事件</h2><ul><li><p>随机试验:</p><ul><li>相同条件可重复</li><li>结果不止一个</li><li>无法预测</li></ul></li><li><p>事件：每种结果，随机事件A、B、C.</p></li><li>基本事件: <strong>相对于实验目的不可再分</strong>.</li><li>复合事件: 由基本事件复合.</li></ul><h2 id="1-2-样本空间"><a href="#1-2-样本空间" class="headerlink" title="1.2 样本空间"></a>1.2 样本空间</h2><ul><li>样本空间: 所有基本事件复合, 记作 $\Omega$.</li><li>样本点: $\Omega$ 中的元素 $\omega$.</li></ul><p>以下两种是非随机/极端:</p><ul><li>必然事件: 一定会发生的事件.</li><li>不可能事件: 一定不发生的事件.</li><li>无限可列个: 按某种规律排成一个序列.</li></ul><h2 id="1-3-事件间的关系"><a href="#1-3-事件间的关系" class="headerlink" title="1.3 事件间的关系"></a>1.3 事件间的关系</h2><ul><li>包含</li><li>交( 积 )</li><li>并( 和 )</li><li>差: $A - B = A - AB$</li><li>互不相容事件: $A$ 与 $B$不同时发生</li><li>对立事件: $A + B = \Omega$ 且 $AB = \phi$<br>与互不相容事件的不同:<ul><li>互不相容事件可以有多个, 对立事件只有两个.</li><li>互不相容事件可以均不发生, 对立事件必定发生一个.<br>相关公式: $A-B=A - AB=A\overline{B}$.</li></ul></li><li><p>完备事件组:</p><script type="math/tex; mode=display">A_1, A_2,A_3...A_n 两两不相容, 且 \bigcup_{i=1}^{n} A_i = \Omega</script></li><li><p>运算律<br>(1) 交换律<br>(2) 结合律<br>(3) 分配律<br>(4) 对偶律:</p><ul><li>$\overline{A\cup{B} } = \overline{A}\cap \overline{ {B}}$</li><li>$\overline{A\cap{B} } = \overline{A}\cup \overline{ {B}}$</li></ul></li></ul><h2 id="1-4-频率与概率"><a href="#1-4-频率与概率" class="headerlink" title="1.4 频率与概率"></a>1.4 频率与概率</h2><h3 id="1-4-1-频率"><a href="#1-4-1-频率" class="headerlink" title="1.4.1 频率"></a>1.4.1 频率</h3><h3 id="1-4-2-概率-发生的可能性大小-P-A"><a href="#1-4-2-概率-发生的可能性大小-P-A" class="headerlink" title="1.4.2 概率: 发生的可能性大小: $P(A)$"></a>1.4.2 概率: 发生的可能性大小: $P(A)$</h3><ul><li>性质:<ol><li>规范性: $P(\Omega) = 1$ , $P(\phi) = 0$</li><li>非负性:  $0 \leq P(A) \leq 1$</li><li>可加性</li></ol></li></ul><h2 id="1-5-事件概率"><a href="#1-5-事件概率" class="headerlink" title="1.5 事件概率"></a>1.5 事件概率</h2><h3 id="1-5-1-古典概型"><a href="#1-5-1-古典概型" class="headerlink" title="1.5.1 古典概型"></a>1.5.1 古典概型</h3><script type="math/tex; mode=display">P(A) = \frac{A的有利样本点}{\Omega 中样本总数}=\frac{A中基本事件数}{基本事件数}</script><ul><li><p>性质:</p><ol><li><p>有限可能</p></li><li><p>等可能</p></li><li><p>有限可加性: </p><script type="math/tex; mode=display">A_1, A_2,A_3...A_n 两两不相容,P(A_1+A_2+A_3...+A_n) = \sum_{i=1}^n {P(A_i)}</script></li></ol></li></ul><h3 id="1-5-2-几何概型"><a href="#1-5-2-几何概型" class="headerlink" title="1.5.2 几何概型"></a>1.5.2 几何概型</h3><p>典型问题: 会面问题, 蒲丰投针</p><ul><li>性质:<ol><li>完全可加性:<script type="math/tex">P(\bigcup_{i=1}^{\infty}A_i) = \sum_{i=1}^{\infty}P(A_i)</script></li></ol></li></ul><h2 id="1-6-公理化"><a href="#1-6-公理化" class="headerlink" title="1.6 公理化"></a>1.6 公理化</h2><ol><li>非负性: $0 \leq P(E) \leq 1$</li><li>规范性: $P(\Omega) = 1$</li><li>完全可加性: <script type="math/tex">P(\bigcup_{i=1}^{\infty}A_i) = \sum_{i=1}^{\infty}P(A_i)</script></li></ol><p>由这三条公理可以推出其他定理.<br>定理 1: $P(\phi) = 0$<br>    证明:</p><script type="math/tex; mode=display">\begin{aligned}&P(\Omega) = P(\Omega+\phi) = 1,\\\because &\Omega \cap \phi = \phi,\\\therefore &P(\Omega) = P(\Omega)+P(\phi) = 1,\\&P(\phi) = 0.\end{aligned}</script><p>定理 2:$P(\overline{E}) = 1 - P(E)$<br>证明:</p><script type="math/tex; mode=display">\begin{aligned}&P(\Omega) = P(E\cup\overline{E}),\\&\because E\cup \overline{E}=\phi,\\&\therefore P(\overline{E})+P(E) = 1.\\\end{aligned}</script><p>定理 3: $P(A\cup B) = P(A)+P(B)-P(AB)$<br>证明:</p><script type="math/tex; mode=display">\begin{aligned}  P(A\cup B)  &= P((A-B)+(B-A)+AB)\\            &=P(A-B)+P(B-A)+P(AB),\\            P(A\cup B) + P(AB) &= P(A-B)+P(AB)+P(B-A)+P(AB),\\            P(A\cup B) +P(AB) &= P(A)+P(B).\\\end{aligned}</script><p>补充: $P(A+B+C) = P(A)+P(B)+P(C)-P(AB)-P(C)-P(BC)+P(ABC).$</p><h2 id="1-7-条件概率"><a href="#1-7-条件概率" class="headerlink" title="1.7 条件概率"></a>1.7 条件概率</h2><h3 id="1-7-1-条件概率"><a href="#1-7-1-条件概率" class="headerlink" title="1.7.1 条件概率"></a>1.7.1 条件概率</h3><p>定义: 在样本空间内, $A$,$B$ 两个事件,$ P(B)&gt;0$,在 $B$ 已经发生的条件下 $A$<br>发生的概率, 记作 $P(A|B)$.<br>公式: $P(A|B) = \frac{P(AB)}{P(B)}$. 乘法公式:$P(AB) = P(A|B)P(B)$<br>性质:</p><ul><li>$P(A|B)\leq 0$</li><li>$P(\Omega|B) = 0$</li></ul><h3 id="1-7-2-全概率公式"><a href="#1-7-2-全概率公式" class="headerlink" title="1.7.2 全概率公式"></a>1.7.2 全概率公式</h3><p>定理：<script type="math/tex">A_1,A_2,A_3...A_n</script> 是完备事件组（互不相容且并集为样本空间），且 <script type="math/tex">P(A_i)>0</script> ,则   <script type="math/tex">P(B)=\sum_{i=1}^nP(A_i)P(B|A_i)</script><br>典型问题: 各个厂家的产品各占多少,每个厂家的不合格率也不一样,求总的不合格概率</p><h3 id="1-7-3-贝叶斯公式"><a href="#1-7-3-贝叶斯公式" class="headerlink" title="1.7.3 贝叶斯公式"></a>1.7.3 贝叶斯公式</h3><p>全概率公式是<strong>知道原因推结果</strong>,贝叶斯公式是<strong>知道结果推原因</strong>, 例子: 感冒和肺炎都有可能引起发烧,全概率公式是感冒情况下发烧概率和肺炎情况下发烧概率都已知情况下求总的发烧概率,而贝叶斯公式是已知发烧,求感冒或者肺炎的概率.定理: $A_1,A_2,A_3…A_n$ 是完备事件组,则</p><script type="math/tex; mode=display">P(A_i)>0,P(B)>0,P(A_k|B)=\frac{P(A_k)P(B|A_k)}{\sum_{i=1}^{n}P(A_i)P(B|A_i)}</script><ul><li>$P(A_i)$:先验概率,易算</li><li>$P(A_i|B)$:后验概率,不易算(知道结果,求原因)</li></ul><h2 id="1-8-独立性"><a href="#1-8-独立性" class="headerlink" title="1.8 独立性"></a>1.8 独立性</h2><p><strong>定义</strong>:<br>&emsp;&emsp;事件 A 发生的概率不受事件 B 是否发生的影响.即: $P(A|B) = P(A)$.</p><ul><li>注意:$\phi,\Omega$与任意事件独立.</li></ul><p><strong>定理 1</strong>：$P(AB)=P(A)P(B)$, 则为独立事件.<br><strong>定理 2</strong>:</p><ul><li>$A$与$B$独立, 则 $A$与$\overline{B}$,$\overline{A}$与$B$,$\overline{A}$与$\overline{B}$独立</li><li>$P(A) = 0$或者$P(A)=1$,则$A$与任何事件独立.<ul><li>注意: 概率为零不一定是空集, 概率为1也不一定是全集,比如集合概率模型,落在数轴上某点概率为零,但仍然可以发生.</li></ul></li><li>$E(X+Y)=E(X)+E(Y)$</li><li>$D(X+Y)=D(X)+D(Y)$</li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 概率论 </tag>
            
            <tag> 数学 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据科学基础(二) 随机变量及其分布</title>
      <link href="2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_02/"/>
      <url>2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_02/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/数据科学基础/数据科学基础_01">随机事件及其概率</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_02">随机变量及其分布</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_03">期望和方差</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_04">大数定律与中心极限定理</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_05">数理统计的基本概念</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_06">参数估计</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_07">假设检验</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_08">多维</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_09">回归分析和方差分析</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_10">降维</a></p></div><h2 id="2-1-随机变量"><a href="#2-1-随机变量" class="headerlink" title="2.1 随机变量"></a>2.1 随机变量</h2><p>将样本空间 $\Omega$ 中的每个元素 e 与实数对应起来. </p><ul><li>定义:<br>设随机试验的样本空间为 $S = \{e\}.\space X = X(e)$ 是定义在样本空间的实值单值函数. 称 $X = X(e)$ 为随机变量.</li></ul><h2 id="2-3-离散型随机变量及其分布律"><a href="#2-3-离散型随机变量及其分布律" class="headerlink" title="2.3 离散型随机变量及其分布律"></a>2.3 离散型随机变量及其分布律</h2><ol><li><p>离散型随机变量定义:</p><ul><li>有限个</li><li>无限可列个</li></ul></li><li><p>满足条件:</p><ul><li>$p_k\geq0,k=1,2…$ </li><li>$\sum^n_{k=1}p_k=1$</li></ul></li><li><p><strong>分布律</strong>:</p><script type="math/tex; mode=display"> P\\{X = x_k\\}=p_k,k=1,2...</script><p>也可以用表格:</p><script type="math/tex; mode=display">\begin{array}{|c|c|c|c|c|c|} \hline X & x_{1} & x_{2} & \ldots & x_{n} & \ldots \\ \hline p_{k} & p_{1} & p_{2} & \ldots & p_{n} & \ldots \\ \hline \end{array}</script></li></ol><h2 id="2-4-连续型随机变量及其概率密度函数"><a href="#2-4-连续型随机变量及其概率密度函数" class="headerlink" title="2.4 连续型随机变量及其概率密度函数"></a>2.4 连续型随机变量及其概率密度函数</h2><ol><li>定义:<br>对于非负可积函数$f(x)$,有 </li></ol><script type="math/tex; mode=display">p\\{a\ < x \leq b\\}=\int^{a}_{b}f(x)dx.</script><script type="math/tex; mode=display">p\\{x<X<x+\Delta x\\} \approx f(x) \cdot \Delta x, \Delta x\rightarrow 0</script><ol><li>满足:</li></ol><ul><li>$f(x) \geq 0$ </li><li>$\int^{-\infty}_{\infty}f(x)dx = 1$</li><li>取个别值概率为 0 , 则端点值有没有无所谓. </li></ul><h2 id="2-5-分布函数-对离散-连续均成立"><a href="#2-5-分布函数-对离散-连续均成立" class="headerlink" title="2.5 分布函数(对离散 连续均成立)"></a>2.5 分布函数(对离散 连续均成立)</h2><ul><li><p>定义:<br>$F(x) = P(X \leq x)$,即 $X$ 取值不超过 $x$ 的概率,它是一个普通的实函数</p></li><li><p>性质:</p><ol><li><p>$0\leq F(X) \leq 1, x \in (-\infty,+\infty)$</p></li><li><p>$F(x)$ 不减, 即 $x_1 &lt; x_2 \Rightarrow F(x_1)&lt;F(x_2)$<br>利用这个性质, 有:</p></li></ol><script type="math/tex; mode=display">   \begin{aligned}   \lim_{x \rightarrow +\infty}F(x) = 1\\   \lim_{x \rightarrow -\infty}F(x) = 0\end{aligned}</script><p>可以用来<strong>求参数</strong></p></li></ul><ul><li><p>$F(x)$右连续,且至多有可列个间断点 . 若为离散型, 则 $F(x)$ 右连续, 若为连续性,  则 $F(x)$ 不仅右连续, 还是连续的.<br>以下公式对<strong>离散型和连续性</strong>均有用:</p><script type="math/tex; mode=display">\begin{array}{l}  \text {。} P\\{X \leq a\\}=F(a)\\  。P\\{X>a\\}=1-F(a)\\  。P\\{a<X \leq b\\}=F(b)-F(a)\\  。P\\{X=a\\}=F(a)-F(a-0) \text { 此处的 } 0 \text { 意为无穷小 }\\  。 P\\{a \leq X \leq b\\}=F(b)-F(a-0)\\  。 P\\{X<a\\}=F(a=0)\\  。P\\{X \geq a\\}=1-F(a-0)  \end{array}</script></li></ul><h3 id="2-5-1-离散型的分布函数"><a href="#2-5-1-离散型的分布函数" class="headerlink" title="2.5.1 离散型的分布函数"></a>2.5.1 离散型的分布函数</h3><ul><li>由概率求分布函数:</li></ul><div class="table-container"><table><thead><tr><th>$X$</th><th style="text-align:center">$-2$</th><th style="text-align:center">$0$</th><th style="text-align:center">$1$</th><th style="text-align:center">$3$</th></tr></thead><tbody><tr><td>$P$</td><td style="text-align:center">$\frac{1}{2}$</td><td style="text-align:center">$\frac{1}{4}$</td><td style="text-align:center">$\frac{1}{8}$</td><td style="text-align:center">$\frac{1}{8}$</td></tr></tbody></table></div><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-1619937209762.webp" alt="分段函数" style="zoom:100%;" /><br>由图可见,函数的每一段都是右连续的.</p><ul><li>由分布函数求概率:<br>只需借助 $P\{X=a\}=F(a)-F(a-0)$.</li></ul><h3 id="2-5-2-连续型的分布函数"><a href="#2-5-2-连续型的分布函数" class="headerlink" title="2.5.2 连续型的分布函数"></a>2.5.2 连续型的分布函数</h3><p>$F(x) = P\{X \leq x\}= \int_{-\infty}^{x}{f(x)}dx$<br>两边同时求导可得$F’(x)=f(x)$</p><h2 id="2-6-几种分布"><a href="#2-6-几种分布" class="headerlink" title="2.6 几种分布"></a>2.6 几种分布</h2><h3 id="2-6-1-离散型的分布"><a href="#2-6-1-离散型的分布" class="headerlink" title="2.6.1 离散型的分布"></a>2.6.1 离散型的分布</h3><h4 id="1-0-1分布"><a href="#1-0-1分布" class="headerlink" title="1. 0-1分布"></a>1. 0-1分布</h4><ul><li>分布律</li></ul><div class="table-container"><table><thead><tr><th>$X$</th><th style="text-align:center">$1$</th><th style="text-align:center">$0$</th></tr></thead><tbody><tr><td>$P$</td><td style="text-align:center">$p$</td><td style="text-align:center">$1-p$</td></tr></tbody></table></div><ul><li>特点:<ul><li>只做一次</li><li>结果只有两种: $p\{x=k\}=p^k(1-p)^{1-k}$</li></ul></li><li>期望$E(X)=p$</li><li>方差$D(X)=p-p^2$</li></ul><h4 id="2-几何分布"><a href="#2-几何分布" class="headerlink" title="2. 几何分布"></a>2. 几何分布</h4><p> $A$发生概率为 $p$ 即$P(A) = p$,第 $k$ 次试验<strong>首次发生</strong>, 则前 $k-1$ 次没有发生,<br> $P\{X=k\}= (1-p)^{k-1}p$,$X$~$G(p)$.</p><h4 id="3-二项分布"><a href="#3-二项分布" class="headerlink" title="3. 二项分布"></a>3. 二项分布</h4><ul><li>$P(A) =p$,$n$次试验,发生 $k$ 次的概率是 $P\{X=k\}=C^k_np^k(1-p)^{n-k},k=1,2,3,…,n, X \sim B(n,p)$</li><li>期望$E(X)=np$</li><li>方差$D(X)= np(1-p)$ 推导:因为每次试验都是互相独立的,所以将每次的都加起来</li></ul><h4 id="4-泊松分布"><a href="#4-泊松分布" class="headerlink" title="4. 泊松分布"></a>4. 泊松分布</h4><ul><li>公式: $P\{X=k\}=\frac{\lambda^k}{k!}e^{- \lambda},k=0,1,2,3,…,\lambda&gt;0,X$~$P(\lambda)$</li><li>证明概率和为1:<br>泰勒<script type="math/tex">:e^x=\sum_{k=0}^{\infty}\frac{x^k}{k!},\sum_{k=0}^{\infty}\frac{\lambda^k}{k!}e^{- \lambda}=e^{-\lambda}\sum_{k=0}^{\infty}\frac{\lambda^k}{k!}=e^{-\lambda} \cdot e^\lambda=1.</script></li><li>适用范围:电台呼叫次数,公用设施(等车,摇号)  </li><li>泊松分布近似二项分布:<ul><li>适用范围:$n$ 较大,$p$ 较小, $np$ 适中的时候. 当 $n\rightarrow+\infty$ 时,$\lambda \rightarrow np$.</li></ul></li></ul><p>例题: 银行有 1000 个账户,每户存了 10 万元. 每户提 2 万的概率是 0.006, 则银行应至少准备多少现金,可以有 95% 的概率满足用户需求?<br>设有 $X$ 名用户来取钱,银行要准备 $x$ 万元现金</p><script type="math/tex; mode=display">\begin{aligned}\lambda =np=6\\X\sim B(1000,0.006)\\P\\{2X \leq x\\}\geq 0.95\\\sum_{k=0}^{\frac{x}{2}}\frac{6^k}{k!}e^{-6} \geq 0.95\\\end{aligned}</script><p>查表即可求得 $x/2 \geq 10$</p><h4 id="5-超几何分布"><a href="#5-超几何分布" class="headerlink" title="5. 超几何分布"></a>5. 超几何分布</h4><ul><li><p>定义：一共有 $N$ 个元素, $N_1$ 个属于第一类,$N_2$ 个属于第二类,取 $n$ 个元素, $X$ 代表这 $n$ 个元素中属于第一类的个数.</p><script type="math/tex; mode=display">P\\{X=k\\}= \frac{C_{N_1}^kC_{N_2}^{n-k}}{C^n_N},k=0,1,2,....min\\{n,N_1\\}</script></li><li><p>超几何分布:不放回试验. 但当 $N$ 很大, $n$ 很小的时候, 可近似视为放回抽样, 此时<strong>可以用二项分布近似</strong>. 例子:</p><p>10000 粒种子, 发芽率 99%, 从中取出 10 粒, 有 k 粒发芽的概率:</p><script type="math/tex; mode=display">P\\{X=k\\}=\frac{C_M^{k}C_{10000-M}^{10-k}}{C_{10000}^{10}}\approx C_{10}^k0.99^k0.01^{10-k }</script></li></ul><h3 id="2-6-2-连续型的分布"><a href="#2-6-2-连续型的分布" class="headerlink" title="2.6.2 连续型的分布"></a>2.6.2 连续型的分布</h3><h4 id="1-均匀分布"><a href="#1-均匀分布" class="headerlink" title="1. 均匀分布"></a>1. 均匀分布</h4><ul><li>密度函数满足:<script type="math/tex; mode=display">f(x)=\begin{cases}\frac{1}{b-a},a \leq x \leq b \\0, else\\\end{cases}</script>则 $x$ 服从均匀分布,记作 $x\sim \mathrm U[a,b]$</li></ul><h4 id="2-指数分布"><a href="#2-指数分布" class="headerlink" title="2. 指数分布"></a>2. 指数分布</h4><ul><li>密度函数满足:<script type="math/tex; mode=display">f(x) = \begin{cases}\frac{1}{\theta} e^{-\frac{1}{\theta} x},x \gt 0\\ 0, x \leq 0\\ \end{cases}</script> 其中 $\theta&gt;0$ 时, $X \sim \mathrm {Exp}(\theta)$<ul><li><strong>无记忆性</strong>: 举例说明: 已经买了 10 年的灯泡还能再用 1 年的概率与刚刚买的灯泡能再用一年的概率相等.<script type="math/tex; mode=display">P\\{X>s+t|X>s\\} = P\\{X>t\\}</script>直接按定义求积分可以证明.</li></ul></li></ul><h4 id="3-正态分布"><a href="#3-正态分布" class="headerlink" title="3. 正态分布"></a>3. 正态分布</h4><ul><li><p>密度函数:</p><script type="math/tex; mode=display">\displaystyle \phi(x) = \frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(x-\mu)^2}{2\sigma^2}},-\infty< x <+\infty</script><p>记作</p><script type="math/tex; mode=display">X \sim N(\mu,\sigma^2).</script><p>由 <script type="math/tex">\displaystyle \int_{-\infty}^{+\infty}e^{-x^2}dx=\sqrt{\pi}</script> 可以证明 <script type="math/tex">\displaystyle \int_{-\infty}^{+\infty}\phi(x)dx = 1.</script> </p></li><li><p>分布函数:</p><script type="math/tex; mode=display">\Phi(x)=\frac{1}{\sqrt{2\pi\sigma}}\int_{-\infty}^{x}e^{-\frac{(x-\mu)^2}{2\sigma^2}}dx</script></li><li><p>性质:</p><ol><li><p>$y=\phi(x)$ 是以 $x=\mu$ 为对称轴的钟形曲线. $x = \mu$时, $\phi(x)$ 最大值$\frac{1}{\sqrt{2\pi}\sigma}.$</p></li><li><p>$y=\phi(x)$ 以 $x$ 轴为渐近线. $x=\mu \pm \sigma$ 为拐点.</p></li><li>$\sigma$ 固定,$\mu$ 变化, 图像左右移动;<br>$\mu$ 固定,$\sigma$ 变化, 图像最高点变化.</li></ol><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image.webp" alt="标准正态"/></p></li><li><p><strong>标准正态分布</strong></p><ul><li>$\mu=0,\sigma=1.$</li><li>性质: <ul><li>以 $y$轴为对称轴. 偶函数</li><li>$\Phi_0(-x)=1-\Phi_0(x).$</li></ul></li></ul></li><li><p>举例: 身高体重,受多种因素影响,且每种因素影响都不大.</p><ul><li><p>将一般的正态分布化为标准正态分布:</p><script type="math/tex; mode=display">\begin{aligned}  \phi(x)&=\frac{1}{\sigma}\phi_0(\frac{x-\mu}{\sigma})\\   \Phi(x)&=\Phi_0(\frac{x-\mu}{\sigma})\\\end{aligned}</script><p>做题时可以直接修改要求的 $X$ ,如:<br>$\mu=1,\sigma=2,$则$P\{-2 \leq X \leq 2\}=P\{\frac{-2-1}{2}\leq \frac{X-1}{2} \leq\frac{2-1}{2}\}=\Phi_0(0.5)-\Phi_0(1.5)$</p></li></ul></li><li><p>3 $\sigma$ 准则<br>$P\{|X-\mu|&lt;\sigma\} =0.6826$</p><p>$P\{|X-\mu|&lt;2\sigma\} =0.9545$</p><p>$P\{|X-\mu|&lt;3\sigma\} = 0.9973.$</p></li><li><p>$X\sim N(0,1)$,给定 $\alpha(0&lt;\alpha&lt;1)$,找出 $v_\alpha$ 使得 </p><script type="math/tex; mode=display">p\\{X>v_\alpha\\}=\alpha,v_\alpha \text{为}\alpha \text{分位数}</script></li></ul><h2 id="2-7-随机变量的函数的分布"><a href="#2-7-随机变量的函数的分布" class="headerlink" title="2.7 随机变量的函数的分布"></a>2.7 随机变量的函数的分布</h2><h3 id="2-7-1-离散型"><a href="#2-7-1-离散型" class="headerlink" title="2.7.1 离散型"></a>2.7.1 离散型</h3><ul><li><p>已知 $X$ 服从某分布,求关于 $X$ 的函数 $Y$ 的分布.</p></li><li><p>例子:</p><script type="math/tex; mode=display">\begin{array}{|c|c|c|c|c|}\hline X & -1 & 0 & 1 & 2 \\\hline p_{k} & 0.2 & 0.3 & 0.1 & 0.4 \\\hline\end{array}</script><p>则 $Y=(x-1)^2$ 的分布律为:</p><script type="math/tex; mode=display">\begin{array}{|c|c|c|c|}\hline Y & 0 & 1 & 4 \\\hline p_{k} & 0.1 & 0.7 & 0.2 \\\hline\end{array}</script></li></ul><h3 id="2-7-2-连续型"><a href="#2-7-2-连续型" class="headerlink" title="2.7.2 连续型"></a>2.7.2 连续型</h3><ul><li><p>随机变量 $X$ 具有密度函数 $f_x(x)$ ,求$Y=g(X)$的密度函数.</p></li><li><p>步骤:</p><ol><li>$F_Y(x)\rightarrow F_x(x)$,注意 $F_Y(x) = p\{Y \leq x\},F_X(x) = p\{X \leq x\}$</li><li>两侧同时求导:$f_Y(x) \leftarrow f_X(x)$</li></ol></li><li><p>例子 1:<br>$X$ 概率密度为 $f_X(x)$,求 $Y=3X+2$ 的概率密度.</p><p>解:</p><script type="math/tex; mode=display">\begin{aligned}F_Y(x)&= P\\{Y \leq x\\}=P\\{3X+2 \leq x\\}\\&=P\\{X \leq \frac{x-2}{3}\\}\\&=F_X(\frac{x-2}{3})\\\end{aligned}</script><p>两边同时求导:</p><script type="math/tex; mode=display">\begin{aligned}f_Y(x)&=\frac{1}{3}f_X(\frac{x-2}{3})\\\end{aligned}</script></li><li><p>例子 2:<br>$X\sim N(\mu,\sigma^2),Y=X^2,$ 求 $Y$ 的密度函数.<br>按照上面方法,最后积分即可<br> $Y$ 服从<strong>卡方分布</strong></p></li><li><p><strong>定理</strong></p><ol><li><p>$X$ 服从 $(a,b)$ 内的均匀分布, 则 $Y=kX+c$ 也服从相应区间内的均匀分布.</p><ul><li>当$k&gt;0,(ka+c,kb+c)$</li><li>当$k&lt;0,(kb+c,ka+c)$  <ol><li>$X \sim N(\mu,\sigma^2)$,$Y=aX+b$,则  $Y\sim N(a\mu+b,a^2\sigma^2)$.<br>证明:可以用上面分布函数求积分的方法,也可以用</li></ol></li></ul></li><li><p>若$X$ 的密度函数 $f_X(x)$,$Y=kX+b$,则$f_Y(x)=\frac{1}{|k|}f_x(\frac{x-b}{k})$</p></li></ol></li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 概率论 </tag>
            
            <tag> 数学 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据科学基础(三) 期望和方差</title>
      <link href="2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_03/"/>
      <url>2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_03/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/数据科学基础/数据科学基础_01">随机事件及其概率</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_02">随机变量及其分布</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_03">期望和方差</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_04">大数定律与中心极限定理</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_05">数理统计的基本概念</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_06">参数估计</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_07">假设检验</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_08">多维</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_09">回归分析和方差分析</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_10">降维</a></p></div><h2 id="3-1-数学期望"><a href="#3-1-数学期望" class="headerlink" title="3.1 数学期望"></a>3.1 数学期望</h2><h3 id="3-1-1-离散型数据的数学期望"><a href="#3-1-1-离散型数据的数学期望" class="headerlink" title="3.1.1 离散型数据的数学期望"></a>3.1.1 离散型数据的数学期望</h3><ul><li>$P(X=x<em>k)= p_k,$ 若 $\sum^\infty</em>{k=1}x<em>kp_k$ 绝对收敛,则 $E(X)=\sum^\infty</em>{k=1}x_kp_k$.<br>注意:数学期望不一定均存在.</li></ul><h3 id="3-1-2-连续型数据的数学期望"><a href="#3-1-2-连续型数据的数学期望" class="headerlink" title="3.1.2 连续型数据的数学期望"></a>3.1.2 连续型数据的数学期望</h3><ul><li>$X$ 的密度函数为 $f(x),\int<em>{-\infty}^{\infty}xf(x)dx$ 绝对收敛,则$Ex = \int</em>{-\infty}^{\infty}xf(x)dx$</li></ul><h3 id="3-1-3-随机变量函数的期望"><a href="#3-1-3-随机变量函数的期望" class="headerlink" title="3.1.3 随机变量函数的期望"></a>3.1.3 随机变量函数的期望</h3><p>$Y=g(X)$</p><ul><li>离散 $E(X)=\sum x_i p_i,Y=g(X)$则$E(Y)=\sum g(x_i)p_i$</li></ul><h3 id="3-1-4-期望的性质"><a href="#3-1-4-期望的性质" class="headerlink" title="3.1.4 期望的性质"></a>3.1.4 期望的性质</h3><ul><li>$EC=C$</li><li>$E(C_1X+C_2)=C_1EX+C_2$</li><li>若$X,Y$ 独立,则 $E(XY)=E(X)E(Y)$</li><li>$E(X \pm Y)=EX \pm EY$           </li></ul><h2 id="3-2-方差"><a href="#3-2-方差" class="headerlink" title="3.2 方差"></a>3.2 方差</h2><h3 id="3-2-1-方差的定义"><a href="#3-2-1-方差的定义" class="headerlink" title="3.2.1 方差的定义"></a>3.2.1 方差的定义</h3><ul><li>$DX = E((X-EX)^2)$</li><li>离散型: $DX=\sum(X_k-EK)^2p_k$</li><li>连续型: $DX=\sum_{-\infty}^{+\infty}(x-EX)^2f(x)dx$</li></ul><p>但是一般用 $DX=E(X^2)-(EX)^2$ 计算.</p><h3 id="3-2-2-方差的性质"><a href="#3-2-2-方差的性质" class="headerlink" title="3.2.2 方差的性质"></a>3.2.2 方差的性质</h3><ul><li>$DC=0$</li><li>$D(C_1X+C_2) = C_1^2DX$</li><li>若$X,Y$ <strong>独立</strong> 则$D(X \pm Y) = D(X)+D(Y)$</li></ul><h2 id="3-3-常见分布的期望和方差"><a href="#3-3-常见分布的期望和方差" class="headerlink" title="3.3 常见分布的期望和方差"></a>3.3 常见分布的期望和方差</h2><h3 id="3-3-1-常见离散型的期望与方差"><a href="#3-3-1-常见离散型的期望与方差" class="headerlink" title="3.3.1 常见离散型的期望与方差"></a>3.3.1 常见离散型的期望与方差</h3><h4 id="1-0-1分布"><a href="#1-0-1分布" class="headerlink" title="1. 0-1分布"></a>1. 0-1分布</h4><ul><li>$EX = p$</li><li>$DX=E(X^2)-(EX)^2=p-p^2=p(1-p)$</li></ul><h4 id="2-二项分布"><a href="#2-二项分布" class="headerlink" title="2. 二项分布"></a>2. 二项分布</h4><ul><li><p>期望<br>设</p><script type="math/tex; mode=display">X_i=\begin{cases}  1,\text{the }\,\text{i-th}\,\text{ is}\,\text{ failure }\\  0, \text{the }\,\text{i-th}\,\text{ is}\,\text{ success}\end{cases},</script><p>则$E(X<em>i)=1 \times p+0 \times (1-p)=p,E(X)=E(\sum</em>{i=1}^nXi)=np$</p></li><li><p>方差<br>$DX=D(\sum_{i=1}^nXi)=np(1-p)$ </p></li></ul><h4 id="3-几何分布"><a href="#3-几何分布" class="headerlink" title="3. 几何分布"></a>3. 几何分布</h4><p>$P\{X=k\}= (1-p)^{k-1}p$<br>$EX=\sum<em>{k=1}^nk(1-p)^{k-1}p=\frac{1}{p}$运用级数求和<br>$DX=\sum</em>{k=1}^nk^2(1-p)^{k-1}p=\frac{1-p}{p^2}$,借助$\sum<em>{k=1}^\infty k^2X^{k-1}=\sum</em>{k=1}^\infty k \cdot kX^{k-1}=(\sum<em>{k=1}^\infty  kX^k)’=(X\sum</em>{k=1}^\infty  kX^{k-1})’=(\frac{X}{(1-X)^2})’=\frac{1-x}{x^2}$</p><h4 id="4-泊松分布"><a href="#4-泊松分布" class="headerlink" title="4. 泊松分布"></a>4. 泊松分布</h4><p>$P\{X=k\}=\frac{\lambda^k}{k!}e^{- \lambda},k=0,1,2,3,…,\lambda&gt;0,X$~$P(\lambda)$</p><ul><li>$EX=\sum<em>{k=0}^\infty k\frac{\lambda^k}{k!}e^{- \lambda}=\sum</em>{k=1}^\infty \frac{\lambda^k}{(k-1)!}e^{- \lambda}=\lambda \sum_{k=1}^\infty \frac{\lambda^{k-1}}{(k-1)!}e^{- \lambda}=\lambda \times 1=\lambda$(可以用概率和为1).</li><li>方差 <script type="math/tex; mode=display">\begin{aligned}E(X^2)&=\sum_{k=0}^\infty k^2\frac{\lambda^k}{k!}e^{- \lambda}\\&=\sum_{k=1}^\infty k\frac{\lambda^k}{(k-1)!}e^{- \lambda}\\&=\lambda\sum_{k=1}^\infty \frac{\lambda^{k-1}}{(k-1)!}e^{- \lambda}+\sum_{k=1}^\infty (k-1)\frac{\lambda^k}{(k-1)!}e^{- \lambda}\\&=\lambda+\sum_{k=2}^\infty \frac{\lambda^k}{(k-2)!}e^{- \lambda}\\&=\lambda+\lambda^{2}\sum_{k=2}^\infty \frac{\lambda^{k-2}}{(k-2)!}e^{- \lambda}\\&=\lambda+\lambda^2\\\end{aligned}</script>则<script type="math/tex; mode=display">\begin{aligned}DX=\lambda+\lambda^2-\lambda^2=\lambda\end{aligned}</script></li></ul><h3 id="3-3-2-常见连续型的期望与方差"><a href="#3-3-2-常见连续型的期望与方差" class="headerlink" title="3.3.2 常见连续型的期望与方差"></a>3.3.2 常见连续型的期望与方差</h3><h4 id="1-均匀分布"><a href="#1-均匀分布" class="headerlink" title="1. 均匀分布"></a>1. 均匀分布</h4><ul><li><p>$f(x)=\begin{cases}<br>\frac{1}{b-a},a \leq x \leq b \<br>0, else\<br>\end{cases}$</p></li><li><p>$\begin{aligned}<br>EX=\int_a^bx\frac{1}{b-a}dx=\frac{a+b}{2}\end{aligned}$</p></li><li>$\begin{aligned}E(X^2)=\int_a^bx^{2}\frac{1}{b-a}dx=\frac{b^2+ab+a^2}{3}\end{aligned}$</li></ul><p>  $\begin{aligned}DX=\frac{b^2+ab+a^2}{3}-(\frac{a+b}{2})^2=\frac{(b-a)^2}{12}\end{aligned}$</p><h4 id="2-指数分布"><a href="#2-指数分布" class="headerlink" title="2. 指数分布"></a>2. 指数分布</h4><ul><li>$f(x) = \begin{cases}<br>\frac{1}{ \theta} e^{-\frac{1}{ \theta} x},x \gt 0\<br> 0, x \leq 0\<br>\end{cases}$</li></ul><ul><li><p>期望<br>$\begin{aligned}EX&amp;=\int_{0}^{\infty}x\cdot \frac{1}{ \theta} e^{-\frac{1}{ \theta} x}dx&amp;=\theta\end{aligned}$</p></li><li><p>方差<br>$\begin{aligned}D(X^2)=\int_{0}^{\infty}x^{2}\cdot \frac{1}{ \theta} e^{-\frac{1}{ \theta} x}dx = \theta^{2}\end{aligned}$</p></li></ul><h4 id="3-正态分布"><a href="#3-正态分布" class="headerlink" title="3. 正态分布"></a>3. 正态分布</h4><ul><li><p>$E(X)=\mu,D(X)=\sigma^2$<br>证明:<br>   $Z=\frac{X-\mu}{\sigma}$,则 $Z\sim N(0,1)$</p><p>   $E(Z)=\displaystyle\int_{-\infty}^{+\infty}x\frac{1}{\sqrt{2\pi}}e^{-\frac{x^2}{2}}dx=0$</p><p>   $D(Z)=E(X^2)-(EX)^2=1$   </p><p>   然后$E(X)=E(\sigma Z+\mu)=\mu,D(X)=D(\sigma Z+\mu)=\sigma^2$</p></li></ul><h2 id="3-4-协方差和相关系数"><a href="#3-4-协方差和相关系数" class="headerlink" title="3.4. 协方差和相关系数"></a>3.4. 协方差和相关系数</h2><h3 id="3-4-1-协方差"><a href="#3-4-1-协方差" class="headerlink" title="3.4.1. 协方差"></a>3.4.1. 协方差</h3><p>当随机变量$X,Y$ 独立时, $D(X+Y) = D(X)+D(Y)$.</p><p>当不独立的时候,  $D(X+Y) = E((X+Y)^2)-(E(X+Y))^2$, 化简可以得到定理:</p><script type="math/tex; mode=display">D(X \pm Y) = D(X)+D(Y)\pm 2E((X-EX)(Y-EY)</script><p>其中<strong>协方差</strong> $Cov(X,Y)=E((X-EX)(Y-EY))$</p><p><strong>推论</strong>: $E(XY)-E(X)E(Y)=Cov(X,Y)$</p><p>$Cov(X+Y,Z)=Cov(X,Z)+Cov(Y,Z)$</p><h3 id="3-4-2-相关系数"><a href="#3-4-2-相关系数" class="headerlink" title="3.4.2. 相关系数"></a>3.4.2. 相关系数</h3><script type="math/tex; mode=display">\displaystyle \rho _{X,Y}=\frac{Cov(X,Y)}{\sqrt{D(X)D(Y)}}</script><h3 id="3-5-中心距和原点矩"><a href="#3-5-中心距和原点矩" class="headerlink" title="3.5 中心距和原点矩"></a>3.5 中心距和原点矩</h3><ul><li>$k$ 阶原点矩: $EX^k$. 例:$EX$ 一阶原点矩.</li><li>$k$ 阶中心距: $E((X-EK)^k)$. 例: 一阶中心距:0; 二阶中心矩:$E((X-EX)^2)$,即方差.</li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 概率论 </tag>
            
            <tag> 数学 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据科学基础(四) 大数定律与中心极限定理</title>
      <link href="2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_04/"/>
      <url>2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_04/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/数据科学基础/数据科学基础_01">随机事件及其概率</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_02">随机变量及其分布</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_03">期望和方差</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_04">大数定律与中心极限定理</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_05">数理统计的基本概念</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_06">参数估计</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_07">假设检验</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_08">多维</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_09">回归分析和方差分析</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_10">降维</a></p></div><h2 id="4-1-大数定律"><a href="#4-1-大数定律" class="headerlink" title="4.1 大数定律"></a>4.1 大数定律</h2><ul><li>大量重复实验的平均结果的稳定性.</li></ul><h3 id="4-1-1-马尔可夫不等式"><a href="#4-1-1-马尔可夫不等式" class="headerlink" title="4.1.1. 马尔可夫不等式"></a>4.1.1. 马尔可夫不等式</h3><ul><li><p>$P\{X\geq a\}\leq\displaystyle\frac{EX}{a}$</p></li><li><p>证明:$EX=\displaystyle\int_0^{\infty}xf(x)dx=\int_a^{\infty}xf(x)dx+\int_0^{a}xf(x)dx\geq\int_a^{\infty}xf(x)dx\geq\int_a^{\infty}af(x)dx=a P\{X\geq a\}$</p></li></ul><h3 id="4-1-2-切比雪夫不等式"><a href="#4-1-2-切比雪夫不等式" class="headerlink" title="4.1.2. 切比雪夫不等式"></a>4.1.2. 切比雪夫不等式</h3><ul><li><p>定理: 若 $EX$ 和 $DX$ 均存在, $\forall \epsilon &gt;0$,均有 ${|X-EX|\geq \epsilon } \leq \frac{DX}{\epsilon ^2}$</p><p>证明:</p><script type="math/tex; mode=display">\begin{aligned}\\{|X-EX|\geq \epsilon \\}&=\int_{|X-EX|\geq \epsilon }f(x)dx \\\\&\leq {\int_{|X-EX| \geq \epsilon }\frac{|X-EX|^2}{\epsilon ^2}f(x)dx}\\\\&\leq {\int_{-\infty}^{+\infty}\frac{(X-EX)^2}{\epsilon ^2}f(x)dx}\\ \\&\leq\frac{DX}{\epsilon ^2} \end{aligned}</script></li></ul><h3 id="4-1-3-切比雪夫大数定律"><a href="#4-1-3-切比雪夫大数定律" class="headerlink" title="4.1.3. 切比雪夫大数定律"></a>4.1.3. 切比雪夫大数定律</h3><ul><li>依概率收敛: $X_n \rightarrow a$, $\forall \epsilon &gt;0,∃ N&gt;0$ 使得当 $n&gt;N$ 时,有 $\{|X_n-a| \leq \epsilon \}=1$</li></ul><h4 id="伯努利大数定律"><a href="#伯努利大数定律" class="headerlink" title="伯努利大数定律"></a>伯努利大数定律</h4><ul><li><p>$n$ 重伯努利试验, $A$ 发生了 $m_n$ 次, $P$ 为概率,则 </p><script type="math/tex; mode=display">\displaystyle\lim_{n\rightarrow+\infty}{|\frac{m_n}{n}-P|\leq \epsilon \\}=1</script><p>证明:</p><script type="math/tex; mode=display">\begin{aligned}&m_n\sim B(n,p),Em_n=np,Dm_n=np(1-p),\\&E(\frac{m_n}{n})=p,D(\frac{m_n}{n})=\frac{p(1-p)}{n}\\&1\geq {|\frac{m_n}{n}-P|\leq \epsilon \\}\geq 1-\frac{\frac{p(1-p)}{n}}{\epsilon ^2}\rightarrow1,n\rightarrow+\infty\end{aligned}</script></li></ul><h4 id="切比雪夫大数定律"><a href="#切比雪夫大数定律" class="headerlink" title="切比雪夫大数定律"></a>切比雪夫大数定律</h4><ul><li><p>$X<em>1,…,X_n$ 是<strong>不相关</strong>(没有线性关系)的变量,$EX_i$ 和 $DX_i$ 均存在,且<strong>方差有界</strong>,,$DX_i \leq M$, 则 $\forall\epsilon &gt;0$ ,有$\displaystyle\lim</em>{n\rightarrow\infty}P\{|\frac{1}{n}\displaystyle\sum<em>{i=1}^{n}X_i-\frac{1}{n}\displaystyle\sum</em>{i=1}^{n}EX_i|&lt;\epsilon \}=1$</p><p>证明:</p><script type="math/tex; mode=display">\begin{aligned}  &E(\frac{1}{n}\displaystyle\sum_{i=1}^{n}X_i)=\frac{1}{n}\sum_{i=1}^n(EX_i),\\  &D(\frac{1}{n}\displaystyle\sum_{i=1}^{n}X_i)=\frac{1}{n^2}\sum_{i=1}^n(DX_i)\leq \frac{M}{n}\\  \therefore  &1\geq\lim_{n\rightarrow\infty}{|\frac{1}{n}\displaystyle\sum_{i=1}^{n}X_i-\frac{1}{n}\displaystyle\sum_{i=1}^{n}EX_i|<\epsilon \\} \geq 1-\frac{D\Bigg(\frac{1}{n}\displaystyle\sum_{i=1}^{n}X_i\Bigg)}{\epsilon ^2} \geq 1-\frac{M}{n\epsilon ^2}=1\\  \end{aligned}</script></li></ul><h4 id="辛钦大数定律"><a href="#辛钦大数定律" class="headerlink" title="辛钦大数定律"></a>辛钦大数定律</h4><ul><li><p>$X<em>1,…,X_n$ 是<strong>独立同分布</strong>的变量,$EX_i=\mu$,( 注:<strong>方差无要求</strong> ) , 则 $\forall\epsilon &gt;0$ ,有$$\displaystyle\lim</em>{n\rightarrow\infty}{|\frac{1}{n}\displaystyle\sum_{i=1}^{n}X_i-\mu|&lt;\epsilon }=1$$</p><p>证明: 同样可用切比雪夫不等式.</p></li></ul><h2 id="4-2-中心极限定理"><a href="#4-2-中心极限定理" class="headerlink" title="4.2 中心极限定理"></a>4.2 中心极限定理</h2><ul><li><p>现象由大量相互独立的因素影响, 大量独立同分布的变量和极限分布是正态分布.</p></li><li><p>定理: 随机变量 $X<em>1, X_2,…,X_n$ 独立同分布, 且 $E(X_i)=\mu,D(X_i)=\sigma^2&gt;0(i=1,2,3…),$则随机变量之和$\displaystyle\sum</em>{i=1}^{n}X_i$的标准化变量</p><script type="math/tex; mode=display">Y_n=\frac{\displaystyle\sum_{i=1}^{n}X_i-E(\sum_{i=1}^{n}X_i)}{\displaystyle\sqrt{D(\displaystyle\sum_{i=1}^{n}X_i)}}=\frac{\displaystyle\sum_{i=1}^{n}X_i-n\mu}{\sqrt{n}\sigma}</script><p>的分布函数 $F_n(x)$ 对于任意 x 满足</p><script type="math/tex; mode=display">\begin{aligned}\lim_{n\rightarrow{\infty}}F_n(x)&=\lim_{n\rightarrow{\infty}}P\lbrace\frac{\displaystyle\sum_{i=1}^{n}X_i-n\mu}{\sqrt{n}\sigma}\leq x\\\}\\&=\frac{1}{\sqrt{2\pi}}\int_{-\infty}^{x}e^{-\frac{x^2}{2}}dx=\Phi_0(x)\end{aligned}</script><p>即该标准化变量近似服从标准正态分布:</p><script type="math/tex; mode=display">\frac{\displaystyle\sum_{i=1}^{n}X_i-n\mu}{\sqrt{n}\sigma}\sim N(0,1)</script><p>可以改写成</p><script type="math/tex; mode=display">\frac{\overline{X}-\mu}{\sigma n^{-\frac{1}{2}}}\sim N(0,1)</script><p>或者</p><script type="math/tex; mode=display">\overline{X} \sim N(\mu,\frac{\sigma^2}{n})</script></li><li><p>e.g. 顾客有$100$人,在 $[0,60]$ 内均匀分布,独立,日销售额超 3500 概率为.</p></li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 概率论 </tag>
            
            <tag> 数学 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据科学基础(五) 数理统计的基本概念</title>
      <link href="2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_05/"/>
      <url>2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_05/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/数据科学基础/数据科学基础_01">随机事件及其概率</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_02">随机变量及其分布</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_03">期望和方差</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_04">大数定律与中心极限定理</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_05">数理统计的基本概念</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_06">参数估计</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_07">假设检验</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_08">多维</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_09">回归分析和方差分析</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_10">降维</a></p></div><h2 id="5-1-总体与样本"><a href="#5-1-总体与样本" class="headerlink" title="5.1. 总体与样本"></a>5.1. 总体与样本</h2><h2 id="5-2-常用统计量"><a href="#5-2-常用统计量" class="headerlink" title="5.2. 常用统计量"></a>5.2. 常用统计量</h2><h3 id="定义"><a href="#定义" class="headerlink" title="定义"></a>定义</h3><ul><li><p>样本均值: $\overline{X}=\displaystyle\frac{1}{n}\displaystyle\sum_{i=1}^{n}X_i$</p></li><li><p>修正后的样本方差: $\begin{aligned}S^{2}=\frac{1}{n-1} \sum<em>{i=1}^{n}\left(X</em>{i}-\bar{X}\right)^{2}\end{aligned}$</p></li></ul><h3 id="样本均值和样本方差的性质"><a href="#样本均值和样本方差的性质" class="headerlink" title="样本均值和样本方差的性质"></a>样本均值和样本方差的性质</h3><ul><li>定理: 设总体$X$的均值为$EX=\mu$,方差为$DX=\sigma^2$,样本{$X_1,X_2,\ldots ,X_n$} 来自总体$X$ ,则:<ul><li>$E\overline{X}=\mu$   </li><li>$\displaystyle D\overline{X} = \frac{1}{n}\sigma^2$    </li><li>$ES^2=\sigma^2$</li></ul></li><li><p>前两者证明略. $ES^2=\sigma^2$ 的证明:</p><script type="math/tex; mode=display">\begin{aligned} & \sum_{i=1}^{n}\left(X_{i}-\bar{X}\right)^{2}=\sum_{i=1}^{n}\left[\left(X_{i}-\mu\right)-(\bar{X}-\mu)\right]^{2} \\=& \sum_{i=1}^{n}\left[\left(X_{i}-\mu\right)^{2}-2\left(X_{i}-\mu\right)(\bar{X}-\mu)+(\bar{X}-\mu)^{2}\right] \\=& \sum_{i=1}^{n}\left(X_{i}-\mu\right)^{2}-2(\bar{X}-\mu) \sum_{i=1}^{n}\left(X_{i}-\mu\right)+\sum_{i=1}^{n}(\bar{X}-\mu)^{2} \\=& \sum_{i=1}^{n}\left(X_{i}-\mu\right)^{2}-2(\bar{X}-\mu)\left(\sum_{i=1}^{n} X_{i}-\sum_{i=1}^{n} \mu\right)+n(\bar{X}-\mu)^{2} \\=& \sum_{i=1}^{n}\left(X_{i}-\mu\right)^{2}-2(\bar{X}-\mu)(n \bar{X}-n \mu)+n(\bar{X}-\mu)^{2} \\=& \sum_{i=1}^{n}\left(X_{i}-\mu\right)^{2}-2 n(\bar{X}-\mu)^{2}+n(\bar{X}-\mu)^{2} \\=& \sum_{i=1}^{n}\left(X_{i}-\mu\right)^{2}-n(\bar{X}-\mu)^{2} \end{aligned}</script><p>有:</p><script type="math/tex; mode=display">\begin{aligned} \text {  } & \sum_{i=1}^{n}\left(X_{i}-\bar{X}\right)^{2}=\sum_{i=1}^{n}\left(X_{i}-\mu\right)^{2}-n(\bar{X}-\mu)^{2} \\ & E S^{2}=E\left[\frac{1}{n-1} \sum_{i=1}^{n}\left(X_{i}-\bar{X}\right)^{2}\right] \\ &=\frac{1}{n-1} E\left[\sum_{i=1}^{n}\left(X_{i}-\mu\right)^{2}-n(\bar{X}-\mu)^{2}\right] \\ &=\frac{1}{n-1}\left\{E\left[\sum_{i=1}^{n}\left(X_{i}-\mu\right)^{2}\right]-n E(\bar{X}-\mu)^{2}\right\} \\ &=\frac{1}{n-1}\left[\sum_{i=1}^{n} E\left(X_{i}-\mu\right)^{2}-n D \bar{X}\right] \\ &=\frac{1}{n-1} [ \sum_{i=1}^{n} D X_{i}-n D \bar{X} ] \\ &=\frac{1}{n-1}\left(n \sigma^{2}-n \frac{1}{n} \sigma^{2}\right)=\sigma^{2} \end{aligned}</script></li></ul><h2 id="5-3-抽样分布"><a href="#5-3-抽样分布" class="headerlink" title="5.3. 抽样分布"></a>5.3. 抽样分布</h2><h3 id="5-3-1-三种重要分布"><a href="#5-3-1-三种重要分布" class="headerlink" title="5.3.1. 三种重要分布"></a>5.3.1. 三种重要分布</h3><h4 id="1-卡方分布-chi-2-分布"><a href="#1-卡方分布-chi-2-分布" class="headerlink" title="1. 卡方分布($\chi^2$分布)"></a>1. 卡方分布($\chi^2$分布)</h4><ul><li><p>定理: 设随机变量 $X<em>{1}, X</em>{2}, \ldots, X<em>{n}$ 相互独立,且服从标准正态分布,则他们的平方和 $\chi^{2}=X</em>{1}^{2}+X<em>{2}^{2}+\ldots+X</em>{n}^{2}$ 服从的分布称为<strong>自由度为 $n$ 的卡方分布</strong>.记作: $X \sim \chi^2(n)$.<br>其中自由度表示<strong>独立的随机变量的个数</strong>.</p></li><li><p>密度函数:</p><script type="math/tex; mode=display">f(x)=\left\{\begin{array}{ll}\frac{1}{2^{\frac{n}{2}} \Gamma\left(\frac{n}{2}\right)} e^{-\frac{x}{2}} x^{\frac{n}{2}-1},&x>0 \text {  } \\ 0 &,x \leq 0 \text {}\end{array}\right.</script></li><li><p>结论:若$X \sim \chi^2(n)$ 则:$EX = n, DX = 2n$</p></li><li><p>定理:若$X \sim \chi^2(m)$,$Y \sim \chi^2(n)$,则$X+Y \sim \chi^2{(m+n)}$</p><ul><li><p>推论:</p><ol><li><p>若 $X<em>{i} \sim \chi^{2}\left(n</em>{i}\right), \quad i=1,2, \ldots, n,$  且相互独立, 则 </p><script type="math/tex; mode=display">\left(\sum_{i=1}^{n} X_{i}\right) \sim \chi^{2}\left(\sum_{i=1}^{n} n_{i}\right)</script></li><li><p>若 $X<em>{1}, X</em>{2}, \ldots, X<em>{n}$ 相互独立，同服从于正态分布 $N\left(\mu</em>{i}, \sigma_{i}^{2}\right),$ 则</p></li></ol><script type="math/tex; mode=display">\sum_{i=1}^{n}\left(\frac{X_{i}-\mu_{i}}{\sigma_{i}}\right)^{2} \sim \chi^{2}(n)</script></li></ul></li></ul><h4 id="2-t-分布"><a href="#2-t-分布" class="headerlink" title="2.$t$ 分布"></a>2.$t$ 分布</h4><ul><li>定理:$X \sim N(0,1), Y \sim \chi^{2}(n), X,Y,$ 独立，则 称随机变量</li></ul><script type="math/tex; mode=display">T=\frac{X}{\sqrt{Y} / n}=\frac{X}{\sqrt{Y}} \sqrt{n}</script><p>服从的分布为自由的为 $n$ 的 $t-$ 分布.当自由度很大时,$t$ 分布无限趋近于标准正态分布.</p><ul><li>性质:因为该分布是对称的, $t<em>{1-\alpha}(n)=-t</em>{\alpha}(n)$</li></ul><h4 id="3-F-分布"><a href="#3-F-分布" class="headerlink" title="3. $F$ 分布"></a>3. $F$ 分布</h4><ul><li>定理:若 $X \sim \chi^{2}\left(n<em>{1}\right), Y \sim \chi^{2}\left(n</em>{2}\right), X, Y$ 独立,<br>则 随机变量 $\quad F=\frac{X} / n<em>{1}{\mathbf{Y} / n}</em>{2} \quad$ 所服从的分布为自由度是$(n_1,n_2)$ 的 $F$ 分布,$n_1,n_2$ 分别为第一自由度,第二自由度.</li></ul><h3 id="5-3-2-正态总体下的抽样分布"><a href="#5-3-2-正态总体下的抽样分布" class="headerlink" title="5.3.2. 正态总体下的抽样分布"></a>5.3.2. 正态总体下的抽样分布</h3><ul><li><p>总体是正态分布, 抽样本, 构造统计量的分布.</p></li><li><p><strong>定理:</strong> $X\sim N(\mu , \sigma^2)$ ,$\{X<em>1\ldots X_n\}$ 为样本,则<br>(1) $\bar{X} \sim N(\mu, \frac{\sigma^2}{n})$<br>(2) $\displaystyle \frac{(n-1) S^{2}}{\sigma^{2}}=\frac{1}{\sigma^{2}} \sum</em>{i=1}^{n}\left(X_{i}-\bar{X}\right)^{2} \sim \chi ^{2}(n-1)$ 证明较复杂,略<br>(3) $\overline{X}$ 与 $S^2$ 独立</p></li><li><p><strong>定理:</strong> (前提与上面的相同)<br>(1) $\displaystyle \sum^{n}<em>{i=1}(\frac{X_i-\mu}{\sigma})^2= \frac{1}{\sigma^{2}} \sum</em>{i=1}^{n}\left(X_{i}-\mu\right)^{2} \sim \chi ^{2}(n)$ 上面的自由度为 $n-1$ 下面的为 $n$ ,可借助”多一个方程,自由未知量少一个来理解”<br>(2) $\displaystyle\frac{\bar{X}-\mu}{S} \sqrt{n} \sim t(n-1)$</p><p>证明:</p><script type="math/tex; mode=display">\begin{aligned} &\displaystyle\frac{\bar{X}-\mu}{\sigma/\sqrt{n}}\sim N(0,1)...①,\\&\frac{(n-1) S^{2}}{\sigma^{2}}\sim\chi^2(n-1)...② \\ \therefore &\frac{①}{\sqrt{② /(n-1)}}=\displaystyle\frac{\bar{X}-\mu}{S} \sqrt{n} \sim t(n-1)\end{aligned}</script><ul><li><p><strong>定理:</strong>   两个正态总体 $X\sim N(\mu_1,\sigma_1^2),Y\sim N(\mu_2,\sigma_2^2),X$ 取了$n_1$ 个,$Y$ 取了 $n_2$ 个,$\bar{X},\bar{Y},S_1^2,S_2^2$,则</p><ol><li>$\displaystyle\bar{X}-\bar{Y} \sim N\left(\mu<em>{1}-\mu</em>{2}, \frac{\sigma^2<em>{1}}{n</em>{1}}+\frac{\sigma<em>{2}^2}{n</em>{2}}\right)$ </li><li>$\displaystyle\frac{S<em>{1}^{2} / \sigma</em>{1}^{2}}{S<em>{2}^{2} / \sigma</em>{2}^{2}} \sim F\left(n<em>{1}-1 , n</em>{2}-1\right)$</li></ol></li></ul></li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 概率论 </tag>
            
            <tag> 数学 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据科学基础(七) 假设检验</title>
      <link href="2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_07/"/>
      <url>2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_07/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/数据科学基础/数据科学基础_01">随机事件及其概率</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_02">随机变量及其分布</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_03">期望和方差</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_04">大数定律与中心极限定理</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_05">数理统计的基本概念</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_06">参数估计</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_07">假设检验</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_08">多维</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_09">回归分析和方差分析</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_10">降维</a></p></div><h2 id="7-1-假设检验"><a href="#7-1-假设检验" class="headerlink" title="7.1.  假设检验"></a>7.1.  假设检验</h2><h3 id="7-1-1-假设检验问题"><a href="#7-1-1-假设检验问题" class="headerlink" title="7.1.1. 假设检验问题"></a>7.1.1. 假设检验问题</h3><ul><li><strong>参数估计</strong>:讨论如何根据样本得到总体分布所含参数的优良估计.</li><li><strong>假设检验</strong>:讨论怎样在样本的基础上观察上面所得到的估计值与真实值之间在统计意义上相拟合,从而做出一个有较大把握的结论.</li><li>例子: 设菜厂生产一种灯管，其寿命X $\sim \mathrm{N}(\mu, 40000),$ 从过去较长一段 时间的生产情况看，灯管的平均寿命为 1500 小时，现在使用了新工艺后，在所生产的灯管中抽取25只，测得的平均寿命为1675 小时，问：采用新工艺后，灯管的寿命是否有显著提高?<br>为了判别新产品的寿命是否显著提高,提出两个假设:<ul><li>原假设 $H_0:$<ul><li>新产品的寿命 $\mu=1500$</li><li>接受 $H_0:$ 新产品寿命没有提高</li></ul></li><li>备择假设 $H_1:$<ul><li>新产品的寿命 $\mu &gt; 1500$</li><li>拒绝 $H_0:$(接受$H_1$) 新产品的寿命有所提高.</li></ul></li><li><strong>注意</strong>:一般情况下,将希望成立的假设设为 $H_1$ ,将其否定形式设为 $H_0$</li></ul></li><li>假设检验问题的处理方法<ol><li>作出参数或者分布的假设.</li><li>根据样本值选择接受还是拒绝所作假设的结论.</li></ol></li></ul><h3 id="7-1-2-基本概念"><a href="#7-1-2-基本概念" class="headerlink" title="7.1.2. 基本概念"></a>7.1.2. 基本概念</h3><ul><li>假设: 对总体分布的各种论断<ul><li>参数假设: 对总体分布中参数的假设</li><li>非参数假设: 不是关于总体分布中的参数的假设(如对分布的假设)</li></ul></li><li>假设检验: 判断假设是否成立<ul><li>参数假设检验</li><li>非参数假设检验</li></ul></li><li>假设检验问题<ul><li>过程<ul><li>对总体分布中的某些参数或对总体分布的类型做某种假设.</li><li>根据样本值做出接受还是拒绝所作假设的结论.</li></ul></li><li>分类<ul><li>只提出一个假设,<strong>显著性检验问题</strong>.</li><li>提出两个假设($H_0,H_1$),且两者必居其一,则称其中一个为<strong>基本假设</strong>,另一个为它的<strong>对立假设</strong>.</li></ul></li></ul></li></ul><h3 id="7-1-3-基本思想"><a href="#7-1-3-基本思想" class="headerlink" title="7.1.3 基本思想"></a>7.1.3 基本思想</h3><ul><li>由样本构造用于检验 $H_0$ 的<strong>检验统计量</strong> $T$, 并且当 $H_0$ 成立的时候, $T$ 的分布已知.</li><li><strong>检验法则</strong>的确定<ul><li>$P\{|T| \geq {k}\} = \alpha$ 是一个小概率事件.若 $H_0$ 为真, 几乎不可能发生.</li><li>若 $|T| \geq {k}$, 拒绝原假设 $H_0$,此时 $T$ 的取值范围被称为<strong>拒绝域</strong>.拒绝域的边界点为<strong>临界点</strong>.</li><li>若 $|T| &lt; {k}$, 接受原假设 $H_0. $</li></ul></li><li>一般步骤<ul><li>第一步 根据问题的要求提出原假设 $H<em>{0}$ 和备择假没 $H</em>{1}$</li><li>第二步 选取检验统计量 $T\left({X<em>{1}, X</em>{2}, \ldots, X<em>{n}}\right),$ 在 $H</em>{0}$ 成立的情形下确定 其分布.</li><li>第三步 对于给定的显著性水平 $\alpha$,找到 $H_{0}$ 的拒绝域 $W$ 和接受域.</li><li>第四步 根据样本值 $\left(x<em>{1}, x</em>{2}, \ldots, x<em>{n}\right)$ 求出检验统计值 $T,$ 如果 $\left(x</em>{1}, x<em>{2}, \ldots, x</em>{n}\right) \in \mathrm{W}\left(\right.$ 小概率事件发生了), 则拒绝 $\mathrm{H}<em>{0},$ 否则接受 $\mathrm{H}</em>{0}$</li></ul></li><li><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image.webp"></li><li><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image (1).webp"></li><li><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image (2).webp"  ></li></ul><h3 id="7-1-4-假设检验中的两类错误"><a href="#7-1-4-假设检验中的两类错误" class="headerlink" title="7.1.4. 假设检验中的两类错误"></a>7.1.4. 假设检验中的两类错误</h3><ul><li>第一类错误: 弃真<ul><li>$P\{ 拒绝 H_0|H_0 为真\}=\alpha$</li></ul></li><li>第二类错误: 取伪<ul><li>$P\{ 接受 H_0|H_0 为假 \}=\beta$</li></ul></li></ul><h2 id="7-2-参数假设检验"><a href="#7-2-参数假设检验" class="headerlink" title="7.2. 参数假设检验"></a>7.2. 参数假设检验</h2><h3 id="7-2-1-单总体-Z-检验"><a href="#7-2-1-单总体-Z-检验" class="headerlink" title="7.2.1 单总体 Z 检验"></a>7.2.1 单总体 Z 检验</h3><p>(1) 建立于均值的备择假设和原假设,选定合适的显著性水平$\alpha$。<br>(2)建立检验统计量乙,满足Z $\sim \mathrm{N}(0,1),$ 根据样本数据计算检验统计量数值Z。<br>(3)根据检验统计量数值 Z 和显著性水平$\alpha$,计算拒绝域。<br>(4)根据样本是否落入拒绝域作出判断, 有需要可以进一步输出 p 值(比样本观察更极端的概率)。</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210502232014077.webp" alt="image-20210502232014077" style="zoom:80%;" /></p><p>例题:</p><p>一种机床加工的零件尺寸绝对平均误差为1.35mm。生产厂家现采用一种新的<br>行加工以期进一一步降低误差。为检验新机床加工的零件平均误差与旧机床相比<br>是否有显著降机床进尺寸的平均误差与旧机床相比是否有显著降低?<br>(a=0.01)尺寸的平均误差与旧机床相比是否有显著降低?($\alpha$=0.01) </p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210502232100827.webp" alt="image-20210502232100827" style="zoom:80%;" /></p><p>解：<br>建立假设： $\quad H<em>{0}: \mu \geq 1.35, H</em>{1}: \mu&lt;1.35$<br>$\bar{x}=1.3152, s=0.365749, n=50,$ 计算检验统计量:</p><script type="math/tex; mode=display">z=\frac{1.3152-1.35}{0.365749 / \sqrt{50}}=-2.6061<-z_{0.01}=-2.33</script><p>结论:拒绝 $\mathrm{H}_{0^{\circ}}$ 新机床加工的零件尺寸的平均误差与旧机床相比有显著降低。<br>计算p值</p><script type="math/tex; mode=display">\text { p= } \Phi(-2.6061)=1-\Phi(2.6061)=0.004579<\alpha=0.01</script><p>根据p值和 我们可以得到同样的结论：拒绝H $_{0}$ 。</p><p><strong>PS</strong>: 这道题中样本总体方差是未知的, 本来应该用 t 检验, 但是在样本容量大于 30 的时候可以用 Z 检验代替 t 检验, 所以此处直接用样本方差代替了总体方差.</p><h3 id="7-2-2-双总体Z检验"><a href="#7-2-2-双总体Z检验" class="headerlink" title="7.2.2. 双总体Z检验"></a>7.2.2. 双总体Z检验</h3><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210502232152116.webp" alt="image-20210502232152116" style="zoom:80%;" /></p><p>1.检验条件: 两个总体近似服从正态分布且两总体方差$\sigma_1^2 ,\sigma_2^2$ 均已知, 则构造的统计量$Z = \frac{(\bar{X}-\bar{Y})-\delta}{\sqrt{\sigma_1^2/n_1+\sigma_2^2/n_2}}\sim N(0,1)$</p><p>2.检验条件：两个总体不服从正态分布，但来自两总体的样本的容量较大 $\left(n<em>{1}, n</em>{2} \geqslant 30\right)<em>{\circ}$ 则我们构造检验统计量Z如下: $\quad Z=\frac{(\bar{X}-\bar{Y})-\delta}{\sqrt{S</em>{1}^{2} / n<em>{1}+S</em>{2}^{2} / n_{2}}} \sim \mathrm{N}(0,1)$</p><h3 id="7-2-3-单总体-t-检验"><a href="#7-2-3-单总体-t-检验" class="headerlink" title="7.2.3. 单总体 t 检验"></a>7.2.3. 单总体 t 检验</h3><p>t检验的基本步骤：<br>(1)建立关于均值的备择假设和原假设，选定合适的显著性水平$\alpha$。<br>(2)建立检验统计量t,满足t $\sim \mathrm{t}\left(n^{\prime}\right),$ 根据样本数据计算检验统计量数值t。<br>(3) 根据检验统计量数值t和显著性水平$\alpha$,计算拒绝域。<br>(4) 根据样本是否落入拒绝域作出判断，如有需要可以进一步输出值。</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210502232429194.webp" alt="image-20210502232429194" style="zoom:67%;" /></p><h3 id="7-2-4-双总体-t-检验"><a href="#7-2-4-双总体-t-检验" class="headerlink" title="7.2.4.双总体 t 检验"></a>7.2.4.双总体 t 检验</h3><p>公式参照参数估计</p><h3 id="7-2-5-卡方检验"><a href="#7-2-5-卡方检验" class="headerlink" title="7.2.5. 卡方检验"></a>7.2.5. 卡方检验</h3><p>$\chi^{2}$ 检验的基本步骤：<br>（1) 进立关于方差的备择假设和原假设, 选定合适的显著性水平 $\alpha_{\circ}$<br>(2) 建立检验统计量 $\chi^{2},$ 满足 $\chi^{2} \sim \chi^{2}\left(n^{\prime}\right)^{1},$ 根据样本数据计算检验统计量数值 $\chi^{2}$ 。<br>(3) 根据检验统计量数值 $\chi^{2}$ 和显著性水平 $\alpha,$ 计算拒绝域。<br>(4) 根据样本是否落入拒绝域作出判断, 如有需要可以进一步输出 $p$ 值。</p><script type="math/tex; mode=display">\chi^{2}=\frac{(n-1) S^{2}}{\sigma_{0}^{2}} \sim \chi^{2}(n-1)</script><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210502232345279.webp" alt="image-20210502232345279" style="zoom:80%;" /></p><p>例题: 生产的某型号电池，其寿命服从方差 $\sigma^2=5000$ 的正态分布.随机取26个电池，测出样本方差为 $\mathrm{s}^{2}=9200,$ 问能否推断波动较以往显著变化 $(\alpha=0.02)$ ?</p><h3 id="7-2-6-F检验"><a href="#7-2-6-F检验" class="headerlink" title="7.2.6. F检验"></a>7.2.6. F检验</h3><p>原理与上面的类似, 公式参照参数估计</p><h2 id="7-3-非参数假设检验"><a href="#7-3-非参数假设检验" class="headerlink" title="7.3. 非参数假设检验"></a>7.3. 非参数假设检验</h2><h3 id="7-3-1-符号检验"><a href="#7-3-1-符号检验" class="headerlink" title="7.3.1 符号检验"></a>7.3.1 符号检验</h3><p>例: 某地 16 座预售楼盘均价如下表 ( 单位: 元/平方米 )</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210502232502347.webp" alt="image-20210502232502347" style="zoom:80%;" /></p><p>判断楼盘价格与媒体公布的 7900元/平方米是否相符($\alpha = 0.05$)</p><p>若用 $t$ 检验来做, 是无法拒绝原假设 $H_0: \mu = 7900$ 的, 但是样本中只有 3 个大于 7900, 此时用平均值并不能很好地衡量总体, 因此考虑用中位数.</p><p>建立假设:</p><script type="math/tex; mode=display">H_0:M_e = 7900, H_1: M_e\ne 7900</script><p>$Mc$ 为总体中位数, $n<em>{+} , n</em>-$ 分别为大于小于 $7900$ 样本的个数. $H<em>0$ 若为真,  $n</em>+ , n_-$</p><p>近似相等, 即$n<em>+$ 不能太大也不能太小. 因此对 $n</em>+$ 进行检验:</p><p>$n<em>{+}=\sum</em>{i=1}^{n} Y<em>{i}.$ 中 $Y</em>{i} \sim B(1, p), n<em>{+} \sim B(n, p), p=P\{X</em>{i} \geq M_{e}\}$, 做如下假设:</p><script type="math/tex; mode=display">H_{0}: p=0.5, H_{1}: p \neq 0.5</script><p>抽到样本 $n_{+} =3 $ 甚至更为极端的概率为:  </p><script type="math/tex; mode=display">B(3 ; 16,0.5)=\sum_{i=0}^{3} C_{16}^{i}(0.5)^{i}(0.5)^{16-i}=0.0213</script><p>则 p 值就是 0.0213, 由$\mathrm {p} = 0.0213&lt;\alpha = 0.05$, 拒绝原假设, 认为总体中心与 7900 在统计意义上存在显著差异.</p><h3 id="7-3-2-秩和检验"><a href="#7-3-2-秩和检验" class="headerlink" title="7.3.2 秩和检验"></a>7.3.2 秩和检验</h3><p>两个连续性总体的密度函数至多只差一个平移. 秩和检验可以用于判断两个样本是否来自同一总体.</p><p>各项假设:</p><script type="math/tex; mode=display">\begin{aligned}H_0: \mu_1 = \mu_2,H_1: \mu_1<\mu_2\\H_0: \mu_1 = \mu_2,H_1: \mu_1\neq\mu_2\\H_0: \mu_1 = \mu_2,H_1: \mu_1>\mu_2\\\end{aligned}</script><p>步骤( 以双边检验为例 ):</p><ul><li><p>将两个样本的观察值按从小到大排序, 求出每个观察值的秩. (总是假定样本容量 $n_1 \leq n_2$)</p></li><li><p>将属于第 1 个样本的总体的秩总和记为 $R_1$ ,其余观察值的秩记为 $R_2$.</p></li><li><p>考虑统计量 $R_1$ , 查表得 $C_U(\frac \alpha 2)$ 和 $C_L(\frac \alpha 2)$ , 则拒绝域为 $R_1\leq C_U(\frac \alpha 2)$ 或者 $R_1\geq C_L(\frac \alpha 2)$</p></li></ul><p>*若 $n_1,n_2 \geq 10$, 当 $H_0$ 为真的时候, 近似地有:</p><script type="math/tex; mode=display">R_1 \sim N(\mu_{R_1},\sigma^2_{R_1}).</script><p>可以采用 $Z$ 检验.</p><h3 id="7-3-3-偏度峰度检验"><a href="#7-3-3-偏度峰度检验" class="headerlink" title="7.3.3. 偏度峰度检验"></a>7.3.3. 偏度峰度检验</h3><h3 id="7-3-4-卡方拟合优度检验"><a href="#7-3-4-卡方拟合优度检验" class="headerlink" title="7.3.4.卡方拟合优度检验"></a>7.3.4.卡方拟合优度检验</h3><p>判断一组样本是否服从某种分布, 可进行卡方拟合优度检验, 首先 当然需要设置$H_0,H_1$.</p><script type="math/tex; mode=display">\chi^2 = \sum^k_{i=1}\frac{(O_i-T_i)^2}{T_i} \sim \chi^2{(n-1)}</script><p>其中, 将样本分为 $k$ 个组, $T_i$是每组的理论频数, $T_i=nP_i$, $P_i$ 是每组的理论频率, $O_i$ 是每组观测的频数</p><p>如果理论分布有 $r$ 个位置参数用估计量代替, 则$n-&gt; \infty, \chi^2\sim \chi^2(k-r-1)$</p>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 概率论 </tag>
            
            <tag> 数学 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 基础(五) 继承(以实现一个存放 CD 、DVD 的 Database 为例)</title>
      <link href="2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_05/"/>
      <url>2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_05/</url>
      
        <content type="html"><![CDATA[<p>在 Database.java 文件中实现了一个 Database 的类，其中含有 ArrayList<Item> 类型的成员变量 list 来存放数据。此外还有对 list 进行增添和遍历的<code>add(Item newItem)</code>和<code>list()</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><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//Database.java</span></span><br><span class="line"><span class="keyword">package</span> database;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Database</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> ArrayList&lt;Item&gt; list = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">add</span><span class="params">(Item newItem)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        list.add(newItem);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">list</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">for</span>(Item item:list)</span><br><span class="line">        item.print();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] arg)</span> </span>&#123;</span><br><span class="line">    Database db = <span class="keyword">new</span> Database();</span><br><span class="line">    db.add(<span class="keyword">new</span> CD(<span class="string">&quot;123&quot;</span>,<span class="string">&quot;123&quot;</span>,<span class="number">123</span>,<span class="number">123</span>,<span class="string">&quot;123&quot;</span>));</span><br><span class="line">    db.list();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Item 作为父类，仅含有最基础的成员变量和成员函数。</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></pre></td><td class="code"><pre><span class="line"><span class="comment">//Item.java</span></span><br><span class="line"><span class="keyword">package</span> database;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Item</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> String title;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> playingTime;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">boolean</span> gotit = <span class="keyword">false</span>;</span><br><span class="line">    <span class="keyword">private</span> String comment;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Item</span><span class="params">(String title, <span class="keyword">int</span> playingTime, String comment)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.title = title;</span><br><span class="line">        <span class="keyword">this</span>.playingTime = playingTime;</span><br><span class="line">        <span class="keyword">this</span>.comment = comment;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">print</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        System.out.print(title);</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>CD 是由 Item 派生的一个类，在 Item 基础上增添了很多属性，并且重写了<code>print()</code>方法。在 Database 类中调用<code>item.print()</code>方法时，若子类重写了该方法，只会调用子类中的。<br><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="comment">//CD.java</span></span><br><span class="line"><span class="keyword">package</span> database;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">CD</span> <span class="keyword">extends</span> <span class="title">Item</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> String artist;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> numofTracks;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">print</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        System.out.print(<span class="string">&quot;CD:&quot;</span>);</span><br><span class="line">        <span class="keyword">super</span>.print();</span><br><span class="line">        System.out.println(artist);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">CD</span><span class="params">(String title, String artist, <span class="keyword">int</span> numofTracks, <span class="keyword">int</span> playingTime, String comment)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(title, playingTime, comment);</span><br><span class="line">        <span class="keyword">this</span>.artist = artist;</span><br><span class="line">        <span class="keyword">this</span>.numofTracks = numofTracks;</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><h2 id="子类继承了什么"><a href="#子类继承了什么" class="headerlink" title="子类继承了什么"></a>子类继承了什么</h2><p>父类中 <strong>private</strong> 属性的<strong>只有自己</strong>可以访问，<strong>protected</strong> 属性的还可供<strong>子类和同一个包内的其他类访问</strong>。</p><p>对于父类中的变量，可以通过将其设为 protected 从而在子类的构造器中对其进行初始化，然而更好的方法是变量属于哪一个类，就用哪一个类的构造器初始化，此时可以借助子类的<code>super()</code>方法传递给父类构造器。初始化的顺序为：1. 父类构造（若子类中未给<code>super()</code>参数或者未调用<code>super()</code>，则自动调用父类默认构造器；若给了<code>super()</code>参数，调用父类对应的构造器）； 2. 定义初始化； 3. 子类构造。</p><h2 id="子类和父类复杂的关系"><a href="#子类和父类复杂的关系" class="headerlink" title="子类和父类复杂的关系"></a>子类和父类复杂的关系</h2><p>若子类与父类含有同名的成员变量，在子类中父类的变量会被隐藏。而父类的函数中处理的还是父类的变量。使用<code>super.f()</code>可以<strong>调用父类中的<code>f()</code>函数</strong>。</p><p><strong>重写</strong>（ Override ）不同于重载（ Overload ），它是父类中某个方法的重新实现而不是拓展。在重写的方法之前加上 <code>@Override</code>可以让编译器帮助检查。</p><h3 id="子类和子类型"><a href="#子类和子类型" class="headerlink" title="子类和子类型"></a>子类和子类型</h3><ul><li>类定义了类型</li><li>子类定义了子类型</li><li>子类的对象可以被<strong>当作父类的对象</strong>来使用<ul><li>赋值给父类的变量</li><li>传递给需要父类对象的函数</li><li>放进存放父类对象的容器里</li></ul></li></ul><h3 id="多态变量"><a href="#多态变量" class="headerlink" title="多态变量"></a>多态变量</h3><ul><li>Java 的对象变量是<strong>多态</strong>的，它们能保存不止一种类型的对象</li><li>它们可以保存的是声明类型的对象，或声明类型的子类的对象</li><li>当把子类的对象赋给父类的变量的时候，就发生了<strong>向上造型</strong>，发生向上造型之后，尽管变量是父类类型的，但调用的仍然是子类的方法（如上述存放 Item 类型容器进行 for-each 循环，并调用 <code>print()</code> 方法时，调用的是子类中重写的方法而非父类的方法）。<br>注：向下造型并非任何时候都不可行，唯一可行的情况是父类型变量实际管理的对象是该子类型的。</li><li>若函数需要一个 Animal 类型参数的 ArrayList，那么只能传入 <code>ArrayList&lt;Animal&gt;</code>而不能是<code>ArrayList&lt;Dog&gt;</code>，否则就只能把函数的声明改为  <figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> &lt;T extends Animal&gt; <span class="function"><span class="keyword">void</span> <span class="title">takeThing</span> <span class="params">(ArrayList&lt;T&gt; list)</span></span></span><br></pre></td></tr></table></figure>  或者  <figure class="highlight java"><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="keyword">public</span> <span class="keyword">void</span> <span class="title">takeThing</span> <span class="params">(ArrayList&lt;？ extends Animal&gt; list)</span></span></span><br></pre></td></tr></table></figure>  注：C++ 实现这个很复杂，可以用 C++ 20 的新内容实现：  <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"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="keyword">concept</span> Another = (std::is_base_of&lt;Animal, T&gt;::value);</span><br><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">bark</span><span class="params">(vector&lt;T*&gt; something)</span> <span class="keyword">requires</span> Another&lt;T&gt;</span>&#123;&#125;</span><br></pre></td></tr></table></figure></li></ul>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据科学基础(九) 回归分析和方差分析</title>
      <link href="2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_09/"/>
      <url>2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_09/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/数据科学基础/数据科学基础_01">随机事件及其概率</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_02">随机变量及其分布</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_03">期望和方差</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_04">大数定律与中心极限定理</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_05">数理统计的基本概念</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_06">参数估计</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_07">假设检验</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_08">多维</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_09">回归分析和方差分析</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_10">降维</a></p></div><h2 id="9-1-回归分析"><a href="#9-1-回归分析" class="headerlink" title="9.1 回归分析"></a>9.1 回归分析</h2><h3 id="9-1-1-相关性分析"><a href="#9-1-1-相关性分析" class="headerlink" title="9.1.1 相关性分析"></a>9.1.1 相关性分析</h3><ul><li><p>皮尔逊 (Pearson) 相关系数.</p><script type="math/tex; mode=display">r=\frac{1}{n-1}\sum_{i=1}^{n}\frac{(X_i-\bar X)(Y_i-\bar Y)}{s_Xs_Y}</script><p>$\bar X,\bar Y$ 为样本均值, $s_x,s_y$ 是样本方差.</p><ul><li>Pearson 相关系数用于度量两个随机变量 $X,Y$ 的<strong>线性关系</strong>. 可近似估计 $\rho$ .</li><li>取值范围: $[-1,1]$ , 绝对值越接近 1 , 则线性关系越强.</li><li>对称性.</li><li>原样本经过线性变换不影响 $r$ 值.</li><li>不描述因果关系.</li></ul></li><li><p>对相关系数 $r$ 进行显著性检验</p><script type="math/tex; mode=display">H_0:\rho = 0, H_1:\rho\neq 0</script><p>构造统计量:</p><script type="math/tex; mode=display">\begin{aligned}\\  t&=\frac{r}{S_r}\sim t(n-2), S_r = \sqrt{\frac {1-r^2}{n-2} }  \end{aligned}</script><p>若原假设成立, $t$ 值应小, 所以拒绝域为 $|t| &gt; t_{\frac \alpha 2}(n-2)$.</p></li><li><p>斯皮尔曼( Spearman ) 相关系数:</p><p>将原始数据根据其在总体数据中的平均降序位置分配一个等级 ( rank ), 这些等级变量之间的 Pearson 相关系数就是 Spearman 相关系数.</p><p>例子:</p><div style="text-align:center"><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210502235007093.webp" alt="image-20210502235007093" style="zoom:67%;" /></div><p>根据右边表格, 按照下面公式计算 (皮尔逊相关系数展开就是这个):</p><script type="math/tex; mode=display">r_{}=\frac{\sum x_{i} y_{i}-\frac{\left(\sum x_{i}\right)\left(\sum y_{i}\right)}{n}}{\sqrt{\sum x_{i}^{2}-\frac{\left(\sum x_{i}\right)^{2}}{n}} \sqrt{\sum y_{i}^{2}-\frac{\left(\sum y_{i}\right)^{2}}{n}}}</script></li></ul><h3 id="9-1-2-一元线性回归分析"><a href="#9-1-2-一元线性回归分析" class="headerlink" title="9.1.2 一元线性回归分析"></a>9.1.2 一元线性回归分析</h3><h4 id="概述"><a href="#概述" class="headerlink" title="概述"></a>概述</h4><p>对从总体 <script type="math/tex">(x, Y)</script> 中抽取的一个样本 <script type="math/tex">\left(x_{1}, Y_{1}\right),\left(x_{2}, Y_{2}\right), \ldots,\left(x_{n}, Y_{n}\right)</script><br>一元线性回归模型：</p><div style="text-align:center"><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210502235759134.webp" alt="image-20210502235759134" style="zoom:67%;" /></div><p>根据样本估计 $\beta_0,\beta_1$, 记作 $\hat \beta_0,\hat\beta_1$, 称为 $y$ 关于 $x$ 的一元线性回归</p><script type="math/tex; mode=display">\hat y = \hat \beta_0+ \hat \beta_1 x</script><p>一元线性回归要解决的问题</p><ul><li>参数估计<ul><li><script type="math/tex">\beta_{0}, \beta_{1}</script> 的估计</li><li>$\sigma^{2}$ 的估计</li></ul></li><li>参数检验及模型应用<ul><li>线性假设的显著性检验</li><li>回归系数 <script type="math/tex">\beta_1</script> 的置信区间</li><li>Y 的点估计</li></ul></li></ul><h4 id="参数估计"><a href="#参数估计" class="headerlink" title="参数估计"></a>参数估计</h4><ul><li><p>$\beta_0,\beta_1$ 的估计 (采用最小二乘法)</p><p>求 <script type="math/tex">\hat \beta_0,\hat \beta_1</script> 使  <script type="math/tex">\displaystyle Q\left(\hat{\beta}_{0}, \hat{\beta}_{1}\right)=\min _{\alpha,\space \beta} Q\left(\beta_{0}, \beta_{1}\right)</script>.</p><p>其中 <script type="math/tex">Q(\beta_{0},\beta_1)</script> 是偏差平方和 <script type="math/tex">\displaystyle \sum_{i=1}^{n}\left(y_{i}-\beta_{0}-\beta_{1} x_{i}\right)^{2}</script>.</p><p>求导令导数为零:</p><script type="math/tex; mode=display">\begin{aligned}\frac{\partial Q}{\partial \beta_{0}} &=-2 \sum_{i=1}^{n}\left(y_{i}-\beta_{0}-\beta_{1} x_{i}\right)=0 \\\frac{\partial Q}{\partial \beta_{1}} &=-2 \sum_{i=1}^{n}\left(y_{i}-\beta_{0}-\beta_{1} x_{i}\right) x_{i}=0\end{aligned}</script><p>整理一下, 得到正规方程系数行列式:</p><script type="math/tex; mode=display">\begin{aligned}n \beta_{0}&+\left(\sum_{i=1}^{n} x_{i}\right) \beta_{1}=\sum_{i=1}^{n} y_{i} \\\left(\sum_{i=1}^{n} x_{i}\right) \beta_{0}&+\left(\sum_{i=1}^{n} x_{i}^{2}\right) \beta_{1}=\sum_{i=1}^{n} x_{i} y_{i}\end{aligned}</script><p>记:</p><script type="math/tex; mode=display">\begin{aligned}&\bar{y}=\frac{1}{n} \sum_{i} y_{i}, \bar{x}=\frac{1}{n} \sum_{i} x_{i},& s_{x x}=\sum_{i}\left(x_{i}-\bar{x}\right)^{2} \\&s_{x y}=\sum_{i}\left(x_{i}-\bar{x}\right)\left(y_{i}-\bar{y}\right), &s_{yy                                                                                                                                                                                                                                                                                            }=\sum_{i}\left(y_{i}-\bar{y}\right)^{2}\end{aligned}</script><p>可以由正规方程系数行列式得到等式:</p><script type="math/tex; mode=display">\begin{array}{l}\hat{\beta}_{0}+\bar{x} \hat{\beta}_{1}=\bar{y} \\s_{x x} \hat{\beta}_{1}=s_{x y}\end{array}</script><p>则 $\beta_0,\beta_1 $ 的最小二乘估计为</p><script type="math/tex; mode=display">\begin{aligned}\hat{\beta}_{0}=\bar{y}-\bar{x} \hat{\beta}_{1}\\\hat{\beta}_{1}=s_{x y} / s_{x x}\end{aligned}</script></li><li><p>误差 $\sigma^2$ 的估计</p><p><strong>残差</strong>: $e_i = y_i-\hat y_i$, 残差 $e_i$ 是 $\varepsilon_i$ 的估计.</p><p>由于 $D(\varepsilon_i) = E(\varepsilon_i^2) = \sigma^2$</p><p>想到用<strong>残差平方和</strong>估计随机误差项的方差, 经计算, $\sigma^2$ 的无偏估计为:</p><script type="math/tex; mode=display">s^2 = \frac 1 {n-2} \sum_{i=1}^{n}(y_i-\hat y_i)^2</script></li></ul><h2 id="9-2-方差分析"><a href="#9-2-方差分析" class="headerlink" title="9.2 方差分析"></a>9.2 方差分析</h2><h3 id="9-2-1-单因素方差分析"><a href="#9-2-1-单因素方差分析" class="headerlink" title="9.2.1 单因素方差分析"></a>9.2.1 单因素方差分析</h3><h4 id="1-检验假设"><a href="#1-检验假设" class="headerlink" title="1.  检验假设"></a>1.  检验假设</h4><p>用于推断两个或两个以上总体均值是否有差异的显著性检验.</p><ul><li>在方差分析中, 把所考察的试验结果称为<strong>试验指标</strong>.</li><li>对试验指标产生影响的原因称为<strong>因素</strong>.</li><li>因素的各个不同状态称为<strong>水平</strong>.</li></ul><p>对于样本:</p><div style="text-align:center"><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210503000648946.webp" alt="image-20210503000648946" style="zoom:67%;" /></div><p>各个样本间是独立的, 则</p><div style="text-align:center"><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210503000737757.webp" alt="image-20210503000737757" style="zoom:67%;" /></div><p>记</p><script type="math/tex; mode=display">\sum_{i=1}^{r} n_{i}=n, \bar{X}_{i \bullet}=\frac{1}{n_{i}} \sum_{j=1}^{n_{i}} X_{i j}, \bar{X}=\frac{1}{n} \sum_{i=1}^{r} \sum_{j=1}^{n_{i}} X_{i j}</script><p>检验假设:</p><script type="math/tex; mode=display">\begin{aligned}\\&H_o: \mu_1=\mu_2=...=\mu_r\\&H_1: \mu_1,\mu_2...\mu_r \,\text{imperfect}\, \text{equality}\end{aligned}</script><p>假设检验采用的方法: 平方和分解:</p><ul><li><strong>总偏差平方和 $S_T$:</strong> <script type="math/tex">\displaystyle S_T =\sum_{i=1}^{r}\sum_{j=1}^{n_i}(X_{ij}-\bar{X})^2</script></li><li><strong>效应平方和:$S_A$:</strong> <script type="math/tex">\displaystyle S_A=\sum_{i=1}^{r}n_i(\bar X_{i\bullet}-\bar{X})^2</script></li><li><strong>误差平方和$S_E$:</strong> <script type="math/tex">\displaystyle S_E = \sum_{i=1}^{r}\sum_{j=1}^{n_i}(X_{ij}-\bar X_{i\bullet})^2</script></li></ul><p>定理:</p><ol><li><p>$S_T = S_A+S_E$</p></li><li><p>$\frac{S_{E}}{\sigma^{2}} \sim \chi^{2}(n-r)$</p><p>证明:</p><script type="math/tex; mode=display">\begin{aligned}\\\frac{(n_i-1)\cdot\frac{\sum_{j=1}^{n_i}(X_{ij}-\bar X_{i\bullet})^2}{n_i-1}}{\sigma^2}\sim \chi^2(n_i-1)\end{aligned}</script><p>卡方分布可以叠加</p></li><li><script type="math/tex; mode=display">\begin{array}{l}S_{A} \text { 与 } S_{E} \text { 相互独立, 当 } H_{0} \text { 成立时, } \frac{S_{A}}{\sigma^{2}} \sim \chi^{2}(r-1) \text { , 此时, }\\F=\frac{S_{A} /(r-1)}{S_{E} /(n-r)} \sim F(r-1, n-r), \text { 因为当拒绝原假设时 }\\S_{A} \text { 会偏大, 所以当 } F \geq F_{\alpha}(r-1, n-r)\end{array}</script></li></ol><p>单因素试验方差分析表:<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image9.webp" style="zoom:100%;" alt="单因素试验方差分析表"/></p><p>例: 保险公司为了解某一险种在四个不同地区索赔额情况是否存在差异。搜集了这四个不同地区一年的索赔额情况记录如表所示. 试判断在四个不同地区索赔额有无显著的差异?</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image (19).webp" style="zoom:100%;" alt=""/></p><ul><li><p>索赔额差异来源于两个方面:</p><ul><li>地区之间的差异</li><li>同一地区内的随机因素</li></ul></li><li><p>因素: 地区</p></li><li><p>水平: 四个不同的地区</p></li><li><p>最终的方差分析表:</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img//image (29).webp" style="zoom:100%;" /></p></li></ul><h4 id="2-未知参数的估计"><a href="#2-未知参数的估计" class="headerlink" title="2.  未知参数的估计"></a>2.  未知参数的估计</h4><ul><li><script type="math/tex">\sigma^2的无偏估计为\displaystyle \hat \sigma=\frac {S_E} {n-r}</script>.  </li><li><script type="math/tex">\mu_i的无偏估计为\displaystyle \hat{\mu}_i={\bar {X}_{i\bullet}},i=1,2,\cdots,n_i</script>.  </li></ul><h4 id="3-比较-在部分相等的情况-比较的方法有两个"><a href="#3-比较-在部分相等的情况-比较的方法有两个" class="headerlink" title="3. 比较 在部分相等的情况, 比较的方法有两个"></a>3. 比较 在<strong>部分相等</strong>的情况, 比较的方法有两个</h4><ul><li><p>作 $\mu_i - \mu_j(i \ne j)$ 的区间估计</p><div style="text-align:center"><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210503001132577.webp" alt="image-20210503001132577" style="zoom:50%;" /></div><p>求得置信区间, 若置信区间包含零, 则认为没有显著差异.</p></li><li><p>做 <script type="math/tex">H_0: \mu_i = \mu_j, H_1:\mu_i\ne \mu_j</script> 的假设检验</p><p>构造检验统计量 <script type="math/tex">\displaystyle t_{i j}=\frac{\bar{X}_{i \bullet}-\bar{X}_{j \bullet}}{\sqrt{M S_{E}\left(1 / n_{i}+1 / n_{j}\right)}} ,</script></p><p>原假设成立时, <script type="math/tex">\displaystyle t_{i j} \sim t(n-r),</script></p><p>拒绝域 $|t<em>{ij}|\geq t</em>{\alpha/2}(n-r)$</p></li></ul><h3 id="9-2-2-双因素试验的方差分析"><a href="#9-2-2-双因素试验的方差分析" class="headerlink" title="9.2.2 双因素试验的方差分析"></a>9.2.2 双因素试验的方差分析</h3><p>略</p><h3 id="9-2-3-双因素试验的方差分析"><a href="#9-2-3-双因素试验的方差分析" class="headerlink" title="9.2.3 双因素试验的方差分析"></a>9.2.3 双因素试验的方差分析</h3><p>略</p><h2 id="9-3-正交试验设计"><a href="#9-3-正交试验设计" class="headerlink" title="9.3 正交试验设计"></a>9.3 正交试验设计</h2><h3 id="极差分析"><a href="#极差分析" class="headerlink" title="极差分析"></a>极差分析</h3><p>仅有一个例子</p><div style="text-align:center"><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210503001402429.webp" alt="image-20210503001402429" style="zoom:67%;" /></div><p>$A,B,C$ 下每个单元格内容为该因素的水平.</p><div style="text-align:center"><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210503001443516.webp" alt="image-20210503001443516" style="zoom:50%;" /></div><p>找到所有该因素对应水平下的试验指标, 求和填入. 可知 $A$ 因素影响最为显著, $C$ 最不显著. 最佳组合为 $A:3, B:1, C:1$</p>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 概率论 </tag>
            
            <tag> 数学 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据科学基础(十) 降维</title>
      <link href="2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_10/"/>
      <url>2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_10/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/数据科学基础/数据科学基础_01">随机事件及其概率</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_02">随机变量及其分布</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_03">期望和方差</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_04">大数定律与中心极限定理</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_05">数理统计的基本概念</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_06">参数估计</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_07">假设检验</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_08">多维</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_09">回归分析和方差分析</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_10">降维</a></p></div><h2 id="10-1-主成分分析（PCA"><a href="#10-1-主成分分析（PCA" class="headerlink" title="10.1 主成分分析（PCA)"></a>10.1 主成分分析（PCA)</h2><p>不懂线性代数, 下面这些参考了一些 PCA 的说明, 但我总觉得某些解释的不是很严谨.</p><h4 id="目标"><a href="#目标" class="headerlink" title="目标"></a>目标</h4><p>PCA 常用于高维数据的降维,可用于提取数据的主要特征分量.</p><p>对于原始数据矩阵 </p><script type="math/tex; mode=display">A=\begin{bmatrix} x_{11} &x_{12}  & \cdots & x_{1n}\\ x_{21} &x_{22}  & \cdots & x_{2n}\\\vdots & \vdots  & \cdots &\vdots \\ x_{r1} &x_{r2}  & \cdots & x_{rn}\\\end{bmatrix}</script><p>其中, 列向量<script type="math/tex">(x_{1i},x_{2i},\cdots,x_{ri})^T</script> 为 $n$ 个样本中的一个. $r$ 行表示 $r$ 个维度.</p><p>对该矩阵进行中心化,得到中心化矩阵 $X$</p><div style="text-align:center"><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_10.assets/image-20210503001820524.webp alt="image-20210503001820524" style="zoom:67%;" /></div><p> X 中心化后, 样本点的中心点即原点, 寻找点分散程度最大的方向, 即让这些点投影后的分散程度最大.</p><div style="text-align:center"><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/数据科学基础_10.assets/8fc21d1f6638e0ef2f83a4d16b6f30b6c04e756e.gif" title="如图所示" style="zoom:100%;" /></div><h4 id="向量内积"><a href="#向量内积" class="headerlink" title="向量内积"></a>向量内积</h4><p>若 $\alpha = (a_1, a_2,\cdots,a_n)^T,\beta = (b_1,b_2,\cdots,b_n)^T$ , 则内积可表示为:</p><script type="math/tex; mode=display">\alpha \cdot \beta= \alpha^T \beta =a_1b_1+a_2b_2+ \cdots +a_nb_n</script><p>内积的几何意义:</p><script type="math/tex; mode=display">A\cdot B = |A|\cdot|B|\cos\theta</script><p>当 $B$ 为单位向量$(\sqrt{b_1^2+b_2^2+\cdots+b_n^2}=1)$时, 两个向量的内积就是 $A$ 在这个单位向量方向投影的长度.</p><h4 id="散度"><a href="#散度" class="headerlink" title="散度"></a>散度</h4><p>分散程度可以用方差或者协方差衡量,  回顾一下方差和协方差:</p><script type="math/tex; mode=display">\begin{aligned}\\&&s^{2}(X)&=\frac{\sum_{i=1}^{n}\left(X_{i}-\bar{X}\right)^{2}}{n-1}\\&&{Cov}(X, Y)&=\frac{\sum_{i=1}^{n}\left(X_{i}-\bar{X}\right)\left(Y_{i}-\bar{Y}\right)}{n-1}\\\end{aligned}</script><p>构建协方差矩阵 $C$:</p><script type="math/tex; mode=display">C=\begin{bmatrix}cov(X_1, X_1) & cov(X_1, X_2) &\cdots &cov(X_1, X_n) \\cov(X_2, X_1) &cov(X_2, X_2) & \cdots&cov(X_2, X_n) \\\vdots & \vdots  & \cdots &\vdots \\cov(X_n, X_1) & cov(X_n, X_2) &\cdots &cov(X_n, X_n)\end{bmatrix}</script><p>由上述公式可知协方差矩阵 $C$ 的每一项为:</p><script type="math/tex; mode=display">C_{ij} =cov(X_i,X_j) = \frac{\sum_{k=1}^{n}\left(X_{ik}-\bar{X_i}\right)\left(X_{jk}-\bar{X_j}\right)}{n-1}= \frac {X_{i1}X_{j1}+X_{i2}X_{j2}+\cdots+X_{in}X_{jn}}{n-1}</script><p>刚好是 $Z$ 中的第 $i$ 行与第 $j$ 行做内积再除以 $n-1$ 的结果.</p><p>则协方差矩阵与中心化后的原始数据矩阵存在以下关联:</p><script type="math/tex; mode=display">C=\frac 1 {n-1} XX^T</script><p>设要投影的单位向量为 $V$ , 则得到的投影后的值为$V\cdot Z=V^TZ$, 投影后的方差为:</p><script type="math/tex; mode=display">s^2 = \frac 1 {n-1} \sum_{i=1}^n (V^T \alpha_i- \frac 1 n\sum _{i=1} ^n(V^T\alpha_i))^2=\frac 1 {n-1} \sum_{i=1}^n V^T \alpha_i \alpha_i^TV = \frac{1}{n-1} V^TZZ^TV=V^TCV</script><p>其中 $\alpha_i$ 为 $Z$ 中的第 $i$ 列.</p><h4 id="拉格朗日乘数法"><a href="#拉格朗日乘数法" class="headerlink" title="拉格朗日乘数法"></a>拉格朗日乘数法</h4><p>求 $S^2$ 最大值,限制条件: $||V||=1$</p><p>构建方程:</p><script type="math/tex; mode=display">F(V) = V^TCV-\lambda(V^TV-1)①</script><p>对 $V$ 求导数得:</p><script type="math/tex; mode=display">\frac {\partial F}{\partial V} = 2CV-2\lambda V</script><p>令导数为零得:</p><script type="math/tex; mode=display">CV=\lambda V ②</script><p>这个形式是特征值和特征向量的定义式, $C$ 是 $n$ 阶方阵, $V$ 是特征向量, $\lambda$ 是特征值. 求特征值和特征向量需要进行特征值分解 (EVD) , 这是线性代数的内容.</p><h4 id="降维"><a href="#降维" class="headerlink" title="降维"></a>降维</h4><p>将 ② 代入 ① 得 $ s^2 = F(V) = \lambda$, 特征值 $λ$  越大, 则散度越大.</p><p>将所有的特征值降序排列, 根据最终需要的维度 $d$ 来选择前 $d$ 大的特征值对应的特征向量, 并将特征向量单位化后组成矩阵 $W = (w_1,w_2,\cdots,w_d)$, 由于每个点都可以视为在各个特征向量方向上的投影组成, 则最终降维后:</p><script type="math/tex; mode=display">X_{d\times n} = W^TX = \begin{pmatrix}w1^T\\w2^T\\\vdots\\w_d^T\\\end{pmatrix}X</script><p>矩阵 $X_{d\times n}$ 的第一行称为第一主成分, 以此类推.</p><p><strong>关于 d 的选择:</strong></p><p>按 czy 课件来的话, 要求 <script type="math/tex">\displaystyle \frac{ \sum _{i=1}^d \lambda_i}{\sum_{i=1}^p \lambda_i}\geq 0.85</script> , p 为得到的特征值的数量.</p>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 概率论 </tag>
            
            <tag> 数学 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构 合集</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_00/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_00/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-bullhorn"></i><p>📖 本笔记参考计算机组织结构课程的课件, 由于时间关系, 后期缺失部分内容</p></div><div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><h2 id="系统概述"><a href="#系统概述" class="headerlink" title="系统概述"></a>系统概述</h2><ul><li>指令和数据在关机时储存在外存中，开机后存储在内存</li><li>冯·诺依曼计算机工作方式的基本特点是<strong>按地址访问指令并自动按序执行程序</strong></li><li>指令由操作码和地址码组成</li><li>控制器通过执行指令来控制整个机器运行</li><li>注意对<strong>存储器</strong>来讲,例如 $32K\times16位$的存储器意为,该存储器为 16 位可寻址, 共有 32K 个存储单元, 若对于芯片来讲,不能得到什么信息</li></ul><p><strong>结构</strong> ( Architecture ) ：对程序员可见</p><ul><li>对于程序的逻辑执行有着直接影响 </li><li>例如: 该计main算机有无乘法器</li></ul><p><strong>组织</strong> ( Organization ) : 对程序员不可见</p><ul><li>操作单元及其相互联系</li><li>该计算机中的乘法器是如何实现的</li></ul><p><strong>Stored Program</strong>: 意为将<strong>指令</strong>、<strong>数据</strong>以<strong>二进制</strong>的方式存储到<strong>主存</strong>中.<br>摩尔定律： 每 18 个月，晶体管的数量增加一倍，价格下降一半，性能提高一倍</p><h2 id="冯·诺依曼体系结构："><a href="#冯·诺依曼体系结构：" class="headerlink" title="冯·诺依曼体系结构："></a>冯·诺依曼体系结构：</h2><ul><li>输入输出设备</li><li>存储（内存）</li><li>控制器: 指挥信息的处理.</li><li>处理器: 实际处理信息</li></ul><p>只有在涉及到存储器相关时,用到的是 $2^n$, 其他任何时候都是 $10^n$, 比如<strong>时钟频率</strong>.</p><h2 id="衡量-CPU-性能的依据"><a href="#衡量-CPU-性能的依据" class="headerlink" title="衡量 CPU 性能的依据"></a>衡量 CPU 性能的依据</h2><script type="math/tex; mode=display">CPI =\frac{ \sum_{i=1}^n(CPI_i\times I_i)}{I_C},I_C = \sum_{i=1}^n I_i,</script><script type="math/tex; mode=display">I_i 为某种指令的条数, CPI_i为某种指令的时钟周期数, I_C 为总的指令数,</script><script type="math/tex; mode=display"> 则 CPI 为每条指令的平均时钟周期数,</script><script type="math/tex; mode=display">T = I_C \times CPI \times t, t 为时钟周期,</script><script type="math/tex; mode=display">每秒钟总指令数 = \frac{f}{CPI} = \frac{I_C}{T}.</script><h2 id="存储"><a href="#存储" class="headerlink" title="存储"></a>存储</h2><ul><li>cache：主存速度较慢，如果所有指令都从 memory 中取，速度很慢。从 cache 中读取会很快。</li><li>memory hierarchy：</li><li>buffer：<ul><li>i/o输入效率比处理慢，提高效率</li><li>减小丢失和等待</li></ul></li></ul><ol><li>三要素：容量、存取时间和价格，关系如下：<ul><li>存取时间越短，平均每位的花费就越大</li><li>存储容量越大，平均每位的花费就越小</li><li>存储容量越大，存取时间就越长</li></ul></li><li>为了满足容量要求、性能要求，也使每位的价格低，采用了 memory hierarchy 的结构。随着层次的下降：<ul><li>每位价格下降</li><li>容量增大</li><li>存取时间变长</li><li>处理器访问存储器的频率变少</li></ul></li></ol><h2 id="中断："><a href="#中断：" class="headerlink" title="中断："></a>中断：</h2><p>有了中断，处理器可以在进行 I/O 操作时执行其他指令。提供中断主要是为了提高效率，因为大部分外设的速度都比处理器慢得多，假如没有中断，每次 I/O 操作后处理器都会进入空闲状态直到外设跟上进度。</p><ul><li><p>默认开</p></li><li><p>程序可以在执行指令的时候执行另一条指令</p></li><li><iframe frameborder="0" style="width:100%;height:280px;" src="https://app.diagrams.net/?lightbox=1&highlight=0000ff&edit=_blank&layers=1&nav=1#R3VjLcpswFP0abTO8H0uwcbtoZzqTRZOlYlRQByNGyLGdr68EEkKGpHk4dpJMJiMdriR07rmPANzFZv%2BNwqb8SXJUAcfK98BdAsfxHZf%2FFcChB1wn7oGC4ryHbA1c4wckQUuiW5yj1jBkhFQMNya4JnWN1szAIKVkZ5r9IZV5agMLNAGu17Caor9xzsoejZxQ498RLkp1sh3I%2B22gMpY3aUuYk90IcjPgLighrB9t9gtUCe4UL%2F261SNPhxejqGbPWRCo92AHdTmU87vKKaGsJAWpYZVpNKVkW%2BdI7GDxmbb5QUjDQZuDfxFjB%2Bk4uGWEQyXbVPIp2mN2Mxrfiq2ufDlb7uXO3eSgJjWjh5vxZLRKTPWybqbW9fcTl3qUIgm1ZEvX0sr3pKwgLZA084PBQVzYiGwQP4fbUFRBhu%2FN%2FaGUWDHYaS%2FwgXTEvFPU4few2spdQeaDdAEiSwySEETpxG%2FaK4LWXYkZum5gd6Edj0LTA%2FIARBnaP83L9L4yaCMpnZ2OAFvJuhypX0nsLYwE9uS6H1Smr5RbMCO38FxyC2blFq1AHIDMA2kk5CYHXIABiJcgscUg4pIMu0cpSLwnJGm9ryTVAqXJS0jU%2BeISDWckGp1JosFUW2ckVxN6O%2Bbz5OS%2BgUi59BfB%2FBQdD74ZD%2F6RzntfykXaGwml8DAya4RB%2B%2Fgxnu3NHbN62VtpKfTna2EMhDxLK%2BFFWpoP5XfPdq%2Fi8Y%2FB95Al%2FyODV3CvkoRRSniZiEXPkkWiavCSMVM4ArgR5aC%2Ba5uBzAsWEtc3FX3WQuJ%2BIv2%2BtQA8L0PY9vskrsAzz3Fflrjc0yaunsxJ8CSu6rpWIPG7wUJElBiEILFkZ5YsOyQQg0uHjx9fsA%2FzZ1icMCT6W%2F5rd0kpE0%2BPOeO3ZyYxsMJFzcdrzgKiHBAc4TWsEvlgg%2FO8j0bU4gd4120lGJc65Pv6KfCXYi8egG0fi6fi3DI5j6ecBzOUO6egfO4fiCnlXKxBR3k3Tab98mejfNL3ROejfK7Qzqk8tkESyaTBE8hnp%2Fw4s9hnVPl8ej7ubb4c5Z51OcrjGcqHLxO%2BqIvpV6R80v%2B8G%2BV8qj829z2L%2FmLvZv8A"></iframe></li></ul><h2 id="多个中断处理的方式："><a href="#多个中断处理的方式：" class="headerlink" title="多个中断处理的方式："></a>多个中断处理的方式：</h2><ul><li>顺序处理</li><li>根据优先级决定优先处理的指令</li></ul><h2 id="总线"><a href="#总线" class="headerlink" title="总线"></a>总线</h2><p>总线：各部分信息共享，包含<strong>地址线、数据线和控制线</strong>，前两者可以复用。</p>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(一) 数的二进制表示</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_01/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_01/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><h2 id="二进制补码整数"><a href="#二进制补码整数" class="headerlink" title="二进制补码整数"></a>二进制补码整数</h2><p>补数：负数加模得补数，负数的补数和负数的绝对值相加等于模</p><h2 id="浮点数"><a href="#浮点数" class="headerlink" title="浮点数"></a>浮点数</h2><p>小密 大稀疏</p>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 基础(九) 数据与表现分离( 以&quot;细胞自动机&quot;为例)</title>
      <link href="2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_09/"/>
      <url>2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_09/</url>
      
        <content type="html"><![CDATA[<p>Field 维护了一个二维数组， 里面存放着 Cell，Field 可以往二维数组中存放、取出指定 Cell, 获得指定 Cell 的邻居; Cell 可以用 <code>draw()</code> 绘制自己； view 只做一件事: 从 Filed 获得数据, 根据数据来<code>paint()</code>.</p>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(四) 浮点数四则运算</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_04/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_04/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><h2 id="浮点数的加减运算"><a href="#浮点数的加减运算" class="headerlink" title="浮点数的加减运算"></a>浮点数的加减运算</h2><p>$X=X_S \times 2^{X_E},Y=Y_S \times 2^{Y_E}$</p><ul><li>步骤<ol><li>检查是否为零</li><li>阶码对齐,尾数移位</li><li>对尾数加或减</li><li>标准化结果</li><li>溢出判断</li></ol></li></ul><ol><li><p>对阶</p><ol><li><p>求阶差<br>$\Delta E=\begin{cases}<br>  =0,已经对齐\<br>\ne0,\begin{cases}大的向小的对齐:减小较r大的阶码,同时扩大其尾数\小的向大的对齐:增大较小的阶码,同时减小其尾数 \end{cases} \<br>\end{cases}$<br>在计算机中,尾数左移可能会使最高位数据丢j失,故采用小阶向大阶对齐<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/deb6114c1afee838908c5071612f84f69a0fa8d0.jpg" alt="浮点数加减" style="zoom:67%;" /></p><center>浮点数加减的过程</center></li></ol></li></ol><h3 id="一些溢出情况"><a href="#一些溢出情况" class="headerlink" title="一些溢出情况"></a>一些溢出情况</h3><h4 id="1-Exponent-overflow"><a href="#1-Exponent-overflow" class="headerlink" title="1. Exponent overflow"></a>1. Exponent overflow</h4><ul><li>一个正的指数超出了指数的最大值(即127)</li><li>指定为$-\infty 或 +\infty$</li></ul><h4 id="2-Exponent-underflow"><a href="#2-Exponent-underflow" class="headerlink" title="2. Exponent underflow"></a>2. Exponent underflow</h4><ul><li>一个负的指数小于了指数的最小值(即-126)</li><li>指定为0.</li></ul><h4 id="3-Significand-overflow"><a href="#3-Significand-overflow" class="headerlink" title="3. Significand overflow"></a>3. Significand overflow</h4><ul><li>同号的两个数字相加时,在最重要的位上产生了进位.</li><li>在realignment时修正</li></ul><h4 id="4-Significand-underflow"><a href="#4-Significand-underflow" class="headerlink" title="4. Significand underflow"></a>4. Significand underflow</h4><ul><li>在对齐尾数的时候, 数据可能从尾数的最右端流失</li><li>需要某种形式的四舍五入</li></ul><h3 id="原码加减法-用于尾数的加减"><a href="#原码加减法-用于尾数的加减" class="headerlink" title="原码加减法(用于尾数的加减)"></a>原码加减法(用于尾数的加减)</h3><ul><li><p>如果两个操作数符号相同,做加法,否则做减法.</p><ul><li>加法:<ul><li>若最高位产生了进位,溢出</li><li>符号同加数</li></ul></li><li>减法:加第二个数的补数<ul><li>若最高位产生进位,结果正确(符号等同于被减数)</li><li>若没有进位,应该取结果的补数,最终结果与被减数相反.<br>注意:此处可以是认定为没有符号位的补码在做计算,所以最终结果需要进行修正.(因为正数补码是它自身,负数补码是其反码加一)<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/baa713a920ac0acf967f9b22dda0cc73973d0598.webp" alt="浮点数运算源码加减法" style="zoom:80%;" /></li></ul></li></ul><p>更通俗的说法:最终算A+B的时候(无论是一开始就是A+B还是减法转化而来).如A,B同号,尾数是正常相加;若A,B异号,尾数为$A<em>S+[B_S]</em>补$</p></li></ul><h3 id="浮点数加减法举例"><a href="#浮点数加减法举例" class="headerlink" title="浮点数加减法举例"></a>浮点数加减法举例</h3><ul><li><p>减法<br>0.5-(-0.4375)=0.5+0.4375=0.9375<br>0.5&emsp;&emsp;&emsp;<font color=RED>0</font>&emsp;<font color=BLUE>01111110</font>&emsp;<font color=GREEN>00000000000000000000000</font><br>-0.4375&emsp;<font color=RED>1</font>&emsp;<font color=BLUE>01111101</font>&emsp;<font color=GREEN>11000000000000000000000</font><br>&ensp;0.4375&emsp;<font color=RED>0</font>&emsp;<font color=BLUE>01111101</font>&emsp;<font color=GREEN>11000000000000000000000</font><br><font color = BLUE>01111110-01111101=01111110+10000011=00000001</font><br>则前者阶码比后者大,后者向前者对齐(后者阶码加1,尾数右移一位,此处尾数包含隐藏位，即橙色位).减法经处理后,两个操作数同号,尾数做正常加法</p><center>&emsp;<font color=#FF8500>1</font>&emsp;<font color=GREEN>0000...00</font></center><center>+&ensp;<font color = GREEN>0</font>&emsp;<font color=#FF8500>1</font><font color=GREEN>110...00</font></center><center>——————————</center><center><font color=#FF8500>&emsp;1</font>&emsp;<font color=GREEN>1110...00</font></center><p>加法计算没有进位，则结果正确，为</p></li></ul><center><font color=RED>1</font>&emsp;<font color=BLUE>01111101</font>&emsp;<font color=GREEN>11000000000000000000000</font></center><ul><li><p>加法<br>0.5+(-0.4375)=0.0625<br>0.5&emsp;&emsp;&emsp;<font color=RED>0</font>&emsp;<font color=BLUE>01111110</font>&emsp;<font color=GREEN>00000000000000000000000</font><br>-0.4375&emsp;<font color=RED>1</font>&emsp;<font color=BLUE>01111101</font>&emsp;<font color=GREEN>11000000000000000000000</font></p><p><font color = BLUE>01111110-01111101=01111110+10000011=00000001</font><br>则前者阶码比后者大,后者向前者对齐(后者阶码加1,尾数右移一位,此处尾数包含隐藏位，即橙色位).两个操作数异号,尾数加法做加后者补数.</p><center>&emsp;<font color=#FF8500>1</font>&emsp;<font color=GREEN>0000...00</font></center><center>+&ensp;<font color = GREEN>1</font>&emsp;<font color=#FF8500>0</font><font color=GREEN>010...00</font></center><center>——————————</center><center><font color = RED>1</font><font color=#FF8500>&ensp;0</font>&emsp;<font color=GREEN>0010...00</font></center><p>符号相异产生进位,结果正确,与第一个操作数符号相同.经规格化后:</p><center><font color=RED>1</font>&emsp;<font color=BLUE>01111011</font>&emsp;<font color=GREEN>00000000000000000000000</font></center></li></ul><h2 id="浮点数乘法"><a href="#浮点数乘法" class="headerlink" title="浮点数乘法"></a>浮点数乘法</h2><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/16896fbb58f26550525aedbf82281f8eec4abede.jpg" alt="浮点数乘" style="zoom:67%;" /></p><ul><li>步骤<ul><li>如果任何一个操作数为0,返回0.</li><li>指数相加时需要减去偏差值,因为阶码用移码表示.</li><li>尾数相乘.</li><li>结果规格化并舍入.(可能造成指数溢出).</li></ul></li></ul><h2 id="浮点数除法"><a href="#浮点数除法" class="headerlink" title="浮点数除法"></a>浮点数除法</h2><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/2489c91543786aa46bdfc31c6d4f6b1851450557.jpg" alt="浮点数除法" style="zoom:67%;" /></p><ul><li>步骤<ul><li>除数为0,报错或设为无穷.</li><li>被除数为0,设为0.</li><li>被除数的阶码和除数的阶码做差,并加回偏差值.</li><li>尾数相除.</li><li>结果标准化并舍入.</li></ul></li></ul><p><strong>注意</strong>:<strong>和无符号整数除法不同</strong>:浮点数除法给被除数后面填零存入余数和商寄存器,而整数是高位填零.</p><h2 id="保护位"><a href="#保护位" class="headerlink" title="保护位"></a>保护位</h2><p>为了提高精度,在计算时每个数字都存在保护位,暂时储存着计算后(比如右移)后的超出低位的数据.</p>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(五) 内置存储器</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_05/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_05/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><h2 id="Memory"><a href="#Memory" class="headerlink" title="Memory"></a>Memory</h2><p>存储器由一定数量的单元构成，每个单元可以被唯一标识，每个单元都有存储一个数值的能力.</p><ul><li>地址:单元的唯一标识符(采用二进制).</li><li>地址空间:可唯一标识的单元总数.</li><li>寻址能力: 存储在每个单元中的信息的位数<ul><li>大多数存储器是字节可寻址的,执行科学计算的计算机通常是64位寻址的.</li></ul></li></ul><h2 id="半导体存储器"><a href="#半导体存储器" class="headerlink" title="半导体存储器"></a>半导体存储器</h2><ul><li>主存中广泛地运用了半导体芯片.</li><li><strong>Memory Cell</strong>:半导体主存的基本元素.<ul><li>特性:<ul><li>它们展示了两种稳定(半稳定)的状态,可以用于表示二进制0和1.</li><li>能够被写入至少一次.</li><li>可以被读.</li></ul></li></ul></li></ul><h2 id="半导体存储器类型"><a href="#半导体存储器类型" class="headerlink" title="半导体存储器类型"></a>半导体存储器类型</h2><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/3ee2f36bb8d10c7aa8595477a7d7bc38efd76b3d.jpg" alt="半导体存储器类型" style="zoom:80%;" /></p><h2 id="RAM"><a href="#RAM" class="headerlink" title="RAM"></a>RAM</h2><h3 id="RAM-1"><a href="#RAM-1" class="headerlink" title="RAM"></a>RAM</h3><ul><li><strong>Random-Access Memory</strong></li><li><strong>Characteristics</strong><ul><li>易于读/写且快速</li><li>易失(断电丢失数据)</li></ul></li><li><strong>类型</strong><ul><li>DRAM:Dynamic RAM</li><li>SRAM:Static RAM</li></ul></li></ul><h3 id="DRAM"><a href="#DRAM" class="headerlink" title="DRAM"></a>DRAM</h3><ul><li><p>以电容器上的电荷来存储数据</p><ul><li>电容器中是否存有电荷被解释称二进制1和0</li></ul></li><li><p>需要定期刷新来维持数据,因为电容器有放电的趋势</p></li><li>本质是模拟设备,因为电容可以存储一定范围内的任何电荷值,因此需要使用一个阈值来确定保存的是1还是0.</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/3d8110ac2957078f247f7fc6725310962f39e43b.jpg" alt="DRAM" style="zoom:80%;" /></p><h3 id="SRAM"><a href="#SRAM" class="headerlink" title="SRAM"></a>SRAM</h3><ul><li>用传统的触发逻辑门配置存储数据<ul><li>处理器中使用了相同的逻辑单元</li></ul></li><li>只要供应电力就能一直保存数据(无需刷新)<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/83a86f458af7b30ca04aca27502cbe704f02e2be.jpg" alt="SRAM" style="zoom:80%;" /></li></ul><h3 id="DRAM-和-SRAM-之间的比较"><a href="#DRAM-和-SRAM-之间的比较" class="headerlink" title="DRAM 和 SRAM 之间的比较"></a>DRAM 和 SRAM 之间的比较</h3><ul><li><p><strong>相似点</strong>:</p><ul><li>易失.必须持续供应电力来保存位值</li></ul></li><li><p><strong>不同点</strong>:</p><ul><li>DRAM 比 SRAM 的单元更小且更简单,但是需要刷新电路<ul><li>DRAM 比 SRAM 集成度更高,更便宜</li><li>DRAM 通常用于大内存需求</li></ul></li><li>SRAM 通常比 DRAM 快</li><li>SRAM 用于 Cache DRAM 用于主存</li></ul></li></ul><h3 id="高级DRAM-组织"><a href="#高级DRAM-组织" class="headerlink" title="高级DRAM 组织"></a>高级DRAM 组织</h3><ul><li><strong>问题</strong><br>传统的DRAM 芯片受限于其内部结构及其与处理器的存储总线的连接. </li><li><strong>解决方案</strong>:<ul><li>SDRAM(Synchronous DRAM)</li><li>DDR (DDR SDRAM)</li></ul></li></ul><h3 id="SDRAM"><a href="#SDRAM" class="headerlink" title="SDRAM"></a>SDRAM</h3><ul><li>传统的 DRAM 是异步的.<ul><li>处理器将地址和控制信号提供给存储器,表示存储器中特定单元的一组数据应当被读出或写入DRAM.</li><li>经过一段延时后,DRAM写入或读出数据.在这段时间内,DRAM 执行各种内部功能，如激活行地址线或列地址线的高电容， 读取数据，以及通过输出缓冲将数据输出,而处理器只是等待,降低了性能.</li><li>SDRAM 与处理器交换数据同步于外部时钟信号,可以以处理器/存储器总线全速运行,而不必等待.</li><li>由于SDRAM随系统时钟移动数据,CPU 知道数据何时能够准备好.<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/pqxwjrSud5agc4m.jpg" alt="SDRAM" style="zoom:67%;" /></li></ul></li></ul><h3 id="DDR-SDRAM"><a href="#DDR-SDRAM" class="headerlink" title="DDR SDRAM"></a>DDR SDRAM</h3><ul><li>Double-data-rate SDRAM双速率 SDRAM.</li><li>每个时钟周期发送两次数据,一次在脉冲上升沿,一次在下降沿.</li><li>DDR 技术的更迭<ul><li>提升操作频率</li><li>提升预取缓冲器位数<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/3308197023c32a8fa15623c9601b5a9039fd8d96.webp" alt="DDR" style="zoom:67%;" /></li></ul></li></ul><h2 id="ROM"><a href="#ROM" class="headerlink" title="ROM"></a>ROM</h2><h3 id="Read-only-memory"><a href="#Read-only-memory" class="headerlink" title="Read-only memory"></a>Read-only memory</h3><h4 id="ROM-1"><a href="#ROM-1" class="headerlink" title="ROM"></a>ROM</h4><ul><li><strong>只读存储器</strong></li><li>特点<ul><li>不易失性:无需电源来维持数据.</li><li>可读但不可写.</li></ul></li><li><strong>应用</strong><ul><li>微程序设计，库子程序，系统程序,函数表.</li></ul></li><li><strong>问题</strong><ul><li>固化数据需要较大的固定成本，不论是制造一片还是复制上千片特殊的ROM 。</li><li>无出错处理机会，如果一位出错．则整批的ROM 芯片只能报废。</li></ul></li></ul><h4 id="PROM"><a href="#PROM" class="headerlink" title="PROM"></a>PROM</h4><ul><li><strong>Programmable ROM</strong></li><li><strong>特征</strong><ul><li>非易失性</li><li>可以但只能写入一次<ul><li>用电信号写</li><li>需要特殊设备</li></ul></li></ul></li><li>与ROM相比<ul><li>PROM 更灵活方便</li><li>ROM在大批量生产领域仍具有吸引力</li></ul></li></ul><h3 id="Read-mostly-Memory"><a href="#Read-mostly-Memory" class="headerlink" title="Read-mostly Memory"></a>Read-mostly Memory</h3><ul><li>特征<ul><li>读操作比写操作更为频繁</li><li>非易失性存储</li></ul></li><li>类型<ul><li>EPROM</li><li>EEPROM</li><li>Flash Memory</li></ul></li></ul><h4 id="EPROM"><a href="#EPROM" class="headerlink" title="EPROM"></a>EPROM</h4><ul><li><strong>Erasable PROM</strong></li><li><strong>特点</strong><ul><li>用电信号读写</li><li>擦除:在写入新的数据之前,用紫外线辐射芯片<ul><li>所有的存储位元都还原为初始状态</li><li>需要20分钟</li></ul></li></ul></li><li>与 PROM 相比<ul><li>EPROM更贵,但可以多次改写</li></ul></li></ul><h4 id="EEPROM"><a href="#EEPROM" class="headerlink" title="EEPROM"></a>EEPROM</h4><ul><li><strong>Electrical EPROM</strong></li><li><p><strong>特点</strong></p><ul><li>任何时候都可以写入,无需擦除原有数据</li><li>只需要更新寻址到的一个或者多个字节</li><li>写操作耗费时间更长,每个字节需要几百微秒</li></ul></li><li><p>与 EPROM 相比</p><ul><li>EEPROM 更加昂贵,且密度更小,适合小容量芯片</li></ul></li></ul><h4 id="Flash-Memory"><a href="#Flash-Memory" class="headerlink" title="Flash Memory"></a>Flash Memory</h4><ul><li><strong>特点</strong><ul><li>电擦除</li><li>擦除至多需要数秒,比 EPROM 要快得多</li><li>可以擦除存储器中的某些块,但不能提供字节级擦除</li><li>相较于 EEPROM ,闪存与EPROM有一样的高存储密度</li></ul></li></ul><h2 id="芯片逻辑"><a href="#芯片逻辑" class="headerlink" title="芯片逻辑"></a>芯片逻辑</h2><ul><li><strong>可寻址单元</strong><ul><li>由拥有相同地址的<strong>存储位元</strong>(memory cell)组成</li></ul></li><li><strong>寻址模式</strong><ul><li>字节可寻址</li><li>字</li></ul></li><li><strong>存储阵列</strong>(Memory array)<ul><li>由许多存储单元组成(如下图中有$2048\times 2048$个存储单元)<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/7efdd71a9827da9b5f3a4d6854acdea6ecdc13a3.webp" alt="RAM" style="zoom:67%;" /></li></ul></li></ul><h2 id="刷新-Refreshing"><a href="#刷新-Refreshing" class="headerlink" title="刷新(Refreshing)"></a>刷新(Refreshing)</h2><ul><li>集中式刷新<ul><li>停止读写操作,刷新每一行.</li><li>当刷新时存储器不能进行操作</li></ul></li><li>分散式刷新<ul><li>在每一个存储周期内当读写操作完成后对一部分刷新</li><li>增加了存储的时间</li></ul></li><li>异步刷新<ul><li>64ms 内对每一行刷新完毕,每行刷新间隔不变</li><li>效率高</li></ul></li></ul><h2 id="字扩展-位扩展和字位扩展"><a href="#字扩展-位扩展和字位扩展" class="headerlink" title="字扩展,位扩展和字位扩展"></a>字扩展,位扩展和字位扩展</h2><ul><li>字扩展<ul><li><strong>增加了存储器中字的个数</strong>,地址线增加,数据线不变.由<strong>片选信号</strong>来区分各芯片的地址范围.</li></ul></li><li>位扩展<ul><li>增加了字长.地址线不变,数据线增加.读写的时候,一个地址对应几块芯片的同一位置.</li></ul></li><li>字位扩展<ul><li>二者结合</li></ul></li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(六) Cache</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_06/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_06/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><h2 id="为什么需要-cache"><a href="#为什么需要-cache" class="headerlink" title="为什么需要 cache?"></a>为什么需要 cache?</h2><ul><li>因为 CPU 比 内存的速度要快得多.`</li></ul><h2 id="基本思路"><a href="#基本思路" class="headerlink" title="基本思路"></a>基本思路</h2><ul><li>使用较小, 较快的 Cache 和相对较大,更为缓慢的 Memory</li><li>Cache 中包含了 Memory 中数据的<strong>副本</strong></li><li>Cache 位于中央处理器和存储器之间,并可以被集成在 CPU 或者作为主板上的一个模块.</li></ul><h2 id="Cache-工作的原理"><a href="#Cache-工作的原理" class="headerlink" title="Cache 工作的原理"></a>Cache 工作的原理</h2><ul><li><font color=FF0000>Check </font>:当处理器试图读取内存中的一个字的时候,会先检查该字是否在 Cache 中.</li><li><font color=00FF00>Hit </font>: 如果确实在, 这个字被传送给处理器.</li><li><p><font color=0000ff>Miss </font>: 否则,由一定数量的字组成的<strong>一块( block )主存中的数据</strong> 被读入 Cache ,然后传给处理器.<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/1f77f889fe21b537409937de54e977f1790a1262.jpg" style="zoom:67%;" /></p></li><li><p>时间局部性:<br>未来将要使用的信息(指令和数据), 可能是现在正在使用的信息.</p></li><li>空间局部性:<br>未来将要使用的信息, 很可能与正在使用的信息在存储空间上是邻近的(比如遍历一个一维数组).</li></ul><h2 id="判断-Hit-与-Miss"><a href="#判断-Hit-与-Miss" class="headerlink" title="判断 Hit 与 Miss"></a>判断 Hit 与 Miss</h2><ul><li>冯诺依曼计算机的设计:<br>内存中的内容按位置寻址,而不考虑其中的数据类型.</li><li>Cache 中有 <font color="ff0000">标记</font>(tag) 来判断需要读取的信息是否存在于 Cache.</li></ul><h2 id="移动”块”而不是字"><a href="#移动”块”而不是字" class="headerlink" title="移动”块”而不是字"></a>移动”块”而不是字</h2><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/10d416f2051d0ff9ed1a4d60861da6582a74da44.webp" style="zoom:67%;" ></p><h2 id="证明-Cache-机制能够提高性能"><a href="#证明-Cache-机制能够提高性能" class="headerlink" title="证明 Cache 机制能够提高性能"></a>证明 Cache 机制能够提高性能</h2><ul><li>设命中率为 $p$, $T_C$ 为访问Cache 的时间,$T_M$ 为访问主存的时间,则总时间为(可以认为返回数据不需要时间, 寻找花时间)<script type="math/tex; mode=display">T=T_Cp+(1-p)(T_C+T_M)</script>由上面可以推出,若 $T<T_M$, 则 $p>\frac{T_C}{T_M}$ ,虽然$\frac{T_C}{T_M}$非常小,但是 Cache 的容量更要远远小于主存的容量,这就体现了局部性的作用.</li></ul><h2 id="Cache-是否越大越好"><a href="#Cache-是否越大越好" class="headerlink" title="Cache 是否越大越好?"></a>Cache 是否越大越好?</h2><p>Cache 容量变大, 命中率增加会变得缓慢,因为搬来的数据可能关联性弱,对效果提升十分有限.此外,Cache 规模变大会使得 check 的时间变长.</p><h2 id="映射功能"><a href="#映射功能" class="headerlink" title="映射功能"></a>映射功能</h2><ul><li>因为 Cache 的行比主存块要少, 所以需要一个算法将主存中的块映射到 Cache 中的行.</li></ul><h3 id="1-直接映射"><a href="#1-直接映射" class="headerlink" title="1. 直接映射"></a>1. 直接映射</h3><ul><li>地址组成：</li></ul><iframe frameborder="0" style="width:100%;height:300px;" src="https://viewer.diagrams.net/?highlight=0000ff&edit=_blank&layers=1&nav=1#R3ZjLjpswFIafxstIsQlgliFh2kW7SqVZe8AFq4CRcUoyT187mDAMpFAVRsmsYv%2B%2BxOc7vy8CWLvs9EWQIvnOI5oCtI5OwNoDhCD0bPWjlbNRXAfWSixYZLRWOLBXasS1UY8somWno%2BQ8lazoiiHPcxrKjkaE4FW320%2Bedv%2B1IDHtCYeQpH31mUUyqVWM3Fb%2FSlmcNP8MHa9uyUjT2URSJiTi1RvJCoC1E5zLupSddjTV9Bou9binG63XhQmayykDkFnYb5IeTXBmYfLcRCv4MY%2BoHrAGll8lTNJDQULdWqkEKy2RWapqUBXNdFRIerq5JniNVHmE8oxKcVZdzABs2Bh3NKiqljRstOQN5Y3RiElufJ24jV8VDIJhHPdE43b4eKHom%2B11F%2BGfmvBH3bAYDjiOQ%2B3fQhfDo0jPviDhLyrHubQQ65okkvFcVVfeeh5sXpfaagDb0B660v4vbpset1JVQbAB%2Fh7gPQgw2EKwxSBwwVaJWxDYwNsDz9UF%2FAR8twdaoZBdiCRlsWYWKiRUKEEDY%2BqQ3pqGjEWRHu4LWrJX8nKZSvMtOMvlJUDbB%2FZez3WUvKyvmZl863QT4E2zLZoDv93DX%2F0Lfgdg%2B6LsgL82Tc1aHzghENtjGYFwqZQ4j3uSIKvr5M20kwTPgc39cGxzUYPvqK3sadjgLHbrP2PE30%2BAHQkTamS8%2BzynMB6%2FBgffknNkAU14Td2pe9%2Bb1%2Fq4PY%2F6j65yNeJeSeKHd%2BqqezsNOdVbyqioh%2FzHJyCKuiYe8LC1FND%2BvfWN5fThicJxpJulkOIe0mcuIoCcVCN8USeEE8trmA8MeYJvZ4Ksqu2Hpkvbm%2B91VvAH"></iframe><ul><li><p>定义: 内存中的一个块映射到 Cache 中固定的行.</p></li><li><p>将主存中的每个块映射到<strong>固定</strong>的可用 Cache 中行.直接映射可以表示为:</p><script type="math/tex; mode=display">i=j\space mod\space m</script><p>其中 i 为 Cache 行号, j 为主存块号, m 为 Cache 行数 .<br>为了实现访问 Cache 每一个主存地址可以看作由<strong>三个域</strong>组成：</p><ul><li>低 $w$ 位标识某个块中的唯一一个存储单元(字节或字).</li><li>剩余 $s$ 位标识了主存 $2^s$ 个块中的一个.<ul><li>其中 $r$ 位标识了 cache 中的行号(cache 的行数为 $m=2^r$)</li><li>$s-r$ 位为 tag 位.用以区分映射到同一行的不同块.</li></ul></li></ul><p>总结:</p><ul><li>地址长度: $(s+w)$ 位</li><li>可寻址单元数: $2^{s+w}$</li><li>块大小=行大小=$2^w$ 个存储单元(字节或字)</li><li>主存的块数:$\frac{2^{s+w}}{2^w}=2^s$</li><li>cache 行数:$m=2^r$</li><li>cache 容量: $2^{r+w}$ 个字或者字节</li><li>标记长度: $(s-r)$ 位</li></ul></li><li><p>举例:<br>$m=16K=2^{14},i=j\space mod\space 2^{14}$,用 16 进制 表示地址有</p></li></ul><table><thead><tr><th style="text-align:center">cache 行</th><th style="text-align:center">主存块的起始地址</th></tr></thead><tbody><tr><td style="text-align:center">0</td><td style="text-align:center">000000,010000,....FF0000</td></tr><tr><td style="text-align:center">1</td><td style="text-align:center">000004,010004,...,FF0004</td></tr><tr><td style="text-align:center">...</td><td style="text-align:center">...</td></tr><tr><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="0" style="font-size: 112.9%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-msup><mjx-mn class="mjx-n"><mjx-c class="mjx-c32"></mjx-c></mjx-mn><mjx-script style="vertical-align: 0.363em;"><mjx-mn class="mjx-n" size="s"><mjx-c class="mjx-c31"></mjx-c><mjx-c class="mjx-c34"></mjx-c></mjx-mn></mjx-script></mjx-msup><mjx-mo class="mjx-n" space="3"><mjx-c class="mjx-c2212"></mjx-c></mjx-mo><mjx-mn class="mjx-n" space="3"><mjx-c class="mjx-c31"></mjx-c></mjx-mn></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mn>2</mn><mn>14</mn></msup><mo>−</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">2^{14}-1</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></td><td style="text-align:center">00FFFC,01FFFC,...,FFFFFFC</td></tr></tbody></table><p>  地址24位,其中,高8位为 tag 位,若当前存在该行的标记数与地址中的相同,则14位标识 cache 行号,  低2位标识行中的4个字节(或者字);否则,前22位标识为从主存中取一块.取的主存块的地址为22位加两位0(因为块都是以4倍数开始的,每个块有4个单元)</p><ul><li><p><strong>优点</strong>:</p><ul><li>check快,从主存中存取的时候快</li><li>tag 短,额外存储少.</li><li>不会随着容量增大而变慢</li><li>实现简单</li></ul></li><li><p><strong>缺点</strong>:</p><ul><li>容易发生抖动:用到的两个块映射到 cache 中的同一行,于是频繁的替换.</li><li>命中率低</li></ul></li></ul><h3 id="2-全相联映射"><a href="#2-全相联映射" class="headerlink" title="2. 全相联映射"></a>2. 全相联映射</h3><ul><li><p>地址图示:</p><iframe frameborder="0" style="width:100%;height:300px;" src="https://viewer.diagrams.net/?highlight=0000ff&edit=_blank&layers=1&nav=1#R3ZdNj5swEIZ%2FzRwj8RGIOUJgt5eeUmnPXnDBKmBkTEn219cOBsKyUViVVM1eovE7tvE8Mx4C2Pvi%2BMxxlX1nCcnBMpIj2CFYlu0i%2BauEUyeYO9fslJTTRGujcKBvRIuGVhuakHoyUTCWC1pNxZiVJYnFRMOcs3Y67SfLp0%2BtcEpmwiHG%2BVx9oYnIOhVZu1H%2FRmia9U82Xa%2FzFLifrCOpM5yw9kKyI7D3nDHRWcVxT3IFr%2BfSrXu64h0OxkkplizQ5%2FqN80bHps8lTn2wnDVlQtR8A%2BygzagghwrHytvK9EotE0UuR6Y09XaEC3K8eiRzCFRWCGEFEfwkp%2Bhq6NG0I1nL0Fp2QXWrNayTmQ47jfFKQ4d8hZfxH8V%2FfBfsdR7oXjjM2zhkxVbKjBuenwKO419E3OYyQuxGAgvKSjnceMY62LwptY39URnNsQ20%2F4rbdsatlkOIthCEgEKIEPgm%2BAiiHfhS9CFywAvB2ykDPUGwm4GWKMQUIs5pqpjFEgnhUlDAqGxLvnYUNEnU8oCTmr7h1%2FNWim%2FFaCnOAToBOKHaqxGs7hrrSnXrThOAlpWttQZ%2BZ4a%2F%2FQx%2BF5BzVvYQGNrVn%2FWBE2Ii51ZGTPNeKXEft5NY9rSSF3YStAI2a8H7aGVs9%2Bq%2F3j%2Fsv9b8vXWj%2FwqcPvz9dqfXe7Pwj8Ia17svywvgP74A0XcN84OLb98LKJoBfWE8AcvNFcFXLq1UDFE%2BMOMB13XI23Ugy%2BH4IXX2XXyO2tEf"></iframe> </li><li><p>定义: 内存中的块可以映射到 Cache 中的任意一行.</p></li><li><p>总结:</p><ul><li>地址长度 s+w 位</li><li>可寻址单元数 $2^{s+w}$ 个字(字节)</li><li>块大小=行大小=$2^w$ 个字(字节)</li><li>主存的块数:$\frac{2^{s+w}}{2^w}=2^s$</li><li>cache 的行数: 不由地址格式决定</li><li>标记长度=s 位</li></ul></li><li><p><strong>优点</strong>:</p><ul><li>避免”抖动”.</li><li>命中率高</li></ul></li><li><p><strong>缺点</strong>:</p><ul><li>check 慢, 从内存中放到 cache 中慢.</li><li>实现较为复杂 </li></ul></li></ul><h3 id="3-组相联映射"><a href="#3-组相联映射" class="headerlink" title="3. 组相联映射"></a>3. 组相联映射</h3><ul><li>图示:</li></ul><iframe frameborder="0" style="width:100%;height:258px;" src="https://viewer.diagrams.net/?highlight=0000ff&edit=_blank&layers=1&nav=1#R3ZhBk5sgFMc%2FDcfMiKjBY0zc9tJTOrNnVqkyVXGQ1GQ%2FfSGihrhp0qnJNHvy8QeR9%2BPxngrQutx%2FEaTOv%2FGUFsB10j1AG%2BC60PVdddHKwShLFHRKJlhqtFHYsndqRMeoO5bSxhooOS8kq20x4VVFE2lpRAje2sN%2B8MJ%2Bak0yOhG2CSmm6itLZd6p2F2O%2BlfKsrx%2FMgzCrqck%2FWDjSZOTlLcnEooBWgvOZWeV%2BzUtNL2eS3ffy4XeYWGCVvKWG8y6fpFiZ3wz65KH3lnBd1VK9XgHoKjNmaTbmiS6t1X7q7RcloVqQWWa6aiQdH9xSXBwVIUI5SWV4qCGmGjo0bQjWdhr%2BQlVz2jEbGY2zDT6qwzj8gVezn%2Fk%2F7733yzqMg98LxzwOg4VsbU2k50oDpEgyU8qr3MZIXYtSSTjlWouQmcebKFNbYGm2D6KooH2P3HzJtwa1QSxB6INwBsQY7CCYIVBvAQrJa5A7INwA8KlNvALiJYT0AqFtCGSgmWaWaKQUKEEDYyptLQyHSVLU317JGjD3snbcSrNt%2BaskkcH%2FQj4Gz3XTvKmS6wzxW1gbwC%2BLWzdOfD7E%2Fzt3%2BAPAPaPyhpEjunq1%2FrEGwKxf21HILzXlgTPm0lcZEfyjZkEz4DNvaEezYxtLmr%2BWf71b6MG54g2d1q3mkX65xQgSfb0J3wB7RO%2B%2BOBdIbzTCe8j84T590%2BA1LOJfnD20b2A4gnQVy5UFAeFJvgmlJXJwcsnZjzgugzZuxNkhCaQtyp9Xmf86K8AeMbogV8BaPo2%2ByxFCJ5XoQfWbjR9C71SgrQRRQB7Jx8Bn%2B6w44eVKNUcf5wc%2B07%2BP6H4Nw%3D%3D"></iframe> <ul><li>定义: Cache 中的行分成组(Set),内存中的块搬到固定的组,组中具体的哪一行不固定.第一步类似直接映射,第二部类似全相联映射. Cache 中分为 $v$ 个组,每组包含 $k$ 个行,则:<script type="math/tex; mode=display">\begin{aligned}  &m=v\times k\\  &i=j\space mod\space v\\\end{aligned}</script>其中: i 为组号, j 为主存块号,m 为主存块数,v 为组数,k 为每个组中的行数, 即 k路组(K-way Set).</li><li>总结:<ul><li>地址长度 s+w 位</li><li>可寻址单元数 $2^{s+w}$ 个字(字节)</li><li>块大小=行大小=$2^w$ 个字(字节)</li><li>主存的块数:$\frac{2^{s+w}}{2^w}=2^s$ </li><li>cache 中每组行数= k</li><li>组数 = v = $2^d$</li><li>cache 中的行数 = m = $k\times v=k\times 2^d$</li><li>标记长度 s-d 位(同一个组中不会出现标记位相同的两个块)</li></ul></li><li><p><strong>优点</strong>:</p><ul><li>固定组 check ,存取,速度比全相联快</li><li>命中率比直接映射高</li></ul></li><li><p><strong>缺点</strong>:</p><ul><li>实现复杂.</li><li>若反复用的的块很多的话,仍然无法避免抖动.</li></ul></li></ul><h2 id="替换算法"><a href="#替换算法" class="headerlink" title="替换算法"></a>替换算法</h2><h3 id="1-最近最少用"><a href="#1-最近最少用" class="headerlink" title="1.最近最少用"></a>1.最近最少用</h3><h3 id="2-先进先出"><a href="#2-先进先出" class="headerlink" title="2.先进先出"></a>2.先进先出</h3><h3 id="3-使用最少"><a href="#3-使用最少" class="headerlink" title="3.使用最少"></a>3.使用最少</h3><h3 id="4-随机"><a href="#4-随机" class="headerlink" title="4.随机"></a>4.随机</h3><h2 id="写策略"><a href="#写策略" class="headerlink" title="写策略"></a>写策略</h2><h3 id="1-写入"><a href="#1-写入" class="headerlink" title="1.写入"></a>1.写入</h3><ul><li>每一次改了之后都更新内存<ul><li>好处:提升cache和主存一致性,保证主存中的内容都是最新的</li></ul></li></ul><h3 id="2-写回"><a href="#2-写回" class="headerlink" title="2.写回"></a>2.写回</h3><ul><li>cache 中的行要被替换时不得不写回去,用 dirty bit 来判断数据是否发生过改写,若没有改过无需写回.</li></ul><h2 id="块大小-Cache-Line-Size"><a href="#块大小-Cache-Line-Size" class="headerlink" title="块大小(Cache Line Size)"></a>块大小(Cache Line Size)</h2><ul><li>由极小变大,根据局部性原理命中率先是提升,因为每个块所能容纳的有用数据增多了.</li><li>到极大时,且新取信息的概率小于重用信息概率时,命中率会减小.因为较大的块减少了块的个数,少量的块导致装入的数据很快会被改写;当块变大时,每个附加字距离所需字就更远,被使用的概率低.</li></ul><h2 id="cache-数目"><a href="#cache-数目" class="headerlink" title="cache 数目"></a>cache 数目</h2><ul><li>多级 cache 比单一大容量 cache 效率更高</li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(七) 外存</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_07/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_07/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><ul><li>特点<ul><li>大容量,非常用</li><li>非易失性</li></ul></li><li>类型<ul><li>磁盘</li><li>光盘</li><li>磁带</li><li>U盘,SSD</li></ul></li></ul><h2 id="磁盘"><a href="#磁盘" class="headerlink" title="磁盘"></a>磁盘</h2><ul><li>磁盘是一种由非磁性材料制成的称为衬底的圆盘,其上涂有一层磁性材料.<ul><li>衬底材料: 铝合金,铝,玻璃..</li><li>玻璃衬底的优点:<ul><li>改善磁层表面的均匀性,增加磁盘的可靠性.</li><li>显著减少整个表面的缺陷,有助于减少读写错误.</li><li>支持更低的飞行高度.</li><li>更好的刚度,降低了磁盘的动力需求.</li><li>更好的耐冲击和耐磨损能力.</li></ul></li></ul></li><li>分类:<ul><li>软盘</li><li>硬盘</li></ul></li></ul><h3 id="物理特性"><a href="#物理特性" class="headerlink" title="物理特性"></a>物理特性</h3><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/3e4cbe481f534268d23e2afca86fc7c67241ab98.webp" style="zoom:80%;" /></p><ul><li>采用可移动磁头,每面只有一个读-写头.磁头固定在支架上,支架可以伸缩,使磁头可以定位到任意磁道.</li><li>任何时候,所有的磁头都定位在磁道上,所有的磁道都是同心圆.</li><li>磁盘上相对位置相同的所有磁道的集合称为柱面.</li></ul><h3 id="读写机制"><a href="#读写机制" class="headerlink" title="读写机制"></a>读写机制</h3><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/e05df25e7ef8c81a42d80706580c0351ca98ce24.webp" style="zoom:80%;" /></p><ul><li>读-写是通过一个叫做<strong>磁头</strong>的导电线圈进行的.</li><li>读写期间,磁头静止不动,盘片高速旋转</li><li>头的数量:<ul><li>单: 读写共用一个头.用于软盘, 老式硬盘.</li><li>双: 单独的读,写头.用于现代硬盘.</li></ul></li></ul><h4 id="写机制"><a href="#写机制" class="headerlink" title="写机制"></a>写机制</h4><ul><li>脉冲电流送入写磁头.</li><li>利用通电线圈周围产生磁场的性质,线圈中的电流在缝隙中感应出一个磁场.</li><li>产生的磁化模式被记录在其下的磁盘表面</li><li>逆转电流的方向将逆转记录介质上的磁化方向.</li></ul><h4 id="读机制"><a href="#读机制" class="headerlink" title="读机制"></a>读机制</h4><ul><li>传统的读机制采用磁盘相对线圈运动产生磁场的效应.</li><li>当代读机制采用一个单独的读磁头,由一个部分被屏蔽的磁阻(MR)传感器组成.当下方介质的磁化方向改变的时候,电阻会发生变化.</li><li>让电流通过 MR 传感器,电阻的变化作为电压变化被检测出来.</li><li>MR 设计允许高频操作, 这等同于更高的存储密度和更快的操作速度.</li></ul><h4 id="磁头机制"><a href="#磁头机制" class="headerlink" title="磁头机制"></a>磁头机制</h4><p>磁头必须产生或者感应到足够大小的电磁场,以便正确读写.</p><ul><li>较窄的磁头要求与盘面距离更近.</li><li>更大的数据密度需要更窄的磁头和更窄的磁道.这将导致更大的出错率.</li><li>温切斯特磁盘:<ul><li>磁头是一个空气动力箔片,盘片静止时,他停靠在盘面上.</li><li>旋转盘片产生的气压足以使滤波从表面上升起.</li></ul></li></ul><h3 id="数据组织和格式化"><a href="#数据组织和格式化" class="headerlink" title="数据组织和格式化"></a>数据组织和格式化</h3><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/fca4b3384798d7895a61507b0374a7cd767c1c06.webp" style="zoom:80%;" /></p><ul><li>盘上的数据组织呈现为一组同心圆环,圆环被称为<strong>磁道</strong>(track).</li><li>数据以<strong>扇区</strong>(sectors)为单位传入或者传出磁盘.通常大小为 512 字节</li><li>相邻此岛之间有<strong>间隙</strong>(gap),它可以防止或减少由于磁头未对准或磁域干扰引起的错误.为了防止对系统提出不合理的定位要求,相邻的扇区也留有间隙.</li></ul><h4 id="恒定角速度-CAV"><a href="#恒定角速度-CAV" class="headerlink" title="恒定角速度(CAV)"></a>恒定角速度(CAV)</h4><ul><li>盘外沿的传输要比靠近盘中心快, 通过增加位之间的间隔,使磁盘以固定的速度扫描信息.</li><li>优点:<ul><li>可以用磁道号和扇区号直接寻址.</li></ul></li><li>缺点:</li><li>外围长磁道与内圈短磁道存储的数据一样多.<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/4adceca11695a8e1f1a09320d9146fed93c63b56.webp"/></li></ul><h4 id="多重区域记录"><a href="#多重区域记录" class="headerlink" title="多重区域记录"></a>多重区域记录</h4><ul><li>盘面被分为多个区域,每个区域中各磁道的扇区数是一定的,远离中心的磁道能够容纳更多的扇区.</li><li>优势: 提升了存储容量.</li><li>劣势: 实现的电路更加复杂.</li></ul><h4 id="格式化"><a href="#格式化" class="headerlink" title="格式化"></a>格式化</h4><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/8f96c47ff22976a116674aba9e61d84bd1fdb87a.webp"/></p><ul><li>磁道必须有一些起始点和辨识每个扇区的起点及终点的方法.</li><li>格式: 附加一些仅被磁盘驱动器使用而不被用户存取的额外数据.<ul><li>ID 域是唯一的一个标识或地址，用于定位具体的扇区.</li><li>同步字节是一个特殊的位模式，用来定义区域的起始点.</li><li>磁道号标识磁盘表面上的一个磁道.</li><li>磁头号标识一个磁头，因为磁盘有多个面.</li><li>ID 和数据域各包含一个检错码.</li></ul></li></ul><h3 id="磁盘性能参数"><a href="#磁盘性能参数" class="headerlink" title="磁盘性能参数"></a>磁盘性能参数</h3><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/dffc832d9baadeeeae29a68f40aed1b8868f484e.jpg"></p><h4 id="寻道时间"><a href="#寻道时间" class="headerlink" title="寻道时间"></a>寻道时间</h4><ul><li>磁头定位到该磁道所花的时间.<ul><li>初始启动的时间</li><li>穿越磁道的时间</li></ul></li></ul><h4 id="旋转延迟"><a href="#旋转延迟" class="headerlink" title="旋转延迟"></a>旋转延迟</h4><ul><li>等待相应扇区的起始处到达磁头的时间.<ul><li>平均为磁盘周期的一半.</li></ul></li></ul><h4 id="存取时间"><a href="#存取时间" class="headerlink" title="存取时间"></a>存取时间</h4><ul><li><strong>寻道时间</strong>和<strong>旋转延迟</strong>总和</li></ul><h4 id="传送时间"><a href="#传送时间" class="headerlink" title="传送时间"></a>传送时间</h4><ul><li>数据传送到磁盘所需时间<script type="math/tex; mode=display">T=\frac {b}{rN}</script><ul><li>$b$ 待传送字节数</li><li>$N$ 各磁道的字节数</li><li>$r$ 转速</li></ul></li></ul><h4 id="总平均存取时间"><a href="#总平均存取时间" class="headerlink" title="总平均存取时间"></a>总平均存取时间</h4><script type="math/tex; mode=display">T = T_S + \frac{1}{2r} + \frac{b}{rN}</script><ul><li>可以证明磁盘整理加快存取速度.</li></ul><h3 id="磁盘调度算法"><a href="#磁盘调度算法" class="headerlink" title="磁盘调度算法"></a>磁盘调度算法</h3><ul><li>先来先服务(FCFS)<ul><li>按 I/O 请求的顺序处理.</li></ul></li><li>最短寻道时间(SSTF)<ul><li>优先处理距离当前磁头位置的最短寻道时间的请求.</li></ul></li><li>SCAN<ul><li>在 0 和 N 之间移动磁头,优先处理当前移动方向上的请求,到达一端后反向.</li></ul></li><li>C-SCAN<ul><li>将磁头从 N 移动到 0, 到达 0 后立即返回 N</li></ul></li><li>LOOK<ul><li>建立在 SCAN 和 C-SCAN 的基础上, 磁头只移动到一个方向最远的请求.</li></ul></li></ul><h2 id="光盘"><a href="#光盘" class="headerlink" title="光盘"></a>光盘</h2><h3 id="CD-和-CD-ROM"><a href="#CD-和-CD-ROM" class="headerlink" title="CD 和 CD-ROM"></a>CD 和 CD-ROM</h3><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/7fb8c174c901eee86e22e7ba055ac09d454ae5c6.jpg"></p><ul><li>生产<ul><li>用精密聚焦的高强度激光制造母盘.</li><li>用母盘在聚碳酸酯上压印出复制品.</li><li>在凹坑表面镀上高反射的材料.</li><li>表面涂一层丙烯酸树脂防止灰尘或划伤.</li><li>用丝网印刷术把标签印刷在丙烯酸上.</li></ul></li><li>读<ul><li>通过安装在光盘播放机或驱动器中的低功率激光从CD或CD-ROM中检索</li><li>如果激光束落在表面有点粗糙的凹坑上，光就会散射，低强度的光就会反射回来</li><li>如果激光束落在一个光滑的表面上，更高的强度会被反射回来</li><li>磁盘包含一个单一的螺旋轨道，和所有扇区是相同的长度</li><li>以变速旋转磁盘</li><li>然后激光以恒定的线速度读取凹坑</li></ul></li><li>CD和CD - ROM的区别<ul><li>CD-ROM player更坚固，并有错误纠正设备，以确保数据正确传输</li></ul></li><li>优势<ul><li>光盘和存储在上面的信息可以廉价地大量复制</li><li>光盘是可移动的</li></ul></li><li>缺点<ul><li>它是只读的，不能更新</li><li>它的存取时间比磁盘长得多</li></ul></li></ul><h3 id="CD-R"><a href="#CD-R" class="headerlink" title="CD-R"></a>CD-R</h3><ul><li>包括染色层，用于改变反射率，并被高强度激光激活</li><li>可以用适当强度激光写入一次</li><li>生成的磁盘可以在CD-R或CD-ROM驱动器上读取</li></ul><h3 id="CD-RW"><a href="#CD-RW" class="headerlink" title="CD-RW"></a>CD-RW</h3><ul><li>使用一种在不同相位下反射率显著不同的材料, 可以被激光改变.</li><li>会随着使用老化最终完全失去性能.</li></ul><h3 id="DVD"><a href="#DVD" class="headerlink" title="DVD"></a>DVD</h3><p><img src = "https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/d44806d7159cd21cf86706a28d258d64997d5484.webp"></p><ul><li>与CD相比 <ul><li>位组装更加紧密.</li><li>DVD 采用双层结构</li><li>DVD-ROM可以是双面的, CD只能是单面的.</li></ul></li></ul><h2 id="磁带"><a href="#磁带" class="headerlink" title="磁带"></a>磁带</h2><ul><li>顺序存储</li><li>廉价</li><li>写方式<ul><li>并行写:多个磁道同时写 </li><li>串行写:一个磁道返回来写另一个</li></ul></li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(八) 纠错</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_08/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_08/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><h2 id="基本思想"><a href="#基本思想" class="headerlink" title="基本思想"></a>基本思想</h2><ul><li>方法： 添加一些位来存储附加信息以便校正</li><li>过程： <ul><li>读入:$M$ 位的数据 $D$ 通过函数 $f$ 产生 $K$ 位的校验码 $C$</li><li>被读出:通过 $f$ 由$D’$ 生成 $C’’$与 $C’$ 相比较<ul><li>无错误: 发送 $D’$</li><li>有错误并可以纠正,发送 $D’’$</li><li>有错误且不能纠正, 报告</li></ul></li></ul></li></ul><h2 id="奇偶校验法"><a href="#奇偶校验法" class="headerlink" title="奇偶校验法"></a>奇偶校验法</h2><ul><li>过程<br>$D=D_M…D_2D_1$<ul><li>奇校验: $D_M \oplus …D_2 \oplus D_1 \oplus 1$</li><li>偶校验: $D_M \oplus …D_2 \oplus D_1$</li><li>检查 $S=C’ \oplus C’’$<ul><li>$S=1$ 错误的位数为奇数</li><li>$S=0$ 错误的位数为偶数或者无错误</li><li>注意: 此处是指$C$与$D$合在一起</li></ul></li></ul></li><li>优势:<ul><li>廉价</li></ul></li><li>劣势:<ul><li>无法确定出错的位置</li><li>无法纠正错误</li></ul></li><li>适用于较短的 $D$</li></ul><h2 id="汉明码"><a href="#汉明码" class="headerlink" title="汉明码"></a>汉明码</h2><ul><li>基本思想:<ul><li>将数据的位分组, 每位都分到多个组且分到的组的情况不同, 每个组中奇偶校验产生一位校验码, 最后根据所有组的校验码可以定位到这位数据</li><li><strong>前提</strong>:仅有一位出错</li></ul></li><li>具体过程:<ul><li>将 $M$ 位数据 $D$ 分成 $K$ 组</li><li>每个组中产生一位奇偶校验码, 最终产生一位$K$ 位的校验码 $C’$</li><li>由 $D’$ 产生 $C’’$</li><li>检查: 故障字 $SW=C’\oplus C’’$, 长度为 $K$ 位</li></ul></li><li>校验码的长度<ul><li>要确保故障字的情况能够包含所有的情况在内.即<script type="math/tex">2^K\geq 1+ M+K</script><br>其中 $K$ 为校验码出错情况,$M$ 为数据出错情况, 1 未出错情况</li></ul></li><li>故障字分析:<ul><li>如果是数据位出错,那么至少有两位校验码会出错, 即故障字至少有两位为1,可得下面规则<ul><li>全为0 : 没有错误</li><li>只有一位为 1: 校验码 $C’$ 出错,无需纠正</li><li>多位为 1: 数据位出错,需要纠正(对相应位置的数据取反)</li></ul></li></ul></li><li>数据位划分<ul><li>以 8 位的数据 $D = D_8…D_2D_1$为例子，校验码$C_1C_2C_3C_4$</li><li>关系如下<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/2baad364b5a440170c2aa4414d5a2e8c5a2a7f1f.jpg"/><br>数据在传输的时候也正是这样穿插进行的</li><li>数据位划分<script type="math/tex; mode=display">\begin{aligned}C_{1}=D_{1} \oplus D_{2} \oplus D_{4} \oplus D_{5} \oplus D_{7} \\C_{2}=D_{1} \oplus D_{3} \oplus D_{4} \oplus D_{6} \oplus D_{7} \\C_{3}=D_{2} \oplus D_{3} \oplus D_{4} \oplus D_{8} \\C_{4}=D_{5} \oplus D_{6} \oplus D_{7} \oplus D_{8}\end{aligned}</script></li></ul></li></ul><h2 id="循环冗余校验-CRC"><a href="#循环冗余校验-CRC" class="headerlink" title="循环冗余校验 (CRC)"></a>循环冗余校验 (CRC)</h2><ul><li>奇偶校验问题:<ul><li>需要将数据 划分为字节级</li><li>额外开销很大</li></ul></li><li>CRC 适用于以流形式存储和传输大型数据</li><li>用数学函数产生数据和校验码的关系</li><li>过程:<ul><li>对于 $n$ 位的数据 $D$, 次数为 $K$ 的生成多项式(用二进制表示的话有 $K+1$ 位),需要将 $D$ 左移 $K$ 位.</li><li>进行模二取余的除法运算, 具体过程如下图:<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/42ae5b4ac3450a3bf179f67b6827527ba37e9b7c.gif@518w.gif"/></li></ul></li><li>检查:<ul><li>将 $n+k$ 位的内容对生成多项式做上述操作,如果无误,所得结果为0</li></ul></li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(九) RAID 磁盘冗余阵列</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_09/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_09/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><h2 id="RAID"><a href="#RAID" class="headerlink" title="RAID"></a>RAID</h2><h3 id="基本思想"><a href="#基本思想" class="headerlink" title="基本思想"></a>基本思想</h3><p>使用多个磁盘, 分散的 I/O 请求, 以至于单一的 I/O 请求可以被并行处理, 只要请求的数据分散在不同的磁盘上.</p><h3 id="特点"><a href="#特点" class="headerlink" title="特点"></a>特点</h3><ol><li>RAID 是被视为<strong>一块逻辑磁盘</strong>的一组物理磁盘.</li><li>数据交叉分布在物理磁盘上.</li><li>冗余的磁盘可用于存储奇偶校验信息, 以保证再磁盘故障的情况下的数据可恢复性.</li></ol><h2 id="RAID-0"><a href="#RAID-0" class="headerlink" title="RAID 0"></a>RAID 0</h2><p>数据在可用的磁盘上<strong>条带</strong> (strip) 状排列, 如果数据跨物理磁盘, 则同时读写</p><p>不含冗余盘</p><p><strong>用途</strong>:</p><ul><li>高速率数据传输</li><li>高速 I/O 请求</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/5c640fb591dd2ac5f4fb02edd077ebdc49f6e700.jpg" style="zoom:67%;" /></p><p>与单个的大容量磁盘相比: </p><p>​    <strong>优点</strong>: 若两个不同的 I/O 请求等待不同的两块数据, 如果这两块数据位于不同的物理磁盘, 就能加速.</p><p>​    <strong>缺点</strong>: 若数据跨盘, 只要其中的一块硬盘坏了, 所有的都不能读取.</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/b1cdc3c889a42b58f7db4790cdaadd03a1480418.jpg" style="zoom:67%;" /></p><h2 id="RAID-1"><a href="#RAID-1" class="headerlink" title="RAID 1"></a>RAID 1</h2><p>所有的数据都按 RAID 0 的方式存取, 只是每个数据都存两份 ( 镜像 ).</p><p><strong>优点</strong>: 恢复很简单, 可以加速读取 ( 若两块硬盘中同时有这个数据 ).</p><p><strong>缺点</strong>: 浪费, 性能会降低为较慢的盘.</p><p><strong>用途</strong>: 仅用于存储系统文件, 数据和其他高度关键文件的驱动器.</p><p>与 RAID 0 相比:</p><ul><li>若请求的大部分是读取, RAID 1 可以实现较高的 I/O 请求率, 性能几乎是 RAID 0 的两倍.</li><li>若大部分是写请求, 性能没有显著的优势.</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/cebac2dff8b13ac60b2d07856d55b1d8daee2029.jpg" style="zoom:67%;" /></p><h2 id="RAID-2-未商业化"><a href="#RAID-2-未商业化" class="headerlink" title="RAID 2 (未商业化)"></a>RAID 2 (未商业化)</h2><p>使用<strong>并行存取技术</strong>(为一个客户服务):</p><ul><li>所有的成员磁盘参与 I/O 的运算,</li><li>各自驱动器的轴是同步旋转的, 以便每个磁盘磁头的位置在同一时刻是相同的.</li></ul><p>使用数据条带: 条带很小, 一个字节或者一个字.</p><p><strong>纠错机制</strong>:</p><ul><li>每个磁盘相应位置计算校验码, 并存在多个校验盘的相应位置上.通常使用<strong>汉明码</strong>.</li><li>读: 获取所请求的数据以及校验码.</li><li>写: 必须访问所有的数据盘和校验盘.</li></ul><p><strong>优点</strong>: </p><ul><li>高速率数据传输</li><li>数据丢失可以恢复</li></ul><p>缺点: </p><ul><li>I/O 响应慢,  同时只能处理一个 I/O</li><li>成本过高, 因为磁盘可靠性已经得到了极大提高, 不容易出现大量错误</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/25f37c6b45723246e13639184a33eda269778c1a.jpg" style="zoom:67%;" /></p><h2 id="RAID-3"><a href="#RAID-3" class="headerlink" title="RAID 3"></a>RAID 3</h2><p>使用<strong>并行存取技术</strong>.</p><p>使用很小的条带</p><p><strong>纠错机制</strong>:</p><ul><li><p>一个奇偶校验盘, 存有数据盘相同位置数据的奇偶校验码</p></li><li><p>若有一个磁盘失效, 可以由其他磁盘和校验盘恢复出这个数据, 如 $b_0$ 失效:</p><script type="math/tex; mode=display">b_0 = P(b)\ \oplus b_1 \oplus b_2 \oplus b_3</script><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/c14185b2896bf704dbdffd8eb15818f8a4ab3f5d.jpg" style="zoom:67%;" /></p></li></ul><p>性能:</p><ul><li>高速率传输数据, 对大型传输改善尤为明显.</li><li>一次只能执行一个 I/O 请求</li></ul><h2 id="RAID-4-未实现商业化"><a href="#RAID-4-未实现商业化" class="headerlink" title="RAID 4(未实现商业化)"></a>RAID 4(未实现商业化)</h2><p>使用<strong>独立访问技术</strong>: 期望每个成员磁盘独立操作, 可以独立地并行完成 I/O 请求.</p><p>使用较大的数据条带</p><p>纠错机制: 每个数据盘上相应的条带上逐位计算奇偶校验带, 存储在奇偶校验盘的相应位置.</p><p>性能: </p><ul><li><p>执行小规模 I/O 写请求时, RAID 4 遭受写损失</p></li><li><p>每次写操作, 阵列管理软件不仅需要更新数据 , 还需要更新对应的奇偶校验码. 两读两写.</p><script type="math/tex; mode=display">P' = P \oplus b_0\oplus b_0'</script></li><li><p>涉及大规模 I/O 写入, 仅根据新数据原数据和校验码就能得到新的校验码.</p></li><li><p>冗余盘不能同时进行多个 I/O 操作, 成为写的瓶颈.</p></li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/82cb8a6c55db2048f293916b87988b3e9e419f7e.jpg" style="zoom:67%;" /></p><h2 id="RAID-5"><a href="#RAID-5" class="headerlink" title="RAID 5"></a>RAID 5</h2><p>与 RAID 4 相类似, 但是没有专门的冗余盘, 而是分散到各个盘, 减少了 I/O 瓶颈.</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/baf3a2e585eaa2a9c04472f81049dc165ad591fc.jpg" style="zoom:67%;" /></p><h2 id="RAID-6"><a href="#RAID-6" class="headerlink" title="RAID 6"></a>RAID 6</h2><p>多一块磁盘, 两种纠错码相互印证.</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/329222880f592d912c0168da0ee8dd5d85a0c895.jpg" style="zoom:67%;" /></p>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(十) 内存管理</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_10/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_10/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><p>过去, 只有操作系统和一个程序在内存中.</p><p>现在, 操作系统和多个程序都在内存中. 程序等待 I/O 时, 为了避免处理器等待, 需要进行优化, 使得更多的程序可以加载入内存.</p><p><strong>内存管理:</strong> 在多程序设计系统中, 内存的 “用户部分” 应该被进一步划分以适应多个程序, 这是由系统动态决定的.</p><h2 id="加载更多程序的途径"><a href="#加载更多程序的途径" class="headerlink" title="加载更多程序的途径"></a>加载更多程序的途径</h2><ul><li><p>增大内存    </p></li><li><p>使用交换和重叠技术</p><ul><li><p>当没有程序就绪的时候, 系统载入程序</p></li><li><p><strong>分区</strong>和<strong>分页</strong></p></li></ul></li><li><p>虚拟内存</p><ul><li>请求分页</li><li>虚拟地址</li></ul></li></ul><h2 id="分区"><a href="#分区" class="headerlink" title="分区"></a>分区</h2><h3 id="固定大小分区"><a href="#固定大小分区" class="headerlink" title="固定大小分区"></a>固定大小分区</h3><p>系统: 固定的大小</p><p>用户程序: 固定的大小, 但各不相同. 当加载一个程序的时候, 将其载入刚好能够容纳下这个程序的最小的区中.</p><p>缺点: 产生大量内部碎片.</p><p><img src="data:image/webp;base64,iVBORw0KGgoAAAANSUhEUgAAAIMAAAFLCAYAAAD1UT8LAAAH8HRFWHRteGZpbGUAJTNDbXhmaWxlJTIwaG9zdCUzRCUyMjg5NzgzZWM2LWE1YTAtNDU3MC1iZjJlLTc3NTExYTYwMzBlMCUyMiUyMG1vZGlmaWVkJTNEJTIyMjAyMC0xMi0xM1QxNyUzQTIwJTNBNDkuMzE5WiUyMiUyMGFnZW50JTNEJTIyNS4wJTIwKFdpbmRvd3MlMjBOVCUyMDEwLjAlM0IlMjBXaW42NCUzQiUyMHg2NCklMjBBcHBsZVdlYktpdCUyRjUzNy4zNiUyMChLSFRNTCUyQyUyMGxpa2UlMjBHZWNrbyklMjBDb2RlJTJGMS41MS4xJTIwQ2hyb21lJTJGODMuMC40MTAzLjEyMiUyMEVsZWN0cm9uJTJGOS4zLjMlMjBTYWZhcmklMkY1MzcuMzYlMjIlMjB2ZXJzaW9uJTNEJTIyMTMuMTAuMCUyMiUyMGV0YWclM0QlMjJ4STNoWTM1V19zQkpFekZiRFZ3NCUyMiUyMHR5cGUlM0QlMjJlbWJlZCUyMiUzRSUzQ2RpYWdyYW0lMjBpZCUzRCUyMjlrUXY2NDRzaXYwYjJoX05FMVpjJTIyJTIwbmFtZSUzRCUyMlBhZ2UtMSUyMiUzRSUzQ214R3JhcGhNb2RlbCUyMGR4JTNEJTIyNDU4JTIyJTIwZHklM0QlMjI4MjklMjIlMjBncmlkJTNEJTIyMSUyMiUyMGdyaWRTaXplJTNEJTIyMTAlMjIlMjBndWlkZXMlM0QlMjIxJTIyJTIwdG9vbHRpcHMlM0QlMjIxJTIyJTIwY29ubmVjdCUzRCUyMjElMjIlMjBhcnJvd3MlM0QlMjIxJTIyJTIwZm9sZCUzRCUyMjElMjIlMjBwYWdlJTNEJTIyMSUyMiUyMHBhZ2VTY2FsZSUzRCUyMjElMjIlMjBwYWdlV2lkdGglM0QlMjI4MjclMjIlMjBwYWdlSGVpZ2h0JTNEJTIyMTE2OSUyMiUyMG1hdGglM0QlMjIwJTIyJTIwc2hhZG93JTNEJTIyMCUyMiUzRSUzQ3Jvb3QlM0UlM0NteENlbGwlMjBpZCUzRCUyMjAlMjIlMkYlM0UlM0NteENlbGwlMjBpZCUzRCUyMjElMjIlMjBwYXJlbnQlM0QlMjIwJTIyJTJGJTNFJTNDbXhDZWxsJTIwaWQlM0QlMjIzJTIyJTIwdmFsdWUlM0QlMjJPUyUyMiUyMHN0eWxlJTNEJTIycm91bmRlZCUzRDAlM0J3aGl0ZVNwYWNlJTNEd3JhcCUzQmh0bWwlM0QxJTNCJTIyJTIwdmVydGV4JTNEJTIyMSUyMiUyMHBhcmVudCUzRCUyMjElMjIlM0UlM0NteEdlb21ldHJ5JTIweCUzRCUyMjE2MCUyMiUyMHklM0QlMjIzNjAlMjIlMjB3aWR0aCUzRCUyMjEyMCUyMiUyMGhlaWdodCUzRCUyMjQwJTIyJTIwYXMlM0QlMjJnZW9tZXRyeSUyMiUyRiUzRSUzQyUyRm14Q2VsbCUzRSUzQ214Q2VsbCUyMGlkJTNEJTIyNCUyMiUyMHZhbHVlJTNEJTIyNjRLJTIyJTIwc3R5bGUlM0QlMjJyb3VuZGVkJTNEMCUzQndoaXRlU3BhY2UlM0R3cmFwJTNCaHRtbCUzRDElM0IlMjIlMjB2ZXJ0ZXglM0QlMjIxJTIyJTIwcGFyZW50JTNEJTIyMSUyMiUzRSUzQ214R2VvbWV0cnklMjB4JTNEJTIyMTYwJTIyJTIweSUzRCUyMjQwMCUyMiUyMHdpZHRoJTNEJTIyMTIwJTIyJTIwaGVpZ2h0JTNEJTIyNDAlMjIlMjBhcyUzRCUyMmdlb21ldHJ5JTIyJTJGJTNFJTNDJTJGbXhDZWxsJTNFJTNDbXhDZWxsJTIwaWQlM0QlMjI1JTIyJTIwdmFsdWUlM0QlMjIxMjhLJTIyJTIwc3R5bGUlM0QlMjJyb3VuZGVkJTNEMCUzQndoaXRlU3BhY2UlM0R3cmFwJTNCaHRtbCUzRDElM0IlMjIlMjB2ZXJ0ZXglM0QlMjIxJTIyJTIwcGFyZW50JTNEJTIyMSUyMiUzRSUzQ214R2VvbWV0cnklMjB4JTNEJTIyMTYwJTIyJTIweSUzRCUyMjQ0MCUyMiUyMHdpZHRoJTNEJTIyMTIwJTIyJTIwaGVpZ2h0JTNEJTIyODAlMjIlMjBhcyUzRCUyMmdlb21ldHJ5JTIyJTJGJTNFJTNDJTJGbXhDZWxsJTNFJTNDbXhDZWxsJTIwaWQlM0QlMjI2JTIyJTIwdmFsdWUlM0QlMjIyNTZLJTIyJTIwc3R5bGUlM0QlMjJyb3VuZGVkJTNEMCUzQndoaXRlU3BhY2UlM0R3cmFwJTNCaHRtbCUzRDElM0IlMjIlMjB2ZXJ0ZXglM0QlMjIxJTIyJTIwcGFyZW50JTNEJTIyMSUyMiUzRSUzQ214R2VvbWV0cnklMjB4JTNEJTIyMTYwJTIyJTIweSUzRCUyMjUyMCUyMiUyMHdpZHRoJTNEJTIyMTIwJTIyJTIwaGVpZ2h0JTNEJTIyMTYwJTIyJTIwYXMlM0QlMjJnZW9tZXRyeSUyMiUyRiUzRSUzQyUyRm14Q2VsbCUzRSUzQyUyRnJvb3QlM0UlM0MlMkZteEdyYXBoTW9kZWwlM0UlM0MlMkZkaWFncmFtJTNFJTNDJTJGbXhmaWxlJTNFcLdt7gAADMJJREFUeF7tnb9LXE8bxcfStGtnY2c6QdKJtfYptlAriwUVQSWN4o8o2C6YbGGRarWw8A+wSaO2AUsbWQKBpLDV0i/PkFnGu+tL7svlec7MPTbi7vWec8/53LmzW8yMOP4wgb8JjDAJJhASIAxkoZ8AYSAMhIEMDCbw1sjwwrCyT2Cg+zdheHkhD7niMDLiaycMuRZc5roIQ5m0Mj+WMGRecJnLIwxl0sr8WMKQecFlLo8wlEkr82MJQ+YFl7k8wlAmrcyPJQyZF1zm8ghDmbQyP5YwZF5wmcsjDGXSyvxYwpB5wWUujzCUSSvzY2sPw/Pzs9vY2HCnp6e+6rm5OXd+fu4ajUa/+vv7e9dsNt3d3Z1/rdVquXa77UZHR7PCo9YwPD4+uoWFBbe0tOR/y8/t7a1bXV11FxcXbnJy0gUQOp2Om5mZ8cccHR25X79+ZQdErWGQEeDh4cHt7u6+usPj1wUOKT8eLQSQ9fV1d3Jy4oHJ5ae2MITHg4wK4Y4PpcYAyGsyavz+/bs/WuRSfvE6CMMQGOTOPzg4cF+/fu3PHWRkWFxc9PlNTU1lCQZh+EcY4rto2KMjh9GitjBIef8yZ5BjwqMiFC4Tz7W1NT96cM6Qw23gnPvXTxPFyaIA0u12Bz6Cph5LrUcGKe//+Z5h2HcRqYMg/msPQw4lVnUNhKGqJDM4D2HIoMSqLoEwVJVkBuchDBmUWNUlEIaqkszgPIQhgxKrugTCUFWSGZyHMGRQYlWXQBiqSjKD8xCGDEqs6hIIQ1VJZnAewpBBiVVdAmGoKskMzkMYMiixqksoDUNVwjwPbAJc+g+2GkVjpUcGLgqq2I6yFGFQDhxZjjAgt6PsjTAoB44sRxiQ21H2RhiUA0eWIwzI7Sh7IwzKgSPLEQbkdpS9EQblwJHlCANyO8reCINy4MhyhAG5HWVvhEE5cGS52sIgK7jt7e35bs7OzvpL/4WywkIeshKcLAA2bIW3sCzgx48fB1aMQy79LW+1hEFWXrm+vvbrOD49PQ1dkifAcnNzMxSGYetDpghA7Ll2MMhKLfv7+255efnN9ZhkAS9ZpqfX6/k7vjgyjI2N+ZEkvJc6BMF/7WCQ4X9nZ8eDsLm5OfCYCIt3yQJeMjoUYZBHi7werypLGBJNIMwF5G6XootzgbC62/z8/Ku7v7h+9LB5RqKR9G3XcmSIl+0LC3zNzs66Dx8+uG/fvrnPnz/7uUT8KAgwfPr0yR8nC4vH60mnDoL4rx0MxWWCYxgkkLAKbFyuTCJlnhAvAZjjwqC1g0FKLi4UHq8iX+ajZW6ry9cSBik8/p4hfHyMR4N/+Z4hHDMxMZHFdgO1hSGHZ3zV10AYqk404fMRhoTLq9o6Yag60YTPRxgSLq9q64Sh6kQTPh9hSLi8qq0ThqoTTfh8hCHh8qq2ThiqTjTh8xGGhMur2jphqDrRhM9HGBIur2rrhKHqRBM+H2FIuLyqrZeGoWoDPB9cAlwHEq4SA0OlRwauA2nQkpIkYVAKOgUZwpBCS0oeCYNS0CnIEIYUWlLySBiUgk5BhjCk0JKSR8KgFHQKMoQhhZaUPBIGpaBTkCEMKbSk5JEwKAWdggxhSKElJY+EQSnoFGQIQwotKXkkDEpBpyBDGFJoSckjYVAKOgUZwpBCS0oeCYNS0CnIEIYUWlLySBiUgk5BhjCk0JKSR8KgFHQKMoQhhZaUPBIGpaBTkCEMKbSk5JEwKAWdggxhSKElJY+EQSnoFGQIQwotKXkkDEpBpyBDGFJoSckjYVAKOgWZ2sEQb1YmBYXd605PT31frVarv99U/N7U1JS7uLjwm6MW96+S/8thv6pawSAgyFaFh4eH/Y3Mw6amsodlvK2h/C2bmsmPbIYab10or8V7XgYQUt8FtzYwhG0Hp6en3Z8/f97c1T5smn58fOy2t7edbH4qxcc748Z7Ycv5NjY2+sel8Dh4y2NtYAgBFB8TxWDi0SCA0W633Y8fP/xIEY8kW1tb7vLy0o2Pj78JV0pwEIaorWG72IZHSzyXCI+Fq6sr/9/xYyel8oteCcPfRASEeOfb4vxh2GNCNldfWVnxj5HU5wsSA2H4ux1yt9v1j4BGo+HxiMuXTxAxHPPz8wObpsf7ZKc6OtQehrc2OB82MjSbTdfpdNz79+9fwSDlC0hFoFKDovYwxHtih/LC/ODp6cmXHuYGZ2dn/u9h3zMEeHq93qsRJiUgagdDSuVoeyUM2okD6xEG4HK0rREG7cSB9QgDcDna1giDduLAeoQBuBxta4RBO3FgPcIAXI62NcKgnTiwHmEALkfbGmHQThxYjzAAl6NtjTBoJw6sRxiAy9G2Rhi0EwfWIwzA5WhbIwzaiQPrEQbgcrStEQbtxIH1CANwOdrWCIN24sB6hAG4HG1rhEE7cWA9wgBcjrY1wqCdOLAeYQAuR9saYdBOHFiPMACXo22NMGgnDqxHGIDL0bZGGLQTB9YjDMDlaFsjDNqJA+sRBuBytK2VhkHbIPXUExgpKg688PeAl5eXF3V3FNRJoPTIQBh0irFQIQwWqYNqEgbQYixsEQaL1EE1CQNoMRa2CINF6qCahAG0GAtbhMEidVBNwgBajIUtwmCROqgmYQAtxsIWYbBIHVSTMIAWY2GLMFikDqpJGECLsbBFGCxSB9UkDKDFWNgiDBapg2oSBtBiLGwRBovUQTUJA2gxFrYIg0XqoJqEAbQYC1uEwSJ1UE3CAFqMhS3CYJE6qCZhAC3GwhZhsEgdVJMwgBZjYYswWKQOqkkYQIuxsEUYLFIH1SQMoMVY2CIMFqmDahIG0GIsbBEGi9RBNQkDaDEWtgiDReqgmoQBtBgLW4TBInVQTcIAWoyFLcJgkTqoJmEALcbCFmGwSB1UkzCAFmNhizBYpA6qSRhAi7GwRRgsUgfVJAygxVjYIgwWqYNqEgbQYixsEQaL1EE1CQNoMRa2CINF6qCahAG0GAtbhMEidVBNwgBajIUtwmCROqgmYQAtxsIWYbBIHVSTMIAWY2GLMFikDqpJGECLsbBFGCxSB9UkDKDFWNgiDBapg2oSBtBiLGwRBovUQTUJA2gxFrYIg0XqoJqEAbQYC1uEwSJ1UE3CAFqMhS3CYJE6qGZtYDg6OnJ7e3u+hrm5OXd+fu4ajYb/O35P/j47O3MLCwsD74XXHx8f/fu7u7tuZmbGHxdem5iYcO12242OjoJW/ratWsBwe3vrvn//7ssL5ctv+fv5+dltbGy4paWlfrEhLgHm+vral/v09OTW1tbcwcGBGxsbewVDAEHOESBKjgTnXC1gKBYjcMhoIGXLTyh5cnKyf6hAsr+/75aXl138ejwKCEzT09MeptnZ2aRBkOuqJQzxHf/z50/XbDbd3d2dB6HVavVHgp2dHQ/C5uamf6/4mNja2nKXl5dufHy8P+qkOCIEz7WD4f7+3q2vr7uTkxNfdDxKvHv3zt/lUu7Kyoq/02VOICNA/H/hMXF1deVzPDw8JAyp3QVSqIwCnU5nYH4QriXA8eXLFz/hlDmCQBPmFvI4mJ+f74MSoEl9vlCrx4SUvLq66i4uLgbmADHUcly323XHx8due3u7P7EcBkP4NFEcbVK7SWr1mPhfZcn84eHh4dUnizAZjN+LYSp+mpAw5ViBKP7ImhoUtZgzSEGLi4uvuom/a4i/Zyg+/+P3bm5u/ONl2PcMYeTo9XrJAlELGFK7Q638Egar5AF1CQNgKVaWCINV8oC6hAGwFCtLhMEqeUBdwgBYipUlwmCVPKAuYQAsxcoSYbBKHlCXMACWYmWJMFglD6hLGABLsbJEGKySB9QlDIClWFkiDFbJA+oSBsBSrCwRBqvkAXUJA2ApVpYIg1XygLqEAbAUK0uEwSp5QF3CAFiKlSXCYJU8oC5hACzFyhJhsEoeUJcwAJZiZYkwWCUPqEsYAEuxskQYrJIH1CUMgKVYWSIMVskD6hIGwFKsLBEGq+QBdQkDYClWlgiDVfKAuoQBsBQrS4TBKnlAXcIAWIqVJcJglTygLmEALMXKEmGwSh5QlzAAlmJliTBYJQ+oSxgAS7GyRBiskgfUJQyApVhZIgxWyQPqEgbAUqwsEQar5AF1CQNgKVaWCINV8oC6hAGwFCtLhMEqeUBdwgBYipUlwmCVPKAuYQAsxcoSYbBKHlCXMACWYmWJMFglD6hLGABLsbJEGKySB9QlDIClWFkiDFbJA+oSBsBSrCwRBqvkAXUJA2ApVpYIg1XygLqEAbAUK0uEwSp5QF3CAFiKlSXCYJU8oC5hACzFyhJhsEoeUJcwAJZiZak0DFZGqauWwEhRaeAFNSsUgkuAMMBVYmeIMNhlD6dMGOAqsTNEGOyyh1P+D/2C1MRfzr3XAAAAAElFTkSuQmCC" style="cursor:pointer;max-width:100%;" onclick="(function(img){if(img.wnd!=null&&!img.wnd.closed){img.wnd.focus();}else{var r=function(evt){if(evt.data=='ready'&&evt.source==img.wnd){img.wnd.postMessage(decodeURIComponent(img.getAttribute('src')),'*');window.removeEventListener('message',r);}};window.addEventListener('message',r);img.wnd=window.open('https://viewer.diagrams.net/?client=1&page=0&edit=_blank');}})(this);"/></p><h3 id="可变大小分区"><a href="#可变大小分区" class="headerlink" title="可变大小分区"></a>可变大小分区</h3><p>系统: 固定的大小</p><p>用户程序: 按需分配</p><p>缺点: 产生大量外部碎片</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/03a8d63fbcb773d9b684288d894255ee5fa00838.webp" style="zoom:67%;" /></p><h2 id="分页"><a href="#分页" class="headerlink" title="分页"></a>分页</h2><p>基本思想:</p><ul><li><p>将内存分为固定大小的块, 称为<strong>页框</strong>(页帧), 将程序分为固定大小的块, 称为<strong>页</strong></p></li><li><p>将页加载入页框中</p></li></ul><p><strong>逻辑地址:</strong> 指令中的地址</p><p><strong>物理地址:</strong>主存中的地址</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/cadfd03860469d165472ec6279b4aed1e349eea9.webp" style="zoom: 67%;" /></p><h2 id="虚拟内存"><a href="#虚拟内存" class="headerlink" title="虚拟内存"></a>虚拟内存</h2><p>内存的大小是有限的，但是对内存的需求在不断增加</p><p><strong>基本思想：</strong>请求分页，一个进程的页只有在需要的时候才被调入</p><p>本质：</p><ul><li>在比内存大的逻辑地址空间中编程</li><li>只调入需要的程序和数据</li><li>通过硬件将逻辑地址转化为物理地址</li><li>当发生页缺失的时候在内存和硬盘之间交换信息</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/a234581cc2a822f4f6f02684b41da95ca8950d73.webp" style="zoom:80%;" /></p><h3 id="一些问题"><a href="#一些问题" class="headerlink" title="一些问题"></a>一些问题</h3><ul><li>页的大小: 4KB, 8Kb…</li><li>映射函数: 关联映射</li><li>类型:<ul><li>基于页的虚拟内存</li><li>基于段的虚拟存储器</li><li>基于段和页的虚拟内存</li></ul></li><li>写策略: 写回</li></ul><h3 id="基于页的虚拟内存"><a href="#基于页的虚拟内存" class="headerlink" title="基于页的虚拟内存"></a>基于页的虚拟内存</h3><p>将主存和虚拟内存分成相同大小的页</p><ul><li>虚页(Virtual page)/逻辑页(Logical page): 虚拟内存中的页</li><li>物理页(Physical page)/页框(page frame): 主存中的页</li></ul><p>页表:</p><ul><li>包含着所有虚页的信息, 包括位置, 有效位, 脏位, 可读写位</li><li>存储在主存中</li><li>虚拟地址 $&lt;-$ 虚页号 + 页内地址 (偏移量)</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/37719366f70bb69d22383fce2f2e421fe635940a.webp" alt="页表" style="zoom:67%;" /></p><h3 id="快表-TLB"><a href="#快表-TLB" class="headerlink" title="快表 (TLB)"></a>快表 (TLB)</h3><p>页表的使用增加了主存的访问</p><p>为了减少访问主存, 将最常用的页表项加载进 cache</p><p><strong>TLB:</strong> 页表项被载入 cache </p><ul><li>全相联映射, 组关联映射</li><li>随机替换策略</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/66ee27fdf8bb2574adf0f46387f468218d6602ca.webp" style="zoom:67%;" /></p><div class="table-container"><table><thead><tr><th>No.</th><th>TLB</th><th>page table</th><th>cache</th><th>possibility</th><th></th></tr></thead><tbody><tr><td>1</td><td>hit \</td><td>valid</td><td>————-</td><td>hit</td><td>possible, in cache</td><td></td></tr><tr><td>2</td><td>hit \</td><td>invalid</td><td>————-</td><td>hit</td><td>impossible</td><td></td></tr><tr><td>3</td><td>hit \</td><td>invalid</td><td>————-</td><td>miss</td><td>impossible</td><td></td></tr><tr><td>4</td><td>hit \</td><td>valid</td><td>————-</td><td>miss</td><td>possible, in memory bu not in cache</td><td></td></tr><tr><td>5</td><td>miss</td><td>valid</td><td>hit</td><td>possible, in cache</td><td></td></tr><tr><td>6</td><td>miss</td><td>invalid</td><td>hit</td><td>impossible</td><td></td></tr><tr><td>7</td><td>miss</td><td>valid</td><td>miss</td><td>possible, in memory bu not in cache</td><td></td></tr><tr><td>8</td><td>miss</td><td>invalid</td><td>miss</td><td>possible, not in memory</td></tr></tbody></table></div><p>ps: 快表中只有 valid 情况下才能算 hit</p><p>分析: </p><ul><li>最好: 1,    未访问内存</li><li>好      4, 5 只访问一次内存  </li><li>坏      7      两次访问主存</li><li>最坏   8      两次访问主存, 并访问硬盘</li></ul><h3 id="基于段的虚拟存储器"><a href="#基于段的虚拟存储器" class="headerlink" title="基于段的虚拟存储器"></a>基于段的虚拟存储器</h3><p>将程序和数据分成不同长度的段, 并将需要的段载入主存</p><p><strong>虚拟地址</strong>: 段号 + 段内偏移量</p><p>与基于页的虚拟内存相比:</p><ul><li>基于页的虚拟内存<ul><li>优势: 简单, 成本低<ul><li>劣势:指令和数据可能跨页</li></ul></li></ul></li><li>基于段的虚拟内存<ul><li>优势: 数据和程序自然划分</li><li>劣势: 长度并非固定</li></ul></li></ul><h3 id="基于段和页的虚拟内存"><a href="#基于段和页的虚拟内存" class="headerlink" title="基于段和页的虚拟内存"></a>基于段和页的虚拟内存</h3><p>将程序和数据划分为段, 并进一步将段划分为页, 每一个段都有它自己页表</p><p><strong>虚拟地址</strong>: 段号 + 页号 + 偏移量</p><p>优势: 程序在段中可以共享和保护</p><p>劣势: 需要多次查表</p><h2 id="补充-PA-中的内存管理部分"><a href="#补充-PA-中的内存管理部分" class="headerlink" title="补充 PA 中的内存管理部分"></a>补充 PA 中的内存管理部分</h2><h3 id="实模式"><a href="#实模式" class="headerlink" title="实模式"></a>实模式</h3><h4 id="8086的实模式"><a href="#8086的实模式" class="headerlink" title="8086的实模式"></a><strong>8086的实模式</strong></h4><ul><li>寄存器长度：16 位<ul><li>访问内存需要结合<strong>段寄存器</strong>(segment register)进行</li></ul></li><li>地址线：20 根</li><li>物理地址计算方式<ul><li>physical address = (seg_reg&lt;&lt;4)+offset，offset 为 16 位的偏移量</li><li>可寻址空间：$2^{20}$=1MB</li></ul></li></ul><h4 id="分段机制"><a href="#分段机制" class="headerlink" title="分段机制"></a>分段机制</h4><p>x86 的机器开机后首先进入实模式</p><ul><li>加载操作系统</li><li>操作系统初始化段表</li><li>拨动一个”开关”, 从实模式切换到保护模式</li></ul><p>进入保护模式后</p><ul><li>程序给出 48 位逻辑地址(16位段选择符 + 32 位有效地址)</li><li>使用段选择符来查段表</li><li>进行段级地址转换得到线性地址</li></ul><h4 id="分段机制-地址转换"><a href="#分段机制-地址转换" class="headerlink" title="分段机制(地址转换)"></a>分段机制(地址转换)</h4><p>80386 保护模式下的地址转换</p><ul><li><p>逻辑地址到线性地址的转换</p><ul><li><p><strong>逻辑地址</strong>: 48 位, 又叫虚拟地址,其中</p><p><strong>段选择符</strong>: 16 位(sreg对应的段寄存器的内容)</p><p><strong>段内偏移量</strong>(有效地址): 32 位(vaddr给出的32位地址)</p></li></ul></li></ul><p>  <img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/a251a56b74772c80ebcd9fc2ea7361bc26c6ab9c.webp" style="zoom:67%;" /></p>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(十一) 总线</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_11/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_11/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><h1 id="总线"><a href="#总线" class="headerlink" title="总线"></a>总线</h1><h2 id="芯片内部总线"><a href="#芯片内部总线" class="headerlink" title="芯片内部总线"></a>芯片内部总线</h2><p>连接芯片的各个部分</p><p>例如连接寄存器, ALU和 CPU 的其他部分</p><h2 id="通信总线"><a href="#通信总线" class="headerlink" title="通信总线"></a>通信总线</h2><p>连接主机和 I/O 设备或者连接不同的计算机系统</p><h2 id="系统总线"><a href="#系统总线" class="headerlink" title="系统总线"></a><font color = "red">系统总线</font></h2><p>连接 CPU, 主存, I/O 控制器和其他的功能设备</p><h3 id="内容"><a href="#内容" class="headerlink" title="内容"></a>内容</h3><p>总线可以分为三种功能组</p><ul><li><p>数据线: 在系统模块之间移动数据. 数据线的数量决定了一次能能够传送的数据的最大容量</p></li><li><p>地址线: 指定数据线上的数据的来源或者去向. 地址线也用于 I/O 端口的寻址. 地址线的数量决定了寻址空间的大小</p></li><li><p>控制线: 控制对数据和地址线路的访问和使用. </p><p>各种控制信号:</p><ul><li>时钟: 用于总线同步</li><li>总线请求(Bus Request): 表示模块需要获得对总线的控制</li><li>总线允许(Bus Grant): 表示发出请求的模块已经被允许控制总线</li><li>中断请求: 表示某个中断尚未被处理</li><li>中断响应: 未决的中断请求被响应</li><li>存储器写: 引起总线上的数据写入被寻址的单元</li><li>存储器读: 使所寻址的单元的数据放在总线上</li><li>I/O 读: 从 I/O 端口读取数据到总线</li><li>I/O 写: 将数据从总线写入到 I/O 端口</li></ul></li></ul><h3 id="设计要素"><a href="#设计要素" class="headerlink" title="设计要素"></a>设计要素</h3><h4 id="总线类型"><a href="#总线类型" class="headerlink" title="总线类型"></a>总线类型</h4><p><strong>专用:</strong></p><p>永久地分配给一个功能或者计算机部件的物理子集</p><p>优势:高吞吐率, 因为有更少的总线竞争</p><p>缺点: 增加了尺寸和成本</p><p><strong>复用:</strong></p><p>多种用途使用相同的线路</p><p>优势: 更少的线路, 节省了空间和成本</p><p>缺点: 每个模块中需要更加复杂的电路, 可能会降低共享的性能</p><h4 id="仲裁"><a href="#仲裁" class="headerlink" title="仲裁"></a>仲裁</h4><p>总线可以被多个设备监听, 但只能被一个设备发送信息</p><p><strong>总线仲裁:</strong> 当多个设备要与总线通信的时候, 用某种策略选择一台设备</p><p>平衡:</p><ul><li>优先级: 优先级高的设备应该先得到服务</li><li>公平性: 优先级最低的设备不可能永远被推迟</li></ul><p><strong>集中式:</strong></p><p>一个被称为<strong>总线控制器</strong>的单独的硬件设备, 负责位总线分配时间</p><ul><li><p>菊花链</p><p>所有的设备串行连接, 许可从最高优先级设备传到最低优先级设备</p><p>若一个设备收到授权, 并且有总线请求, 设置总线忙并且许可不再被传递.</p><p><strong>优势:</strong> 确定优先级很容易, 添加设备很灵活</p><p><strong>劣势:</strong>无法兼顾公平性, 对设备故障敏感, 限制了总线速度</p><p><img src = "https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/ad9ccc3d658ce27417fa4964c61f7b2b52890852.webp"></p></li></ul><ul><li><p>计数器查询</p><p>移除了总线许可线, 使用设备 ID 线.</p><p>若总线不繁忙, 仲裁器将通过设备 ID 线发送计数,  若设备 ID 线上的 ID 与一设备 ID 相同, 同时该设备发出请求, 则将总线设为忙, 同时停止计数</p><p><strong>优势:</strong>对电路故障不敏感, 可以通过灵活地报数来兼顾公平和优先性</p><p><strong>劣势:</strong>增加了 ID 线, 需要解码和比较 ID 信号</p><p>ps: ID 线是<strong>一组</strong>而不是一根</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/97b8bcebc5718ccae167c8a765ba5a92d06b55d6.webp" alt=""></p></li></ul><ul><li><p>独立请求</p><p>每个设备都有它的总线请求和总线许可线</p><p>当一个设备请求总线时, 它通过总线请求先向总线仲裁器发送请求信号.由仲裁器决定哪些设备可以使用总线.</p><p>确定策略: 固定优先级, 菊花链, LRU, FIFO</p><p><strong>优势:</strong>响应快,无等待, 优先级很灵活</p><p><strong>劣势:</strong>控制逻辑复杂, 更多的控制线</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/c4c6d3ea6471ed7ad051062bced6132865d48487.webp" alt=""></p></li></ul><p><strong>分布式:</strong></p><p>没有中央控制器,  而是在每个模块中包含访问控制逻辑, 这些模块共同作用, 分享总线.</p><ul><li><p>自举式</p><p>固定优先级</p><p>每个设备在它的总线请求线上发送请求, 最低优先级的设备没有请求线</p><p>每个设备独立决定它是否拥有最高优先级</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/dfebd1c7b50dd3f714b0ee0e58f6fcd438fb8c22.webp" alt=""></p></li><li><p>碰撞检测</p><p>当一个设备想要使用总线的时候, 检查总线是否为忙, 如果不忙, 使用总线.</p><p>若发生<strong>碰撞(冲突)</strong>,即两个设备发现总线不忙, 但是它们同时发起请求. 在数据传输时, 设备会监听总线, 检查是否存在碰撞, 如碰撞发生了, 所有使用总线的设备将停止数据传输, 并在随机持续一段时间后再次请求总线.                             </p></li></ul><h4 id="时序"><a href="#时序" class="headerlink" title="时序"></a>时序</h4><p>总线上协调时间的方式: 决定每个总线事务的开始和结束时间</p><ul><li><p><strong>同步时序</strong>: 总线上的事件的发生由时钟决定</p><p>总线事务: 地址 + 数据 + 数据 +…+ 数据</p><p>优势:容易实现 , 测试</p><p>劣势: 所有的设备共享时钟; 无法避免时钟漂移的影响</p><p><img src="image/README.assets/8e0b8a819ef420c0cc1d703b3160dcfb36fa55d7.webp" alt=""></p><p>  CLK 时钟, BReq 总线请求, BG 总线许可</p></li><li><p><strong>异步时序</strong>: 总线上一个事件的发生遵循并取决于前一个事件的发生</p><p>总线事务: 地址 + 数据 + 数据 +…+ 数据</p><p>使用 <strong>握手协议</strong></p><p>优势: 对速度不同的各种设备都很灵活</p><p>劣势: 对噪声敏感; 接口逻辑复杂</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/02a74fd69a419c5ef9bcf0e77b23edcd281803c1.webp" alt=""></p><p><strong>握手</strong>的样例: </p><p> <img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/27998c3a8bb48f3970e1eaf868e837d52094e858.webp" alt="">                </p><p> <img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/27babc06420cc8c0e436f97540af8e5e784e388b.webp" alt=""></p></li><li><p>半同步时序: 结合同步时序(时钟)和异步时序(握手)</p><p>为了减小噪声的影响, 在异步时序中使用时钟.时钟上升沿的就绪信号和应答信号都是有效的. 额外加一条等待线, 以协调不同速度的设备, 比如图中在第三个时钟周期时, Data1 尚未准备完毕, 所以继续等待直到 Data1 准备好, 释放等待线.</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/ce326c52f5da9ded6538dbd707f812facba524ea.webp" alt=""></p></li><li><p>分割事务: 分割总线事务: 当设备准备好数据时释放总线</p><p>将一个总线事务分割成两个过程</p><p><strong>优势:</strong>提高了总线利用率</p><p><strong>缺点:</strong>增加了每个总线事务的持续时间和系统复杂性</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/a44f52cef72189278f36692269324130069b39d4.webp" alt=""></p></li></ul><h4 id="总线带宽和数据传输率"><a href="#总线带宽和数据传输率" class="headerlink" title="总线带宽和数据传输率"></a>总线带宽和数据传输率</h4><p><strong>总线带宽</strong>:总线的最大数据传输率</p><ul><li>不考虑总线仲裁, 地址传送</li></ul><p><strong>数据传输率:</strong></p><ul><li>考虑地址传输</li></ul><p><strong>总线宽度:</strong>组成总线的总的线路数</p><ul><li>数据线越宽, 一次传输的位数就越大</li><li>地址总线越宽, 可寻址的范围也就越大</li></ul><h4 id="数据传输类型"><a href="#数据传输类型" class="headerlink" title="数据传输类型"></a>数据传输类型</h4>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(十二) 指令集: 特征</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_12/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_12/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><h2 id="机器指令特征"><a href="#机器指令特征" class="headerlink" title="机器指令特征"></a>机器指令特征</h2><p>CPU 的操作由它所执行的指令确定, 这些指令被称为<strong>机器指令</strong>. CPU 能执行的各种不同指令的集合称为 CPU 的<strong>指令集</strong></p><h3 id="指令周期"><a href="#指令周期" class="headerlink" title="指令周期"></a>指令周期</h3><p>指令周期: 指单条指令所需的处理过程</p><ul><li>取指令: 每次从内存中取一条指令</li><li>执行指令: 执行每条指令</li></ul><p>只有关机时, 程序执行才会停止, 或者遇到致命错误或者停止计算机的指令.</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/image (1).jpg" style="zoom:80%;" /></p><p>指令周期状态图:</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/image (1).jpg" style="zoom:80%;" /></p><h3 id="带有中断的指令周期"><a href="#带有中断的指令周期" class="headerlink" title="带有中断的指令周期"></a>带有中断的指令周期</h3><p>带有中断的指令周期:</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/image.jpg" style="zoom:80%;" /></p><p>带有中断的指令周期状态图:</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/image.jpg" style="zoom:80%;" /></p><h3 id="机器指令要素"><a href="#机器指令要素" class="headerlink" title="机器指令要素"></a>机器指令要素</h3><ul><li><p><strong>操作码:</strong>指定要执行的操作 </p></li><li><p><strong>源操作数引用:</strong>操作会涉及一个或多个源操作数， 这是操作所需的输入</p></li><li><p><strong>结果操作数引用:</strong>该操作可能产生一个结果</p></li><li><p><strong>下一指令引用:</strong>它告诉处理器这条指令执行完成后到哪儿去取下一条指令</p></li></ul><h3 id="指令表示"><a href="#指令表示" class="headerlink" title="指令表示"></a>指令表示</h3><ul><li>每条指令都由一个位序列表示</li><li>指令格式:指令被划分为字段，对应于指令的要素</li><li>对于大多数指令集，使用一种以上的格式</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/image (1).jpg" style="zoom:80%;" /></p><ul><li>符号表示:帮助程序员和教科书的读者处理指令</li><li>操作码用缩写表示，称为助记符</li><li>ADD: ADD, SUB: subtract, MUL: multiply, DIV: divide，</li><li>LOAD:从内存加载数据，STOR:将数据存储到内存</li><li>操作数也用符号表示</li><li>用寄存器名或内存地址替换操作数</li></ul><h3 id="指令类型"><a href="#指令类型" class="headerlink" title="指令类型"></a>指令类型</h3><ul><li><strong>数据处理</strong>:算数和逻辑指令</li><li><strong>数据存储</strong>: 存储器指令</li><li><strong>数据传送:</strong>I/O指令</li><li><strong>控制:</strong> 测试和分支(branch)能力</li></ul><h2 id="操作类型"><a href="#操作类型" class="headerlink" title="操作类型"></a>操作类型</h2><ul><li>Data transfer</li><li>Arithmetic</li><li>Logical</li><li>Conversion</li><li>I/O</li><li>System control</li><li>Transfer of control</li></ul><h2 id="操作数类型"><a href="#操作数类型" class="headerlink" title="操作数类型"></a>操作数类型</h2><ul><li>地址</li><li>数字</li><li>字符</li><li>逻辑(布尔)量</li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(十三) 指令集:寻址方式和指令格式</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_13/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_13/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a><a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><p>表示:</p><ul><li>A: 指令中地址字段的内容</li><li>R: 指向寄存器的指令字段的内容</li><li>EA: 被访问未知的实际(有效)地址</li><li>(X): 存储器位置 X 或者寄存器 X 的内容</li></ul><h2 id="立即寻址-Immediate-Addressing"><a href="#立即寻址-Immediate-Addressing" class="headerlink" title="立即寻址 (Immediate Addressing)"></a>立即寻址 (Immediate Addressing)</h2><p>操作数存在于指令中:</p><center>操作数 = A</center><p>应用: 定义和使用常数, 或者设置变量的初始值.</p><p>优点: 获取操作书不需要访问存储器, 只获取指令</p><p>缺点: 数字的大小被限制为地址字段的大小</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/COA_13.assets/image%20(2" alt="">.jpg)</p><h2 id="直接寻址-Direct-Addressing"><a href="#直接寻址-Direct-Addressing" class="headerlink" title="直接寻址 (Direct Addressing)"></a>直接寻址 (Direct Addressing)</h2><p>地址字段包含着操作数的有效地址, 早期计算机常见</p><center>    EA = A</center><p>优点: 只有一次存储器访问, 不需要进行专门计算</p><p>缺点: 只能提供有限的地址空间</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/COA_13.assets/8ff6aaf8a8134196fe5e560e0b8b8105b51e453a.jpg" alt=""></p><h2 id="间接寻址-Indirect-Addressing"><a href="#间接寻址-Indirect-Addressing" class="headerlink" title="间接寻址(Indirect Addressing)"></a>间接寻址(Indirect Addressing)</h2><p>指令中地址字段只是一个存储器字地址, 而这个地址保存着操作数的全长度地址</p><center>    EA = (A)</center><p>优点: 扩大了寻址空间</p><p>缺点: 需要访问两次内存来获取操作数</p><p>评价: 一次能够引用的不同地址数存在限制</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/COA_13.assets/image (2" alt="">.jpg)</p><h3 id="寄存器寻址-Register-Addressing"><a href="#寄存器寻址-Register-Addressing" class="headerlink" title="寄存器寻址 (Register Addressing)"></a>寄存器寻址 (Register Addressing)</h3><p>类似直接寻址, 地址字段指的时寄存器而不是一个主存地址.</p><center>    EA = R</center><p>优点: 指令中只需要一个很小的地址字段用来指向寄存器, 不需要访问内存</p><p>缺点: 寻址空间极其有限</p><p>注意: 只有寄存器得到了有效的使用才有意义</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/COA_13.assets/image.jpg" alt=""></p><h3 id="寄存器间接寻址-Register-Indirect-Addressing"><a href="#寄存器间接寻址-Register-Indirect-Addressing" class="headerlink" title="寄存器间接寻址(Register Indirect Addressing)"></a>寄存器间接寻址(Register Indirect Addressing)</h3><p>地址的字段指向一个寄存器</p><center>    EA = (R)</center><p>优点: 扩大了寻址空间, 比间接寻址少访问一次主存</p><p>劣势: ?</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/COA_13.assets/image (1" alt="">.jpg)</p><h3 id="偏移寻址-Displacement-Addressing"><a href="#偏移寻址-Displacement-Addressing" class="headerlink" title="偏移寻址(Displacement Addressing)"></a>偏移寻址(Displacement Addressing)</h3><p>结合直接寻址和间接寻址</p><center>    EA = (R) + A</center><p>指令中有两条地址字段, 其中至少一个是显性的. 其中一个地址字段(val = A) 被直接使用, 另一个地址字段指向寄存器. 寄存器的内容加上 A 产生有效地址.</p><p>三种偏移寻址:</p><p>1.<strong>相对寻址</strong></p><p>隐式引用的寄存器时程序计数器<code>PC</code>, 即当前 PC 的值 (为现执行指令的下一条指令的地址), 加上地址字段的值(A, 通常为补码整数), 得到有效地址</p><center>    EA = (PC) + A</center><p>优点: 利用了程序局部性的概念, 并在指令中保存了地址位.</p><p>用途: 子程序跳转?</p><p>2.<strong>基址寄存器寻址</strong></p><p>引用的寄存器含有一个主存地址, 地址字段含有一个相对于那个地址的偏移量(usually unsigned)</p><p>可以是显式引用, 也可以是隐式引用</p><center>    EA = (R) +A</center><p>3.<strong>变址</strong></p><p>地址字段引用一个主存地址, 被引用的寄存器对于那个地址有一个正的偏移量</p><center>    EA = A+(R)</center><p>用法: 高效完成重复操作, 将值 A 存入指令的地址字段, 选取一个寄存器作为变址寄存器, 初始化为0, 每次操作之后, 变址寄存器加1</p><p>扩展:结合间接寻址和变址:</p><ul><li><p>后变址: 间接寻址之后变址</p><center>    EA = (A) + (R)</center></li><li><p>前变址: 变址在间接寻址之前</p><center>    EA = (A+(R))</center></li></ul><h3 id="栈寻址"><a href="#栈寻址" class="headerlink" title="栈寻址"></a>栈寻址</h3><p>栈指针维护在寄存器中, 所以对内存栈位置的访问实际上是一种寄存器间接寻址方式.</p><p>注意: 与栈相关的是一个指针, 它的值可能是栈顶地址或者第三个元素的地址(前两个可能已经进入寄存器)</p><h2 id="指令格式"><a href="#指令格式" class="headerlink" title="指令格式"></a>指令格式</h2><p>指令长度, 位分配, 可变长度指令</p>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 基础(四) 容器与泛型</title>
      <link href="2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_04/"/>
      <url>2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_04/</url>
      
        <content type="html"><![CDATA[<h2 id="常用容器"><a href="#常用容器" class="headerlink" title="常用容器"></a>常用容器</h2><ul><li>常用 Collections</li></ul><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/Java_abc_06.assets/4ac92fdadbf8ac65a744814e500225e6382ebb55.webp" alt=""></p><h3 id="1-ArrayList"><a href="#1-ArrayList" class="headerlink" title="1. ArrayList"></a>1. ArrayList</h3><p>类似于 c++ 中 Vector 的存在<br><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><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="keyword">package</span> notebook;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">NoteBook</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> ArrayList&lt;String&gt; notes = <span class="keyword">new</span> ArrayList&lt;String&gt;();<span class="comment">//指定元素的类型</span></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">add</span><span class="params">(String s)</span> </span>&#123;</span><br><span class="line">        notes.add(s);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">insert</span><span class="params">(<span class="keyword">int</span> index, String s)</span> </span>&#123;</span><br><span class="line">        notes.add(index, s);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">getSize</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> notes.size();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getNote</span><span class="params">(<span class="keyword">int</span> index)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> notes.get(index);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">removeNote</span><span class="params">(<span class="keyword">int</span> index)</span> </span>&#123;</span><br><span class="line">        notes.remove(index);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> String[] list() &#123;</span><br><span class="line">        String[] a = <span class="keyword">new</span> String[notes.size()];</span><br><span class="line">        <span class="keyword">return</span> notes.toArray(a);<span class="comment">//这个方法可以把ArrayList中的内容存到数组里</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] arg)</span> </span>&#123;</span><br><span class="line">        NoteBook nb = <span class="keyword">new</span> NoteBook();</span><br><span class="line">        nb.add(<span class="string">&quot;你好&quot;</span>);</span><br><span class="line">        nb.add(<span class="string">&quot;不错&quot;</span>);</span><br><span class="line">        nb.add(<span class="string">&quot;邪王真眼&quot;</span>);</span><br><span class="line">        nb.removeNote(<span class="number">2</span>);</span><br><span class="line">        String[] a = nb.list();</span><br><span class="line">        <span class="comment">//for (String s : a) &#123;</span></span><br><span class="line">        <span class="comment">//    System.out.println(s);</span></span><br><span class="line">        <span class="comment">//&#125;</span></span><br><span class="line">        System.out.println(a);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><h3 id="2-集合容器-Set"><a href="#2-集合容器-Set" class="headerlink" title="2. 集合容器(Set)"></a>2. 集合容器(Set)</h3><h4 id="1-HashSet"><a href="#1-HashSet" class="headerlink" title="1. HashSet"></a>1. HashSet</h4><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">HashSet&lt;String&gt; s = <span class="keyword">new</span> HashSet&lt;String&gt;();</span><br><span class="line">s.add(<span class="string">&quot;first&quot;</span>);</span><br><span class="line">s.add(<span class="string">&quot;second&quot;</span>);</span><br><span class="line">s.add(<span class="string">&quot;first&quot;</span>);</span><br><span class="line">System.out.println(s);</span><br></pre></td></tr></table></figure><p>显示结果：<br><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">second</span><br><span class="line">first</span><br></pre></td></tr></table></figure><br>集合容器<code>HashSet</code>具有<strong>无序性</strong>和<strong>无重复型</strong>。此外，如果一个类的内部实现了<code>String toString()</code>函数(如数组、ArrayList 、HashMap )，那么可以直接用<code>System.out.println(容器名)</code>打印该函数内部指定返回的内容。<br>遍历 HashSet 可以使用迭代器或者 for-each 循环</p><h2 id=""><a href="#" class="headerlink" title=""></a><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="comment">//迭代器</span></span><br><span class="line">Iterator iterator = s.iterator();</span><br><span class="line"><span class="keyword">for</span>(iterator.hasNext())</span><br><span class="line">&#123;</span><br><span class="line">...   </span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(String string:s)</span><br><span class="line">&#123;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//for-each</span></span><br></pre></td></tr></table></figure></h2><h5 id="HashSet-检查重复的方法-hashCode-与-equals"><a href="#HashSet-检查重复的方法-hashCode-与-equals" class="headerlink" title="HashSet 检查重复的方法 hashCode() 与 equals()"></a>HashSet 检查重复的方法 hashCode() 与 equals()</h5><p>当把对象加入 HashSet 时，它会首先使用该对象的 hashcode 值u来判断对象加入的位置，但是同时也与其他对象的 hashcode 比对，如果没有相同的，这个对象<strong>一定不是重复的</strong>。如果 hashcode 相等，对象也不一定相等，这就会调用其中一者的 <code>equals()</code> 来判断是否真的相同。</p><h4 id="2-TreeSet"><a href="#2-TreeSet" class="headerlink" title="2. TreeSet"></a>2. TreeSet</h4><p>TreeSet 同样不允许有重复的元素，但是他会一直保持有序。<br>要使用 TreeSet，必须保证下面其中一项为真：</p><ul><li>TreeSet 中的元素实现了 Comparable</li><li><p>使用重载、取用 Comparable 参数的构造函数来创建 TreeSet</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">TreeSet&lt;Song&gt; tree = <span class="keyword">new</span> TreeSet&lt;Song&gt;(<span class="keyword">new</span> AuthorCompare());</span><br></pre></td></tr></table></figure><h3 id="3-哈希表-HashMap"><a href="#3-哈希表-HashMap" class="headerlink" title="3. 哈希表(HashMap)"></a>3. 哈希表(HashMap)</h3><p>哈希表以键值对的形式储存顺序。</p></li></ul><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><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">package</span> coin;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.Scanner;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Coin</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> HashMap&lt;Integer, String&gt; coinnames = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">Coin</span><span class="params">()</span></span>&#123;</span><br><span class="line">        coinnames.put(<span class="number">1</span>,<span class="string">&quot;penny&quot;</span>);</span><br><span class="line">        coinnames.put(<span class="number">10</span>,<span class="string">&quot;dime&quot;</span>);</span><br><span class="line">        coinnames.put(<span class="number">25</span>,<span class="string">&quot;quarter&quot;</span>);</span><br><span class="line">        coinnames.put(<span class="number">50</span>,<span class="string">&quot;half-dollar&quot;</span>);</span><br><span class="line">        coinnames.put(<span class="number">50</span>,<span class="string">&quot;五毛&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getName</span><span class="params">(<span class="keyword">int</span> amount)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">      <span class="comment">//判断哈希表中是否存有这个Key</span></span><br><span class="line">        <span class="keyword">if</span>(coinnames.containsKey(amount)) &#123;</span><br><span class="line">            <span class="keyword">return</span> coinnames.get(amount);</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;NOT FOUND&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="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] arg)</span> </span>&#123;</span><br><span class="line">        Coin coin = <span class="keyword">new</span> Coin();</span><br><span class="line">        Scanner in = <span class="keyword">new</span> Scanner(System.in);</span><br><span class="line">        <span class="keyword">int</span> amount = in.nextInt();</span><br><span class="line">        String name = coin.getName(amount);</span><br><span class="line">        System.out.println(name);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>遍历哈希表中的值可以用以下方法：<br><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="keyword">int</span> key:coinnames.keySet()) &#123;</span><br><span class="line">    System.out.println(coinnames.get(key));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>打印结果<br><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><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">penny</span><br><span class="line">五毛</span><br><span class="line">quarter</span><br><span class="line">dime</span><br></pre></td></tr></table></figure><br>没有打印出 “half-dollar” , 这是因为 HashMap 中键( Key )是<strong>不允许重复</strong>的，所以后一次的 “五毛” 会覆盖前一次。</p><h2 id="2-由-sort-方法所知道的"><a href="#2-由-sort-方法所知道的" class="headerlink" title="2. 由 sort() 方法所知道的"></a>2. 由 sort() 方法所知道的</h2><p>ArrayList 类中不含 <code>sort()</code> 函数, 但是 Collections 类中含有 <code>sort()</code>方法, 所以可以使用<code>Collections.sort(List list)</code>将实现了 List 接口的 ArrayList 传进去.</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">//创建存放歌曲名的容器</span></span><br><span class="line"><span class="keyword">private</span> ArrayList&lt;String&gt; songList = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line"><span class="comment">//调用 sort() 函数, 根据首字母排序</span></span><br><span class="line">Collections.sort(songList);</span><br></pre></td></tr></table></figure><p>但当 ArrayList 中存放的不是 String 而是一个自定义的对象时, 就不能直接用了.如下面的代码不能通过编译:</p><h2 id="-1"><a href="#-1" class="headerlink" title=""></a><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> ArrayList&lt;Song&gt; songList = <span class="keyword">new</span> ArrayList&lt;&gt;();</span><br><span class="line"><span class="comment">//调用 sort() 函数, 根据首字母排序</span></span><br><span class="line">Collections.sort(songList);</span><br></pre></td></tr></table></figure></h2><p>以下两种都是正确的:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> &lt;T extends Animal&gt; <span class="function"><span class="keyword">void</span> <span class="title">takeThing</span><span class="params">(ArrayList &lt;T&gt; list)</span> </span></span><br></pre></td></tr></table></figure><br><figure class="highlight java"><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="keyword">public</span> <span class="keyword">void</span> <span class="title">takeThing</span><span class="params">(ArrayList&lt;Animal&gt; list)</span></span></span><br></pre></td></tr></table></figure><br>这两者<strong>不同</strong>. 前者表示任何 Animal 或者 Animal 的子类都可以被传入, 后者仅能接收 <code>ArrayLiast&lt;Animal&gt;</code> </p><hr><p><code>sort()</code>函数的声明如下:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> &lt;T extends Comparable&lt; ? <span class="keyword">super</span> T&gt;&gt; <span class="function"><span class="keyword">void</span> <span class="title">sort</span><span class="params">(List&lt;T&gt; list)</span></span></span><br></pre></td></tr></table></figure><br>由此可知,  T 必须实现( 此处也是 extends ) Comparable 这个接口.<code>? super T</code>代表 Comparable 的类型参数必须是 T 或者 T 的父型.<br>所以 Song 类应该是这样的:<br><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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Song</span> <span class="keyword">implements</span> <span class="title">Comparable</span>&lt;<span class="title">Song</span>&gt;</span></span><br><span class="line"><span class="class"></span>&#123;</span><br><span class="line">    <span class="comment">//具体属性略</span></span><br><span class="line">    ...</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">comepareTo</span><span class="params">(obeject o)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="comment">//只需要按照标题比较</span></span><br><span class="line">        <span class="keyword">return</span> title.compareTo(o.getTitle);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><br>comepareTo 返回值小于 0, 则传入的 Song 大于执行的 Song.</p><hr><p>除了实现 Comparable, 还可以用 Comparator 参数来调用不同方式的排序.</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="class"><span class="keyword">class</span> <span class="title">AuthorCompare</span> <span class="keyword">implements</span> <span class="title">Comparator</span>&lt;<span class="title">Song</span>&gt;</span>&#123;</span><br><span class="line">    <span class="meta">@override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span> <span class="title">compare</span><span class="params">(Song o1, Song o2)</span></span>&#123;</span><br><span class="line">        <span class="comment">//这里的compare与之前compareTo作用是一样的, 都是根据某个指标相减的结果返回, 从而判断大小</span></span><br><span class="line">        <span class="keyword">return</span> o1.getSAuthor.compareTo(o2.getAuthor);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>于是, 可以在其他地方调用两个参数版本的<code>sort()</code>:<br><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Collection.sort(songList,<span class="keyword">new</span> AuthorCompare);</span><br></pre></td></tr></table></figure></p>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 基础(三) 对象数组</title>
      <link href="2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_03/"/>
      <url>2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_03/</url>
      
        <content type="html"><![CDATA[<p>对象数组与基础类型的数组如<code>int []</code>是不同的。对象数组的每个元素都是对象的<strong>管理者</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></pre></td><td class="code"><pre><span class="line">String[] a = <span class="keyword">new</span> String[<span class="number">10</span>];</span><br><span class="line">System.out.println(a[<span class="number">0</span>]);<span class="comment">//显示为null</span></span><br><span class="line">System.outprintfln(a[<span class="number">0</span>].length());<span class="comment">//抛出异常</span></span><br></pre></td></tr></table></figure><p>当通过创建了一个<code>String</code>类型的数组时，这个数组的每一个“格子”里都是<code>String</code>类型的<strong>管理者</strong>。此时该数组每一个元素管理的都是空的，即<code>null</code>。</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="keyword">for</span>(<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; a.length; i++)&#123;</span><br><span class="line">  a[i] = <span class="string">&quot;&quot;</span> + i;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="对象数组的-for-each-循环"><a href="#对象数组的-for-each-循环" class="headerlink" title="对象数组的 for-each 循环"></a>对象数组的 for-each 循环</h2><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></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyClass</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> value;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">set</span><span class="params">(<span class="keyword">int</span> val)</span> </span>&#123;</span><br><span class="line">        value = val;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">int</span>  <span class="title">get</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> value;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] arg)</span></span>&#123;</span><br><span class="line">        MyClass []a = <span class="keyword">new</span> MyClass[<span class="number">10</span>];</span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> i=<span class="number">0</span>;i&lt;<span class="number">10</span>;i++)&#123;</span><br><span class="line">            a[i] = <span class="keyword">new</span> MyClass();</span><br><span class="line">            a[i].set(<span class="number">1</span>);<span class="comment">//赋值为1</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span>(MyClass i: a)&#123;</span><br><span class="line">            i.set(<span class="number">0</span>);<span class="comment">//赋值为0</span></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span>(MyClass i: a)&#123;</span><br><span class="line">            System.out.println(i.value);</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>输出结果为：<br><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><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">0</span><br><span class="line">0</span><br><span class="line">0</span><br><span class="line">0</span><br><span class="line">0</span><br><span class="line">0</span><br><span class="line">0</span><br><span class="line">0</span><br><span class="line">0</span><br><span class="line">0</span><br></pre></td></tr></table></figure><br>这其中发生的事情是<code>for-each</code>循环中，变量<code>i</code>与a中的元素管理<strong>同一个对象</strong>，所以调用<code>i.set(0)</code>后，遍历<code>a</code>数组得到的结果也是0。</p>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 基础(一) 开放的访问属性(见 Display 项目)</title>
      <link href="2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_01/"/>
      <url>2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_01/</url>
      
        <content type="html"><![CDATA[<ul><li>public 意味着任何人都可以自由地使用</li><li>如果一个函数前没有加 public 限定，意味着和他位于<strong>同一个包</strong>的类可以访问，称为 friendly</li><li>protected</li><li>public Class 意味着任何人都可以用这个类来定义变量<br>要求：public Class 必须定义在同名源文件中<br>一个 .java 文件为一个编译单元，<strong>一个编译单元只能有一个 public 的类</strong></li></ul>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>计算机组织结构(二) 定点运算</title>
      <link href="2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_02/"/>
      <url>2020/12/27/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BB%84%E7%BB%87%E7%BB%93%E6%9E%84/COA_02/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/计算机组织结构/COA_00">合集</a>-<a href="/2020/12/27/计算机组织结构/COA_01">数的二进制表示</a>-<a href="/2020/12/27/计算机组织结构/COA_02">定点运算</a>-<a href="/2020/12/27/计算机组织结构/COA_03">BCD 码</a>-<a href="/2020/12/27/计算机组织结构/COA_04">浮点数四则运算</a>-<a href="/2020/12/27/计算机组织结构/COA_05">内置存储器</a>-<a href="/2020/12/27/计算机组织结构/COA_06">Cache</a>-<a href="/2020/12/27/计算机组织结构/COA_07">外存</a>-<a href="/2020/12/27/计算机组织结构/COA_08">纠错</a>-<a href="/2020/12/27/计算机组织结构/COA_09">RAID</a>-<a href="/2020/12/27/计算机组织结构/COA_10">内存管理</a>-<a href="/2020/12/27/计算机组织结构/COA_11">总线</a>-<a href="/2020/12/27/计算机组织结构/COA_12">指令集: 特征</a>-<a href="/2020/12/27/计算机组织结构/COA_13"> 指令集:寻址方式和指令格式</a></p></div><h2 id="1-移位运算"><a href="#1-移位运算" class="headerlink" title="1. 移位运算"></a>1. 移位运算</h2><h3 id="1-算数移位"><a href="#1-算数移位" class="headerlink" title="1.算数移位"></a>1.算数移位</h3><ul><li><strong>符号位不变</strong>, 左移相当于乘以 2, 右移相当于除以 2(左侧全补符号位).</li></ul><h3 id="2-逻辑移位"><a href="#2-逻辑移位" class="headerlink" title="2. 逻辑移位"></a>2. 逻辑移位</h3><ul><li><strong>无符号数的移位</strong>, 右移时永远在高位填 0.</li></ul><h2 id="2-加法运算"><a href="#2-加法运算" class="headerlink" title="2. 加法运算"></a>2. 加法运算</h2><h3 id="1-全加器"><a href="#1-全加器" class="headerlink" title="1. 全加器"></a>1. 全加器</h3><ul><li>$𝑆<em>𝑖=𝑋</em>𝑖⊕𝑌<em>𝑖⊕𝐶</em>{𝑖−1}$</li><li>$𝐶<em>𝑖=𝑋</em>𝑖𝐶<em>{𝑖−1}+𝑌</em>𝑖𝐶<em>{𝑖−1}+𝑋</em>𝑖𝑌_𝑖$</li></ul><h3 id="2-Serial-Carry-Adder"><a href="#2-Serial-Carry-Adder" class="headerlink" title="2. Serial Carry Adder"></a>2. Serial Carry Adder</h3><iframe frameborder="0" style="width:100%;height:200%;" src="https://app.diagrams.net/?lightbox=1&highlight=0000ff&edit=_blank&layers=1&nav=1#R7VpLc9owEP41HJvxS9g%2BJpC0h3amMxxKjipWsDrGYmwRIL%2B%2BMpZfWiAE%2FMAMF8ZaybL0fatvd20G5mix%2BR7hpf%2BLeSQYGJq3GZjjgWG4riF%2BE8M2NdjITA3ziHqpSS8ME%2FpBpFGT1hX1SFwZyBkLOF1WjTMWhmTGKzYcRWxdHfbGgupTl3hOgGEywwG0%2FqEe91OrY9iF%2FQehcz97sj50054FzgbLncQ%2B9ti6ZDKfB%2BYoYoynV4vNiAQJdhku6X0vB3rzhUUk5KfcYMslx3ybbY54Yq%2ByySLuszkLcfBcWJ8itgo9ksygiVYx5idjS2HUhfEf4XwricMrzoTJ54tA9pIN5VN5e3L9mlw%2FINkab0pd461spOtMFndwq9IUs1U0k6NsPQdVOCNhC8KjrRgTkQBz%2Bl6dC0u3mOfj8lt%2FMyqeYmjSgy1T8icdWM%2Fa2RQcR3PC5V0F%2FuKitIzCtGNlP0Ou3gVDV4U2UtA2GgPblmt7x8FKrvblEeC%2F9iknkyXebXstFK6KHY6Xqei80U3CgQTznUScbI7DCaHLHM6tQpA11yX5kSa%2FpDyOdhjrCkzHMDEAJtAjQ%2B8x0VXRmgU4julMOfCheOi03Cgd%2BaRZnPld6%2BuHPvWB425YAgvtASuzXeitw%2BEn2pCeGOCu0O3VifTm%2FN4EHI80wLJwX664ekDnYUK6oINEwpA4ORWB8lF2LKjnpYpEYvqB%2F%2B6mSphdJqve7QM9DdA4mUuIUJzqkV7PoRlqCoCaDU6NuccRVH0569S4PZJttOcMDS%2BU8lOBcrrJQNoVJNRMFqKfl4WAiUz7PMkSmo%2B3pWHyUF%2BoRehKY7BhdRaDHbNHanKpchxw9tYy7nQDV%2BiAutadA2owQYCFSd8SBAt1lyA4FkQ07D2iQ6c7QB0AKBTNok4JWZiA5OHY32mkfp72dVVlmE5NVUaLrzIc90sMHa8ktQcjT9Zey503VEoiJcHLg%2BCXS0k1etqNkezCSHF9JHdGKKqLUDVyNUioAQid9D%2F0q%2B8UEcylmgpULnzZMu0%2FoJaL9rt2G4jCXOq1%2F4gis0NEERTt6yk4ay8uDSWbOvELw6fzuKfJ%2BzmqDIvUe5jNaRjWFGbViZoMs%2Fad0MPVjlYToepETRIK69FJ%2BK3%2FYcmwrQqEezInq6moBAvI6U1Aah1w7xYwzV8qlpOnmwBVjemtgnrV%2F9qoPX%2FSVQc%2BM39S52kuf9I1WNbe423Og1FTvFUnajDe6hqsq%2B%2BM5kTUlRKrEzXKKKzrJ%2F3%2FRqKKXIuvnnQNflyf3gCih8qDViCFlfjrDUB6QkpaE6SiWfzhOZWJ4l%2Fj5vN%2F"></iframe><ul><li>缺点: 速度慢.</li><li>延时(OR AND 1ty, XOR 3ty)<ul><li>Cn: 2n ty</li><li>Sn: 2n+1 ty</li></ul></li></ul><h3 id="3-Carry-Look-Ahead-Adder"><a href="#3-Carry-Look-Ahead-Adder" class="headerlink" title="3. Carry Look Ahead Adder"></a>3. Carry Look Ahead Adder</h3><p><strong>注意</strong>：这里的+均为“或”</p><script type="math/tex; mode=display">\begin{aligned}𝐶_𝑖&=𝑋_𝑖𝐶_{𝑖−1}+𝑌_𝑖𝐶_{𝑖−1}+𝑋_𝑖𝑌_i\\\\C_1&=𝑋_1𝑌_1+(𝑋_1+𝑌_1)𝐶_0\\𝐶_2&=𝑋_2𝑌_2+(𝑋_2+𝑌_2)𝑋_1𝑌_1+(𝑋_2+𝑌_2)(𝑋_1+𝑌_1)𝐶_0\\𝐶_3&=𝑋_3𝑌_3+𝑋_3+𝑌_3𝑋_2𝑌_2+𝑋_3+𝑌_3𝑋_2+𝑌_2𝑋_1𝑌_1+(𝑋_3+𝑌_3)(𝑋_2+𝑌_2)(𝑋_1+𝑌_1)𝐶_0\\C_4 &=...\end{aligned}</script><p>可见,$Ci$ 仅与最初的X Y和 $C<em>0$有关.<br>令$𝑃</em>𝑖=𝑋<em>𝑖+𝑌</em>𝑖, 𝐺<em>𝑖=𝑋</em>𝑖𝑌_i$<br>则:</p><script type="math/tex; mode=display">\begin{aligned}\\𝐶_1&=𝐺_1+𝑃_1𝐶_0\\𝐶_2&=𝐺_2+𝑃_2𝐺_1+𝑃_2𝑃_1𝐶_0\\𝐶_3&=𝐺_3+𝑃_3𝐺_2+𝑃_3𝑃_2𝐺_1+𝑃_3𝑃_2𝑃_1𝐶_0\\𝐶_4&=...\end{aligned}</script><p>总结得:$C<em>{i+1} = G</em>{i+1}+P_{i+1}C_i$, 超前进位加法器采用的是将低一位的逻辑代数代入高一位, 依此类推最终每一个进位输出仅考虑 $C_0, X_i, Y_i$几个信号, 于是所有的进位都能同时计算.</p><ul><li>缺点:复杂</li><li>延时: 1 ty+ 2ty + 3 ty = 6 ty</li></ul><h3 id="4-Partial-Carry-Look-Ahead-Adder"><a href="#4-Partial-Carry-Look-Ahead-Adder" class="headerlink" title="4. Partial Carry Look Ahead Adder"></a>4. Partial Carry Look Ahead Adder</h3><p>   结合两者  </p><h3 id="5-溢出判断"><a href="#5-溢出判断" class="headerlink" title="5. 溢出判断"></a>5. 溢出判断</h3><ul><li>$C<em>n\oplus C</em>{n-1} =1$, 即符号位进位与最高有效位进位不同时,发生溢出.</li><li>$𝑋<em>𝑛 𝑌</em>𝑛 \overline{𝑆<em>𝑛}+\overline{𝑋</em>𝑛𝑌<em>𝑛}𝑆</em>𝑛=1$,则溢出,与上面等价.</li></ul><h3 id="3-减法运算"><a href="#3-减法运算" class="headerlink" title="3. 减法运算"></a>3. 减法运算</h3><p>减法运算大致与加法相同,只需要将减数取反加一然后按加法算即可, <strong>注意加一的操作是令 $C_0 = 1$</strong>.</p><h3 id="4-乘法运算"><a href="#4-乘法运算" class="headerlink" title="4. 乘法运算"></a>4. 乘法运算</h3><h4 id="1-无符号整数乘法"><a href="#1-无符号整数乘法" class="headerlink" title="1. 无符号整数乘法"></a>1. 无符号整数乘法</h4><p>通过<strong>加法和移位实现</strong>,与竖式乘法极其类似,但是计算机很难像人类那样一次性把各位乘的结果一次性相加,因此采用部分积的方式:<br>例:$0111\times0110$</p><div class="table-container"><table><thead><tr><th style="text-align:center"><font color=#FF0000>部分积</font></th><th style="text-align:center">乘数</th><th style="text-align:center">得到当前行的操作</th></tr></thead><tbody><tr><td style="text-align:center"><font color=#FF0000>0000</font></td><td style="text-align:center">0110</td><td style="text-align:center">部分积+乘数末位$\times 0111$</td></tr><tr><td style="text-align:center"><font color=#FF0000>0000</font></td><td style="text-align:center"><font color=#FF0000>0</font>011</td><td style="text-align:center">右移</td></tr><tr><td style="text-align:center"><font color=#FF0000>0111</font></td><td style="text-align:center"><font color=#FF0000>0</font>011</td><td style="text-align:center">部分积+乘数末位$\times 0111$</td></tr><tr><td style="text-align:center"><font color=#FF0000>0011</font></td><td style="text-align:center"><font color=#FF0000>10</font>01</td><td style="text-align:center">右移</td></tr><tr><td style="text-align:center"><font color=#FF0000>1010</font></td><td style="text-align:center"><font color=#FF0000>10</font>01</td><td style="text-align:center">部分积+乘数末位$\times 0111$</td></tr><tr><td style="text-align:center"><font color=#FF0000>0101</font></td><td style="text-align:center"><font color=#FF0000>010</font>0</td><td style="text-align:center">右移</td></tr><tr><td style="text-align:center"><font color=#FF0000>0101</font></td><td style="text-align:center"><font color=#FF0000>010</font>0</td><td style="text-align:center">部分积+乘数末位$\times 0111$</td></tr><tr><td style="text-align:center"><font color=#FF0000>0010</font></td><td style="text-align:center"><font color=#FF0000>1010</font></td><td style="text-align:center">右移</td></tr></tbody></table></div><ul><li>乘数末位决定被乘数是否加到部分积,然后部分积和乘数均<strong>右移</strong>,部分积低位保存到乘数高位.</li><li><strong>被乘数只与部分积高位相加</strong></li></ul><p>原理:</p><script type="math/tex; mode=display">\begin{aligned}XY &= XY_nY_{n-1}...Y_2Y_1\\&=X(Y_n\times2^{n-1}+Y_n\times2^{n-2}+...+Y_2\times2^1+Y_1\times2^0)\\&=2^n(XY_n\times2^{-1}+XY_{n-1}\times2^{-2}+...+XY_1\times2^{-n})\\&=2^nP_{n},其中P_{n} = 2^{-1}\times(XY_{n}+P_{n-1}),n\gt1.\end{aligned}</script><h4 id="2-补码整数乘法"><a href="#2-补码整数乘法" class="headerlink" title="2. 补码整数乘法"></a>2. 补码整数乘法</h4><p>根据上面无符号整数的原理, 可以将二进制补码整数相乘变形如下:</p><script type="math/tex; mode=display">\begin{aligned}XY& = XY_nY_{n-1}...Y_2Y_1\\&=X(-Y_n\times2^{n-1}+Y_n\times2^{n-2}+...+Y_2\times2^1+Y_1\times2^0)\\&=2^nX((Y_{n-1}-Y_n)\times2^{-1}+(Y_{n-2}-Y_{n-1})\times2^{-2}+...+(Y_0-Y_1)\times2^{-n})\\&=2^nP_{n},其中Y_0=0,P_{n} = 2^{-1}\times(X(Y_{n-1}-Y_{n})+P_{n-1}),n\gt1.\end{aligned}</script><p>形式上还原了,只是每次乘的<strong>不是乘数的末位数</strong>, 且注意是<strong>算数右移</strong>,需要补符号位,<br>例: $-7\times-6 = 42,即 1001\times1010=00101010$</p><div class="table-container"><table><thead><tr><th style="text-align:center"><font color=#FF0000>部分积</font></th><th style="text-align:center">乘数</th><th style="text-align:center">得到当前行的操作</th></tr></thead><tbody><tr><td style="text-align:center"><font color=#FF0000>0000</font></td><td style="text-align:center">1010<font color=#0000FF>0</font></td><td style="text-align:center">部分积+$(Y_0-Y_1)\times 1001$</td></tr><tr><td style="text-align:center"><font color=#FF0000>0000</font></td><td style="text-align:center"><font color=#FF0000>0</font>1010</td><td style="text-align:center">右移</td></tr><tr><td style="text-align:center"><font color=#FF0000>0111</font></td><td style="text-align:center"><font color=#FF0000>0</font>1010</td><td style="text-align:center">部分积+$(Y_1-Y_2)\times 1001$</td></tr><tr><td style="text-align:center"><font color=#FF0000>0011</font></td><td style="text-align:center"><font color=#FF0000>10</font>101</td><td style="text-align:center">右移</td></tr><tr><td style="text-align:center"><font color=#FF0000>1100</font></td><td style="text-align:center"><font color=#FF0000>10</font>101</td><td style="text-align:center">部分积+$(Y_2-Y_3)\times 1001$</td></tr><tr><td style="text-align:center"><font color=#FF0000>1110</font></td><td style="text-align:center"><font color=#FF0000>010</font>10</td><td style="text-align:center">右移</td></tr><tr><td style="text-align:center"><font color=#FF0000>0101</font></td><td style="text-align:center"><font color=#FF0000>010</font>10</td><td style="text-align:center">部分积+$(Y_3-Y_4)\times 1001$</td></tr><tr><td style="text-align:center"><font color=#FF0000>0010</font></td><td style="text-align:center"><font color=#FF0000>1010</font>1</td><td style="text-align:center">右移</td></tr></tbody></table></div><h3 id="5-除法运算"><a href="#5-除法运算" class="headerlink" title="5. 除法运算"></a>5. 除法运算</h3><h4 id="1-unsigned"><a href="#1-unsigned" class="headerlink" title="1. unsigned"></a>1. unsigned</h4><p>1.人的计算:除数右移, 2n位</p><ul><li>竖式计算:<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/8216b980b855f3139a28932f6883a053a6e04f1f.webp" style="zoom:50%;" /></li></ul><div class="table-container"><table><thead><tr><th style="text-align:center">余数</th><th style="text-align:center"><font color=#0000FF>除数</font></th><th style="text-align:center">商</th></tr></thead><tbody><tr><td style="text-align:center">00000111</td><td style="text-align:center"><font color=#0000FF>00110000</font></td><td style="text-align:center">0000</td></tr><tr><td style="text-align:center">00000111</td><td style="text-align:center">0<font color=#0000FF>0011000</font></td><td style="text-align:center">0000</td></tr><tr><td style="text-align:center">00000111</td><td style="text-align:center">0<font color=#0000FF>0011000</font></td><td style="text-align:center">000<font color=#FF0000>0</font></td></tr><tr><td style="text-align:center">00000111</td><td style="text-align:center">00<font color=#0000FF>001100</font></td><td style="text-align:center">000<font color=#FF0000>0</font></td></tr><tr><td style="text-align:center">00000111</td><td style="text-align:center">00<font color=#0000FF>001100</font></td><td style="text-align:center">00<font color=#FF0000>00</font></td></tr><tr><td style="text-align:center">00000111</td><td style="text-align:center">000<font color=#0000FF>00110</font></td><td style="text-align:center">00<font color=#FF0000>00</font></td></tr><tr><td style="text-align:center">00000001</td><td style="text-align:center">000<font color=#0000FF>00110</font></td><td style="text-align:center">0<font color=#FF0000>001</font></td></tr><tr><td style="text-align:center">00000001</td><td style="text-align:center">0000<font color=#0000FF>0011</font></td><td style="text-align:center">0<font color=#FF0000>001</font></td></tr><tr><td style="text-align:center">00000001</td><td style="text-align:center">0000<font color=#0000FF>0011</font></td><td style="text-align:center"><font color=#FF0000>0010</font></td></tr></tbody></table></div><ol><li>计算机的计算: <strong>余数左移</strong>, n位</li></ol><div class="table-container"><table><thead><tr><th style="text-align:center"><font color=#0000FF>余数</font></th><th style="text-align:center"><font color=#FF0000>商</font></th><th style="text-align:center">除数</th></tr></thead><tbody><tr><td style="text-align:center"><font color=#0000FF>0000</font></td><td style="text-align:center"><font color=#0000FF>0111</font></td><td style="text-align:center">0011</td></tr><tr><td style="text-align:center"><font color=#0000FF>0000</font></td><td style="text-align:center"><font color=#0000FF>111</font></td><td style="text-align:center">0011</td></tr><tr><td style="text-align:center"><font color=#0000FF>0000</font></td><td style="text-align:center"><font color=#0000FF>111</font><font color=#FF0000>0</font></td><td style="text-align:center">0011</td></tr><tr><td style="text-align:center"><font color=#0000FF>0001</font></td><td style="text-align:center"><font color=#0000FF>11</font><font color=#FF0000>0</font></td><td style="text-align:center">0011</td></tr><tr><td style="text-align:center"><font color=#0000FF>0001</font></td><td style="text-align:center"><font color=#0000FF>11</font><font color=#FF0000>00</font></td><td style="text-align:center">0011</td></tr><tr><td style="text-align:center"><font color=#0000FF>0011</font></td><td style="text-align:center"><font color=#0000FF>1</font><font color=#FF0000>00</font></td><td style="text-align:center">0011</td></tr><tr><td style="text-align:center"><font color=#0000FF>0000</font></td><td style="text-align:center"><font color=#0000FF>1</font><font color=#FF0000>001</font></td><td style="text-align:center">0011</td></tr><tr><td style="text-align:center"><font color=#0000FF>0001</font></td><td style="text-align:center"><font color=#FF0000>001</font></td><td style="text-align:center">0011</td></tr><tr><td style="text-align:center"><font color=#0000FF>0001</font></td><td style="text-align:center"><font color=#FF0000>0010</font></td><td style="text-align:center">0011</td></tr></tbody></table></div><h4 id="2-带有符号的除法"><a href="#2-带有符号的除法" class="headerlink" title="2. 带有符号的除法"></a>2. 带有符号的除法</h4><ul><li>如何判断余数(的绝对值)是否大于除数(的绝对值)?<ul><li>同号则减, 异号则加. 与结果符号相同的那个数绝对值大</li></ul></li></ul><table style="border-collapse:collapse;margin-left:52.305pt" cellspacing="0"><tbody><tr style="height:29pt"><td style="width:94pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt" rowspan="2"><p class="s116" style="padding-top: 2pt;padding-left: 6pt;padding-right: 5pt;text-indent: 0pt;line-height: 22pt;text-align: center;">remainder</p><p class="s116" style="padding-left: 6pt;padding-right: 5pt;text-indent: 0pt;line-height: 22pt;text-align: center;">sign</p></td><td style="width:74pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt" rowspan="2"><p class="s116" style="padding-top: 2pt;padding-left: 10pt;padding-right: 9pt;text-indent: 0pt;line-height: 22pt;text-align: center;">Divisor</p><p class="s116" style="padding-left: 10pt;padding-right: 9pt;text-indent: 0pt;line-height: 22pt;text-align: center;">sign</p></td><td style="width:211pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt" colspan="2"><p class="s116" style="padding-top: 2pt;padding-left: 62pt;text-indent: 0pt;text-align: left;">Subtraction</p></td><td style="width:216pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt" colspan="2"><p class="s116" style="padding-top: 2pt;padding-left: 74pt;padding-right: 73pt;text-indent: 0pt;text-align: center;">Addition</p></td></tr><tr style="height:29pt"><td style="width:106pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s116" style="padding-top: 2pt;text-indent: 0pt;text-align: center;">0</p></td><td style="width:105pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s116" style="padding-top: 2pt;text-indent: 0pt;text-align: center;">1</p></td><td style="width:111pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s116" style="padding-top: 2pt;text-indent: 0pt;text-align: center;">0</p></td><td style="width:105pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s116" style="padding-top: 2pt;text-indent: 0pt;text-align: center;">1</p></td></tr><tr style="height:29pt"><td style="width:94pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;text-indent: 0pt;text-align: center;">0</p></td><td style="width:74pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;text-indent: 0pt;text-align: center;">0</p></td><td style="width:106pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 8pt;padding-right: 7pt;text-indent: 0pt;text-align: center;">Enough</p></td><td style="width:105pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 8pt;padding-right: 7pt;text-indent: 0pt;text-align: center;">Not enough</p></td><td style="width:111pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 11pt;padding-right: 10pt;text-indent: 0pt;text-align: center;">----</p></td><td style="width:105pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 8pt;padding-right: 7pt;text-indent: 0pt;text-align: center;">----</p></td></tr><tr style="height:29pt"><td style="width:94pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;text-indent: 0pt;text-align: center;">0</p></td><td style="width:74pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;text-indent: 0pt;text-align: center;">1</p></td><td style="width:106pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 8pt;padding-right: 7pt;text-indent: 0pt;text-align: center;">----</p></td><td style="width:105pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 8pt;padding-right: 7pt;text-indent: 0pt;text-align: center;">----</p></td><td style="width:111pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 11pt;padding-right: 10pt;text-indent: 0pt;text-align: center;">Enough</p></td><td style="width:105pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 8pt;padding-right: 7pt;text-indent: 0pt;text-align: center;">Not enough</p></td></tr><tr style="height:29pt"><td style="width:94pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;text-indent: 0pt;text-align: center;">1</p></td><td style="width:74pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;text-indent: 0pt;text-align: center;">0</p></td><td style="width:106pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 8pt;padding-right: 7pt;text-indent: 0pt;text-align: center;">----</p></td><td style="width:105pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 8pt;padding-right: 7pt;text-indent: 0pt;text-align: center;">----</p></td><td style="width:111pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 11pt;padding-right: 10pt;text-indent: 0pt;text-align: center;">Not enough</p></td><td style="width:105pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 8pt;padding-right: 7pt;text-indent: 0pt;text-align: center;">Enough</p></td></tr><tr style="height:29pt"><td style="width:94pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;text-indent: 0pt;text-align: center;">1</p></td><td style="width:74pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;text-indent: 0pt;text-align: center;">1</p></td><td style="width:106pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 8pt;padding-right: 7pt;text-indent: 0pt;text-align: center;">Not enough</p></td><td style="width:105pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 8pt;padding-right: 7pt;text-indent: 0pt;text-align: center;">Enough</p></td><td style="width:111pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 11pt;padding-right: 10pt;text-indent: 0pt;text-align: center;">----</p></td><td style="width:105pt;border-top-style:solid;border-top-width:1pt;border-left-style:solid;border-left-width:1pt;border-bottom-style:solid;border-bottom-width:1pt;border-right-style:solid;border-right-width:1pt"><p class="s117" style="padding-top: 2pt;padding-left: 8pt;padding-right: 7pt;text-indent: 0pt;text-align: center;">----</p></td></tr></tbody></table><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/aadda87e9086a37cb714b2970fa7596c0721f939.webp" width = "30%" /></p><ol><li><p><strong>恢复余数法</strong> 在下面的步骤中,余数和除数的和是存储在余数寄存器里面的,判断完成后,还要恢复原来的余数(即减去余数).之前的不带符号位除法<strong>也都是恢复余数法</strong>,只是没有表示出来.</p>   <table>   <thead>   <tr>   <th style="text-align:center"><font color="#0000FF">余数</font></th>   <th style="text-align:center"><font color="#FF0000">商</font></th>   <th style="text-align:center">除数</th>   <th style="text-align:center">得到本步操作</th>   </tr>   </thead>   <tbody>   <tr>   <td style="text-align:center"><font color="#0000FF">1111</font></td>   <td style="text-align:center"><font color="#0000FF">1001</font></td>   <td style="text-align:center">0011</td>   <td style="text-align:center">-</td>   </tr>   <tr>   <td style="text-align:center"><font color="#0000FF">1111</font></td>   <td style="text-align:center"><font color="#0000FF">001</font></td>   <td style="text-align:center">0011</td>   <td style="text-align:center">左移</td>   </tr>   <tr>   <td style="text-align:center"><font color="#0000FF">1111</font></td>   <td style="text-align:center"><font color="#0000FF">001</font><font color="#FF0000">0</font></td>   <td style="text-align:center">0011</td>   <td style="text-align:center">1111+0011 =0010,not enough</td>   </tr>   <tr>   <td style="text-align:center"><font color="#0000FF">1110</font></td>   <td style="text-align:center"><font color="#0000FF">01</font><font color="#FF0000">0</font></td>   <td style="text-align:center">0011</td>   <td style="text-align:center">左移</td>   </tr>   <tr>   <td style="text-align:center"><font color="#0000FF">1110</font></td>   <td style="text-align:center"><font color="#0000FF">01</font><font color="#FF0000">00</font></td>   <td style="text-align:center">0011</td>   <td style="text-align:center">1110+0011=0001, not enough</td>   </tr>   <tr>   <td style="text-align:center"><font color="#0000FF">1100</font></td>   <td style="text-align:center"><font color="#0000FF">1</font><font color="#FF0000">00</font></td>   <td style="text-align:center">0011</td>   <td style="text-align:center">左移</td>   </tr>   <tr>   <td style="text-align:center"><font color="#0000FF">1111</font></td>   <td style="text-align:center"><font color="#0000FF">1</font><font color="#FF0000">001</font></td>   <td style="text-align:center">0011</td>   <td style="text-align:center">1100+0011=1111, enough</td>   </tr>   <tr>   <td style="text-align:center"><font color="#0000FF">1111</font></td>   <td style="text-align:center"><font color="#FF0000">001</font></td>   <td style="text-align:center">0011</td>   <td style="text-align:center">左移</td>   </tr>   <tr>   <td style="text-align:center"><font color="#0000FF">1111</font></td>   <td style="text-align:center"><font color="#FF0000">0010</font></td>   <td style="text-align:center">0011</td>   <td style="text-align:center">1111+0011=0010,not enough</td>   </tr>   </tbody>   </table><p><strong>最后,结果取 <font color=#FF0000>0010</font> 的补码整数 <font color=#FF0000>1110 </font>为最终结果.</strong></p><ul><li>缺点:Problem: recover remainder is high cost</li><li>解决方案:使用不恢复余数法(加减相消法)</li></ul></li><li><p>加减相消法.</p><ul><li>规则<ul><li>将被除数符号拓展 n 位后存储在余数和商寄存器.</li><li>如果被除数与除数符号相同, 作减法; 若符号位不同, 作加法.<ul><li>若新的<strong>余数与除数符号相同, 上商 1</strong>; 否则上商 0.</li></ul></li><li>新的余数(指左移前的余数)与除数符号位相同, 则 $R<em>{i+1}= 2R_i-Y$, 即<code>余数=余数&lt;&lt;1-除数</code>;否则$R</em>{i+1}= 2R_i+Y$</li></ul></li><li>商的修正:<ul><li><strong>商左移一位. 若被除数和除数异号(即商为负), 商加一</strong></li><li>若余数与被除数符号不同:<ul><li>若被除数和除数同号,余数加除数</li><li>若被除数和除数异号,余数减除数</li></ul></li><li>注意：若做完如上修正后，余数为除数相反数，需要将余数置为0，同时商减一</li></ul></li><li>示例:<br><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/README.assets/35ad64b739a0dbd5d9908dcf33a496f7bd10bac0.webp" ></li></ul></li></ol>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 底层 </tag>
            
            <tag> 计组 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>Java 基础(二) 类变量和类函数</title>
      <link href="2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_02/"/>
      <url>2020/12/27/Java%20%E5%9F%BA%E7%A1%80/Java_abc_02/</url>
      
        <content type="html"><![CDATA[<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></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">ClassA</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">int</span> value;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">int</span> alpha;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">f</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="comment">//alpha++   //ERROR</span></span><br><span class="line">        value++;    <span class="comment">//OK</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] arg)</span> </span>&#123;</span><br><span class="line">    ClassA a = <span class="keyword">new</span> ClassA();</span><br><span class="line">    ClassA b = <span class="keyword">new</span> ClassA();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在 ClassA 中有一个 static 类型的变量，它不属于 ClassA 创建的任何对象，而是属于 ClassA 本身。可以通过 <code>ClassA.value</code> 或者<code>a.value</code>来使用。<code>a.value</code>与<code>b.value</code>实际上是同一个变量。</p><p><code>f()</code>就是一个类函数，可以直接调用，但<code>f()</code>内部<strong>只能访问静态成员</strong>。</p><p>ArrayList 可以实现一个可变的数组，与 C++ 中的 Vector 容器类似，内置了增加/插入<code>add()</code>、删除<code>remove()</code>等方法。</p>]]></content>
      
      
      <categories>
          
          <category> 教程 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> Java </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据科学基础(六) 参数估计</title>
      <link href="2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_06/"/>
      <url>2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_06/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/数据科学基础/数据科学基础_01">随机事件及其概率</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_02">随机变量及其分布</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_03">期望和方差</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_04">大数定律与中心极限定理</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_05">数理统计的基本概念</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_06">参数估计</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_07">假设检验</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_08">多维</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_09">回归分析和方差分析</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_10">降维</a></p></div><h2 id="6-1-参数的点估计"><a href="#6-1-参数的点估计" class="headerlink" title="6.1. 参数的点估计"></a>6.1. 参数的点估计</h2><ul><li>总体分布 X 的<strong>分布形式已知</strong>,未知的只是分布中的<strong>参数</strong>,要估计的只是参数或者参数的某一函数.</li></ul><h3 id="6-1-1-矩估计法"><a href="#6-1-1-矩估计法" class="headerlink" title="6.1.1. 矩估计法"></a>6.1.1. 矩估计法</h3><ul><li><p>公式</p><script type="math/tex; mode=display">\displaystyle \frac{1}{n}\sum_{i=1}^{n}x_i^k=A_k=\mu_k=E(x^k)</script><script type="math/tex; mode=display">样本矩 \qquad\qquad\quad\quad 总体矩</script></li><li><p>注意: 样本阶中的计算都是 $n$ 而不会用到样本方差 $S^2$</p></li></ul><h3 id="6-1-2-极大似然估计"><a href="#6-1-2-极大似然估计" class="headerlink" title="6.1.2. 极大似然估计"></a>6.1.2. 极大似然估计</h3><ul><li><p>估计参数值,使得出现该样本的可能性最大.</p></li><li><table><thead><tr><th style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="0" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D44B TEX-I"></mjx-c></mjx-mi></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi></mrow><annotation encoding="application/x-tex">X</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></th><th style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="1" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-msub><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D44B TEX-I"></mjx-c></mjx-mi><mjx-script style="vertical-align: -0.15em; margin-left: -0.024em;"><mjx-mn class="mjx-n" size="s"><mjx-c class="mjx-c31"></mjx-c></mjx-mn></mjx-script></mjx-msub></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>X</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">X_1</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></th><th style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="2" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-msub><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D44B TEX-I"></mjx-c></mjx-mi><mjx-script style="vertical-align: -0.15em; margin-left: -0.024em;"><mjx-mn class="mjx-n" size="s"><mjx-c class="mjx-c32"></mjx-c></mjx-mn></mjx-script></mjx-msub></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>X</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">X_2</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></th><th style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="3" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-msub><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D44B TEX-I"></mjx-c></mjx-mi><mjx-script style="vertical-align: -0.15em; margin-left: -0.024em;"><mjx-mn class="mjx-n" size="s"><mjx-c class="mjx-c33"></mjx-c></mjx-mn></mjx-script></mjx-msub></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>X</mi><mn>3</mn></msub></mrow><annotation encoding="application/x-tex">X_3</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></th><th style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="4" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-mo class="mjx-n"><mjx-c class="mjx-c2026"></mjx-c></mjx-mo></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>…</mo></mrow><annotation encoding="application/x-tex">\ldots</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></th><th style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="5" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-msub><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D44B TEX-I"></mjx-c></mjx-mi><mjx-script style="vertical-align: -0.15em; margin-left: -0.024em;"><mjx-mi class="mjx-i" size="s"><mjx-c class="mjx-c1D45B TEX-I"></mjx-c></mjx-mi></mjx-script></mjx-msub></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>X</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">X_n</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></th></tr></thead><tbody><tr><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="6" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D443 TEX-I"></mjx-c></mjx-mi></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi></mrow><annotation encoding="application/x-tex">P</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span>(离散型)</td><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="7" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-msub><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D443 TEX-I"></mjx-c></mjx-mi><mjx-script style="vertical-align: -0.15em; margin-left: -0.109em;"><mjx-mn class="mjx-n" size="s"><mjx-c class="mjx-c31"></mjx-c></mjx-mn></mjx-script></mjx-msub></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">P_1</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></td><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="8" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-msub><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D443 TEX-I"></mjx-c></mjx-mi><mjx-script style="vertical-align: -0.15em; margin-left: -0.109em;"><mjx-mn class="mjx-n" size="s"><mjx-c class="mjx-c32"></mjx-c></mjx-mn></mjx-script></mjx-msub></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">P_2</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></td><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="9" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-msub><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D443 TEX-I"></mjx-c></mjx-mi><mjx-script style="vertical-align: -0.15em; margin-left: -0.109em;"><mjx-mn class="mjx-n" size="s"><mjx-c class="mjx-c33"></mjx-c></mjx-mn></mjx-script></mjx-msub></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>3</mn></msub></mrow><annotation encoding="application/x-tex">P_3</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></td><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="10" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-mo class="mjx-n"><mjx-c class="mjx-c2026"></mjx-c></mjx-mo></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>…</mo></mrow><annotation encoding="application/x-tex">\ldots</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></td><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="11" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-msub><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D443 TEX-I"></mjx-c></mjx-mi><mjx-script style="vertical-align: -0.15em; margin-left: -0.109em;"><mjx-mi class="mjx-i" size="s"><mjx-c class="mjx-c1D45B TEX-I"></mjx-c></mjx-mi></mjx-script></mjx-msub></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">P_n</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></td></tr><tr><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="12" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D443 TEX-I"></mjx-c></mjx-mi></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi></mrow><annotation encoding="application/x-tex">P</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span>(连续型)</td><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="13" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D453 TEX-I"></mjx-c></mjx-mi><mjx-mo class="mjx-n"><mjx-c class="mjx-c28"></mjx-c></mjx-mo><mjx-msub><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D44B TEX-I"></mjx-c></mjx-mi><mjx-script style="vertical-align: -0.15em; margin-left: -0.024em;"><mjx-mn class="mjx-n" size="s"><mjx-c class="mjx-c31"></mjx-c></mjx-mn></mjx-script></mjx-msub><mjx-mo class="mjx-n"><mjx-c class="mjx-c29"></mjx-c></mjx-mo></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><msub><mi>X</mi><mn>1</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(X_1)</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></td><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="14" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D453 TEX-I"></mjx-c></mjx-mi><mjx-mo class="mjx-n"><mjx-c class="mjx-c28"></mjx-c></mjx-mo><mjx-msub><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D44B TEX-I"></mjx-c></mjx-mi><mjx-script style="vertical-align: -0.15em; margin-left: -0.024em;"><mjx-mn class="mjx-n" size="s"><mjx-c class="mjx-c32"></mjx-c></mjx-mn></mjx-script></mjx-msub><mjx-mo class="mjx-n"><mjx-c class="mjx-c29"></mjx-c></mjx-mo></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><msub><mi>X</mi><mn>2</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(X_2)</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></td><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="15" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D453 TEX-I"></mjx-c></mjx-mi><mjx-mo class="mjx-n"><mjx-c class="mjx-c28"></mjx-c></mjx-mo><mjx-msub><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D44B TEX-I"></mjx-c></mjx-mi><mjx-script style="vertical-align: -0.15em; margin-left: -0.024em;"><mjx-mn class="mjx-n" size="s"><mjx-c class="mjx-c33"></mjx-c></mjx-mn></mjx-script></mjx-msub><mjx-mo class="mjx-n"><mjx-c class="mjx-c29"></mjx-c></mjx-mo></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><msub><mi>X</mi><mn>3</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(X_3)</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></td><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="16" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-mo class="mjx-n"><mjx-c class="mjx-c2026"></mjx-c></mjx-mo></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>…</mo></mrow><annotation encoding="application/x-tex">\ldots</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></td><td style="text-align:center"><span class="katex"><span class="katex-mathml mathjax-overflow"><mjx-container class="MathJax CtxtMenu_Attached_0" jax="CHTML" tabindex="0" ctxtmenu_counter="17" style="font-size: 113.1%; position: relative;"><mjx-math class="MJX-TEX" aria-hidden="true"><mjx-semantics><mjx-mrow><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D453 TEX-I"></mjx-c></mjx-mi><mjx-mo class="mjx-n"><mjx-c class="mjx-c28"></mjx-c></mjx-mo><mjx-msub><mjx-mi class="mjx-i"><mjx-c class="mjx-c1D44B TEX-I"></mjx-c></mjx-mi><mjx-script style="vertical-align: -0.15em; margin-left: -0.024em;"><mjx-mi class="mjx-i" size="s"><mjx-c class="mjx-c1D45B TEX-I"></mjx-c></mjx-mi></mjx-script></mjx-msub><mjx-mo class="mjx-n"><mjx-c class="mjx-c29"></mjx-c></mjx-mo></mjx-mrow></mjx-semantics></mjx-math><mjx-assistive-mml unselectable="on" display="inline"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>f</mi><mo stretchy="false">(</mo><msub><mi>X</mi><mi>n</mi></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">f(X_n)</annotation></semantics></math></mjx-assistive-mml></mjx-container></span></span></td></tr></tbody></table><p>则 <strong>似然函数</strong>:</p><script type="math/tex; mode=display">\begin{aligned}\\ &L(\theta)=P_1P_2P_3\ldots P_n(\text {Discrete}) \\ &L(\theta)=f(X_1)f(X_2)f(X_3)\ldots f(X_n)(\text{continuous})\end{aligned}</script><p>令 $L’(\theta)=0$(等价于$(\ln(L(\theta)))’=0$),得到一阶导函数零点,进而求得最大值.</p></li><li><p>注意: 可能求出多个可能的 $p$, 保证样本每一项的概率都为正进行舍去.</p></li></ul><h2 id="6-2-点估计的优良性准则"><a href="#6-2-点估计的优良性准则" class="headerlink" title="6.2. 点估计的优良性准则"></a>6.2. 点估计的优良性准则</h2><h3 id="1-无偏性"><a href="#1-无偏性" class="headerlink" title="1. 无偏性"></a>1. 无偏性</h3><p>   令 $\hat{\theta}$ 为参数 $\theta$ 的估计量 $t$, 定义：如果对一切  $\theta \in \Theta$, 有 $E\hat{\theta}=\theta$ 成立,则称 $\hat\theta$ 为参数 $\theta$ 的无偏估计量.</p><ul><li><p>例1: 总体 $X$ ,$EX=\mu,DX=\sigma^2$,样本为$(X_1,X_2\ldots X_n)$,则</p><ul><li>$\bar{X}$ 是$\mu$ 的无偏估计.</li><li>样本方差 $S^2$ 是 $\sigma^2$ 的无偏估计.</li><li>非修正样本方差是 $\sigma^2$ 的有偏估计.</li></ul></li></ul><p>注意:例1 永远成立, 与总体分布类型无关.</p><ul><li><p>例2: $S^2$ 是 $\sigma^2$ 的无偏估计, $S$ 不一定是 $\sigma$ 的无偏估计.</p><ul><li><p>可得到结论: $\hat\theta$ 是 $\theta$ 的无偏估计, $g(\hat{\theta})$ 不一定是 $\theta$ 的无偏估计.</p><p>证明:</p><script type="math/tex; mode=display">\begin{aligned}  &\\   &DS = ES^2 - (ES)^2=\sigma^2-(ES)^2     \\   &ES = \sqrt{\sigma^2-DS} \leq \sigma                                      \\\end{aligned}</script></li></ul></li><li><p>例3:$\quad \mathcal{\mu}= EX. \quad\left(X<em>{1}\cdots X</em>{n}\right)$<br>  $\hat{\mu}=C<em>{1} X</em>{1}+\cdots+C<em>{n} X</em>{n}$<br>  $C<em>{1}+C</em>{2}+\cdots +C_{n}=1$<br>  则 $\hat\mu$是$\mu$ 的无偏估计</p></li></ul><h3 id="2-有效性"><a href="#2-有效性" class="headerlink" title="2. 有效性"></a>2. 有效性</h3><ul><li>$D\left(\hat{\theta}<em>{1}\right) \leq D\left(\hat{\theta}</em>{2}\right)$ 方差越小越有效</li><li>例: 可以证明, $D(X_i) \geq D(\bar{X}), D(a_1X_1+a_2X_2\cdots a_nX_n) \geq D(\bar{X})$</li></ul><h3 id="3-相合性-一致性"><a href="#3-相合性-一致性" class="headerlink" title="3. 相合性(一致性)"></a>3. 相合性(一致性)</h3><ul><li>$\displaystyle\lim _{n \rightarrow+\infty} p(|\hat{\theta}-\theta|&lt;\varepsilon)=1$</li></ul><h2 id="6-3-参数的区间估计"><a href="#6-3-参数的区间估计" class="headerlink" title="6.3. 参数的区间估计"></a>6.3. 参数的区间估计</h2><ul><li>找两个估计量 $\hat\theta_1,\hat\theta_2(\hat\theta_1 &lt; \hat\theta_2)$ 为端点的区间$[\hat\theta_1,\hat\theta_2]$ 来估计$\theta.$<ul><li><strong>可靠度</strong>: 要求区间以很大的可能性包含 $\theta$ ,即 $P\{\hat\theta_1 &lt;\theta &lt;\hat\theta_2\}.$要尽可能大</li><li><strong>精度</strong>: 精度要尽可能高,即区间长度要尽可能小.</li></ul></li></ul><h3 id="6-3-1-置信区间和枢轴变量"><a href="#6-3-1-置信区间和枢轴变量" class="headerlink" title="6.3.1. 置信区间和枢轴变量"></a>6.3.1. 置信区间和枢轴变量</h3><h4 id="置信区间"><a href="#置信区间" class="headerlink" title="置信区间"></a>置信区间</h4><ul><li><p>定义:  </p><ul><li>对于给定的 $\alpha(0&lt;\alpha&lt;1),$ 如果<script type="math/tex; mode=display">{P}\left(\hat{\theta}_{1} \leq \theta \leq \hat{\theta}_{2}\right)=1-\alpha</script> 则称区间$[\hat\theta_1,\hat\theta_2]$为<strong>置信区间</strong>$, 1-\alpha$为<strong>置信度</strong>(置信系数),$\hat\theta_1,\hat\theta_2$ 分别被称为<strong>置信下限</strong>和<strong>置信上限</strong>.其中 $\alpha$ 一般取 0.05.</li></ul><p>注意: 求置信区间, 就是找一个区间能够 “框住” $\theta$ , 因为 $\theta$ 虽然未知,却是确定的.</p></li></ul><h4 id="枢轴变量"><a href="#枢轴变量" class="headerlink" title="枢轴变量"></a>枢轴变量</h4><ul><li>$I=I(T,\theta)$,其中,$\theta$ 是未知的<strong>待估参数</strong>, $T$ 是已知的与 $\theta$ 有关的统计量, $I$ 服从的分布 $F$ 已知且与 $\theta$ 无关.</li><li>给定 $1-\alpha$ , 确定 $F$ 的上 $\frac \alpha 2$ 分位数 $u<em>{\frac \alpha 2}$ 和上 $(1-\frac \alpha 2)$ 分位数$u</em>{1-\frac \alpha 2}$</li><li>$P\{u<em>{\frac \alpha 2}\leq I(T,\theta)\leq u</em>{\frac \alpha 2}\} = 1-\alpha$, 据此可以求得置信区间.</li></ul><h3 id="6-3-2-单正态总体参数的区间估计"><a href="#6-3-2-单正态总体参数的区间估计" class="headerlink" title="6.3.2. 单正态总体参数的区间估计"></a>6.3.2. 单正态总体参数的区间估计</h3><h4 id="估计-mu"><a href="#估计-mu" class="headerlink" title="估计 $\mu$"></a>估计 $\mu$</h4><ul><li>$\sigma^2$ 已知<ul><li>枢轴变量 $U = \displaystyle\frac{\bar{X}-\mu}{\sigma/\sqrt{n}}\sim N(0,1)$, 然后查表求得 $u<em>\frac \alpha 2$ 再根据对称求得 $u</em>{1 - \frac \alpha 2}.$</li></ul></li><li>$\sigma^2$ 未知<ul><li>枢轴变量 $U = \displaystyle\frac{\bar{X}-\mu}{S/\sqrt{n}}\sim t(n-1)$</li></ul></li></ul><h4 id="估计-sigma-2"><a href="#估计-sigma-2" class="headerlink" title="估计 $\sigma^2$"></a>估计 $\sigma^2$</h4><ul><li>$\mu$ 已知<ul><li>枢轴变量 $U=\displaystyle\frac{1}{\sigma^{2}} \sum<em>{i=1}^{n}\left(X</em>{i}-\mu\right)^{2} \sim \chi ^{2}(n)$</li></ul></li><li>$\mu$ 未知<ul><li>枢轴变量  $U=\displaystyle \frac{(n-1) S^{2}}{\sigma^{2}} \sim \chi ^{2}(n-1)$</li></ul></li><li>注意卡方分布图像不是对称的,所以上分位点必须求两个.</li></ul><h3 id="6-3-2-双正态总体参数的区间估计"><a href="#6-3-2-双正态总体参数的区间估计" class="headerlink" title="6.3.2. 双正态总体参数的区间估计"></a>6.3.2. 双正态总体参数的区间估计</h3><h4 id="估计均值差-mu-1-mu-2"><a href="#估计均值差-mu-1-mu-2" class="headerlink" title="估计均值差 $\mu_1-\mu_2$"></a>估计均值差 $\mu_1-\mu_2$</h4><ul><li><p>$\sigma_1^2,\sigma_2^2$ 已知</p><ul><li>枢轴变量<script type="math/tex; mode=display">\begin{aligned}U=\frac{(\overline{X}-\overline{Y})-\left(\mu_{1}-\mu_{2}\right)}{\sqrt{\frac{\sigma_{\mathbf{1}}^{\mathbf{2}}}{\mathbf{n}_{\mathbf{1}}}+\frac{\sigma_{\mathbf{2}}^{\mathbf{2}}}{\mathbf{n}_{\mathbf{2}}}} }\sim N(\mathbf{0}, \mathbf{1})\end{aligned}</script></li></ul></li><li><p>$\sigma_1^2=\sigma_2^2=\sigma^2$ 未知</p><ul><li>枢轴变量$T=\displaystyle\frac{(\bar{X}-\bar{Y})-\left(\mu<em>{1}-\mu</em>{2}\right)}{\sqrt{\frac{\left(n<em>{1}-1\right) S</em>{1}^{2}+\left(n<em>{2}-1\right) S</em>{2}^{2}}{\left(n<em>{1}+n</em>{2}-2\right)}} \sqrt{\frac{1}{n<em>{1}}+\frac{1}{n</em>{2}}}} \sim t\left(n<em>{1}+n</em>{2}-2\right)$</li></ul></li></ul><h4 id="估计方差比-displaystyle-sigma-2-1-sigma-2-2"><a href="#估计方差比-displaystyle-sigma-2-1-sigma-2-2" class="headerlink" title="估计方差比 $\displaystyle{\sigma^2_1}/{\sigma^2_2}$"></a>估计方差比 $\displaystyle{\sigma^2_1}/{\sigma^2_2}$</h4><ul><li>$\mu_1,\mu_2$ 未知<ul><li>枢轴变量 $\displaystyle\frac{S<em>{1}^{2} / \sigma</em>{1}^{2}}{S<em>{2}^{2} / \sigma</em>{2}^{2}} \sim F\left(n<em>{1}-1 , n</em>{2}-1\right)$</li></ul></li></ul>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 概率论 </tag>
            
            <tag> 数学 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>数据科学基础(八) 多维</title>
      <link href="2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_08/"/>
      <url>2020/12/27/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%A7%91%E5%AD%A6%E5%9F%BA%E7%A1%80_08/</url>
      
        <content type="html"><![CDATA[<div class="note blue icon modern"><i class="note-icon fas fa-rocket"></i><p>📚 文档目录<br><a href="/2020/12/27/数据科学基础/数据科学基础_01">随机事件及其概率</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_02">随机变量及其分布</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_03">期望和方差</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_04">大数定律与中心极限定理</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_05">数理统计的基本概念</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_06">参数估计</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_07">假设检验</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_08">多维</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_09">回归分析和方差分析</a><br><a href="/2020/12/27/数据科学基础/数据科学基础_10">降维</a></p></div><h2 id="8-1-多维概率分布"><a href="#8-1-多维概率分布" class="headerlink" title="8.1 多维概率分布"></a>8.1 多维概率分布</h2><p><strong>分布函数:</strong> $F(x,y) = P\{X \leq x,Y \leq y\}$</p><p><strong>密度函数:</strong> $\displaystyle f(x,y) = \frac{\partial F}{\partial x\partial y}$</p><p><strong>边缘分布</strong>: 设 $(X, Y)$ 为二维随机变量,称一维随机变量 $X$ 或 $Y$ 的概率分布为二维随机变量 $(X, Y)$ 关于 $X$ 或 $Y$ 对应的边缘分布; 分别记作: $F<em>{X}(x), F</em>{Y}(y)_{}$</p><p><strong>二维离散型边缘分布率</strong>:<br>设二维随机变量 $(X, Y)$ 的分布律为 $p_{i j},$ 那么对千随机变量 $X, Y$ 其各自的分布律对于固定的 $i, j=1,2, \cdots,$ 满足</p><script type="math/tex; mode=display">P\left\{X=x_{i}\right\}=\sum_{j} p_{i j}=p_{i}</script><p>则称 $p_{i} .$ 为随机变量 $(X, Y)$ 的边缘分布律。</p><p><strong>二维连续型的边缘概率密度:</strong><br>设二维随机变量$(X,Y)$的概率密度为$f(x,y)$, 由于</p><script type="math/tex; mode=display">F_{X}(x)=\int_{-\infty}^{x} \int_{-\infty}^{\infty} f(x, y) d y d x, F_{Y}(y)=\int_{-\infty}^{y} \int_{-\infty}^{\infty} f(x, y) d x d y</script><p>则</p><script type="math/tex; mode=display">\begin{array}{l}f_{X}(x)=\int_{-\infty}^{+\infty} f(x, y) d y \\f_{Y}(y)=\int_{-\infty}^{+\infty} f(x, y) d x\end{array}</script><p><strong>二维离散随机变量的条件概率:</strong><br>设 $(X, Y)$ 是二维离散型随机变量，其分布律为 $P\{X=x<em>{i}, Y=y</em>{j}\}=p<em>{i j},$ 其边缘概率分别为 $p</em>{i}, p_{\cdot j} .$ 则条件概率定义为</p><script type="math/tex; mode=display">\displaystyle\begin{array}{l}P\left\{X=x_{i} \mid Y=y_{j}\right\}=\frac{P\left\{X=x_{i}, Y=y_{j}\right\}}{P\left\{Y=y_{j}\right\}}=\frac{p_{i j}}{p_{\cdot j}} \\P\left\{Y=y_{j} \mid \mathrm{X}=x_{j}\right\}=\frac{P\left\{X=x_{i}, Y=y_{j}\right\}}{P\left\{X=x_{i}\right\}}=\frac{p_{i j}}{p_{i}}\end{array}</script><p><strong>独立性:</strong> 联合概率 = 边缘概率相乘</p><script type="math/tex; mode=display">\begin{aligned}&F(x,y)=F_X(x) \cdot F_Y(y),\\&P\{X \leq x, Y \leq y\}=P\{X \leq x\} P\{Y \leq y\}\end{aligned}</script><p>几乎处处成立, 则随机变量$X,Y$是相互独立的</p><p>也可以用 $f(x,y)$ 可分离判断.</p><h2 id="8-2-chi-2-独立性检验"><a href="#8-2-chi-2-独立性检验" class="headerlink" title="8.2 $\chi^2$ 独立性检验"></a>8.2 $\chi^2$ 独立性检验</h2><p>假设两个随机变量 $X,Y$, 给定显著性水平 $\alpha$ , 检验非参数假设:</p><p>$H_0: X,Y$ 相互独立, $H_1: X,Y$ 不相互独立</p><p><img src="https://unpkg.zhimg.com/rikka-os@1.0.3/img/image-20210502234756426.webp" alt="image-20210502234756426" style="zoom:80%;" /></p><p>若随机变量 $X,Y$ 独立, 则联合概率  = 边缘概率$\times$边缘概率. 即, 若原假设 $H_0$ 成立, 那么实际联合概率(相对应的经验频数)和理论联合概率,即边缘概率之积(相对应的理论频数)不会相差很大. 构造下方的统计量.</p><script type="math/tex; mode=display">\chi^{2}=\sum \frac{\left(E_{i j}-T_{i j}\right)^{2}}{T_{i j}}</script><p>其中经验频数 <script type="math/tex">E_{ij}=n_{ij}</script>, 理论频数<script type="math/tex">T_{ij}=n\cdot \frac{n_i}{n} \cdot \frac{n_j}{n}</script>, 当 <script type="math/tex">n</script> 充分大时, <script type="math/tex">\chi^2</script> 近似服从 <script type="math/tex">\chi^2</script> 分布:</p><script type="math/tex; mode=display">\chi^{2} \sim \chi^{2}((r-1)(c-1)), r 为行数, c 为列数</script><p>若 $H_0$ 假设成立, 则经验频数和理论频数相差不应该太大, 所以拒绝域为:</p><script type="math/tex; mode=display">\chi^{2} \geq \chi_{\alpha}^{2}((r-1)(c-1))</script>]]></content>
      
      
      <categories>
          
          <category> NJU 笔记 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> 概率论 </tag>
            
            <tag> 数学 </tag>
            
        </tags>
      
    </entry>
    
    
    
    <entry>
      <title>C++ 多态的实现机制</title>
      <link href="2020/06/02/CPP/%E5%A4%9A%E6%80%81/"/>
      <url>2020/06/02/CPP/%E5%A4%9A%E6%80%81/</url>
      
        <content type="html"><![CDATA[<div class="note info flat"><p>若无特殊说明, 以下所有操作均在 32 位环境下进行 </p></div><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><span class="line">6</span><br><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"><span class="class"><span class="keyword">class</span> <span class="title">Animal</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Animal</span>() &#123;&#125;;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">eat</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;Animal::eat()&quot;</span> &lt;&lt; endl; &#125;;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">bark</span><span class="params">()</span> </span>&#123; cout &lt;&lt; <span class="string">&quot;bark()&quot;</span> &lt;&lt; endl; &#125;;</span><br><span class="line">    <span class="keyword">virtual</span> ~<span class="built_in">Animal</span>() &#123;&#125;;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">growUp</span><span class="params">()</span> </span>&#123; age += <span class="number">1</span>; &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">protected</span>:</span><br><span class="line">    <span class="keyword">int</span> age = <span class="number">10</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Dog</span> :</span> <span class="keyword">public</span> Animal</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="built_in">Dog</span>() &#123; age = <span class="number">20</span>; &#125;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">wag</span><span class="params">()</span> </span>&#123;&#125;;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">eat</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        cout &lt;&lt; <span class="string">&quot;Dog::eat()&quot;</span> &lt;&lt; <span class="string">&quot; tail=&quot;</span> &lt;&lt; tail &lt;&lt; <span class="string">&quot;cm&quot;</span> &lt;&lt; endl;</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="keyword">int</span> tail = <span class="number">90</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="工作原理"><a href="#工作原理" class="headerlink" title="工作原理"></a>工作原理</h2><p>首先验证一件事, 任何一个类只要有了虚函数 (Virtual Function) 就会大一点. </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><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">Animal* a = <span class="keyword">new</span> Animal;</span><br><span class="line"><span class="keyword">int</span>* p = (<span class="keyword">int</span>*)a;</span><br><span class="line"></span><br><span class="line">cout &lt;&lt; <span class="built_in"><span class="keyword">sizeof</span></span>(*a) &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">cout &lt;&lt; *p &lt;&lt; endl;</span><br><span class="line">p += <span class="number">1</span>;</span><br><span class="line">cout &lt;&lt; *p &lt;&lt; endl;</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></pre></td><td class="code"><pre><span class="line">8</span><br><span class="line">14588724</span><br><span class="line">10</span><br></pre></td></tr></table></figure><p>可以看到, a 所指的对象大小为 8 个字节, 并且直接把 a 当成 <code>int*</code> 去访问所得到的<strong>不是成员变量 i</strong>,  而 <code>p++</code> 后 (此处地址实际增加了 4), p 指向了成员变量 i </p><p>此时 a 所指的对象如下图:</p><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="121px" viewBox="-0.5 -0.5 121 106" content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2021-05-19T19:09:22.066Z&quot; agent=&quot;5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.57 Safari/537.36 Edg/91.0.864.27&quot; etag=&quot;BUyCiz07XpiV64KJhOeM&quot; version=&quot;14.6.13&quot;&gt;&lt;diagram id=&quot;h0ERZKRE8EeoDrHTSB4W&quot; name=&quot;Page-1&quot;&gt;zZTBboMwDIafJsdNIaGlPZaObodNO1Rbd42ISzIFgtIwaJ9+YQQoqiq1t0kcnM+OY/+2QHSdN8+GleJNc1CIYN4g+oQICUJCUPthfuzIAnuQGcl90Ai28gQeYk8ryeEwCbRaKyvLKUx1UUBqJ4wZo+tp2F6r6asly+ACbFOmLulOcit8FyQa+QvITPQvB/Nl58lZH+w7OQjGdX2GaILo2mhtOytv1qBa8XpdunubK96hMAOFveXC18frN8v2sf0sIrlTlX0np4c+zQ9Tle9Y+nLtsdfA6Krg0KbBiMa1kBa2JUtbb+2m7piwuXKnwJk+HxgLzdVKg6F/tzigc7Dm6EL6C71kfmfI0p/rcQJDjDhTf+YZ80PPhtSjLs7w0twjE76QCSUztArRKmqNGKPFBiUhihcoXrXZXKf/TkY6eyThjUqGj9H8bjHdcdznP9/ZX4Emvw==&lt;/diagram&gt;&lt;/mxfile&gt;" onclick="(function(svg){var src=window.event.target||window.event.srcElement;while (src!=null&amp;&amp;src.nodeName.toLowerCase()!='a'){src=src.parentNode;}if(src==null){if(svg.wnd!=null&amp;&amp;!svg.wnd.closed){svg.wnd.focus();}else{var r=function(evt){if(evt.data=='ready'&amp;&amp;evt.source==svg.wnd){svg.wnd.postMessage(decodeURIComponent(svg.getAttribute('content')),'*');window.removeEventListener('message',r);}};window.addEventListener('message',r);svg.wnd=window.open('https://viewer.diagrams.net/?client=1&amp;page=0&amp;edit=_blank');}}})(this);" style="cursor:pointer;max-width:100%;max-height:106px;"><defs/><g><rect x="0" y="55" width="120" height="50" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 80px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">i</div></div></div></foreignObject><text x="60" y="84" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">age</text></switch></g><rect x="0" y="0.24" width="120" height="54.76" fill="#ffffff" stroke="#000000" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 28px; margin-left: 1px;"><div style="box-sizing: border-box; font-size: 0; text-align: center; "><div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; ">大小为 int</div></div></div></foreignObject><text x="60" y="31" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle">大小为 int</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Viewer does not support full SVG 1.1</text></a></switch></svg><p>上面的其实就是<strong>虚函数表指针 vptr</strong>, 下面才是成员变量 i</p><p>vptr 指向<strong>虚函数表(Vtable)</strong>, 虚函数表中存储的是<strong>该类中所有的 virtual function 的指针</strong>, 也就是说, 每个类只有一张虚函数表, 可以验证一下这件事</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></pre></td><td class="code"><pre><span class="line">Animal a, b;</span><br><span class="line">cout &lt;&lt; *(<span class="keyword">int</span>*)(&amp;a) &lt;&lt; endl;<span class="comment">// 打印出 vptr 所指向的地址</span></span><br><span class="line">cout &lt;&lt; *(<span class="keyword">int</span>*)(&amp;b) &lt;&lt; endl;</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></pre></td><td class="code"><pre><span class="line">4295476</span><br><span class="line">4295476</span><br></pre></td></tr></table></figure><p>两个对象的 vptr 指向了同一张虚函数表.</p><p>以本篇开头的 Animal 类为例, 若实例化一个 Animal 类的对象 , 则这个对象在内存中的组织形式为:</p><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="471px" viewBox="-0.5 -0.5 471 108" content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2021-05-20T09:20:50.229Z&quot; agent=&quot;5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.57 Safari/537.36 Edg/91.0.864.27&quot; etag=&quot;NT_T4InIQ_K9PAUMkzbf&quot; version=&quot;14.6.13&quot;&gt;&lt;diagram id=&quot;kqWCheUJdv6XPKkfyIvA&quot; name=&quot;Page-1&quot;&gt;7ZjbTuMwEIafptLuBascmlAu29I9SLBCdAHtpYndxKrjiRz3xNPvuHGapCFQEKi7K6RcxH/Gh5n57Knb88fp+psiWXIJlIme59B1zz/veZ7b97yeeRy6KZSBY4VYcWqNKmHKH5gVHasuOGV5w1ADCM2zphiBlCzSDY0oBaum2QxEc9aMxKwlTCMi2uodpzqxXninlf6d8TgpZ3bDs+JLSkpj60meEAqrmuRPev5YAejiLV2PmTDBK+NS9Pva8XW3MMWkPqTD75P5rxtYPcxPlj9u3fPJ3XDy88QNi2GWRCysx0NsDiVPibDr1psyGPmKp4JIbI1mIPXUfnGxTQSPJb5HuBqmUFgypTnGcWg/aMhQjRIu6AXZwMKsOdckmpetUQKKP+CwOHExJn5W2iLhOw2LqemJslEVy9HmqgyEuyddknXD8ILk2goRCEGynN/v3EiJirkcgdaQWiPN1nq4752NGvrI1p35cHdZxu3BIGVabdDEdtiBYXeGX7ZXFWduaLWkxtjA7iBi0Y53Q+9mu8atQGSMblXT9Q+YznlkOi9sTkcEhkASzUawkDSvM4cvNU8raUviS6g8bVG5zLRq8WhSs+VEwZyNQYDa6v7Au/fD0FDKhajpNGAD2j+c1jwjEZfxBZuZWPQr5dqGx0iAfWdiu7MTTimThjTQRJMCK8NQBlzqbfyCET4Y5bHzJegFuKgxtt2qjY8xV3oMEv0ifAsTQ2ZXzHB7GHlP7PU2jyUQB+K3z0MdvwYIL876WSvr5nA+KOkSilOplm8rfaS6neogPHKqS0fqZceWHOe2iOZfVHu88Fi15w3KTOC/ssy4Tv+9su91Zd8f4kM1qE+fu/b9f3ikd9ev158AXVRsmjv7eCdA/0kG7omadzPwUfDfgoHAOzYDj1w+agwworsR+IcT+nJ63w2B08GxERi0EGhlnEk6NDd5k21B8pxHphzrtCzVLRSKERht3ez3aibOAgsVsWdvIu341QIWPBKvUlNMEM2XzXU8cW+7MpRVtdsP92r3wGkOUazf9qrf/fcGav0ICM6aA+GvnZjp1kDPX+iwWf2FUZhXfwT5kz8=&lt;/diagram&gt;&lt;/mxfile&gt;" onclick="(function(svg){var src=window.event.target||window.event.srcElement;while (src!=null&amp;&amp;src.nodeName.toLowerCase()!='a'){src=src.parentNode;}if(src==null){if(svg.wnd!=null&amp;&amp;!svg.wnd.closed){svg.wnd.focus();}else{var r=function(evt){if(evt.data=='ready'&amp;&amp;evt.source==svg.wnd){svg.wnd.postMessage(decodeURIComponent(svg.getAttribute('content')),'*');window.removeEventListener('message',r);}};window.addEventListener('message',r);svg.wnd=window.open('https://viewer.diagrams.net/?client=1&amp;page=0&amp;edit=_blank');}}})(this);" style="cursor:pointer;max-width:100%;max-height:108px;"><defs><clipPath id="mx-clip-4-35-152-26-0"><rect x="4" y="35" width="152" height="26"/></clipPath><clipPath id="mx-clip-4-61-152-26-0"><rect x="4" y="61" width="152" height="26"/></clipPath><clipPath id="mx-clip-314-31-152-26-0"><rect x="314" y="31" width="152" height="26"/></clipPath><clipPath id="mx-clip-314-57-152-26-0"><rect x="314" y="57" width="152" height="26"/></clipPath><clipPath id="mx-clip-314-83-152-26-0"><rect x="314" y="83" width="152" height="26"/></clipPath></defs><g><path d="M 0 30 L 0 0 L 160 0 L 160 30" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 0 30 L 0 82 L 160 82 L 160 30" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 0 30 L 160 30" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g fill="#000000" font-family="Helvetica" font-weight="bold" pointer-events="none" text-anchor="middle" font-size="12px"><text x="79.5" y="17.5">A Animal</text></g><rect x="0" y="30" width="160" height="26" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/><g fill="#000000" font-family="Helvetica" pointer-events="none" clip-path="url(#mx-clip-4-35-152-26-0)" text-anchor="middle" font-size="12px"><text x="79.5" y="47.5">vptr</text></g><g fill="#000000" font-family="Helvetica" pointer-events="none" clip-path="url(#mx-clip-4-61-152-26-0)" text-anchor="middle" font-size="12px"><text x="79.5" y="73.5">age</text></g><path d="M 310 26 L 310 0 L 470 0 L 470 26" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 310 26 L 310 104 L 470 104 L 470 26" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 310 26 L 470 26" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g fill="#000000" font-family="Helvetica" font-weight="bold" pointer-events="none" text-anchor="middle" font-size="12px"><text x="389.5" y="17.5">Animal Vtable</text></g><rect x="310" y="26" width="160" height="26" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/><g fill="#000000" font-family="Helvetica" pointer-events="none" clip-path="url(#mx-clip-314-31-152-26-0)" text-anchor="middle" font-size="12px"><text x="389.5" y="43.5">Animal::dtor()</text></g><rect x="310" y="52" width="160" height="26" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/><g fill="#000000" font-family="Helvetica" pointer-events="none" clip-path="url(#mx-clip-314-57-152-26-0)" text-anchor="middle" font-size="12px"><text x="389.5" y="69.5">Animal::bark()</text></g><rect x="310" y="78" width="160" height="26" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/><g fill="#000000" font-family="Helvetica" pointer-events="none" clip-path="url(#mx-clip-314-83-152-26-0)" text-anchor="middle" font-size="12px"><text x="389.5" y="95.5">Animal::eat()</text></g><path d="M 160 41.61 L 303.63 39.11" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 308.88 39.02 L 301.94 42.64 L 303.63 39.11 L 301.82 35.64 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/></g></svg><p>任何一个 Animal 的对象都会有一个指向 <strong>Animal Vtable</strong> 的虚函数指针</p><p>而派生类 Dog 的对象如下:</p><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="471px" viewBox="-0.5 -0.5 471 112" content="&lt;mxfile host=&quot;app.diagrams.net&quot; modified=&quot;2021-05-22T02:36:33.684Z&quot; agent=&quot;5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.69 Safari/537.36 Edg/91.0.864.33&quot; etag=&quot;Wcxjx654K8i-MXn583rs&quot; version=&quot;14.7.0&quot; type=&quot;browser&quot;&gt;&lt;diagram id=&quot;kqWCheUJdv6XPKkfyIvA&quot; name=&quot;Page-1&quot;&gt;7Vhbb5swFP41kbaHTFwCoY8kzbpJ7VQ1W7s9OtiAFWMj41x//exgAsRJS6d22apKPODPx5dzvu/41nPH2fqKgzy9YRCRnmPBdc+97DmOPXCcnvosuCmRwNJAwjHURjUwxVukQUujCwxR0TIUjBGB8zYYMUpRJFoY4Jyt2mYxI+1Rc5AgA5hGgJjoA4Yi1V44wxr/gnCSViPb/kVZk4HKWHtSpACyVQNyJz13zBkT5V+2HiOiglfFpWz3+UTtfmIcUdGlwa/+/PsPttrO+8uv9/bl5CGcfOu7g7KbJSAL7XEoi5cs0ZMWmyoSxQpnBFBZGsWMiqmusWUZEJxQ+R/JqSAugSXiAssghrpCsFyiUYoJvAYbtlATLgSI5lVplDKOt7JbQHSfspoLrQfXallMVUsJK5SjQtrcVlGwD6AbsG4ZXoNCaCBihIC8wLO9GxngCaYjJgTLtJFAaxEeemdGXpOh3EbrBqSZuEIsQ4JvpImu3etbp4Xn6vKqFpntayxtCswKtLi1sJN93/vh7mQiAJpIv+rxBu3xXOfIeNaR8Ry/PRwgMgYUCDRiCwqLpuLkT8PVGtrp8Dma9AxNLnPBDUEqbnZC4WyOxowwvsPdwJm5vq9kiglp4NBDARx0l2uRgwjT5BrFKhaDGrnT4VEQk21jssvrFEOIqJIaE0CAUldKRDnDVOzi543kJ6M8tj55PU9OaizLdl2WnzLnYsyo9AvgncCQFO0KKeEekd7jaf20ICtBdNTfoR6a8msJ4dms+wbramnuRDpl5bLU4FtD71SbVHv+36N6atNkGfxM4m0aL+dhPg1j2LcNpgXApHN++1GAZvGR/AYoiKO3QLrBZWcdnCQ9cM6d30OD9d0pw7ovQ/kPHTcc/1zHjRc4WXjOH58sBq9FfXCUejeUHxSMf/h4KvffYIafXs66JvqwsyQ27Zw+X+5fmLcMijOVfEoDM8DnpzXwfr57CQ14517/qwvIsUUAAXGa//+YzecfXV6N/2Fwbv7NU5/BOKIwVG82im0CigKrkKQiqzZpQwon98uCLXiEHougvmQi2Hr/MePXCJh3JF4VxhEBAi/br0aP3NFvlcrqXdv1DnbtC6vdRemQbtV85TnoyNj+q/eoqiN5zkmQMDp6+vIui/VjVWleP/m5k98=&lt;/diagram&gt;&lt;/mxfile&gt;" onclick="(function(svg){var src=window.event.target||window.event.srcElement;while (src!=null&amp;&amp;src.nodeName.toLowerCase()!='a'){src=src.parentNode;}if(src==null){if(svg.wnd!=null&amp;&amp;!svg.wnd.closed){svg.wnd.focus();}else{var r=function(evt){if(evt.data=='ready'&amp;&amp;evt.source==svg.wnd){svg.wnd.postMessage(decodeURIComponent(svg.getAttribute('content')),'*');window.removeEventListener('message',r);}};window.addEventListener('message',r);svg.wnd=window.open('https://viewer.diagrams.net/?client=1&amp;page=0&amp;edit=_blank');}}})(this);" style="cursor:pointer;max-width:100%;max-height:112px;"><defs><clipPath id="mx-clip-4-35-152-26-0"><rect x="4" y="35" width="152" height="26"/></clipPath><clipPath id="mx-clip-4-61-152-26-0"><rect x="4" y="61" width="152" height="26"/></clipPath><clipPath id="mx-clip-4-87-152-26-0"><rect x="4" y="87" width="152" height="26"/></clipPath><clipPath id="mx-clip-314-31-152-26-0"><rect x="314" y="31" width="152" height="26"/></clipPath><clipPath id="mx-clip-314-57-152-26-0"><rect x="314" y="57" width="152" height="26"/></clipPath><clipPath id="mx-clip-314-83-152-26-0"><rect x="314" y="83" width="152" height="26"/></clipPath></defs><g><path d="M 0 30 L 0 0 L 160 0 L 160 30" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="all"/><path d="M 0 30 L 0 108 L 160 108 L 160 30" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 0 30 L 160 30" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g fill="#000000" font-family="Helvetica" font-weight="bold" pointer-events="none" text-anchor="middle" font-size="12px"><text x="79.5" y="17.5">A Dog</text></g><rect x="0" y="30" width="160" height="26" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/><g fill="#000000" font-family="Helvetica" pointer-events="none" clip-path="url(#mx-clip-4-35-152-26-0)" text-anchor="middle" font-size="12px"><text x="79.5" y="47.5">vptr</text></g><g fill="#000000" font-family="Helvetica" pointer-events="none" clip-path="url(#mx-clip-4-61-152-26-0)" text-anchor="middle" font-size="12px"><text x="79.5" y="73.5">age</text></g><rect x="0" y="82" width="160" height="26" fill="#dae8fc" stroke="#6c8ebf" pointer-events="none"/><g fill="#000000" font-family="Helvetica" pointer-events="none" clip-path="url(#mx-clip-4-87-152-26-0)" text-anchor="middle" font-size="12px"><text x="79.5" y="99.5">tail</text></g><path d="M 310 26 L 310 0 L 470 0 L 470 26" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 310 26 L 310 104 L 470 104 L 470 26" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 310 26 L 470 26" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g fill="#000000" font-family="Helvetica" font-weight="bold" pointer-events="none" text-anchor="middle" font-size="12px"><text x="389.5" y="17.5">Dog Vtable</text></g><rect x="310" y="26" width="160" height="26" fill="#dae8fc" stroke="#6c8ebf" pointer-events="none"/><g fill="#000000" font-family="Helvetica" pointer-events="none" clip-path="url(#mx-clip-314-31-152-26-0)" text-anchor="middle" font-size="12px"><text x="389.5" y="43.5">Dog::dtor()</text></g><rect x="310" y="52" width="160" height="26" fill="#d5e8d4" stroke="#82b366" pointer-events="none"/><g fill="#000000" font-family="Helvetica" pointer-events="none" clip-path="url(#mx-clip-314-57-152-26-0)" text-anchor="middle" font-size="12px"><text x="389.5" y="69.5">Animal::bark()</text></g><rect x="310" y="78" width="160" height="26" fill="#dae8fc" stroke="#6c8ebf" pointer-events="none"/><g fill="#000000" font-family="Helvetica" pointer-events="none" clip-path="url(#mx-clip-314-83-152-26-0)" text-anchor="middle" font-size="12px"><text x="389.5" y="95.5">Dog::eat()</text></g><path d="M 160 41.61 L 303.63 39.11" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 308.88 39.02 L 301.94 42.64 L 303.63 39.11 L 301.82 35.64 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/></g></svg><p>这个对象也有一个 vptr, 但是它指向的不是 Animal 类的虚函数表, 而是自己类的.</p><p>需要注意的一点是, 派生类的虚函数表和基类的结构是一致的, 其中析构函数和 eat() 是自己的, bark() 沿用了 Animal 的 (析构函数编译器自动制造一个). 如果派生类中新增了虚函数, 虚函数表中会在原来的基础上新增.</p><h2 id="如果做点邪恶的事情"><a href="#如果做点邪恶的事情" class="headerlink" title="如果做点邪恶的事情"></a>如果做点邪恶的事情</h2><p>将一个 Animal 的指针指向一个 Dog 的对象, 通过指针调用 <code>eat()</code> 函数, 会调用 Dog::eat()</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">Animal a;</span><br><span class="line">Dog b;</span><br><span class="line">Animal* p = &amp;b;</span><br><span class="line">p-&gt;eat();</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">Dog::eat() tail=30cm</span><br></pre></td></tr></table></figure><p>这是一般用法. 对象没有发生任何的变化, 仅仅是让一个基类的指针指向了派生类的对象.</p><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></pre></td><td class="code"><pre><span class="line">Animal a;</span><br><span class="line">Dog b;</span><br><span class="line">a = b;</span><br><span class="line">a.<span class="built_in">eat</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></pre></td><td class="code"><pre><span class="line">Animal::eat()</span><br></pre></td></tr></table></figure><p>这叫做<strong>sliced off</strong>, 只有继承自基类的部分会被拷贝给 a, 其余的部分就被 “切掉了”.</p><p>只有通过<strong>指针或者引用调用</strong>才会是动态绑定, 此处当然在 <code>a=b;</code> 后, 即使通过指向 a 的指针调用也不会是动态绑定的, 这是因为, 在进行对象的赋值操作时, 虚函数表指针 vptr 并不会随着赋给 a, a 调用的还是 Animal 类内的函数.</p><p>是否可以做一些邪恶的事情呢 ?手动将 b 的 vptr 赋值给 a 会怎样?</p><div class="note warning flat"><p>千万不要在实际写代码中这样做! 这仅仅是为了研究 virtual function 实现的原理</p></div><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><span class="line">6</span><br><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">// 不同的编译器可能不一样, 此处为 cl 编译器 32 位环境. 若需要在 64 位下查看, 应该把 1 均改为 2, 2 均改为 4. </span></span><br><span class="line"><span class="comment">//我在 g++ 下编译需要将 *(p+1) 改为 *(p+2), 原来的 *(p+2) 改为 *(p+3) 我暂时先不去研究了</span></span><br><span class="line"><span class="comment">//若无法得到预期的结果, 将 Animal 和 Dog 的 protected 以及 private 设为 public 根据它们的地址调整偏移量</span></span><br><span class="line">Animal a;</span><br><span class="line">Dog b;</span><br><span class="line">Animal* pa = &amp;a;</span><br><span class="line"></span><br><span class="line">pa-&gt;<span class="built_in">eat</span>();<span class="comment">//调用 Animal::eat(), 这是正常的用法</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//cout &lt;&lt; &amp;b.age &lt;&lt; &quot; &quot; &lt;&lt; &amp;b.tail &lt;&lt; endl;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span>* p = (<span class="keyword">int</span>*)&amp;a;</span><br><span class="line"><span class="keyword">int</span>* q = (<span class="keyword">int</span>*)&amp;b;</span><br><span class="line"></span><br><span class="line">cout &lt;&lt; <span class="string">&quot;a vtable 的地址&quot;</span> &lt;&lt; *p &lt;&lt; endl;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;age &quot;</span> &lt;&lt; *(p + <span class="number">1</span>) &lt;&lt; endl;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;b vtable 的地址&quot;</span> &lt;&lt; *q &lt;&lt; endl;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;age &quot;</span> &lt;&lt; *(q + <span class="number">1</span>) &lt;&lt; endl;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;tail &quot;</span> &lt;&lt; *(q +<span class="number">2</span>) &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">*p = *q;<span class="comment">//仅将 Dog 的vptr 赋给 a</span></span><br><span class="line"></span><br><span class="line">cout &lt;&lt; <span class="string">&quot;a vtable 的地址&quot;</span> &lt;&lt; *p &lt;&lt; endl;<span class="comment">//可以观察到a 的 vtable 的地址已经与 b 一致</span></span><br><span class="line">cout &lt;&lt; <span class="string">&quot;age &quot;</span> &lt;&lt; *(p + <span class="number">1</span>) &lt;&lt; endl;<span class="comment">//其他的没有变化</span></span><br><span class="line">cout &lt;&lt; <span class="string">&quot;b vtable 的地址&quot;</span> &lt;&lt; *q &lt;&lt; endl;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;age &quot;</span> &lt;&lt; *(q + <span class="number">1</span>) &lt;&lt; endl;</span><br><span class="line">cout &lt;&lt; <span class="string">&quot;tail &quot;</span> &lt;&lt; *(q + <span class="number">2</span>) &lt;&lt; endl;</span><br><span class="line"></span><br><span class="line">pa-&gt;<span class="built_in">eat</span>();<span class="comment">//调用 Dog::eat()</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></pre></td><td class="code"><pre><span class="line">Animal::eat()</span><br><span class="line">a vtable 的地址12229428</span><br><span class="line">age 10</span><br><span class="line">b vtable 的地址12229464</span><br><span class="line">age 20</span><br><span class="line">tail 90</span><br><span class="line">a vtable 的地址12229464</span><br><span class="line">age 10</span><br><span class="line">b vtable 的地址12229464</span><br><span class="line">age 20</span><br><span class="line">tail 90</span><br><span class="line">Dog::eat() tail=-858993460cm</span><br></pre></td></tr></table></figure><p>手动将 vptr 赋值后, a 的 vptr 不再指向 Animal 的虚函数表, 而是指向 Dog 的虚函数表, 所以调用 <code>eat()</code> 的时候会调用 <code>Dog::eat()</code> . 同时可以看到, 最后打印了一个奇怪的值, 因为 Dog 类中新增了一个成员变量 tail (可以看到尽管 tail 是private 也<strong>并非没有办法去访问甚至修改</strong>), 而在基类 Animal 中是不存在的. 所以 <code>Dog::eat()</code> 会把 <code>a.age</code> 下面的那块内存当成 <code>a.tail</code> 来打印.</p><h2 id="虚拟析构函数-Virtual-destructors"><a href="#虚拟析构函数-Virtual-destructors" class="headerlink" title="虚拟析构函数 (Virtual destructors)"></a>虚拟析构函数 (Virtual destructors)</h2><p>关于析构函数, 若类中存在虚函数, 则必须将该类的析构函数也设为 virtual, 否则会有麻烦, 因为如果不是 virtual, 在析构时发生的是静态绑定, 派生类的析构就被丢掉了.</p><h2 id="重写-Overridding"><a href="#重写-Overridding" class="headerlink" title="重写 (Overridding)"></a>重写 (Overridding)</h2><p>C++ 中, Overidding 重定义了 virtual function 的函数体, 发生 overriding 之后, 若要调用基类中的同名的 virtual function, 需要用 <code>Base::func();</code> 这样的语法</p><p>构成 overridding 的条件:</p><ul><li><p>函数名一致</p></li><li><p>函数参数一致</p></li><li><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><span class="line">6</span><br><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">class</span> <span class="title">Expr</span>&#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> Expr* <span class="title">newExpr</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> Expr&amp; <span class="title">clone</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> Expr <span class="title">self</span><span class="params">()</span></span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BinaryExpr</span> :</span> <span class="keyword">public</span> Expr&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> BinaryExpr* <span class="title">newExpr</span><span class="params">()</span></span>;<span class="comment">//OK</span></span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> BinaryExpr&amp; <span class="title">clone</span><span class="params">()</span></span>;<span class="comment">//OK</span></span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> BinaryExpr <span class="title">self</span><span class="params">()</span></span>;<span class="comment">//ERROR</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></li></ul><h2 id="重载与虚函数-Overloading-and-virtuals"><a href="#重载与虚函数-Overloading-and-virtuals" class="headerlink" title="重载与虚函数 (Overloading and virtuals)"></a>重载与虚函数 (Overloading and virtuals)</h2><ul><li><p>Overloading 添加了多种签名</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="class"><span class="keyword">class</span> <span class="title">Base</span> &#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">func</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">func</span><span class="params">(<span class="keyword">int</span>)</span></span>;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></li><li><p>若对基类中的重载函数 (overloaded function)进行重写 (override), 必须保证重写所有的重载</p><ul><li>若只重写一部分, 其余的基类中的同名函数将会发生 name hiding.</li></ul></li></ul><h2 id="通过函数指针调用-virtual-function-的尝试"><a href="#通过函数指针调用-virtual-function-的尝试" class="headerlink" title="通过函数指针调用 virtual function 的尝试"></a>通过函数指针调用 virtual function 的尝试</h2><p>既然已经能够得到虚函数表的地址, 那么自然想要尝试用函数指针的方式来调用, 但是这并没有想象中的那么简单, 以下内容来自本人的尝试, 非常感谢 czg 同学的帮助.</p><div class="note info disabled"><p>测试平台的配置信息:<br>    系统: Windows 10<br>    编译器: cl (x86)/g++ (x64)<br>若在 64 位下编译, 需要将所有的 1 改为 2, 2 改为 4</p></div><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><span class="line">6</span><br><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="keyword">typedef</span> <span class="title">void</span><span class="params">(*Fun)</span><span class="params">()</span></span>;</span><br><span class="line">Animal* a = <span class="keyword">new</span> <span class="built_in">Animal</span>();</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span>* p = (<span class="keyword">int</span>*)a;<span class="comment">//*p 是一个指针, 指向虚函数表</span></span><br><span class="line"><span class="keyword">int</span>* q = (<span class="keyword">int</span>*)*p;<span class="comment">//q 的值与 *p 相同, 指向虚函数表第一项 , *q 是函数指针</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//调用 Animal::eat(), 等价于 ((void(*)())(*(int*)*(int*)a))();</span></span><br><span class="line">((Fun)*q)();</span><br><span class="line"></span><br><span class="line"><span class="comment">//调用bark(), 等价于 ((void(*)())*((int*)*(int*)a+1))();</span></span><br><span class="line">((Fun)*(q+<span class="number">1</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></pre></td><td class="code"><pre><span class="line">Animal::eat()</span><br><span class="line">bark()</span><br></pre></td></tr></table></figure><p>通过函数指针确实成功地调用了函数, 接下来尝试验证动态绑定, 使指针 a 指向一个 Dog 类型的对象:</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><span class="line">6</span><br><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="keyword">typedef</span> <span class="title">void</span><span class="params">(*Fun)</span><span class="params">()</span></span>;</span><br><span class="line">Animal* a = <span class="keyword">new</span> <span class="built_in">Dog</span>();</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span>* p = (<span class="keyword">int</span>*)a;<span class="comment">//*p 是一个指针, 指向虚函数表</span></span><br><span class="line"><span class="keyword">int</span>* q = (<span class="keyword">int</span>*)*p;<span class="comment">//q 的值与 *p 相同, 指向虚函数表第一项 , *q 是函数指针</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//调用 Dog::eat(), 等价于 ((void(*)())(*(int*)*(int*)a))();</span></span><br><span class="line">((Fun)*q)();</span><br><span class="line"></span><br><span class="line"><span class="comment">//调用bark(), 等价于 ((void(*)())*((int*)*(int*)a+1))();</span></span><br><span class="line">((Fun)*(q+<span class="number">1</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></pre></td><td class="code"><pre><span class="line">Dog::eat() tail=-1779892224cm</span><br><span class="line">bark()</span><br></pre></td></tr></table></figure><p>成功地调用了 <code>Dog::eat()</code> , 不过 <code>Dog::eat()</code> 并没有成功地获取到成员变量 tail 的值.</p><p>如何才能让虚函数绑定到具体的对象? 很自然的想法是将函数指针<code>Fun</code> 声明为 <code>typedef void(*Fun)(Animal*);</code>, 然后通过传参将 “this 指针” (实际上是指向对象的指针) 传给函数, 以期待函数将这个参数像 this 指针 那般使用.</p><span class='p red bold'>然后问题出现了:</span><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><span class="line">6</span><br><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="keyword">typedef</span> <span class="title">void</span><span class="params">(*Fun)</span><span class="params">(Animal*)</span></span>;</span><br><span class="line">Animal* a = <span class="keyword">new</span> <span class="built_in">Dog</span>();</span><br><span class="line"></span><br><span class="line"><span class="keyword">int</span>* p = (<span class="keyword">int</span>*)a;<span class="comment">//*p 是一个指针, 指向虚函数表</span></span><br><span class="line"><span class="keyword">int</span>* q = (<span class="keyword">int</span>*)*p;<span class="comment">//q 的值与 *p 相同, 指向虚函数表第一项 , *q 是函数指针</span></span><br><span class="line"></span><br><span class="line">((<span class="built_in"><span class="keyword">void</span></span>(*)(Animal*))(*(<span class="keyword">int</span>*)*(<span class="keyword">int</span>*)a))(a);   <span class="comment">//OK</span></span><br><span class="line"></span><br><span class="line">((Fun)(*(<span class="keyword">int</span>*)*(<span class="keyword">int</span>*)a))(a);                <span class="comment">//OK</span></span><br><span class="line"></span><br><span class="line">((Fun)(*(<span class="keyword">int</span>*)*p))(a);                      <span class="comment">//OK</span></span><br><span class="line"></span><br><span class="line">((Fun)(*q))(a);                             <span class="comment">//tail 的值不正确</span></span><br></pre></td></tr></table></figure><p>输出结果(截图):</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/多态.assets//image-20210521000428670.png" alt="image-20210521000428670"></p><p>可是, <code>*(int*)*p)</code> 的值与 <code>*q</code> 是完全一致的, 问题到底出在哪里?</p><p>换到 g++ 编译器上, 再试试看:</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/多态.assets//image-20210521000634740.png" alt="image-20210521000634740"></p><p>尽管编译器给出了不少 waring ,但这确实是预期的结果. 在 czg 同学的帮助下, 我查看了汇编代码以及微软 Argument Passing and Naming Conventions (传参与命名公约)文档</p><div class="tag link"><a class="link-card" title="Argument Passing and Naming Conventions" href="https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions?view=msvc-160"><div class="left"><img src="https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE1Mu3b?ver=5c31"/></div><div class="right"><p class="text">Argument Passing and Naming Conventions</p><p class="url">https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions?view=msvc-160</p></div></a></div><p>The following calling conventions are supported by the Visual C/C++ compiler.</p><div class="table-container"><table><thead><tr><th style="text-align:left">Keyword</th><th style="text-align:left">Stack cleanup</th><th style="text-align:left">Parameter passing</th></tr></thead><tbody><tr><td style="text-align:left"><a href="https://docs.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-160">__cdecl</a></td><td style="text-align:left">Caller</td><td style="text-align:left">Pushes parameters on the stack, in reverse order (right to left)</td></tr><tr><td style="text-align:left"><a href="https://docs.microsoft.com/en-us/cpp/cpp/clrcall?view=msvc-160">__clrcall</a></td><td style="text-align:left">n/a</td><td style="text-align:left">Load parameters onto CLR expression stack in order (left to right).</td></tr><tr><td style="text-align:left"><a href="https://docs.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-160">__stdcall</a></td><td style="text-align:left">Callee</td><td style="text-align:left">Pushes parameters on the stack, in reverse order (right to left)</td></tr><tr><td style="text-align:left"><a href="https://docs.microsoft.com/en-us/cpp/cpp/fastcall?view=msvc-160">__fastcall</a></td><td style="text-align:left">Callee</td><td style="text-align:left">Stored in registers, then pushed on stack</td></tr><tr><td style="text-align:left"><a href="https://docs.microsoft.com/en-us/cpp/cpp/thiscall?view=msvc-160">__thiscall</a></td><td style="text-align:left">Callee</td><td style="text-align:left">Pushed on stack; <strong><code>this</code></strong> pointer stored in ECX</td></tr><tr><td style="text-align:left"><a href="https://docs.microsoft.com/en-us/cpp/cpp/vectorcall?view=msvc-160">__vectorcall</a></td><td style="text-align:left">Callee</td><td style="text-align:left">Stored in registers, then pushed on stack in reverse order (right to left)</td></tr></tbody></table></div><p>在调用成员函数时是 <a href="https://docs.microsoft.com/en-us/cpp/cpp/thiscall?view=msvc-160">__thiscall</a> , 将 <code>this</code> 指针存入 ECX 寄存器, 而通过传参的方式 <a href="https://docs.microsoft.com/en-us/cpp/cpp/cdecl?view=msvc-160">__cdecl</a> 是将参数压入栈中, 因此, 此处出问题是成员函数 <code>Dog::eat()</code> 想从 ECX 寄存器得到 <code>this</code> 指针, 但是 <code>this</code> 并不在哪里, 所以得到的 tail 值就是错误的.</p><p>至于为什么前几个看似工作正常, 是由于函数执行期间恰好将 a 的值 move 进了 ECX 寄存器.</p><p>可以看一下相应的汇编代码</p><p><img src="https://cdn.jsdelivr.net/gh/ayasa520/ayasa520.github.io@master/image/多态.assets//image-20210521002412609.png" alt="image-20210521002412609"></p><p>在 Visual Studio x86 编译下出现的这种情况是可以复现的, g++ 编译却没有出现过. 这件事情和不同的平台, 不同的编译器都有关系, 因此只需了解虚函数实现多态的原理即可, 不必强求用代码实现.</p>]]></content>
      
      
      <categories>
          
          <category> 日常总结 </category>
          
      </categories>
      
      
        <tags>
            
            <tag> C++ </tag>
            
        </tags>
      
    </entry>
    
    
  
  
</search>
