C++ 日期计算接口:mktime、gmtime、localtime与boost::posix_time
过去的一个星期日(11月1号),美国的冬令时回归,使用了夏令时的州人民都需要在这一天将时钟往前拨一个小时,现代智能设备基本都支持自动的时间跳变,11月1号凌晨2点一到,全美的时钟会再次自动跳转至1点;如果你忘记为机械表调整时间,那么明天9点你到学校,估计只有若干个和你一样忘记调冬令时的伙伴。对夏令时而言,则是在春天前(一般是3月的第二个周日2点),往后调一个小时至三点。
目前全球目前只有少部分国家使用夏令时制度,但在上世纪尤其是战时夏令时非常普遍,中国在1986年也尝试实行夏令时制度,1991年废止,夏令时旨在最大程度利用白天光照,起到节能增效目的,本质就是春夏天日照时间长时早起一小时、早睡一小时,照明的时间也相应减少,电费也少交了。但进入21世纪这样的节能制度没什么效果,因为空调成本可能还更高,这也是为什么许多国家正意欲废除夏令时制度。
夏令时也是影响本地时间的因素之一,因此程序设计中了解本地时间和UTC时间很有必要,C/C++也提供许多跨平台接口。
时间戳转具体日期时间
计算机系统定义1970-01-01 00:00:00 UTC起,Unix时间戳指的就是从这个时间刻过去的 ...
Golang基础(五):goroutine并发哲学、原理实现与编程
并发编程
golang并发哲学
同C++/java等传统语言不一样,golang天生支持并发,而且使用的设计哲学是通信顺序进程(Communicating
sequential processes, CSP);
并发与并行
golang严格区分了并发和并行的含义:
并发(Concurrency):解决多个任务如何合理地组织起来,例如单核情况下不同任务的时间片分配;(核内依赖于时间片调度);
并行(Parallelism):
解决如何在多核上同时跑更多东西,例如多核情况同时进行多个任务(核间本身不依赖时间片并发);
将问题拆分成多个可独立推行的任务,至于任务的调度、是否多核同时进行,完全由golang运行调度器决定。
通信顺序进程CSP
我们知道,C++/java的并发完全依赖于对共享内存的控制,每个想访问共享内存的线程都需要先获取锁,才能对内存进行读写;尽管存在一些被称为无锁编程的事务,例如原子变量,实际上是来自底层硬件CAS的支持,而且复杂的对象结构仍然会退化成自旋锁或者互斥锁的机制。
1978年,Tony
Hoare(1980图灵奖得主,于26年3 ...
Golang基础(四):接口、动态类型与反射
Go接口与动态类型
静态类型和动态类型
golang的接口类型同时支持静态类型和动态类型,其中:
静态类型(static
type):指编译期确定的类型,例如普通变量的类型,var a int/var b string,一旦定义类型就不可变更,不合法的赋值也会在编译期报错;
动态类型(dynamic
type):指运行时装入接口值的具体类型;
定义一个接口值(interface
value),%T能够正常获取动态类型,默认打印%#v能够获取动态值:
123456var i interface{}i = 2fmt.Printf("%T %#v\n", i, i) // <int> <2>i = "EdenMo"fmt.Printf("%T %#v\n", i, i) // <string> <EdenMo>
从定义而言,interface{}就是i的静态类型,int和string就是程序运行时的动态类型,其可以在程 ...
Golang基础(三):流程控制与函数
流程控制
条件语句if
基本形式: 12345678if cond1{ ...}else if cond2{ ...}else{ ...} 特点:
条件必须是布尔值或者布尔表达式,不再支持整型0/1或者其他非零值(指针等);
条件表达式不需要括号,代码块必须有花括号;
最大的特点是支持初始化语句,允许在if后定义局部变量供给条件语句块使用:
1234567891011if x:=f(); x>0{ ...}else{ ...}if n:="abc"; x>0{ fmt.Println(n[0]) }else{ fmt.Println(n[1]) }
条件语句switch
基本形式: 1234567var flag int = 0switch flag { case 0: flag = 1 case 1: flag = 2 c ...
Golang基础(二):变量与数据类型
变量声明
golang变量以关键字var开头,变量名放中间,变量类型声明后置:
var 变量名 变量类型
123var name stringvar num intvar isok bool
为了简化掉var,还支持批量变量声明:
123456var( a string b int c bool d float32)
变量赋值
和C++类似,变量声明会进行默认初始化,例如整型和浮点型默认为0,字符串类型默认为空字符串,布尔型默认为false,切片/函数/指针变量默认为nil。
同样可以在声明时通过表达式赋值: 12var name string = "EdemMo"var age int = 18
编译器还支持自动的类型推导,省略类型声明,甚至一个等式声明多种变量:
1234var name = "Eden"var age = 18var name,age = "Eden", 18 //ok
函数变量
全局变量使用上述方式进行声明,如果是函数内部的局部变量,无需var ...
Golang基础(一):环境部署与Hello World
Go语言概述
Golang创自2007年,由谷歌于2009年正式开源的一门计算机高级语言,其由C系语言改进而来,自开源以来便得到许多为人津津乐道的赞赏:天然支持高并发、跨平台、简单易用、性能高,其生态社区也逐渐完善,其设计哲学非常简单,直接丢弃了C++三大面向对象特性——类封装、继承和多态,泛型(1.18,2022年)是后面才引入的。
当然,Go在国内市场仍然是一款高度业务化的语言,多用于设计微服务和高并发,可玩性(可折腾性)比不上python和C/C++,这也是其设计哲学的体现,从底层而言其不提供手动内存管理而使用自动gc,不适用于内核开发;从应用层而言其更多专注后端服务,对Gui支持较差,就业市场也比较狭窄,尤其AI时代下使用其他语言去造轮子成本更低,使得Go并不那么需要被迫切普及。
但尝试新东西总会有新的启发,golang仍然是其中较为值得学习的语言之一。
windows 11安装和VsCode编译
go的安装比较简单,在网址下载msi安装,或下载压缩包(如go1.27.1.windows-amd64.zip,注意要x86-64架构的),解压并且设置环境变量即可,以下下 ...
C++ 23 新特性总结(一):Deducing this与CRTP模式
C++ 23新特性:Deducing
this(this推断特性)
Deducing this是来自Gašper
Ažman 、 Sy Brand 、
Ben Deane 和 Barry
Revzin的提案,他们希望用一种新的方式来推断成员函数中被调用表达式值的类别,也即从成员函数内部,判断它调用的表达式的cv特性和左右值类型等。
目前看来有三大用处:
在匿名函数中简单的实现递归:这就是在此前文章中描述的;
替代过多左右值重载函数的实现;
简化CRTP模式的实现;
完整提案见Deducing
this。
重载函数deducing
在Scott Meyers的《Effective C++》中(见读书笔记:Effective
C++(第三版))中提到,C++
03允许成员函数拥有cv限定符,某个类中需要同一个成员的const和non-const重载,但他们的实现是基本一样的,这种情况要么写相同的代码,要么类似Scott
Meyers那样采用委托的方式,让一个重载依赖于另一个重载的实现:
1234567891011class TextBlock ...
C++实现匿名函数递归:std::function、Y Combinator and Deducing This
这周写到递归的快速排序时突然发现:我不懂如何去用匿名函数去递归自身,因为正常的lambda就不支持:
12345678910//this is a wrong code phasestd::vector<int> nums{9,5,2,7,1,2,3};auto quick_sort = [&nums](int low, int high){ if(low < high){ int pivot = sort_paticial(low,high); quick_sort(low, pivot-1); quick_sort(pivot+1, high); //wrong }};
当然C++委员会也意识到这个问题,在C++
11我们有std::function,C++
14有Y组合子,C++
23有Deducing this,籍此机会详细记录一下。
方案1(C++11):std::function封装
对大部分编译器匿名函数不支持在捕获列 ...
数值分析方法:C++的工程实现
《数值分析方法》想来是不少工科研究生的必修课程,最近发现不少工程问题的初始推导都来自数值分析的一些方法,全面梳理其中的算法和结论推导是想做很久的事情之一,虽然很耗时间,但是并不是什么很困难的事情(对比此前各种的Labs),毕竟教会一个engineer如何做researching,比教会一个reseacher如何做好engineering要来得简单(然而很多reseacher乐意去做engineering,但engineer有机会且沉下心做reseach的少之又少)。这本书更是有很多适合工程化的算法,因此本文会基于原教材的编排和定理结论,尤其注重结论的证明和相关算法demo的C++实现,提供:
数值分析的基本思想方法和手段。
遵循数理的结论推导与证明。
开箱即用的各种C++算法。
适量的数值优化/最优化理论拓展;
第一章:数值分析与科学计算引论
误差定性与分析
误差分类
模型误差:建立的数学模型和实际问题之间出现的误差,称为模型误差;只有简化和抽象问题时合理才能得到较好的结果,这种误差不在数值分析的讨论中,同时要衡量这种误差有时候需要根据观测物理量,如温度、电 ...
快速方差更新算法:Welford Online算法
方差Two Pass算法
最近在数据处理中验证数据时发现细小的理论偏差,排查后发现是数据的方差更新方法出现了错误,起源是想优化这么一组函数:
123456789101112auto calculateVariance = [](const std::deque<int>& data){ if(data.empty()){ return 0; } int mean = std::accumulate(data.begin(), data.end(), 0)/data.size(); double sum_sq_diff = 0.0f; for(const auto& pos : data){ int diff = pos - mean; sum_sq_diff += diff*diff; } return (int)(sum_sq_diff/data.size());};
因为这个data时常需要更新,每次更新都要重算整组函数,于是想到缓存一下总数,但是却没有重新计算均值 ...

