一个函数的自白:从函数的角度看编程的方式

RISC-V实战:从逻辑门到32位ALU的Verilog实现 ALU是CPU核心组合逻辑单元,直接决定算术、逻辑与移位指令的执行正确性。其原理基于布尔代数与超前进位加法器,通过并行计算与选择输出实现低延迟运算。在RISC-V处理器设计中,ALU设计质量影响时序余量与运算正确性,广泛应用于嵌入式与FPGA开发。掌握ALU设计有助于理解数据通路与流水线,是RISC-V入门的关键一步。 阅读详情

 以下内容转载自

https://mp.weixin.qq.com/s?__biz=MzA5MzY4NTQwMA==&mid=2651002566&idx=1&sn=76b652c0af85df983993271adcc0b87e&chksm=8bada531bcda2c2722c093be5ba61081b4833eee06dec31e7337b6a617a2238959ca2146aec0&scene=21#wechat_redirect


作者丨老曹

来源丨喔家ArchiSelf

我是——编程世界的函数,不是数学中的幂,指,对和三角函数等等,但是和f(x)又有着千丝万缕的关系。

我是代码中的最小执行组织,但不是最小执行单元。最小的执行单元是一条条语句,这些语句有机地组合起来完成一个或多个功能并且可以复用,这才是我——函数。

内存与堆栈和我之间是啥关系?
有无参数的我有何异同?
我的简洁性?复杂度如何评估?
我的高阶与递归有啥区别?
我的回调和匿名是一回事么?
对象中的方法是我么?
控制对象的行为方式有哪些呢?
为什么说类型错误只是异常处理的一种方式?
面对数据密集型应用和并发场景,我有何作用?
......

且听一个函数的自白,从函数的角度看编程的方式。

我眼中的大环境——内存

空山不见人  但闻人语响

代码最终都要加载到内存中执行,组成函数的代码同样如此。内存容量是受限的,需要考虑一个函数在内存中所需要处理和生成的数据量。内存中没有变量名或签名的内存地址,只有以数字表示的内存地址。考虑“什么将存入内存”,“什么存入硬盘”以及“何时将内存内容存入硬盘”,这些考量都与性能优化息息相关。

而现代编程语言强调透明的内存管理,关注处理中不断增长的数据规模,这很容易失去对内存消耗的控制,从而导致运行时性能的下降。对我所采用的不同内存使用策略,所带来的不同结果给予适当的关注,是件有意义的好事情。

我的运行环境——堆栈

明月松间照 清泉石上流

由于内存中的东西太多了,于是把我运行环境中的内存称为堆栈。对于栈,所有操作都针对栈中的数据,堆用于存储后续操作所需的数据。堆中数据需要入栈进行操作,最终出栈回到堆。栈溢出是内存耗尽的情况。

通常对程序员来说,栈是不可见的,几乎在每个现代的编程语言中,栈都是支持线程执行的内存区域。 堆是许多现代编程语言实现中的另一重要内存区域,用于动态内存的分配和释放,例如创建列表和对象。不要将这里的堆栈与数据结构中的概念混淆,数据结构中的堆是一个基于树的数据结构。

有一种执行环境叫栈机器,使用了栈而不是寄存器来支持程序表达式的计算,许多现代虚拟机都是这样的,例如JVM。

我源自面向过程的抽象——过程函数

大事化小  小事易了

程序员们通常会把复杂问题分解为若干个较小的容易问题,这是一种面向过程的抽象,一个过程是实现某一功能的我,我可能接收输入,但未必产生输出。极端一点的我既没有输入参数,也没有返回值,是纯粹的过程函数。每个过程函数独立做一件事,完成一项任务,过程函数一般不返回数据,只操作共享数据。人们把这种编程方式叫做结构化编程。

作为过程函数的我一般用全局变量来共享状态,我会改变或增加共享状态。过程函数可能不是幂等的,而缺乏幂等性被很多人认为是编程错误的一个来源。

幂等性: 若一个函数或过程是幂等的,对其进行多次调用将观察到同样的效果,
与一次调用的效果是相同的。

而且,采用全局变量也一直被认为是一个馊主意,然而在系统层面,架构中的组件共享其实和全局变量类似,这让我有时候感到无语。

我和伙伴们组合起来——复合嵌套

但远山长 云山乱 晓山青

当程序员把复杂问题分解成若干小问题的时候,一般都是把我接收的输入形成输出,这样就可以把所有任务都视为输入集合到输出集合的映射关系了。嗯,f(x)的味道来了。

这时候,函数间无状态共享,类似于数学中的复合函数。特殊的,把函数作为输入或者输出的函数被称为高阶函数。多个参数的函数可以通过柯里化技术转化为一系列的单参数高阶函数。

这种串行话处理的一个知名应用就是Unix Shell 中的管道,编译器及其他语言处理器也很适合这种方式,且倾向于利用图和树等数据结构组合过程。类似的,还有单元测试和开发部署。

构成我的代码简洁性

天街小雨润如酥 草色遥看近却无

程序员通常把简洁作为编程技艺的标志之一,但是当代码简洁成为唯一目标的时候,每行代码又往往会变得冗长且难以理解,这是因为需要利用编程语言的许多高级特性和库来实现。无论好坏,源代码行数(SLOC)还是可以用来估算成本和开发效率的,也可以评估可维护性和其他许多管理指标。例如,CoCoMO就是基于SLOC的成本评估模型,至今还被采用。

基于代码行数的简洁性往往取决于已经构建好的第三方库和方法,当然,运用得当,简洁性也会带来优雅且可读性强的代码。一般地,可以信任核心库,但对第三方库的使用需谨慎。

面向简洁性,融合高阶函数,以至于一切皆为函数, 甚至形成了新的编程模式——函数式编程。纯粹的函数式编程语言,以Haskell 为代表。

我的复杂性度量

吾尝观窍妙  渠敢讥杂驳

我的复杂程度是由程序员决定的,可以非常简单,也可以非常复杂。一般地,可以采用一种叫圈复杂度的方式来评估我的复杂程度。圈复杂度是一个用于衡量代码复杂度的方式,主要是通过描述控制流路径的数量来表示复杂度。圈复杂度把程序看成一个有向图,计算公式如下:

CC = E -N +2P  E是边数  N 是节点数,P是节点出口数。

圈复杂度可以衡量程序的复杂性,同样适用于函数。

我调用我自己——递归函数

知人者智 知己者明 

由于很多的问题都可以使用归纳法进行建模,就象学生时代的数学归纳法那样,即已知n=0的情况和n到n+1的推导规则,对问题进行求解。一般地,在编程世界中,归纳法用递归函数表示。递归函数就是自己调用自己,一直在栈中操作,如果递归层次过深的话,会导致栈溢出问题的出现。

在许多编程语言中,尾递归优化解决了递归调用中的栈溢出问题。 尾调用是指一个函数里的最后一个动作是一个函数调用,即在函数尾部发生的递归调用。尾递归即在函数尾部发生的递归调用,尾递归发生时,程序语言的处理器可以安全地删除先前的栈记录,因为该调用返回时栈中不需要继续其他操作,这就是尾递归优化,尾递归优化有效地将递归函数转为迭代,节省了时间和内存。

需要注意的是,python中并不对尾递归进行优化,一般要对调用深度进行限制。

下一个是我的自动调用——回调和匿名

忽如一夜春风来,千树万树梨花开。

一般地,函数间的调用是显式的,即一个函数执行完毕在执行下一个函数。 但有这样一种使用场景,一个函数有一个额外的参数,通常是最后一个,这一参数是另一个函数,在函数执行到末尾的时候,作为参数的函数也会被调用。 

参数函数作为输入,也作为当前函数的输出,函数间的这种管道式传递可以解决处理规模较大的问题,即管道中下一个被调用的函数会当作当前参数的输出。 这种后续传递,通常使用匿名函数。

如果参数函数并不是在末尾被调用,而是在特定的事件或条件发生时由另外的一方调用,参数函数用于对该事件或条件进行响应,通常使用回调函数。在C/C++中,回调函数就是一个通过函数指针调用的函数,把函数的指针(地址)作为参数传递给另一个函数,用这个指针来调用其所指向的函数。回调函数一般使用通知机制。典型的场景如编译器优化,处理程序的正常流程和异常流程,解决单线程语言的IO阻塞问题等等。

需要注意的是,大量的回调函数可能会增加复杂性,使代码的可读性变差,例如JavaScript 中的回调地狱。

我们长在对象上就成了——方法

千人同心   则得千人之力

我们都是要处理数据的,可以把数据封装起来形成一个可以修改的数据抽象。 将若干函数逐个绑定在数据抽象上,建立函数的调用顺序,查看数据的最终结果,这是一种面向数据的过程封装抽象,特点在于绑定操作将数据抽象作为参数,调用指定函数,并将函数返回值赋回。

如果将问题分解成某些问题领域的相关对象,每个对象都是一个数据封装,处理过程暴露在外,数据只能通过这些过程访问,不可直接访问,每个对象可以重新定义在其他对象中已经定义好的过程。这种长在对象上的函数又叫——方法。

对象的本质是过程分享对象內的数据,与类和继承联系在一起。继承实际上定义了对象间的从属关系,从而有了抽象类,基类,实例,覆盖,子类,单例等等。

对象中我们的远程调用

万里云霄送君去 不妨风雨破吾庐

随着网络应用的发展,网络中某个节点的软件希望引用其他远程节点的对象实例,并且把远程对象的方法当作本地方法来使用。于是,诞生了分布式对象系统的平台和框架,例如CORBA 和RMI。这些分布式对象系统有一个前提假设,就是需要为所有的分布式组件采取通用的编程语言或基础架构,但通用基础架构的假设是难以成立的。CORBA的统一化方式退出了舞台,它和web技术的大规模应用相冲突,因为后者基于的是不同技术的大规模系统设计方法。

但是对象方法的远程调用还是有使用场景的,如果每个对象是仅公开一个过程的数据封装,即能够接收和发送消息。消息分发机制能将消息发送至另一个封装。 对象向外界公开一个函数————接收消息的函数而并非一系列函数,其他的数据和函数被隐藏在内部, 接口函数处理能够被对象解释的消息;一些无法被对象解释的消息,则被忽略或生成某种形式的错误;另一些消息可能并不由该对象直接处理,而是由其他与接收对象相关的对象处理。

对于消息分发机制,带来的是某个对象使用其他对象的方法执行过程的能力。消息分发是接收消息、解释消息并确定执行步骤的过程。该过程可能是方法执行、错误返回或者向其他对象转发消息。

对象的域——我们与对象中数据的关系

悠然一曲泉明调 浅立闲愁轻闭门

对象的域一般是指键与简单值的映射,对象中的一些方法成为了键与值之间的函数映射,构造函数是最先被调用的方法。闭域是指每个对象是一个键值映射,其中某些值是我们这些函数。对象的方法引用对象自身的键,使得映射是封闭域的。

闭域解释了对象编程中的一个特色——原型。原型常见于无类面向对象语言中的对象。原型带有自己的数据和函数,可以自由地改变而不影响其他对象,新原型可以通过复制已存在的原型获得。

闭域风格的缺点在于没有访问控制,只能由程序员来约束,通过键来检索字典等同于向字典发消息。

对象的抽象——抽象对象

草枯鹰眼疾 雪尽马蹄轻

抽象对象是将大问题分解为问题域相关的对象抽象。抽象对象定义了对象的抽象行为,具体对象以某种方式与抽象对象绑定,绑定机制可以不定,应用程序的其他部分并不依赖对象的内容,而依赖对象的行为。

在设计模式中,适配器模式的目的与抽象对象是一致的,隔离了应用程序与具体的功能实现。抽象对象在大型系统设计中举足轻重,抽象对象的实现根据涉及的具体编程语言而定。Java中的抽象对象是接口,可以在类型上参数化;Haskell是一种强类型的纯函数语言,抽象对象表现为类型类;C++拥有抽象类,连同模版一起完备地提供了参数化抽象对象的概念。

控制对象中我们的另一方式——控制反转

春潮带雨晚来急  野渡无人舟自横

还有另一种对象行为的控制方式,利用对象和模块等不同形式的抽象,将大问题分解成若干个实体,这些实体不能被直接调用,而是为其他实体提供接口,使其他实体能够注册回调函数,这些实体中的函数调用是通过其他实体注册过的回调函数来完成的。

这种行为控制方式不会在程序中显式地调用函数,而是通过反转关系,使调用者可以同时触发多个行为,是一种能够在框架中触发任意应用代码的机制,这就是控制反转。

控制反转是分布式系统设计的一个重要概念,源于异步硬件中断,回调函数可以同步执行也可以异步执行。在事件发生时,不同网络节点间的回调函数不用长轮询,从而,事件驱动框架应运而生。

类似的,可以使用一个用于发布和订阅事件的基础结构,对象实体中的我们负责订阅和发布事件,基础结构负责事件的管理和分发。 这样的基础结构常与异步组件共同使用,也可能包含更复杂的事件结构,支持更精确的事件过滤,相当于控制反转的轻量级形式。

审视自身,进而改变我自己

见贤思齐焉 见不贤而内自省也

在程序设计的过程中可以将程序自身也一起考虑。有一种抽象的方式是可以获取自身以及其他的抽象信息,但不能改变这些信息。程序获取自身信息的能力叫做自省,支持自省的语言有java,python,javascript,以及PHP等,而C/C++不支持自省。其中,python 有强大的自省能力,如callable,inspect等。 然而,使用自省使得程序变得不直观,甚至难以理解,有利有弊吧。

反射使用了自省,程序在运行时可以通过增加抽象、变量等方式进行自我修改。反射的目的是要求程序能自我修改,ruby支持完备反射,python 和javascript在限制条件下支持反射,而java只支持小部分的反射。在设计过程中,当无法预期代码被修改方式的时候,会使用反射。

如果将问题的切面增加到主程序中,但不改变这种抽象方式的源码和使用该抽象的代码段,再通过一个外部绑定机制将这种抽象形式和切面绑定在一起,这就是AOP。AOP是一种受限制的反射,目的是在已有程序的指定代码前后插入任意代码。 切面主要关注可能被分散到应用程序中的代码,这些代码通常会影响许多组件,典型的切面如 profiling 和 tracing。

把我们有组织的固定下来充分复用——插件

但要前尘减   无妨外相同

如果把我们有组织的固定下来,所有或部分被预编译后通常会自成一体,主程序和每个包单独编译,主程序在开始时动态地加载这些包,使用动态加载包中的函数和对象,无需知道具体事项,这就是插件。

插件又叫plugin或者addon,不需重新编译,就可以将一系列功能加入到正在执行的应用程序中。通过一个外部定义来说明哪些包需要被加载,通常是配置文件,路径约定,用户输入或其他运行时加载外部代码的机制。现代操作系统的动态链接库dll/so 就是插件风格,需要注意的是存在配置深渊。

对于分布式体系结构和支持第三方扩展的独立应用程序,带有反射能力的编程语言使得在运行时链接组件变得可行并且非常简单。Java Spring框架就支持由反射机制带来的插件化开发,称为“依赖注入”和“插件”,插件一般使用描述性配置语言如INI和XML。

据说,插件是软件进化和定制的核心。

我错了?!——异常处理

此情可待成追忆  只是当时已惘然

异常是在程序运行中超出正常预期的情况。我和每一个伙伴都会检查自身参数的合理性,当参数不合理时,返回合理的结果或者给参数指定合理的值。所有的代码块都会检测可能存在的错误,当错误发生时,跳过代码块,设置合理的状态并继续执行函数的其他部分。

通常防御式编程能为用户带来较好的体验,每个过程和函数都检测自身参数的合理性,若参数不合理,程序停止运行。另外,当错误发生时,最好将上下文相关的信息写入日志,同时将错误传递回函数调用链。如果对异常采取消极态度,至少也应该通知各方正确的使用方式,以及停止运行的原因。

全局捕获是我们另一种处理异常的方法,在调用其他函数时,程序仅检测能够提供有意义反馈的错误。这种异常处理在函数调用链中位于较上层,仅在程序最外层进行异常处理,无视异常时间发生的位置。

无论在哪里捕获异常,调用栈都是异常信息的一部分,除非局部存在有意义的处理方式,更好的做法是将异常返回到函数调用链的上游。

我眼中的类型错误

堪嗟岁月蹉跎久   却悔尘寰错误多

对于输入参数而言,一般地,我会声明所期待的参数类型。如果调用方没有传送预期类型的参数,则会产生类型错误,这时将不再执行。类型不匹配是指我得到的值类型与所期待的值类型不符;或者一个伙伴返回了一个特定类型的值,但该值稍后被调用者当作其他类型的值使用。不同类型的值通常被分配不同大小的内存空间,这意味着当发生类型不匹配时,内存可能被重写而变得不一致,这就是这类异常的问题所在。

所有现代高级编程语言都有一个类型系统,在开发和执行过程中的不同节点检测数据类型。静态类型的语言如Java 和 Haskell,动态类型如JS,python等等。参数类型分为显示类型和隐式类型,相关的逻辑操作包括强制类型装换,类型推理和类型安全。

我可以专注于数据计算

无边落木萧萧下  不尽长江滚滚来

如果我专注于数据计算的话,会有一些特殊的约束。首先是隔离,核心函数不要有任何副作用,所有IO行为都最好和纯粹的函数明确区分开来,所有包含IO的函数最好从主程序中调用。这样做的主要目的是避免或最小化IO操作,尽量隔离IO操作,因为IO操作在大型系统中是个大问题。 

典型的数据密集型应用是数据库,数据独立于程序执行,能够被多个程序使用,存储易于快速检索,通过对数据查询来解决问题。对某些数据的规范处理可能包含数据列及公式,某些数据可能由其他数据通过公式决定。当数据改变时,相关联数据将自动改变,例如数据库中的视图,触发器和存储过程等。

如果数据的可用形式是流,我就是数据流的过滤器/变换器,根据下游的需求,对上游的数据进行处理。流式处理适用于支持生成器的语言,对于Java 这些不支持生成器的语言,可以通过迭代器实现。

我也可以适应并发处理场景

水深草茂群蛙怒   日出风和宿麦秋

面向高并发的场景,每个对象都存在一个队列,用于放置向其他对象发送的消息。每个对象都是一个数据封装,仅公开其接收消息的接口,用于前述队列,每个对象运行于独立的线程中。每个对象主动轮询各自的消息队列,一次处理一条消息,当队列为空时,阻塞当前线程。这大概就是Actor模型了。

当一个或多个并发单元,同时配备了一个或多个数据空间,数据空间用于并发单元的数据存储和检索,并发单元之间只能通过数据空间进行数据交换。 尤其是当任务需要横向开展的时时候,这种基于数据空间交换的方式,也是适合于数据密集型并行处理的。

对于流式数据而言,输入的数据流被分成若干块,map函数对每个数据块运用worker,通常过程是并行的。而 reduce 函数得到各个worker函数的结果,并重组成相关输出。 这种基于MapReduce的函数处理方式,极其适用于可以单独拆分和处理数据的数据密集型操作,其局部结果在最后被重组。如果将worker 函数的结果重组,第二次map以重组后的数据作为reduce函数的参数的话,就是双重MapReduce方式了。

一般的,map可以并行,而reduce不行,hadoop将map的结果列表重组并打乱,使后续reduce函数的调用可以对数据重组进行修改,从而reduce也成了可以并行化的。

至于restful,不过是将我们函数的思想用于子系统,更关注扩展性,去中心化和独立组件开发而已。

结尾的告白

谁人在处望风烟  芸芸众生吾自潜

函数是程序中最小的有序时空,运转于内存堆栈。

关于参数,没有输入参数和返回值就是纯过程函数, 而同时有参数和返回值才可能实现幂等性。多参数的我可以柯里化为单参数高阶函数,而参数中是函数的话可以形成处理管道,或者回调函数。我自己调用自己,就是递归函数。

关于对象,我长在对象上变成了方法,进一步可以提升为抽象对象。对象间的远程调用一般用消息机制,对象间的行为操控可以说是控制反转,而通过对本身的自省可以形成反射,AOP 可以看作有条件的反射。对于插件,几乎是函数组装之集大成者。

关于错误,一般采用防御式编程,也可以采用消极的方式,无论是否采用全局捕获,调用栈都是异常信息的重要部分。

关于特定场景,不论是密集数据计算还是高并发情况,都最终落实到函数的层面。


MBA论文降AI率实战:九大工具与人工润色策略详解 AI写作检测系统通过困惑度、突发性和模板化连接词密度等统计特征识别机器生成文本。MBA案例分析因大量使用SWOT、波特五力等标准化理论框架,天然接近AI语言风格,容易被误判。理解检测原理后,降AI率的关键在于提高文本的不规则性——包括增加低频词、打散句子长度、植入个人经验。本文解析QuillBot、笔灵AI、DeepL Write、Claude等九款主流工具的适用场景与副作用,并给出从分级检测、局部改写、人工“人味化”收尾到两轮验证的完整处理流程,帮助学习者在学术诚信前提下,通过语言自然化有效降低AI检测率 阅读详情

相关推荐

stm32f407VET6 系统学习 day01 GPIO 配置

stm32f407VET6 系统学习 day01 GPIO 配置 LED 蜂鸣器 按键的不讲了,之前讲过了

she666666的博客 8904

《自白》悬疑剧解析:4K画质下的心理博弈与叙事结构

悬疑剧作为一种影视类型,其核心在于通过精心设计的叙事结构和视听语言制造悬念与反转。从技术原理看,4K高画质能够呈现更丰富的画面细节,特别是在暗部表现和环境氛围营造上具有明显优势,这为悬疑题材的沉浸式体验提供了技术支撑。在工程实践层面,合理的剪辑节奏和镜头语言设计能够有效控制信息释放的节奏,避免观众过早猜透剧情。这种技术组合的价值在于提升作品的艺术表现力和观赏价值,适用于需要精细情绪渲染的影视场景。《自白》正是通过4K画质与双线叙事的技术融合,在密室命案背景下构建了律师与企业家的心理博弈,其反转设置和细节伏笔

weixin_34367257的博客 377

STM32F103C8T6通过ESP8266连接阿里云物联网平台(附代码)

STM32F103C8T6连接阿里云物联网平台(1)—阿里云lot Studio控制 Web开发 分享一下自己使用stm32f103c8t6通过ESP_01模块连接阿里云物联网平台,实现温湿度上传和控制命令下达的过程,能力有限,用的是最简单的方法,如有错误,多多担待。 一、硬件选型 1、 stm32f103c8t6 2、ESP_01 wifi模块 3、其他 二、硬件连接 WSP_01 STM32F103C8T6 RXD PA2 TXD PA3 RES PA4 VCC 3.3

weixin_A13253323604 3万+

一个函数的自白

我是——编程世界的函数,不是数学中的幂,指,对和三角函数等等,但是和f(x)又有着千丝万缕的关系。我是代码中的最小执行组织,但不是最小执行单元。最小的执行单元是一条条语句,这些语句有机地组合起来完成一个或多个功能并且可以复用,这才是我——函数。内存与堆栈和我之间是啥关系? 有无参数的我有何异同? 我的简洁性?复杂度如何评估? 我的高阶与递归有啥区别? 我的回调和匿名是一回事么? 对象中的方法是我么

喔家ArchiSelf 775

SRC漏洞挖掘实战指南:从零入门到月入过万的网络安全副业

网络安全的核心在于识别和修复系统缺陷,其中逻辑漏洞与信息泄露是常见的安全风险。其原理在于应用程序在业务逻辑设计或数据处理过程中存在缺陷,导致未授权访问或敏感数据暴露。掌握这些技术对于构建安全的应用体系至关重要,不仅能有效防范攻击,也为安全研究人员提供了将技术能力变现的合法途径。在漏洞赏金(Bug Bounty)和SRC(安全应急响应中心)等应用场景中,白帽子通过系统化的测试方法,挖掘此类漏洞,既能获得经济回报,又能积累宝贵的实战经验。本文聚焦于逻辑漏洞与信息泄露的实战挖掘技巧,为初学者提供清晰的入门路径和效

weixin_28568819的博客 349

快速玩转 Llama2!机器学习 PAI 最佳实践(一)—低代码 Lora 微调及部署

本实践将采用阿里云机器学习平台PAI-快速开始模块针对 Llama-2-7b-chat 进行开发。PAI-快速开始支持基于开源模型的低代码训练、布署和推理全流程,适合想要快速开箱体验预训练模型的开发者。

阿里云云栖号 1766

函数栈帧和内存分布笔记

<br /> <!-- @page { margin: 2cm } P { margin-bottom: 0.21cm } --> <br />call:函数的调用<br />ret:函数的返回<br /> <br />函数在调用时要做两件事:<br />1、将函数的返回地址保存<br />2、跳转到函数代码的位置处执行<br /> <br />函数在返回时要做两件事:<br />1、取出返回地址<br />2、跳转<br /> <br />函数的栈帧<br />每一

lanseshenhua的专栏 1637

STM32C8T6HAL库实战:MAX30102心率血氧检测与OLED多级菜单一体化方案

本文详细介绍了基于STM32C8T6和HAL库的MAX30102心率血氧检测与OLED多级菜单一体化方案。内容涵盖硬件连接、CubeMX工程配置、传感器驱动移植、数据滤波算法、OLED显示驱动以及高效的多级菜单系统设计,旨在提供一个稳定、实用且易于移植的嵌入式健康监测项目参考。

weixin_29256771的博客 397

栈帧 内存

4. **函数返回:** 当函数执行完毕并返回时,其对应的栈帧会被弹出(pop)调用栈,并且控制权会返回到调用该函数的代码处,即返回地址所指向的地方。4. **上一栈帧的基指针:** 也就是前一个函数的栈帧的起始地址,用于在函数返回时恢复前一个函数的执行环境。- 每个函数有自己的栈帧,因此函数内的局部变量和参数在函数外是不可见的,实现了变量的作用域隔离。3. **函数执行:** 在栈帧内,函数执行并可以访问其局部变量和参数。1. **函数调用:** 每次函数被调用时,都会创建一个新的栈帧。

OntheSnow的博客 217

vmware虚拟机网络连接问题

主机:ubuntu14.04 Vitual Network Editor

入门虽易,精通不易,且学且珍惜! 1354

详解AUTOSAR:AUTOSAR架构中的配置文件(拓展篇—7)

查看AUTOSAR代码包时会发现一些这样格式的文件:xxx_PBcfg.c、xxx_Lcfg.c和xxx_Cfg.h,本篇博文讲一讲这几个配置文件的作用和特点。

不脱发的程序猿 2147

函数栈帧的创建和销毁讲解

文章目录本章主题:1. 什么是函数栈帧2. 理解函数栈帧能解决什么问题呢?3. 函数栈帧的创建和销毁解析3.1 什么是栈?3.2 认识相关寄存器和汇编指令相关寄存器相关汇编命令3.3 解析函数栈帧的创建和销毁3.3.1 预备知识3.3.2 函数的调用堆栈3.3.4 准备环境3.3.5 转到反汇编3.3.6 函数栈帧的创建3.3.7 函数栈帧的销毁总结 本章主题: 什么是函数栈帧? 理解函数栈帧能解决什么问题? 函数栈帧的创建和销毁解析 1. 什么是函数栈帧 我们在写C语言代码的时候,经常会把一个独立的功能抽

杨同学的博客 2141

windows下宝塔安装教程

windows下宝塔安装教程 目录宝塔是什么?宝塔安装流程1.下载2.配置3.登录4.安装的环境套件小结 宝塔是什么? 宝塔是管理服务器的免费的软件,宝塔上面可以进行对你的服务器批量进行管理,对于运维人员来说还是必不可少的一个软件,值得使用。 宝塔安装流程 1.下载 链接: https://download.bt.cn/win/panel/BtSoft.zip 下载后安装买最好自定义目录,方便找 2.配置 下载完成后会出现这个页面,对着页面进行配置 点击默认密码复制进来,这里注意一点就是一定要查看

你在看屏幕的同时,屏幕也在注视着你 4423

函数与内存堆栈

目标文件和可执行文件的格式? 不同的系统的可执行文件有不同的格式。在SVr4实现中都采用了ELF(Extensible and Linker Format,可执行文件夹和链接格式)的格式,在其他系统中,可执行文件的格式是COFF(Common Object-File Format,普通目标文件格式,在BSD UNIX中也有自己自己的格式。可以通过命令man a.out 查看。 但是所有

doudou0918的专栏 626

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

[论文阅读] 人工智能 + 软件工程 | 开源软件中的GenAI自白:开发者如何用、项目如何管、代码质量受何影响?

本文解读了研究“开源软件中GenAI自承认使用”的论文。该研究通过分析开发者在代码中主动提及使用ChatGPT、GitHub Copilot的“自白”,揭示了GenAI在开源项目中的真实使用场景(如写代码、翻译)、项目规范(禁止、要求披露等),并发现GenAI使用后代码质量未普遍下降。其核心价值在于用“自承认”视角绕过技术难题,为理解和规范AI辅助开发提供了新依据。

张较瘦 1251

深度学习工具包 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")

《自白》悬疑剧技术解析:4K制作与心理博弈的叙事艺术

悬疑剧作为一种成熟的影视类型,其核心在于通过严密的叙事结构和视听语言制造心理张力。从技术原理来看,4K制作流程涉及摄影构图、光线控制和色彩管理等关键技术,能够提升画面的真实感和沉浸感。在工程实践中,双人心理博弈场景需要通过对话层次设计和微表情细节来展现人物内心活动,这种技术手法能够增强剧情的戏剧张力。悬疑剧的技术价值在于通过信息控制和节奏把握来引导观众预期,在密室命案等经典场景中,空间封闭性和时间线把控成为关键创作要素。应用场景涵盖影视制作、编剧学习等多个领域,自然收敛到《自白》这部剧对4K画质和心理博弈技

weixin_30698297的博客 516

No MFC (我) 的自白

请不要误会,我的名字不叫 "No MFC" 。     写这 "自白" 缘于昨日一网友 chinaeagle 问我,写 No MFC 系列的目的何在?  我竟一时间答不上来,我后来想了很多。     起初写作的时候,因为我所举的源程序在开头都会预先定义  #define WIN32_LEAN_AND_MEAN  。使不包含和 MFC 有关的预编译,所以取名 No MFC 编程系列 。   

benny5609的专栏 563

《一个广告人的自白》如何写一则广告?

3>在标题中可以使用的最有分量的两个词是“免费”和“新”,使用“免费”的机会不多,但“新”总是可以用上的。其他会产生良好效果的字眼是:如何、突然、当今、宣布、引进、就在此地、最新到货、重大发展、改进、惊人、轰动一时、了不起、划时代、令人叹为观止、奇迹、魔力、风险、快捷、简易、需求、挑战、奉劝、实情、比较、廉价、从速、最后机会...标题里加进一些充满感情的字就可以起到加强的作用,比如:亲爱的、爱、怕、引以为傲、朋友、宝贝...标题中使用否定词是很危险的,很多读者会忽略否定词。文字要简洁、直截了当。

m0_66471270的博客 288

一个程序员的自白(危机可导)

导数(英语:Derivative)是微积分学中重要的基础概念。一个函数在某一点的导数描述了这个函数在这一点附近的变化率。导数的本质是通过极限的概念对函数进行局部的线性逼近。或者可以简短地说,导数是用来找到“线性近似”的数学工具。 而微积分基本定理描述了微积分的两个主要运算──“微分”和“积分”之间的关系。其实本质也是一种“分而治之”的思维模式,首先把复杂问题分解(逼近极限),然后把这些分解后问题简...

weixin_43759452的博客 148

算法歧视暴雷:某招聘软件测试员的自白书

《算法偏见:一个软件测试工程师的职业反思》讲述了从业十年的测试工程师李工在AI招聘系统中发现的隐性歧视问题。通过构造性别、年龄等变量相同的测试简历,他发现系统对女性、年长者的评分普遍低8%-15%。深入调查揭示,这种偏见源于历史招聘数据中的结构性失衡,以及算法通过代理变量无意识强化的刻板印象。文章反思了技术人员的伦理责任,呼吁将"算法公平性测试"纳入必备环节,建立分群评估指标和人工监督机制。这不仅是对技术的检验,更是对社会公平的守护,提醒工程师们要成为照亮算法黑箱的"光&quo

2501_94436481的博客 319

随笔:做一个平庸程序员,are you scared?

背景:一个平庸程序员的自白。近期看到的少有的好文,细细品味,感触良多,思来想去不知如何与作者交流。无论从工作经验,还是从境界,都与原作与译作有一段差距。但很多人都会有相似的经历,说出自己的故事,彼此交流或许是最好的途径。题记:编程在外人看来绝对属于脑力劳动,至少从大学教育来看软件工程、计算机专业都是需要很强的理科功底的。然而看看帝都上地、中关村深夜的壮观景象,你又会觉得编程是体力活,要不怎么会被戏称

只要踏出一步,路就在前方——zssure 4371

一个程序员的自白(认同迷失)

在“旁观者”中,他的一句“而不是轻易地活在别人的道理和假象之中”导出了许多现代人的焦虑,就连我这么一个高考语文不及格的平凡人都能在短短的两年内向互联网世界贡献文字10万+,可见这个信息化社会的是如此地波涛汹涌,哪怕缺少一点独立性思考,都无法幸免于“洪灾”之中。从我这个旁观者角度看,他不是一个缺乏思考能力的人,但他还是不能在这场“灾难”中幸免,我想源于他的独立性还不够强大,迷失在追求“信息认同”...

weixin_33939843的博客 123

程序员如何高效地摆脱编程困境

每个人学习编程时都会遇到困难,因此作为程序员,需要学习的最重要的技能之一是如何高效地摆脱困境。下面简要地介绍几种方法,以帮助我们摆脱编程困境。 1 第一步 陷入困境后,首先需要判断形势。我们必须能够明确地回答如下三个问题,才能够从他人那里获得帮助。 ⑴你想要做什么? ⑵你已尝试哪些方式? ⑶结果如何? 对于以上三个问题,答案应尽可能具体。 对于第一个问题,像“我要在我的Window...

www.wangpeng.cn 534
上一篇: UPDATE servercmd SET serverid = 998;
下一篇: 值得学习的C/C++开源项目
shankusu2017
博客等级 码龄15年 155粉丝 155原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值