从零构建高效比较逻辑:C++20三向比较返回类型的实战应用

第一章:三向比较操作符的演进与核心价值

三向比较操作符(Three-way Comparison Operator),又称“太空船操作符”(<=>),是现代编程语言在类型比较逻辑上的一次重要演进。它通过单一操作符统一了对象间小于、等于和大于的判断流程,显著简化了比较逻辑的实现。

设计动机与语言支持

传统比较需要分别重载 ==、<、> 等多个操作符,容易导致逻辑不一致。三向比较操作符在 C++20 中被正式引入,返回一个可比较的 ordering 类型,如 std::strong_ordering 或 std::partial_ordering,从而自动推导出所有关系操作。
  • C++20 首次标准化该操作符
  • Rust 通过 Ord trait 实现类似语义
  • Python 虽未内置,但可通过 __cmp__ 模拟
代码实现示例

#include <iostream>
#include <compare>

struct Point {
    int x, y;
    auto operator<=>(const Point&) const = default; // 自动生成比较逻辑
};

int main() {
    Point a{1, 2}, b{1, 3};
    if (a < b) {
        std::cout << "a is less than b\n"; // 输出结果
    }
    return 0;
}
上述代码中,operator<=> 被设为 default,编译器自动生成成员逐个比较的逻辑,并返回适当的 ordering 值。

比较结果类型对照

返回类型语义适用场景
std::strong_ordering完全可排序,值相等则对象等价整数、字符串等
std::partial_ordering允许不可比较状态(如 NaN)浮点数
graph LR A[输入两个对象] --> B{调用 <=>} B --> C[返回 ordering 值] C --> D[根据值判断 <, ==, >]

第二章:C++20 <=> 操作符的基础语义与返回类型体系

2.1 三向比较的基本语法与编译器支持条件

三向比较(Three-way comparison),又称“太空船操作符”(<=>),是 C++20 引入的重要特性,用于简化对象间的比较逻辑。
基本语法结构
auto result = a <=> b;
该表达式返回一个比较类别类型:如 std::strong_ordering、std::weak_ordering 或 std::partial_ordering,根据操作数的语义决定。例如,整型比较返回 std::strong_ordering。
编译器支持条件
实现三向比较需满足:
  • C++20 标准支持(-std=c++20)
  • 编译器版本:GCC 10+、Clang 10+、MSVC 19.28+
  • 头文件包含:#include <compare>
此特性自动合成所有六种比较操作符(==, !=, <, <=, >, >=),显著减少样板代码。

2.2 std::strong_ordering、std::weak_ordering 与 std::partial_ordering 解析

C++20 引入了三类新的强类型比较结果,用于替代传统的整型返回值(如 -1, 0, 1),提升类型安全和语义清晰度。
三种 ordering 类型的语义差异
  • std::strong_ordering:表示完全等价关系,可比较且相等即值相同(如整数);
  • std::weak_ordering:允许不等价但不可区分(如忽略大小写的字符串比较);
  • std::partial_ordering:支持部分有序,可能返回“无序”(如浮点数中的 NaN)。
典型使用示例

#include <compare>
double a = 1.0, b = NAN;
auto result = a <=> b; // 返回 std::partial_ordering::unordered
if (result == std::partial_ordering::less) {
    // a 小于 b
} else if (result == std::partial_ordering::equivalent) {
    // a 等于 b
}
上述代码中,a <=> b 返回 std::partial_ordering::unordered,因为涉及 NaN,体现了对不完整顺序的支持。

2.3 不同返回类型的选择逻辑与对象语义关联

在设计函数返回类型时,需结合对象语义明确值传递与引用传递的使用场景。值返回适用于不可变或小型数据结构,确保调用方无法修改原始状态。
常见返回类型对比
  • 值类型:如 int、string,直接拷贝,安全但成本高
  • 指针类型:如 *User,避免拷贝,可修改原对象
  • 接口类型:如 io.Reader,支持多态和解耦

func NewUser(name string) *User {
    return &User{Name: name} // 返回指针,维持唯一实例语义
}
该函数返回指针,表明对象生命周期由调用方管理,符合资源封装原则。当对象较大或需共享状态时,应优先返回指针或接口,以提升性能并明确语义意图。

2.4 自动生成比较函数的规则与隐式合成机制

在现代编程语言中,编译器可根据类型的结构自动合成比较函数,前提是所有成员均支持比较操作。这一机制称为隐式合成。
自动生成条件
类型需满足以下规则:
  • 所有字段均实现比较接口(如 == 和 !=)
  • 无显式定义冲突的比较方法
  • 类型为结构体或枚举等复合类型
代码示例
type Point struct {
    X, Y int
}
// 编译器自动合成 == 和 != 比较函数
上述代码中,Point 的比较函数由编译器隐式生成,因 int 支持相等性判断,且未定义手动比较逻辑。
合成优先级表
类型可合成说明
基本类型是内置比较逻辑
结构体是逐字段比较
含函数字段否函数不可比较

2.5 实践:为自定义类实现安全的 <=> 操作符

在现代C++中,三路比较操作符<=>(也称“太空船操作符”)可简化对象间的比较逻辑。为自定义类实现该操作符时,需确保其满足严格弱序性并避免未定义行为。
基本实现原则
优先使用default关键字让编译器自动生成安全的三路比较:
struct Point {
    int x, y;
    auto operator<=>(const Point&) const = default;
};
此方式利用成员变量的自然顺序进行逐字段比较,语义清晰且不易出错。
手动实现场景
当需要自定义比较逻辑时,应显式处理各类边界情况:
  • 确保operator<=>返回std::strong_ordering或其变体
  • 避免直接减法运算以防溢出
正确实现能提升容器排序、查找等操作的性能与安全性。

第三章:基于返回类型的精细化控制策略

3.1 利用比较结果进行模板约束的设计模式

在泛型编程中,利用类型比较结果实现编译期约束是一种高效且安全的设计模式。通过标准库中的类型特征(type traits)和条件判断,可在模板实例化时强制验证类型属性。
类型约束的典型实现
template<typename T>
requires std::integral<T>
T add(T a, T b) {
    return a + b;
}
上述代码使用 C++20 的 concepts 特性,通过 std::integral<T> 比较 T 是否为整型。若不满足约束,编译器将直接报错,避免运行时错误。
约束机制的优势
  • 提升编译期错误检测能力
  • 增强模板接口的可读性与可用性
  • 减少 SFINAE 的复杂性
该模式将类型比较结果直接转化为约束条件,使模板设计更加健壮和直观。

3.2 在容器与算法中利用 ordering 类型优化排序行为

在现代 C++ 中,`std::strong_ordering`、`std::weak_ordering` 等 ordering 类型为容器和算法提供了更精确的比较语义。通过使用三路比较(three-way comparison),可显著提升排序效率并减少冗余代码。
Ordering 类型分类
  • std::strong_ordering:支持完全等价与不等关系,如整数比较
  • std::weak_ordering:允许等价但不完全可替换,如字符串忽略大小写
  • std::partial_ordering:支持无定义顺序(NaN 场景)
结合容器优化排序
struct Point {
    int x, y;
    auto operator<=>(const Point& other) const {
        if (auto cmp = x <=> other.x; cmp != 0) return cmp;
        return y <=> other.y;
    }
};
std::set<Point> points; // 自动利用 <=> 实现高效插入排序
上述代码中,编译器自动生成高效的比较逻辑,避免多次重载 `<` 或 `==`。`operator<=>` 返回 `std::strong_ordering`,使 `std::set` 插入时仅需一次比较调用即可完成排序定位,减少运行时开销。

3.3 处理浮点数与混合类型比较的边界情况

在数值比较中,浮点数精度和类型隐式转换常引发不可预期的行为。尤其是在涉及整数、浮点数和字符串混合比较时,必须谨慎处理类型转换规则。
浮点数精度问题
由于浮点数以二进制形式存储,某些十进制小数无法精确表示,导致比较偏差:

a := 0.1 + 0.2
b := 0.3
fmt.Println(a == b) // 输出 false
上述代码中,a 实际值约为 0.30000000000000004,直接使用 == 比较会失败。应采用误差容忍比较:

epsilon := 1e-9
fmt.Println(math.Abs(a - b) < epsilon) // 安全比较方式
混合类型比较陷阱
不同语言对类型强制转换策略不同。例如在 JavaScript 中:
  • 0 == "0" 返回 true(类型自动转换)
  • 0 === "0" 返回 false(严格类型匹配)
建议始终使用严格比较操作符,避免隐式类型转换带来的逻辑漏洞。

第四章:典型应用场景中的高效比较构建

4.1 构建高性能键值映射时的比较逻辑设计

在高性能键值存储系统中,比较逻辑直接影响查找效率与数据一致性。合理的键比较策略需兼顾时间复杂度与语义正确性。
比较函数的设计原则
理想的键比较应满足全序性、可重复性和低延迟。对于字符串键,通常采用字典序比较;数值键则使用自然序。自定义类型需明确定义偏序关系。
代码实现示例

func CompareBytes(a, b []byte) int {
    for i := 0; i < len(a) && i < len(b); i++ {
        if a[i] != b[i] {
            if a[i] < b[i] {
                return -1
            }
            return 1
        }
    }
    if len(a) < len(b) {
        return -1
    } else if len(a) > len(b) {
        return 1
    }
    return 0
}
该函数逐字节比较两个字节数组,返回-1、0或1,符合Go语言sort.Interface要求。时间复杂度为O(min(m,n)),适用于变长键的快速排序与二分查找场景。

4.2 在泛型库中封装可复用的比较策略组件

在构建泛型库时,将比较逻辑抽象为可插拔的策略组件能显著提升代码复用性与扩展性。通过定义统一的比较接口,用户可根据具体类型注入定制化比较行为。
比较策略接口设计

type Comparator[T any] interface {
    Compare(a, b T) int // 返回-1, 0, 1表示小于、等于、大于
}
该接口适用于任意可比较类型,支持在排序、去重等场景中动态替换比较逻辑。
内置策略实现示例
  • NaturalComparator:基于类型的自然顺序(如int升序)
  • ReverseComparator:反转比较结果,实现降序排列
  • CustomFuncComparator:接收函数式参数,适配复杂业务规则
通过组合这些策略,泛型容器可无需修改核心逻辑即可适应多样化排序需求。

4.3 结合 concepts 定制条件化的三向比较行为

在 C++20 中,通过结合 `concepts` 与三向比较运算符(`<=>`),可以实现更精细的条件化比较逻辑。利用 concept 约束模板参数类型,确保仅在满足特定条件时启用相应的比较行为。
使用 Concept 约束比较操作
template<typename T>
concept Orderable = requires(T a, T b) {
    { a <=> b } -> std::convertible_to<std::strong_ordering>;
};

template<Orderable T>
auto compare(const T& lhs, const T& rhs) {
    return lhs <=> rhs;
}
上述代码定义了一个名为 `Orderable` 的 concept,要求类型支持 `<=>` 并返回可转换为 `std::strong_ordering` 的结果。函数 `compare` 仅对满足该约束的类型实例化,避免无效调用。
差异化处理不同排序类别
通过 if-constexpr 与 `std::is_same_v` 可根据 `<=>` 返回类型执行分支逻辑,实现对强序、弱序、偏序的定制化响应,提升泛型代码的安全性与灵活性。

4.4 实战案例:实现一个支持多级排序的记录结构

在处理复杂数据集时,常需根据多个字段进行排序。本案例设计一个通用的记录结构,支持按优先级定义的多级排序规则。
数据结构定义
使用 Go 语言定义记录结构体,包含姓名、部门和薪资字段:
type Employee struct {
    Name      string
    Department string
    Salary    int
}
该结构可扩展用于企业员工管理系统中的排序需求。
多级排序逻辑实现
通过 sort.Slice 实现链式比较:先按部门升序,再按薪资降序,最后按姓名字母排序。
sort.Slice(employees, func(i, j int) bool {
    if employees[i].Department != employees[j].Department {
        return employees[i].Department < employees[j].Department
    }
    if employees[i].Salary != employees[j].Salary {
        return employees[i].Salary > employees[j].Salary
    }
    return employees[i].Name < employees[j].Name
})
此嵌套比较逻辑确保高优先级字段主导排序结果,适用于报表生成等场景。

第五章:总结与现代C++比较逻辑的发展趋势

三路比较运算符的广泛应用
C++20引入的三路比较运算符(<=>)显著简化了类型间的比较逻辑。开发者不再需要手动重载多个关系运算符,编译器可自动生成一致的比较行为。

struct Point {
    int x, y;
    auto operator<=>(const Point&) const = default;
};
上述代码利用默认的三路比较,自动推导出==、!=、<等所有比较操作,减少样板代码并提升类型安全性。
比较语义的标准化演进
现代C++强调强类型和语义清晰。通过std::strong_ordering、std::weak_ordering和std::partial_ordering,程序能精确表达对象间的排序关系。
  • strong_ordering:适用于完全可比较的类型,如整数
  • weak_ordering:支持等价但不完全相同的顺序,如不区分大小写的字符串
  • partial_ordering:允许不可比较的情况,常见于浮点数中的NaN
实际工程中的迁移策略
在大型项目中,逐步引入<=>需谨慎。建议先在值类型中启用默认三路比较,并通过静态断言验证比较结果的一致性:

static_assert(std::is_same_v<
    decltype(p1 <=> p2),
    std::strong_ordering
>);
同时,结合explicit operator bool()可防止隐式布尔转换带来的逻辑错误,提升接口安全性。
C++20三向比较运算符实战指南:简化自定义类型比较逻辑 在C++编程中,运算符重载是实现自定义类型行为的关键技术,其中比较运算符的重载尤为常见。其核心原理是通过定义特定的成员函数,使对象能够响应如等于、小于等关系操作。这项技术的核心价值在于提升代码的语义清晰度和复用性,确保自定义类型能无缝集成到标准库容器和算法中,例如用于std::set排序或std::map的键值比较。在实际应用场景中,手动重载多个比较运算符(如operator<、operator==)不仅代码冗余,还极易因逻辑不对称而引入难以察觉的Bug。C++20引入的三向比较运算符(operator<= 阅读详情

相关推荐

【RabbitMQ C++】AMQP-CPP实战:从零构建高效消息队列系统

本文详细介绍了如何使用C++和AMQP-CPP库从零构建高效的RabbitMQ消息队列系统。内容涵盖环境搭建、核心概念解析,并通过实战代码示例演示了如何编写生产者和消费者程序,实现消息的发布与订阅。文章重点讲解了如何与libev事件循环集成,以构建高性能、可靠的异步通信组件,为C++分布式系统开发提供了一套完整的解决方案。

5f4d3s2a1q的博客 933

现代C++的AI革命:C++20/C++23核心特性解析与实战应用

C++在AI时代的重生:现代特性赋能大模型开发 摘要:本文探讨了C++语言在人工智能时代的复兴与进化。随着AI模型规模的爆发式增长,C++凭借其底层控制能力和"零开销抽象"哲学,在推理引擎开发中展现了不可替代的性能优势。文章重点分析了C++20/23的关键特性:Concepts提升模板类型安全,Ranges优化迭代器范式,协程简化异步编程,Modules加速编译过程。通过Llama.cpp和vLLM等框架的实践案例,展示了这些特性如何赋能大模型的高效部署,包括量化技术、内存优化和并发处理

不断学习,不断进步,提高自己 2468

通信工程学习:什么是OLT光线路终端

OLT(光线路终端)是无源光网络(PON)的核心局端设备,负责光/电信号转换、数据处理、带宽分配及用户管理。具有高带宽、低损耗、高安全性和易维护等技术特点,广泛应用于家庭、企业及公共机构宽带接入。未来将向更高性能、智能化方向发展,结合SDN/NFV等新技术,提升网络服务质量。

limengshi138392的博客 4359

【C++20特性实战指南】:掌握现代C++高效编程的7大核心特性

掌握C++20特性实践,提升代码效率与可维护性。涵盖协程、概念、范围算法等7大核心特性,解析现代C++在高性能编程与系统开发中的实际应用。方法实用,场景明确,助你快速落地现代C++编程,值得收藏。

FuncTide的博客 649

关于对鱼眼相机图片进行畸变校正的两种思路

鱼眼畸变主要表现为径向畸变(Radial Distortion),图像中心正常,边缘向外拉伸。畸变模型通常基于入射角θ\thetaθ(光线与光学轴夹角)和图像半径rrr的关系。等距投影(Equidistant Projection)rdfθrd​fθ,其中rdr_drd​为畸变图像半径,fff为焦距,θ\thetaθ为入射角。等立体角投影(Equisolid Angle Projection)rd2fsin⁡θ2rd​2fsinθ/2。

qq_45670407的博客 1546

Grey Hack v0.7.3618 保姆级教程:手把手教你用metaxploit.so写一个自动提权脚本

本文详细介绍了如何在Grey Hack v0.7.3618中使用metaxploit.so库编写自动化提权脚本。从环境准备到核心功能解析,再到漏洞利用链构建和权限提升的智能处理,手把手教你掌握游戏中的高级黑客技巧。通过多库联合利用和错误处理优化,提升脚本的效率和成功率。

weixin_42537919的博客 395

C++20三路比较返回类型实战(仅限高级开发者阅读)

掌握C++20三路比较运算符核心机制,深入解析C++20 <=> 的返回类型及其在类类型比较中的实际应用。涵盖std::strong_ordering等关键枚举类型,揭示简洁高效的比较逻辑实现原理,提升代码安全性与表达力,值得收藏。

CompiGap的博客 313

机器人学习-matlab四足机器人控制仿真

《机器人学,机器视觉与控制》学习笔记 使用工具箱版本9.10 题目与解决思路: 【1】. 通过减少复位期间的抬腿高度来缩短复位的轨迹 Z轴向下,为了减小复位器件的抬腿高度,应当缩小△Z,故可以将示例程序中zu值调大。 【2】. 增加腿的步幅 腿的步幅可由改变x方向上腿前进和后退运动的极限来达到,令xf = 7; xb = -xf;即可。 ...

weixin_44609769的博客 5539

C++20三向比较运算符实战指南(从入门到精通的7个关键步骤)

掌握C++20三向比较运算符<=>,告别繁琐的比较函数重载。本文详解其在类类型、容器和自定义排序中的应用,揭示简化代码、提升性能的核心优势。7个步骤循序渐进,助你精通现代C++编程技巧,值得收藏。

PoliVein的博客 331

实测对比:DeepSeek、豆包、千问三大AI模型生成测试用例谁更强?(附完整代码)

本文通过实测对比了DeepSeek、豆包、千问三大AI模型在生成测试用例方面的表现。文章提供了完整的Python代码实现,详细分析了各模型在用例完整性、准确性、边界覆盖及幻觉控制等维度的差异,并分享了工程化集成与多模型融合等优化策略,旨在帮助测试团队选择合适工具以提升工作效率。

ik6789012的博客 946

手把手教你用TUSB2E22中继器实现eUSB2与USB 2.0互转(附实测数据对比)

本文详细介绍了如何利用TUSB2E22中继器实现eUSB2与USB 2.0的高效互转,包括技术背景、硬件设计要点、信号完整性测试方法及故障排查策略。通过实测数据对比,展示了TUSB2E22在信号延迟、功耗和眼图性能上的显著优势,为工程师提供了实用的工程方案。

weixin_29199873的博客 283

C++20 <=> 返回类型揭秘:5分钟掌握三大合成结果与比较范畴

快速掌握C++20 <=> 的返回类型,解析三大合成结果与比较范畴。适用于现代C++编程中的对象比较场景,揭示如何通过auto和三路比较简化代码逻辑,提升类型安全与性能。核心方法清晰易懂,值得收藏。

CodeWhim的博客 301

内网渗透(二)之基础知识-工作组介绍

在一个大型单位里,可能有成百上千台计算机互相连接组成局域网,它们都会列在"网络"(网上邻居)内。如果不对这些计算机进行分组,网络的混乱程度是可想而知的 为了解决这一问题,产生了工作组( Work Group)这个概念。将不同的计算机按功能(或部 门)分别列入不同的工作组,例如技术部的计算机都列入"技术部"工作组、行政部的计算机都 列入"行政部"工作组。要想访问某个部门的资源,只要在"网络"里双击该部门的工作组名 就可以看到该部门的所有计算机了。相比不分组的情况,这样的情况有序得多(尤其对大型局域网来说)。

把自己活成一道光,因为你不知道,谁会借着你的光,走出了黑暗。请保持心中的善良,因为你不知道,谁会借着你的善良,走出了绝望。请保持你心中的信仰,因为你不知道,谁会借着你的信仰,走出了迷茫。请相信自己的力量,因为你不知道,谁会因为相信你,开始相信了自己.... 1219

【C++20三路比较运算符深度解析】:彻底搞懂<=>的返回类型与应用陷阱

掌握C++20三路比较运算符核心机制,深入解析C++20 <=> 的返回类型及其在类类型比较中的应用。涵盖强/弱序、相等性判断与编译优化优势,避免常见重载陷阱,提升代码安全性与可读性,值得收藏。

LiteTrans的博客 360

Auto.js实现视频号点赞自动化

摘要:本文介绍了一个微信视频号自动化点赞的实现方案。通过定位点赞图标和数量容器,点击点赞按钮后检测点赞数变化,若发现取消点赞则自动补点。核心代码包括:1)获取点赞容器和图标;2)记录点赞前后数量;3)判断是否误取消并补点;4)循环执行点赞和滑动页面操作。该方案解决了滑动页面可能导致误取消点赞的问题,实现了自动化批量点赞功能。文章强调仅供学习参考,提醒勿滥用该技术。

分享前端工程化、AI 应用、Agent 开发与大模型实践! 2575

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

【C++20高级特性必知】:<=>操作符返回类型的选择逻辑全剖析

掌握C++20 <=> 的返回类型选择逻辑,深入解析三大比较结果类型及其适用场景。涵盖强/弱序关系判断、与旧版比较函数的兼容策略,提升代码简洁性与安全性。核心方法全剖析,值得收藏。

DevPath的博客 291

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

C++20 三路比较运算符 `<=>` 与 `operator==() = default` 的深度剖析及实际应用

三路比较运算符<=>的主要功能是对两个对象进行比较,并返回一个特定类型的结果,这些类型包括 std::strong_ordering以及 std::partial_ordering:适用于完全可比较的对象,其返回结果为less(小于)、equal(等于)或greater(大于)。:用于对象可能存在不可比较情况的场景,结果为less(小于)、equivalent(等价)或greater(大于)。:同样适用于对象可能有不可比较情况的场景,结果除了less(小于)、equivalent(等价)或。

码事漫谈 1382

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

【现代C++高效编程】:为什么你必须掌握<=>的6种返回类型?

掌握C++20 <=> 的返回类型,轻松实现高效类类型比较。详解6种返回类型的适用场景与核心优势,包括强/弱序关系判断及与传统比较函数的兼容技巧。提升代码简洁性与可读性,现代C++编程必备技能,值得收藏。

FastCompile的博客 392

C++事件驱动编程从入门到实战:深入理解与高效应用

事件驱动编程是一种编程范式,其中程序的执行流程由外部事件的发生来触发。事件可以是用户的操作(如鼠标点击、键盘输入)、系统消息(如定时器到期、网络数据到达)或其他程序产生的信号。事件驱动程序通常包含一个事件循环(Event Loop),不断监听并处理各种事件,确保程序对各种输入做出及时响应。事件驱动编程作为一种灵活、高效的编程范式,在C++应用开发中扮演着重要角色。

编程技术探索者,分享C/C++、C#、Java、数据库等开发经验,聚焦实战技巧与AI兴趣,助力编程爱好者成长。 1963

Cpp-PegLib:高效C++解析库实战指南

**Cpp-PegLib** 是一个由Yhirose维护的强大、高效的C++解析库,它基于 Parsing Expression Grammar (PEG) 理论实现。该库允许开发者通过简洁直观的文本语法定义语言结构,进而轻松实现语法分析。相较于传统的LL或LR解析器生成工具,PegLib提供了一个更为直接且易于理解的方式来创建解析器,极大地简化了复杂语法的处理逻辑。 ## 项目快速启动 ##...

gitblog_00770的博客 945

C++新特性:constexpr容器、std::format与三向比较运算符,你掌握了吗?

在 C++ 中,constexpr是一个强大的关键字,它用于声明常量表达式。常量表达式是指在编译期就能计算出结果的表达式,而非在运行时才进行计算。这意味着,使用constexpr声明的变量或函数,其值在编译阶段就已经确定,从而避免了运行时的计算开销,大大提高了程序的执行效率。例如:// result在编译时被计算为25在上述代码中,square函数被声明为constexpr,这表示它可以在编译时被调用。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 955

C++20新特性

这些特性极大地增强了语言的表达能力,使代码更简洁、更高效、更易于维护。C++20 是 C++ 语言发展中的一个重要里程碑,引入了众多新特性,这些特性不仅提升了语言的功能性和性能,还极大地简化了许多编程任务。捕获 this:使用 [*this] 捕获当前对象的拷贝,而不是引用,避免了 Lambda 中出现悬空引用的问题。惰性计算:此操作不会立即对所有元素进行过滤和转换,只有在访问元素时才会计算结果,节省了不必要的开销。安全性:std::span 提供了类似指针的接口,但不会产生指针的安全问题(如越界访问)。

weixin_42936764的博客 1758

C++运算符与表达式:构建高效计算逻辑的基石

本文详细介绍了C++运算符与表达式的核心知识,包括运算符分类、优先级规则以及具体应用。主要内容涵盖:算术运算符(+、-、*、/、%)、赋值运算符(=、+=等)、关系与逻辑运算符(>、==、&&等)、位运算符(&、|、^等)的使用方法,并通过代码示例演示了各类运算符的实际应用。文章还强调了运算符优先级和结合性对表达式求值的影响,帮助开发者编写高效且可读性强的计算逻辑,为后续学习运算符重载和复杂表达式构建奠定基础。

今天比昨天更努力一点! 3389

C++20新特征的一些总结

Ranges 库是对标准模板库(STL)的一个重要扩展。它重新定义了容器和算法的交互方式,使代码更具可读性和表达力。Ranges 库的设计目标是减少代码中复杂的迭代器操作,使程序员能够以声明式风格操作序列数据。三向比较运算符,俗称“太空飞船运算符”(),是 C++20 引入的一种新型比较运算符。它简化了多重比较运算的实现过程,自动生成 ==、!=、= 等运算符。协程是一种特殊的函数,允许在执行过程中暂停并在稍后恢复。C++20 原生支持协程,使异步编程和生成器的实现更加简洁和高效。

weixin_50508006的博客 2016

C++反射革命:reflect-cpp如何让序列化变得简单高效

在C++开发中,你是否曾为繁琐的序列化代码而烦恼?是否觉得反射功能实现起来既复杂又容易出错?今天我要介绍的reflect-cpp将彻底改变你对C++反射的认知——这是一个让序列化变得前所未有的简单高效的C++20库。 ## 🎯 为什么你需要关注reflect-cpp? 在现代软件开发中,数据序列化无处不在:从配置文件读写到网络通信,从数据持久化到API交互。传统C++实现这些功能需要编写大量

gitblog_00765的博客 374

C++ 第四阶段 STL 容器 - 第十讲:C++20 新特性与 STL 容器的未来演进

C++20革新了STL,引入六大核心特性:范围(Ranges)支持链式数据操作,概念(Concepts)强化模板类型约束,三向比较简化自定义类型排序,std::contains优化容器查询,透明哈希提升查找效率,std::span提供安全内存访问。这些特性显著提升了代码简洁性、类型安全性和运行效率。典型应用包括数据流处理(Ranges)、模板泛型编程(Concepts)和性能敏感场景(std::span)。需注意版本兼容性和生命周期管理等潜在问题。

弘羽 2199
上一篇: 揭秘atomic fetch_add 的内存序陷阱:99%的程序员都忽略的关键细节
下一篇: 委托构造函数如何正确调用?彻底搞懂C++11中构造函数链的执行顺序
QuickDebug
博客等级 码龄1年 152粉丝 2013原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值