密码学笔记——RSA算法
整理一下RSA算法的内容,主要参考维基百科。 对称加密与非对称加密 首先从对称加密开始,Alice和Bob需要进行加密的通信,Alice传递信息 \(m\) 给Bob。 为了信息安全,Alice首先用字母表替换的方式 \(A\) 将明文m变成密文 \(m'=f_A(m)\),然后通过公开方式传递给Bob,Bob使用同样约定好的字母表替换方式 \(A\) ,将收到的密文 \(m'\) 变成明文 \(f_A^{−1}(m')=f_A^{−1}(fA(m))=m\) 。 这里我们对信息都视作字符串,从而字母表替换规则 \(A\) 实际上定义了字符串到字符串的加密函数 \(f_A\) 和解密函数 \(f_A^{−1}\) ,这里加密函数和解密函数都是通过 \(A\) 决定的,并且极容易从其中一个推出另一个,因此双方都必须保管好密码本 \(A\) 。 例如,使用替换的字母表 \(A\) 为 11->3, 2->4, 3->2, 4->1 用轮换的记号就是\((1324)\),此时的加密函数 \(f_A\) ,明文\(1234\),密文 \(f...
Docsify 搭建记录
需要一个小型的在线文档系统,Docsify可以满足需求,记录一下搭建记录,主要参考Docsify官方的中文文档。 本地搭建 前提:本地需要安装 nodejs 并完成相应配置。 新建DocBase/文件夹,在其中本地安装 docsify-cli 1npm i docsify-cli -g 由于 docsify-cli 不是全局安装的,存在找不到 hexo 命令的问题,对于 Windows 可以通过临时添加路径到 PATH 解决,在 DocBase 目录下执行 1$env:Path += ";$((Get-Item -Path .\node_modules\.bin -Force).FullName)" 初始化项目 1docsify init ./docs 初始化过程会自动新建./docs子文件夹,并生成如下文件: index.html:项目入口 README.md:内容会被渲染成项目主页 .nojekyll:防止Github忽视下划线开头文件 使用下面的命令可以在本地预览 123cd ./docsdocsify serve# or docsify s...
Cpp 函数重载与函数标识符
函数重载 重载(Overloading)是 C++ 为允许同名函数使用多种参数列表以及多种实现版本而提供的机制,C语言是不支持的。 具体来说,函数重载指在同一个作用域中,定义多个具有相同名称但参数列表不同(个数或类型不同)的函数,这一组函数会构成相互重载的关系, 它们之间可以具有相同或不同的返回值类型。 例如 1234567891011121314#include <iostream>int add(int a, int b) { return a + b; }double add(double a, double b) { return a + b; }int add(int a, int b, int c) { return a + b + c; }int main() { std::cout << add(1, 2) << "\n"; std::cout << add(1.5, 2.3) << "\n&q...
Linux 学习笔记:控制台,终端,tty
整理一下关于下面这些概念的学习: 终端(terminal) 控制台(console) 电传打字机 tty(teletype) 这些概念在早期是有明确的定义的,但是随着计算机的发展,它们的物理实体逐渐消失,各种概念主要靠计算机软件模拟,它们之间的区别变得模糊难以理解,因此学习整理一下,以Linux系统为主。 TODO shell 控制台与终端 早期的计算机是一套巨大的机器,就像工厂的大型机器一样,如此的庞然大物必然需要一个专门的操作台, 用于陈列各种仪表盘、指示灯、按钮、电线,专业操作人员通过这个操作台控制计算机的启动、运行、停止,结果也会实时反馈到操作台,这个操作台就叫“控制台”(console)。 控制台是附着在机器上的设备,可以实现对计算机的完全操控,但是主要是用来管理计算机的。 对于多用户操作系统(特别是UNIX),控制台并不方便给用户提供计算服务。 因此自然产生了终端(terminal)的硬件概念:每个用户通过终端设备与主机远程连接(还不是现代意义上的基于互联网的远程连接),管理员给每个用户分配一个账户,用户“登录”到系统获得计算机使用权。在这个阶段,计算机通常只...
Cpp 并行计算学习笔记
基本概念 首先学习几组基本概念: 并发(Concurrency)/并行(Parallelism) 同步(Synchronous)/异步(Asynchronous) 进程(Process)/线程(Thread) 并发 / 并行 并发指的是多个任务在同一时间段内被同时推进,可能是同时执行不同的任务,也可能是频繁交替执行每一个任务的一小部分 并行指的是多个任务在同一时间段内真正同时执行 举个例子: 学生在课后可以并发地完成每一个科目的作业:一会写语文作业,一会又切换回写数学作业,切换可以非常频繁,但是不可能同时写两科作业,也就是不能并行 人体的消化系统的任务和循环系统的任务在并行地执行:在同一时间内,肠道蠕动和血液循环在同时进行,不可能说心脏跳动时就让肠道蠕动暂停 同步 / 异步 同步是指任务按照顺序依次执行,每个任务在前一个任务完成后开始执行。在同步模式中,任务之间需要等待其他任务完成才能继续执行。 异步是指任务可以独立于其他任务进行执行,它们的执行过程不会产生堵塞。在异步模式中,任务可以在后台执行,执行结果可能需要等待一段时间才能获得,但这不会影响其他任务的执行。 ...
GCC 源码编译安装(离线,普通用户)
gcc 的非 root 用户离线编译安装比其他的软件的源码安装都要复杂:因为它有依赖,在服务器上无法通过联网下载,要提前下载依赖的压缩包,而且gcc的编译时间很长。 安装过程主要参考CentOS7 离线升级安装gcc到6.3.0 和Linux 非root安装GCC9.1.0 下载依赖 在官网或者镜像网站下载 gcc-11.4.0.tar.gz,传到服务器上解压为~/tmp/gcc-11.4.0 进入~/tmp/gcc-11.4.0子目录,需要解决下载依赖的问题。在可以联网的情况下,直接执行自带的下载依赖的脚本 ./contrib/download_prerequisites。如果服务器无法联网,则需要手动下载处理 查看上述脚本,找到四个必要的依赖 gmp,mpfr,mpc,isl 以及对应的具体版本,例如 gcc-11.4.0 需要的四个依赖版本及其下载地址如下(不同版本的gcc对应的依赖版本也不一样) 123456gmp='gmp-6.1.0.tar.bz2'mpfr='mpfr-3.1.6.tar.bz2'mpc='mpc-...
Cpp 面向对象——成员函数中的 this
整理一下关于C++类的成员函数所拥有的特殊的this指针的知识,并且学习C++23中的新内容:显式推导this。 隐式this 基础 this指针是C++面向对象编程中的重要机制,在自定义类型的非静态成员函数中,都存在这一个自动传递的this指针指向当前对象自身,例如 12345678910111213#include <iostream>struct Test { int data = 0; void call() { std::cout << "call: " << data << "\n"; }};int main() { Test test{1}; test.call(); return 0;} 对于编译器来说,这里的定义和调用过程等效于下面的形式(因为this是关键词,在代码中使用this_来代表) 1234567891011121314#include <iostre...
Cpp 未定义行为/小坑/冷知识
未定义行为 概述 C/C++存在很多的未定义行为,如果程序中使用了未定义行为,那么得到的结果是不可知的,编译器给出任何反馈都是符合语法标准的,因为未定义行为导致的BUG是难以察觉的。 未定义行为可能会导致编译报错,也可能导致运行出错等,还可能无事发生,具体结果可能与平台/编译器有关,不过在大部分情况下不同编译器会得到类似的结果。 未定义行为的存在是有客观原因的,一方面语法标准无法穷尽所有的可能情况;另一方面有些可能非法的行为(例如下标越界)在编译期难以直接检测,如果在运行期进行检测(例如检查下标越界),又会牺牲很多的运行效率。 如果我们在不经意间使用了未定义行为,那么即使是相同的代码,在C++的编译器不同等级的优化措施下,也可能得到完全不同的结果,例如: Debug模式正常,Release模式异常 例如产生随机的结果,通常的原因是使用没有正确初始化的变量,在Debug模式下被编译器初始化为0,但是Release模式下直接使用了内存中的随机值; 其它未定义行为,在Release模式下经过编译器优化中,产生不合理的结果。 Debug模式异常,Release模式正常 代码中的未...
编程语言中的整除和取余
整除和取余是两个看起来非常简单明确的基本数学运算,但是在不同编程语言的实现中,其实存在着很多的差异,需要注意一下。 数论中的整除和取余 我们从这两个概念的数学定义出发,在数论中的整除和取余定义为:对于整数 \(a,b \in \mathbb{Z}\),其中 \(b \neq 0\),存在唯一的商 \(q\in \mathbb{Z}\) 和余数 \(r \in \mathbb{Z}\),使得 \[ a = b \,q + r \] 对于余数要求 \(0 \le r < b\),即余数是一个非负的且不超过除数的整数。 虽然初等数论主要关注的都是整数,通常不会涉及对实数的整除和取余运算,但是我们仍然可以直接将上述定义推广到实数中:对于实数 \(a,b \in \mathbb{R}\),其中 \(b \neq 0\),存在唯一的商 \(q\in \mathbb{Z}\) 和余数 \(r \in \mathbb{R}\),使得 \[ a = b \,q + r \] 对于余数要求 \(0 \le r < b\),即余数是一个非负的且不超过除数的实数。 数论中要求在任何情况下,...
关于编程语言的理解
不再细究某个编程语言的细节,而是从宏观角度来理解编程语言的设计哲学。 部分内容取自网络资料和GPT,仅作为学习整理,不保证正确性,事实上这部分内容在网上的中文资料很混乱,有很多都是错的。 编程范式的历史与演变 简单回顾一下编程范式的历史与演变。 顺序编程 在早期编程中,人们采用的编程方式被称为顺序编程(非结构化编程)——程序按照上下文顺序执行指令,GOTO语句在其中发挥了重要作用, 它可以无条件地跳转到程序的任意部分。 GOTO语句的滥用导致了“意大利面条式代码”,使得程序变得难以理解和维护。为了克服GOTO语句带来的代码混乱,20世纪60年代Edsger Dijkstra等人提出了结构化编程。 结构化编程 结构化编程的核心是控制结构,例如顺序、选择(如if、switch)、循环(如for、while)等结构,通过这些控制结构来组织代码,尽可能避免GOTO语句的使用。控制结构提高了代码的可读性和维护性,是现代编程语言的重要基础。 面向过程编程 面向过程编程是基于函数调用的编程范式,通过一系列过程(函数)的调用来组织代码,C语言是其中的典型代表。 面向过程编程的特点是数据与操作...