<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <generator uri="http://jekyllrb.com" version="4.3.3">Jekyll</generator>
  
  
  <link href="https://blog.talkincode.net/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://blog.talkincode.net/" rel="alternate" type="text/html" />
  <updated>2024-07-02T17:37:54+00:00</updated>
  <id>https://blog.talkincode.net//</id>

  
    <title type="html">谈晶阁</title>
  

  
    <subtitle>谈晶阁是一个技术博客；关于编程，梦想、科技和未来的故事集。我们渴望知识，对未知充满好奇。</subtitle>
  

  

  
  
    <entry>
      
      <title type="html">信息奥赛一本通函数题库解析: 回文三位数</title>
      
      
      <link href="https://blog.talkincode.net/2024/07/02/palindromic-three-digit-numbers/" rel="alternate" type="text/html" title="信息奥赛一本通函数题库解析: 回文三位数" />
      
      <published>2024-07-02T17:24:37+00:00</published>
      <updated>2024-07-02T17:24:37+00:00</updated>
      <id>https://blog.talkincode.net/2024/07/02/palindromic-three-digit-numbers</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/07/02/palindromic-three-digit-numbers/">&lt;p&gt;原题链接: &lt;a href=&quot;http://ybt.ssoier.cn:8088/problem_show.php?pid=1155&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/jamiesun/images/master/default/F9bxon.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;解题思路&lt;/h2&gt;

&lt;p&gt;题目要求找出所有既是回文数又是素数的三位数。一个回文数是指从左到右读和从右到左读都相同的数。一个素数是指除了 1 和自身外没有其他因数的自然数。&lt;/p&gt;

&lt;h3&gt;步骤&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;判断一个数是否为素数&lt;/strong&gt;：编写一个函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_prime&lt;/code&gt; 来判断一个数是否为素数。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;判断一个数是否为回文数&lt;/strong&gt;：编写一个函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_palindrome&lt;/code&gt; 来判断一个数是否为回文数。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;遍历所有三位数&lt;/strong&gt;：从 100 到 999 遍历每个数，检查它们是否既是回文数又是素数，并输出结果。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;代码实现&lt;/h3&gt;

&lt;p&gt;以下是实现上述步骤的 C++ 代码：&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 函数：判断一个数是否为素数&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 1 及以下的数不是素数&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 如果找到因子，则不是素数&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 如果没有找到因子，则是素数&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 函数：判断一个数是否为回文数&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_palindrome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;original&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reversed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;reversed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reversed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;original&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reversed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 遍历所有三位数&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;999&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_palindrome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 输出既是回文数又是素数的三位数&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3&gt;代码讲解&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_prime&lt;/code&gt; 函数&lt;/strong&gt;：用于判断一个数是否为素数。若数小于或等于1，则返回 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;。否则，通过遍历从 2 到 (\sqrt{num}) 的所有整数，检查 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;num&lt;/code&gt; 是否能被整除。如果能被整除，则返回 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;；否则返回 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;。&lt;/p&gt;

    &lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_palindrome&lt;/code&gt; 函数&lt;/strong&gt;：用于判断一个数是否为回文数。通过将数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;num&lt;/code&gt; 反转并与原数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;original&lt;/code&gt; 比较，若相同则为回文数。&lt;/p&gt;

    &lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_palindrome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
     &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;original&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reversed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;reversed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reversed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;original&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reversed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;主程序&lt;/strong&gt;：遍历所有三位数（100 到 999），对于每个数，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_prime&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_palindrome&lt;/code&gt; 函数检查其是否既是回文数又是素数。如果是，则输出该数。&lt;/p&gt;

    &lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;999&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_palindrome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
             &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;知识点总结&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;素数判断&lt;/strong&gt;：通过判断一个数是否能被 2 到 (\sqrt{num}) 之间的数整除来判断其是否为素数。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;回文数判断&lt;/strong&gt;：通过反转数字并与原数字比较来判断其是否为回文数。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;遍历和条件判断&lt;/strong&gt;：遍历所有三位数并使用条件判断来筛选既是回文数又是素数的数。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;以上代码和讲解展示了如何有效地找出所有既是回文数又是素数的三位数并按要求输出结果。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="algorithms" />
      
        <category term="olympiad" />
      
        <category term="functions" />
      

      

      
        <summary type="html">原题链接: 解题思路 题目要求找出所有既是回文数又是素数的三位数。一个回文数是指从左到右读和从右到左读都相同的数。一个素数是指除了 1 和自身外没有其他因数的自然数。 步骤 判断一个数是否为素数：编写一个函数 is_prime 来判断一个数是否为素数。 判断一个数是否为回文数：编写一个函数 is_palindrome 来判断一个数是否为回文数。 遍历所有三位数：从 100 到 999 遍历每个数，检查它们是否既是回文数又是素数，并输出结果。 代码实现 以下是实现上述步骤的 C++ 代码： #include &amp;lt;iostream&amp;gt; #include &amp;lt;cmath&amp;gt; using namespace std; // 函数：判断一个数是否为素数 bool is_prime(int num) { if (num &amp;lt;= 1) return false; // 1 及以下的数不是素数 for (int i = 2; i &amp;lt;= sqrt(num); ++i) { if (num % i == 0) return false; // 如果找到因子，则不是素数 } return true; // 如果没有找到因子，则是素数 } // 函数：判断一个数是否为回文数 bool is_palindrome(int num) { int original = num, reversed = 0; while (num &amp;gt; 0) { reversed = reversed * 10 + num % 10; num /= 10; } return original == reversed; } int main() { // 遍历所有三位数 for (int i = 100; i &amp;lt;= 999; ++i) { if (is_prime(i) &amp;amp;&amp;amp; is_palindrome(i)) { cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; endl; // 输出既是回文数又是素数的三位数 } } return 0; } 代码讲解 is_prime 函数：用于判断一个数是否为素数。若数小于或等于1，则返回 false。否则，通过遍历从 2 到 (\sqrt{num}) 的所有整数，检查 num 是否能被整除。如果能被整除，则返回 false；否则返回 true。 bool is_prime(int num) { if (num &amp;lt;= 1) return false; for (int i = 2; i &amp;lt;= sqrt(num); ++i) { if (num % i == 0) return false; } return true; } is_palindrome 函数：用于判断一个数是否为回文数。通过将数 num 反转并与原数 original 比较，若相同则为回文数。 bool is_palindrome(int num) { int original = num, reversed = 0; while (num &amp;gt; 0) { reversed = reversed * 10 + num % 10; num /= 10; } return original == reversed; } 主程序：遍历所有三位数（100 到 999），对于每个数，使用 is_prime 和 is_palindrome 函数检查其是否既是回文数又是素数。如果是，则输出该数。 int main() { for (int i = 100; i &amp;lt;= 999; ++i) { if (is_prime(i) &amp;amp;&amp;amp; is_palindrome(i)) { cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; endl; } } return 0; } 知识点总结 素数判断：通过判断一个数是否能被 2 到 (\sqrt{num}) 之间的数整除来判断其是否为素数。 回文数判断：通过反转数字并与原数字比较来判断其是否为回文数。 遍历和条件判断：遍历所有三位数并使用条件判断来筛选既是回文数又是素数的数。 以上代码和讲解展示了如何有效地找出所有既是回文数又是素数的三位数并按要求输出结果。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">信息奥赛一本通函数题库解析: 绝对素数</title>
      
      
      <link href="https://blog.talkincode.net/2024/07/02/olympiad-prime-numbers-analysis-4/" rel="alternate" type="text/html" title="信息奥赛一本通函数题库解析: 绝对素数" />
      
      <published>2024-07-02T17:16:39+00:00</published>
      <updated>2024-07-02T17:16:39+00:00</updated>
      <id>https://blog.talkincode.net/2024/07/02/olympiad-prime-numbers-analysis-4</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/07/02/olympiad-prime-numbers-analysis-4/">&lt;p&gt;原题链接: &lt;a href=&quot;http://ybt.ssoier.cn:8088/problem_show.php?pid=1153&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/jamiesun/images/master/default/p8ZvfS.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;解题思路&lt;/h2&gt;

&lt;p&gt;题目要求找出所有二位绝对素数。一个绝对素数是指它和它的数字对换后的数都是素数。比如 13 和 31 都是素数，所以 13 是绝对素数。&lt;/p&gt;

&lt;h3&gt;步骤&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;判断一个数是否为素数&lt;/strong&gt;：编写一个函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_prime&lt;/code&gt; 来判断一个数是否为素数。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;判断一个数是否为绝对素数&lt;/strong&gt;：编写一个函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_absolute_prime&lt;/code&gt; 来判断一个数和它的数字对换后的数是否都是素数。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;遍历所有两位数&lt;/strong&gt;：从 10 到 99 遍历每个数，检查它们是否为绝对素数，并输出结果。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;代码实现&lt;/h3&gt;

&lt;p&gt;以下是实现上述步骤的 C++ 代码：&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 函数：判断一个数是否为素数&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 1 及以下的数不是素数&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 如果找到因子，则不是素数&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 如果没有找到因子，则是素数&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 函数：检查两个数是否为绝对素数&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_absolute_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reversed_num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 对换数字位置&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reversed_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 判断原数和对换后的数是否都是素数&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 遍历所有两位数&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_absolute_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 输出绝对素数&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3&gt;代码讲解&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_prime&lt;/code&gt; 函数&lt;/strong&gt;：用于判断一个数是否为素数。若数小于或等于1，则返回 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;。否则，通过遍历从 2 到 (\sqrt{num}) 的所有整数，检查 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;num&lt;/code&gt; 是否能被整除。如果能被整除，则返回 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;；否则返回 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;。&lt;/p&gt;

    &lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_absolute_prime&lt;/code&gt; 函数&lt;/strong&gt;：用于判断一个数及其数字对换后的数是否都是素数。首先将数字对换位置，然后使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_prime&lt;/code&gt; 函数检查两个数是否为素数。&lt;/p&gt;

    &lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_absolute_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
     &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reversed_num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reversed_num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;主程序&lt;/strong&gt;：遍历所有两位数（10 到 99），对于每个数，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_absolute_prime&lt;/code&gt; 函数检查其是否为绝对素数。如果是，则输出该数。&lt;/p&gt;

    &lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_absolute_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
             &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
     &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;知识点总结&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;素数判断&lt;/strong&gt;：通过判断一个数是否能被 2 到 (\sqrt{num}) 之间的数整除来判断其是否为素数。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;数字对换&lt;/strong&gt;：通过取余和除法运算对换两位数的数字。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;遍历和条件判断&lt;/strong&gt;：遍历所有两位数并使用条件判断来筛选绝对素数。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;以上代码和讲解展示了如何有效地找出所有二位绝对素数并按要求输出结果。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="algorithms" />
      
        <category term="olympiad" />
      
        <category term="functions" />
      

      

      
        <summary type="html">原题链接: 解题思路 题目要求找出所有二位绝对素数。一个绝对素数是指它和它的数字对换后的数都是素数。比如 13 和 31 都是素数，所以 13 是绝对素数。 步骤 判断一个数是否为素数：编写一个函数 is_prime 来判断一个数是否为素数。 判断一个数是否为绝对素数：编写一个函数 is_absolute_prime 来判断一个数和它的数字对换后的数是否都是素数。 遍历所有两位数：从 10 到 99 遍历每个数，检查它们是否为绝对素数，并输出结果。 代码实现 以下是实现上述步骤的 C++ 代码： #include &amp;lt;iostream&amp;gt; #include &amp;lt;cmath&amp;gt; using namespace std; // 函数：判断一个数是否为素数 bool is_prime(int num) { if (num &amp;lt;= 1) return false; // 1 及以下的数不是素数 for (int i = 2; i &amp;lt;= sqrt(num); ++i) { if (num % i == 0) return false; // 如果找到因子，则不是素数 } return true; // 如果没有找到因子，则是素数 } // 函数：检查两个数是否为绝对素数 bool is_absolute_prime(int num) { int reversed_num = (num % 10) * 10 + (num / 10); // 对换数字位置 return is_prime(num) &amp;amp;&amp;amp; is_prime(reversed_num); // 判断原数和对换后的数是否都是素数 } int main() { // 遍历所有两位数 for (int i = 10; i &amp;lt;= 99; ++i) { if (is_absolute_prime(i)) { cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; endl; // 输出绝对素数 } } return 0; } 代码讲解 is_prime 函数：用于判断一个数是否为素数。若数小于或等于1，则返回 false。否则，通过遍历从 2 到 (\sqrt{num}) 的所有整数，检查 num 是否能被整除。如果能被整除，则返回 false；否则返回 true。 bool is_prime(int num) { if (num &amp;lt;= 1) return false; for (int i = 2; i &amp;lt;= sqrt(num); ++i) { if (num % i == 0) return false; } return true; } is_absolute_prime 函数：用于判断一个数及其数字对换后的数是否都是素数。首先将数字对换位置，然后使用 is_prime 函数检查两个数是否为素数。 bool is_absolute_prime(int num) { int reversed_num = (num % 10) * 10 + (num / 10); return is_prime(num) &amp;amp;&amp;amp; is_prime(reversed_num); } 主程序：遍历所有两位数（10 到 99），对于每个数，使用 is_absolute_prime 函数检查其是否为绝对素数。如果是，则输出该数。 int main() { for (int i = 10; i &amp;lt;= 99; ++i) { if (is_absolute_prime(i)) { cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; endl; } } return 0; } 知识点总结 素数判断：通过判断一个数是否能被 2 到 (\sqrt{num}) 之间的数整除来判断其是否为素数。 数字对换：通过取余和除法运算对换两位数的数字。 遍历和条件判断：遍历所有两位数并使用条件判断来筛选绝对素数。 以上代码和讲解展示了如何有效地找出所有二位绝对素数并按要求输出结果。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">信息奥赛一本通函数题库解析: 最大数max(x,y,z)</title>
      
      
      <link href="https://blog.talkincode.net/2024/07/02/Olympiad-function-problem-3/" rel="alternate" type="text/html" title="信息奥赛一本通函数题库解析: 最大数max(x,y,z) " />
      
      <published>2024-07-02T17:03:06+00:00</published>
      <updated>2024-07-02T17:03:06+00:00</updated>
      <id>https://blog.talkincode.net/2024/07/02/Olympiad-function-problem-3</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/07/02/Olympiad-function-problem-3/">&lt;p&gt;原题链接: &lt;a href=&quot;http://ybt.ssoier.cn:8088/problem_show.php?pid=1152&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/jamiesun/images/master/default/spmq21.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;解题思路&lt;/h2&gt;

&lt;p&gt;题目要求我们计算 ( m ) 的值，公式为：&lt;/p&gt;

&lt;p&gt;[ m = \frac{\max(a, b, c)}{\max(a+b, b, c) \times \max(a, b, b+c)} ]&lt;/p&gt;

&lt;p&gt;其中， ( a, b, c ) 为输入的三个数。我们需要定义求最大值的函数，并利用它来计算公式中的最大值。最后，输出结果并保留三位小数。&lt;/p&gt;

&lt;h3&gt;步骤&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;定义求最大值的函数&lt;/strong&gt;：为了简化代码并提高可读性，我们定义一个函数来求三个数中的最大值。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;输入处理&lt;/strong&gt;：读取用户输入的三个数 ( a, b, c )。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;计算 ( m ) 的值&lt;/strong&gt;：利用公式计算 ( m )。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;输出结果&lt;/strong&gt;：按照题目要求，输出保留三位小数的结果。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;代码实现&lt;/h3&gt;

&lt;p&gt;以下是实现上述步骤的 C++ 代码：&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iomanip&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 定义函数：求三个数中的最大值&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 输入a, b, c&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 计算 m&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 输出结果，保留三位小数&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fixed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setprecision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3&gt;代码讲解&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max&lt;/code&gt; 函数&lt;/strong&gt;：该函数使用标准库函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::max&lt;/code&gt; 来计算三个数中的最大值。我们首先计算 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;y&lt;/code&gt; 的最大值，然后再与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;z&lt;/code&gt; 进行比较，得到最终的最大值。&lt;/p&gt;

    &lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;输入处理&lt;/strong&gt;：读取用户输入的三个浮点数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a, b, c&lt;/code&gt;。&lt;/p&gt;

    &lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;cin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;计算 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt; 的值&lt;/strong&gt;：根据公式计算 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m&lt;/code&gt; 的值。&lt;/p&gt;

    &lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;输出结果&lt;/strong&gt;：使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixed&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setprecision(3)&lt;/code&gt; 控制输出格式，保留三位小数。&lt;/p&gt;

    &lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fixed&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setprecision&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;知识点总结&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;函数定义和调用&lt;/strong&gt;：通过定义 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max&lt;/code&gt; 函数，简化了代码并提高了可读性。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;标准库函数&lt;/strong&gt;：利用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::max&lt;/code&gt; 函数计算两个数的最大值。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;格式化输出&lt;/strong&gt;：使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixed&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setprecision&lt;/code&gt; 控制浮点数的输出格式。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;以上代码和讲解展示了如何高效地计算并输出保留三位小数的结果。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="algorithms" />
      
        <category term="olympiad" />
      
        <category term="functions" />
      

      

      
        <summary type="html">原题链接: 解题思路 题目要求我们计算 ( m ) 的值，公式为： [ m = \frac{\max(a, b, c)}{\max(a+b, b, c) \times \max(a, b, b+c)} ] 其中， ( a, b, c ) 为输入的三个数。我们需要定义求最大值的函数，并利用它来计算公式中的最大值。最后，输出结果并保留三位小数。 步骤 定义求最大值的函数：为了简化代码并提高可读性，我们定义一个函数来求三个数中的最大值。 输入处理：读取用户输入的三个数 ( a, b, c )。 计算 ( m ) 的值：利用公式计算 ( m )。 输出结果：按照题目要求，输出保留三位小数的结果。 代码实现 以下是实现上述步骤的 C++ 代码： #include &amp;lt;iostream&amp;gt; #include &amp;lt;iomanip&amp;gt; using namespace std; // 定义函数：求三个数中的最大值 double max(double x, double y, double z) { return std::max(std::max(x, y), z); } int main() { double a, b, c; cin &amp;gt;&amp;gt; a &amp;gt;&amp;gt; b &amp;gt;&amp;gt; c; // 输入a, b, c // 计算 m double m = max(a, b, c) / (max(a + b, b, c) * max(a, b, b + c)); // 输出结果，保留三位小数 cout &amp;lt;&amp;lt; fixed &amp;lt;&amp;lt; setprecision(3) &amp;lt;&amp;lt; m &amp;lt;&amp;lt; endl; return 0; } 代码讲解 max 函数：该函数使用标准库函数 std::max 来计算三个数中的最大值。我们首先计算 x 和 y 的最大值，然后再与 z 进行比较，得到最终的最大值。 double max(double x, double y, double z) { return std::max(std::max(x, y), z); } 输入处理：读取用户输入的三个浮点数 a, b, c。 double a, b, c; cin &amp;gt;&amp;gt; a &amp;gt;&amp;gt; b &amp;gt;&amp;gt; c; 计算 m 的值：根据公式计算 m 的值。 double m = max(a, b, c) / (max(a + b, b, c) * max(a, b, b + c)); 输出结果：使用 fixed 和 setprecision(3) 控制输出格式，保留三位小数。 cout &amp;lt;&amp;lt; fixed &amp;lt;&amp;lt; setprecision(3) &amp;lt;&amp;lt; m &amp;lt;&amp;lt; endl; 知识点总结 函数定义和调用：通过定义 max 函数，简化了代码并提高了可读性。 标准库函数：利用 std::max 函数计算两个数的最大值。 格式化输出：使用 fixed 和 setprecision 控制浮点数的输出格式。 以上代码和讲解展示了如何高效地计算并输出保留三位小数的结果。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">信息奥赛一本通函数题库解析: 素数个数</title>
      
      
      <link href="https://blog.talkincode.net/2024/07/02/function-question-analysis-2/" rel="alternate" type="text/html" title="信息奥赛一本通函数题库解析: 素数个数" />
      
      <published>2024-07-02T16:36:24+00:00</published>
      <updated>2024-07-02T16:36:24+00:00</updated>
      <id>https://blog.talkincode.net/2024/07/02/function-question-analysis-2</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/07/02/function-question-analysis-2/">&lt;p&gt;原题链接: &lt;a href=&quot;http://ybt.ssoier.cn:8088/problem_show.php?pid=1151&quot;&gt;素数个数&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/jamiesun/images/master/default/qzMvZi.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h2&gt;解题思路&lt;/h2&gt;

&lt;p&gt;这道题目要求我们计算从 2 到 n（其中 n 的最大值为 50000）之间的素数个数。素数是指除了 1 和自身以外不再有其他因数的自然数。解决这个问题我们可以使用 &lt;strong&gt;埃拉托色尼筛法（Sieve of Eratosthenes）&lt;/strong&gt;，这是一种高效的计算素数的算法。&lt;/p&gt;

&lt;h3&gt;埃拉托色尼筛法解释&lt;/h3&gt;

&lt;p&gt;埃拉托色尼筛法是一种古老的算法，用于寻找一个范围内的所有素数。其基本思想是从 2 开始，将每个素数的倍数标记为合数（即非素数）。具体步骤如下：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;初始化&lt;/strong&gt;：创建一个布尔数组 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_prime&lt;/code&gt;，大小为 n+1，并将所有元素初始化为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_prime[i]&lt;/code&gt; 表示数 i 是否为素数。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;标记合数&lt;/strong&gt;：从 2 开始，对于每个数 i，如果 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_prime[i]&lt;/code&gt; 为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;，则将 i 的所有倍数标记为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;计数素数&lt;/strong&gt;：遍历数组 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_prime&lt;/code&gt;，统计值为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; 的元素个数，这些元素对应的索引即为素数。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;算法的时间复杂度&lt;/h3&gt;

&lt;p&gt;埃拉托色尼筛法的时间复杂度为 (O(n \log \log n))，对于 n 最大值为 50000 的情况，效率是非常高的。&lt;/p&gt;

&lt;h3&gt;代码实现&lt;/h3&gt;

&lt;p&gt;下面是使用埃拉托色尼筛法计算从 2 到 n 范围内素数个数的代码：&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;algorithm&amp;gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt; // 引入算法库以使用 fill_n&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 函数：使用埃拉托色尼筛法计算素数的个数&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;count_primes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 如果 n 小于 2，则没有素数&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 创建布尔数组并初始化&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fill_n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 初始化数组为 true&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 0 和 1 不是素数&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 使用埃拉托色尼筛法&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 标记 i 的倍数为非素数&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 统计素数的个数&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_prime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 如果是素数，计数加一&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 返回素数的总个数&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 输入 n&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prime_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count_primes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 计算素数的个数&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prime_count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 输出素数的个数&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3&gt;代码解析&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;初始化布尔数组&lt;/strong&gt;：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool is_prime[n + 1];&lt;/code&gt; 创建一个大小为 n+1 的布尔数组，并使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fill_n(is_prime, n + 1, true);&lt;/code&gt; 初始化所有元素为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;特殊处理 0 和 1&lt;/strong&gt;：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_prime[0] = is_prime[1] = false;&lt;/code&gt; 将 0 和 1 标记为非素数。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;筛选素数&lt;/strong&gt;：使用两层循环，外层循环从 2 到 (\sqrt{n})，内层循环从 i(^2) 开始，将每个素数 i 的所有倍数标记为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;统计素数&lt;/strong&gt;：最后遍历数组 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is_prime&lt;/code&gt;，统计所有为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; 的元素个数。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这样就能高效地计算从 2 到 n 之间的素数个数并输出结果。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="algorithms" />
      
        <category term="olympiad" />
      
        <category term="functions" />
      

      

      
        <summary type="html">原题链接: 素数个数 解题思路 这道题目要求我们计算从 2 到 n（其中 n 的最大值为 50000）之间的素数个数。素数是指除了 1 和自身以外不再有其他因数的自然数。解决这个问题我们可以使用 埃拉托色尼筛法（Sieve of Eratosthenes），这是一种高效的计算素数的算法。 埃拉托色尼筛法解释 埃拉托色尼筛法是一种古老的算法，用于寻找一个范围内的所有素数。其基本思想是从 2 开始，将每个素数的倍数标记为合数（即非素数）。具体步骤如下： 初始化：创建一个布尔数组 is_prime，大小为 n+1，并将所有元素初始化为 true。is_prime[i] 表示数 i 是否为素数。 标记合数：从 2 开始，对于每个数 i，如果 is_prime[i] 为 true，则将 i 的所有倍数标记为 false。 计数素数：遍历数组 is_prime，统计值为 true 的元素个数，这些元素对应的索引即为素数。 算法的时间复杂度 埃拉托色尼筛法的时间复杂度为 (O(n \log \log n))，对于 n 最大值为 50000 的情况，效率是非常高的。 代码实现 下面是使用埃拉托色尼筛法计算从 2 到 n 范围内素数个数的代码： #include &amp;lt;iostream&amp;gt; #include &amp;lt;algorithm&amp;gt; // 引入算法库以使用 fill_n using namespace std; // 函数：使用埃拉托色尼筛法计算素数的个数 int count_primes(int n) { if (n &amp;lt; 2) return 0; // 如果 n 小于 2，则没有素数 // 创建布尔数组并初始化 bool is_prime[n + 1]; fill_n(is_prime, n + 1, true); // 初始化数组为 true is_prime[0] = is_prime[1] = false; // 0 和 1 不是素数 // 使用埃拉托色尼筛法 for (int i = 2; i * i &amp;lt;= n; ++i) { if (is_prime[i]) { for (int j = i * i; j &amp;lt;= n; j += i) { is_prime[j] = false; // 标记 i 的倍数为非素数 } } } // 统计素数的个数 int count = 0; for (int i = 2; i &amp;lt;= n; ++i) { if (is_prime[i]) { count++; // 如果是素数，计数加一 } } return count; // 返回素数的总个数 } int main() { int n; cin &amp;gt;&amp;gt; n; // 输入 n int prime_count = count_primes(n); // 计算素数的个数 cout &amp;lt;&amp;lt; prime_count &amp;lt;&amp;lt; endl; // 输出素数的个数 return 0; } 代码解析 初始化布尔数组：bool is_prime[n + 1]; 创建一个大小为 n+1 的布尔数组，并使用 fill_n(is_prime, n + 1, true); 初始化所有元素为 true。 特殊处理 0 和 1：is_prime[0] = is_prime[1] = false; 将 0 和 1 标记为非素数。 筛选素数：使用两层循环，外层循环从 2 到 (\sqrt{n})，内层循环从 i(^2) 开始，将每个素数 i 的所有倍数标记为 false。 统计素数：最后遍历数组 is_prime，统计所有为 true 的元素个数。 这样就能高效地计算从 2 到 n 之间的素数个数并输出结果。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">信息奥赛一本通函数题库解析: 求正整数2和n之间的完全数</title>
      
      
      <link href="https://blog.talkincode.net/2024/07/02/info-olympiad-function-questions-analysis/" rel="alternate" type="text/html" title="信息奥赛一本通函数题库解析: 求正整数2和n之间的完全数" />
      
      <published>2024-07-02T16:22:51+00:00</published>
      <updated>2024-07-02T16:22:51+00:00</updated>
      <id>https://blog.talkincode.net/2024/07/02/info-olympiad-function-questions-analysis</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/07/02/info-olympiad-function-questions-analysis/">&lt;p&gt;原题链接: &lt;a href=&quot;http://ybt.ssoier.cn:8088/problem_show.php?pid=1150&quot;&gt;求正整数2和n之间的完全数&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/jamiesun/images/master/default/iVjIKr.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;根据题目描述和样例输入输出的要求，我们需要编写一个程序，找到 2 和 n 之间的完全数，并按升序输出。一个完全数是指它的所有真因子（不包括自身）之和等于它本身。&lt;/p&gt;

&lt;p&gt;以下是针对这道题的详细解题思路：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;理解完全数的定义&lt;/strong&gt;：完全数是一个正整数，它等于其所有真因子（包括 1，但不包括自身）的和。例如，6 是一个完全数，因为 6 = 1 + 2 + 3。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;输入输出&lt;/strong&gt;：输入一个整数 n (n &amp;lt;= 5000)，输出 2 到 n 之间的所有完全数，每行一个数，按从小到大的顺序排列。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;解决方案&lt;/strong&gt;：&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;首先，我们需要一个函数来判断一个数是否为完全数。&lt;/li&gt;
      &lt;li&gt;然后，我们遍历从 2 到 n 的所有整数，使用该函数判断是否为完全数。&lt;/li&gt;
      &lt;li&gt;如果是完全数，将其存储在一个列表中。&lt;/li&gt;
      &lt;li&gt;最后，按顺序输出列表中的所有完全数。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;以下是实现该方案的代码：&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 函数：判断一个数是否为完全数&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_perfect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 1 不是完全数&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 1 是所有数的因子&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 避免重复添加平方根&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 如果因子和等于自身，则是完全数&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 读入 n&lt;/span&gt;

    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perfect_numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 假设最多有 5 个完全数&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 完全数的计数&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_perfect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;perfect_numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 如果 i 是完全数，加入数组&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;perfect_numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 输出所有的完全数&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3&gt;知识点总结：&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;因数分解&lt;/strong&gt;：为了求一个数的所有真因子，我们需要遍历从 1 到这个数平方根之间的所有整数。如果某个整数是这个数的因子，那么它的对应因子也可以求出。例如，12 的因子包括 1, 2, 3, 4, 6 和 12，我们只需遍历到 sqrt(12) 即可。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;数据存储和排序&lt;/strong&gt;：使用数组或列表来存储找到的完全数，并按顺序输出。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;复杂度分析&lt;/strong&gt;：由于我们需要遍历从 2 到 n 的所有数，并对每个数进行因数分解，时间复杂度为 O(n * sqrt(n))，对于 n &amp;lt;= 5000 是可以接受的。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这段代码可以有效解决这个问题，找出所有满足条件的完全数并输出。&lt;/p&gt;

&lt;h3&gt;为什么 只需遍历到 sqrt(12) 即可&lt;/h3&gt;

&lt;p&gt;只需遍历到 (\sqrt{n}) 是因为在查找一个数 (n) 的因子时，如果 (i) 是 (n) 的一个因子，那么 (\frac{n}{i}) 也是 (n) 的一个因子。具体来说，如果我们找到一个因子 (i)，那么我们可以直接确定另一个因子 (\frac{n}{i})。&lt;/p&gt;

&lt;p&gt;例如，对于 (n = 12)：&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;因子对包括 (1, 12), (2, 6), 和 (3, 4)。&lt;/li&gt;
  &lt;li&gt;如果我们从 1 遍历到 (\sqrt{12} \approx 3.46)，那么当我们找到因子 2 时，我们也可以确定 6 是因子（因为 (12 / 2 = 6)）。&lt;/li&gt;
  &lt;li&gt;同样，当我们找到因子 3 时，我们也可以确定 4 是因子（因为 (12 / 3 = 4)）。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这就意味着，我们只需遍历到 (\sqrt{n}) 就可以找到所有的因子对，因为对于每一个 (i \leq \sqrt{n})，对应的 (\frac{n}{i}) 都会被找到。&lt;/p&gt;

&lt;p&gt;这个方法大大减少了需要检查的数的数量，降低了时间复杂度。遍历到 (\sqrt{n}) 的时间复杂度是 (O(\sqrt{n}))，而不是遍历到 (n) 的 (O(n))，这对于较大的 (n) 来说是非常有效的。&lt;/p&gt;

&lt;p&gt;让我们再来看一遍代码中的这部分：&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 避免重复添加平方根&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;sum&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i * i &amp;lt;= num&lt;/code&gt; 就是为了遍历到 (\sqrt{num})。如果 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; 是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;num&lt;/code&gt; 的因子，我们将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;num / i&lt;/code&gt; 都加到因子和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum&lt;/code&gt; 中。&lt;/p&gt;

&lt;p&gt;避免重复添加平方根的目的是处理完全平方数的情况。例如，16 的因子包括 1, 2, 4, 8 和 16，但我们不希望将 4 添加两次。&lt;/p&gt;

&lt;p&gt;通过这种方法，我们能够高效地找到所有因子并判断一个数是否为完全数。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="algorithms" />
      
        <category term="olympiad" />
      
        <category term="functions" />
      

      

      
        <summary type="html">原题链接: 求正整数2和n之间的完全数 根据题目描述和样例输入输出的要求，我们需要编写一个程序，找到 2 和 n 之间的完全数，并按升序输出。一个完全数是指它的所有真因子（不包括自身）之和等于它本身。 以下是针对这道题的详细解题思路： 理解完全数的定义：完全数是一个正整数，它等于其所有真因子（包括 1，但不包括自身）的和。例如，6 是一个完全数，因为 6 = 1 + 2 + 3。 输入输出：输入一个整数 n (n &amp;lt;= 5000)，输出 2 到 n 之间的所有完全数，每行一个数，按从小到大的顺序排列。 解决方案： 首先，我们需要一个函数来判断一个数是否为完全数。 然后，我们遍历从 2 到 n 的所有整数，使用该函数判断是否为完全数。 如果是完全数，将其存储在一个列表中。 最后，按顺序输出列表中的所有完全数。 以下是实现该方案的代码： #include &amp;lt;iostream&amp;gt; using namespace std; // 函数：判断一个数是否为完全数 bool is_perfect(int num) { if (num == 1) { return false; // 1 不是完全数 } int sum = 1; // 1 是所有数的因子 for (int i = 2; i * i &amp;lt;= num; ++i) { if (num % i == 0) { sum += i; if (i * i != num) { // 避免重复添加平方根 sum += num / i; } } } return sum == num; // 如果因子和等于自身，则是完全数 } int main() { int n; cin &amp;gt;&amp;gt; n; // 读入 n int perfect_numbers[5]; // 假设最多有 5 个完全数 int count = 0; // 完全数的计数 for (int i = 2; i &amp;lt;= n &amp;amp;&amp;amp; count &amp;lt; 5; ++i) { if (is_perfect(i)) { perfect_numbers[count++] = i; // 如果 i 是完全数，加入数组 } } for (int i = 0; i &amp;lt; count; ++i) { cout &amp;lt;&amp;lt; perfect_numbers[i] &amp;lt;&amp;lt; endl; // 输出所有的完全数 } return 0; } 知识点总结： 因数分解：为了求一个数的所有真因子，我们需要遍历从 1 到这个数平方根之间的所有整数。如果某个整数是这个数的因子，那么它的对应因子也可以求出。例如，12 的因子包括 1, 2, 3, 4, 6 和 12，我们只需遍历到 sqrt(12) 即可。 数据存储和排序：使用数组或列表来存储找到的完全数，并按顺序输出。 复杂度分析：由于我们需要遍历从 2 到 n 的所有数，并对每个数进行因数分解，时间复杂度为 O(n * sqrt(n))，对于 n &amp;lt;= 5000 是可以接受的。 这段代码可以有效解决这个问题，找出所有满足条件的完全数并输出。 为什么 只需遍历到 sqrt(12) 即可 只需遍历到 (\sqrt{n}) 是因为在查找一个数 (n) 的因子时，如果 (i) 是 (n) 的一个因子，那么 (\frac{n}{i}) 也是 (n) 的一个因子。具体来说，如果我们找到一个因子 (i)，那么我们可以直接确定另一个因子 (\frac{n}{i})。 例如，对于 (n = 12)： 因子对包括 (1, 12), (2, 6), 和 (3, 4)。 如果我们从 1 遍历到 (\sqrt{12} \approx 3.46)，那么当我们找到因子 2 时，我们也可以确定 6 是因子（因为 (12 / 2 = 6)）。 同样，当我们找到因子 3 时，我们也可以确定 4 是因子（因为 (12 / 3 = 4)）。 这就意味着，我们只需遍历到 (\sqrt{n}) 就可以找到所有的因子对，因为对于每一个 (i \leq \sqrt{n})，对应的 (\frac{n}{i}) 都会被找到。 这个方法大大减少了需要检查的数的数量，降低了时间复杂度。遍历到 (\sqrt{n}) 的时间复杂度是 (O(\sqrt{n}))，而不是遍历到 (n) 的 (O(n))，这对于较大的 (n) 来说是非常有效的。 让我们再来看一遍代码中的这部分： for (int i = 2; i * i &amp;lt;= num; ++i) { if (num % i == 0) { sum += i; if (i * i != num) { // 避免重复添加平方根 sum += num / i; } } } 这里的 i * i &amp;lt;= num 就是为了遍历到 (\sqrt{num})。如果 i 是 num 的因子，我们将 i 和 num / i 都加到因子和 sum 中。 避免重复添加平方根的目的是处理完全平方数的情况。例如，16 的因子包括 1, 2, 4, 8 和 16，但我们不希望将 4 添加两次。 通过这种方法，我们能够高效地找到所有因子并判断一个数是否为完全数。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">深入解密MSGraph认证机制： DefaultAzureCredential 详解</title>
      
      
      <link href="https://blog.talkincode.net/2024/04/25/MSGraph-DefaultAzureCredential/" rel="alternate" type="text/html" title="深入解密MSGraph认证机制： DefaultAzureCredential 详解" />
      
      <published>2024-04-25T03:25:23+00:00</published>
      <updated>2024-04-25T03:25:23+00:00</updated>
      <id>https://blog.talkincode.net/2024/04/25/MSGraph-DefaultAzureCredential</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/04/25/MSGraph-DefaultAzureCredential/">&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DefaultAzureCredential&lt;/code&gt;是Azure Identity库中的一个核心组件，设计用来简化Azure服务的身份验证过程。它提供了一种透明和无缝的方法来获取访问令牌，支持在不同的环境（例如，开发环境、生产环境）中自动选择最合适的认证方式。&lt;/p&gt;

&lt;h3&gt;主要特点&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;灵活性和易用性&lt;/strong&gt;：自动尝试多种认证方法，无需手动切换或配置多个认证方式。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;支持多种环境&lt;/strong&gt;：无论是本地开发环境、CI/CD管道还是Azure云环境，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DefaultAzureCredential&lt;/code&gt;都能根据当前环境选择合适的认证方式。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;扩展性&lt;/strong&gt;：支持环境变量、托管身份、Azure CLI、Visual Studio Code、Azure PowerShell等身份。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;认证流程&lt;/h2&gt;

&lt;p&gt;当请求访问令牌时，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DefaultAzureCredential&lt;/code&gt;将依次尝试以下认证方式，直到成功获取令牌：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;环境变量&lt;/strong&gt;：通过设置环境变量提供的服务主体。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Azure 托管身份&lt;/strong&gt;：利用Azure虚拟机或Azure服务实例的托管身份进行认证。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Azure CLI&lt;/strong&gt;：使用Azure CLI登录的身份。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Azure PowerShell&lt;/strong&gt;：使用Azure PowerShell登陆的身份。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Visual Studio Code&lt;/strong&gt;：使用VS Code Azure账户插件登陆的身份。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Azure 开发者命令行接口&lt;/strong&gt;：使用Azure Developer CLI登录的身份。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;交互式浏览器认证&lt;/strong&gt;：通过弹出的浏览器窗口进行交互式登录。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;关键参数和配置选项&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DefaultAzureCredential&lt;/code&gt;提供了多个参数和配置选项，使开发者能够根据具体需求调整认证行为，例如：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;authority&lt;/strong&gt;：指定一个Microsoft Entra认证终端的授权机构。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;exclude_XXX_credential&lt;/strong&gt;：排除特定的认证方式，例如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exclude_cli_credential&lt;/code&gt;用来排除Azure CLI认证方式。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;使用示例&lt;/h3&gt;

&lt;p&gt;以下Python代码演示了如何使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DefaultAzureCredential&lt;/code&gt;获取访问令牌：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;azure.identity&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DefaultAzureCredential&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;azure.mgmt.resource&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SubscriptionClient&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 创建 DefaultAzureCredential 实例
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;credential&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DefaultAzureCredential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 使用 credential 实例访问 Azure 资源
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subscription_client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SubscriptionClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;credential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 枚举订阅
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subscription&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subscription_client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subscriptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subscription&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subscription_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;此代码利用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DefaultAzureCredential&lt;/code&gt;自动选择适合当前环境的认证方式，创建服务客户端实例，并列出所有Azure订阅。&lt;/p&gt;

&lt;h2&gt;结论&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DefaultAzureCredential&lt;/code&gt;是一个强大的工具，为开发者提供了一种简单、灵活并且可在不同环境中无缝切换的认证方法。通过透明地处理身份验证细节，它使得开发者可以将更多精力集中在实现业务功能上，而不是处理身份验证的复杂性。&lt;/p&gt;

&lt;p&gt;了解并实施&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DefaultAzureCredential&lt;/code&gt;，对于希望在其应用程序中安全高效地使用Microsoft Graph API和其他Azure服务的开发者来说，非常重要。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="azure" />
      
        <category term="MSGraph" />
      
        <category term="authentication" />
      

      

      
        <summary type="html">DefaultAzureCredential是Azure Identity库中的一个核心组件，设计用来简化Azure服务的身份验证过程。它提供了一种透明和无缝的方法来获取访问令牌，支持在不同的环境（例如，开发环境、生产环境）中自动选择最合适的认证方式。 主要特点 灵活性和易用性：自动尝试多种认证方法，无需手动切换或配置多个认证方式。 支持多种环境：无论是本地开发环境、CI/CD管道还是Azure云环境，DefaultAzureCredential都能根据当前环境选择合适的认证方式。 扩展性：支持环境变量、托管身份、Azure CLI、Visual Studio Code、Azure PowerShell等身份。 认证流程 当请求访问令牌时，DefaultAzureCredential将依次尝试以下认证方式，直到成功获取令牌： 环境变量：通过设置环境变量提供的服务主体。 Azure 托管身份：利用Azure虚拟机或Azure服务实例的托管身份进行认证。 Azure CLI：使用Azure CLI登录的身份。 Azure PowerShell：使用Azure PowerShell登陆的身份。 Visual Studio Code：使用VS Code Azure账户插件登陆的身份。 Azure 开发者命令行接口：使用Azure Developer CLI登录的身份。 交互式浏览器认证：通过弹出的浏览器窗口进行交互式登录。 关键参数和配置选项 DefaultAzureCredential提供了多个参数和配置选项，使开发者能够根据具体需求调整认证行为，例如： authority：指定一个Microsoft Entra认证终端的授权机构。 exclude_XXX_credential：排除特定的认证方式，例如exclude_cli_credential用来排除Azure CLI认证方式。 使用示例 以下Python代码演示了如何使用DefaultAzureCredential获取访问令牌： from azure.identity import DefaultAzureCredential from azure.mgmt.resource import SubscriptionClient # 创建 DefaultAzureCredential 实例 credential = DefaultAzureCredential() # 使用 credential 实例访问 Azure 资源 subscription_client = SubscriptionClient(credential) # 枚举订阅 for subscription in subscription_client.subscriptions.list(): print(subscription.subscription_id) 此代码利用DefaultAzureCredential自动选择适合当前环境的认证方式，创建服务客户端实例，并列出所有Azure订阅。 结论 DefaultAzureCredential是一个强大的工具，为开发者提供了一种简单、灵活并且可在不同环境中无缝切换的认证方法。通过透明地处理身份验证细节，它使得开发者可以将更多精力集中在实现业务功能上，而不是处理身份验证的复杂性。 了解并实施DefaultAzureCredential，对于希望在其应用程序中安全高效地使用Microsoft Graph API和其他Azure服务的开发者来说，非常重要。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">深入解密MSGraph认证机制： CertificateCredential 详解</title>
      
      
      <link href="https://blog.talkincode.net/2024/04/25/MSGraph-CertificateCredential/" rel="alternate" type="text/html" title="深入解密MSGraph认证机制： CertificateCredential 详解" />
      
      <published>2024-04-25T03:25:23+00:00</published>
      <updated>2024-04-25T03:25:23+00:00</updated>
      <id>https://blog.talkincode.net/2024/04/25/MSGraph-CertificateCredential</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/04/25/MSGraph-CertificateCredential/">&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CertificateCredential&lt;/code&gt;是一种用于Azure身份验证的方法，它使用X.509证书代替传统的用户名和密码，来验证服务主体(Service Principal)的身份。这种方法提供了更高的安全性，因为它消除了密码泄露的风险，并且易于管理，特别是在自动化部署和多服务环境中。&lt;/p&gt;

&lt;h2&gt;关键特性与优势&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;增强的安全性&lt;/strong&gt;：使用证书作为凭证避免了密码泄露的危险，同时确保了交互的安全性。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;自动化友好&lt;/strong&gt;：适合自动化工具和DevOps实践，简化了认证过程。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;广泛的适用性&lt;/strong&gt;：可以与Azure AD一起用于多种Microsoft服务的认证。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;简化的管理&lt;/strong&gt;：通过中央认证管理，简化了服务主体的验证过程。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;实现步骤和考虑事项&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;创建证书&lt;/strong&gt;：首先需要生成或获取一个X.509证书。证书可以是自签名的，也可以由权威证书颁发机构(CA)签发。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;注册应用程序和证书&lt;/strong&gt;：在Azure Active Directory中注册应用程序，并上传证书。证书的公钥将用于验证来自应用程序的身份请求。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;配置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CertificateCredential&lt;/code&gt;&lt;/strong&gt;：使用Azure SDK（例如Azure SDK for Python）时，需要配置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CertificateCredential&lt;/code&gt;以使用注册的证书。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;发送认证请求&lt;/strong&gt;：应用程序在发送请求访问Microsoft Graph资源时，将包括使用证书私钥签名的JWT（Json Web Token）。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;技术实现&lt;/h2&gt;

&lt;p&gt;以下展示了如何使用Python SDK创建&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CertificateCredential&lt;/code&gt;实例：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;azure.identity&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CertificateCredential&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 证书路径和应用（客户端）ID
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tenant_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;Azure租户ID&amp;gt;&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;client_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;Azure客户端应用程序ID&amp;gt;&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;certificate_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;证书文件路径&amp;gt;&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 创建证书凭证实例
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;credential&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CertificateCredential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tenant_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tenant_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;client_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;certificate_path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;certificate_path&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：实现时一定要注意保护私钥的安全，避免私钥泄露。&lt;/p&gt;

&lt;h2&gt;错误处理和调试&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;确保证书已正确上传至Azure Active Directory，并与对应的应用程序注册信息匹配。&lt;/li&gt;
  &lt;li&gt;确认应用程序的权限和API调用是否符合策略要求。&lt;/li&gt;
  &lt;li&gt;使用Azure的日志和监视工具来跟踪认证过程中出现的问题。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;总结&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CertificateCredential&lt;/code&gt;提供了一种安全、可靠、便于管理的方法来处理Azure服务的认证。通过使用证书，开发者可以在自动化部署和服务间通信中，确保应用程序的高安全性和效率。理解并正确实现&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CertificateCredential&lt;/code&gt;，对于构建现代云应用至关重要。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="azure" />
      
        <category term="MSGraph" />
      
        <category term="authentication" />
      

      

      
        <summary type="html">CertificateCredential是一种用于Azure身份验证的方法，它使用X.509证书代替传统的用户名和密码，来验证服务主体(Service Principal)的身份。这种方法提供了更高的安全性，因为它消除了密码泄露的风险，并且易于管理，特别是在自动化部署和多服务环境中。 关键特性与优势 增强的安全性：使用证书作为凭证避免了密码泄露的危险，同时确保了交互的安全性。 自动化友好：适合自动化工具和DevOps实践，简化了认证过程。 广泛的适用性：可以与Azure AD一起用于多种Microsoft服务的认证。 简化的管理：通过中央认证管理，简化了服务主体的验证过程。 实现步骤和考虑事项 创建证书：首先需要生成或获取一个X.509证书。证书可以是自签名的，也可以由权威证书颁发机构(CA)签发。 注册应用程序和证书：在Azure Active Directory中注册应用程序，并上传证书。证书的公钥将用于验证来自应用程序的身份请求。 配置CertificateCredential：使用Azure SDK（例如Azure SDK for Python）时，需要配置CertificateCredential以使用注册的证书。 发送认证请求：应用程序在发送请求访问Microsoft Graph资源时，将包括使用证书私钥签名的JWT（Json Web Token）。 技术实现 以下展示了如何使用Python SDK创建CertificateCredential实例： from azure.identity import CertificateCredential # 证书路径和应用（客户端）ID tenant_id = &quot;&amp;lt;Azure租户ID&amp;gt;&quot; client_id = &quot;&amp;lt;Azure客户端应用程序ID&amp;gt;&quot; certificate_path = &quot;&amp;lt;证书文件路径&amp;gt;&quot; # 创建证书凭证实例 credential = CertificateCredential( tenant_id=tenant_id, client_id=client_id, certificate_path=certificate_path ) 注意：实现时一定要注意保护私钥的安全，避免私钥泄露。 错误处理和调试 确保证书已正确上传至Azure Active Directory，并与对应的应用程序注册信息匹配。 确认应用程序的权限和API调用是否符合策略要求。 使用Azure的日志和监视工具来跟踪认证过程中出现的问题。 总结 CertificateCredential提供了一种安全、可靠、便于管理的方法来处理Azure服务的认证。通过使用证书，开发者可以在自动化部署和服务间通信中，确保应用程序的高安全性和效率。理解并正确实现CertificateCredential，对于构建现代云应用至关重要。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">深入解密MSGraph认证机制： AzureDeveloperCliCredential 详解</title>
      
      
      <link href="https://blog.talkincode.net/2024/04/25/MSGraph-AzureDeveloperCliCredential/" rel="alternate" type="text/html" title="深入解密MSGraph认证机制： AzureDeveloperCliCredential 详解" />
      
      <published>2024-04-25T03:25:23+00:00</published>
      <updated>2024-04-25T03:25:23+00:00</updated>
      <id>https://blog.talkincode.net/2024/04/25/MSGraph-AzureDeveloperCliCredential</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/04/25/MSGraph-AzureDeveloperCliCredential/">&lt;p&gt;本文旨在深入解析 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt; 认证机制，这是一种专为开发者在本地开发环境中设计的认证方式，让我们一探究竟。&lt;/p&gt;

&lt;h2&gt;什么是 AzureDeveloperCliCredential？&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt; 是 Azure 标识库（Azure Identity library）中的一个类，它提供了一种便捷的认证方法，允许开发者在本地开发环境中使用 Azure Developer CLI 工具进行认证。这种认证机制主要面向的是使用 Microsoft Entra 进行身份管理和访问控制的应用程序开发场景。&lt;/p&gt;

&lt;p&gt;借助于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt;，开发者无需在代码中硬编码任何敏感信息，如客户端 ID、秘钥或访问令牌等，大大降低了管理凭证时的安全风险。&lt;/p&gt;

&lt;h2&gt;如何工作？&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt; 的工作流程相对直接，主要包括以下几个步骤：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;开发者首先需要在本地环境中安装和配置 Azure Developer CLI（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azd&lt;/code&gt;）工具，并通过它进行登录。&lt;/li&gt;
  &lt;li&gt;在成功登录后，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azd&lt;/code&gt;能够获取并管理访问令牌。&lt;/li&gt;
  &lt;li&gt;当 Azure SDK 需要访问 Azure 服务时，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt; 会与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azd&lt;/code&gt; 交互，请求一个访问令牌。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azd&lt;/code&gt; 返回一个有效的访问令牌给 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt;，该令牌随后被用于对 Azure 服务的 API 调用。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这一过程免去了开发者在应用程序代码中直接处理和存储凭证的需要，为开发者提供了更加安全便捷的身份认证方式。&lt;/p&gt;

&lt;h2&gt;关键特点&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;安全性&lt;/strong&gt;：避免在应用程序代码中硬编码敏感信息，减少潜在的安全风险。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;便捷性&lt;/strong&gt;：开发者仅需通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azd&lt;/code&gt; 登陆一次，便可在本地开发环境中自如访问 Azure 资源。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;灵活性&lt;/strong&gt;：支持多租户认证，开发者可以指定一个或多个租户 ID，增加了使用的灵活性。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;示例：创建和使用 AzureDeveloperCliCredential&lt;/h2&gt;

&lt;p&gt;以下是如何创建一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt;对象并使用它获取 Azure 服务访问令牌的示例代码片段：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;azure.identity&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AzureDeveloperCliCredential&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 创建AzureDeveloperCliCredential实例
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;credential&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AzureDeveloperCliCredential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 使用该凭证请求访问令牌
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;credential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://management.azure.com/.default&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;获取的访问令牌：&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在这个简单的例子中，我们首先导入并创建了一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt;的实例。随后，我们调用了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get_token&lt;/code&gt;方法来获取针对 Azure 管理 API 的访问令牌。这简化了访问 Azure 资源的认证过程，使开发者能够专注于业务逻辑的实现。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;注意你可能会得到如下错误提示 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential.get_token failed: Azure Developer CLI could not be found. Please visit https://aka.ms/azure-dev for installation instructions and then,once installed, authenticate to your Azure account using &apos;azd auth login&apos;.&lt;/code&gt;, 这是提醒你需要安装 azd 命令行工具并通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;azd auth login&lt;/code&gt; 登录&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;azd 工具安装&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;windows: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;winget install microsoft.azd&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;macos: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew tap azure/azd &amp;amp;&amp;amp; brew install azd&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;linux: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -fsSL https://aka.ms/install-azd.sh | bash&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;总结&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt; 为 Azure 资源的开发和管理提供了一种简便且安全的认证方式，特别适合在本地开发环境中使用。通过将身份认证过程外包给 Azure Developer CLI，它有效减少了代码中管理敏感信息的需要，提高了开发效率同时保障了安全性。无论是新手开发者还是经验丰富的 Azure 专家，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt; 都是一个值得了解和利用的强大工具。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="azure" />
      
        <category term="MSGraph" />
      
        <category term="authentication" />
      

      

      
        <summary type="html">本文旨在深入解析 AzureDeveloperCliCredential 认证机制，这是一种专为开发者在本地开发环境中设计的认证方式，让我们一探究竟。 什么是 AzureDeveloperCliCredential？ AzureDeveloperCliCredential 是 Azure 标识库（Azure Identity library）中的一个类，它提供了一种便捷的认证方法，允许开发者在本地开发环境中使用 Azure Developer CLI 工具进行认证。这种认证机制主要面向的是使用 Microsoft Entra 进行身份管理和访问控制的应用程序开发场景。 借助于 AzureDeveloperCliCredential，开发者无需在代码中硬编码任何敏感信息，如客户端 ID、秘钥或访问令牌等，大大降低了管理凭证时的安全风险。 如何工作？ AzureDeveloperCliCredential 的工作流程相对直接，主要包括以下几个步骤： 开发者首先需要在本地环境中安装和配置 Azure Developer CLI（azd）工具，并通过它进行登录。 在成功登录后，azd能够获取并管理访问令牌。 当 Azure SDK 需要访问 Azure 服务时，AzureDeveloperCliCredential 会与 azd 交互，请求一个访问令牌。 azd 返回一个有效的访问令牌给 AzureDeveloperCliCredential，该令牌随后被用于对 Azure 服务的 API 调用。 这一过程免去了开发者在应用程序代码中直接处理和存储凭证的需要，为开发者提供了更加安全便捷的身份认证方式。 关键特点 安全性：避免在应用程序代码中硬编码敏感信息，减少潜在的安全风险。 便捷性：开发者仅需通过 azd 登陆一次，便可在本地开发环境中自如访问 Azure 资源。 灵活性：支持多租户认证，开发者可以指定一个或多个租户 ID，增加了使用的灵活性。 示例：创建和使用 AzureDeveloperCliCredential 以下是如何创建一个AzureDeveloperCliCredential对象并使用它获取 Azure 服务访问令牌的示例代码片段： from azure.identity import AzureDeveloperCliCredential # 创建AzureDeveloperCliCredential实例 credential = AzureDeveloperCliCredential() # 使用该凭证请求访问令牌 token = credential.get_token(&quot;https://management.azure.com/.default&quot;) print(&quot;获取的访问令牌：&quot;, token.token) 在这个简单的例子中，我们首先导入并创建了一个AzureDeveloperCliCredential的实例。随后，我们调用了get_token方法来获取针对 Azure 管理 API 的访问令牌。这简化了访问 Azure 资源的认证过程，使开发者能够专注于业务逻辑的实现。 注意你可能会得到如下错误提示 AzureDeveloperCliCredential.get_token failed: Azure Developer CLI could not be found. Please visit https://aka.ms/azure-dev for installation instructions and then,once installed, authenticate to your Azure account using &apos;azd auth login&apos;., 这是提醒你需要安装 azd 命令行工具并通过 azd auth login 登录 azd 工具安装 windows: winget install microsoft.azd macos: brew tap azure/azd &amp;amp;&amp;amp; brew install azd linux: curl -fsSL https://aka.ms/install-azd.sh | bash 总结 AzureDeveloperCliCredential 为 Azure 资源的开发和管理提供了一种简便且安全的认证方式，特别适合在本地开发环境中使用。通过将身份认证过程外包给 Azure Developer CLI，它有效减少了代码中管理敏感信息的需要，提高了开发效率同时保障了安全性。无论是新手开发者还是经验丰富的 Azure 专家，AzureDeveloperCliCredential 都是一个值得了解和利用的强大工具。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">深入解密MSGraph认证机制： AzureCliCredential 详解</title>
      
      
      <link href="https://blog.talkincode.net/2024/04/25/MSGraph-AzureCliCredential/" rel="alternate" type="text/html" title="深入解密MSGraph认证机制： AzureCliCredential 详解" />
      
      <published>2024-04-25T03:25:23+00:00</published>
      <updated>2024-04-25T03:25:23+00:00</updated>
      <id>https://blog.talkincode.net/2024/04/25/MSGraph-AzureCliCredential</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/04/25/MSGraph-AzureCliCredential/">&lt;p&gt;AzureCliCredential是一个便利的认证方式，它允许开发者通过已登录的Azure CLI（Command Line Interface）身份来请求访问令牌，进而访问Microsoft Graph等Azure服务。这意味着，你可以在通过Azure CLI登录Azure之后，无需进行额外的登录步骤，即可在代码中安全地访问Azure资源。&lt;/p&gt;

&lt;h2&gt;AzureCliCredential的工作原理&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;通过执行Azure CLI命令&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;az account get-access-token&lt;/code&gt;来获得访问令牌。它利用CLI的当前登录会话信息来请求令牌，因此，在使用之前必须确保已通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;az login&lt;/code&gt;命令登录Azure CLI。以下是其工作流程的简要描述：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;开发者登录Azure CLI&lt;/strong&gt;：通过执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;az login&lt;/code&gt;命令并完成认证，开发者的Azure账户信息和访问权限将被CLI记录。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;初始化AzureCliCredential实例&lt;/strong&gt;：在应用程序中，通过创建&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;的实例来准备进行认证操作。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;请求访问令牌&lt;/strong&gt;：当你的应用程序需要访问Microsoft Graph或其他Azure服务时，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;会自动通过调用Azure CLI获取访问令牌。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;访问资源&lt;/strong&gt;：应用程序使用步骤3中获得的访问令牌来进行身份验证，并安全地访问所需的Azure资源。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;如何使用AzureCliCredential&lt;/h2&gt;

&lt;p&gt;使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;相对简单直观。首先，确保你已安装Azure CLI并且已通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;az login&lt;/code&gt;登录。接下来，在你的Python代码中，你需要做的只是创建一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;的实例，并通过这个实例获取访问令牌。&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;azure.identity&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AzureCliCredential&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msgraph&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GraphServiceClient&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 创建 AzureCliCredential 实例
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;credential&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AzureCliCredential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 创建 GraphClient 实例
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GraphServiceClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;credential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 使用 client 获取 Microsoft Graph 的数据
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;me&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 输出获取的用户信息
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;注意事项&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;之前，必须确保已通过Azure CLI登录。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;适用于开发和测试环境，因为它依赖于本地CLI登录状态。在生产环境中，考虑使用更适合自动化场景的认证方式，例如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientSecretCredential&lt;/code&gt;或&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CertificateCredential&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;了解&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;支持的参数（如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tenant_id&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;process_timeout&lt;/code&gt;）可以帮助你更加灵活地控制其行为。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;AzureCliCredential 与 AzureDeveloperCliCredential 的比较&lt;/h2&gt;

&lt;p&gt;在探讨&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;时，了解它与&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt;的区别是一个重要方面，这有助于开发者根据自己的场景选择最合适的认证方式。下面是对两者特性的比较以及各自的最佳使用场景。&lt;/p&gt;

&lt;h3&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;定义和用途&lt;/strong&gt;：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;允许开发者通过已登录的Azure CLI来请求访问令牌。它是一个基于Azure CLI身份认证状态的认证方法。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;工作方式&lt;/strong&gt;：利用当前通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;az login&lt;/code&gt;命令登录的Azure CLI会话，自动获得访问令牌。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;：最适合于开发和测试环境，特别是在个人开发阶段或当开发者想要使用自己的账户权限来进行API调用时。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;优点&lt;/strong&gt;：简化了认证流程，开发者不需要在应用程序中额外配置或管理密钥。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;局限性&lt;/strong&gt;：主要依赖于Azure CLI的登录状态，因此不适合生产环境或自动化工作流程。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt;&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;定义和用途&lt;/strong&gt;：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt;是一种更加灵活的认证方式，它尝试使用多种开发环境中可用的身份验证方法，包括环境变量、Visual Studio Code的Azure插件登录身份、Azure CLI登录身份等。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;工作方式&lt;/strong&gt;：通过依次尝试不同的认证方式来获取访问令牌，直到某一种方法成功为止。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;使用场景&lt;/strong&gt;：适用于需要在多种开发环境中灵活切换或者在开发团队中共享代码的情景。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;优点&lt;/strong&gt;：为开发者提供了更多的灵活性和方便性，不需要针对每个开发环境单独配置认证方式。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;局限性&lt;/strong&gt;：虽然提供了灵活性，但在自动化部署或生产环境中可能仍需考虑更稳定的认证方式，如使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientSecretCredential&lt;/code&gt;或&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CertificateCredential&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;最佳使用场景&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;对于独立开发者或小团队，正在开发阶段，希望快速验证Azure服务集成，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;是一个快速入门的选择。&lt;/li&gt;
  &lt;li&gt;如果项目涉及多种开发环境或需要在团队成员间共享，而且希望最小化配置工作，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt;提供了更广泛的匹配范围和灵活性。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在选择认证方式时，了解不同认证方式的特性和适用场景至关重要。对于开发和测试环境，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureDeveloperCliCredential&lt;/code&gt;都提供了方便的认证方式，但是在准备转向生产环境时，建议评估其他更适合自动化和安全要求的认证方式。正确选择认证机制是确保应用安全和高效运行的重要步骤之一。&lt;/p&gt;

&lt;h2&gt;总结&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;提供了一种快捷且安全的方式，通过利用Azure CLI的登录状态来请求和使用访问令牌，极大地简化了开发者访问Azure资源的过程。理解并正确应用这种认证方式，对于开发基于Azure服务的应用程序至关重要。&lt;/p&gt;

&lt;p&gt;通过结合其他Azure SDK for Python的工具和服务，你可以构建强大且安全的云应用程序，全面掌控你的Azure资源。不论你是正在探索Azure服务，还是已经在构建基于云的解决方案，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AzureCliCredential&lt;/code&gt;都是认证选项中的一个重要组成部分。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="azure" />
      
        <category term="MSGraph" />
      
        <category term="authentication" />
      

      

      
        <summary type="html">AzureCliCredential是一个便利的认证方式，它允许开发者通过已登录的Azure CLI（Command Line Interface）身份来请求访问令牌，进而访问Microsoft Graph等Azure服务。这意味着，你可以在通过Azure CLI登录Azure之后，无需进行额外的登录步骤，即可在代码中安全地访问Azure资源。 AzureCliCredential的工作原理 AzureCliCredential通过执行Azure CLI命令az account get-access-token来获得访问令牌。它利用CLI的当前登录会话信息来请求令牌，因此，在使用之前必须确保已通过az login命令登录Azure CLI。以下是其工作流程的简要描述： 开发者登录Azure CLI：通过执行az login命令并完成认证，开发者的Azure账户信息和访问权限将被CLI记录。 初始化AzureCliCredential实例：在应用程序中，通过创建AzureCliCredential的实例来准备进行认证操作。 请求访问令牌：当你的应用程序需要访问Microsoft Graph或其他Azure服务时，AzureCliCredential会自动通过调用Azure CLI获取访问令牌。 访问资源：应用程序使用步骤3中获得的访问令牌来进行身份验证，并安全地访问所需的Azure资源。 如何使用AzureCliCredential 使用AzureCliCredential相对简单直观。首先，确保你已安装Azure CLI并且已通过az login登录。接下来，在你的Python代码中，你需要做的只是创建一个AzureCliCredential的实例，并通过这个实例获取访问令牌。 from azure.identity import AzureCliCredential from msgraph import GraphServiceClient # 创建 AzureCliCredential 实例 credential = AzureCliCredential() # 创建 GraphClient 实例 client = GraphServiceClient(credential) # 使用 client 获取 Microsoft Graph 的数据 result = client.users.get(&quot;me&quot;) print(result) # 输出获取的用户信息 注意事项 使用AzureCliCredential之前，必须确保已通过Azure CLI登录。 AzureCliCredential适用于开发和测试环境，因为它依赖于本地CLI登录状态。在生产环境中，考虑使用更适合自动化场景的认证方式，例如ClientSecretCredential或CertificateCredential。 了解AzureCliCredential支持的参数（如tenant_id和process_timeout）可以帮助你更加灵活地控制其行为。 AzureCliCredential 与 AzureDeveloperCliCredential 的比较 在探讨AzureCliCredential时，了解它与AzureDeveloperCliCredential的区别是一个重要方面，这有助于开发者根据自己的场景选择最合适的认证方式。下面是对两者特性的比较以及各自的最佳使用场景。 AzureCliCredential 定义和用途：AzureCliCredential允许开发者通过已登录的Azure CLI来请求访问令牌。它是一个基于Azure CLI身份认证状态的认证方法。 工作方式：利用当前通过az login命令登录的Azure CLI会话，自动获得访问令牌。 使用场景：最适合于开发和测试环境，特别是在个人开发阶段或当开发者想要使用自己的账户权限来进行API调用时。 优点：简化了认证流程，开发者不需要在应用程序中额外配置或管理密钥。 局限性：主要依赖于Azure CLI的登录状态，因此不适合生产环境或自动化工作流程。 AzureDeveloperCliCredential 定义和用途：AzureDeveloperCliCredential是一种更加灵活的认证方式，它尝试使用多种开发环境中可用的身份验证方法，包括环境变量、Visual Studio Code的Azure插件登录身份、Azure CLI登录身份等。 工作方式：通过依次尝试不同的认证方式来获取访问令牌，直到某一种方法成功为止。 使用场景：适用于需要在多种开发环境中灵活切换或者在开发团队中共享代码的情景。 优点：为开发者提供了更多的灵活性和方便性，不需要针对每个开发环境单独配置认证方式。 局限性：虽然提供了灵活性，但在自动化部署或生产环境中可能仍需考虑更稳定的认证方式，如使用ClientSecretCredential或CertificateCredential。 最佳使用场景 对于独立开发者或小团队，正在开发阶段，希望快速验证Azure服务集成，AzureCliCredential是一个快速入门的选择。 如果项目涉及多种开发环境或需要在团队成员间共享，而且希望最小化配置工作，AzureDeveloperCliCredential提供了更广泛的匹配范围和灵活性。 在选择认证方式时，了解不同认证方式的特性和适用场景至关重要。对于开发和测试环境，AzureCliCredential和AzureDeveloperCliCredential都提供了方便的认证方式，但是在准备转向生产环境时，建议评估其他更适合自动化和安全要求的认证方式。正确选择认证机制是确保应用安全和高效运行的重要步骤之一。 总结 AzureCliCredential提供了一种快捷且安全的方式，通过利用Azure CLI的登录状态来请求和使用访问令牌，极大地简化了开发者访问Azure资源的过程。理解并正确应用这种认证方式，对于开发基于Azure服务的应用程序至关重要。 通过结合其他Azure SDK for Python的工具和服务，你可以构建强大且安全的云应用程序，全面掌控你的Azure资源。不论你是正在探索Azure服务，还是已经在构建基于云的解决方案，AzureCliCredential都是认证选项中的一个重要组成部分。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">深入解密MSGraph认证机制： AuthorizationCodeCredential 详解</title>
      
      
      <link href="https://blog.talkincode.net/2024/04/25/MSGraph-AuthorizationCodeCredential/" rel="alternate" type="text/html" title="深入解密MSGraph认证机制： AuthorizationCodeCredential 详解" />
      
      <published>2024-04-25T03:13:43+00:00</published>
      <updated>2024-04-25T03:13:43+00:00</updated>
      <id>https://blog.talkincode.net/2024/04/25/MSGraph-AuthorizationCodeCredential</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/04/25/MSGraph-AuthorizationCodeCredential/">&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AuthorizationCodeCredential&lt;/code&gt; 是Azure SDK for Python中用于通过Microsoft Entra ID的授权码流程（Authorization Code Flow）进行身份验证的一种凭证方式。这种凭证方式主要应用于需要直接与用户交互来获取授权的应用程序中，例如Web应用或Web API。让我们深入了解它的工作原理、如何实现以及它的关键参数。&lt;/p&gt;

&lt;h2&gt;工作原理&lt;/h2&gt;

&lt;p&gt;在OAuth 2.0授权码流程中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AuthorizationCodeCredential&lt;/code&gt;执行以下主要步骤：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;用户登录和授权&lt;/strong&gt;：用户首先登录Microsoft认证系统，并授予客户端应用程序访问其资源的权限。此时，客户端应用将获得一个授权码。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;使用授权码获取访问令牌&lt;/strong&gt;：客户端应用使用步骤1中获得的授权码，向Microsoft的认证服务器请求访问令牌。请求必须包括应用程序的客户端ID、客户端密钥（对于Web应用或API）、重定向URI和所需的授权范围（scopes）。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;访问资源&lt;/strong&gt;：客户端应用使用获取到的访问令牌请求Microsoft Graph或其他API，来访问或操作用户数据。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;关键参数&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;tenant_id&lt;/strong&gt;：应用程序的Microsoft Entra租户ID，也称为目录ID。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;client_id&lt;/strong&gt;：应用程序的客户端ID。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;authorization_code&lt;/strong&gt;：用户登录并授权后获得的授权码。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;redirect_uri&lt;/strong&gt;：应用程序的重定向URI，必须与请求授权码时使用的URI匹配。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;client_secret&lt;/strong&gt;（可选）：应用的客户端密钥，Web应用和Web API需要此参数。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;authorization_code 获取流程&lt;/h2&gt;

&lt;p&gt;authorization_code获取：获取&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authorization_code&lt;/code&gt;是OAuth 2.0授权码流程中的关键步骤。该过程主要涉及用户、客户端应用程序和认证服务器之间的交互。以下是详细的操作流程：&lt;/p&gt;

&lt;h3&gt;1. 引导用户到登录页面&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;客户端应用程序首先构造一个用户登录的URL，该URL将指向认证服务器（例如，Microsoft Entra的登录页面），并包括以下重要参数：
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;response_type&lt;/strong&gt;：该参数的值应设置为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;code&lt;/code&gt;，表示客户端请求一个授权码。&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;client_id&lt;/strong&gt;：应用程序在Azure AD中注册时获取的客户端ID。&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;redirect_uri&lt;/strong&gt;：认证服务器在授权后将用户重定向到的客户端应用指定的URI。这个URI需要预先在Azure AD中注册。&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;scope&lt;/strong&gt;：客户端应用请求访问的权限范围，例如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;user.read&lt;/code&gt;。&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;state&lt;/strong&gt;（可选）：一个客户端状态值，认证服务器将在重定向回客户端时原样返回。这可用于防止跨站请求伪造（CSRF）攻击。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;完整的URL大致格式如下：&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  https://login.microsoftonline.com/&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;tenant_id&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;/oauth2/v2.0/authorize?
  &lt;span class=&quot;nv&quot;&gt;client_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;={&lt;/span&gt;client_id&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&amp;amp;
  &lt;span class=&quot;nv&quot;&gt;response_type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;code&amp;amp;
  &lt;span class=&quot;nv&quot;&gt;redirect_uri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;={&lt;/span&gt;redirect_uri&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&amp;amp;
  &lt;span class=&quot;nv&quot;&gt;scope&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;={&lt;/span&gt;scope&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&amp;amp;
  &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;={&lt;/span&gt;state&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;2. 用户登录和授权&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;用户被重定向到构造好的URL指向的登录页面，在那里用户需要输入自己的凭据来登录。&lt;/li&gt;
  &lt;li&gt;登录后，认证服务器会展示一个授权页面，要求用户确认是否同意授予客户端应用所请求的权限。&lt;/li&gt;
  &lt;li&gt;用户同意授权后，认证服务器将用户重定向回客户端应用预先注册的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;redirect_uri&lt;/code&gt;，同时在返回的URL中包含一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authorization_code&lt;/code&gt;参数。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;3. 捕获授权码&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;应用程序需要监听重定向URI的响应，从中截取包含的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authorization_code&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;授权码作为URL参数返回，形如：&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;redirect_uri&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;?code&lt;span class=&quot;o&quot;&gt;={&lt;/span&gt;authorization_code&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&amp;amp;state&lt;span class=&quot;o&quot;&gt;={&lt;/span&gt;state&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;应用程序从这个URI中提取&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authorization_code&lt;/code&gt;值准备下一步的操作。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;4. 示例：如何通过构造URL引导用户&lt;/h3&gt;

&lt;p&gt;以下是客户端应用程序可能使用的简化示例代码，用于生成并引导用户到登录页面的URL：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# 定义参数
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tenant_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;你的租户ID&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;client_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;你的客户端ID&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;redirect_uri&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;你的重定向URI&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https%3A%2F%2Fgraph.microsoft.com%2F.default&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;12345&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 随机生成的一个字符串，用于保护免受CSRF攻击
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 构造URL
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auth_url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://login.microsoftonline.com/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tenant_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/oauth2/v2.0/authorize?client_id=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;client_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;amp;response_type=code&amp;amp;redirect_uri=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;redirect_uri&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;amp;scope=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;amp;state=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 引导用户到这个URL进行登录和授权
&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;请访问以下URL进行登录和授权：&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;auth_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;获取授权码仅是整个OAuth 2.0授权码流程的一部分，客户端应用需要在接下来的步骤中使用这个授权码向认证服务器请求访问令牌，才能最终访问保护资源。&lt;/p&gt;

&lt;h3&gt;最终使用示例&lt;/h3&gt;

&lt;p&gt;以下代码展示了如何创建一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AuthorizationCodeCredential&lt;/code&gt;实例：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;azure.identity&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AuthorizationCodeCredential&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;credential&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AuthorizationCodeCredential&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tenant_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;你的租户ID&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;client_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;你的客户端ID&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;authorization_code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;用户授权后获得的授权码&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;redirect_uri&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;你的重定向URI&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;client_secret&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;你的客户端密钥&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 对于Web应用或Web API
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3&gt;错误处理&lt;/h3&gt;

&lt;p&gt;在尝试获取访问令牌的过程中，若认证失败，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AuthorizationCodeCredential&lt;/code&gt;将抛出&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientAuthenticationError&lt;/code&gt;异常。异常信息将提供认证失败的具体原因，开发者需要根据异常信息进行相应的错误处理。&lt;/p&gt;

&lt;h2&gt;总结&lt;/h2&gt;

&lt;p&gt;通过使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AuthorizationCodeCredential&lt;/code&gt;，开发者可以在需要用户直接交互授权的应用程序中，实现标准的OAuth 2.0授权码流程，安全地访问用户数据。了解并正确实现该凭证方式，对于开发安全、可靠的应用程序至关重要。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="MSGraph" />
      
        <category term="认证机制" />
      

      

      
        <summary type="html">AuthorizationCodeCredential 是Azure SDK for Python中用于通过Microsoft Entra ID的授权码流程（Authorization Code Flow）进行身份验证的一种凭证方式。这种凭证方式主要应用于需要直接与用户交互来获取授权的应用程序中，例如Web应用或Web API。让我们深入了解它的工作原理、如何实现以及它的关键参数。 工作原理 在OAuth 2.0授权码流程中，AuthorizationCodeCredential执行以下主要步骤： 用户登录和授权：用户首先登录Microsoft认证系统，并授予客户端应用程序访问其资源的权限。此时，客户端应用将获得一个授权码。 使用授权码获取访问令牌：客户端应用使用步骤1中获得的授权码，向Microsoft的认证服务器请求访问令牌。请求必须包括应用程序的客户端ID、客户端密钥（对于Web应用或API）、重定向URI和所需的授权范围（scopes）。 访问资源：客户端应用使用获取到的访问令牌请求Microsoft Graph或其他API，来访问或操作用户数据。 关键参数 tenant_id：应用程序的Microsoft Entra租户ID，也称为目录ID。 client_id：应用程序的客户端ID。 authorization_code：用户登录并授权后获得的授权码。 redirect_uri：应用程序的重定向URI，必须与请求授权码时使用的URI匹配。 client_secret（可选）：应用的客户端密钥，Web应用和Web API需要此参数。 authorization_code 获取流程 authorization_code获取：获取authorization_code是OAuth 2.0授权码流程中的关键步骤。该过程主要涉及用户、客户端应用程序和认证服务器之间的交互。以下是详细的操作流程： 1. 引导用户到登录页面 客户端应用程序首先构造一个用户登录的URL，该URL将指向认证服务器（例如，Microsoft Entra的登录页面），并包括以下重要参数： response_type：该参数的值应设置为code，表示客户端请求一个授权码。 client_id：应用程序在Azure AD中注册时获取的客户端ID。 redirect_uri：认证服务器在授权后将用户重定向到的客户端应用指定的URI。这个URI需要预先在Azure AD中注册。 scope：客户端应用请求访问的权限范围，例如user.read。 state（可选）：一个客户端状态值，认证服务器将在重定向回客户端时原样返回。这可用于防止跨站请求伪造（CSRF）攻击。 完整的URL大致格式如下： https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize? client_id={client_id}&amp;amp; response_type=code&amp;amp; redirect_uri={redirect_uri}&amp;amp; scope={scope}&amp;amp; state={state} 2. 用户登录和授权 用户被重定向到构造好的URL指向的登录页面，在那里用户需要输入自己的凭据来登录。 登录后，认证服务器会展示一个授权页面，要求用户确认是否同意授予客户端应用所请求的权限。 用户同意授权后，认证服务器将用户重定向回客户端应用预先注册的redirect_uri，同时在返回的URL中包含一个authorization_code参数。 3. 捕获授权码 应用程序需要监听重定向URI的响应，从中截取包含的authorization_code。 授权码作为URL参数返回，形如： {redirect_uri}?code={authorization_code}&amp;amp;state={state} 应用程序从这个URI中提取authorization_code值准备下一步的操作。 4. 示例：如何通过构造URL引导用户 以下是客户端应用程序可能使用的简化示例代码，用于生成并引导用户到登录页面的URL： # 定义参数 tenant_id = &quot;你的租户ID&quot; client_id = &quot;你的客户端ID&quot; redirect_uri = &quot;你的重定向URI&quot; scope = &quot;https%3A%2F%2Fgraph.microsoft.com%2F.default&quot; state = &quot;12345&quot; # 随机生成的一个字符串，用于保护免受CSRF攻击 # 构造URL auth_url = f&quot;https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize?client_id={client_id}&amp;amp;response_type=code&amp;amp;redirect_uri={redirect_uri}&amp;amp;scope={scope}&amp;amp;state={state}&quot; # 引导用户到这个URL进行登录和授权 print(&quot;请访问以下URL进行登录和授权：&quot;, auth_url) 获取授权码仅是整个OAuth 2.0授权码流程的一部分，客户端应用需要在接下来的步骤中使用这个授权码向认证服务器请求访问令牌，才能最终访问保护资源。 最终使用示例 以下代码展示了如何创建一个AuthorizationCodeCredential实例： from azure.identity import AuthorizationCodeCredential credential = AuthorizationCodeCredential( tenant_id=&quot;你的租户ID&quot;, client_id=&quot;你的客户端ID&quot;, authorization_code=&quot;用户授权后获得的授权码&quot;, redirect_uri=&quot;你的重定向URI&quot;, client_secret=&quot;你的客户端密钥&quot; # 对于Web应用或Web API ) 错误处理 在尝试获取访问令牌的过程中，若认证失败，AuthorizationCodeCredential将抛出ClientAuthenticationError异常。异常信息将提供认证失败的具体原因，开发者需要根据异常信息进行相应的错误处理。 总结 通过使用AuthorizationCodeCredential，开发者可以在需要用户直接交互授权的应用程序中，实现标准的OAuth 2.0授权码流程，安全地访问用户数据。了解并正确实现该凭证方式，对于开发安全、可靠的应用程序至关重要。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">深入解密MSGraph认证机制</title>
      
      
      <link href="https://blog.talkincode.net/2024/04/25/MSGraph-Authentication-Detailed-Guide/" rel="alternate" type="text/html" title="深入解密MSGraph认证机制" />
      
      <published>2024-04-25T02:57:25+00:00</published>
      <updated>2024-04-25T02:57:25+00:00</updated>
      <id>https://blog.talkincode.net/2024/04/25/MSGraph-Authentication-Detailed-Guide</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/04/25/MSGraph-Authentication-Detailed-Guide/">&lt;p&gt;Microsoft Graph（MSGraph）是微软提供的一个强大的API接口，允许开发者访问和操作Microsoft Cloud服务（包括Microsoft 365、Windows 10、Enterprise Mobility + Security 等）中的数据和情报。为了确保数据的安全性和访问的合法性，MSGraph采用了一套复杂的认证机制。这项认证机制的核心是基于OAuth 2.0协议，它是一种广泛采用的开放标准，用于安全地进行授权。&lt;/p&gt;

&lt;p&gt;在MSGraph中，认证过程主要涉及三个角色：资源所有者（如用户）、客户端应用程序（希望访问资源的应用）、以及认证服务器（负责验证身份并提供访问令牌的服务器）。简单来说，客户端应用程序需向认证服务器请求并获得访问令牌，这个访问令牌随后将用于向MSGraph API发起请求，从而获取或操作Microsoft Cloud服务中的数据。&lt;/p&gt;

&lt;p&gt;为了获取访问令牌，客户端首先需要在Azure AD（Azure Active Directory）中注册，这一过程涉及到指定所需权限、配置重定向URL等步骤。注册完成后，客户端将获得一个应用程序ID和一个或多个秘钥，这些是后续认证过程中的重要元素。根据应用程序的类型（比如公共客户端或机密客户端）和使用场景，认证流程会有所不同，例如有代表用户认证的授权码流程、仅用于后台服务的客户端凭据流程等。&lt;/p&gt;

&lt;p&gt;MSGraph的认证机制通过提供一套标准化、安全的认证流程，确保只有被授权的应用程序可以访问微软云服务中的数据，从而保护用户数据和企业资产的安全。&lt;/p&gt;

&lt;h2&gt;资源链接&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;/2024/04/25/MSGraph-AuthorizationCodeCredential/&quot;&gt;AuthorizationCodeCredential 详解&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2024/04/25/MSGraph-AzureDeveloperCliCredential/&quot;&gt;AzureDeveloperCliCredential 详解&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2024/04/25/MSGraph-AzureCliCredential/&quot;&gt;AzureCliCredential 详解&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2024/04/25/MSGraph-CertificateCredential/&quot;&gt;CertificateCredential 详解&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;/2024/04/25/MSGraph-DefaultAzureCredential/&quot;&gt;DefaultAzureCredential 详解&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      

      
        <category term="msgraph" />
      
        <category term="认证" />
      
        <category term="security" />
      

      

      
        <summary type="html">Microsoft Graph（MSGraph）是微软提供的一个强大的API接口，允许开发者访问和操作Microsoft Cloud服务（包括Microsoft 365、Windows 10、Enterprise Mobility + Security 等）中的数据和情报。为了确保数据的安全性和访问的合法性，MSGraph采用了一套复杂的认证机制。这项认证机制的核心是基于OAuth 2.0协议，它是一种广泛采用的开放标准，用于安全地进行授权。 在MSGraph中，认证过程主要涉及三个角色：资源所有者（如用户）、客户端应用程序（希望访问资源的应用）、以及认证服务器（负责验证身份并提供访问令牌的服务器）。简单来说，客户端应用程序需向认证服务器请求并获得访问令牌，这个访问令牌随后将用于向MSGraph API发起请求，从而获取或操作Microsoft Cloud服务中的数据。 为了获取访问令牌，客户端首先需要在Azure AD（Azure Active Directory）中注册，这一过程涉及到指定所需权限、配置重定向URL等步骤。注册完成后，客户端将获得一个应用程序ID和一个或多个秘钥，这些是后续认证过程中的重要元素。根据应用程序的类型（比如公共客户端或机密客户端）和使用场景，认证流程会有所不同，例如有代表用户认证的授权码流程、仅用于后台服务的客户端凭据流程等。 MSGraph的认证机制通过提供一套标准化、安全的认证流程，确保只有被授权的应用程序可以访问微软云服务中的数据，从而保护用户数据和企业资产的安全。 资源链接 AuthorizationCodeCredential 详解 AzureDeveloperCliCredential 详解 AzureCliCredential 详解 CertificateCredential 详解 DefaultAzureCredential 详解</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">C++命名空间: 代码治理的良方</title>
      
      
      <link href="https://blog.talkincode.net/2024/03/21/Cpp-Namespace-Demystified/" rel="alternate" type="text/html" title="C++命名空间: 代码治理的良方" />
      
      <published>2024-03-21T07:24:55+00:00</published>
      <updated>2024-03-21T07:24:55+00:00</updated>
      <id>https://blog.talkincode.net/2024/03/21/Cpp-Namespace-Demystified</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/03/21/Cpp-Namespace-Demystified/">&lt;p&gt;代码开发中使用命名空间（namespaces）是为了防止命名冲突，并且对程序中的实体进行适当的组织。它有点像我们现实生活中的邮政系统。设想一个没有邮编和地区名称的世界。如果只告诉邮差“送到张三家”，而没有更具体的地址，可以想象会发生多少混乱和错误投递。邮编和地区名称的作用就像编程中的命名空间一样，它们帮助我们准确无误地把邮件送到正确的目的地。&lt;/p&gt;

&lt;p&gt;在C++中，命名空间允许我们定义一组属于特定领域的标识符，比如变量名、函数、结构等，从而避免了不同代码库中相同名称的冲突。就像在现实世界里，两个完全不相关的城市可以有同一个街道名，但由于它们位于不同的地区，这并不会引起混淆。&lt;/p&gt;

&lt;p&gt;例如，两个不同的软件公司可能都开发了名为“Logger”的工具，如果没有命名空间，一旦这两个库在同一个项目中被使用，编译器就会混淆这两个“Logger”。但是，如果每个公司分别将自己的“Logger”置于独有的命名空间中，比如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;companyA::Logger&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;companyB::Logger&lt;/code&gt;，那么使用起来就不会有冲突。&lt;/p&gt;

&lt;p&gt;C++的命名空间不仅帮助区分同名的标识符，而且也支持代码的可维护性和可读性。命名空间可以嵌套，就像地区可以有子区域一样，这进一步地增加了组织性。使用命名空间还可以避免名称过长导致的麻烦，因为我们可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt;声明，类似于我们对地址的简称，只要在当前上下文中没有歧义，我们可以省略了长地址的部分。&lt;/p&gt;

&lt;p&gt;因此，命名空间在C++中的使用可以被视为代码管理的一种高效机制，它确保了相同或相似名称的实体可以和平共存，就像现实世界中详尽的地址系统能够确保每封邮件都能送达到正确的收件人一样。&lt;/p&gt;

&lt;h2&gt;std 命名空间&lt;/h2&gt;

&lt;p&gt;在C++中，最为人熟知的内置命名空间莫过于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;是Standard Library的缩写，意为“标准库”。C++ Standard Library是一个功能强大的功能集合，它包含了各种各样的常用功能和类型，如输入/输出（I/O）、字符串处理、数值计算、数据容器、算法等。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;命名空间中包含的实体被C++标准所规范，因此它们在不同的C++环境和编译器中具有一致的行为和接口。这种一致性对于开发者来说至关重要，因为它确保了代码的可移植性和可重用性。&lt;/p&gt;

&lt;p&gt;使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;命名空间中的实体，一种方式是通过完全限定名来访问，也就是在实体前面加上&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::&lt;/code&gt;。比如，想使用标准库中的一个非常常见的容器vector，你需要写出&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::vector&lt;/code&gt;。同样，使用输入输出流时，你会使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::cout&lt;/code&gt;来输出到标准输出。&lt;/p&gt;

&lt;p&gt;如果不想每次都写出完全限定名，可以在代码中加入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt;声明。例如：&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样，在这个文件或者作用域中，你可以直接使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cout&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;endl&lt;/code&gt;而不需要前缀&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::&lt;/code&gt;。或者使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using namespace std;&lt;/code&gt;可以将整个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;命名空间的实体都引入当前的作用域。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然而，过度使用上述声明会增加命名冲突的风险，特别是在大型项目中，可能会不经意间覆盖命名空间中的名称。&lt;/p&gt;

&lt;p&gt;以下是一些&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;命名空间中常见的组件示例：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::string&lt;/code&gt;: 动态大小的字符串类。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::vector&lt;/code&gt;: 动态大小的数组。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::map&lt;/code&gt; &amp;amp; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::unordered_map&lt;/code&gt;: 关联容器，提供键值对的存储。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::set&lt;/code&gt;: 集合，保证元素的唯一性。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::istream&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::ostream&lt;/code&gt;: 输入输出流的基本类型，如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::cin&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::cout&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::thread&lt;/code&gt;: 用于管理线程的类。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::unique_ptr&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::shared_ptr&lt;/code&gt;: 智能指针，用于更容易地管理动态分配的内存。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;冲突与冲突解决&lt;/h2&gt;

&lt;p&gt;当使用两个或者更多具有相同名字的实体时，即发生了命名冲突。这对于编译器来说是不明确的，因为它不知道程序员打算使用哪个。这在以下两种情况中尤为常见：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;从不同的库引入相同的名字。&lt;/li&gt;
  &lt;li&gt;在项目的不同部分对同名实体赋予了不同的定义。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;为了解决这类冲突，C++提供了几种机制：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;使用完整命名空间&lt;/strong&gt;：即使用命名空间的名称前缀来指定需要的确切实体，如前文的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;companyA::Logger&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;companyB::Logger&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt;指令&lt;/strong&gt;：如果一个命名空间中的几个或所有名字在某个文件中会频繁被用到，可以用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt;指令将这个命名空间引入当前文件或作用域。然而, 如果引入了包含相同名称的多个命名空间，反而可能造成冲突。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;namespace&lt;/code&gt;别名&lt;/strong&gt;: 可以给长的或不方便的命名空间名字设置一个较短的别名。例如，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;namespace fs = std::filesystem;&lt;/code&gt;允许我们用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fs&lt;/code&gt;代替较长的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::filesystem&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;避免&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using namespace std&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;许多初学者喜欢使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using namespace std;&lt;/code&gt;来避免每次调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;命名空间中的标识符时需要额外键入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::&lt;/code&gt;。然而，在更复杂或更大的项目中，过度使用这个声明可能会导致问题。这是因为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std&lt;/code&gt;命名空间包含了数千个函数和类，将会污染全局命名空间，增加了不同库之间发生命名冲突的风险。&lt;/p&gt;

&lt;h2&gt;命名空间的最佳实践&lt;/h2&gt;

&lt;p&gt;为了保持代码的清晰和可维护性，以下是一些命名空间的最佳实践建议：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;有意识地使用命名空间&lt;/strong&gt;: 只在需要时引入命名空间，避免使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using namespace std;&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;避免无名（匿名）命名空间的频繁使用&lt;/strong&gt;: 这些命名空间在单个文件中是独一无二的，但是在大型项目中使用过多会使得代码难以追踪。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;适当设计自己的命名空间&lt;/strong&gt;: 根据功能、模块或者库的逻辑关系组织代码，并为它们创建合理的命名空间。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;使用内联命名空间&lt;/strong&gt;: 对于需要保持API兼容性的版本控制，它允许特定版本的实现被默认选用，而不需要改变使用者的代码。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;当我们在C++项目中使用命名空间来解决命名冲突和组织代码时，一个典型的例子是库的集成。&lt;/p&gt;

&lt;p&gt;假设你正在开发一个游戏引擎，而这个引擎用到了两个不同的图形处理库：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GraphicsLibA&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GraphicsLibB&lt;/code&gt;。这两个库都提供了一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Renderer&lt;/code&gt;类来处理图形渲染。如果没有命名空间，编译器将不知道你提到的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Renderer&lt;/code&gt;是来自哪个库的，从而引发命名冲突。&lt;/p&gt;

&lt;p&gt;这个问题可以通过使用命名空间优雅地解决：&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GraphicsLibA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Renderer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// GraphicsLibA的渲染实现&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GraphicsLibB&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Renderer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;public:&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// GraphicsLibB的渲染实现&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;现在，两个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Renderer&lt;/code&gt;类分别位于它们自己的命名空间中。当你需要使用特定的库时，你可以通过命名空间来指定你想要使用的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Renderer&lt;/code&gt;类:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;GraphicsLibA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Renderer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rendererA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rendererA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 调用GraphicsLibA中的render方法&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;GraphicsLibB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Renderer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rendererB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;rendererB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 调用GraphicsLibB中的render方法&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果你确定只会使用其中一个库的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Renderer&lt;/code&gt;，可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt;声明来简化代码:&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GraphicsLibA&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Renderer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;renderer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 这会调用GraphicsLibA中的Renderer的render方法&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;但是，如果同时使用了两个库的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Renderer&lt;/code&gt;，那么最好不要使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt;声明，以免造成歧义。&lt;/p&gt;

&lt;p&gt;命名空间不仅解决了命名冲突的问题，还可以用来划分逻辑上相关的代码组，提高项目的模块化和可读性。例如，在游戏引擎中，除了图形处理，你可能还要处理音频和物理模拟，可以为这些功能定义不同的命名空间：&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Audio&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SoundSystem&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// 音频处理相关的代码&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Physics&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PhysicsEngine&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// 物理模拟相关的代码&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;使用命名空间的最佳实践是一种避免混淆并加强代码结构的方法，它保证了当项目规模不断扩大时，代码依然能够清晰、可管理。&lt;/p&gt;

&lt;p&gt;理解命名空间的用途与最佳实践，能够帮助开发者更加高效地组织和维护他们的C++代码库，从而减少错误并增强代码的重用性。&lt;/p&gt;

&lt;h2&gt;扩展思考&lt;/h2&gt;

&lt;p&gt;关于C++命名空间的使用价值和最佳实践，以下问题可以引导您深入思考：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;命名空间在C++中的设计初衷是什么？&lt;/li&gt;
  &lt;li&gt;如何在一个大型项目中合理使用命名空间来组织代码？&lt;/li&gt;
  &lt;li&gt;在使用多个库时，命名空间如何帮助解决命名冲突？&lt;/li&gt;
  &lt;li&gt;命名空间可以嵌套使用吗？嵌套命名空间有哪些潜在的优点和缺点？&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt;声明和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt;指令的使用在什么情况下是合适的？&lt;/li&gt;
  &lt;li&gt;不当使用命名空间可能会带来哪些问题？如何避免？&lt;/li&gt;
  &lt;li&gt;如何结合匿名命名空间来管理仅在一个文件中使用的代码？&lt;/li&gt;
  &lt;li&gt;命名空间应该如何与类和模板等其他语言特性协同工作？&lt;/li&gt;
  &lt;li&gt;C++17中引入的内联命名空间具有哪些特殊的用途？&lt;/li&gt;
  &lt;li&gt;如何通过合理使用命名空间提高代码的可读性和可维护性？&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      

      
        <category term="cpp" />
      
        <category term="namespace" />
      

      

      
        <summary type="html">代码开发中使用命名空间（namespaces）是为了防止命名冲突，并且对程序中的实体进行适当的组织。它有点像我们现实生活中的邮政系统。设想一个没有邮编和地区名称的世界。如果只告诉邮差“送到张三家”，而没有更具体的地址，可以想象会发生多少混乱和错误投递。邮编和地区名称的作用就像编程中的命名空间一样，它们帮助我们准确无误地把邮件送到正确的目的地。 在C++中，命名空间允许我们定义一组属于特定领域的标识符，比如变量名、函数、结构等，从而避免了不同代码库中相同名称的冲突。就像在现实世界里，两个完全不相关的城市可以有同一个街道名，但由于它们位于不同的地区，这并不会引起混淆。 例如，两个不同的软件公司可能都开发了名为“Logger”的工具，如果没有命名空间，一旦这两个库在同一个项目中被使用，编译器就会混淆这两个“Logger”。但是，如果每个公司分别将自己的“Logger”置于独有的命名空间中，比如companyA::Logger和companyB::Logger，那么使用起来就不会有冲突。 C++的命名空间不仅帮助区分同名的标识符，而且也支持代码的可维护性和可读性。命名空间可以嵌套，就像地区可以有子区域一样，这进一步地增加了组织性。使用命名空间还可以避免名称过长导致的麻烦，因为我们可以使用using声明，类似于我们对地址的简称，只要在当前上下文中没有歧义，我们可以省略了长地址的部分。 因此，命名空间在C++中的使用可以被视为代码管理的一种高效机制，它确保了相同或相似名称的实体可以和平共存，就像现实世界中详尽的地址系统能够确保每封邮件都能送达到正确的收件人一样。 std 命名空间 在C++中，最为人熟知的内置命名空间莫过于std。std是Standard Library的缩写，意为“标准库”。C++ Standard Library是一个功能强大的功能集合，它包含了各种各样的常用功能和类型，如输入/输出（I/O）、字符串处理、数值计算、数据容器、算法等。 std命名空间中包含的实体被C++标准所规范，因此它们在不同的C++环境和编译器中具有一致的行为和接口。这种一致性对于开发者来说至关重要，因为它确保了代码的可移植性和可重用性。 使用std命名空间中的实体，一种方式是通过完全限定名来访问，也就是在实体前面加上std::。比如，想使用标准库中的一个非常常见的容器vector，你需要写出std::vector。同样，使用输入输出流时，你会使用std::cout来输出到标准输出。 如果不想每次都写出完全限定名，可以在代码中加入using声明。例如： using std::cout; using std::endl; 这样，在这个文件或者作用域中，你可以直接使用cout和endl而不需要前缀std::。或者使用using namespace std;可以将整个std命名空间的实体都引入当前的作用域。 using namespace std; 然而，过度使用上述声明会增加命名冲突的风险，特别是在大型项目中，可能会不经意间覆盖命名空间中的名称。 以下是一些std命名空间中常见的组件示例： std::string: 动态大小的字符串类。 std::vector: 动态大小的数组。 std::map &amp;amp; std::unordered_map: 关联容器，提供键值对的存储。 std::set: 集合，保证元素的唯一性。 std::istream, std::ostream: 输入输出流的基本类型，如std::cin和std::cout。 std::thread: 用于管理线程的类。 std::unique_ptr, std::shared_ptr: 智能指针，用于更容易地管理动态分配的内存。 冲突与冲突解决 当使用两个或者更多具有相同名字的实体时，即发生了命名冲突。这对于编译器来说是不明确的，因为它不知道程序员打算使用哪个。这在以下两种情况中尤为常见： 从不同的库引入相同的名字。 在项目的不同部分对同名实体赋予了不同的定义。 为了解决这类冲突，C++提供了几种机制： 使用完整命名空间：即使用命名空间的名称前缀来指定需要的确切实体，如前文的companyA::Logger和companyB::Logger。 使用using指令：如果一个命名空间中的几个或所有名字在某个文件中会频繁被用到，可以用using指令将这个命名空间引入当前文件或作用域。然而, 如果引入了包含相同名称的多个命名空间，反而可能造成冲突。 使用namespace别名: 可以给长的或不方便的命名空间名字设置一个较短的别名。例如，namespace fs = std::filesystem;允许我们用fs代替较长的std::filesystem。 避免using namespace std 许多初学者喜欢使用using namespace std;来避免每次调用std命名空间中的标识符时需要额外键入std::。然而，在更复杂或更大的项目中，过度使用这个声明可能会导致问题。这是因为std命名空间包含了数千个函数和类，将会污染全局命名空间，增加了不同库之间发生命名冲突的风险。 命名空间的最佳实践 为了保持代码的清晰和可维护性，以下是一些命名空间的最佳实践建议： 有意识地使用命名空间: 只在需要时引入命名空间，避免使用using namespace std;。 避免无名（匿名）命名空间的频繁使用: 这些命名空间在单个文件中是独一无二的，但是在大型项目中使用过多会使得代码难以追踪。 适当设计自己的命名空间: 根据功能、模块或者库的逻辑关系组织代码，并为它们创建合理的命名空间。 使用内联命名空间: 对于需要保持API兼容性的版本控制，它允许特定版本的实现被默认选用，而不需要改变使用者的代码。 当我们在C++项目中使用命名空间来解决命名冲突和组织代码时，一个典型的例子是库的集成。 假设你正在开发一个游戏引擎，而这个引擎用到了两个不同的图形处理库：GraphicsLibA和GraphicsLibB。这两个库都提供了一个Renderer类来处理图形渲染。如果没有命名空间，编译器将不知道你提到的Renderer是来自哪个库的，从而引发命名冲突。 这个问题可以通过使用命名空间优雅地解决： namespace GraphicsLibA { class Renderer { public: void render() { // GraphicsLibA的渲染实现 } }; } namespace GraphicsLibB { class Renderer { public: void render() { // GraphicsLibB的渲染实现 } }; } 现在，两个Renderer类分别位于它们自己的命名空间中。当你需要使用特定的库时，你可以通过命名空间来指定你想要使用的Renderer类: GraphicsLibA::Renderer rendererA; rendererA.render(); // 调用GraphicsLibA中的render方法 GraphicsLibB::Renderer rendererB; rendererB.render(); // 调用GraphicsLibB中的render方法 如果你确定只会使用其中一个库的Renderer，可以使用using声明来简化代码: using GraphicsLibA::Renderer; Renderer renderer; renderer.render(); // 这会调用GraphicsLibA中的Renderer的render方法 但是，如果同时使用了两个库的Renderer，那么最好不要使用using声明，以免造成歧义。 命名空间不仅解决了命名冲突的问题，还可以用来划分逻辑上相关的代码组，提高项目的模块化和可读性。例如，在游戏引擎中，除了图形处理，你可能还要处理音频和物理模拟，可以为这些功能定义不同的命名空间： namespace Audio { class SoundSystem { // 音频处理相关的代码 }; } namespace Physics { class PhysicsEngine { // 物理模拟相关的代码 }; } 使用命名空间的最佳实践是一种避免混淆并加强代码结构的方法，它保证了当项目规模不断扩大时，代码依然能够清晰、可管理。 理解命名空间的用途与最佳实践，能够帮助开发者更加高效地组织和维护他们的C++代码库，从而减少错误并增强代码的重用性。 扩展思考 关于C++命名空间的使用价值和最佳实践，以下问题可以引导您深入思考： 命名空间在C++中的设计初衷是什么？ 如何在一个大型项目中合理使用命名空间来组织代码？ 在使用多个库时，命名空间如何帮助解决命名冲突？ 命名空间可以嵌套使用吗？嵌套命名空间有哪些潜在的优点和缺点？ using声明和using指令的使用在什么情况下是合适的？ 不当使用命名空间可能会带来哪些问题？如何避免？ 如何结合匿名命名空间来管理仅在一个文件中使用的代码？ 命名空间应该如何与类和模板等其他语言特性协同工作？ C++17中引入的内联命名空间具有哪些特殊的用途？ 如何通过合理使用命名空间提高代码的可读性和可维护性？</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">完全指掌握 C++ cmath 库</title>
      
      
      <link href="https://blog.talkincode.net/2024/03/21/Mastering-CPP-cmath/" rel="alternate" type="text/html" title="完全指掌握 C++ cmath 库" />
      
      <published>2024-03-21T06:56:22+00:00</published>
      <updated>2024-03-21T06:56:22+00:00</updated>
      <id>https://blog.talkincode.net/2024/03/21/Mastering-CPP-cmath</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/03/21/Mastering-CPP-cmath/">&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/jamiesun/images/master/default/6zGy8A.jpg&quot; alt=&quot;6zGy8A&quot; /&gt;&lt;/p&gt;

&lt;p&gt;C++ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt; 库为程序员提供了一套丰富的数学函数，允许执行各种数学运算。这篇文章将详细讲解 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt; 库中的每个方法，并通过具体示例来展示它们的用法。&lt;/p&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pow&lt;/code&gt; - 幂函数&lt;/h2&gt;

&lt;p&gt;该函数用于计算一个数的指数幂。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2 的 3 次方是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2 的 3 次方是: 8&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sqrt&lt;/code&gt; - 平方根函数&lt;/h2&gt;

&lt;p&gt;这个函数用于计算一个非负数的平方根。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;9.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;9 的平方根是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9 的平方根是: 3&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;三角函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sin&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cos&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tan&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;这些函数分别用于计算角度的正弦、余弦和正切值。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;degrees&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;45.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;radians&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;acos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;degrees&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;180.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;45°的正弦值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radians&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;45°的余弦值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radians&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;45°的正切值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radians&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;45°的正弦值是: 0.707107
45°的余弦值是: 0.707107
45°的正切值是: 1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;对数函数&lt;/h2&gt;

&lt;h3&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log&lt;/code&gt; - 自然对数&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log&lt;/code&gt; 函数返回一个数的自然对数（以e为底）。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.718281828459045&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;e 的自然对数是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e 的自然对数是: 1&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log10&lt;/code&gt; - 常用对数&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log10&lt;/code&gt; 函数返回一个数的常用对数（以10为底）。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;100.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;100 的对数（以10为底）是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100 的对数（以10为底）是: 2&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exp&lt;/code&gt; - 指数函数&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exp&lt;/code&gt; 函数计算 e（自然对数的底数）的幂。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;e 的 &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exponent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; 次幂是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e 的 1 次幂是: 2.71828&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fabs&lt;/code&gt; - 绝对值函数&lt;/h2&gt;

&lt;p&gt;用于计算浮点数的绝对值。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;5.67&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;-5.67的绝对值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fabs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-5.67的绝对值是: 5.67&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ceil&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;floor&lt;/code&gt; - 向上和向下取整函数&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ceil&lt;/code&gt; 函数返回大于或等于给定数值的最小整数，而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;floor&lt;/code&gt; 函数返回小于或等于给定数值的最大整数。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.3 向上取整的结果是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ceil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.3 向下取整的结果是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;floor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;-2.3 向上取整的结果是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ceil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;-2.3 向下取整的结果是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;floor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2.3 向上取整的结果是: 3
2.3 向下取整的结果是: 2
&lt;span class=&quot;nt&quot;&gt;-2&lt;/span&gt;.3 向上取整的结果是: &lt;span class=&quot;nt&quot;&gt;-2&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;-2&lt;/span&gt;.3 向下取整的结果是: &lt;span class=&quot;nt&quot;&gt;-3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fmod&lt;/code&gt; - 浮点数取余函数&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fmod&lt;/code&gt; 函数用于计算两个浮点数相除的余数。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numerator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;12.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;denominator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;12.5 除以 3.2 的余数是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fmod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numerator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;denominator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;12.5 除以 3.2 的余数是: 2.9&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;round&lt;/code&gt; - 四舍五入函数&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;round&lt;/code&gt; 函数可以将一个浮点数四舍五入到最接近的整数。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.5 四舍五入的结果是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;2.49&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2.49 四舍五入的结果是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;2.5 四舍五入的结果是: 3
2.49 四舍五入的结果是: 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nan&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;infinity&lt;/code&gt; - 特殊值函数&lt;/h2&gt;

&lt;p&gt;处理数学运算时有时会遇到非数值（NaN）或无穷大的情况，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nan&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;infinity&lt;/code&gt; 函数来处理。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;非数字 (NaN) 的值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;正无穷的值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numeric_limits&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;infinity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;负无穷的值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numeric_limits&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;infinity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;非数字 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;NaN&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 的值是: nan
正无穷的值是: inf
负无穷的值是: &lt;span class=&quot;nt&quot;&gt;-inf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;双曲函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sinh&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cosh&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tanh&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sinh&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cosh&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tanh&lt;/code&gt; 是双曲正弦、双曲余弦、双曲正切函数，它们用于计算双曲角的对应值。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;双曲正弦函数 sinh(1) 的值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sinh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;双曲余弦函数 cosh(1) 的值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cosh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;双曲正切函数 tanh(1) 的值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tanh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;双曲正弦函数 sinh&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 的值是: 1.1752
双曲余弦函数 cosh&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 的值是: 1.54308
双曲正切函数 tanh&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 的值是: 0.761594
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;反三角函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;asin&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acos&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;atan&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;asin&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acos&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;atan&lt;/code&gt; 分别计算给定数值的反正弦、反余弦、反正切值，返回的是对应的角度值，范围通常在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-π/2&lt;/code&gt; 到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;π/2&lt;/code&gt; 之间。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;0.5 的反正弦值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;0.5 的反余弦值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;acos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;0.5 的反正切值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;atan&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0.5 的反正弦值是: 0.523599
0.5 的反余弦值是: 1.0472
0.5 的反正切值是: 0.463648
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;erf&lt;/code&gt; - 误差函数&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;erf&lt;/code&gt; 函数返回参数对应的误差函数值，用于计算高斯误差分布的积分。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;误差函数 erf(1) 的值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;erf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;误差函数 erf(1) 的值是: 0.842700&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tgamma&lt;/code&gt; - 伽马函数&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tgamma&lt;/code&gt; 函数返回参数的伽马函数值，该函数是阶乘概念在实数和复数上的推广。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;伽马函数 tgamma(5) 的值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tgamma&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;伽马函数 tgamma(5) 的值是: 24&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nextafter&lt;/code&gt; - 浮点数下一个表示函数&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nextafter&lt;/code&gt; 函数返回从给定的浮点数到第二个给定浮点数表示的下一个可能值。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;从0到1浮点数下一个表示的值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nextafter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;从0到1浮点数下一个表示的值是: 4.94066e-324&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;至此，本篇关于 C++ &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt; 库的介绍已经涵盖了大部分常用的数学函数。我们讨论了基本的算术运算、三角函数、对数函数、取整函数、双曲函数、反三角函数以及错误函数和特殊数学函数。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt; 库是 C程序员可以非常轻松地在代码中嵌入数学运算和计算准确的科学结果。不管您是在开发游戏、进行科学计算还是处理日常的编程任务，掌握 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt; 库都将大大提高您的工作效率。&lt;/p&gt;

&lt;p&gt;此外，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt; 库还包括一些不太常用但功能强大的函数，如下所示：&lt;/p&gt;

&lt;h2&gt;贝塞尔函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j0&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jn&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;贝塞尔函数是解决波动问题（如热传导、电磁波等）时经常遇到的函数。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j0&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j1&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jn&lt;/code&gt; 分别是第一类零阶、第一阶和第 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;n&lt;/code&gt; 阶贝塞尔函数。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;第一类零阶贝塞尔函数 j0(1) 的值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;第一类第一阶贝塞尔函数 j1(1) 的值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;第一类第三阶贝塞尔函数 jn(3, 1) 的值是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;第一类零阶贝塞尔函数 j0&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 的值是: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;具体值]
第一类第一阶贝塞尔函数 j1&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 的值是: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;具体值]
第一类第三阶贝塞尔函数 jn&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;3, 1&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 的值是: &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;具体值]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hypot&lt;/code&gt; - 求直角三角形斜边长度&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hypot&lt;/code&gt; 函数用于计算直角三角形的斜边长度，其参数是两个直角边的长度。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;直角三角形的斜边长度是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hypot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;直角三角形的斜边长度是: 5&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;copysign&lt;/code&gt; - 复制符号函数&lt;/h2&gt;

&lt;p&gt;该函数将第二个参数的符号复制到第一个参数上，结果的绝对值等于第一个参数。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;cmath&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;magnitude&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sign&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;带上第二个值符号的结果是: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;copysign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magnitude&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sign&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;输出：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;带上第二个值符号的结果是: -3.5&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这些是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt; 库中的一些高级功能，在处理特定领域的问题时可能会用到。对于 C++ 程序员来说，熟练运用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt; 库将帮助你轻松应对各种数学挑战。&lt;/p&gt;

&lt;p&gt;希望这篇文章能帮助你更好地理解 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt; 库的功能，不论是简单的算术计算还是复杂的数学模型，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt; 库都能提供所需的数学工具，使你的代码变得更加优雅和高效。&lt;/p&gt;

&lt;h2&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt; 库时的编译器和操作系统考虑&lt;/h2&gt;

&lt;h3&gt;GCC (GNU Compiler Collection)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;兼容性&lt;/strong&gt;：GCC在多数Linux发行版中是默认的C++编译器，自带对&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库良好的支持。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;标准遵循&lt;/strong&gt;：GCC对C++标准的遵循度很高，使用时要确保选用合适的标准，例如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-std=c++11&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-std=c++17&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;数学库链接&lt;/strong&gt;：在进行编译时可能需要显式链接数学库，即在命令行中加上 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-lm&lt;/code&gt; 选项。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Clang&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;标准库&lt;/strong&gt;：Clang通常使用LLVM的libc++作为其标准库，与GCC使用的libstdc++有所不同。在大部分情况下，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;中的函数表现相似。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;跨平台&lt;/strong&gt;：Clang旨在实现跨平台的兼容性，确保在不同操作系统上的一致体验。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;MSVC (Microsoft Visual C++)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Visual Studio IDE&lt;/strong&gt;：MSVC通常与Visual Studio集成，Visual Studio环境下&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库函数的使用通常不会遇到特殊的问题。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Windows特有的实现&lt;/strong&gt;：MSVC有时会在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;函数背后使用Windows API的特定实现，可能会导致行为与GCC和Clang在某些边缘情况下略有不同。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;操作系统差异&lt;/h3&gt;

&lt;h4&gt;Windows&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;精度差异&lt;/strong&gt;：由于不同的编译器可能使用不同的底层实现，可能会在函数的精度上有细微差异。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;路径问题&lt;/strong&gt;：在Windows中包含库文件时，可能需要注意路径和斜杠方向，以确保正确地找到头文件。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Linux&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;版本管理&lt;/strong&gt;：Linux系统中的库通常由系统的包管理器管理，确保系统更新可保持库的最新状态。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;环境差异&lt;/strong&gt;：不同的Linux发行版可能会使用不同版本的编译器和标准库实现，这可能会影响构建过程和运行时行为。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;macOS&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Clang为主&lt;/strong&gt;：macOS通常使用Clang作为其主要的编译环境，因此其对&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库的支持通常与Linux上的Clang保持一致。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Xcode&lt;/strong&gt;：与MSVC类似，Apple的Xcode IDE集成了Clang编译器和相关工具链，提供了良好的支持和集成。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;具体注意事项&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;宏定义&lt;/strong&gt;：一些系统或编译器特定的宏可能会影响&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库的行为，例如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_USE_MATH_DEFINES&lt;/code&gt;在Windows上可以启用对π等数学常量的定义。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;编译器优化&lt;/strong&gt;：编译器的优化设置可能会影响数学函数的效率，必要时可以进行调整使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-O2&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-O3&lt;/code&gt; 等优化选项。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;严格标准遵循&lt;/strong&gt;：有些编译器提供了严格遵循标准的模式，可以通过命令行选项启动，如GCC和Clang的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-pedantic&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;扩展思考&lt;/h2&gt;

&lt;p&gt;你提到的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;通常是指C++中的一个数学库，它用于提供复数类的支持以及对复数的数学运算。下面是一系列用索格拉底式提问法来引导你深入思考如何有效利用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库为什么在处理复数运算时比C++标准库中的数学函数更有优势？&lt;/li&gt;
  &lt;li&gt;在使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库时，掌握哪些基础的复数概念是必要的？&lt;/li&gt;
  &lt;li&gt;如何在C++程序中正确地包含和使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库？&lt;/li&gt;
  &lt;li&gt;使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库中的函数时，如何确保传入的参数满足函数要求？&lt;/li&gt;
  &lt;li&gt;在进行复数运算时，如何使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库提高代码的效率和准确性？&lt;/li&gt;
  &lt;li&gt;当结果需要是实数而不是复数时，如何从&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库返回的结果中正确提取信息？&lt;/li&gt;
  &lt;li&gt;在哪些类型的问题或者项目中，使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库会特别有帮助？&lt;/li&gt;
  &lt;li&gt;如何通过实例学习来加深对&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库的理解和应用？&lt;/li&gt;
  &lt;li&gt;使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmath&lt;/code&gt;库进行计算时可能会遇到什么挑战，又如何解决这些挑战？&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      

      
        <category term="c++" />
      
        <category term="programming" />
      
        <category term="cmath" />
      

      

      
        <summary type="html">C++ cmath 库为程序员提供了一套丰富的数学函数，允许执行各种数学运算。这篇文章将详细讲解 cmath 库中的每个方法，并通过具体示例来展示它们的用法。 pow - 幂函数 该函数用于计算一个数的指数幂。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double base = 2.0; double exponent = 3.0; std::cout &amp;lt;&amp;lt; &quot;2 的 3 次方是: &quot; &amp;lt;&amp;lt; std::pow(base, exponent) &amp;lt;&amp;lt; std::endl; return 0; } 输出：2 的 3 次方是: 8 sqrt - 平方根函数 这个函数用于计算一个非负数的平方根。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double number = 9.0; std::cout &amp;lt;&amp;lt; &quot;9 的平方根是: &quot; &amp;lt;&amp;lt; std::sqrt(number) &amp;lt;&amp;lt; std::endl; return 0; } 输出：9 的平方根是: 3 三角函数 sin, cos, tan 这些函数分别用于计算角度的正弦、余弦和正切值。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double degrees = 45.0; double radians = std::acos(-1) * degrees/180.0; std::cout &amp;lt;&amp;lt; &quot;45°的正弦值是: &quot; &amp;lt;&amp;lt; std::sin(radians) &amp;lt;&amp;lt; std::endl; std::cout &amp;lt;&amp;lt; &quot;45°的余弦值是: &quot; &amp;lt;&amp;lt; std::cos(radians) &amp;lt;&amp;lt; std::endl; std::cout &amp;lt;&amp;lt; &quot;45°的正切值是: &quot; &amp;lt;&amp;lt; std::tan(radians) &amp;lt;&amp;lt; std::endl; return 0; } 输出： 45°的正弦值是: 0.707107 45°的余弦值是: 0.707107 45°的正切值是: 1 对数函数 log - 自然对数 log 函数返回一个数的自然对数（以e为底）。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double number = 2.718281828459045; std::cout &amp;lt;&amp;lt; &quot;e 的自然对数是: &quot; &amp;lt;&amp;lt; std::log(number) &amp;lt;&amp;lt; std::endl; return 0; } 输出：e 的自然对数是: 1 log10 - 常用对数 log10 函数返回一个数的常用对数（以10为底）。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double number = 100.0; std::cout &amp;lt;&amp;lt; &quot;100 的对数（以10为底）是: &quot; &amp;lt;&amp;lt; std::log10(number) &amp;lt;&amp;lt; std::endl; return 0; } 输出：100 的对数（以10为底）是: 2 exp - 指数函数 exp 函数计算 e（自然对数的底数）的幂。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double exponent = 1.0; std::cout &amp;lt;&amp;lt; &quot;e 的 &quot; &amp;lt;&amp;lt; exponent &amp;lt;&amp;lt;&quot; 次幂是: &quot; &amp;lt;&amp;lt; std::exp(exponent) &amp;lt;&amp;lt; std::endl; return 0; } 输出：e 的 1 次幂是: 2.71828 fabs - 绝对值函数 用于计算浮点数的绝对值。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double number = -5.67; std::cout &amp;lt;&amp;lt; &quot;-5.67的绝对值是: &quot; &amp;lt;&amp;lt; std::fabs(number) &amp;lt;&amp;lt; std::endl; return 0; } 输出：-5.67的绝对值是: 5.67 ceil 和 floor - 向上和向下取整函数 ceil 函数返回大于或等于给定数值的最小整数，而 floor 函数返回小于或等于给定数值的最大整数。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double number = 2.3; std::cout &amp;lt;&amp;lt; &quot;2.3 向上取整的结果是: &quot; &amp;lt;&amp;lt; std::ceil(number) &amp;lt;&amp;lt; std::endl; std::cout &amp;lt;&amp;lt; &quot;2.3 向下取整的结果是: &quot; &amp;lt;&amp;lt; std::floor(number) &amp;lt;&amp;lt; std::endl; number = -2.3; std::cout &amp;lt;&amp;lt; &quot;-2.3 向上取整的结果是: &quot; &amp;lt;&amp;lt; std::ceil(number) &amp;lt;&amp;lt; std::endl; std::cout &amp;lt;&amp;lt; &quot;-2.3 向下取整的结果是: &quot; &amp;lt;&amp;lt; std::floor(number) &amp;lt;&amp;lt; std::endl; return 0; } 输出： 2.3 向上取整的结果是: 3 2.3 向下取整的结果是: 2 -2.3 向上取整的结果是: -2 -2.3 向下取整的结果是: -3 fmod - 浮点数取余函数 fmod 函数用于计算两个浮点数相除的余数。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double numerator = 12.5; double denominator = 3.2; std::cout &amp;lt;&amp;lt; &quot;12.5 除以 3.2 的余数是: &quot; &amp;lt;&amp;lt; std::fmod(numerator, denominator) &amp;lt;&amp;lt; std::endl; return 0; } 输出：12.5 除以 3.2 的余数是: 2.9 round - 四舍五入函数 round 函数可以将一个浮点数四舍五入到最接近的整数。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double number = 2.5; std::cout &amp;lt;&amp;lt; &quot;2.5 四舍五入的结果是: &quot; &amp;lt;&amp;lt; std::round(number) &amp;lt;&amp;lt; std::endl; number = 2.49; std::cout &amp;lt;&amp;lt; &quot;2.49 四舍五入的结果是: &quot; &amp;lt;&amp;lt; std::round(number) &amp;lt;&amp;lt; std::endl; return 0; } 输出： 2.5 四舍五入的结果是: 3 2.49 四舍五入的结果是: 2 nan、infinity - 特殊值函数 处理数学运算时有时会遇到非数值（NaN）或无穷大的情况，可以使用 nan 和 infinity 函数来处理。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { std::cout &amp;lt;&amp;lt; &quot;非数字 (NaN) 的值是: &quot; &amp;lt;&amp;lt; std::nan(&quot;1&quot;) &amp;lt;&amp;lt; std::endl; std::cout &amp;lt;&amp;lt; &quot;正无穷的值是: &quot; &amp;lt;&amp;lt; std::numeric_limits&amp;lt;double&amp;gt;::infinity() &amp;lt;&amp;lt; std::endl; std::cout &amp;lt;&amp;lt; &quot;负无穷的值是: &quot; &amp;lt;&amp;lt; -std::numeric_limits&amp;lt;double&amp;gt;::infinity() &amp;lt;&amp;lt; std::endl; return 0; } 输出： 非数字 (NaN) 的值是: nan 正无穷的值是: inf 负无穷的值是: -inf 双曲函数 sinh, cosh, tanh sinh, cosh, tanh 是双曲正弦、双曲余弦、双曲正切函数，它们用于计算双曲角的对应值。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double value = 1.0; std::cout &amp;lt;&amp;lt; &quot;双曲正弦函数 sinh(1) 的值是: &quot; &amp;lt;&amp;lt; std::sinh(value) &amp;lt;&amp;lt; std::endl; std::cout &amp;lt;&amp;lt; &quot;双曲余弦函数 cosh(1) 的值是: &quot; &amp;lt;&amp;lt; std::cosh(value) &amp;lt;&amp;lt; std::endl; std::cout &amp;lt;&amp;lt; &quot;双曲正切函数 tanh(1) 的值是: &quot; &amp;lt;&amp;lt; std::tanh(value) &amp;lt;&amp;lt; std::endl; return 0; } 输出： 双曲正弦函数 sinh(1) 的值是: 1.1752 双曲余弦函数 cosh(1) 的值是: 1.54308 双曲正切函数 tanh(1) 的值是: 0.761594 反三角函数 asin, acos, atan asin, acos, atan 分别计算给定数值的反正弦、反余弦、反正切值，返回的是对应的角度值，范围通常在 -π/2 到 π/2 之间。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double value = 0.5; std::cout &amp;lt;&amp;lt; &quot;0.5 的反正弦值是: &quot; &amp;lt;&amp;lt; std::asin(value) &amp;lt;&amp;lt; std::endl; std::cout &amp;lt;&amp;lt; &quot;0.5 的反余弦值是: &quot; &amp;lt;&amp;lt; std::acos(value) &amp;lt;&amp;lt; std::endl; std::cout &amp;lt;&amp;lt; &quot;0.5 的反正切值是: &quot; &amp;lt;&amp;lt; std::atan(value) &amp;lt;&amp;lt; std::endl; return 0; } 输出： 0.5 的反正弦值是: 0.523599 0.5 的反余弦值是: 1.0472 0.5 的反正切值是: 0.463648 erf - 误差函数 erf 函数返回参数对应的误差函数值，用于计算高斯误差分布的积分。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double value = 1.0; std::cout &amp;lt;&amp;lt; &quot;误差函数 erf(1) 的值是: &quot; &amp;lt;&amp;lt; std::erf(value) &amp;lt;&amp;lt; std::endl; return 0; } 输出：误差函数 erf(1) 的值是: 0.842700 tgamma - 伽马函数 tgamma 函数返回参数的伽马函数值，该函数是阶乘概念在实数和复数上的推广。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double value = 5.0; std::cout &amp;lt;&amp;lt; &quot;伽马函数 tgamma(5) 的值是: &quot; &amp;lt;&amp;lt; std::tgamma(value) &amp;lt;&amp;lt; std::endl; return 0; } 输出：伽马函数 tgamma(5) 的值是: 24 nextafter - 浮点数下一个表示函数 nextafter 函数返回从给定的浮点数到第二个给定浮点数表示的下一个可能值。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double from = 0.0; double to = 1.0; std::cout &amp;lt;&amp;lt; &quot;从0到1浮点数下一个表示的值是: &quot; &amp;lt;&amp;lt; std::nextafter(from, to) &amp;lt;&amp;lt; std::endl; return 0; } 输出：从0到1浮点数下一个表示的值是: 4.94066e-324 至此，本篇关于 C++ cmath 库的介绍已经涵盖了大部分常用的数学函数。我们讨论了基本的算术运算、三角函数、对数函数、取整函数、双曲函数、反三角函数以及错误函数和特殊数学函数。cmath 库是 C程序员可以非常轻松地在代码中嵌入数学运算和计算准确的科学结果。不管您是在开发游戏、进行科学计算还是处理日常的编程任务，掌握 cmath 库都将大大提高您的工作效率。 此外，cmath 库还包括一些不太常用但功能强大的函数，如下所示： 贝塞尔函数 j0, j1, jn 贝塞尔函数是解决波动问题（如热传导、电磁波等）时经常遇到的函数。j0, j1, jn 分别是第一类零阶、第一阶和第 n 阶贝塞尔函数。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double value = 1.0; std::cout &amp;lt;&amp;lt; &quot;第一类零阶贝塞尔函数 j0(1) 的值是: &quot; &amp;lt;&amp;lt; std::j0(value) &amp;lt;&amp;lt; std::endl; std::cout &amp;lt;&amp;lt; &quot;第一类第一阶贝塞尔函数 j1(1) 的值是: &quot; &amp;lt;&amp;lt; std::j1(value) &amp;lt;&amp;lt; std::endl; std::cout &amp;lt;&amp;lt; &quot;第一类第三阶贝塞尔函数 jn(3, 1) 的值是: &quot; &amp;lt;&amp;lt; std::jn(3, value) &amp;lt;&amp;lt; std::endl; return 0; } 输出： 第一类零阶贝塞尔函数 j0(1) 的值是: [具体值] 第一类第一阶贝塞尔函数 j1(1) 的值是: [具体值] 第一类第三阶贝塞尔函数 jn(3, 1) 的值是: [具体值] hypot - 求直角三角形斜边长度 hypot 函数用于计算直角三角形的斜边长度，其参数是两个直角边的长度。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double x = 3.0; double y = 4.0; std::cout &amp;lt;&amp;lt; &quot;直角三角形的斜边长度是: &quot; &amp;lt;&amp;lt; std::hypot(x, y) &amp;lt;&amp;lt; std::endl; return 0; } 输出：直角三角形的斜边长度是: 5 copysign - 复制符号函数 该函数将第二个参数的符号复制到第一个参数上，结果的绝对值等于第一个参数。 #include &amp;lt;cmath&amp;gt; #include &amp;lt;iostream&amp;gt; int main() { double magnitude = 3.5; double sign = -1.0; std::cout &amp;lt;&amp;lt; &quot;带上第二个值符号的结果是: &quot; &amp;lt;&amp;lt; std::copysign(magnitude, sign) &amp;lt;&amp;lt; std::endl; return 0; } 输出：带上第二个值符号的结果是: -3.5 这些是 cmath 库中的一些高级功能，在处理特定领域的问题时可能会用到。对于 C++ 程序员来说，熟练运用 cmath 库将帮助你轻松应对各种数学挑战。 希望这篇文章能帮助你更好地理解 cmath 库的功能，不论是简单的算术计算还是复杂的数学模型，cmath 库都能提供所需的数学工具，使你的代码变得更加优雅和高效。 使用 cmath 库时的编译器和操作系统考虑 GCC (GNU Compiler Collection) 兼容性：GCC在多数Linux发行版中是默认的C++编译器，自带对cmath库良好的支持。 标准遵循：GCC对C++标准的遵循度很高，使用时要确保选用合适的标准，例如 -std=c++11 或 -std=c++17。 数学库链接：在进行编译时可能需要显式链接数学库，即在命令行中加上 -lm 选项。 Clang 标准库：Clang通常使用LLVM的libc++作为其标准库，与GCC使用的libstdc++有所不同。在大部分情况下，cmath中的函数表现相似。 跨平台：Clang旨在实现跨平台的兼容性，确保在不同操作系统上的一致体验。 MSVC (Microsoft Visual C++) Visual Studio IDE：MSVC通常与Visual Studio集成，Visual Studio环境下cmath库函数的使用通常不会遇到特殊的问题。 Windows特有的实现：MSVC有时会在cmath函数背后使用Windows API的特定实现，可能会导致行为与GCC和Clang在某些边缘情况下略有不同。 操作系统差异 Windows 精度差异：由于不同的编译器可能使用不同的底层实现，可能会在函数的精度上有细微差异。 路径问题：在Windows中包含库文件时，可能需要注意路径和斜杠方向，以确保正确地找到头文件。 Linux 版本管理：Linux系统中的库通常由系统的包管理器管理，确保系统更新可保持库的最新状态。 环境差异：不同的Linux发行版可能会使用不同版本的编译器和标准库实现，这可能会影响构建过程和运行时行为。 macOS Clang为主：macOS通常使用Clang作为其主要的编译环境，因此其对cmath库的支持通常与Linux上的Clang保持一致。 Xcode：与MSVC类似，Apple的Xcode IDE集成了Clang编译器和相关工具链，提供了良好的支持和集成。 具体注意事项 宏定义：一些系统或编译器特定的宏可能会影响cmath库的行为，例如_USE_MATH_DEFINES在Windows上可以启用对π等数学常量的定义。 编译器优化：编译器的优化设置可能会影响数学函数的效率，必要时可以进行调整使用 -O2 或 -O3 等优化选项。 严格标准遵循：有些编译器提供了严格遵循标准的模式，可以通过命令行选项启动，如GCC和Clang的 -pedantic。 扩展思考 你提到的cmath通常是指C++中的一个数学库，它用于提供复数类的支持以及对复数的数学运算。下面是一系列用索格拉底式提问法来引导你深入思考如何有效利用cmath库： cmath库为什么在处理复数运算时比C++标准库中的数学函数更有优势？ 在使用cmath库时，掌握哪些基础的复数概念是必要的？ 如何在C++程序中正确地包含和使用cmath库？ 使用cmath库中的函数时，如何确保传入的参数满足函数要求？ 在进行复数运算时，如何使用cmath库提高代码的效率和准确性？ 当结果需要是实数而不是复数时，如何从cmath库返回的结果中正确提取信息？ 在哪些类型的问题或者项目中，使用cmath库会特别有帮助？ 如何通过实例学习来加深对cmath库的理解和应用？ 使用cmath库进行计算时可能会遇到什么挑战，又如何解决这些挑战？</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">如何更通俗易懂的解释 C++ 二维数组</title>
      
      
      <link href="https://blog.talkincode.net/2024/03/21/CPP-2D-Arrays-Demystified/" rel="alternate" type="text/html" title="如何更通俗易懂的解释 C++ 二维数组" />
      
      <published>2024-03-21T06:21:14+00:00</published>
      <updated>2024-03-21T06:21:14+00:00</updated>
      <id>https://blog.talkincode.net/2024/03/21/CPP-2D-Arrays-Demystified</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/03/21/CPP-2D-Arrays-Demystified/">&lt;h2&gt;图书馆的书架&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/jamiesun/images/master/default/9NIP9a.jpg&quot; alt=&quot;9NIP9a&quot; /&gt;&lt;/p&gt;

&lt;p&gt;想象一下，一家大型的图书馆。在这座图书馆里，有无数个书架，每个书架上都整齐地排列着一行行的书籍。如果你想找到一本特定的书，你需要知道它在哪个书架上，以及它在这个书架上的具体位置。在这里，书架就像是一个一维数组，它代表这本书的“行”位置，而书架上的每个位置就像是一维数组中的一个元素，代表这本书的“列”位置。把这个概念扩展到二维，你实际上就有了一大堆书架，且每个书架都有自己的书籍排列，构成了一个二维数组。&lt;/p&gt;

&lt;p&gt;在 C++ 中，一个二维数组就像这个图书馆。你可以想象它为一个大表格，表格里有很多行（书架）和列（书本）。就像在图书馆你需要行和列的信息来找到一本书一样，你在 C++ 的二维数组中需要两个坐标：一个代表行的索引和一个代表列的索引。用代码来说，如果你有一个名为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bookshelves&lt;/code&gt; 的二维数组，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bookshelves[3][2]&lt;/code&gt; 就像是在图书馆中跑到第四个书架上，然后拿起了这个书架上从左边数的第三本书。&lt;/p&gt;

&lt;p&gt;使用二维数组时，每个维度都可以想象成是数组中的一个级别。第一个维度通常代表“行”，就像书架一样；而第二个维度代表“列”，就像书本在书架上的摆放。同样，在 C++ 中，如果你创建了一个二维数组 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int seats[2][3]&lt;/code&gt;，可以想象这是一个拥有两排（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt; 行）和每排三个座位（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3&lt;/code&gt; 列）的小型电影院。&lt;/p&gt;

&lt;p&gt;让我们构建一个关于图书馆的书架的例子。我们会创建一个包含书架和书籍的二维数组，并且尝试访问其中一个特定的书籍。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 创建一个有 4 个书架的图书馆，每个书架可以存放 5 本书&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Book1-1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book1-2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book1-3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book1-4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book1-5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Book2-1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book2-2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book2-3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book2-4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book2-5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Book3-1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book3-2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book3-3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book3-4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book3-5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Book4-1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book4-2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book4-3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book4-4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book4-5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// 想找到第 3 个书架上的第 2 本书&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shelf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 由于数组索引从 0 开始，第 3 个书架其索引是 2&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 同样地，第 2 本书的索引是 1&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Book at shelf &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shelf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;, position &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;library&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shelf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;操场上的方阵&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/jamiesun/images/master/default/69wAsx.png&quot; alt=&quot;69wAsx&quot; /&gt;&lt;/p&gt;

&lt;p&gt;想象一个宽阔的操场，在特别的活动日上，学校的学生们被安排成一个完美的方阵形式进行表演。每个学生站在操场的一个特定位置上，一排排的学生形成了横行，一列列则形成了纵列。这和C++中的二维数组非常相似。&lt;/p&gt;

&lt;p&gt;如果我们将这个操场抽象成一个二维数组，那么每一行学生可以看作是数组的一行，每一列学生就是数组的一列。当我们指涉“操场上的方阵”时，我们实际上是在说一个由行(row)和列(column)组成的结构。&lt;/p&gt;

&lt;p&gt;以 C++ 中的数组表示，如果操场上的方阵用变量 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;students&lt;/code&gt; 来代表，那么 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;students[2][3]&lt;/code&gt; 就代表着第三排的第四个学生。这是因为，在编程中，索引是从零开始的。所以，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;students[0][0]&lt;/code&gt; 表示的是第一排的第一个学生，而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;students[2][3]&lt;/code&gt; 则定位在第三排的第四个学生。&lt;/p&gt;

&lt;p&gt;使用这个类比，二维数组的概念变得生动且具象化。学生们站成的方阵就如同一个表格，里面的每个位置既有行的坐标也有列的坐标。我们可以轻松地通过这两个坐标找到任意一个特定的学生，就像我们在 C++ 中使用行索引和列索引来访问数组元素那样简单。&lt;/p&gt;

&lt;p&gt;示例如下：&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 设定一个学生方阵，3 行 4 列&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;students&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Alice&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Bob&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Charlie&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;David&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Eva&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Frank&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Grace&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Helen&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Irene&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Jack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Kathy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Leo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// 想找到第 3 排的第 4 个学生&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 第 3 排的索引是 2&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 第 4 个学生的索引是 3&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Student at row &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;, column &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;students&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;现在我们使用两层嵌套循环来模拟每个学生轮流报出自己名字的情景。外层循环将遍历每一排（二维数组的第一个维度），而内层循环将遍历每一排中的每个学生（二维数组的第二个维度）。&lt;/p&gt;

&lt;p&gt;下面是示例代码：&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 定义了一个 3 行 4 列的学生方阵&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;students&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Alice&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Bob&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Charlie&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;David&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Eva&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Frank&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Grace&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Helen&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Irene&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Jack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Kathy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Leo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// 外层循环遍历操场上的每一排（行）&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// 内层循环遍历每排（行）的每个学生（列）&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// 输出当前学生的名字，并行报数&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Student at row &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;, column &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; is: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;students&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;col&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当这段代码执行时，它将逐个访问二维数组 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;students&lt;/code&gt; 中的每个元素。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;row&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;col&lt;/code&gt; 变量分别表示当前遍历到的行索引和列索引。在数组里，行和列的索引都是从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; 开始计数的，所以第一个学生的位置是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;students[0][0]&lt;/code&gt;。每访问到一个学生，程序都会输出学生所在的行和列，以及学生的名字。这个过程会重复进行直到数组中的所有学生都被访问一次，仿佛每个学生轮流报出自己的名字。&lt;/p&gt;

&lt;h2&gt;二维数组的特点&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;像个格子状的表格&lt;/strong&gt;：二维数组就像是一个Excel表格，有行有列。想象一下，你在看一个足球队的排名表，上面有不同的队伍（行）和他们在每个赛季的得分（列）。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;由一维数组组成&lt;/strong&gt;：每一行（或者说每个书架）其实就是一个一维数组。正如图书馆中的每个书架都放着一排书一样，这些一维数组合在一起就形成了一个二维数组。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;通过两个索引来访问&lt;/strong&gt;：想找到特定的信息，比如书架上的某一本书，你需要两个索引：一个代表书架的行，另一个代表书的列。这跟你在游乐园地图里找厕所是一个道理，你需要知道它在哪个区域的哪个位置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;存储相同类型的元素&lt;/strong&gt;：每个格子（或者学生的位置）里存放的元素都是同一类型的。比如，整个学生方阵里的每个位置都填着学生的名字。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;固定的行和列大小&lt;/strong&gt;：通常，当你定义了一个二维数组，你就固定了它的行数和列数。这就跟买衣服一样，一旦标签上写的是中号，你就不能随意把它拉伸成大号。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;可以用循环遍历&lt;/strong&gt;：你可以使用两层循环来遍历二维数组的每个元素。就像在学校操场的方阵练习中，教练会从第一个学生开始检查，一列一列地走过去，确保每个学生都在正确的位置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;动态和静态都行&lt;/strong&gt;：虽然我们上面的例子用的是静态数组，也就是在编译时就固定大小的数组，但C++也允许创建动态的二维数组，那种可以在程序运行时确定大小的数组。这就像你决定在家里搭一个书架，随时可以根据需要添加新的层。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;初始化时可选&lt;/strong&gt;：在创建二维数组时，你可以选择是否立即填满它。就像买了一个书架，你可以先放几本你最爱的书，也可以一次性把它装满。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;可以嵌套多层&lt;/strong&gt;：二维数组的概念可以扩展到三维、四维，以此类推，每增加一个维度就像是再增加一个维度的索引。这就有点像三维电影，你不仅知道角色的左右和上下位置，还可感受到他们离你有多远。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;典型的应用场景&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;游戏开发中的棋盘和地图设计&lt;/strong&gt;：在游戏设计领域，二维数组是构建棋盘和各类游戏地图的理想工具。比如说，一个国际象棋游戏就可以用一个8x8的数组来表示。开发者可以使用二维数组来跟踪每个棋子的位置，判断移动是否合法，以及保存游戏的状态。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;电子表格的数据存储&lt;/strong&gt;：我们都知道微软的Excel或谷歌表格都是处理表格数据的利器。在幕后，这些数据通常以二维数组的形式存储，这样可以轻易地通过行和列来访问每一个数据单元。这就像我们前面提到的足球队排名表，有清晰的行（队伍）和列（赛季得分）。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;图像处理应用&lt;/strong&gt;：图像实际上可以被视为一个二维数组，每个元素代表图片中的一个像素点。在图像处理应用中，二维数组被用来存储和操作像素值，进行图片编辑，诸如滤镜、旋转、缩放等操作。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;社交网络分析&lt;/strong&gt;：在社交网络分析中，二维数组可能被用来表示用户之间的关系。例如，数组的行和列都可以代表不同的用户，而数组中的值可以表示一对用户之间的关系状态，如好友、屏蔽或者关注。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;矩阵计算在科学中的应用&lt;/strong&gt;：在物理、工程和计算机科学等领域，矩阵是一种基本的数学工具，通常用二维数组来表示。它们用于描述和模拟复杂的系统，例如天气模型、飞机设计模拟或者在量子计算中的状态变换。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;存储表结构数据&lt;/strong&gt;：在软件开发中，不少情况下需要处理和存储来自数据库的表结构数据。二维数组提供了一个便利的方式来缓存这些数据，供程序处理和显示。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;教育工具中的示范和实践&lt;/strong&gt;：在编程教学中，二维数组是一个很好的教学工具。它可以帮助学生们更好地理解数据的组织方式和多维数据结构。比如，可以通过二维数组教导学生如何进行棋类游戏编程，或者创建简单的地图应用等。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;</content>

      
      
      
      
      

      

      
        <category term="cpp" />
      
        <category term="multidimensional-arrays" />
      

      

      
        <summary type="html">图书馆的书架 想象一下，一家大型的图书馆。在这座图书馆里，有无数个书架，每个书架上都整齐地排列着一行行的书籍。如果你想找到一本特定的书，你需要知道它在哪个书架上，以及它在这个书架上的具体位置。在这里，书架就像是一个一维数组，它代表这本书的“行”位置，而书架上的每个位置就像是一维数组中的一个元素，代表这本书的“列”位置。把这个概念扩展到二维，你实际上就有了一大堆书架，且每个书架都有自己的书籍排列，构成了一个二维数组。 在 C++ 中，一个二维数组就像这个图书馆。你可以想象它为一个大表格，表格里有很多行（书架）和列（书本）。就像在图书馆你需要行和列的信息来找到一本书一样，你在 C++ 的二维数组中需要两个坐标：一个代表行的索引和一个代表列的索引。用代码来说，如果你有一个名为 bookshelves 的二维数组，bookshelves[3][2] 就像是在图书馆中跑到第四个书架上，然后拿起了这个书架上从左边数的第三本书。 使用二维数组时，每个维度都可以想象成是数组中的一个级别。第一个维度通常代表“行”，就像书架一样；而第二个维度代表“列”，就像书本在书架上的摆放。同样，在 C++ 中，如果你创建了一个二维数组 int seats[2][3]，可以想象这是一个拥有两排（2 行）和每排三个座位（3 列）的小型电影院。 让我们构建一个关于图书馆的书架的例子。我们会创建一个包含书架和书籍的二维数组，并且尝试访问其中一个特定的书籍。 #include &amp;lt;iostream&amp;gt; int main() { // 创建一个有 4 个书架的图书馆，每个书架可以存放 5 本书 std::string library[4][5] = { {&quot;Book1-1&quot;, &quot;Book1-2&quot;, &quot;Book1-3&quot;, &quot;Book1-4&quot;, &quot;Book1-5&quot;}, {&quot;Book2-1&quot;, &quot;Book2-2&quot;, &quot;Book2-3&quot;, &quot;Book2-4&quot;, &quot;Book2-5&quot;}, {&quot;Book3-1&quot;, &quot;Book3-2&quot;, &quot;Book3-3&quot;, &quot;Book3-4&quot;, &quot;Book3-5&quot;}, {&quot;Book4-1&quot;, &quot;Book4-2&quot;, &quot;Book4-3&quot;, &quot;Book4-4&quot;, &quot;Book4-5&quot;} }; // 想找到第 3 个书架上的第 2 本书 int shelf = 2; // 由于数组索引从 0 开始，第 3 个书架其索引是 2 int book = 1; // 同样地，第 2 本书的索引是 1 std::cout &amp;lt;&amp;lt; &quot;Book at shelf &quot; &amp;lt;&amp;lt; shelf + 1 &amp;lt;&amp;lt; &quot;, position &quot; &amp;lt;&amp;lt; book + 1 &amp;lt;&amp;lt; &quot;: &quot;; std::cout &amp;lt;&amp;lt; library[shelf][book] &amp;lt;&amp;lt; std::endl; return 0; } 操场上的方阵 想象一个宽阔的操场，在特别的活动日上，学校的学生们被安排成一个完美的方阵形式进行表演。每个学生站在操场的一个特定位置上，一排排的学生形成了横行，一列列则形成了纵列。这和C++中的二维数组非常相似。 如果我们将这个操场抽象成一个二维数组，那么每一行学生可以看作是数组的一行，每一列学生就是数组的一列。当我们指涉“操场上的方阵”时，我们实际上是在说一个由行(row)和列(column)组成的结构。 以 C++ 中的数组表示，如果操场上的方阵用变量 students 来代表，那么 students[2][3] 就代表着第三排的第四个学生。这是因为，在编程中，索引是从零开始的。所以，students[0][0] 表示的是第一排的第一个学生，而 students[2][3] 则定位在第三排的第四个学生。 使用这个类比，二维数组的概念变得生动且具象化。学生们站成的方阵就如同一个表格，里面的每个位置既有行的坐标也有列的坐标。我们可以轻松地通过这两个坐标找到任意一个特定的学生，就像我们在 C++ 中使用行索引和列索引来访问数组元素那样简单。 示例如下： #include &amp;lt;iostream&amp;gt; int main() { // 设定一个学生方阵，3 行 4 列 std::string students[3][4] = { {&quot;Alice&quot;, &quot;Bob&quot;, &quot;Charlie&quot;, &quot;David&quot;}, {&quot;Eva&quot;, &quot;Frank&quot;, &quot;Grace&quot;, &quot;Helen&quot;}, {&quot;Irene&quot;, &quot;Jack&quot;, &quot;Kathy&quot;, &quot;Leo&quot;} }; // 想找到第 3 排的第 4 个学生 int row = 2; // 第 3 排的索引是 2 int col = 3; // 第 4 个学生的索引是 3 std::cout &amp;lt;&amp;lt; &quot;Student at row &quot; &amp;lt;&amp;lt; row + 1 &amp;lt;&amp;lt; &quot;, column &quot; &amp;lt;&amp;lt; col + 1 &amp;lt;&amp;lt; &quot;: &quot;; std::cout &amp;lt;&amp;lt; students[row][col] &amp;lt;&amp;lt; std::endl; return 0; } 现在我们使用两层嵌套循环来模拟每个学生轮流报出自己名字的情景。外层循环将遍历每一排（二维数组的第一个维度），而内层循环将遍历每一排中的每个学生（二维数组的第二个维度）。 下面是示例代码： #include &amp;lt;iostream&amp;gt; int main() { // 定义了一个 3 行 4 列的学生方阵 std::string students[3][4] = { {&quot;Alice&quot;, &quot;Bob&quot;, &quot;Charlie&quot;, &quot;David&quot;}, {&quot;Eva&quot;, &quot;Frank&quot;, &quot;Grace&quot;, &quot;Helen&quot;}, {&quot;Irene&quot;, &quot;Jack&quot;, &quot;Kathy&quot;, &quot;Leo&quot;} }; // 外层循环遍历操场上的每一排（行） for (int row = 0; row &amp;lt; 3; ++row) { // 内层循环遍历每排（行）的每个学生（列） for (int col = 0; col &amp;lt; 4; ++col) { // 输出当前学生的名字，并行报数 std::cout &amp;lt;&amp;lt; &quot;Student at row &quot; &amp;lt;&amp;lt; row + 1 &amp;lt;&amp;lt; &quot;, column &quot; &amp;lt;&amp;lt; col + 1 &amp;lt;&amp;lt; &quot; is: &quot;; std::cout &amp;lt;&amp;lt; students[row][col] &amp;lt;&amp;lt; std::endl; } } return 0; } 当这段代码执行时，它将逐个访问二维数组 students 中的每个元素。row 和 col 变量分别表示当前遍历到的行索引和列索引。在数组里，行和列的索引都是从 0 开始计数的，所以第一个学生的位置是 students[0][0]。每访问到一个学生，程序都会输出学生所在的行和列，以及学生的名字。这个过程会重复进行直到数组中的所有学生都被访问一次，仿佛每个学生轮流报出自己的名字。 二维数组的特点 像个格子状的表格：二维数组就像是一个Excel表格，有行有列。想象一下，你在看一个足球队的排名表，上面有不同的队伍（行）和他们在每个赛季的得分（列）。 由一维数组组成：每一行（或者说每个书架）其实就是一个一维数组。正如图书馆中的每个书架都放着一排书一样，这些一维数组合在一起就形成了一个二维数组。 通过两个索引来访问：想找到特定的信息，比如书架上的某一本书，你需要两个索引：一个代表书架的行，另一个代表书的列。这跟你在游乐园地图里找厕所是一个道理，你需要知道它在哪个区域的哪个位置。 存储相同类型的元素：每个格子（或者学生的位置）里存放的元素都是同一类型的。比如，整个学生方阵里的每个位置都填着学生的名字。 固定的行和列大小：通常，当你定义了一个二维数组，你就固定了它的行数和列数。这就跟买衣服一样，一旦标签上写的是中号，你就不能随意把它拉伸成大号。 可以用循环遍历：你可以使用两层循环来遍历二维数组的每个元素。就像在学校操场的方阵练习中，教练会从第一个学生开始检查，一列一列地走过去，确保每个学生都在正确的位置。 动态和静态都行：虽然我们上面的例子用的是静态数组，也就是在编译时就固定大小的数组，但C++也允许创建动态的二维数组，那种可以在程序运行时确定大小的数组。这就像你决定在家里搭一个书架，随时可以根据需要添加新的层。 初始化时可选：在创建二维数组时，你可以选择是否立即填满它。就像买了一个书架，你可以先放几本你最爱的书，也可以一次性把它装满。 可以嵌套多层：二维数组的概念可以扩展到三维、四维，以此类推，每增加一个维度就像是再增加一个维度的索引。这就有点像三维电影，你不仅知道角色的左右和上下位置，还可感受到他们离你有多远。 典型的应用场景 游戏开发中的棋盘和地图设计：在游戏设计领域，二维数组是构建棋盘和各类游戏地图的理想工具。比如说，一个国际象棋游戏就可以用一个8x8的数组来表示。开发者可以使用二维数组来跟踪每个棋子的位置，判断移动是否合法，以及保存游戏的状态。 电子表格的数据存储：我们都知道微软的Excel或谷歌表格都是处理表格数据的利器。在幕后，这些数据通常以二维数组的形式存储，这样可以轻易地通过行和列来访问每一个数据单元。这就像我们前面提到的足球队排名表，有清晰的行（队伍）和列（赛季得分）。 图像处理应用：图像实际上可以被视为一个二维数组，每个元素代表图片中的一个像素点。在图像处理应用中，二维数组被用来存储和操作像素值，进行图片编辑，诸如滤镜、旋转、缩放等操作。 社交网络分析：在社交网络分析中，二维数组可能被用来表示用户之间的关系。例如，数组的行和列都可以代表不同的用户，而数组中的值可以表示一对用户之间的关系状态，如好友、屏蔽或者关注。 矩阵计算在科学中的应用：在物理、工程和计算机科学等领域，矩阵是一种基本的数学工具，通常用二维数组来表示。它们用于描述和模拟复杂的系统，例如天气模型、飞机设计模拟或者在量子计算中的状态变换。 存储表结构数据：在软件开发中，不少情况下需要处理和存储来自数据库的表结构数据。二维数组提供了一个便利的方式来缓存这些数据，供程序处理和显示。 教育工具中的示范和实践：在编程教学中，二维数组是一个很好的教学工具。它可以帮助学生们更好地理解数据的组织方式和多维数据结构。比如，可以通过二维数组教导学生如何进行棋类游戏编程，或者创建简单的地图应用等。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">如何更通俗易懂的解释 C++ 内存分配</title>
      
      
      <link href="https://blog.talkincode.net/2024/03/21/CPP-Memory-Allocation-Explained/" rel="alternate" type="text/html" title="如何更通俗易懂的解释 C++ 内存分配" />
      
      <published>2024-03-21T06:15:00+00:00</published>
      <updated>2024-03-21T06:15:00+00:00</updated>
      <id>https://blog.talkincode.net/2024/03/21/CPP-Memory-Allocation-Explained</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/03/21/CPP-Memory-Allocation-Explained/">&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/jamiesun/images/master/default/xrzjGp.jpg&quot; alt=&quot;xrzjGp&quot; /&gt;&lt;/p&gt;

&lt;p&gt;想象一下有一家五星级酒店，程序则是这家酒店的客人。C++内存分配基本上就是确定程序中的每个变量或对象在酒店的哪个房间住下。&lt;/p&gt;

&lt;p&gt;在 C++的世界里，内存分配就像是分配酒店房间一样。这家酒店有几种类型的房间：自动房间（栈）、动态房间（堆）、共享空间（静态存储区），还有专用 VIP 区（寄存器）。每种房型都有其特点和用途，客人（程序）根据需要选择房型。&lt;/p&gt;

&lt;h2&gt;自动房间（栈 Stack）&lt;/h2&gt;

&lt;p&gt;栈是提供速度快速的服务，适合快速住宿的客人。当你创建一个局部变量时，C++会自动分配一个栈房间给它，这就像走进酒店大堂，告诉前台你需要一个房间，然后工作人员马上给你安排一个房间那样方便。但要注意，栈上的房间不能随意调整大小，你带的行李必须能够适应房间的大小，并且当你离开时，房间就会立刻清空给下一位客人使用。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;专业解释： 栈是一种先入后出（LIFO）的内存结构，用于存储局部变量和函数调用的控制信息。在C++中，当函数被调用时，函数参数和局部变量会在栈上分配空间，且这一分配过程是自动的，编译器会为我们管理这些内存。内存的分配与释放速度极快，但栈的大小通常是有限制的，且不易调整。一旦函数执行完成，其栈帧（对应的内存块）就会被销毁，相关的内存空间被释放。这种自管理特性意味着栈内存通常不会引起内存泄漏问题。然而，栈的空间有限，对大量数据的存储或者复杂数据结构的创建可能不够用，在这些情况下，通常会选择堆内存分配。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// &apos;a&apos; 存储在栈上&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;&apos;x&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// &apos;b&apos; 也存储在栈上&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 当foo函数被调用时, &apos;a&apos; 和 &apos;b&apos; 被分配在栈上.&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 当foo函数返回时, &apos;a&apos; 和 &apos;b&apos; 被自动释放.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;动态房间（堆）&lt;/h2&gt;

&lt;p&gt;堆内存像是酒店的长期套房，适合那些需要自定义服务和长期住宿的客人。当你的需求变化多端，需要更多的空间或者要住得更久时，你可以请求一个堆房间。这就像是你向酒店提出特殊要求，他们为你找到一个合适的房间，大小和住宿时长都是你自己定的。不过，不要忘了在离开时退房（释放内存），否则这个房间就会一直空着，造成空间浪费。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;专业解释：堆内存是由程序运行时动态分配的一块内存区域，提供了灵活的内存大小配置和生命周期管理。不同于栈内存的自动分配和释放，堆内存的分配通常通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new&lt;/code&gt; 操作符，在 C++ 中进行，而释放则通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delete&lt;/code&gt; 操作符。堆内存适合存储生命周期长于函数调用或者大小超过栈限制的数据。尽管堆提供了更大的灵活性，其管理却完全依赖于程序员，这意味着必须显式地分配和释放内存，以防止内存泄漏或野指针的问题。堆的动态特性允许程序在运行时根据需要扩展或缩减数据结构，但这也意味着相比于栈操作，堆内存分配和释放的过程相对缓慢，且容易产生内存碎片。因此，专业的开发者需要权衡使用堆内存的时机，以兼顾性能和灵活性。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 动态分配单个整数的内存&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 给动态分配的整数赋值&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 输出动态分配的整数的值&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Value of dynamic integer: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 释放之前分配的内存&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 重要：将指针设置为NULL，避免野指针&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;共享空间（静态存储区）&lt;/h2&gt;

&lt;p&gt;静态存储区就像是酒店的共享会议室，可以被任何人使用，并且一直保持着开放状态。这部分内存用于存放全局变量和静态变量，一旦分配，在程序的整个生命周期内都是有效的。这类似于你在酒店预订了一个共享空间，无论你在不在，空间都会一直为你保留，并且在你整个逗留期间都可以使用。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;专业解释：静态存储区是程序运行期间持续存在的内存部分，用来存储程序的全局变量和静态变量；一旦这些变量被初始化，它们会在程序的整个生命周期内保持分配状态，直到程序终止。这种存储方式保证了变量的值在函数调用之间是持久的，不会像自动存储的局部变量那样在其作用域结束时失效。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// 静态存储区的简单使用示例&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// 全局变量 - 存储在静态存储区&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;globalVariable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 静态局部变量 - 也存储在静态存储区&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;staticLocalExample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;staticLocalVariable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Static local variable: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;staticLocalVariable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;staticLocalVariable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Global variable: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;globalVariable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// 调用函数，显示静态局部变量的值&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;staticLocalExample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 输出: Static local variable: 50&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;staticLocalExample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 输出: Static local variable: 51&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 再次显示全局变量的值&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 它在整个程序执行期间保持不变，除非被修改&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Global variable: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;globalVariable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;专用 VIP 区（寄存器）&lt;/h2&gt;

&lt;p&gt;寄存器是最快速的房间，像是酒店的特快专用通道。这些内存非常有限，只用于存储最频繁访问的数据。不是所有客人都能住在这里，只有 VIP（非常重要的程序部件）才有资格。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;专业解释： 寄存器是 CPU 内的非常小但速度极快的数据存储区域，用于存储那些需要被快速访问和处理的操作数和指令。在程序执行过程中，最常用的变量和最频繁执行的计算结果往往被放置在寄存器中，以提高程序的执行效率。寄存器的数量和大小是固定的，由 CPU 架构决定。编译器通常会在编译过程中进行寄存器分配优化，以确保重要的计算可以尽可能地利用这些高速内存资源。由于寄存器的高速特性，它们通常用于实现快速的算术运算、函数调用的参数传递和局部变量存储，但受限于数量，它们不能用于大量数据的存储。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// 寄存器存储示例 - 适用于理解基础概念，实际中寄存器的分配由编译器优化决定&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;register&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fastVariable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 建议编译器尽可能将 &apos;fastVariable&apos; 存储在寄存器中&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;The value of register variable: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fastVariable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;// 由于 &apos;fastVariable&apos; 可能存储在寄存器中，我们不能获取它的内存地址&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// 下面的代码如果取消注释, 将会导致编译错误:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// std::cout &amp;lt;&amp;lt; &quot;The address of register variable: &quot; &amp;lt;&amp;lt; &amp;amp;fastVariable &amp;lt;&amp;lt; std::endl;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 输出: The value of register variable: 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在这个示例中，变量 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fastVariable&lt;/code&gt; 被建议存储在寄存器中，以便快速访问。关键字 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;register&lt;/code&gt; 是向编译器的一个建议，告诉它我们希望这个变量能够存放在寄存器中。然而，是不是真的会被存放在寄存器中，以及哪一个寄存器会被使用，取决于编译器的优化决策。&lt;/p&gt;

&lt;p&gt;请注意，在现代C++编译器中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;register&lt;/code&gt; 关键字基本上已经过时，因为现代编译器的优化算法足够智能，能够自主决定哪些变量应该存储在寄存器中。实际编码时，我们很少（如果不是从不）需要手动指示编译器使用寄存器，因为编译器会为我们做出最优决策。&lt;/p&gt;

&lt;h2&gt;现实中的 C++内存管家&lt;/h2&gt;

&lt;p&gt;要成为 C++的内存管家，你必须理解每种房型的规则：栈是自动的，快速但有限制；堆是灵活的，但需要手动管理；静态是持久的，但是共享的；而寄存器是最快的，却也是最稀缺的资源。你要做的就是正确地分配这些房间，确保程序的客人有一个舒适的住宿体验！&lt;/p&gt;

&lt;h2&gt;扩展思考&lt;/h2&gt;

&lt;p&gt;在探究如何高效利用C++进行内存分配时，以下一系列的问题有助于您深入思考与理解：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;C++中内存分配的基本机制包括哪些？&lt;/li&gt;
  &lt;li&gt;如何在C++中正确区分和使用栈（stack）和堆（heap）内存分配？&lt;/li&gt;
  &lt;li&gt;C++中的new和delete操作符如何工作，它们与malloc和free函数有何异同？&lt;/li&gt;
  &lt;li&gt;您是如何保证C++程序中动态分配内存的安全性与效率的？&lt;/li&gt;
  &lt;li&gt;C++标准库中提供了哪些内存管理器（如std::allocator）来辅助内存分配，它们的运作原理是什么？&lt;/li&gt;
  &lt;li&gt;C++中智能指针（如std::unique_ptr, std::shared_ptr等）是如何帮助管理内存分配与释放的？&lt;/li&gt;
  &lt;li&gt;如何检测和避免C++中常见的内存问题，比如内存泄漏和野指针？&lt;/li&gt;
  &lt;li&gt;当使用C++编写多线程程序时，如何管理内存分配以避免竞争条件和死锁？&lt;/li&gt;
  &lt;li&gt;C++中的内存池是什么，使用它们可以带来哪些性能上的优势？&lt;/li&gt;
  &lt;li&gt;现代C++标准（例如C++11及之后的版本）对内存分配和管理带来了哪些新特性和改进？&lt;/li&gt;
&lt;/ul&gt;</content>

      
      
      
      
      

      

      
        <category term="c++" />
      
        <category term="memory-allocation" />
      

      

      
        <summary type="html">想象一下有一家五星级酒店，程序则是这家酒店的客人。C++内存分配基本上就是确定程序中的每个变量或对象在酒店的哪个房间住下。 在 C++的世界里，内存分配就像是分配酒店房间一样。这家酒店有几种类型的房间：自动房间（栈）、动态房间（堆）、共享空间（静态存储区），还有专用 VIP 区（寄存器）。每种房型都有其特点和用途，客人（程序）根据需要选择房型。 自动房间（栈 Stack） 栈是提供速度快速的服务，适合快速住宿的客人。当你创建一个局部变量时，C++会自动分配一个栈房间给它，这就像走进酒店大堂，告诉前台你需要一个房间，然后工作人员马上给你安排一个房间那样方便。但要注意，栈上的房间不能随意调整大小，你带的行李必须能够适应房间的大小，并且当你离开时，房间就会立刻清空给下一位客人使用。 专业解释： 栈是一种先入后出（LIFO）的内存结构，用于存储局部变量和函数调用的控制信息。在C++中，当函数被调用时，函数参数和局部变量会在栈上分配空间，且这一分配过程是自动的，编译器会为我们管理这些内存。内存的分配与释放速度极快，但栈的大小通常是有限制的，且不易调整。一旦函数执行完成，其栈帧（对应的内存块）就会被销毁，相关的内存空间被释放。这种自管理特性意味着栈内存通常不会引起内存泄漏问题。然而，栈的空间有限，对大量数据的存储或者复杂数据结构的创建可能不够用，在这些情况下，通常会选择堆内存分配。 void foo() { int a = 10; // &apos;a&apos; 存储在栈上 char b = &apos;x&apos;; // &apos;b&apos; 也存储在栈上 } int main() { foo(); // 当foo函数被调用时, &apos;a&apos; 和 &apos;b&apos; 被分配在栈上. // 当foo函数返回时, &apos;a&apos; 和 &apos;b&apos; 被自动释放. return 0; } 动态房间（堆） 堆内存像是酒店的长期套房，适合那些需要自定义服务和长期住宿的客人。当你的需求变化多端，需要更多的空间或者要住得更久时，你可以请求一个堆房间。这就像是你向酒店提出特殊要求，他们为你找到一个合适的房间，大小和住宿时长都是你自己定的。不过，不要忘了在离开时退房（释放内存），否则这个房间就会一直空着，造成空间浪费。 专业解释：堆内存是由程序运行时动态分配的一块内存区域，提供了灵活的内存大小配置和生命周期管理。不同于栈内存的自动分配和释放，堆内存的分配通常通过 new 操作符，在 C++ 中进行，而释放则通过 delete 操作符。堆内存适合存储生命周期长于函数调用或者大小超过栈限制的数据。尽管堆提供了更大的灵活性，其管理却完全依赖于程序员，这意味着必须显式地分配和释放内存，以防止内存泄漏或野指针的问题。堆的动态特性允许程序在运行时根据需要扩展或缩减数据结构，但这也意味着相比于栈操作，堆内存分配和释放的过程相对缓慢，且容易产生内存碎片。因此，专业的开发者需要权衡使用堆内存的时机，以兼顾性能和灵活性。 #include &amp;lt;iostream&amp;gt; int main() { // 动态分配单个整数的内存 int *ptr = new int; // 给动态分配的整数赋值 *ptr = 42; // 输出动态分配的整数的值 std::cout &amp;lt;&amp;lt; &quot;Value of dynamic integer: &quot; &amp;lt;&amp;lt; *ptr &amp;lt;&amp;lt; std::endl; // 释放之前分配的内存 delete ptr; // 重要：将指针设置为NULL，避免野指针 ptr = nullptr; return 0; } 共享空间（静态存储区） 静态存储区就像是酒店的共享会议室，可以被任何人使用，并且一直保持着开放状态。这部分内存用于存放全局变量和静态变量，一旦分配，在程序的整个生命周期内都是有效的。这类似于你在酒店预订了一个共享空间，无论你在不在，空间都会一直为你保留，并且在你整个逗留期间都可以使用。 专业解释：静态存储区是程序运行期间持续存在的内存部分，用来存储程序的全局变量和静态变量；一旦这些变量被初始化，它们会在程序的整个生命周期内保持分配状态，直到程序终止。这种存储方式保证了变量的值在函数调用之间是持久的，不会像自动存储的局部变量那样在其作用域结束时失效。 // 静态存储区的简单使用示例 #include &amp;lt;iostream&amp;gt; // 全局变量 - 存储在静态存储区 int globalVariable = 10; // 静态局部变量 - 也存储在静态存储区 void staticLocalExample() { static int staticLocalVariable = 50; std::cout &amp;lt;&amp;lt; &quot;Static local variable: &quot; &amp;lt;&amp;lt; staticLocalVariable &amp;lt;&amp;lt; std::endl; staticLocalVariable++; } int main() { std::cout &amp;lt;&amp;lt; &quot;Global variable: &quot; &amp;lt;&amp;lt; globalVariable &amp;lt;&amp;lt; std::endl; // 调用函数，显示静态局部变量的值 staticLocalExample(); // 输出: Static local variable: 50 staticLocalExample(); // 输出: Static local variable: 51 // 再次显示全局变量的值 // 它在整个程序执行期间保持不变，除非被修改 std::cout &amp;lt;&amp;lt; &quot;Global variable: &quot; &amp;lt;&amp;lt; globalVariable &amp;lt;&amp;lt; std::endl; return 0; } 专用 VIP 区（寄存器） 寄存器是最快速的房间，像是酒店的特快专用通道。这些内存非常有限，只用于存储最频繁访问的数据。不是所有客人都能住在这里，只有 VIP（非常重要的程序部件）才有资格。 专业解释： 寄存器是 CPU 内的非常小但速度极快的数据存储区域，用于存储那些需要被快速访问和处理的操作数和指令。在程序执行过程中，最常用的变量和最频繁执行的计算结果往往被放置在寄存器中，以提高程序的执行效率。寄存器的数量和大小是固定的，由 CPU 架构决定。编译器通常会在编译过程中进行寄存器分配优化，以确保重要的计算可以尽可能地利用这些高速内存资源。由于寄存器的高速特性，它们通常用于实现快速的算术运算、函数调用的参数传递和局部变量存储，但受限于数量，它们不能用于大量数据的存储。 // 寄存器存储示例 - 适用于理解基础概念，实际中寄存器的分配由编译器优化决定 #include &amp;lt;iostream&amp;gt; int main() { register int fastVariable = 10; // 建议编译器尽可能将 &apos;fastVariable&apos; 存储在寄存器中 std::cout &amp;lt;&amp;lt; &quot;The value of register variable: &quot; &amp;lt;&amp;lt; fastVariable &amp;lt;&amp;lt; std::endl; // 由于 &apos;fastVariable&apos; 可能存储在寄存器中，我们不能获取它的内存地址 // 下面的代码如果取消注释, 将会导致编译错误: // std::cout &amp;lt;&amp;lt; &quot;The address of register variable: &quot; &amp;lt;&amp;lt; &amp;amp;fastVariable &amp;lt;&amp;lt; std::endl; return 0; } // 输出: The value of register variable: 10 在这个示例中，变量 fastVariable 被建议存储在寄存器中，以便快速访问。关键字 register 是向编译器的一个建议，告诉它我们希望这个变量能够存放在寄存器中。然而，是不是真的会被存放在寄存器中，以及哪一个寄存器会被使用，取决于编译器的优化决策。 请注意，在现代C++编译器中，register 关键字基本上已经过时，因为现代编译器的优化算法足够智能，能够自主决定哪些变量应该存储在寄存器中。实际编码时，我们很少（如果不是从不）需要手动指示编译器使用寄存器，因为编译器会为我们做出最优决策。 现实中的 C++内存管家 要成为 C++的内存管家，你必须理解每种房型的规则：栈是自动的，快速但有限制；堆是灵活的，但需要手动管理；静态是持久的，但是共享的；而寄存器是最快的，却也是最稀缺的资源。你要做的就是正确地分配这些房间，确保程序的客人有一个舒适的住宿体验！ 扩展思考 在探究如何高效利用C++进行内存分配时，以下一系列的问题有助于您深入思考与理解： C++中内存分配的基本机制包括哪些？ 如何在C++中正确区分和使用栈（stack）和堆（heap）内存分配？ C++中的new和delete操作符如何工作，它们与malloc和free函数有何异同？ 您是如何保证C++程序中动态分配内存的安全性与效率的？ C++标准库中提供了哪些内存管理器（如std::allocator）来辅助内存分配，它们的运作原理是什么？ C++中智能指针（如std::unique_ptr, std::shared_ptr等）是如何帮助管理内存分配与释放的？ 如何检测和避免C++中常见的内存问题，比如内存泄漏和野指针？ 当使用C++编写多线程程序时，如何管理内存分配以避免竞争条件和死锁？ C++中的内存池是什么，使用它们可以带来哪些性能上的优势？ 现代C++标准（例如C++11及之后的版本）对内存分配和管理带来了哪些新特性和改进？</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">未来货币的进化：山姆-奥特曼洞察AI的潜能与风险</title>
      
      
      <link href="https://blog.talkincode.net/2024/03/20/AI-Potential-Risks/" rel="alternate" type="text/html" title="未来货币的进化：山姆-奥特曼洞察AI的潜能与风险" />
      
      <published>2024-03-20T01:08:24+00:00</published>
      <updated>2024-03-20T01:08:24+00:00</updated>
      <id>https://blog.talkincode.net/2024/03/20/AI-Potential-Risks</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/03/20/AI-Potential-Risks/">&lt;iframe width=&quot;740&quot; height=&quot;423&quot; src=&quot;https://www.youtube.com/embed/jvqFAi7vkBc?si=zV86-Y9nfOTvVaXq&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;blockquote&gt;
  &lt;p&gt;在这场与萨姆·奥特曼的对话中，他分享了对计算力作为未来货币的看法，预测到本世纪末我们可能会见证制造出极其出色的系统。他认为，AGI的发展可能伴随着全球范围内的巨大权力斗争，并提到了去年与Openai董事会的严峻经历，这是他职业生涯中最艰难的时刻之一，同时也是一个有教育意义的挑战。这场闹剧让他对人们的信任产生了质疑，但他也从中感受到了爱和支持。他对公司未来的董事会结构和组织架构提出了一些思考，并坚信个人不应对AGI或公司拥有绝对控制。&lt;/p&gt;

  &lt;p&gt;此外，萨姆讨论了Openai对机器人工作的历史和SOAR项目的能力，以及它对仿真世界的生成能力意味着我们可能处在一个仿真中的可能性。此次对话还涉及了对《创新宝典》的评价、谷歌GeminAI的问题、全球对信息获取方式的期待变化以及对AGI的愿景。他坚持认为，应在全球范围内建立针对AGI的治理体系，避免任何一个人或公司对其拥有太多控制权。尽管未来存在可能的危险，但萨姆对人类通过科技进步共同创造未来持乐观态度。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;未来，我们如何定义货币的价值和存在？当我们探讨这一议题时，我们不得不考虑计算作为一种资源的无限潜能。山姆·奥特曼最近对此有着深刻的见解和预见，认为计算将成为未来货币的基础，这不是毫无根据的臆想。随着技术的迅猛发展，尤其是人工智能领域的突破性进展，我们有理由相信，计算能力所代表的实际价值正以我们之前无法想象的速度增长。&lt;/p&gt;

&lt;p&gt;目前，我们已经目睹了计算能力在增强型技术中的关键作用，如山姆所领导的OpenAI所示。GPT-4，该公司的先进AI模型，不仅在技术社区内掀起了波澜，更是向我们展示了计算潜力的未来图景。这一技术的影响早已超出纯粹的应用层面，逐步渗透到经济、社会及文化各个方面。人工智能已不再是辅助工具，而是正在成为创新和增长的核心动力。&lt;/p&gt;

&lt;p&gt;更值得关注的是，山姆将计算比作是最珍贵的商品，这一点值得我们深思。从历史上看，货币的价值往往与某种稀有资源相关，例如黄金。但在数字化和全球信息化时代，计算能力的扩张和突破似乎预示着一种新的货币标准的来临。在这个即将到来的时代，数据和算法可能会成为新的“黄金标准”。&lt;/p&gt;

&lt;p&gt;然而，随着计算力成为一种主导资源，一系列实质性的风险和挑战也随之涌现。首先，我们必须面对计算带来的巨大能量开销。山姆提到核能作为一个潜在的能源解决方案，但这同样伴随着公众接受度和安全风险的考量。此外，随着计算能力的升级，我们如何确保其在不同群体之间的平等可访问性，避免加剧现有的社会不平等，这是另外一个必须关注的领域。&lt;/p&gt;

&lt;p&gt;在道德和监管层面，对AI的忧虑同样不容轻视。山姆本人对于AI安全的考虑体现了对这一问题的深度关注，这一问题不仅关乎技术本身，更触及集体意识和社会共识。如何在迎接计算能力带来的诸多机遇的同时，确保我们遵循的是可持续和负责任的发展路径，将是所有参与者的共同课题。&lt;/p&gt;

&lt;p&gt;最终，我们将如何适应这个可能的未来——一个计算成为最核心资源的未来？这将要求我们在众多领域进行创新，不仅仅是技术，还包括法律、伦理和社会结构。我们的经济体系、教育系统、甚至我们的全球政治结构可能都需要进行重大调整。尽管这一未来充满不确定性，但它也提供了无数创新和成长的机会。只有通过共同努力，我们才能确保计算作为未来货币所承载的潜力能够以最负责任、最具包容性的方式实现。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="AI" />
      
        <category term="Future" />
      
        <category term="Economy" />
      

      
        <category term="AI" />
      
        <category term="Future" />
      
        <category term="Economy" />
      

      
        <summary type="html">在这场与萨姆·奥特曼的对话中，他分享了对计算力作为未来货币的看法，预测到本世纪末我们可能会见证制造出极其出色的系统。他认为，AGI的发展可能伴随着全球范围内的巨大权力斗争，并提到了去年与Openai董事会的严峻经历，这是他职业生涯中最艰难的时刻之一，同时也是一个有教育意义的挑战。这场闹剧让他对人们的信任产生了质疑，但他也从中感受到了爱和支持。他对公司未来的董事会结构和组织架构提出了一些思考，并坚信个人不应对AGI或公司拥有绝对控制。 此外，萨姆讨论了Openai对机器人工作的历史和SOAR项目的能力，以及它对仿真世界的生成能力意味着我们可能处在一个仿真中的可能性。此次对话还涉及了对《创新宝典》的评价、谷歌GeminAI的问题、全球对信息获取方式的期待变化以及对AGI的愿景。他坚持认为，应在全球范围内建立针对AGI的治理体系，避免任何一个人或公司对其拥有太多控制权。尽管未来存在可能的危险，但萨姆对人类通过科技进步共同创造未来持乐观态度。 未来，我们如何定义货币的价值和存在？当我们探讨这一议题时，我们不得不考虑计算作为一种资源的无限潜能。山姆·奥特曼最近对此有着深刻的见解和预见，认为计算将成为未来货币的基础，这不是毫无根据的臆想。随着技术的迅猛发展，尤其是人工智能领域的突破性进展，我们有理由相信，计算能力所代表的实际价值正以我们之前无法想象的速度增长。 目前，我们已经目睹了计算能力在增强型技术中的关键作用，如山姆所领导的OpenAI所示。GPT-4，该公司的先进AI模型，不仅在技术社区内掀起了波澜，更是向我们展示了计算潜力的未来图景。这一技术的影响早已超出纯粹的应用层面，逐步渗透到经济、社会及文化各个方面。人工智能已不再是辅助工具，而是正在成为创新和增长的核心动力。 更值得关注的是，山姆将计算比作是最珍贵的商品，这一点值得我们深思。从历史上看，货币的价值往往与某种稀有资源相关，例如黄金。但在数字化和全球信息化时代，计算能力的扩张和突破似乎预示着一种新的货币标准的来临。在这个即将到来的时代，数据和算法可能会成为新的“黄金标准”。 然而，随着计算力成为一种主导资源，一系列实质性的风险和挑战也随之涌现。首先，我们必须面对计算带来的巨大能量开销。山姆提到核能作为一个潜在的能源解决方案，但这同样伴随着公众接受度和安全风险的考量。此外，随着计算能力的升级，我们如何确保其在不同群体之间的平等可访问性，避免加剧现有的社会不平等，这是另外一个必须关注的领域。 在道德和监管层面，对AI的忧虑同样不容轻视。山姆本人对于AI安全的考虑体现了对这一问题的深度关注，这一问题不仅关乎技术本身，更触及集体意识和社会共识。如何在迎接计算能力带来的诸多机遇的同时，确保我们遵循的是可持续和负责任的发展路径，将是所有参与者的共同课题。 最终，我们将如何适应这个可能的未来——一个计算成为最核心资源的未来？这将要求我们在众多领域进行创新，不仅仅是技术，还包括法律、伦理和社会结构。我们的经济体系、教育系统、甚至我们的全球政治结构可能都需要进行重大调整。尽管这一未来充满不确定性，但它也提供了无数创新和成长的机会。只有通过共同努力，我们才能确保计算作为未来货币所承载的潜力能够以最负责任、最具包容性的方式实现。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Apple mlx框架及Sounddevice搭档Whisper, 实现语音实时识别</title>
      
      
      <link href="https://blog.talkincode.net/2024/03/13/Apple-ml5-Sounddevice-Whisper-Speech-Recognition/" rel="alternate" type="text/html" title="Apple mlx框架及Sounddevice搭档Whisper, 实现语音实时识别" />
      
      <published>2024-03-13T01:19:11+00:00</published>
      <updated>2024-03-13T01:19:11+00:00</updated>
      <id>https://blog.talkincode.net/2024/03/13/Apple-ml5-Sounddevice-Whisper-Speech-Recognition</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/03/13/Apple-ml5-Sounddevice-Whisper-Speech-Recognition/">&lt;p&gt;在本文中，我们将探索通过结合Apple的mlx框架和Sounddevice库与OpenAI创造的Whisper模型，如何实现实时语音识别的功能。我们将看到这一过程的核心代码，并附上详细解释和注释。这样的技术可以应用于各种语音到文本场景中，如自动字幕生成、语音助手、实时会议记录等。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;注意，这里使用的 whisper 并非 openai-whisper， 而是来自 Apple 封装厚的 &lt;a href=&quot;https://github.com/ml-explore/mlx-examples&quot;&gt;whisper&lt;/a&gt;&lt;/p&gt;

  &lt;p&gt;为什么没有使用 pyaudio： 在使用 pyaudio 时遇到了一点小问题， pyaudio 对 apple arm芯片支持的不够完美，很容易出错&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;依赖的 模块&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;numba
numpy
torch
tqdm
more-itertools
&lt;span class=&quot;nv&quot;&gt;tiktoken&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;0.3.3
huggingface_hub
mlx
pyaudio
scipy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;mlx 模型转换&lt;/h2&gt;

&lt;p&gt;convert.py 来自 &lt;a href=&quot;https://github.com/ml-explore/mlx-examples/tree/main/whisper&quot;&gt;mlx-examples&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;medium&quot;&lt;/span&gt;
python convert.py &lt;span class=&quot;nt&quot;&gt;--torch-name-or-path&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--mlx-path&lt;/span&gt; mlx_models/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;_fp16
python convert.py &lt;span class=&quot;nt&quot;&gt;--torch-name-or-path&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--dtype&lt;/span&gt; float32 &lt;span class=&quot;nt&quot;&gt;--mlx-path&lt;/span&gt; mlx_models/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;_fp32
python convert.py &lt;span class=&quot;nt&quot;&gt;--torch-name-or-path&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--q_bits&lt;/span&gt; 4 &lt;span class=&quot;nt&quot;&gt;--mlx-path&lt;/span&gt; mlx_models/&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;_quantized_4bits

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2&gt;范例代码&lt;/h2&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# 导入必要的库
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;whisper&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;threading&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 定义一个AudioTranscriber类
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AudioTranscriber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 构造函数初始化模型路径及采样率
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model_path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;mlx_models/medium_fp16&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model_path&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sample_rate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16000&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 设置采样率为16000Hz
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;silence_threshold&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.01&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 设置静音阈值，判断时否为静音
&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 定义音频转录功能
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;transcribe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;audio_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# 使用Whisper模型转录音频数据
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;whisper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transcribe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;audio_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_or_hf_repo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Transcription: &lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 打印转录结果
&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 定义音频回调函数
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;audio_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# 转换音频数据格式以适应模型
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;audio_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;squeeze&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;astype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;float32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# 检测静音
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;audio_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;silence_threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# 创建新线程进行转录
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;threading&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;transcribe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;audio_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,)).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# 开始监听并转录音频
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;start_listening&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# 以指定的采样率打开音频输入流
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;InputStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;audio_callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;samplerate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sample_rate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;float32&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;n&quot;&gt;blocksize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sample_rate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
            &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Listening, please speak now...&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# 监听一段时间后停止
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 主函数
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;__main__&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;transcriber&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AudioTranscriber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 创建AudioTranscriber实例
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;transcriber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;start_listening&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 开始监听10秒的音频
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;以下是对上述核心代码的详细解释和注释：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;初始化Transcriber实例&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__init__&lt;/code&gt;函数设置了模型路径，采样率，和静音阈值。&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self.model_path&lt;/code&gt;用于定位存储Whisper模型的目录。&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self.sample_rate&lt;/code&gt;设定了录音的采样率为16000Hz, 这是Whisper模型要求的标准采样率。&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self.silence_threshold&lt;/code&gt;用于检测音频是否静音（音量过低）。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;实时音频转录&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transcribe&lt;/code&gt;函数调用whisper库，将实时捕获的音频数据转录成文本。&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;whisper.transcribe&lt;/code&gt;函数负责执行音频转录工作。&lt;/li&gt;
      &lt;li&gt;输出转录结果的文本。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;处理音频流&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;audio_callback&lt;/code&gt;是一个回调函数，由sounddevice库在捕获到音频帧时调用。&lt;/li&gt;
      &lt;li&gt;检查是否有错误信息，如果有，会输出到标准错误流。&lt;/li&gt;
      &lt;li&gt;把捕获的音频数据&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indata&lt;/code&gt;压缩和转换成单通道浮点数据，为模型处理做准备。&lt;/li&gt;
      &lt;li&gt;如果音频数据超出设定的静音阈值，则启动一个线程，调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transcribe&lt;/code&gt;进行实时转录。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;开始监听&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start_listening&lt;/code&gt;函数使用sounddevice库开启一个音频输入流进行监听。&lt;/li&gt;
      &lt;li&gt;音频流配置采样率为16000Hz，单通道，32位浮点数格式。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blocksize&lt;/code&gt;定义了每次处理的数据块大小。&lt;/li&gt;
      &lt;li&gt;使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sd.sleep&lt;/code&gt;函数来控制监听的持续时间。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;在上述代码的支持下，我们可以构建一个可以实时监听用户语音，并将其转录为文本的应用程序。通过多线程技术，我们保证了语音实时识别的流畅性和效率。此外，静音检测功能避免了无效数据的处理，提升了整体性能。在实践中，以上代码可以集成到各种支持Python的环境下，为用户提供即时的语音识别服务。&lt;/p&gt;

&lt;p&gt;不过缺点也是存在的，使用 threading 不是个好主意， 这个实时依然依赖于硬件的能力， 即使在满血 MacStudio 上依然有3-5秒的延时。&lt;/p&gt;

&lt;h2&gt;另一个简单的例子&lt;/h2&gt;

&lt;p&gt;这个例子简单的实现了一次识别&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;whisper&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AudioTranscriber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model_path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;mlx_models/medium_fp16&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model_path&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sample_rate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16000&lt;/span&gt; 
        
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;transcribe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Recording...&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;indata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sample_rate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;samplerate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sample_rate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;float32&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; 
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Recording stopped.&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;audio_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;squeeze&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;astype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;float32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;whisper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transcribe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;audio_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;path_or_hf_repo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Transcription: &lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;__main__&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;transcriber&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AudioTranscriber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;transcriber&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;transcribe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content>

      
      
      
      
      

      

      
        <category term="speech-recognition" />
      
        <category term="mlx" />
      
        <category term="whisper" />
      
        <category term="Sounddevice" />
      

      

      
        <summary type="html">在本文中，我们将探索通过结合Apple的mlx框架和Sounddevice库与OpenAI创造的Whisper模型，如何实现实时语音识别的功能。我们将看到这一过程的核心代码，并附上详细解释和注释。这样的技术可以应用于各种语音到文本场景中，如自动字幕生成、语音助手、实时会议记录等。 注意，这里使用的 whisper 并非 openai-whisper， 而是来自 Apple 封装厚的 whisper 为什么没有使用 pyaudio： 在使用 pyaudio 时遇到了一点小问题， pyaudio 对 apple arm芯片支持的不够完美，很容易出错 依赖的 模块 numba numpy torch tqdm more-itertools tiktoken==0.3.3 huggingface_hub mlx pyaudio scipy mlx 模型转换 convert.py 来自 mlx-examples model=&quot;medium&quot; python convert.py --torch-name-or-path ${model} --mlx-path mlx_models/${model}_fp16 python convert.py --torch-name-or-path ${model} --dtype float32 --mlx-path mlx_models/${model}_fp32 python convert.py --torch-name-or-path ${model} -q --q_bits 4 --mlx-path mlx_models/${model}_quantized_4bits 范例代码 # 导入必要的库 import numpy as np import sounddevice as sd import whisper import threading # 定义一个AudioTranscriber类 class AudioTranscriber: # 构造函数初始化模型路径及采样率 def __init__(self, model_path=&quot;mlx_models/medium_fp16&quot;): self.model_path = model_path self.sample_rate = 16000 # 设置采样率为16000Hz self.silence_threshold = 0.01 # 设置静音阈值，判断时否为静音 # 定义音频转录功能 def transcribe(self, audio_data): # 使用Whisper模型转录音频数据 result = whisper.transcribe(audio_data, path_or_hf_repo=self.model_path) print(&quot;Transcription: &quot;, result[&apos;text&apos;]) # 打印转录结果 # 定义音频回调函数 def audio_callback(self, indata, frames, time, status): if status: print(status, file=sys.stderr) # 转换音频数据格式以适应模型 audio_data = np.squeeze(indata).astype(np.float32) # 检测静音 if np.mean(np.abs(audio_data)) &amp;gt; self.silence_threshold: # 创建新线程进行转录 threading.Thread(target=self.transcribe, args=(audio_data,)).start() # 开始监听并转录音频 def start_listening(self, duration=5): # 以指定的采样率打开音频输入流 with sd.InputStream(callback=self.audio_callback, samplerate=self.sample_rate, channels=1, dtype=&apos;float32&apos;, blocksize=int(self.sample_rate * duration)): print(&quot;Listening, please speak now...&quot;) # 监听一段时间后停止 sd.sleep(duration * 1000) # 主函数 if __name__ == &quot;__main__&quot;: transcriber = AudioTranscriber() # 创建AudioTranscriber实例 transcriber.start_listening(10) # 开始监听10秒的音频 以下是对上述核心代码的详细解释和注释： 初始化Transcriber实例： __init__函数设置了模型路径，采样率，和静音阈值。 self.model_path用于定位存储Whisper模型的目录。 self.sample_rate设定了录音的采样率为16000Hz, 这是Whisper模型要求的标准采样率。 self.silence_threshold用于检测音频是否静音（音量过低）。 实时音频转录： transcribe函数调用whisper库，将实时捕获的音频数据转录成文本。 whisper.transcribe函数负责执行音频转录工作。 输出转录结果的文本。 处理音频流： audio_callback是一个回调函数，由sounddevice库在捕获到音频帧时调用。 检查是否有错误信息，如果有，会输出到标准错误流。 把捕获的音频数据indata压缩和转换成单通道浮点数据，为模型处理做准备。 如果音频数据超出设定的静音阈值，则启动一个线程，调用transcribe进行实时转录。 开始监听： start_listening函数使用sounddevice库开启一个音频输入流进行监听。 音频流配置采样率为16000Hz，单通道，32位浮点数格式。blocksize定义了每次处理的数据块大小。 使用sd.sleep函数来控制监听的持续时间。 在上述代码的支持下，我们可以构建一个可以实时监听用户语音，并将其转录为文本的应用程序。通过多线程技术，我们保证了语音实时识别的流畅性和效率。此外，静音检测功能避免了无效数据的处理，提升了整体性能。在实践中，以上代码可以集成到各种支持Python的环境下，为用户提供即时的语音识别服务。 不过缺点也是存在的，使用 threading 不是个好主意， 这个实时依然依赖于硬件的能力， 即使在满血 MacStudio 上依然有3-5秒的延时。 另一个简单的例子 这个例子简单的实现了一次识别 import numpy as np import sounddevice as sd import whisper class AudioTranscriber: def __init__(self, model_path=&quot;mlx_models/medium_fp16&quot;): self.model_path = model_path self.sample_rate = 16000 def transcribe(self, duration=5): print(&quot;Recording...&quot;) indata = sd.rec(int(duration * self.sample_rate), samplerate=self.sample_rate, channels=1, dtype=&apos;float32&apos;) sd.wait() print(&quot;Recording stopped.&quot;) audio_data = np.squeeze(indata).astype(np.float32) result = whisper.transcribe(audio_data, path_or_hf_repo=self.model_path) print(&quot;Transcription: &quot;, result[&apos;text&apos;]) if __name__ == &quot;__main__&quot;: transcriber = AudioTranscriber() transcriber.transcribe(5)</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">LangChain：您的AI开发伙伴，让技术实现更简单！</title>
      
      
      <link href="https://blog.talkincode.net/2024/03/13/LangChain-AI-Language-Assistant/" rel="alternate" type="text/html" title="LangChain：您的AI开发伙伴，让技术实现更简单！" />
      
      <published>2024-03-13T00:55:53+00:00</published>
      <updated>2024-03-13T00:55:53+00:00</updated>
      <id>https://blog.talkincode.net/2024/03/13/LangChain-AI-Language-Assistant</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/03/13/LangChain-AI-Language-Assistant/">&lt;p&gt;&lt;img src=&quot;https://raw.githubusercontent.com/jamiesun/images/master/default/UvioZG.jpg&quot; alt=&quot;LangChain：您的AI开发伙伴，让技术实现更简单！&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在当前数字时代，大语言模型(LLM)的能力不断扩大，让我们能够构建更加智能、互动的应用。LangChain正是在这样的背景下应运而生，它是专门为构建以大语言模型为基础的应用程序而设计的框架，不仅提供了丰富的组件和集成工具，使开发过程更加便捷，而且通过其开源的特性，鼓励更多的开发者参与贡献，共同推动技术的进步。&lt;/p&gt;

&lt;p&gt;LangChain的优势在于其设计的灵活性和可扩展性。开发者们可以根据需求选择合适的链和代理(agent)构建应用，或利用现成的组件快速定制。其中，LangChain的组件模块致力于提升语言模型的交互体验，如优化提示管理(prompt management)与输入/输出接口，同时支持与外部数据源交互获取信息，进而增强语言模型的上下文感知能力。&lt;/p&gt;

&lt;h2&gt;LangChain 的重要概念&lt;/h2&gt;

&lt;p&gt;LangChain 引入了多个重要概念，为开发者提供强有力的工具以及框架，以便创建高效、智能的语言模型应用程序。以下是LangChain的关键概念介绍：&lt;/p&gt;

&lt;h3&gt;链(Chains)与代理(Agents)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;链(Chains)&lt;/strong&gt;: 是组件的序列，通过有序的组合实现特定的流程或行为。例如，一个简单的问答链可能首先与数据库连接，检索信息，然后生成基于检索信息的回答。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;想象一下你手里的珠宝串，珠子一个接一个地串起来，形成了一个整体。在LangChain里，这些”珠子”其实就是一系列操作步骤或者叫组件，每个步骤都有它特定的作用。这样，当我们沿着这条‘珠宝串’走下去，就可以实现一个接一个的动作，完成一个复杂的任务。举个例子，想要打造一个能回答你各种问题的程序，你就可以设计一个链：先查询必要的信息（比如上网搜索或者在数据库里翻翻），然后让语言模型根据这些信息来构造答案。这个过程就像一串精心设计的珠宝，每一步都连接起来，最终闪耀着解答的光芒。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;代理(Agents)&lt;/strong&gt;: 是具有决策能力的语言模型实体，能够选择性地触发不同的链，进行更加复杂的任务。例如，一个代理可能会分析用户的询问，判断需要执行哪种类型的链来提供正确的回答或采取相应的行动。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;比如在家里我们有各种小助手，比如遥控器帮我们换电视频道，闹钟叫我们起床，代理（Agents）就像是LangChain世界里的智能小精灵。它们拥有自己的“大脑”，能够根据你的需要做出判断和选择，然后找到最佳的解决方案。&lt;/p&gt;

&lt;p&gt;假设你有个虚拟小精灵，可以帮你做决定，它就是LangChain的代理。比如，你问它“今天晚上我应该吃什么？”这个代理会先想一想，然后可能会考虑你最近的饮食记录和营养需求，或者查看网上的菜谱，最后给你一个建议。在这个过程中，它可能使用了几种不同的“链”——就像前面讲的那串珠宝链——每一个链就像一个解决步骤，最后串联起来帮助代理给出最后的答案。&lt;/p&gt;

&lt;p&gt;所以，代理的魔力在于它能够将所有零散的信息、工具和规则有序地联系起来，然后在这个基础上，根据你的问题和它掌握的信息做出明智的决策。简单来说，代理就像是你个人的AI决策助手，它们借助大脑风暴（也就是LangChain的链）来帮你解决问题。&lt;/p&gt;

&lt;h3&gt;组件(Modules)与集成(Integrations)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;模型 I/O 组件&lt;/strong&gt;: 包括提示管理、提示优化、所有LLM的通用接口以及处理LLM的常见工具。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这就像是大语言模型的翻译机和管家，负责确保我们跟它们的对话能够顺畅进行。想象一下，你和一位会多国语言的朋友聊天，模型 I/O 组件就好比是一个超级翻译器，能够帮助你把你要表达的意思准确无误地传递给朋友，并确保朋友回答的内容你也能懂。还记得打电话时会说的“请稍等，正在为您转接”吗？模型 I/O 组件也会帮助管理这样的转接过程，确保每次交流就像和应答服务员一样友好和智能。简而言之，它们帮助我们的话语在人与大语言模型间顺畅翻译和传达，保证了我们能和AI就像和一个真人一样自然地对话。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;检索 (Retrieval) 组件&lt;/strong&gt;: 提供与外部数据源交互的方法，这对于数据增强生成非常关键，能够根据外部信息来优化语言模型的生成内容。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;你可以把它想象成AI世界的图书管理员。当我们问AI一个问题时，如果AI不确定答案，它会跑到图书馆去找相关书籍，取回来的资料就是回答问题的关键线索。检索组件正是这样一种工具，它确保AI不是闭门造车，而是根据最新的资料，或者说“外面的世界”的信息来做出反应和回答。这样一来，AI就可以像个博学的权威一样，告诉你关于几乎任何话题的见解，因为它具备了去“外出”获取知识的能力。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;代理 (Agents) 组件&lt;/strong&gt;: 支持LLM在确定要采取的行动、执行操作、接收观测结果并根据需要重复此流程，实现有目的性的自主决策循环。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;想象一下，我们在玩一款电子游戏，需要打败怪兽、解迷谜、找到宝藏，为此我们有一个虚拟助手，可以根据我们的命令和游戏环境的变化作出不同的举动。这个助手，就是LangChain世界里的”代理”（Agents）组件。&lt;/p&gt;

&lt;p&gt;“代理”组件本质上是一个聪明的语言模型，它的智能之处在于不只是机械地回答问题或者执行命令，而是可以做出选择和决策。它会根据情况的不同，考虑该使用哪一个“链”来达成目标或者解决问题。&lt;/p&gt;

&lt;p&gt;例如，假如我们问代理：“我该如何准备明天的面试？”它会分析这个问题，决定需要做些什么。它可能会运用一个查找链，去互联网上搜集成功面试的技巧和建议；又或者触发一个复习链，回忆你之前学过的相关知识。代理就像是一名指挥官，它内部有很多不同的特工队（也就是链），每一队都有特殊的能力。面对任务，它会指派最适合的特工队出动，完成任务。&lt;/p&gt;

&lt;p&gt;在LangChain的世界里，这些代理组件使得与语言模型的互动更加智能和动态，它们不仅听命于我们，更能够自主思考和规划，这就像给AI换上了一套更聪明的“大脑芯片”。你给它一个任务，它就能自己制定战略、选择路径，甚至途中自我调整，以确保最终达成目标，真正做到了“智能助理”的称号。&lt;/p&gt;

&lt;h3&gt;开发与监控(Development and Monitoring)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://smith.langchain.com&quot;&gt;LangSmith&lt;/a&gt;&lt;/strong&gt;: 一个统一的开发者平台，支持开发、测试、评估和监控基于任何LLM框架的链，并与LangChain无缝集成。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/langchain-ai/langserve&quot;&gt;LangServe&lt;/a&gt;&lt;/strong&gt;: 一个库，用于将LangChain的链部署为REST API，以便于与现有的应用程序和服务集成。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;可扩展性(Extensibility)&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://python.langchain.com/docs/langgraph&quot;&gt;LangGraph&lt;/a&gt;&lt;/strong&gt;: 一个高级库，它利用LangChain构建有状态、多行为体应用程序。LangGraph扩展了LangChain表达式语言，允许协调多个链（或代理）在多步计算周期中的行为。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;开源与贡献(Open Source and Contribution)&lt;/h3&gt;

&lt;p&gt;LangChain作为一个开源项目，强调社区贡献和协作。开发者可以共享改进，提交新特性，提高基础架构，或者提高文档质量，从而推动整个生态系统的进步。&lt;/p&gt;

&lt;h2&gt;参考资源&lt;/h2&gt;

&lt;p&gt;LangChain 提供广泛的文档和资源来帮助开发者快速上手和深入理解如何构建基于大语言模型的应用程序。以下是一些关键的参考资源，可以为开发者提供宝贵的信息和指导：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://python.langchain.com&quot;&gt;官方文档&lt;/a&gt;&lt;/strong&gt;: 提供详细的安装指引、环境设置、简单示例演示，以及LangChain接口、模块和结构的全面介绍。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/langchain-ai/langchain&quot;&gt;LangChain GitHub 仓库&lt;/a&gt;&lt;/strong&gt;: 作为项目的主页，包含代码、发行说明、贡献指南以及版本更新。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://discord.gg/6adMQxSpJS&quot;&gt;LangChain 社区&lt;/a&gt;&lt;/strong&gt;: 提供开发者和用户交流的平台，可以分享使用经验、讨论技术问题，并与LangChain团队进行直接互动。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://python.langchain.com/docs/get_started/introduction&quot;&gt;快速安装&lt;/a&gt;&lt;/strong&gt;: 快速入门指南，详细介绍了通过pip或conda进行安装的方法。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://python.langchain.com/docs/use_cases/&quot;&gt;使用案例&lt;/a&gt;&lt;/strong&gt;: 有实际案例指导，展示LangChain在多种场景下的应用，涵盖问题回答、结构化数据分析和聊天机器人等。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://python.langchain.com/docs/contributing/&quot;&gt;贡献指南&lt;/a&gt;&lt;/strong&gt;: 详细说明了如何为LangChain项目作出贡献，无论是新增特性、提升架构质量，还是改善文档等。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/langchain-ai/langchain/tree/master/templates&quot;&gt;LangChain Templates&lt;/a&gt;&lt;/strong&gt;: 提供一系列易于部署的参考架构，帮助快速搭建起符合特定任务需求的应用。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;此外，LangChain 的发展也离不开社区贡献者的努力，欢迎更多的开发者加入我们的行列，一起打造更加强大和智能的语言模型应用程序。&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/langchain-ai/langchainjs&quot;&gt;LangChain.js&lt;/a&gt;: 针对JavaScript/TypeScript语言的LangChain库，支持在这些语言的生态系统内构建应用。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="AI" />
      
        <category term="LangChain" />
      
        <category term="人工智能" />
      

      

      
        <summary type="html">在当前数字时代，大语言模型(LLM)的能力不断扩大，让我们能够构建更加智能、互动的应用。LangChain正是在这样的背景下应运而生，它是专门为构建以大语言模型为基础的应用程序而设计的框架，不仅提供了丰富的组件和集成工具，使开发过程更加便捷，而且通过其开源的特性，鼓励更多的开发者参与贡献，共同推动技术的进步。 LangChain的优势在于其设计的灵活性和可扩展性。开发者们可以根据需求选择合适的链和代理(agent)构建应用，或利用现成的组件快速定制。其中，LangChain的组件模块致力于提升语言模型的交互体验，如优化提示管理(prompt management)与输入/输出接口，同时支持与外部数据源交互获取信息，进而增强语言模型的上下文感知能力。 LangChain 的重要概念 LangChain 引入了多个重要概念，为开发者提供强有力的工具以及框架，以便创建高效、智能的语言模型应用程序。以下是LangChain的关键概念介绍： 链(Chains)与代理(Agents) 链(Chains): 是组件的序列，通过有序的组合实现特定的流程或行为。例如，一个简单的问答链可能首先与数据库连接，检索信息，然后生成基于检索信息的回答。 想象一下你手里的珠宝串，珠子一个接一个地串起来，形成了一个整体。在LangChain里，这些”珠子”其实就是一系列操作步骤或者叫组件，每个步骤都有它特定的作用。这样，当我们沿着这条‘珠宝串’走下去，就可以实现一个接一个的动作，完成一个复杂的任务。举个例子，想要打造一个能回答你各种问题的程序，你就可以设计一个链：先查询必要的信息（比如上网搜索或者在数据库里翻翻），然后让语言模型根据这些信息来构造答案。这个过程就像一串精心设计的珠宝，每一步都连接起来，最终闪耀着解答的光芒。 代理(Agents): 是具有决策能力的语言模型实体，能够选择性地触发不同的链，进行更加复杂的任务。例如，一个代理可能会分析用户的询问，判断需要执行哪种类型的链来提供正确的回答或采取相应的行动。 比如在家里我们有各种小助手，比如遥控器帮我们换电视频道，闹钟叫我们起床，代理（Agents）就像是LangChain世界里的智能小精灵。它们拥有自己的“大脑”，能够根据你的需要做出判断和选择，然后找到最佳的解决方案。 假设你有个虚拟小精灵，可以帮你做决定，它就是LangChain的代理。比如，你问它“今天晚上我应该吃什么？”这个代理会先想一想，然后可能会考虑你最近的饮食记录和营养需求，或者查看网上的菜谱，最后给你一个建议。在这个过程中，它可能使用了几种不同的“链”——就像前面讲的那串珠宝链——每一个链就像一个解决步骤，最后串联起来帮助代理给出最后的答案。 所以，代理的魔力在于它能够将所有零散的信息、工具和规则有序地联系起来，然后在这个基础上，根据你的问题和它掌握的信息做出明智的决策。简单来说，代理就像是你个人的AI决策助手，它们借助大脑风暴（也就是LangChain的链）来帮你解决问题。 组件(Modules)与集成(Integrations) 模型 I/O 组件: 包括提示管理、提示优化、所有LLM的通用接口以及处理LLM的常见工具。 这就像是大语言模型的翻译机和管家，负责确保我们跟它们的对话能够顺畅进行。想象一下，你和一位会多国语言的朋友聊天，模型 I/O 组件就好比是一个超级翻译器，能够帮助你把你要表达的意思准确无误地传递给朋友，并确保朋友回答的内容你也能懂。还记得打电话时会说的“请稍等，正在为您转接”吗？模型 I/O 组件也会帮助管理这样的转接过程，确保每次交流就像和应答服务员一样友好和智能。简而言之，它们帮助我们的话语在人与大语言模型间顺畅翻译和传达，保证了我们能和AI就像和一个真人一样自然地对话。 检索 (Retrieval) 组件: 提供与外部数据源交互的方法，这对于数据增强生成非常关键，能够根据外部信息来优化语言模型的生成内容。 你可以把它想象成AI世界的图书管理员。当我们问AI一个问题时，如果AI不确定答案，它会跑到图书馆去找相关书籍，取回来的资料就是回答问题的关键线索。检索组件正是这样一种工具，它确保AI不是闭门造车，而是根据最新的资料，或者说“外面的世界”的信息来做出反应和回答。这样一来，AI就可以像个博学的权威一样，告诉你关于几乎任何话题的见解，因为它具备了去“外出”获取知识的能力。 代理 (Agents) 组件: 支持LLM在确定要采取的行动、执行操作、接收观测结果并根据需要重复此流程，实现有目的性的自主决策循环。 想象一下，我们在玩一款电子游戏，需要打败怪兽、解迷谜、找到宝藏，为此我们有一个虚拟助手，可以根据我们的命令和游戏环境的变化作出不同的举动。这个助手，就是LangChain世界里的”代理”（Agents）组件。 “代理”组件本质上是一个聪明的语言模型，它的智能之处在于不只是机械地回答问题或者执行命令，而是可以做出选择和决策。它会根据情况的不同，考虑该使用哪一个“链”来达成目标或者解决问题。 例如，假如我们问代理：“我该如何准备明天的面试？”它会分析这个问题，决定需要做些什么。它可能会运用一个查找链，去互联网上搜集成功面试的技巧和建议；又或者触发一个复习链，回忆你之前学过的相关知识。代理就像是一名指挥官，它内部有很多不同的特工队（也就是链），每一队都有特殊的能力。面对任务，它会指派最适合的特工队出动，完成任务。 在LangChain的世界里，这些代理组件使得与语言模型的互动更加智能和动态，它们不仅听命于我们，更能够自主思考和规划，这就像给AI换上了一套更聪明的“大脑芯片”。你给它一个任务，它就能自己制定战略、选择路径，甚至途中自我调整，以确保最终达成目标，真正做到了“智能助理”的称号。 开发与监控(Development and Monitoring) LangSmith: 一个统一的开发者平台，支持开发、测试、评估和监控基于任何LLM框架的链，并与LangChain无缝集成。 LangServe: 一个库，用于将LangChain的链部署为REST API，以便于与现有的应用程序和服务集成。 可扩展性(Extensibility) LangGraph: 一个高级库，它利用LangChain构建有状态、多行为体应用程序。LangGraph扩展了LangChain表达式语言，允许协调多个链（或代理）在多步计算周期中的行为。 开源与贡献(Open Source and Contribution) LangChain作为一个开源项目，强调社区贡献和协作。开发者可以共享改进，提交新特性，提高基础架构，或者提高文档质量，从而推动整个生态系统的进步。 参考资源 LangChain 提供广泛的文档和资源来帮助开发者快速上手和深入理解如何构建基于大语言模型的应用程序。以下是一些关键的参考资源，可以为开发者提供宝贵的信息和指导： 官方文档: 提供详细的安装指引、环境设置、简单示例演示，以及LangChain接口、模块和结构的全面介绍。 LangChain GitHub 仓库: 作为项目的主页，包含代码、发行说明、贡献指南以及版本更新。 LangChain 社区: 提供开发者和用户交流的平台，可以分享使用经验、讨论技术问题，并与LangChain团队进行直接互动。 快速安装: 快速入门指南，详细介绍了通过pip或conda进行安装的方法。 使用案例: 有实际案例指导，展示LangChain在多种场景下的应用，涵盖问题回答、结构化数据分析和聊天机器人等。 贡献指南: 详细说明了如何为LangChain项目作出贡献，无论是新增特性、提升架构质量，还是改善文档等。 LangChain Templates: 提供一系列易于部署的参考架构，帮助快速搭建起符合特定任务需求的应用。 此外，LangChain 的发展也离不开社区贡献者的努力，欢迎更多的开发者加入我们的行列，一起打造更加强大和智能的语言模型应用程序。 LangChain.js: 针对JavaScript/TypeScript语言的LangChain库，支持在这些语言的生态系统内构建应用。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">Sounddevice: 高效的Python音频处理库</title>
      
      
      <link href="https://blog.talkincode.net/2024/03/11/sounddevice-python-library/" rel="alternate" type="text/html" title="Sounddevice: 高效的Python音频处理库" />
      
      <published>2024-03-11T12:59:05+00:00</published>
      <updated>2024-03-11T12:59:05+00:00</updated>
      <id>https://blog.talkincode.net/2024/03/11/sounddevice-python-library</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/03/11/sounddevice-python-library/">&lt;p&gt;Sounddevice 是一个用于录制和播放音频的Python库，它以直观的API为特色，并为PortAudio音频I/O库提供了一个封装。Sounddevice是 cross-platform，支持多种操作系统和硬件设备。以下是一些比较常见的例子：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;实时音频处理：利用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.Stream&lt;/code&gt; 对象，可以实现低延迟的实时音频信号处理。音乐家和音频工程师可能使用 Sounddevice 来处理实时音乐表演的音频信号，比如实时混音、音频特效的添加和态音频信号监测。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;音频录制：Sounddevice 可用于录制音频信号，例如录制演讲、会议内容或者音乐创作时的素材。例如，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.InputStream&lt;/code&gt; 类来监听音频输入设备，并将接收到的音频数据保存到文件。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;音频播放：与音频录制相对，Sounddevice 也可以用于播放音频文件。例如，在播放器或音乐应用程序中，可以利用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.OutputStream&lt;/code&gt; 来播放音乐和声效。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;实验和教育：在教育和研究场景中，Sounddevice 作为一个易于使用的包，允许学生和研究人员探索数字信号处理的概念。例如，在数字音频处理的课程中，可以利用它来演示滤波器、FFT变换和其他信号处理方法的效果。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;音频分析：Sounddevice 可以用于音频信号的分析，比如声音识别、频谱分析或者音乐信息检索。例如，可以从输入流获取音频数据，使用信号处理技术进行分析，并提取需要的信息，如节拍、音高或声音特征。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;输入/输出流路由：对于需要定制音频流路由的复杂应用程式，Sounddevice 可以提供高级的输入/输出流管理。比如一个虚拟音频合成器可能需要将多个输入信号路由到不同效果处理链中，然后再混合输出。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;人机交互：在需要音频作为交互媒介的应用中，如语音指令识别或音频反馈，Sounddevice 可以实现音频的捕获和输出。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;1. 初始化与终止&lt;/h2&gt;

&lt;p&gt;当&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice&lt;/code&gt;模块被导入时，PortAudio系统会自动被初始化。在大多数情况下，用户无需手动初始化或终止。如果需要，可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice._initialize()&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice._terminate()&lt;/code&gt;来手动管理。&lt;/p&gt;

&lt;h2&gt;2. 核心对象和函数&lt;/h2&gt;

&lt;h3&gt;2.1. Stream 对象&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.Stream&lt;/code&gt;: 一个全双工的音频流。通过实例化这个类可以同时处理音频的播放和录音。该对象提供了开始(start)、停止(stop)、中止(abort)和关闭(close)流的方法。下面列举了创建 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stream&lt;/code&gt; 对象时可以使用的一些参数以及它们的作用：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;samplerate&lt;/code&gt;：采样率，以赫兹（Hz）为单位，确定每秒钟采集和播放的样本数。标准的CD质量采样率是44100Hz。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blocksize&lt;/code&gt;：块大小，定义了传递给 stream 回调函数的帧数，或阻塞型读/写流的首选块粒度。0 表示使用主机 API 的最佳块大小。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;device&lt;/code&gt;：设备索引或查询字符串，指定要使用的输入/输出设备。如果未指定，默认从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.device&lt;/code&gt; 中获取设置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channels&lt;/code&gt;：通道数，定义了要传递给流回调函数的声音通道数，或者 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write()&lt;/code&gt; 访问的通道数。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dtype&lt;/code&gt;：数据类型，指定了提供给流回调函数、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read()&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;write()&lt;/code&gt; 的 numpy 数组的样本格式。支持的格式有 ‘float32’、’int32’、’int16’、’int8’、’uint8’ 等。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latency&lt;/code&gt;：延迟，以秒为单位，表示期望的流延迟时间。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;low&apos;&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;high&apos;&lt;/code&gt; 分别代表设备的默认低延迟和高延迟配置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extra_settings&lt;/code&gt;：特定于主机 API 的额外设置，如 ASIO 的通道选择等。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;callback&lt;/code&gt;：用户提供的回调函数，用于在流活动期间生成或处理音频数据。回调函数的参数定义了输入和输出缓冲区，帧数，回调时间和状态。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;finished_callback&lt;/code&gt;：用户提供的回调函数，当流变为非活动状态时调用。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clip_off&lt;/code&gt;：布尔值，设置为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; 以禁用默认的剪裁。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dither_off&lt;/code&gt;：布尔值，设置为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; 以禁用默认的抖动。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;never_drop_input&lt;/code&gt;：布尔值，对于全双工流，设置为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; 可请求不丢弃溢出的输入样本。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prime_output_buffers_using_stream_callback&lt;/code&gt;：布尔值，设置为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; 会在初始输出缓冲区上调用流回调进行填充，而不是使用默认的 0 填充。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这些参数允许在创建 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stream&lt;/code&gt; 对象时进行精细控制，优化音频流的行为以匹配特定应用程序的需求。&lt;/p&gt;

&lt;p&gt;以下是使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.Stream&lt;/code&gt; 对象的代码示例：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 采样率
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44100&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 持续时间（秒）
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 回调函数
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outdata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 在此处处理音频数据
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;outdata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indata&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 直接将输入数据复制到输出数据中，形成回声
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 打开音频流
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;samplerate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 准备开始录制五秒音频
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 暂停主线程，允许音频流处理音频数据
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在这个例子中，我们定义了一个采样率为 44.1 kHz 的音频流，双声道输入和输出。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;callback&lt;/code&gt; 函数用于处理音频数据，在本例中，它简单地将接收到的输入数据复制到输出数据中，这将导致音频信号被回放（回声效果）。&lt;/p&gt;

&lt;p&gt;注意，通过使用 Python 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with&lt;/code&gt; 语句，我们保证音频流在退出代码块时被正确关闭。我们在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with&lt;/code&gt; 代码块中使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sd.sleep()&lt;/code&gt; 函数来避免主线程终止，在这段时间内 callback 函数会不断地被调用并处理音频数据。&lt;/p&gt;

&lt;p&gt;请根据实际应用调整回调函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;callback&lt;/code&gt; 中音频处理的逻辑。&lt;/p&gt;

&lt;h3&gt;2.2. 输入/输出流&lt;/h3&gt;

&lt;h4&gt;2.2.1. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.InputStream&lt;/code&gt;: 专门用于录音的流&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.InputStream&lt;/code&gt; 是用于录音的流对象。您可以创建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InputStream&lt;/code&gt; 实例来接收音频数据，这些数据可以用于实时处理或保存至文件。以下是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InputStream&lt;/code&gt; 类的构造函数参数的详细解释：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;samplerate&lt;/code&gt; (可选): 以赫兹（Hz）为单位的采样率，确定每秒钟采集的样本数。标准CD质量是44100Hz。如果未指定，默认使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.samplerate&lt;/code&gt; 的设置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blocksize&lt;/code&gt; (可选): 块大小，定义了传递给 stream 回调函数的帧数。 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; 表示使用主机 API 的最佳块大小。如果未指定，默认使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.blocksize&lt;/code&gt; 的设置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;device&lt;/code&gt; (可选): 设备索引或查询字符串，指定要使用的音频输入设备。如果未指定，默认从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.device&lt;/code&gt; 中获取输入设备的设置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channels&lt;/code&gt; (可选): 音频通道数，定义了要传递给 stream 设备的声道数量。如果未指定，默认使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.channels&lt;/code&gt; 中的输入通道数设置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dtype&lt;/code&gt; (可选): 数据类型，指定了为录音数据指定的 NumPy 数组的数据类型。支持的格式包括 ‘float32’、’int32’、’int16’、’int8’ 和 ‘uint8’。如果未指定，默认使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.dtype&lt;/code&gt; 中的输入数据类型。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latency&lt;/code&gt; (可选): 延迟，以秒为单位，表示流的期望延迟时间。值可以是具体的延迟时间，或字符串 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;low&apos;&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;high&apos;&lt;/code&gt;，分别代表设备的默认低延迟和高延迟配置。如果未指定，默认使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.latency&lt;/code&gt; 中的输入设备延迟。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extra_settings&lt;/code&gt; (可选): 特定于主机 API 的额外设置，例如使用 ASIO 驱动时可指定的额外设置如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.AsioSettings&lt;/code&gt;。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;callback&lt;/code&gt; (可选): 用户提供的回调函数，用于在流活动期间处理音频数据。回调函数接收几个参数：输入数据、帧数、时间信息以及状态，它必须返回 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt;。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;finished_callback&lt;/code&gt; (可选): 用户提供的回调函数，当流变为非活动状态时调用。例如，可以用于清理在录音过程中使用的资源。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clip_off&lt;/code&gt; (可选): 布尔值，如果设置为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，将关闭默认的剪裁功能，否则超出范围的样本将被剪裁为有效的最大/最小值。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dither_off&lt;/code&gt; (可选): 布尔值，如果设置为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，将关闭默认的抖动功能。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;never_drop_input&lt;/code&gt; (可选): 布尔值，对于全双工流，将此项设为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; 可以保证不会丢弃溢出的输入样本。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prime_output_buffers_using_stream_callback&lt;/code&gt; (可选): 布尔值，如果设为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，流的输出缓冲区会在开始时使用回调函数来填充，而不是默认的零填充。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;创建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InputStream&lt;/code&gt; 实例用于录制音频，并打印状态消息：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 回调函数处理录音数据
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 创建 InputStream 对象
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;InputStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 开始录音
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 录音 5 秒钟
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在这个例子中，回调函数仅检查并打印状态信息，但实际中您可能需要将输入数据 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indata&lt;/code&gt; 写入文件或进行进一步处理。通过使用 Python 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with&lt;/code&gt; 语句，我们确保在代码块结束时 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InputStream&lt;/code&gt; 会被正确关闭，并且通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sd.sleep()&lt;/code&gt; 暂停主线程，允许音频流在此期间处理音频数据。&lt;/p&gt;

&lt;h4&gt;2.2.2. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.OutputStream&lt;/code&gt;: 专门用于播放音频的流&lt;/h4&gt;

&lt;p&gt;在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice&lt;/code&gt; 库中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OutputStream&lt;/code&gt; 类用于创建一个只支持音频播放的流。下面是它的参数的详细解释和使用方法：&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OutputStream&lt;/code&gt;类的构造函数接收以下参数：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;samplerate&lt;/code&gt; (可选): 采样率，以赫兹（Hz）为单位。这是每秒钟捕获和播放的样本数。如果未指定，默认使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.samplerate&lt;/code&gt; 的设置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blocksize&lt;/code&gt; (可选): 块大小，定义了传递给流的回调函数的帧数。 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; 表示使用主机 API 的最佳块大小。如果未指定，默认使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.blocksize&lt;/code&gt; 的设置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;device&lt;/code&gt; (可选): 设备索引或查询字符串，指定要使用的音频输出设备。如果未指定，默认从 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.device&lt;/code&gt; 中获取输出设备的设置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channels&lt;/code&gt; (可选): 音频通道数，定义了要传递给流的声道数量。如果未指定，默认使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.channels&lt;/code&gt; 中的输出通道数设置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dtype&lt;/code&gt; (可选): 数据类型，指定了为播放数据指定的 NumPy 数组的数据类型。支持的格式包括 ‘float32’、’int32’、’int16’、’int8’ 和 ‘uint8’。如果未指定，默认使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.dtype&lt;/code&gt; 中的输出数据类型。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latency&lt;/code&gt; (可选): 延迟，以秒为单位，表示流的期望延迟时间。值可以是具体的延迟时间，或字符串 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;low&apos;&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;high&apos;&lt;/code&gt;，分别代表设备的默认低延迟和高延迟配置。如果未指定，默认使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.latency&lt;/code&gt; 中的输出设备延迟。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extra_settings&lt;/code&gt; (可选): 特定于主机 API 的额外设置，例如使用 ASIO 驱动时可指定的额外设置如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.AsioSettings&lt;/code&gt;。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;callback&lt;/code&gt; (可选): 用户提供的回调函数，用于在流活动期间生成音频数据。回调函数接收几个参数：输出数据、帧数、时间信息以及状态，它必须返回 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt;。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;finished_callback&lt;/code&gt; (可选): 用户提供的回调函数，当流变为非活动状态时调用。例如，可以用于清理在播放过程中使用的资源。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clip_off&lt;/code&gt; (可选): 布尔值，如果设置为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，将关闭默认的剪裁功能，否则超出范围的样本将被剪裁为有效的最大/最小值。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dither_off&lt;/code&gt; (可选): 布尔值，如果设置为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，将关闭默认的抖动功能。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;never_drop_input&lt;/code&gt; (可选): 布尔值，对于全双工流，将此项设为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; 可以保证不会丢弃溢出的输入样本。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prime_output_buffers_using_stream_callback&lt;/code&gt; (可选): 布尔值，如果设为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，流的输出缓冲区会在开始时使用回调函数来填充，而不是默认的零填充。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;具体使用时，需要根据自己的需求配置参数。以下演示一个创建 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OutputStream&lt;/code&gt; 对象并播放一段随机生成的声音的示例：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 生成一秒钟的随机噪音
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44100&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 采样率
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;uniform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 创建输出流
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;OutputStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;samplerate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 启动输出流并播放数据
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在这个示例中，我们首先生成了随机音频数据，然后创建了一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OutputStream&lt;/code&gt; 对象进行播放。需要注意的是，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OutputStream&lt;/code&gt; 类的实例也可以作为上下文管理器使用，在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;with&lt;/code&gt; 语句块结束时自动关闭流。&lt;/p&gt;

&lt;h3&gt;2.3. 播放与录制函数&lt;/h3&gt;

&lt;h4&gt;2.3.1. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.play()&lt;/code&gt;: 用于播放NumPy数组中的音频信号&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.play()&lt;/code&gt; 函数是用于通过Python的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice&lt;/code&gt;库播放NumPy数组中的音频数据的便捷函数。它简化了音频播放的过程，让用户不必手动创建和管理音频流。下面将详细解释该函数的参数以及其用途：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;data&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;array_like&lt;/code&gt;): 包含音频数据的数组。如果数组是二维的，每一列都表示一个通道；如果是一维数组，则视为单声道数据。此参数是必需的。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;samplerate&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;float&lt;/code&gt;, 可选): 音频的采样率，以赫兹（Hz）为单位。如果未指定，则使用默认设备的采样率。此参数对音频的播放速度和音调都有影响。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;mapping&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;array_like&lt;/code&gt;, 可选): 一个列表，用于指定哪些通道用于播放&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt;中的音频。列表中的每个数字对应一个通道编号（编号从1开始）。如果未指定，则音频数据将被播放到默认的输出设备通道上。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;blocking&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool&lt;/code&gt;, 可选): 如果为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;play()&lt;/code&gt; 调用将阻塞，直到全部数据播放完毕。如果为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;False&lt;/code&gt;（默认值），将在后台进行播放，并且函数会立即返回。非阻塞调用可以随时使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.stop()&lt;/code&gt;停止。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;loop&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool&lt;/code&gt;, 可选): 如果为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，音频数据将循环播放，直到明确停止。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;**kwargs&lt;/strong&gt;: 其他传递给&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OutputStream&lt;/code&gt;的关键字参数。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;play()&lt;/code&gt;函数没有返回值。如果在播放时发生错误，则会抛出&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.PortAudioError&lt;/code&gt;异常。&lt;/p&gt;

&lt;p&gt;播放一个440 Hz的正弦波:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44100&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 采样率
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;440&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# 频率, Hz
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# 持续时间秒
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;linspace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endpoint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;samplerate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 等待直到数据播放完成
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上面的例子创建了一个时长为1秒的正弦波信号，并用采样率为44100 Hz播放它。在播放后，代码使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sd.wait()&lt;/code&gt;保持程序阻塞，直到播放结束。&lt;/p&gt;

&lt;p&gt;注意：使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.play()&lt;/code&gt;时应该确保你的NumPy数组中的数据类型与声音设备可接受的数据类型匹配。通常，一种安全的选择是使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;float32&lt;/code&gt;数据类型，其取值范围为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-1.0&lt;/code&gt;到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1.0&lt;/code&gt;。&lt;/p&gt;

&lt;h4&gt;2.3.2. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.rec()&lt;/code&gt;: 用于录制音频并将结果存储在NumPy数组中&lt;/h4&gt;

&lt;p&gt;函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.rec()&lt;/code&gt; 用于录制音频并将结果存储在NumPy数组中。以下是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.rec()&lt;/code&gt;的参数详解：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;frames&lt;/code&gt;: 录音帧数。一帧对应于所有通道的单个样本集合。例如，若要录制5秒的音频，并且采样率（samplerate）是44100，那么frames将是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5*44100&lt;/code&gt;。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;samplerate&lt;/code&gt;: 采样率，以赫兹（Hz）为单位。这是每秒钟捕获和播放的样本数。常见的采样率包括44100（CD质量）、48000（专业音频设备）等。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channels&lt;/code&gt;: 录制的通道数。单声道为1，立体声为2。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dtype&lt;/code&gt;: 指定录制数据的数据类型。常用类型包括&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;float32&apos;&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;int16&apos;&lt;/code&gt;。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;float32&apos;&lt;/code&gt;将样本值范围规范化为从-1.0到+1.0，而&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;int16&apos;&lt;/code&gt;是16位整型，表示的范围则是-32768到+32767。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;out&lt;/code&gt;: 可选。输出的NumPy数组。如果指定了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;out&lt;/code&gt;参数，则将在该数组中放置录制的音频数据，否则内部会创建一个新数组。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mapping&lt;/code&gt;: 可选。这是一个指定哪些通道（从1开始编号）实际用于录音的序列。通常情况下，默认的设备所有通道都会被使用。（此参数并未在原文的注释中提到，但在函数API中存在。）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blocking&lt;/code&gt;: 可选。默认值为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;False&lt;/code&gt;。如果设置为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，函数调用将阻塞，直到录制完成。否则，它会立即返回，并且需要外部逻辑来确保录制完成，通常是通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.wait()&lt;/code&gt;函数。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;**kwargs&lt;/code&gt;: 其他一些可选的关键字参数，可能在未来版本的sounddevice模块中添加。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;示例用法：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44100&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 采样率
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 持续时间（秒）
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 录制
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myrecording&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;rec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;samplerate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;float32&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# myrecording 现在包含了录制的音频数据
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这将录制5秒钟的立体声音频，并在NumPy数组&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;myrecording&lt;/code&gt;中以32位浮点格式保存样本数据。通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sd.wait()&lt;/code&gt;确保录音完成，然后可以进一步处理或保存录音数据。&lt;/p&gt;

&lt;h4&gt;2.3.3. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.playrec()&lt;/code&gt;: 同时录制和播放音频&lt;/h4&gt;

&lt;p&gt;函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.playrec()&lt;/code&gt; 用于同时进行音频的播放和录制，并将播放的音频和录制的音频结果作为 NumPy 数组返回。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.playrec()&lt;/code&gt; 是一个高度灵活的函数，它结合了音频播放和录制功能。在实时音频处理中，这个函数非常有用。以下是一些典型应用场景：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;回声消除测试&lt;/strong&gt;：
开发音频处理中的回声消除算法时，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playrec()&lt;/code&gt; 播放一段音频并同时录制麦克风输入，以便分析回声效果并优化算法。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;实时音频效果处理&lt;/strong&gt;：
对于音乐制作者和声音工程师而言，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playrec()&lt;/code&gt; 可以实现实时音效处理，比如实时添加混响、均衡器设定或其他音频效果。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;乐器调音软件&lt;/strong&gt;：
乐器练习时可以通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playrec()&lt;/code&gt; 获取乐器声音输入，并实时提供调音反馈，从而辅助乐器的准确调音。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;音频同步应用&lt;/strong&gt;：
在音视频开发中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playrec()&lt;/code&gt; 可以在播放音轨的同时录制声音，帮助开发者实现音频与视频的精确同步。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;双向通讯应用&lt;/strong&gt;：
在VoIP通讯或语音会议系统中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playrec()&lt;/code&gt; 可以同时处理语音输入和输出流，实现如电话会议等双向通信功能。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;声音识别测试&lt;/strong&gt;：
使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playrec()&lt;/code&gt; 进行声音识别训练时，可以在播放特定声音的同时录制环境中的声音响应，用于声音识别算法的训练和测试。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;声学测量&lt;/strong&gt;：
在声学测量和分析中，通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playrec()&lt;/code&gt; 播放已知测试信号并录制响应，以测量房间的声学特性或扬声器的频率响应。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;教育与研究&lt;/strong&gt;：
教育和研究领域中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playrec()&lt;/code&gt; 可以用来演示和探讨声音的录制和播放原理，以及数字信号处理的实时应用案例。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playrec()&lt;/code&gt; 由于其实时性和便捷性，成为了音频处理应用程序中不可或缺的函数之一。它使应用程序能够同时控制音频的输入和输出，从而支持多种复杂的音频处理流程。&lt;/p&gt;

&lt;p&gt;以下是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.playrec()&lt;/code&gt;的参数详解：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt;: array_like
要播放的音频数据的数组。如果数组是二维的，每一列都表示一个通道；如果是一维数组，则视为单声道数据。这个参数是必需的。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;samplerate&lt;/code&gt;: float, 可选
音频的采样率，以赫兹（Hz）为单位。如果未指定，则使用默认设备的采样率。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channels&lt;/code&gt;: int, 可选
录制的通道数。单声道为1，立体声为2。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dtype&lt;/code&gt;: str 或 numpy.dtype, 可选
指定录制数据的数据类型。常用类型包括 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;float32&apos;&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;int16&apos;&lt;/code&gt;。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;float32&apos;&lt;/code&gt; 将样本值范围规范化为从-1.0到+1.0，而 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;int16&apos;&lt;/code&gt; 是16位整型，表示的范围则是-32768到+32767。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;out&lt;/code&gt;: numpy.ndarray 或子类, 可选
如果指定了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;out&lt;/code&gt; 参数，则将在该数组中放置录制的音频数据，否则内部会创建一个新数组。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mapping&lt;/code&gt;: array_like, 可选
这是一个指定哪些通道（从1开始编号）实际用于播放和录音的序列。通常情况下，默认的设备所有通道都会被使用。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blocking&lt;/code&gt;: bool, 可选
默认值为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;False&lt;/code&gt;。如果设置为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，函数调用将阻塞，直到录制完成。否则，它会立即返回，并且需要外部逻辑来确保录制完成，通常是通过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.wait()&lt;/code&gt; 函数。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;**kwargs&lt;/code&gt;: 其他一些可选的关键字参数。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;示例用法：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 创建音频数据
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44100&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 采样率
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 持续时间（秒）
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frequency&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;440&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 频率（Hz）
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;samples&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;arange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frequency&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;astype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;float32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 播放并录制音频
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myrecording&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;playrec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;samples&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;samplerate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;float32&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 等待直到数据播放和录制完成
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在这个例子中，我们首先生成一个时长为5秒，频率为440 Hz的正弦波音频数据，并用采样率为44100 Hz的设定将其播放出去。同时，我们还录制了音频，保存在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;myrecording&lt;/code&gt; 这个 NumPy 数组中。播放和录制完成后，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sd.wait()&lt;/code&gt; 函数来确保操作完成。&lt;/p&gt;

&lt;h3&gt;2.4. 查询函数&lt;/h3&gt;

&lt;h4&gt;2.4.1. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.query_devices()&lt;/code&gt;: 查询可用的音频输入/输出设备&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.query_devices()&lt;/code&gt; 是一个函数，它查询可用的音频输入/输出设备，并返回有关这些设备的信息。这个函数可以在不带参数的情况下调用，也可以接受一些可选参数来查询特定的设备或者设备的特定类型（输入或输出）。返回的结果取决于所传递的参数。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;device&lt;/code&gt; (可选): 可以是一个设备的数字ID或者设备名称的字符串。如果指定了这个参数，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;query_devices()&lt;/code&gt; 只会返回有关这个特定设备的信息。如果不指定或为None，则返回所有可用设备的信息。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kind&lt;/code&gt; (可选): 可以是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;input&apos;&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;output&apos;&lt;/code&gt;。如果指定了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kind&lt;/code&gt; 而没有指定 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;device&lt;/code&gt;，则函数返回有关默认输入或输出设备的信息。如果 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;device&lt;/code&gt; 也被指定，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kind&lt;/code&gt; 参数将决定要查询输入还是输出属性（如果设备同时支持输入和输出）。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;当不带任何参数调用时，返回一个包含所有可用设备信息的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.DeviceList&lt;/code&gt; 对象，其中每个设备的信息用一个字典表示，键包括设备的名称、索引号、所属的主机API、最大输入/输出通道数、默认低延迟和高延迟值以及默认采样频率等。&lt;/p&gt;

&lt;p&gt;如果 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;device&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kind&lt;/code&gt; 被指定，则返回一个含有所请求设备信息的字典。&lt;/p&gt;

&lt;p&gt;查询所有可用设备：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;devices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;query_devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;查询特定设备的信息：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;device_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;query_devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 查询设备ID为2的设备
&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;查询默认输出设备的信息：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;default_output_device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;query_devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default_output_device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;查询默认输入设备的信息：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;default_input_device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;query_devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default_input_device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在实际使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;query_devices()&lt;/code&gt; 时，通常需要查看设备的特性（例如支持的通道数或者默认延迟），或者在打开音频流之前选择合适的设备。此外，这个函数还可以在音频设备调试和选择最佳设备时提供有用的信息。&lt;/p&gt;

&lt;h4&gt;2.4.2. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.query_hostapis()&lt;/code&gt;: 查询可用的音频主机API信息&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.query_hostapis()&lt;/code&gt; 函数用于查询计算机上可用的音频主机API。在PortAudio中，主机API是具体的音频接口，比如ASIO, DirectSound, WASAPI (在Windows上) 或者 ALSA, OSS, JACK (在Linux上)。此函数用来获取有关这些音频主机API的信息，这对于了解系统配置和调试音频问题非常有用。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.query_hostapis()&lt;/code&gt;函数只接受一个可选参数：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt;: int, 可选
    &lt;ul&gt;
      &lt;li&gt;若指定，将仅返回关于给定主机API &lt;em&gt;index&lt;/em&gt; 的信息，呈现为一个字典。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;函数的返回值取决于是否指定了 &lt;em&gt;index&lt;/em&gt; 参数：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;若未指定 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt;，函数返回一个包含每个可用主机API信息的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tuple&lt;/code&gt;，其中每个API的信息都以字典形式存在。&lt;/li&gt;
  &lt;li&gt;若指定 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt;，将返回一个字典，包含指定主机API的信息。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;每个API信息的字典都包含以下键：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;name&apos;&lt;/code&gt;: 主机API的名称。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;devices&apos;&lt;/code&gt;: 属于此主机API的设备ID列表。使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;query_devices()&lt;/code&gt; 获取有关设备的信息。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;default_input_device&apos;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;default_output_device&apos;&lt;/code&gt;: 对应于每个主机API的默认输入/输出设备ID。若不存在默认输入/输出设备，则值为-1。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这些信息可以帮助您选择合适的主机API和设备来打开音频流。&lt;/p&gt;

&lt;p&gt;查询所有可用的音频主机API:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;hostapis&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;query_hostapis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hostapis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;查询特定主机API的信息：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 假设我们想查询第一个主机API的信息
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hostapi_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;query_hostapis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hostapi_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;获取默认输入设备的主机API：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;default_hostapi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;query_hostapis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hostapi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default_hostapi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这些示例显示了如何使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.query_hostapis()&lt;/code&gt;函数获取主机API的详细信息。这些信息在配置音频硬件接口和调试音频流时非常有用。&lt;/p&gt;

&lt;h3&gt;2.5. 默认设备和设置&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.device&lt;/code&gt;: 默认音频设备的ID。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.device&lt;/code&gt; 是一个属性，它被用来存储和读取默认的输入和输出音频设备的索引。在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice&lt;/code&gt; 模块中，每个音频设备都由一个唯一的数字索引来标识。这个属性允许用户设置一个默认设备，该设备会在创建音频流时默认使用，除非在创建流时指定了其他设备。&lt;/p&gt;

&lt;p&gt;默认情况下，当 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice&lt;/code&gt; 模块初始化时，它会自动查询 PortAudio 接口并将系统中的默认音频设备的索引赋给 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.device&lt;/code&gt;。用户可以通过修改这个属性来更改默认的音频设备，这将影响所有后续创建的音频流，除非在创建流时手动指定了设备。&lt;/p&gt;

&lt;p&gt;该属性可以设置为单一值，这种情况下对输入和输出设备采用相同的设备索引，也可以设置为一个由两个值组成的元组或列表，分别指定输入和输出设备的设备索引。&lt;/p&gt;

&lt;p&gt;下面是一些使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.device&lt;/code&gt; 的示例：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 查询所有可用的音频设备
&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;query_devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 将默认的音频设备设置为第一个设备
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 分别设置默认的输入和输出设备
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 输入设备索引为1，输出设备索引为2
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 通过设备的名称查询设备索引并设置为默认设备
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;query_devices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;input_device_index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                           &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;My Favorite Input&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;output_device_index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;My Favorite Output&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_device_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output_device_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 检查当前设置的默认设备索引
&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 输出当前默认的输入和输出设备索引
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;注意：在使用时应确保指定的设备索引或名称是有效的，否则可能会抛出异常。如果所需设备的名称在多个设备中出现，可能需要更具体地指定设备名称或使用设备索引。&lt;/p&gt;

&lt;p&gt;最后，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.device&lt;/code&gt; 的设定将影响所有后续创建的音频流，直到该属性被重新赋值或整个模块被重新加载。系统管理员或用户可以根据需要配置此属性，以确保音频应用程序使用正确的音频设备。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.samplerate&lt;/code&gt;: 默认采样率。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;samplerate&lt;/code&gt;是sounddevice模块中的一个属性，它定义了在创建音频流时使用的默认采样率。采样率是指每秒钟采集或播放的样本数，通常以赫兹（Hz）来度量。更改该属性将影响对&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stream&lt;/code&gt;类实例化对象时未明确指定采样率的所有音频处理函数。&lt;/p&gt;

&lt;p&gt;在数字音频处理中，采样率是非常重要的参数，因为它会影响音频的质量和处理的复杂度。标准的CD品质采样率为44100Hz，而专业音频设备的采样率可能是48000Hz或更高。&lt;/p&gt;

&lt;p&gt;在sounddevice模块中，如果没有明确给出&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;samplerate&lt;/code&gt;，那么在使用诸如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;play&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rec&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playrec&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stream&lt;/code&gt;等功能创建音频流时，将使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.samplerate&lt;/code&gt;作为默认值，如果它也没有被设置，那么将根据使用的音频设备来确定采样率。&lt;/p&gt;

&lt;p&gt;如果想在没有指定具体采样率的情况下使用不同的默认值，可以通过设置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.samplerate&lt;/code&gt;来实现。&lt;/p&gt;

&lt;p&gt;示例用法：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 将默认采样率设置为48000Hz
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;samplerate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;48000&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 创建一个新的Stream对象，它将使用上面设置的默认采样率
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在上述示例中，我们将默认采样率修改为48000Hz并创建了一个新的Stream对象。由于没有为Stream对象指定采样率，它将使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;samplerate&lt;/code&gt;属性中指定的默认值。&lt;/p&gt;

&lt;p&gt;通常，采样率的选择取决于特定应用或音频硬件的要求。例如，在音频播放、录音或音频分析某些特定应用程序中，可能需要选择更高或更低的采样率以实现最佳性能。&lt;/p&gt;

&lt;p&gt;如果需要重置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;samplerate&lt;/code&gt;为其初始化状态（即PortAudio库的默认设置），可以将其赋值为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt;：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# 重置默认采样率
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;samplerate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在以上命令执行后，当新的Stream对象被创建且没有明确指定采样率时，将使用PortAudio库提供的默认采样率。&lt;/p&gt;

&lt;h3&gt;2.6. 异常&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.PortAudioError&lt;/code&gt;: 封装PortAudio错误的异常类。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.PortAudioError&lt;/code&gt; 是在使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice&lt;/code&gt; 模块时操作PortAudio库时可能引发的异常类。当PortAudio API调用返回错误时，该异常会被触发。PortAudio是用于音频捕获和播放的跨平台开源音频API，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice&lt;/code&gt; 模块则为Python环境提供了PortAudio的简洁接口。&lt;/p&gt;

&lt;p&gt;在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.PortAudioError&lt;/code&gt; 异常类中包含了通常用于描述错误的多个属性。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;属性&lt;/strong&gt;：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;args&lt;/code&gt;: 包含关于错误的详细信息的元组。元组中的内容可能包含以下元素：&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;字符串描述的错误信息。&lt;/li&gt;
      &lt;li&gt;PortAudio错误代码，即 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PaErrorCode&lt;/code&gt; 的值。&lt;/li&gt;
      &lt;li&gt;包含主机API索引号、主机错误代码及主机错误消息的三元组。&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;行为&lt;/strong&gt;：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;当在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice&lt;/code&gt; 模块中使用PortAudio相关函数时，例如打开或关闭音频流、录音、播放等，如果底层PortAudio库调用失败，可能会抛出 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PortAudioError&lt;/code&gt; 异常。&lt;/li&gt;
  &lt;li&gt;在引发此异常时，它会捕获并提供有关发生错误的具体细节，这有助于调试和识别问题的起因。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;以下是如何在代码中处理 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.PortAudioError&lt;/code&gt; 的一个例子。&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 尝试做一些涉及音频的操作，比如打开音频流
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;samplerate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;44100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 更多的音频处理...
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PortAudioError&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 如果发生PortAudioError异常，我们可以在这里处理它
&lt;/span&gt;    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;注意事项&lt;/strong&gt;：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;通常，当你在正确配置音频I/O设备时无需担心此异常。但在音频设备权限不足、配置不正确或它正被其他应用程序独占使用时，可能会遇到这个错误。&lt;/li&gt;
  &lt;li&gt;正常操作PortAudio时，最好在所有可能出错的地方进行异常捕获，以确保程序的健壮性和异常信息的捕获。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.PortAudioError&lt;/code&gt; 内部也会包含一个指向具体系统音频层错误的引用（如ASIO、WASAPI、ALSA等），这为进一步的错误诊断提供了便利。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.PortAudioError&lt;/code&gt; 异常是你在使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice&lt;/code&gt; 模块进行音频操作时，与PortAudio交互出现问题的信号。理解和正确处理这个异常对于开发稳定可靠的音频应用程序至关重要。&lt;/p&gt;

&lt;h3&gt;2.7. 回调处理&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.CallbackFlags&lt;/code&gt;: 告知回调函数的音频流状况。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.CallbackFlags&lt;/code&gt; 是一个类，它的实例被用作音频流回调中的状态标志。这些标志表明在处理音频数据时是否发生了输入或输出缓冲区的下溢（underflow）或上溢（overflow）等问题。如果在处理音频数据时遇到此类问题，应该检查音频流的配置，并尝试通过调整采样率、缓冲区大小或其它参数来优化性能。&lt;/p&gt;

&lt;p&gt;回调函数的状态参数包含一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CallbackFlags&lt;/code&gt; 实例，其中可能包含以下几个布尔属性，用于指示相应的问题是否发生。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input_underflow&lt;/code&gt;：
为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; 表示输入缓冲区（recording buffer）中数据量不足，导致需要输入数据时并未能提供足够的数据给音频设备。这可能是因为音频回调函数未能及时处理输入数据，或处理耗时过长导致的。通常，这种情况下听到的会是中断或噪声。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input_overflow&lt;/code&gt;：
为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; 表明输入缓冲区中的数据超载，导致一部分数据丢失。在输入流中，这通常是因为数据的到达速度超过了应用程序处理的能力。这可能导致录音中断或失真。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;output_underflow&lt;/code&gt;：
为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; 表示输出缓冲区（playback buffer）的数据量不够，没有足够的数据写入音频设备用于播放。这会导致播放时听到的音频出现中断或”卡顿”。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;output_overflow&lt;/code&gt;：
为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; 表明输出缓冲区中的数据溢出，通常这是因为应用程序生成数据的速度慢于音频设备的播放速度。注意，这对于输出流通常并不适用，因为在正常情况下，输出缓冲区不会溢出。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;priming_output&lt;/code&gt;：
为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt; 表明部分或全部输出数据将用于启动（prime）流，输入数据可能为零。当设置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prime_output_buffers_using_stream_callback=True&lt;/code&gt;时，将调用音频流回调来填充初始输出缓冲区，而不使用默认的静音填充。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;以下是如何使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.CallbackFlags&lt;/code&gt; 的一个示例：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;indata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outdata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_overflow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Input overflow!&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output_underflow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Output underflow!&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 在此进行音频数据处理 ...
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;outdata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indata&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 例如，此处将输入直接复制到输出（延迟播放）
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 使音频流播放一段时间
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在此示例中，我们定义了一个回调函数 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;callback&lt;/code&gt;，它在每次被音频流调用时检查状态，并打印出相应的溢出/下溢问题。利用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CallbackFlags&lt;/code&gt;，我们可以监视这些情况，并在我们的代码中适当地响应这些错误信息。&lt;/p&gt;

&lt;p&gt;注意：过多的缓冲下溢/上溢表明音频处理可能存在性能瓶颈或配置问题，这可能需要代码优化或硬件配置调整。&lt;/p&gt;

&lt;h3&gt;2.8. 配置&lt;/h3&gt;

&lt;h4&gt;2.8.1. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.AsioSettings&lt;/code&gt;: 为ASIO设备提供额外的配置&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.AsioSettings&lt;/code&gt;类是面向Windows操作系统的音频驱动ASIO (Audio Stream Input/Output) 的专有配置选项。ASIO是由Steinberg公司开发的一种音频驱动规范，它能够在Windows平台上提供低延迟和高性能的音频流。该类提供了使用特定ASIO音频输入/输出设备时的附加设置，通常用于音频应用或数字音频工作站（DAW）中。&lt;/p&gt;

&lt;p&gt;使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsioSettings&lt;/code&gt;类时，需要提供ASIO通道选择器的参数，这是一个整数列表，指示要使用的ASIO设备的通道编号。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;实例化方法&lt;/strong&gt;：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AsioSettings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channel_selectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;参数&lt;/strong&gt;：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;channel_selectors&lt;/strong&gt;：一个整数列表，它指定了要使用的ASIO设备的通道编号（索引从0开始）。这个列表的长度必须和当时使用的输入输出通道数一致。在这个列表中，每个通道编号都应该在设备支持的通道数范围之内。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;假设某个ASIO设备有8个通道，而你只想使用其中的第1、4和第5通道，你应该这样设置：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;channels_to_use&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# ASIO通道编号从0开始
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asio_settings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AsioSettings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channel_selectors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channels_to_use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样设置后，当你创建一个音频流时可以用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;asio_settings&lt;/code&gt;对象作为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extra_settings&lt;/code&gt;参数。&lt;/p&gt;

&lt;p&gt;当你想要对音频捕获和播放的处理有更精细的控制时，特别是在需要低延迟的情况下，ASIO设置就非常有用。例如，对于专业的音频处理和现场表演，使用ASIO驱动和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsioSettings&lt;/code&gt;可以提供稳定且响应快速的音频输入/输出能力。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;注意事项&lt;/strong&gt;：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ASIO是专为Windows系统设计的，并且需要一块支持ASIO的音频接口硬件。&lt;/li&gt;
  &lt;li&gt;ASIO通道选择器是高级设置，只有对声卡和ASIO有较深理解的用户才建议使用。&lt;/li&gt;
  &lt;li&gt;如果不当地使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channel_selectors&lt;/code&gt;，例如给出了过长或过短的列表、通道编号范围错误，可能会导致程序崩溃或运行异常。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;正是由于这些设置提供了对较低层次和较为底层的音频设备参数的控制，因此&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AsioSettings&lt;/code&gt;在准确配置和优化音频性能方面扮演着重要角色。&lt;/p&gt;

&lt;h4&gt;2.8.2. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.CoreAudioSettings&lt;/code&gt;: 为Mac OS X Core Audio设备提供额外的配置&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.CoreAudioSettings&lt;/code&gt; 是一个用于 Mac OS X Core Audio 设备的特定配置类。它提供了一种方式，让用户可以设置与 Core Audio 相关的高级参数。这个类可以用在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.Stream()&lt;/code&gt; 及其变体中作为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extra_settings&lt;/code&gt; 参数，或者用于 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.default.extra_settings&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;下面详细说明 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sounddevice.CoreAudioSettings&lt;/code&gt; 的构造函数：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CoreAudioSettings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channel_map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;change_device_parameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                 &lt;span class=&quot;n&quot;&gt;fail_if_conversion_required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;conversion_quality&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;参数说明&lt;/strong&gt;：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channel_map&lt;/code&gt; (序列类型，int 类型，可选): 用于只打开 Core Audio 设备特定的通道。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channel_map&lt;/code&gt; 的处理方式在输入和输出通道上是不同的。&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;对于输入设备，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channel_map&lt;/code&gt; 是指定使用的（从 0 开始计数的）通道号的整数列表。&lt;/li&gt;
      &lt;li&gt;对于输出设备，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channel_map&lt;/code&gt; 应该与设备的输出通道数长度相同。未使用的通道用 -1 来标记，需要的通道用 0 开始的索引指定。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;change_device_parameters&lt;/code&gt; (布尔型，可选): 如果设置为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，允许 PortAudio 更改设备的帧大小等参数，这样可以获得更低的延迟，但如果设备正被其他程序使用，就可能会冲突。默认值为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;False&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fail_if_conversion_required&lt;/code&gt; (布尔型，可选): 结合上面的参数使用，若设为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，仅当设备支持精确的采样率时才会打开流。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conversion_quality&lt;/code&gt; (字符串，可选): 用于设置 Core Audio 的采样率转换品质，可选项有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;min&apos;&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;low&apos;&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;medium&apos;&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;high&apos;&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;max&apos;&lt;/code&gt;，默认为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;max&apos;&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;以下示例演示了如何将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CoreAudioSettings&lt;/code&gt; 用于音频流的创建和修改 Core Audio 的高级设置：&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 设置 Core Audio 特定的通道映射和参数
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coreaudio_settings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;CoreAudioSettings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;channel_map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 用前两个通道，其他的设置为-1
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;change_device_parameters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fail_if_conversion_required&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;conversion_quality&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;high&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;# 确保高质量的采样率转换
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# 使用特定的 Core Audio 设置创建一个输出流
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;OutputStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra_settings&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;coreaudio_settings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# 读取和播放音频数据
&lt;/span&gt;    &lt;span class=&quot;bp&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# 也可以将 CoreAudioSettings 对象赋值给默认的 extra_settings
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extra_settings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;coreaudio_settings&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在这个例子中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;channel_map&lt;/code&gt; 设置了四个通道的映射，指定了仅使用前两个通道，而通过设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;change_device_parameters&lt;/code&gt; 为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;True&lt;/code&gt;，该设置允许 PortAudio 在需要时更改设备参数以获得更低的延迟。&lt;/p&gt;

&lt;p&gt;更多关于 Core Audio 设置的细节可以参考 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PortAudio&lt;/code&gt;_ 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Core Audio&lt;/code&gt;_ 的官方文档。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;_PortAudio: http://www.portaudio.com/&lt;/li&gt;
  &lt;li&gt;_Core Audio: https://developer.apple.com/documentation/coreaudio&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;请注意，本示例仅为演示，实际使用中需要根据实际设备及需求适配参数。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="python" />
      
        <category term="audio" />
      
        <category term="sounddevice" />
      

      

      
        <summary type="html">Sounddevice 是一个用于录制和播放音频的Python库，它以直观的API为特色，并为PortAudio音频I/O库提供了一个封装。Sounddevice是 cross-platform，支持多种操作系统和硬件设备。以下是一些比较常见的例子： 实时音频处理：利用 sounddevice.Stream 对象，可以实现低延迟的实时音频信号处理。音乐家和音频工程师可能使用 Sounddevice 来处理实时音乐表演的音频信号，比如实时混音、音频特效的添加和态音频信号监测。 音频录制：Sounddevice 可用于录制音频信号，例如录制演讲、会议内容或者音乐创作时的素材。例如，可以使用 sounddevice.InputStream 类来监听音频输入设备，并将接收到的音频数据保存到文件。 音频播放：与音频录制相对，Sounddevice 也可以用于播放音频文件。例如，在播放器或音乐应用程序中，可以利用 sounddevice.OutputStream 来播放音乐和声效。 实验和教育：在教育和研究场景中，Sounddevice 作为一个易于使用的包，允许学生和研究人员探索数字信号处理的概念。例如，在数字音频处理的课程中，可以利用它来演示滤波器、FFT变换和其他信号处理方法的效果。 音频分析：Sounddevice 可以用于音频信号的分析，比如声音识别、频谱分析或者音乐信息检索。例如，可以从输入流获取音频数据，使用信号处理技术进行分析，并提取需要的信息，如节拍、音高或声音特征。 输入/输出流路由：对于需要定制音频流路由的复杂应用程式，Sounddevice 可以提供高级的输入/输出流管理。比如一个虚拟音频合成器可能需要将多个输入信号路由到不同效果处理链中，然后再混合输出。 人机交互：在需要音频作为交互媒介的应用中，如语音指令识别或音频反馈，Sounddevice 可以实现音频的捕获和输出。 1. 初始化与终止 当sounddevice模块被导入时，PortAudio系统会自动被初始化。在大多数情况下，用户无需手动初始化或终止。如果需要，可以使用sounddevice._initialize()和sounddevice._terminate()来手动管理。 2. 核心对象和函数 2.1. Stream 对象 sounddevice.Stream: 一个全双工的音频流。通过实例化这个类可以同时处理音频的播放和录音。该对象提供了开始(start)、停止(stop)、中止(abort)和关闭(close)流的方法。下面列举了创建 Stream 对象时可以使用的一些参数以及它们的作用： samplerate：采样率，以赫兹（Hz）为单位，确定每秒钟采集和播放的样本数。标准的CD质量采样率是44100Hz。 blocksize：块大小，定义了传递给 stream 回调函数的帧数，或阻塞型读/写流的首选块粒度。0 表示使用主机 API 的最佳块大小。 device：设备索引或查询字符串，指定要使用的输入/输出设备。如果未指定，默认从 sounddevice.default.device 中获取设置。 channels：通道数，定义了要传递给流回调函数的声音通道数，或者 read()/write() 访问的通道数。 dtype：数据类型，指定了提供给流回调函数、read() 或 write() 的 numpy 数组的样本格式。支持的格式有 ‘float32’、’int32’、’int16’、’int8’、’uint8’ 等。 latency：延迟，以秒为单位，表示期望的流延迟时间。&apos;low&apos; 和 &apos;high&apos; 分别代表设备的默认低延迟和高延迟配置。 extra_settings：特定于主机 API 的额外设置，如 ASIO 的通道选择等。 callback：用户提供的回调函数，用于在流活动期间生成或处理音频数据。回调函数的参数定义了输入和输出缓冲区，帧数，回调时间和状态。 finished_callback：用户提供的回调函数，当流变为非活动状态时调用。 clip_off：布尔值，设置为 True 以禁用默认的剪裁。 dither_off：布尔值，设置为 True 以禁用默认的抖动。 never_drop_input：布尔值，对于全双工流，设置为 True 可请求不丢弃溢出的输入样本。 prime_output_buffers_using_stream_callback：布尔值，设置为 True 会在初始输出缓冲区上调用流回调进行填充，而不是使用默认的 0 填充。 这些参数允许在创建 Stream 对象时进行精细控制，优化音频流的行为以匹配特定应用程序的需求。 以下是使用 sounddevice.Stream 对象的代码示例： import sounddevice as sd import numpy as np # 采样率 fs = 44100 # 持续时间（秒） duration = 5 # 回调函数 def callback(indata, outdata, frames, time, status): if status: print(status) # 在此处处理音频数据 outdata[:] = indata # 直接将输入数据复制到输出数据中，形成回声 # 打开音频流 with sd.Stream(callback=callback, samplerate=fs, channels=2) as stream: # 准备开始录制五秒音频 sd.sleep(int(duration * 1000)) # 暂停主线程，允许音频流处理音频数据 在这个例子中，我们定义了一个采样率为 44.1 kHz 的音频流，双声道输入和输出。callback 函数用于处理音频数据，在本例中，它简单地将接收到的输入数据复制到输出数据中，这将导致音频信号被回放（回声效果）。 注意，通过使用 Python 的 with 语句，我们保证音频流在退出代码块时被正确关闭。我们在 with 代码块中使用 sd.sleep() 函数来避免主线程终止，在这段时间内 callback 函数会不断地被调用并处理音频数据。 请根据实际应用调整回调函数 callback 中音频处理的逻辑。 2.2. 输入/输出流 2.2.1. sounddevice.InputStream: 专门用于录音的流 sounddevice.InputStream 是用于录音的流对象。您可以创建一个 InputStream 实例来接收音频数据，这些数据可以用于实时处理或保存至文件。以下是 InputStream 类的构造函数参数的详细解释： samplerate (可选): 以赫兹（Hz）为单位的采样率，确定每秒钟采集的样本数。标准CD质量是44100Hz。如果未指定，默认使用 sounddevice.default.samplerate 的设置。 blocksize (可选): 块大小，定义了传递给 stream 回调函数的帧数。 0 表示使用主机 API 的最佳块大小。如果未指定，默认使用 sounddevice.default.blocksize 的设置。 device (可选): 设备索引或查询字符串，指定要使用的音频输入设备。如果未指定，默认从 sounddevice.default.device 中获取输入设备的设置。 channels (可选): 音频通道数，定义了要传递给 stream 设备的声道数量。如果未指定，默认使用 sounddevice.default.channels 中的输入通道数设置。 dtype (可选): 数据类型，指定了为录音数据指定的 NumPy 数组的数据类型。支持的格式包括 ‘float32’、’int32’、’int16’、’int8’ 和 ‘uint8’。如果未指定，默认使用 sounddevice.default.dtype 中的输入数据类型。 latency (可选): 延迟，以秒为单位，表示流的期望延迟时间。值可以是具体的延迟时间，或字符串 &apos;low&apos; 和 &apos;high&apos;，分别代表设备的默认低延迟和高延迟配置。如果未指定，默认使用 sounddevice.default.latency 中的输入设备延迟。 extra_settings (可选): 特定于主机 API 的额外设置，例如使用 ASIO 驱动时可指定的额外设置如 sounddevice.AsioSettings。 callback (可选): 用户提供的回调函数，用于在流活动期间处理音频数据。回调函数接收几个参数：输入数据、帧数、时间信息以及状态，它必须返回 None。 finished_callback (可选): 用户提供的回调函数，当流变为非活动状态时调用。例如，可以用于清理在录音过程中使用的资源。 clip_off (可选): 布尔值，如果设置为 True，将关闭默认的剪裁功能，否则超出范围的样本将被剪裁为有效的最大/最小值。 dither_off (可选): 布尔值，如果设置为 True，将关闭默认的抖动功能。 never_drop_input (可选): 布尔值，对于全双工流，将此项设为 True 可以保证不会丢弃溢出的输入样本。 prime_output_buffers_using_stream_callback (可选): 布尔值，如果设为 True，流的输出缓冲区会在开始时使用回调函数来填充，而不是默认的零填充。 创建一个 InputStream 实例用于录制音频，并打印状态消息： import sounddevice as sd # 回调函数处理录音数据 def callback(indata, frames, time, status): if status: print(status) # 创建 InputStream 对象 stream = sd.InputStream(callback=callback) # 开始录音 with stream: sd.sleep(5000) # 录音 5 秒钟 在这个例子中，回调函数仅检查并打印状态信息，但实际中您可能需要将输入数据 indata 写入文件或进行进一步处理。通过使用 Python 的 with 语句，我们确保在代码块结束时 InputStream 会被正确关闭，并且通过 sd.sleep() 暂停主线程，允许音频流在此期间处理音频数据。 2.2.2. sounddevice.OutputStream: 专门用于播放音频的流 在 sounddevice 库中，OutputStream 类用于创建一个只支持音频播放的流。下面是它的参数的详细解释和使用方法： OutputStream类的构造函数接收以下参数： samplerate (可选): 采样率，以赫兹（Hz）为单位。这是每秒钟捕获和播放的样本数。如果未指定，默认使用 sounddevice.default.samplerate 的设置。 blocksize (可选): 块大小，定义了传递给流的回调函数的帧数。 0 表示使用主机 API 的最佳块大小。如果未指定，默认使用 sounddevice.default.blocksize 的设置。 device (可选): 设备索引或查询字符串，指定要使用的音频输出设备。如果未指定，默认从 sounddevice.default.device 中获取输出设备的设置。 channels (可选): 音频通道数，定义了要传递给流的声道数量。如果未指定，默认使用 sounddevice.default.channels 中的输出通道数设置。 dtype (可选): 数据类型，指定了为播放数据指定的 NumPy 数组的数据类型。支持的格式包括 ‘float32’、’int32’、’int16’、’int8’ 和 ‘uint8’。如果未指定，默认使用 sounddevice.default.dtype 中的输出数据类型。 latency (可选): 延迟，以秒为单位，表示流的期望延迟时间。值可以是具体的延迟时间，或字符串 &apos;low&apos; 和 &apos;high&apos;，分别代表设备的默认低延迟和高延迟配置。如果未指定，默认使用 sounddevice.default.latency 中的输出设备延迟。 extra_settings (可选): 特定于主机 API 的额外设置，例如使用 ASIO 驱动时可指定的额外设置如 sounddevice.AsioSettings。 callback (可选): 用户提供的回调函数，用于在流活动期间生成音频数据。回调函数接收几个参数：输出数据、帧数、时间信息以及状态，它必须返回 None。 finished_callback (可选): 用户提供的回调函数，当流变为非活动状态时调用。例如，可以用于清理在播放过程中使用的资源。 clip_off (可选): 布尔值，如果设置为 True，将关闭默认的剪裁功能，否则超出范围的样本将被剪裁为有效的最大/最小值。 dither_off (可选): 布尔值，如果设置为 True，将关闭默认的抖动功能。 never_drop_input (可选): 布尔值，对于全双工流，将此项设为 True 可以保证不会丢弃溢出的输入样本。 prime_output_buffers_using_stream_callback (可选): 布尔值，如果设为 True，流的输出缓冲区会在开始时使用回调函数来填充，而不是默认的零填充。 具体使用时，需要根据自己的需求配置参数。以下演示一个创建 OutputStream 对象并播放一段随机生成的声音的示例： import sounddevice as sd import numpy as np # 生成一秒钟的随机噪音 fs = 44100 # 采样率 data = np.random.uniform(-1, 1, fs) # 创建输出流 stream = sd.OutputStream(samplerate=fs, channels=1) # 启动输出流并播放数据 with stream: stream.write(data) 在这个示例中，我们首先生成了随机音频数据，然后创建了一个 OutputStream 对象进行播放。需要注意的是，OutputStream 类的实例也可以作为上下文管理器使用，在 with 语句块结束时自动关闭流。 2.3. 播放与录制函数 2.3.1. sounddevice.play(): 用于播放NumPy数组中的音频信号 sounddevice.play() 函数是用于通过Python的sounddevice库播放NumPy数组中的音频数据的便捷函数。它简化了音频播放的过程，让用户不必手动创建和管理音频流。下面将详细解释该函数的参数以及其用途： data (array_like): 包含音频数据的数组。如果数组是二维的，每一列都表示一个通道；如果是一维数组，则视为单声道数据。此参数是必需的。 samplerate (float, 可选): 音频的采样率，以赫兹（Hz）为单位。如果未指定，则使用默认设备的采样率。此参数对音频的播放速度和音调都有影响。 mapping (array_like, 可选): 一个列表，用于指定哪些通道用于播放data中的音频。列表中的每个数字对应一个通道编号（编号从1开始）。如果未指定，则音频数据将被播放到默认的输出设备通道上。 blocking (bool, 可选): 如果为True，play() 调用将阻塞，直到全部数据播放完毕。如果为False（默认值），将在后台进行播放，并且函数会立即返回。非阻塞调用可以随时使用sounddevice.stop()停止。 loop (bool, 可选): 如果为True，音频数据将循环播放，直到明确停止。 **kwargs: 其他传递给OutputStream的关键字参数。 play()函数没有返回值。如果在播放时发生错误，则会抛出sounddevice.PortAudioError异常。 播放一个440 Hz的正弦波: import sounddevice as sd import numpy as np fs = 44100 # 采样率 f = 440 # 频率, Hz seconds = 1 # 持续时间秒 t = np.linspace(0, seconds, int(fs*seconds), endpoint=False) data = np.sin(2 * np.pi * f * t) sd.play(data, samplerate=fs) sd.wait() # 等待直到数据播放完成 上面的例子创建了一个时长为1秒的正弦波信号，并用采样率为44100 Hz播放它。在播放后，代码使用sd.wait()保持程序阻塞，直到播放结束。 注意：使用sounddevice.play()时应该确保你的NumPy数组中的数据类型与声音设备可接受的数据类型匹配。通常，一种安全的选择是使用float32数据类型，其取值范围为-1.0到1.0。 2.3.2. sounddevice.rec(): 用于录制音频并将结果存储在NumPy数组中 函数 sounddevice.rec() 用于录制音频并将结果存储在NumPy数组中。以下是sounddevice.rec()的参数详解： frames: 录音帧数。一帧对应于所有通道的单个样本集合。例如，若要录制5秒的音频，并且采样率（samplerate）是44100，那么frames将是5*44100。 samplerate: 采样率，以赫兹（Hz）为单位。这是每秒钟捕获和播放的样本数。常见的采样率包括44100（CD质量）、48000（专业音频设备）等。 channels: 录制的通道数。单声道为1，立体声为2。 dtype: 指定录制数据的数据类型。常用类型包括&apos;float32&apos;和&apos;int16&apos;。&apos;float32&apos;将样本值范围规范化为从-1.0到+1.0，而&apos;int16&apos;是16位整型，表示的范围则是-32768到+32767。 out: 可选。输出的NumPy数组。如果指定了out参数，则将在该数组中放置录制的音频数据，否则内部会创建一个新数组。 mapping: 可选。这是一个指定哪些通道（从1开始编号）实际用于录音的序列。通常情况下，默认的设备所有通道都会被使用。（此参数并未在原文的注释中提到，但在函数API中存在。） blocking: 可选。默认值为False。如果设置为True，函数调用将阻塞，直到录制完成。否则，它会立即返回，并且需要外部逻辑来确保录制完成，通常是通过sounddevice.wait()函数。 **kwargs: 其他一些可选的关键字参数，可能在未来版本的sounddevice模块中添加。 示例用法： import sounddevice as sd fs = 44100 # 采样率 duration = 5 # 持续时间（秒） # 录制 myrecording = sd.rec(int(duration * fs), samplerate=fs, channels=2, dtype=&apos;float32&apos;) sd.wait() # myrecording 现在包含了录制的音频数据 这将录制5秒钟的立体声音频，并在NumPy数组myrecording中以32位浮点格式保存样本数据。通过sd.wait()确保录音完成，然后可以进一步处理或保存录音数据。 2.3.3. sounddevice.playrec(): 同时录制和播放音频 函数 sounddevice.playrec() 用于同时进行音频的播放和录制，并将播放的音频和录制的音频结果作为 NumPy 数组返回。 sounddevice.playrec() 是一个高度灵活的函数，它结合了音频播放和录制功能。在实时音频处理中，这个函数非常有用。以下是一些典型应用场景： 回声消除测试： 开发音频处理中的回声消除算法时，可以使用 playrec() 播放一段音频并同时录制麦克风输入，以便分析回声效果并优化算法。 实时音频效果处理： 对于音乐制作者和声音工程师而言，playrec() 可以实现实时音效处理，比如实时添加混响、均衡器设定或其他音频效果。 乐器调音软件： 乐器练习时可以通过 playrec() 获取乐器声音输入，并实时提供调音反馈，从而辅助乐器的准确调音。 音频同步应用： 在音视频开发中，playrec() 可以在播放音轨的同时录制声音，帮助开发者实现音频与视频的精确同步。 双向通讯应用： 在VoIP通讯或语音会议系统中，playrec() 可以同时处理语音输入和输出流，实现如电话会议等双向通信功能。 声音识别测试： 使用 playrec() 进行声音识别训练时，可以在播放特定声音的同时录制环境中的声音响应，用于声音识别算法的训练和测试。 声学测量： 在声学测量和分析中，通过 playrec() 播放已知测试信号并录制响应，以测量房间的声学特性或扬声器的频率响应。 教育与研究： 教育和研究领域中，playrec() 可以用来演示和探讨声音的录制和播放原理，以及数字信号处理的实时应用案例。 playrec() 由于其实时性和便捷性，成为了音频处理应用程序中不可或缺的函数之一。它使应用程序能够同时控制音频的输入和输出，从而支持多种复杂的音频处理流程。 以下是sounddevice.playrec()的参数详解： data: array_like 要播放的音频数据的数组。如果数组是二维的，每一列都表示一个通道；如果是一维数组，则视为单声道数据。这个参数是必需的。 samplerate: float, 可选 音频的采样率，以赫兹（Hz）为单位。如果未指定，则使用默认设备的采样率。 channels: int, 可选 录制的通道数。单声道为1，立体声为2。 dtype: str 或 numpy.dtype, 可选 指定录制数据的数据类型。常用类型包括 &apos;float32&apos; 和 &apos;int16&apos;。&apos;float32&apos; 将样本值范围规范化为从-1.0到+1.0，而 &apos;int16&apos; 是16位整型，表示的范围则是-32768到+32767。 out: numpy.ndarray 或子类, 可选 如果指定了 out 参数，则将在该数组中放置录制的音频数据，否则内部会创建一个新数组。 mapping: array_like, 可选 这是一个指定哪些通道（从1开始编号）实际用于播放和录音的序列。通常情况下，默认的设备所有通道都会被使用。 blocking: bool, 可选 默认值为 False。如果设置为 True，函数调用将阻塞，直到录制完成。否则，它会立即返回，并且需要外部逻辑来确保录制完成，通常是通过 sounddevice.wait() 函数。 **kwargs: 其他一些可选的关键字参数。 示例用法： import sounddevice as sd import numpy as np # 创建音频数据 fs = 44100 # 采样率 duration = 5 # 持续时间（秒） frequency = 440 # 频率（Hz） samples = (np.sin(2 * np.pi * np.arange(fs * duration) * frequency / fs)).astype(np.float32) # 播放并录制音频 myrecording = sd.playrec(samples, samplerate=fs, channels=2, dtype=&apos;float32&apos;) sd.wait() # 等待直到数据播放和录制完成 在这个例子中，我们首先生成一个时长为5秒，频率为440 Hz的正弦波音频数据，并用采样率为44100 Hz的设定将其播放出去。同时，我们还录制了音频，保存在 myrecording 这个 NumPy 数组中。播放和录制完成后，使用 sd.wait() 函数来确保操作完成。 2.4. 查询函数 2.4.1. sounddevice.query_devices(): 查询可用的音频输入/输出设备 sounddevice.query_devices() 是一个函数，它查询可用的音频输入/输出设备，并返回有关这些设备的信息。这个函数可以在不带参数的情况下调用，也可以接受一些可选参数来查询特定的设备或者设备的特定类型（输入或输出）。返回的结果取决于所传递的参数。 device (可选): 可以是一个设备的数字ID或者设备名称的字符串。如果指定了这个参数，query_devices() 只会返回有关这个特定设备的信息。如果不指定或为None，则返回所有可用设备的信息。 kind (可选): 可以是 &apos;input&apos; 或 &apos;output&apos;。如果指定了 kind 而没有指定 device，则函数返回有关默认输入或输出设备的信息。如果 device 也被指定，kind 参数将决定要查询输入还是输出属性（如果设备同时支持输入和输出）。 当不带任何参数调用时，返回一个包含所有可用设备信息的 sounddevice.DeviceList 对象，其中每个设备的信息用一个字典表示，键包括设备的名称、索引号、所属的主机API、最大输入/输出通道数、默认低延迟和高延迟值以及默认采样频率等。 如果 device 或 kind 被指定，则返回一个含有所请求设备信息的字典。 查询所有可用设备： import sounddevice as sd devices = sd.query_devices() print(devices) 查询特定设备的信息： device_info = sd.query_devices(device=2) # 查询设备ID为2的设备 print(device_info) 查询默认输出设备的信息： default_output_device = sd.query_devices(kind=&apos;output&apos;) print(default_output_device) 查询默认输入设备的信息： default_input_device = sd.query_devices(kind=&apos;input&apos;) print(default_input_device) 在实际使用 query_devices() 时，通常需要查看设备的特性（例如支持的通道数或者默认延迟），或者在打开音频流之前选择合适的设备。此外，这个函数还可以在音频设备调试和选择最佳设备时提供有用的信息。 2.4.2. sounddevice.query_hostapis(): 查询可用的音频主机API信息 sounddevice.query_hostapis() 函数用于查询计算机上可用的音频主机API。在PortAudio中，主机API是具体的音频接口，比如ASIO, DirectSound, WASAPI (在Windows上) 或者 ALSA, OSS, JACK (在Linux上)。此函数用来获取有关这些音频主机API的信息，这对于了解系统配置和调试音频问题非常有用。 sounddevice.query_hostapis()函数只接受一个可选参数： index: int, 可选 若指定，将仅返回关于给定主机API index 的信息，呈现为一个字典。 函数的返回值取决于是否指定了 index 参数： 若未指定 index，函数返回一个包含每个可用主机API信息的tuple，其中每个API的信息都以字典形式存在。 若指定 index，将返回一个字典，包含指定主机API的信息。 每个API信息的字典都包含以下键： &apos;name&apos;: 主机API的名称。 &apos;devices&apos;: 属于此主机API的设备ID列表。使用 query_devices() 获取有关设备的信息。 &apos;default_input_device&apos;, &apos;default_output_device&apos;: 对应于每个主机API的默认输入/输出设备ID。若不存在默认输入/输出设备，则值为-1。 这些信息可以帮助您选择合适的主机API和设备来打开音频流。 查询所有可用的音频主机API: import sounddevice as sd hostapis = sd.query_hostapis() print(hostapis) 查询特定主机API的信息： index = 0 # 假设我们想查询第一个主机API的信息 hostapi_info = sd.query_hostapis(index) print(hostapi_info) 获取默认输入设备的主机API： default_hostapi = sd.query_hostapis(sd.default.hostapi) print(default_hostapi) 这些示例显示了如何使用sounddevice.query_hostapis()函数获取主机API的详细信息。这些信息在配置音频硬件接口和调试音频流时非常有用。 2.5. 默认设备和设置 sounddevice.default.device: 默认音频设备的ID。 sounddevice.default.device 是一个属性，它被用来存储和读取默认的输入和输出音频设备的索引。在 sounddevice 模块中，每个音频设备都由一个唯一的数字索引来标识。这个属性允许用户设置一个默认设备，该设备会在创建音频流时默认使用，除非在创建流时指定了其他设备。 默认情况下，当 sounddevice 模块初始化时，它会自动查询 PortAudio 接口并将系统中的默认音频设备的索引赋给 sounddevice.default.device。用户可以通过修改这个属性来更改默认的音频设备，这将影响所有后续创建的音频流，除非在创建流时手动指定了设备。 该属性可以设置为单一值，这种情况下对输入和输出设备采用相同的设备索引，也可以设置为一个由两个值组成的元组或列表，分别指定输入和输出设备的设备索引。 下面是一些使用 sounddevice.default.device 的示例： import sounddevice as sd # 查询所有可用的音频设备 print(sd.query_devices()) # 将默认的音频设备设置为第一个设备 sd.default.device = 0 # 分别设置默认的输入和输出设备 sd.default.device = (1, 2) # 输入设备索引为1，输出设备索引为2 # 通过设备的名称查询设备索引并设置为默认设备 device_info = sd.query_devices() input_device_index = next((index for index, d in enumerate(device_info) if &apos;My Favorite Input&apos; in d[&apos;name&apos;]), None) output_device_index = next((index for index, d in enumerate(device_info) if &apos;My Favorite Output&apos; in d[&apos;name&apos;]), None) sd.default.device = (input_device_index, output_device_index) # 检查当前设置的默认设备索引 print(sd.default.device) # 输出当前默认的输入和输出设备索引 注意：在使用时应确保指定的设备索引或名称是有效的，否则可能会抛出异常。如果所需设备的名称在多个设备中出现，可能需要更具体地指定设备名称或使用设备索引。 最后，sounddevice.default.device 的设定将影响所有后续创建的音频流，直到该属性被重新赋值或整个模块被重新加载。系统管理员或用户可以根据需要配置此属性，以确保音频应用程序使用正确的音频设备。 sounddevice.default.samplerate: 默认采样率。 samplerate是sounddevice模块中的一个属性，它定义了在创建音频流时使用的默认采样率。采样率是指每秒钟采集或播放的样本数，通常以赫兹（Hz）来度量。更改该属性将影响对Stream类实例化对象时未明确指定采样率的所有音频处理函数。 在数字音频处理中，采样率是非常重要的参数，因为它会影响音频的质量和处理的复杂度。标准的CD品质采样率为44100Hz，而专业音频设备的采样率可能是48000Hz或更高。 在sounddevice模块中，如果没有明确给出samplerate，那么在使用诸如play、rec、playrec和Stream等功能创建音频流时，将使用sounddevice.default.samplerate作为默认值，如果它也没有被设置，那么将根据使用的音频设备来确定采样率。 如果想在没有指定具体采样率的情况下使用不同的默认值，可以通过设置sounddevice.default.samplerate来实现。 示例用法： import sounddevice as sd # 将默认采样率设置为48000Hz sd.default.samplerate = 48000 # 创建一个新的Stream对象，它将使用上面设置的默认采样率 stream = sd.Stream(...) 在上述示例中，我们将默认采样率修改为48000Hz并创建了一个新的Stream对象。由于没有为Stream对象指定采样率，它将使用samplerate属性中指定的默认值。 通常，采样率的选择取决于特定应用或音频硬件的要求。例如，在音频播放、录音或音频分析某些特定应用程序中，可能需要选择更高或更低的采样率以实现最佳性能。 如果需要重置samplerate为其初始化状态（即PortAudio库的默认设置），可以将其赋值为None： # 重置默认采样率 sd.default.samplerate = None 在以上命令执行后，当新的Stream对象被创建且没有明确指定采样率时，将使用PortAudio库提供的默认采样率。 2.6. 异常 sounddevice.PortAudioError: 封装PortAudio错误的异常类。 sounddevice.PortAudioError 是在使用 sounddevice 模块时操作PortAudio库时可能引发的异常类。当PortAudio API调用返回错误时，该异常会被触发。PortAudio是用于音频捕获和播放的跨平台开源音频API，sounddevice 模块则为Python环境提供了PortAudio的简洁接口。 在 sounddevice.PortAudioError 异常类中包含了通常用于描述错误的多个属性。 属性： args: 包含关于错误的详细信息的元组。元组中的内容可能包含以下元素： 字符串描述的错误信息。 PortAudio错误代码，即 PaErrorCode 的值。 包含主机API索引号、主机错误代码及主机错误消息的三元组。 行为： 当在 sounddevice 模块中使用PortAudio相关函数时，例如打开或关闭音频流、录音、播放等，如果底层PortAudio库调用失败，可能会抛出 PortAudioError 异常。 在引发此异常时，它会捕获并提供有关发生错误的具体细节，这有助于调试和识别问题的起因。 以下是如何在代码中处理 sounddevice.PortAudioError 的一个例子。 import sounddevice as sd try: # 尝试做一些涉及音频的操作，比如打开音频流 stream = sd.Stream(samplerate=44100, channels=2) stream.start() # 更多的音频处理... except sd.PortAudioError as e: # 如果发生PortAudioError异常，我们可以在这里处理它 print(e) finally: if &apos;stream&apos; in locals() and stream.active: stream.stop() stream.close() 注意事项： 通常，当你在正确配置音频I/O设备时无需担心此异常。但在音频设备权限不足、配置不正确或它正被其他应用程序独占使用时，可能会遇到这个错误。 正常操作PortAudio时，最好在所有可能出错的地方进行异常捕获，以确保程序的健壮性和异常信息的捕获。 sounddevice.PortAudioError 内部也会包含一个指向具体系统音频层错误的引用（如ASIO、WASAPI、ALSA等），这为进一步的错误诊断提供了便利。 sounddevice.PortAudioError 异常是你在使用 sounddevice 模块进行音频操作时，与PortAudio交互出现问题的信号。理解和正确处理这个异常对于开发稳定可靠的音频应用程序至关重要。 2.7. 回调处理 sounddevice.CallbackFlags: 告知回调函数的音频流状况。 sounddevice.CallbackFlags 是一个类，它的实例被用作音频流回调中的状态标志。这些标志表明在处理音频数据时是否发生了输入或输出缓冲区的下溢（underflow）或上溢（overflow）等问题。如果在处理音频数据时遇到此类问题，应该检查音频流的配置，并尝试通过调整采样率、缓冲区大小或其它参数来优化性能。 回调函数的状态参数包含一个 CallbackFlags 实例，其中可能包含以下几个布尔属性，用于指示相应的问题是否发生。 input_underflow： 为 True 表示输入缓冲区（recording buffer）中数据量不足，导致需要输入数据时并未能提供足够的数据给音频设备。这可能是因为音频回调函数未能及时处理输入数据，或处理耗时过长导致的。通常，这种情况下听到的会是中断或噪声。 input_overflow： 为 True 表明输入缓冲区中的数据超载，导致一部分数据丢失。在输入流中，这通常是因为数据的到达速度超过了应用程序处理的能力。这可能导致录音中断或失真。 output_underflow： 为 True 表示输出缓冲区（playback buffer）的数据量不够，没有足够的数据写入音频设备用于播放。这会导致播放时听到的音频出现中断或”卡顿”。 output_overflow： 为 True 表明输出缓冲区中的数据溢出，通常这是因为应用程序生成数据的速度慢于音频设备的播放速度。注意，这对于输出流通常并不适用，因为在正常情况下，输出缓冲区不会溢出。 priming_output： 为 True 表明部分或全部输出数据将用于启动（prime）流，输入数据可能为零。当设置prime_output_buffers_using_stream_callback=True时，将调用音频流回调来填充初始输出缓冲区，而不使用默认的静音填充。 以下是如何使用 sounddevice.CallbackFlags 的一个示例： import sounddevice as sd def callback(indata, outdata, frames, time, status): if status.input_overflow: print(&apos;Input overflow!&apos;) if status.output_underflow: print(&apos;Output underflow!&apos;) # 在此进行音频数据处理 ... outdata[:] = indata # 例如，此处将输入直接复制到输出（延迟播放） stream = sd.Stream(callback=callback) with stream: sd.sleep(10000) # 使音频流播放一段时间 在此示例中，我们定义了一个回调函数 callback，它在每次被音频流调用时检查状态，并打印出相应的溢出/下溢问题。利用 CallbackFlags，我们可以监视这些情况，并在我们的代码中适当地响应这些错误信息。 注意：过多的缓冲下溢/上溢表明音频处理可能存在性能瓶颈或配置问题，这可能需要代码优化或硬件配置调整。 2.8. 配置 2.8.1. sounddevice.AsioSettings: 为ASIO设备提供额外的配置 sounddevice.AsioSettings类是面向Windows操作系统的音频驱动ASIO (Audio Stream Input/Output) 的专有配置选项。ASIO是由Steinberg公司开发的一种音频驱动规范，它能够在Windows平台上提供低延迟和高性能的音频流。该类提供了使用特定ASIO音频输入/输出设备时的附加设置，通常用于音频应用或数字音频工作站（DAW）中。 使用AsioSettings类时，需要提供ASIO通道选择器的参数，这是一个整数列表，指示要使用的ASIO设备的通道编号。 实例化方法： sounddevice.AsioSettings(channel_selectors) 参数： channel_selectors：一个整数列表，它指定了要使用的ASIO设备的通道编号（索引从0开始）。这个列表的长度必须和当时使用的输入输出通道数一致。在这个列表中，每个通道编号都应该在设备支持的通道数范围之内。 假设某个ASIO设备有8个通道，而你只想使用其中的第1、4和第5通道，你应该这样设置： import sounddevice as sd channels_to_use = [0, 3, 4] # ASIO通道编号从0开始 asio_settings = sd.AsioSettings(channel_selectors=channels_to_use) 这样设置后，当你创建一个音频流时可以用asio_settings对象作为extra_settings参数。 当你想要对音频捕获和播放的处理有更精细的控制时，特别是在需要低延迟的情况下，ASIO设置就非常有用。例如，对于专业的音频处理和现场表演，使用ASIO驱动和AsioSettings可以提供稳定且响应快速的音频输入/输出能力。 注意事项： ASIO是专为Windows系统设计的，并且需要一块支持ASIO的音频接口硬件。 ASIO通道选择器是高级设置，只有对声卡和ASIO有较深理解的用户才建议使用。 如果不当地使用channel_selectors，例如给出了过长或过短的列表、通道编号范围错误，可能会导致程序崩溃或运行异常。 正是由于这些设置提供了对较低层次和较为底层的音频设备参数的控制，因此AsioSettings在准确配置和优化音频性能方面扮演着重要角色。 2.8.2. sounddevice.CoreAudioSettings: 为Mac OS X Core Audio设备提供额外的配置 sounddevice.CoreAudioSettings 是一个用于 Mac OS X Core Audio 设备的特定配置类。它提供了一种方式，让用户可以设置与 Core Audio 相关的高级参数。这个类可以用在 sounddevice.Stream() 及其变体中作为 extra_settings 参数，或者用于 sounddevice.default.extra_settings。 下面详细说明 sounddevice.CoreAudioSettings 的构造函数： class CoreAudioSettings: def __init__(self, channel_map=None, change_device_parameters=False, fail_if_conversion_required=False, conversion_quality=&apos;max&apos;): ... 参数说明： channel_map (序列类型，int 类型，可选): 用于只打开 Core Audio 设备特定的通道。channel_map 的处理方式在输入和输出通道上是不同的。 对于输入设备，channel_map 是指定使用的（从 0 开始计数的）通道号的整数列表。 对于输出设备，channel_map 应该与设备的输出通道数长度相同。未使用的通道用 -1 来标记，需要的通道用 0 开始的索引指定。 change_device_parameters (布尔型，可选): 如果设置为 True，允许 PortAudio 更改设备的帧大小等参数，这样可以获得更低的延迟，但如果设备正被其他程序使用，就可能会冲突。默认值为 False。 fail_if_conversion_required (布尔型，可选): 结合上面的参数使用，若设为 True，仅当设备支持精确的采样率时才会打开流。 conversion_quality (字符串，可选): 用于设置 Core Audio 的采样率转换品质，可选项有 &apos;min&apos;、&apos;low&apos;、&apos;medium&apos;、&apos;high&apos; 和 &apos;max&apos;，默认为 &apos;max&apos;。 以下示例演示了如何将 CoreAudioSettings 用于音频流的创建和修改 Core Audio 的高级设置： import sounddevice as sd # 设置 Core Audio 特定的通道映射和参数 coreaudio_settings = sd.CoreAudioSettings( channel_map=[0, 1, -1, -1], # 用前两个通道，其他的设置为-1 change_device_parameters=True, fail_if_conversion_required=False, conversion_quality=&apos;high&apos;) # 确保高质量的采样率转换 # 使用特定的 Core Audio 设置创建一个输出流 with sd.OutputStream(device=1, channels=2, extra_settings=coreaudio_settings) as stream: # 读取和播放音频数据 ... # 也可以将 CoreAudioSettings 对象赋值给默认的 extra_settings sd.default.extra_settings = coreaudio_settings 在这个例子中，channel_map 设置了四个通道的映射，指定了仅使用前两个通道，而通过设置 change_device_parameters 为 True，该设置允许 PortAudio 在需要时更改设备参数以获得更低的延迟。 更多关于 Core Audio 设置的细节可以参考 PortAudio_ 和 Core Audio_ 的官方文档。 _PortAudio: http://www.portaudio.com/ _Core Audio: https://developer.apple.com/documentation/coreaudio 请注意，本示例仅为演示，实际使用中需要根据实际设备及需求适配参数。</summary>
      

      
      
    </entry>
  
  
  
    <entry>
      
      <title type="html">TeamsCode：基于 OpenAI 的 VSCode AI 写作插件</title>
      
      
      <link href="https://blog.talkincode.net/2024/03/10/TeamsCode-VSCode-AI/" rel="alternate" type="text/html" title="TeamsCode：基于 OpenAI 的 VSCode AI 写作插件" />
      
      <published>2024-03-10T05:32:40+00:00</published>
      <updated>2024-03-10T05:32:40+00:00</updated>
      <id>https://blog.talkincode.net/2024/03/10/TeamsCode-VSCode-AI</id>
      <content type="html" xml:base="https://blog.talkincode.net/2024/03/10/TeamsCode-VSCode-AI/">&lt;p&gt;TeamsCode是一个为 VSCode 设计的插件，后端对接 OpenAI的能力来增强编码和写作体验。它为用户提供了多种功能，包括智能写作、代码辅助、自动摘要，以及幻灯片和模板内容的生成，开发者和内容创作者可以通过这个工具来提高工作效率。通过这些功能，使用户能够专注于创造性任务，同时将重复性和耗时的任务交由后端的AI处理。&lt;/p&gt;

&lt;h2&gt;核心功能&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;ol&gt;
      &lt;li&gt;更灵活的 AI 写作&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在TeamsCode的更灵活的AI写作功能中，用户可以通过 alt+t 轻松地获得AI辅助写作的支持。这一创新工具不仅能够理解用户的写作意图，而且能够在保持上下文一致性的前提下，快速生成与现有内容风格相匹配的文本。此外，TeamsCode的AI写作工具被设计成具有高度的灵活性，允许用户指定特定的写作风格，以满足专业写作、商业文档、技术论文等多种场景的需求。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;ol&gt;
      &lt;li&gt;智能编程&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;不同于 github copilot ，TeamsCode 的智能编程功能插件提供的优势提供更个性化的辅助，比如，可以根据自定义的笔记列表作为上下文辅助代码的生成，通过笔记列表， 用户可以更灵活的定制上下文。同时 TeamsCode 使用的是最新的 Openai 模型， 除了代码生成能力， 通用性更强。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;ol&gt;
      &lt;li&gt;摘要生成&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;摘要生成是TeamsCode扩展中的一项核心功能，专门设计用于将长篇的文本内容压缩成简洁、高效的概要。这一功能支持用户迅速捕捉文档的主旨要点，提供文本的精炼版，并能极大地节约用户在信息提炼上的时间与精力。用户简单选择所需概括的文本段落，系统会利用OpenAI模型的能力，分析文本内容并生成紧凑的摘要。这个智能化过程不但能够捕捉原始文本的核心信息，还保持了原文的基本语境和关键信息。结合 VSCode 的编辑能力，TeamsCode提供生成摘要的功能，用户能够更有效的同时处理阅读和写作。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;ol&gt;
      &lt;li&gt;创建 Marp 幻灯片&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TeamsCode 的创建 Marp 幻灯片功能，使用户得以高效地将文本内容转换成标记化的幻灯片。在VsCode 中，Marp 是一个第三方的基于 Markdown 创建 幻灯片的扩展，使用 Marp 扩展创建的幻灯片内容可以通过相关的Markdown语法快速转变为精致的幻灯片展示。TeamsCode 凭借其与 OpenAI 集成的智能写作功能，可以针对用户的特定需求生成符合 Marp 格式规范的内容，使得幻灯片制作变得轻而易举。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;ol&gt;
      &lt;li&gt;按模板生成内容&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;按模板生成是TeamsCode中的一项实用功能，它可以根据预置的模板和相关提示来自动化生成特定格式的内容。这项功能轻松应对常见写作任务，如编写常规报告、个人博客、准备会议记录或创建项目提案， 甚至是专利申请书。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;ol&gt;
      &lt;li&gt;笔记列表管理&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;笔记列表是TeamsCode扩展的一项强大功能，旨在为用户提供一个强有力写作辅助能力。 用户随时可以将文本内容加入笔记列表， 在多个同时打开的 VsCode 中保持同步， 通过笔记可以灵活的自定义 AI 输入的上下文， 不管是只能写作，还是代码生成， 都可以提供很大帮助。&lt;/p&gt;</content>

      
      
      
      
      

      

      
        <category term="vscode" />
      
        <category term="OpenAI" />
      
        <category term="AI插件" />
      

      

      
        <summary type="html">TeamsCode是一个为 VSCode 设计的插件，后端对接 OpenAI的能力来增强编码和写作体验。它为用户提供了多种功能，包括智能写作、代码辅助、自动摘要，以及幻灯片和模板内容的生成，开发者和内容创作者可以通过这个工具来提高工作效率。通过这些功能，使用户能够专注于创造性任务，同时将重复性和耗时的任务交由后端的AI处理。 核心功能 更灵活的 AI 写作 在TeamsCode的更灵活的AI写作功能中，用户可以通过 alt+t 轻松地获得AI辅助写作的支持。这一创新工具不仅能够理解用户的写作意图，而且能够在保持上下文一致性的前提下，快速生成与现有内容风格相匹配的文本。此外，TeamsCode的AI写作工具被设计成具有高度的灵活性，允许用户指定特定的写作风格，以满足专业写作、商业文档、技术论文等多种场景的需求。 智能编程 不同于 github copilot ，TeamsCode 的智能编程功能插件提供的优势提供更个性化的辅助，比如，可以根据自定义的笔记列表作为上下文辅助代码的生成，通过笔记列表， 用户可以更灵活的定制上下文。同时 TeamsCode 使用的是最新的 Openai 模型， 除了代码生成能力， 通用性更强。 摘要生成 摘要生成是TeamsCode扩展中的一项核心功能，专门设计用于将长篇的文本内容压缩成简洁、高效的概要。这一功能支持用户迅速捕捉文档的主旨要点，提供文本的精炼版，并能极大地节约用户在信息提炼上的时间与精力。用户简单选择所需概括的文本段落，系统会利用OpenAI模型的能力，分析文本内容并生成紧凑的摘要。这个智能化过程不但能够捕捉原始文本的核心信息，还保持了原文的基本语境和关键信息。结合 VSCode 的编辑能力，TeamsCode提供生成摘要的功能，用户能够更有效的同时处理阅读和写作。 创建 Marp 幻灯片 TeamsCode 的创建 Marp 幻灯片功能，使用户得以高效地将文本内容转换成标记化的幻灯片。在VsCode 中，Marp 是一个第三方的基于 Markdown 创建 幻灯片的扩展，使用 Marp 扩展创建的幻灯片内容可以通过相关的Markdown语法快速转变为精致的幻灯片展示。TeamsCode 凭借其与 OpenAI 集成的智能写作功能，可以针对用户的特定需求生成符合 Marp 格式规范的内容，使得幻灯片制作变得轻而易举。 按模板生成内容 按模板生成是TeamsCode中的一项实用功能，它可以根据预置的模板和相关提示来自动化生成特定格式的内容。这项功能轻松应对常见写作任务，如编写常规报告、个人博客、准备会议记录或创建项目提案， 甚至是专利申请书。 笔记列表管理 笔记列表是TeamsCode扩展的一项强大功能，旨在为用户提供一个强有力写作辅助能力。 用户随时可以将文本内容加入笔记列表， 在多个同时打开的 VsCode 中保持同步， 通过笔记可以灵活的自定义 AI 输入的上下文， 不管是只能写作，还是代码生成， 都可以提供很大帮助。</summary>
      

      
      
    </entry>
  
  
</feed>
