CppCon 2016 學習:What C++ Programmers Need to Know about Header <random>

隨機數生成的歷史背景

Middle-Square 方法(中位平方法):

  • 已知最早的隨機算法之一
  • 或由修道士 Brother Edvin 在 1245 年發明
  • 由 John von Neumann 在 1949 年重新發現
  • 缺點明顯,但執行速度快

Monte Carlo 方法:

  • 起初是機密代碼名
  • 由 Stanislaw Ulam 和 John von Neumann 在 1946 年為曼哈頓計劃開發
  • 在 ENIAC 上實現
  • 通過大量模擬生成隨機樣本,再用統計方法分析其行為
  • 直到今天仍廣泛用于復雜系統模擬

隨機數的現代用途

應用示例
模擬蒙特卡洛方法、物理/金融模擬等
算法遺傳算法、隨機算法、Zobrist 哈希
排列洗牌、隨機抽簽、比賽排位、選舉
選擇游戲抽獎、學生點名、藝術創作、快速排序 pivot
抽樣醫藥實驗、調查問卷、審計、生產質檢
加密需要額外強度,不適用 <random>

注意:密碼學需求遠高于 <random> 能提供的強度,需使用操作系統安全 API 或專用庫(如 OpenSSL、libsodium 等)

識別“隨機”本身就是難題

“假設神諭者給了你十個連續的 0,你會覺得這是隨機的嗎?”

  • 這是一個引發思考的問題:十個連續的零看起來像是非隨機的,但事實上,在隨機數序列中,這樣的情況完全可能出現
  • Pete Becker 的觀點是:十個數字太少了,無法判斷一個隨機數生成器的質量。
  • 同樣,Scott Adams(Dilbert漫畫作者) 用諷刺幽默的方式表達了類似的觀點 —— 我們人類對“看起來隨機”的直覺,往往靠不住。

人類直覺在“隨機性”問題上常常失靈

P. Diaconis 的研究:硬幣落地后落在原來同一面朝上的概率其實略大于 50%(約 51%)。

  • 表明真實世界中的“隨機”也有物理偏差。
  • 比如,頭朝上的硬幣更容易再次朝上朝上——這打破了我們對拋硬幣“完美對半概率”的直覺認知。

Joe Peach 的故事:一個人在賭桌上用硬幣決定是否要要牌,結果硬幣立在了邊上 —— 一種極小概率但確實可能發生的“隨機事件”。

實現真正的隨機行為非常困難

  • Chris Wetzel 指出:統計意義上的“隨機”意味著不可預測無法發現模式
  • Jeff Atwood 和 Mads Haahr 都提到:計算機是“決定性”機器,本質上無法直接生成真正的隨機數。
  • 隨機數相關的教材和論文中,充斥著最終被證明有缺陷或完全錯誤的算法,說明這確實是一個“看起來簡單,實際上復雜”的問題領域。

培訓嚴重不足

  • 編程教育很少系統講授隨機性、概率分布、隨機變量等知識。
  • 一個看似簡單的例子:
    如果 f() 是均勻分布的,那么 2 * f() 也是均勻分布,
    f() + f() 卻變成了接近正態分布(高斯分布) —— 并非均勻。

    這意味著我們即使對隨機數做了很小的變換,也可能改變其分布性質!

挑戰性問題(由 von Neumann 提出):

給定一個有偏的硬幣(概率未知,0 < p < 1)
如何用它生成公平(等概率)的結果?
提示:Wikipedia 上“公平硬幣”條目有解法(可查找 von Neumann extractor)
→ 但作者建議你先自己思考

建議:務必極其小心!(

  • Stephen K. Park 和 Keith W. Miller:大多數隨機數生成器其實都存在非隨機行為,有些甚至“糟糕透頂”。
  • Brad Lucier:歷史上確實有不少“非常糟糕的” RNG 算法被發表在權威期刊,并被廣泛采用。
  • detly 博客名言:對隨機數做任意運算,并不意味著輸出依然是隨機的!

最后 —— 一點諷刺幽默

“你得到了你要求的,但不是你想要的。”

  • 很多程序員寫隨機代碼的時候“語法正確”,但輸出的結果和預期完全不符。
  • 在 RNG 上更容易出這種“技術上沒錯、但實際上錯了”的情況。

用戶分類:

  1. 初級用戶
    • 一個默認引擎類型(std::default_random_engine
    • 兩個通用的均勻分布模板(整數、實數)
  2. 中高級用戶
    • 9 個預設引擎類型(如 Mersenne Twister)
    • 18 個可配置的分布類型(如正態、泊松等)
    • 一個系統隨機源類(std::random_device
    • 一個輔助種子類(std::seed_seq
  3. 專家用戶
    • 6 個可配置引擎模板(如線性同余、混合引擎等)
    • 一個自定義分布模板工具
      說明:<random> 設計為支持從簡單用途復雜科研級別的隨機數生成。

C++ 中的術語(Slide 18)

術語混亂的歷史:

傳統術語“隨機數生成器”太模糊了!

<random> 中,我們區分兩個核心組件:

  1. Engine(引擎)
    • 生成原始、均勻、偽隨機的比特序列。
    • 理想上是 不可預測 的(雖然計算機做不到真正隨機)。
    • std::mt19937std::default_random_engine 等。
  2. Distribution(分布)
    • 從 engine 的比特流中抽樣,轉換為特定分布的數值。
    • 如:
      • std::uniform_int_distribution
      • std::normal_distribution
      • std::poisson_distribution
      • std::chi_squared_distribution
      • std::weibull_distribution
        結論:引擎負責“比特”,分布負責“形狀”。

引擎類型和用法

  • 引擎對象 e 在每次調用 e() 時返回一串偽隨機的比特(長度為 n),以 E::result_type 編碼的整數形式返回。
  • 比如:
    • std::mt19937::min() = 0
    • std::mt19937::max() = 232 - 1
  • 每次調用返回的數是可預測的(偽隨機),但難以預測(設計目標)。
  • 一般不需要直接使用返回的比特串,而是通過分布對象來使用引擎。

分布類型和用法

  • 分布對象 d 通過調用 d(e) 獲取一個符合分布的隨機值。
  • 示例 1:擲骰子函數
#include <random>
int roll_a_fair_die() {static std::default_random_engine e{};static std::uniform_int_distribution<int> d{1, 6};return d(e); // 返回 1 到 6 的偽隨機整數
}
  • 示例 2:生成長度為 N 的數組,填入擲骰子結果
constexpr std::size_t N = 1000;
int a[N];
std::generate(a, a + N, roll_a_fair_die); // 用骰子函數填數組

注意事項:

  • 使用 static 是為了避免每次調用重新構建引擎,影響性能與隨機性。
  • 可將引擎設為全局、共享,便于多個模塊使用同一隨機序列。

小結這一部分的要點:

內容要點
rand()不可移植,質量差,應避免使用
<random>可擴展、高質量、現代化設計
Engine生成偽隨機比特流
Distribution將比特流映射為具有特定統計特性的值
示例使用引擎 + 分布組合獲得擲骰子的整數

對C++ <random> 頭文件中隨機數引擎和分布的深入講解,重點涵蓋了以下幾個方面:

1. random_device 作為 URBG(Uniform Random Bit Generator)

  • random_device 設計用來訪問物理或環境隨機源,比如 /dev/random、CPU 的 RDRAND 指令,或者大氣噪聲等。
  • 它的構造函數帶一個實現定義的字符串,用來指定設備。
  • 它有 entropy() 成員函數,用來估計該設備產生的隨機性的熵值(信息量)。
  • 這保證了你可以用它作為真正隨機(或接近真實隨機)的隨機數生成器。

2. 提供的 20 種分布

  • 包含五類:
    • 均勻分布uniform_int_distribution, uniform_real_distribution
    • 伯努利及相關分布bernoulli_distribution, binomial_distribution, geometric_distribution, negative_binomial_distribution
    • 泊松及相關分布poisson_distribution, exponential_distribution, gamma_distribution, weibull_distribution, extreme_value_distribution
    • 正態及相關分布normal_distribution, lognormal_distribution, chi_squared_distribution, cauchy_distribution, fisher_f_distribution, student_t_distribution
    • 采樣分布discrete_distribution, piecewise_constant_distribution, piecewise_linear_distribution
  • 設計理由是這些分布是統計、工程和科學應用中最常見、最重要的。

3. 分布與引擎的互操作性

  • 任何實現了 URBG 接口的引擎都可以和任意分布搭配使用。
  • 這保證了擴展性,用戶可以自定義新的引擎和分布,且和標準庫無縫集成。
  • 例如,PCG、Random123 是第三方擴展引擎,GCC 自帶了一些額外的分布。

4. 自定義分布的輔助工具

  • generate_canonical<>() 是一個模板工具,能從 URBG 中產生一個在 [0,1) 均勻分布的浮點數,作為構造自定義分布的基礎。

5. 分布的統計測試

  • 通過均值、方差、卡方檢驗、Kolmogorov-Smirnov 檢驗等統計測試驗證分布是否合理。
  • 偶爾失敗是正常的,失敗太多才要懷疑隨機數生成的質量。

6. 不要濫用 rand() % n 取模法

  • 這個簡單取余方法會導致偏差,因為 rand() 的范圍通常不是 n 的整數倍。
  • 應該用標準庫的分布,比如 std::uniform_int_distribution,或者通過拒絕采樣(rejection sampling)實現均勻分布。

7. 如何正確生成隨機數

  • 實例化一個引擎(如 std::default_random_engine
  • 實例化一個分布(如 std::uniform_int_distribution<int>)
  • 每次生成隨機數時通過 distribution(engine) 產生,確保滿足所需分布。

8. 種子與可復現性

  • 引擎種子很關鍵,單個整數種子對大型狀態的引擎(如 Mersenne Twister)不足。
  • std::seed_seq 試圖擴展種子,但不總是效果很好。
  • 種子來源可以是時間戳、進程ID等,但它們質量較低。

9. C++17 之后新增的隨機數算法

  • std::sample:可以從一個范圍中采樣固定大小的隨機子集。
  • std::shuffle:隨機打亂序列。
  • 不再推薦使用 random_shuffle,它已被移除。

10. 迭代器接口(可選進階)

  • 設計了 variate_iterator,可以把一個隨機引擎 + 分布封裝成輸入迭代器,從而在標準算法中直接使用隨機數。
    總結起來,這些內容幫你深入理解 <random> 設計理念、最佳實踐、性能與質量權衡、以及如何用好它來寫出健壯的隨機數代碼。

你這段內容介紹了 C++17 <random> 庫中的一些高級用法,特別是 sample()shuffle() 的用法,還有用迭代器接口封裝隨機數分布生成的思路。

1. sample() 用法

C++17 新增了 std::sample(),功能是從一個區間(population)中隨機采樣固定數量元素。接口:

template<class PopulationIter, class SampleIter, class Size, class URBG>
SampleIter sample(PopulationIter first, PopulationIter last,SampleIter out, Size wanted_size, URBG&& g);
  • PopulationIter 是輸入區間的迭代器。
  • SampleIter 是輸出區間迭代器。
  • wanted_size 是采樣元素數。
  • URBG 是隨機數生成器。
    實現時,會根據輸入迭代器能力,選擇不同算法。

2. shuffle() 用法

用于將序列隨機打亂。
示例:

using card_t = int;
using deck_t = std::array<card_t, 52>;
deck_t deck;
std::iota(deck.begin(), deck.end(), 0);  // 生成0~51
using engine_t = std::default_random_engine;
engine_t e{ std::random_device{}() };     // 真隨機種子
std::shuffle(deck.begin(), deck.end(), e);
// 輸出花色和點數
auto suit = [](card_t c) { return "????"[c / 13]; };
auto rank = [](card_t c) { return "A23456789TJQK"[c % 13]; };
for (auto c : deck)std::cout << rank(c) << suit(c) << ' ';

3. shuffle_sort 的“反直覺”示例

template<class RA, class Engine>
void shuffle_sort(RA b, RA e, Engine g)
{while (!std::is_sorted(b, e))std::shuffle(b, e, g);
}
  • 這個算法隨機打亂序列直到它排序好了,顯然效率非常差,作為玩笑演示。

4. 自定義 shuffle 實現示例

這段代碼體現了 Fisher–Yates 洗牌算法:

template<class RA, class URBG>
void shuffle(RA b, RA e, URBG&& g)
{using diff_t = decltype(e - b);using dist_t = std::uniform_int_distribution<diff_t>;using param_t = typename dist_t::param_type;static dist_t d;  // 分布范圍由調用時動態傳入diff_t L = e - b - 1;for (diff_t m = 0; m < L; ++m)std::iter_swap(b + m, b + d(g, param_t{m, L}));
}
  • d(g, param_t{m, L}) 生成 [m, L] 范圍內的隨機數。
  • 逐步交換未洗牌部分的元素,保證均勻性。

5. 設計基于 <random> 的迭代器 variate_iterator

這是一個可用作輸入迭代器的類,封裝了隨機數引擎和分布,使其可以像迭代器一樣訪問隨機數流。

代碼草圖解析

template<class URBG, class Dist>
class variate_iterator : public std::iterator<std::input_iterator_tag, typename Dist::result_type>
{
private:using val_t = typename Dist::result_type;URBG* u{nullptr};   // 非擁有指針,指向隨機數生成器Dist* d{nullptr};   // 非擁有指針,指向分布val_t v{};          // 最近一次生成的隨機數值bool valid{false};  // 當前緩存的值是否有效void step() noexcept { valid = false; }val_t& deref() {if (!valid) {v = (*d)(*u);  // 調用分布生成新的隨機數valid = true;}return v;}
public:constexpr variate_iterator() noexcept = default;variate_iterator(URBG& u_, Dist& d_) : u(&u_), d(&d_) {}val_t& operator*() { return deref(); }val_t const* operator->() { return &deref(); }variate_iterator& operator++() { step(); return *this; }variate_iterator operator++(int) {variate_iterator tmp = *this;step();return tmp;}// TODO: 添加相等比較等必要接口,符合輸入迭代器要求
};

用途示例

  • 生成隨機數序列并復制到容器:
std::default_random_engine engine{std::random_device{}()};
std::uniform_real_distribution<double> dist(0.0, 1.0);
variate_iterator<std::default_random_engine, decltype(dist)> it(engine, dist);
std::vector<double> v(100);
std::copy_n(it, 100, v.begin());
  • 用于數學操作,如點積:
double prod = std::inner_product(v.begin(), v.end(), it, 0.0);
  • 對已有向量加隨機噪聲:
std::transform(v.begin(), v.end(), v.begin(), [&](double x) { return x + *it++; });

總結

  • <random> 提供了強大的隨機數工具,不光是生成單個隨機數,也可以對序列做采樣、洗牌。
  • 通過封裝迭代器,可以讓隨機數生成器與 STL 算法更好地結合。
  • 了解算法實現(如 Fisher-Yates shuffle)能幫助你理解隨機過程的正確性。
  • sample() 函數允許隨機采樣,避免了先打亂再選取的低效方法。

幾個簡單實用的隨機數小例子(小李子),用C++ <random>寫的,涵蓋不同類型的隨機數生成:

1. 生成 0 到 99 的隨機整數

#include <iostream>
#include <random>
int main() {std::random_device rd;  // 真隨機種子std::mt19937 gen(rd()); // Mersenne Twister引擎std::uniform_int_distribution<> dist(0, 99); // 均勻分布 [0,99]for (int i = 0; i < 10; ++i) {std::cout << dist(gen) << " ";}std::cout << "\n";
}

2. 生成 0.0 到 1.0 之間的浮點數

#include <iostream>
#include <random>
int main() {std::random_device rd;std::mt19937 gen(rd());std::uniform_real_distribution<> dist(0.0, 1.0);for (int i = 0; i < 10; ++i) {std::cout << dist(gen) << " ";}std::cout << "\n";
}

3. 從容器中隨機采樣(使用 std::sample

#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
int main() {std::vector<int> population{1,2,3,4,5,6,7,8,9,10};std::vector<int> sample_result;std::random_device rd;std::mt19937 gen(rd());std::sample(population.begin(), population.end(), std::back_inserter(sample_result),4, gen);  // 從population隨機采樣4個元素for (int x : sample_result) {std::cout << x << " ";}std::cout << "\n";
}

4. 洗牌一副撲克牌(52張)

#include <iostream>
#include <array>
#include <algorithm>
#include <random>
int main() {using card_t = int;std::array<card_t, 52> deck;std::iota(deck.begin(), deck.end(), 0);  // 0~51std::random_device rd;std::mt19937 gen(rd());std::shuffle(deck.begin(), deck.end(), gen);auto suit = [](card_t c) { return "????"[c / 13]; };auto rank = [](card_t c) { return "A23456789TJQK"[c % 13]; };for (auto c : deck) {std::cout << rank(c) << suit(c) << " ";}std::cout << "\n";
}

5. 用隨機數給數組元素加點噪聲

#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
int main() {std::vector<double> data = {1.0, 2.0, 3.0, 4.0, 5.0};std::random_device rd;std::mt19937 gen(rd());std::normal_distribution<> noise(0, 0.1); // 均值0,標準差0.1的高斯噪聲std::transform(data.begin(), data.end(), data.begin(),[&](double x) { return x + noise(gen); });for (auto d : data) {std::cout << d << " ";}std::cout << "\n";
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84264.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84264.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84264.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Origin:誤差棒點線圖繪制

1.首先將你的數據復制到表格 2.選中B(y)列數據&#xff0c;依次點擊圖示選項 3.選中圖中紅框數據&#xff0c;點擊繪制點線圖即可 4.結果展示

Spring 源碼學習 1:ApplicationContext

Spring 源碼學習 1&#xff1a;ApplicationContext Bean 定義和 Bean 實例 AnnotationConfigApplicationContext 首先&#xff0c;創建一個最簡單的 Spring Boot 應用。 在入口類中接收SpringApplication.run的返回值&#xff1a; SpringBootApplication public class Dem…

CppCon 2017 學習:Design Patterns for Low-Level Real-Time Rendering

這段內容講的是離散顯卡&#xff08;Discrete GPU&#xff09;中的內存管理模型&#xff0c;重點是CPU和GPU各自獨立管理自己的物理內存&#xff0c;以及它們如何通過虛擬內存和DMA引擎實現高效通信。以下是詳細的理解和梳理&#xff1a; 1. 基本概念 CPU 和 GPU 是兩個獨立的…

【單調隊列】-----【原理+模版】

單調隊列 一、什么是單調隊列&#xff1f; 單調隊列是一種在滑動窗口或區間查詢中維護候選元素單調性的數據結構&#xff0c;通常用于解決“滑動窗口最大值/最小值”等問題。 核心思想是&#xff1a;利用雙端隊列&#xff08;deque&#xff09;維護當前窗口內或候選范圍內元素…

CSS語法中的選擇器與屬性詳解

CSS:層疊樣式表&#xff0c;Cascading Style Sheets 層疊樣式表 內容和樣式分離解耦&#xff0c;便于修改樣式。 特殊說明&#xff1a; 最后一條聲明可以沒有分號&#xff0c;但是為了以后修改方便&#xff0c;一般也加上分號為了使用樣式更加容易閱讀&#xff0c;可以將每條代…

模擬設計的軟件工程項目

考核題目 論文論述題&#xff1a;結合你 參與開發、調研或模擬設計的軟件工程項目 &#xff0c;撰寫一篇論文 完成以下任務&#xff0c;論文題目為《面向微服務架構的軟件系統設計與建模分析》&#xff0c;總分&#xff1a; 100 分。 1. 考核內容&#xff1a; 一、系統論述…

個人理解redis中IO多路復用整個網絡處理流

文章目錄 1.redis網絡處理流2.理解通知機制 1.redis網絡處理流 10個客戶端通過TCP與Redis建立socket連接&#xff0c;發送GET name指令到服務器端。服務器端的網卡接收數據&#xff0c;數據進入內核態的網絡協議棧。Redis通過IO多路復用機制中的epoll向內核注冊監聽這些socket的…

【鄭州輕工業大學|數據庫】數據庫課設-酒店管理系統

該數據課設是一個基于酒店管理系統的數據庫設計 建庫語句 create database hotel_room default charset utf8 collate utf8_general_ci;建表語句 use hotel_room;-- 房型表 create table room_type( id bigint primary key auto_increment comment 房型id, name varchar(50)…

TCP 三次握手與四次揮手詳解

前言 在當今互聯網時代&#xff0c;前端開發的工作范疇早已超越了簡單的頁面布局和交互設計。隨著前端應用復雜度的不斷提高&#xff0c;對網絡性能的優化已成為前端工程師不可忽視的重要職責。而要真正理解并優化網絡性能&#xff0c;就需要探究支撐整個互聯網的基礎協議——…

RTD2735TD/RTD2738 (HDMI,DP轉EDP 高分辨率高刷新率顯示器驅動芯片)

一、芯片概述 RTD2738是瑞昱半導體&#xff08;Realtek&#xff09;推出的一款高性能顯示驅動芯片&#xff0c;專為高端顯示器、便攜屏、專業顯示設備及多屏拼接系統設計。其核心優勢在于支持4K分辨率下240Hz高刷新率及8K30Hz顯示&#xff0c;通過集成DisplayPort 1.4a與HDMI …

C++實現手寫strlen函數

要實現求字符串長度的函數&#xff0c;核心思路是通過指針或索引遍歷字符串&#xff0c;直到遇到字符串結束標志 \0 。以下是兩種常見的實現方式&#xff1a; 指針遍歷版本 #include <iostream> using namespace std; // 指針方式實現strlen size_t myStrlen(const cha…

NVPL 函數庫介紹和使用

文章目錄 NVPL 函數庫介紹和使用什么是 NVPLNVPL 的主要組件NVPL 的優勢安裝 NVPL基本使用示例示例1&#xff1a;使用 NVPL RAND 生成隨機數示例2&#xff1a;使用 NVPL FFT 進行快速傅里葉變換 編譯 NVPL 程序性能優化建議總結 NVPL 函數庫介紹和使用 什么是 NVPL NVPL (NVI…

HTTP相關內容補充

目錄 一、URI 和 URL 二、使用 Cookie 的狀態管理 三、返回結果的 HTTP狀態碼 一、URI 和 URL URI &#xff1a;統一資源標識符 URL&#xff1a;統一資源定位符 URI 格式 登錄信息&#xff08;認證&#xff09;指定用戶名和密碼作為從服務器端獲取資源時必要的登錄信息&a…

MySQL: Invalid use of group function

https://stackoverflow.com/questions/2330840/mysql-invalid-use-of-group-function 出錯SQL: 錯誤原因&#xff1a; 1. 不能在 WHERE 子句中使用聚合&#xff08;或分組&#xff09;函數 2. HAVING 只能篩選分組后的聚合結果或分組字段 # Write your MySQL query statem…

C#財政票查驗接口集成-醫療發票查驗-非稅收入票據查驗接口

財政票據是企事業單位、醫療機構、金融機構等組織的重要報銷憑證&#xff0c;其真實性、完整性和合規性日益受到重視。現如今&#xff0c;為有效防范虛假票據報銷、入賬、資金流失等問題的發生&#xff0c;財政票據查驗接口&#xff0c;結合財政票據識別接口&#xff0c;旨在為…

瀏覽器基礎及緩存

目錄 瀏覽器概述 主流瀏覽器&#xff1a;IE、Chrome、Firefox、Safari Chrome Firefox IE Safari 瀏覽器內核 核心職責 主流瀏覽器內核 JavaScript引擎 主流的JavaScript引擎 瀏覽器兼容性 瀏覽器渲染 渲染引擎的基本流程 DOM和render樹構建 html解析 DOM 渲染…

Ubuntu 安裝Telnet服務

1. 安裝Telnet 客戶端 sudo apt-get install telnet 2. 安裝Telnet 服務器 &#xff08;這樣才能用A電腦的客戶端連接B電腦的Telnet服務&#xff09; sudo apt-get install telnetd 3. 這時候Telnet服務器是無法自我啟動的&#xff0c;需要網絡守護進程服務程序來管理…

AI+預測3D新模型百十個定位預測+膽碼預測+去和尾2025年6月19日第113彈

從今天開始&#xff0c;咱們還是暫時基于舊的模型進行預測&#xff0c;好了&#xff0c;廢話不多說&#xff0c;按照老辦法&#xff0c;重點8-9碼定位&#xff0c;配合三膽下1或下2&#xff0c;殺1-2個和尾&#xff0c;再殺4-5個和值&#xff0c;可以做到100-300注左右。 (1)定…

觀察者模式 vs 發布訂閱模式詳解教程

&#x1f31f;觀察者模式 vs 發布訂閱模式詳解教程 收藏 點贊 關注&#xff0c;持續更新高頻面試知識庫&#xff01;&#x1f680; 一、核心概念&#xff08;總&#xff09; 在軟件開發中&#xff0c;觀察者模式&#xff08;Observer&#xff09; 和 發布訂閱模式&#xff0…

【云馨AI-大模型】MD2Card:從Markdown到知識卡片的完美轉變

Markdown的魅力與挑戰MD2Card的核心功能使用體驗與案例分析總結 在當今這個信息快速傳播的時代&#xff0c;內容創作者們一直在尋找更有效的方式來呈現他們的想法和知識。無論是為了個人學習筆記、團隊內部的知識分享還是對外的內容發布&#xff0c;一個清晰、美觀的展示方式顯…