Java 中的 switch 语句:类型支持与限制 1、switch 语句支持的数据类型2、switch 语句不支持的数据类型3、总结 💖The Begin💖点点关注,收藏不迷路💖 在 Java 中,switch 语句是一种用于多分支选择的控制结构。从 Java 1.0 开始,switch 语句就支持了基本数据类型,而随着时间的推移,Java 不断扩展了 switch 语句的功能,支持了更多的数据类型。下面,我们来详细探讨一下 switch 语句在 Java 中的类型支持与限制。
1、switch 语句支持的数据类型 基本数据类型 char:从 Java 1.0 开始就支持。
byte:从 Java 1.0 开始就支持。
short:从 Java 1.0 开始就支持。由于 short 可以隐式转换为 int,所以实际上 switch 是以 int 的形式来处理 short 类型的值。
int:从 Java 1.0 开始就支持。
包装类 虽然 switch 语句本身不支持包装类(如 Character、Byte、Short、Integer),但我们可以很容易地将这些包装类的对象转换为它们对应的基本数据类型,然后在 switch 语句中使用。
字符串(String) 从 Java 1.7 开始,switch 语句支持了 字符串类型。这使得我们可以根据字符串的不同值来执行不同的代码块,极大地提高了代码的可读性和可维护性。
枚举类型(Enum) 从 JDK 1.
一、Vue 1.什么是vue? 1.JavaScript框架
2.简化Dom操作
3.响应式数据驱动
2.如何使用vue? 官网:介绍 — Vue.js
开发环境版本,包含了有帮助的命令行警告https://unpkg.com/vue@2/dist/vue.js
1.引入Vue文件
2.在body定义一个双标签
3.定义自己的js代码--创建Vue对象--el:把Vue对象挂载到双标签上,data用于定义数据
2.1EL挂载属性作用? Vue实例的作用范围是什么?
Vue会管理el选项命中的元素及内部的后代元素。
是否可以使用其他选择器?
可以使用,但是建议使用ID选择器
是否可以设置其他的dom元素?
可以使用其他双标签,不能使用HTML和Body
2.2data定义vue的数据 语法:
data:{
key:value,
............
}
//(value类型可以是Number、boolean、String、Object、Arrays、underfined)
3.Vue中常用的指令 vue中的属性,这些指令可以使用在dom属性上。可以调用vue中成员。所有的指令都是以v-开始
3.1v-text和v-html--文本值 设置标签的文本值(textContext)
v-html可以解析内容中的标签 ,v-text和{{}}无法解析
3.2v-on/@事件--绑定事件 为元素绑定事件 [onclick ondblclick onblur onfocus onchange onsubmit等]
v-on:触发的是vue对象method属性中方法名
v-on:可以缩写为@
如果方法中调用vue对象中成员必须使用this
3.3v-show和v-if(不)满足条件(隐藏)显示 满足条件显示,不满足隐藏
根据表达值的真假,切换元素的显示和隐藏
v-if:通过删除标签和添加标签来控制标签的显示和隐藏
v-show:通过style样式来控制标签的显示和隐藏display:none。
如果频繁的显示和隐藏使用v-show
3.4v-else和v-else-if判断 3.5v-bind/:绑定标签属性(src,title,class) 设置元素的属性(比如:src,title,class)
v-bind:可以缩写为:
3.6v-for循环指令 根据数据生成列表结构
v-for="(元素变量名,索引) in 数组"
3.7v-model双向绑定表单元素 获取和设置表单元素的值(双向数据绑定)
比如表单元素(input、radio、select)使用,
双向绑定数据,可以快速 获取或设置 表单元素内容
v-model表示双向绑定。表单元素内容改变-vue数据跟着改变。 vue数据变化对应的表单元素的内容跟着变化
<body> <div id="
我是阿星,今天给大家带来是2024年最新TikTok国际版抖音的下载和安装教程,而且还是免root免拔卡的那种,安卓和iOS都能用哦!由于某些原因,国内用户并不能使用TikTok。今天阿星就教一下大家怎么安装TikTok。
TikTok在全球范围内火得一塌糊涂,这是字节跳动给外国朋友们精心准备的国际版抖音,内容多得眼花缭乱,各种文化和地区的都有。
注意:资源下载地址,请到文末,按照提示的关键词获取!
说到TikTok,不得不提直播打赏,这事儿在国外也是火得一塌糊涂。据阿星了解,老外们在直播间刷礼物的热情,一点也不比咱们差,7年刷了100亿美元!这数字,阿星听了都惊呆了。
好了,言归正传,怎么安装TikTok呢?
iOS的小伙伴们,你们真是太幸运了,安装过程简单得跟一加一似的。跟着阿星的教程地址,在线直接安装就行。安装完了,去“设置-通用-设备管理”里信任一下开发者,然后连上工具网络,TikTok就能用了。
安卓用户也别急,先安装TikTok专用工具,再装TikTok本身。装完了,记得先连工具,再点TikTok图标,你就可以开始刷视频了。
说说海外版抖音TikTok。TikTok是一个非常有趣的平台,用户可以在上面观看、分享和创作短视频内容。由于TikTok有着庞大的用户群体和丰富的功能,他的推荐算法真的太厉害了。用户可以轻松地找到自己感兴趣的内容,并与其他用户互动。
TikTok上经常会有一些挑战和趋势,比如舞蹈挑战、模仿挑战等。TikTok的快速增长和高用户黏性,与其发现和提供内容的独特方式密切相关。推荐算法通过充分满足用户的需求来迎合用户:兴趣标签层次结构树、用户画像和数据分区桶策略,可以为用户提供更精准和个性化的内容推荐。
阿星用TikTok也有一段时间了,发现这玩意儿真是个时间黑洞,一刷就停不下来!
不过,也正是因为它的推荐算法,让阿星总能发现一些新鲜有趣的内容,有时候还能找到一些灵感和创意。
阿星想说的是,虽然TikTok很火,但大家也要注意合理安排时间,不要沉迷其中哦!
最新版的软件安装包和相关工具,阿星已经打包在一起,
下载地址: 点击下载
目录
一、用法精讲
39、pandas.DataFrame.to_stata函数
39-1、语法
39-2、参数
39-3、功能
39-4、返回值
39-5、说明
39-6、用法
39-6-1、数据准备
39-6-2、代码示例
39-6-3、结果输出
40、pandas.read_stata函数
40-1、语法
40-2、参数
40-3、功能
40-4、返回值
40-5、说明
40-6、用法
40-6-1、数据准备
40-6-2、代码示例
40-6-3、结果输出 二、推荐阅读
1、Python筑基之旅
2、Python函数之旅
3、Python算法之旅
4、Python魔法之旅
5、博客个人主页
一、用法精讲 39、pandas.DataFrame.to_stata函数 39-1、语法 # 39、pandas.DataFrame.to_stata函数 DataFrame.to_stata(path, *, convert_dates=None, write_index=True, byteorder=None, time_stamp=None, data_label=None, variable_labels=None, version=114, convert_strl=None, compression='infer', storage_options=None, value_labels=None) Export DataFrame object to Stata dta format. Writes the DataFrame to a Stata dataset file. “dta” files contain a Stata dataset. Parameters: pathstr, path object, or buffer String, path object (implementing os.
0202 分段hash表 专栏内容:
postgresql使用入门基础手写数据库toadb并发编程 个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.
文章目录 0202 分段hash表一、概述 二、分段hash并发操作原理 三、分段算法原理 3.1 固定位的分段算法 3.1 不固定位的分段算法 四、hash表操作 hash bucket序号获取 分段hash的定义 hash 查找 五、总结 结尾 一、概述 上节介绍了hashTable的原理与实现,在数据库中,往往是高并发,高性能的要求,对于hashTable的操作,必须加读写锁来保护一致性。
当一个任务要插入一条key-value数据时,其它并发都需要等待,吞吐量明显不足。
本节就来分享一种分段式的hashTable,当hashKey 在不同分段时,可以进行并发的插入和删除操作,这对于高并发来讲,性能就会成倍的提升。
二、分段hash并发操作原理 在并发操作中,会对共享数据加锁保护,了为提升读取数据的并发性能,一般会在读操作时加读锁,写操作时加写锁。
其中:
读读不冲突,可以同时多个任务进行读操作;读写冲突,读时写的任务在等待,写时读的任务会等待;写写冲突,同一把锁上,只能有一个写的任务运行,其它都会等待; 上面锁的冲突规则是对于一把锁来讲,当有多把锁时,各锁之间是相互不干涉的,也就是有几把锁,就可以同时运行几个写任务。
这就是分段hash的理论基础,每个分段会对应的独立的一把段级别的锁,只负责保护此分段的hashtable操作,这样几个分段就可以同进行分段操作了。
分段的hashtable中有多个segment;每个segment相当于一个独立的hashtable;每个segment中有一把并发控制的锁segmentLock;在segment内部用锁进行同步处理。 三、分段算法原理 对于分段的hashtable来讲,分段就非常关键,既要简单高效,又需要算法稳定,同时还要尽可能的分散,看起来要求挺高的,下面我们来看如何设计分段算法。
在hashTable中,散列的主要依据是hashKey,是否继续在hashKey上做文章呢?
答案是肯定的,将hashKey的高bit位定义位segment的序号,低bit位定义位段内的bucket序号;
如图所示,对于64bits的hashKey, 可以将高字节定义位segment 序号,低7字节定义为bucket序号;
这里的划分算法可以是固定位的,也可以是不固定位的。
3.1 固定位的分段算法 固定划分,也就是segment序号对应的bit数量是固定的,比如一个字节,8bits。
此时最大可以表示256个segment,也就是不能超过最大值。当配置的segment小于256时,可以采用 取余的算法,将一个节字的数字散列到此区间内; 固定划分,算法相对简单,当划分的segment不能一一对应时,需要一次映射计算。
3.1 不固定位的分段算法 当segment数量,可以更新数据量进行优化配置时,比如数据量为2GB时,配置16个segment,而数据量为2TB时,有更多的数据会产生冲突,进一步通过增加segment进行分散,可以配置segment为256。
同时又期望划分后的bits可以直接是segment的下标,那么就要计算不同划分下,需要占用多个少bit。
算法描述如下:
segment数量必须是2的幂次,如果配置的不是2的幂次时,取大于此值的2的幂次数;这样保证与bit数量一一对应。计算2的幂次数,也就是 2n ,n的具体值;比如配置为1024个segment,那么它就是210;幂次数n就是segment序号的bit数量,从最高到低位取; 下面来看代码的具体实现。
向上取2的幂次数
对于32位HashKey的算法如下:
HASHKEY getAlignNum(unsigned int num) { HASHKEY mask = num - 1; mask |= mask >> 1; mask |= mask >> 2; mask |= mask >> 4; mask |= mask >> 8; mask |= mask >> 16; return mask+1; } 这是一个很巧妙的算法,通过将该数字二进制中的最高位的1,填充到所有低位的,再加1就变成了最大的2的幂次数。
Django有两种静态文件 static: 静态文件夹,存放CSS,JS,网站的一些图片等静态资源,为Templates下的html页面提供的。static是不会变化的
media:媒体文件夹,存放网站中用户所相关的一些文件,比如说用户的图片,歌曲的资源,封面等一系列资源。media下的文件是变动的,由系统用户等来决定
项目开发中的配置 static 1:在项目的根目录下创建static文件夹
2:在settings.py下进行配置
BASE_DIR = Path(__file__).resolve().parent.parent STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static/'), ) 3:在url中配置 4:在html中使用
{% load static %} # 引入js文件 <script data-main="/static/js/play.js" src="/static/js/require.js" ></script> # 通过{% static %}引入 <img src="{% static "imgs/logo.jpg" %}" alt=""/> mdia 标注:
MEDIA_ROOT:设置用户上传文件的实际保存目录,该文件夹自动创建
MEDIA_URL :代表用户通过URL来访问这个本地地址的URL
1:在项目的根目录下创建media文件夹
2:在settings.py下进行配置
BASE_DIR = Path(__file__).resolve().parent.parent MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 3:在url中配置
4:在html中使用
怎样编写PHP网站
一、什么是编写PHP网站
在开始讨论如何编写PHP网站之前,我们先来理解一下这个“编写”的概念。编写,顾名思义,就是使用某种编程语言,如PHP,来创建和构建网站的过程。但这个过程并非简单的打字和复制粘贴,它涉及到对网站需求的深入理解、对编程语言的熟练掌握,以及对网站架构的精心规划。
当我们谈论编写PHP网站时,我们实际上是在谈论一个复杂的系统工程。这个系统需要处理用户请求、存储和检索数据、展示动态内容,以及与其他系统或服务进行交互。而PHP,作为一种流行的服务器端脚本语言,为我们提供了实现这些功能的强大工具。
二、为什么要编写PHP网站
那么,为什么我们要选择使用PHP来编写网站呢?这背后有着多方面的原因。
可以这么认为PHP具有广泛的应用基础和成熟的生态系统。许多知名的网站和应用程序都使用PHP作为其后端开发语言,如WordPress、Facebook等。这意味着,当你使用PHP编写网站时,你可以轻松地找到各种成熟的解决方案和插件,帮助你快速实现所需功能。
考虑到这种影响,PHP具有良好的跨平台性和可扩展性。无论是在Windows、Linux还是Mac OS上,PHP都可以稳定运行。你知道的PHP还支持与多种数据库进行交互,如MySQL、PostgreSQL等,这使得你可以根据实际需求选择合适的数据库系统。
如果按照这个逻辑来看的话,PHP还具有良好的学习曲线和丰富的文档资源。对于初学者来说,PHP的语法相对简单易懂,而且有许多优秀的教程和文档可供参考。这使得你可以更快地掌握PHP编程技能,并将其应用于实际项目中。
三、怎样编写PHP网站
既然我们已经了解了什么是编写PHP网站以及为什么要使用PHP来编写网站,那么接下来就让我们来探讨一下具体的编写过程。
1. 需求分析
在开始编写PHP网站之前,首先需要进行详细的需求分析。这包括了解网站的目标用户、功能需求、性能要求等方面。只有充分理解了用户需求,我们才能为网站设计出合理的架构和功能模块。
2. 设计网站架构
在需求分析的基础上,我们需要设计网站的整体架构。这包括确定网站的前后端分离方式、数据库设计、API接口设计等方面。一个良好的网站架构可以确保网站的稳定性和可扩展性,为后续的开发和维护提供便利。
3. 编写PHP代码
在确定了网站架构之后,我们就可以开始编写PHP代码了。这包括实现用户注册登录、数据查询、页面渲染等功能。在编写代码时,我们需要注意代码的规范性和可维护性,确保代码的可读性和可重用性。
4. 调试与测试
编写完PHP代码之后,我们需要进行多次的调试和测试。这包括检查代码的逻辑是否正确、功能是否完善、性能是否达标等方面。通过模拟用户行为和使用自动化测试工具,我们可以发现潜在的问题和错误,并及时进行修复和优化。
5. 上线与维护
当网站经过多次测试并确认无误后,我们就可以将其上线运行了。上线后,我们还需要对网站进行定期的维护和更新,确保网站的安全性和稳定性。你知道的我们还需要根据用户反馈和业务需求的变化,及时对网站进行功能扩展和优化。
这就意味着,编写PHP网站是一个复杂而有趣的过程。通过合理的需求分析、设计网站架构、编写PHP代码、调试与测试以及上线与维护等步骤,我们可以创建出一个功能完善、性能稳定且易于维护的PHP网站。
目录
1. 问题背景和描述
1.1 问题背景
1.2 问题描述
2. 数学模型的建立
2.1决策变量
2.2 目标函数
2.3 约束条件
2.4 数学模型总结
3. 使用Python解决线性规划问题
3.1 导入必要的库
3.2 定义目标函数系数
3.3 定义不等式约束矩阵和向量
3.4 定义变量的边界
非负约束
变量边界在SciPy中的表示
3.5 求解线性规划问题
调用linprog函数
3.6 输出结果
获取和解释最优解
4. 结果解释和应用
4.1 结果解释
4.2 应用
4.3 验证结果
5. 扩展阅读
5.1 扩展阅读
5.2 线性规划的其他类型
编辑
代码
结果
总结
专栏:数学建模学习笔记
1. 问题背景和描述 1.1 问题背景 在现代制造业和商业运作中,资源的有效利用和利润的最大化是企业追求的重要目标。企业面临的常见问题是如何在有限的资源条件下,通过合理分配和优化使用资源,来实现利润的最大化。线性规划(Linear Programming,LP)是一种数学优化技术,能够在这些情况下发挥重要作用。它通过建立数学模型,帮助企业在众多可能的选择中找到最优解,进而指导实际操作。
假设有一家工厂,生产两种产品:产品A和产品B。每种产品的生产都需要消耗特定的资源。每天,每种资源的使用时间是有限的,这使得资源分配问题变得复杂。工厂的目标是通过合理分配资源,确定每天应该生产多少单位的产品A和产品B,以实现总利润的最大化。
具体数据如下:
资源1:每天最多可用60个小时资源2:每天最多可用40个小时产品A:每单位需要资源1的2个小时和资源2的1个小时产品B:每单位需要资源1的1个小时和资源2的2个小时产品A:每单位的利润为30美元产品B:每单位的利润为20美元 通过对这些数据进行分析和建模,我们可以利用线性规划技术来制定一个优化的生产计划,确保在资源限制条件下实现利润的最大化。
1.2 问题描述 我们需要建立一个线性规划模型来描述上述问题,并使用该模型找到每天应该生产的产品A和产品B的最优数量,从而实现总利润的最大化。同时,生产过程中必须满足资源的限制条件,即不能超过每天可用的资源时间。
在这个问题中,我们的目标是构建一个数学模型,通过这个模型可以:
确定每天生产的产品A和产品B的数量。满足资源的限制条件。实现总利润的最大化。 2. 数学模型的建立 建立数学模型是解决线性规划问题的基础。我们将根据问题背景中的具体数据,定义决策变量,构建目标函数和约束条件。
一 拷贝构造函数的概念: 拷贝构造函数是一种特殊的构造函数,用于创建一个对象是另一个对象的副本。当需要用一个已存在的对象来初始化一个新对象时,或者将对象传递给函数或从函数返回对象时,会调用拷贝构造函数。
二 拷贝构造函数的特点: 1:拷贝构造函数是构造函数的一个重载形式。
2:拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错, 因为会引发无穷递归调用。
3:若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按 字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
注意:在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定 义类型是调用其拷贝构造函数完成拷贝的。
4:编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗? 当然像日期类这样的类是没必要的。
2.1 代码示例: class Time { public: // 普通构造函数 Time(int hour = 0, int minute = 0, int second = 0) { _hour = hour; _minute = minute; _second = second; } // 拷贝构造函数,使用引用传递 Time(const Time& other) { _hour = other._hour; _minute = other._minute; _second = other._second; } void Print() const { std::cout << _hour << "
移除链表元素 题目连接:
https://leetcode.cn/problems/remove-linked-list-elements/description/
使用双指针法,开始时,一个指针指向头节点,另一个指针指向头节点的下一个结点,然后开始遍历链表删除结点。
这里要注意如果是空链表的话,使用双指针第二个指针会发生空指针异常,所以要判断一下
最后程序运行到最后,我们还差头节点没有判断,最后加上即可。
class Solution { public ListNode removeElements(ListNode head, int val) { if(head == null) { return head; } ListNode prev = head; ListNode cur = head.next; while(cur != null) { if(cur.val == val) { prev.next = cur.next; } else { prev = cur; } cur = cur.next; } if(head.val == val) { head = head.next; } return head; } } 反转链表 题目连接:
https://leetcode.cn/problems/reverse-linked-list/description/
我们还是使用双指针,不过这次有一个指针就是头指针,因为反转链表之后的头指针会发生改变,那还不如直接让头指针一起移动,先将另一个指针指向头指针的下一个结点,然后开始遍历链表,把每一个结点的指针指向的对象变为前面的对象。
引言
在大数据时代,信息就是力量。对于企业而言,掌握行业动态、竞品分析、市场趋势等关键数据,是决策制定的重要依据。然而,手动收集这些信息既费时又低效。因此,自动化数据采集变得至关重要。本文将向你展示如何使用Python技术栈(Scrapy、Django、Celery、Elasticsearch)搭建一个高可用的企业级爬虫管理平台。
一、需求分析与架构设计
在开始之前,我们先明确平台需要满足的核心功能:
爬虫任务管理:创建、编辑、删除爬虫任务。动态调度:根据需求调整爬虫执行频率。数据处理:清洗、解析、存储爬取的数据。监控与报警:实时监控爬虫状态,异常自动报警。数据检索与分析:提供高效的数据查询与分析接口。 二、技术选型
Scrapy:强大的爬虫框架,用于数据抓取。Django:构建管理界面和API服务。Celery:异步任务队列,处理爬虫任务。RabbitMQ:消息中间件,传递任务指令。PostgreSQL:关系型数据库,存储元数据。Elasticsearch:全文搜索引擎,存储与检索数据。Nginx:反向代理服务器,提高安全性与负载均衡。 三、平台构建步骤
1. 环境搭建 首先,使用virtualenv创建虚拟环境并安装依赖:
virtualenv venv source venv/bin/activate pip install scrapy django celery rabbitmq-server elasticsearch psycopg2-binary 2. 开发Scrapy爬虫 在scrapy_project中,定义爬虫:
import scrapy class ProductSpider(scrapy.Spider): name = 'product' start_urls = ['http://example.com/products'] def parse(self, response): for product in response.css('div.product'): yield { 'name': product.css('h1::text').get(), 'price': product.css('span.price::text').get(), } 3. Django管理界面 创建Django应用,实现用户认证、爬虫任务管理界面:
# models.py from django.db import models class SpiderTask(models.Model): name = models.CharField(max_length=255) url = models.URLField() schedule = models.
乐观学习,乐观生活,才能不断前进啊!!!
我的主页:optimistic_chen
我的专栏:c语言
欢迎大家访问~
创作不易,大佬们点赞鼓励下吧~
前言 无论c语言还是java数组都是重中之重,今天我们来学习java数组,看他与C语言中有几分不同。
文章目录 前言数组的创建初始化数组的使用数组的本质数组应用参数传基本数据类型参数传输组类型(引用数据类型) 引用变量完结 数组的创建 Type[ ] 数组名=new Type[N]
例如:
int[] array=new int[10]; double[] array2=new double[10]; String[] array3=new String[10]; 初始化 动态初始化:在创建数组时,直接指定数组中元素的个数
int[] array=new int[10]; 静态初始化:在创建数组时不直接指定数据元素的个数,而直接将具体的数据内容进行指定
Type[] 数组名={data1,data2,...,datan}; int[] array={1,2,3,4,6}; 注意:
·静态初始化虽然没有指定数组的长度,编译器在编译时会根据{}中元素个数来确定数组的长度。
·静态初始化时, {}中数据类型必须与[]前数据类型一致。
·静态初始化可以简写,省去后面的new Type[ ]。
·如果没有对数组初始化,数组中元素为默认值。
·如果·数组中储存元素的类型为引用类型,默认值为NULL
类型默认值byte0short0int0long0float0.0fdouble0.0char0booleanfalse 数组的使用 因为在C语言中我们接触过数组,所以对于基本的数组访问和遍历我们不再说明,相信大家都了解过很多。我们直接从两者不同的地方开始说起。
C语言中求数组长度时使用sizeof关键词,但是在Java中数组长度可以通过数组对象.length来获取
int[]array = new int[]{10, 20, 30, 40, 50}; for(int i = 0; i < array.length; i++){ System.out.println(array[i]); } 当然,遍历数组也有一个新方式,for-each循环,语法格式如下:
for(数据类型 变量:集合名称){
什么是String Rust的核心语言中只有一个String类型,那就是String slice,str通常被当作是&str的借用。String类型是通过标准库提供的,而不是直接编码到核心语言中,它是一个可增长的、可变的、utf-8编码的类型。str和String都是utf-8编码的。 创建新的String String实际上是通过包装bytes类型的vector实现的。使用new方法创建String:let mut s = String::new()使用to_string方法创建String:let data = "initial contents"; let s = data.to_string(); let s = "initial contents".to_string(); 使用String::from方法创建字符串,let s = String::from("initial contents"). 更新String 使用push_str和push追加字符串 let mut s = String::from("foo"); s.push_str("bar"); // s is foobar push_str方法不会改变字符串的所有权
let mut s = String::from("lo"); s.push('l'); // s is lol 使用+操作符或者 format!宏连接字符串 let s1 = String::from("Hello, "); let s2 = String::from("world!"); let s3 = s1 + &s2; // note s1 has been moved here and can no longer be used let s1 = String::from("
建造者模式是一种创建型设计模式, 旨在将复杂对象的构建过程与其表示分离, 使同样的构建过程可以构建不同的表示. 建造者模式主要用于以下情况:
需要创建的对象非常复杂: 这个对象由多个部分组成, 且这些部分需要一步步地构建不同的表示: 通过相同的构建过程可以生成不同的表示构建过程的控制: 希望能够有更多的控制, 逐步创建对象, 而不是在一个步骤中完成 建造者模式结构 抽象建造者: 定义了创建产品的各部件的抽象接口具体建造者: 实现了建造者接口, 构建并装配各个部件, 最终生成具体的产品产品: 具体要创建的复杂对象指挥者: 负责安排已有模块的顺序构建一个复杂的对象 建造者模式实现 // 产品类 public class Product { private String partA; private String partB; private String partC; public void setPartA(String partA) { this.partA = partA; } public void setPartB(String partB) { this.partB = partB; } public void setPartC(String partC) { this.partC = partC; } @Override public String toString() { return "Product [partA="
这篇文章来自华为的渥太华无线先进系统能力中心和无线技术实验室,作者中有大名鼎鼎的童文。
一、自编码架构的全局收发机面临的主要问题 文章对我比较有启发的地方,是提到自编码架构的全局收发机面临的主要问题:
问题一:基于随机梯度下降法,使用反向传播算法训练自编码器,需要一个或多个可微信道模型层,用于连接发射机的深度神经层和接收机的深度神经层。由于真实信道必须包含很多非线性分量(如数字或模拟的预失真与转换),又涉及上采样、下采样等不可微阶段,因此收发机深度神经层训练出来的模型是基于构造的信道而非真实信道。在真实信道场景下,这样得到的模型可能会在推理阶段带来性能损失。
问题二:所有隐藏层或中间层均根据输入信号的后验概率进行训练。在自编码器全局收发机中,接收机深度神经层的第一层是一个中间层,该中间层的输入信号易受当前信道失真的影响。这种影响会不可避免地渗透到接收机的所有深度神经层。如果信道变化的程度大到超出了训练期望,会导致接收机在推理阶段失效。
问题三:神经层之间缺乏可解释性,无法获知哪些神经元以及神经层之间的哪些连接会有效影响最终的学习准确度。 Goodfellow等人举了一个深度神经网络分类器的例子,虽然该分类器通过非噪声图像完成了良好的训练,但仍可能将带噪声的熊猫图像误判为长臂猿。这个例子表明,基于深度神经网络的分类器进行最终决策时,很大程度上依赖于一些“关键路径”(指熊猫图像中的部分像素,也称为“局部特征”)。如果关键路径完好无损,就能做出正确的分类;如果关键路径受到干扰,则会做出错误的分类。同时,这种由噪声导致的分类误判,只是在存在加性随机噪声的前提下出现的偶发情况,这表明深度神经网络依赖于这样一种假设——即 “关键路径”经过噪声信道处理后仍然保持完好。深度神经网络易受加性随机噪声的影响,这对它在无线收发机设计中的应用几乎是致命打击。
这三个问题的本质可以归结为同一个核心问题,即面临无线信道的随机变化时,深度神经网络的泛化性能太差。没有任何模型(即便是十分优越的信道模型)能够完全捕获无线电传播的所有可能场景,因此分布外(Out-of-Distribution, OOD)样本或离群点的处理是自编码器始终要面对的现实问题。
更糟糕的是,针对这些问题的现有解决方案还面临许多阻碍,因为所提出的解决方案必须满足无线通信设备和基础设施的低能耗、低时延、低开销等实际要求。一方面,在动态环境中,自编码器收发机对自身进行累加、增强以及重训练的成本过高;另一方面,进行累加、增强和重训练的整个过程本身也违反了深度神经网络的“Once-for-All”策略——即一次学习、长期有效,进而无法很好地满足现实需要和能耗要求。
在无线场景中,离群点通常由信道的随机变化引起。在推理阶段,如果信道正在发生变化,偏离了训练阶段所使用的信道模型,这时离群点的问题表现得尤为突出。随着推理的进行,会出现更多的离群点,进而影响到接收信号的分布形状, Bengio就将深度学习泛化性能差的原因归咎于这一点。目前有一些补救方法,比如进行额外的训练,包括迁移训练、基于注意力的循环网络,或强化学习。然而,面对未来无线通信低能耗、低时延和低控制开销的要求,这些补救方法变得不切实际,缺乏可行性。
对于文章提出的MPA方法,文章也分析解决思路,重点是下面我标黑的部分:
“首先,为实现可微性,需要简化信道模型,但这种简化会损害自编码器收发机的性能。造成性能损害的原因在于,用来训练自编码器的信道模型是一种简化模型,而非真实模型。也就是说,训练阶段使用的简化信道模型与推理阶段处理的真实信道之间存在偏移,这种偏移带来了性能损失。如果偏移量增加到超出期望的程度,整个自编码器收发机将会失效。有两种补救方法可以缓解这种性能下降。第一种是利用强化学习,不间断地记录信道状态,并对策略DNN和(或)评估 DNN进行持续训练。不过,从维度的复杂程度上讲,强化学习对无线系统来说过于复杂,因为强化学习处理的维度实际上比AlphaGo围棋还要大得多。因此,基于强化学习的调整机制并不可行。第二种是利用生成对抗网络(Generative Adversary Network,GAN),将尽可能多的信道场景学习到一个大的深度神经网络模型中。然而,这是一种经验方法,无法证明该方法能够涵盖所有信道场景。
出于对上述问题的考虑,带MPA的自编码器采取不同的技术路径。在推理阶段,MPA会针对每次数据传输,调整当前信道测量函数中的降维层系数,因此自适应推理会在训练阶段使用一个粗信道模型,我们称之为“粗学习”。如果粗学习对训练和推理两个阶段模拟了相同或相似的信道模型,则很难证明粗学习的优势,不过这种优势可以在实际的现场测试中得到证明。
其次,带MPA的自编码器可以与基于生成对抗网络的信道模型联合工作。从经验来讲,大部分信道的实际条件依赖于用户位置和环境拓扑,比如高层建筑、山丘、道路等。参考文献提出利用条件生成对抗网络,对未知信道建模,并获得了良好的性能。我们可以利用该方法建立一个信道模型,为训练阶段提供良好的支持。
在推理阶段,我们建议依靠导频的信道估计、信道测量反馈或信道互易来获得最新的信道条件。众所周知,MPA还受益于稀疏性,能够较好地容忍偏置与偏移(这也是LDPC解码器可以有效工作的原因)。从这一角度来看,没有必要进行全维信道测量,只需测量部分维度,即使存在一定的估计误差,我们的方案在整体性能上仍具备较好的鲁棒性。另外,残差可以通过误差容忍度较高的接收深度神经层得到处理。由于在推理和训练阶段已经做好了降维层的调整,我们可以将降维层作为整个传输链的预编码器,因而不必在接收深度神经层再做训练。这样不但带来节能效益,而且对延长用户设备的电池寿命也是一种巨大的优势。”
二、文章速读 其实,对文章提出的方法,我个人还是持一种怀疑态度。来简单看看文章的方法。
文章摘要 文章提出了一种基于消息传递算法(Message Passing Algorithm, MPA)的自编码器收发机,以解决传统自编码器在处理随机信道变化时泛化性能较差的问题。作者通过在自编码器中引入MPA,实现了一种灵活的收发机,能够在不同使用场景下提供较好的泛化性能。该方法允许在训练阶段进行粗学习,并在推理阶段实现自适应推理。
解决的主要问题 泛化性能问题:传统自编码器收发机在面对随机信道变化时,由于神经元一旦训练完成就固定,导致泛化性能较差。模型与真实信道的偏差:使用基于随机梯度下降法和反向传播算法训练的自编码器,依赖于构造的信道模型而非真实信道,可能导致推理阶段性能损失。信道变化的适应性问题:自编码器全局收发机在信道变化超出训练期望时,可能导致接收机失效。分布外样本处理:无线信道的随机变化导致分布外样本或离群点问题,现有解决方案难以满足无线通信设备的低能耗、低时延、低开销要求。 主要方法 消息传递算法(MPA):引入MPA功能,通过预编码器层实现自适应调整,提升收发机在信道动态变化时的泛化性能。降维层:将降维层插入自编码器框架中,进行线性降维转换,并通过MPA对降维层系数进行迭代调整。独立式MPA迭代:采用前向迭代(类似非线性支持向量机)和反向迭代(类似注意力深度神经网络)来独立调整降维层,不依赖于原始自编码器的反向传播。全局串联学习:通过串联训练方案,分别训练降维层和深度神经层,实现粗学习和自适应推理。粗学习与自适应推理:在训练阶段使用简化信道模型进行粗学习,而在推理阶段通过MPA调整降维层以适应当前信道测量情况。 通过这些方法,文章旨在提高自编码器收发机在随机信道变化条件下的性能和泛化能力。
对于文章的MPA方法,看图16和17可以了解大概。
主要是加入了MPA层,完成了发射向量到信道之间的一个维度变换,然后训练的时候先冻结MPA层,完成整体收发的训练后,再迭代训练MPA层。MPA层可以看作是发射的一个预编码映射,具体的维度可以通过对信道的测量获得,这里还是对信道采取了常见的多径假设。MPA层的训练,是依靠接收信号和发射向量之间的注意力。注意力深度神经网络是测量不同维度间两个特征相似度的一种有效方法。应当注意,注意力的数量小于接收信号的数量,即L < N。注意力深度神经网络可以用于降维层的反向传播。
上图显示了带MPA层与传统方式的差异,MPA层可以实现在线学习,而接收信号可以通过信道互易性获得。
Leetcode146 LRU缓存 经典题,典型compund data structure思想
link
思路:
主要思想就是hash table + double-linked list重点就是手动实现这些功能因为get和put都要求 O ( 1 ) O(1) O(1)时间内实现,所以就是要用hash table而要实现LRU,所以用双向链表维护最近使用 ps: code 多打几遍就熟悉了
class Node { public: int key; int value; Node *last, *next; Node(int k = 0, int val = 0) : key(k), value(val), last(nullptr), next(nullptr) {} }; class LRUCache { private: unordered_map<int, Node*> cache; int size; int capacity; Node *head; Node *tail; void addNode(Node *node) { node->next = head->next; head->next->last = node; node->last = head; head->next = node; } void deleteNode(Node *node) { node->last->next = node->next; node->next->last = node->last; } void move(Node *node) { deleteNode(node); addNode(node); } Node *deleteTail() { Node *node = tail->last; deleteNode(node); return node; } public: LRUCache(int capacity) : capacity(capacity), size(0) { head = new Node(); tail = new Node(); head->next = tail; tail->last = head; } int get(int key) { if (cache.
文章目录 a+=1 和a = a+1的区别一、实例代码二、代码解释三、总结 a+=1 和a = a+1的区别 一、实例代码 public class Test { public static void main(String[] args) { byte a = 10; // a = a + 1; // a = (byte) (a + 1); a += 1; System.out.println(a); } } 上面的对变量a进行加一操作时,使用了不同的方法
二、代码解释 对于注释的两行,第一行是错误的方法,因为在java中进行运算的时候默认使用的是int类型,并且在java中高精度向低精度转化的时候需要声明,因此第二行注释是正确的。
对于+=而言,不用注重类型转化
三、总结 综上所述,+=不用管类型转化,=需要注重类型转化
字符串 1.字符串长度 给定一行长度不超过 100 的非空字符串,请你求出它的具体长度。
输入格式 输入一行,表示一个字符串。注意字符串中可能包含空格。
输出格式 输出一个整数,表示它的长度。
数据范围 1≤字符串长度≤100
字符串末尾无回车
输入样例: I love Beijing. 输出样例: 15 参考代码:
//fgets在读取的时候也会帮我们把回车('\n)读进来。 #include <iostream> #include <cstdio> using namespace std; int main() { char str[101]; //fgets(字符串名,最大读取的长度+1,stdin(固定必备的)); fgets(str,101,stdin);//读取长度最多为100可包含空格的字符串。 int count=0; //for()的第二句:字符串str第i个有效且不等于回车。 for(int i=0;str[i]&&str[i]!='\n';i++) { count++; } cout<<count<<endl; return 0; } 2.字符串中的数字个数 输入一行字符,长度不超过 100,请你统计一下其中的数字字符的个数。
输入格式 输入一行字符。注意其中可能包含空格。
输出格式 输出一个整数,表示数字字符的个数。
输入样例: I am 18 years old this year. 输出样例: 2 参考代码:
#include <iostream> #include <cstdio> using namespace std; int main() { char s1[101]; fgets(s1,101,stdin); int c=0; for(int i=0;s1[i]&&s1[i]!
目录
前言
一、两种不同的数据库设计
1、状态字段存储JSON
2、使用位运算
二、数据库中的位运算实践
1、MySQL中的位运算实践
2、PostgreSQL中位运算实践
三、总结
前言 最近在解决某用户的一个业务需求时,遇到一个很有意思的场景。首先先跟大家分享一下需求背景。用户主要是面向一线的企业工厂,在他们实际生产过程中,为了保障安全生产。由于在车间中,所有的设备和机器都是全天运行,因此特别容易出现运行故障。因此,安全管理部门呢就结合生产时间,将组织专门的人员在上班时间内实现对运行设备的一个巡视,每个班组上班时间为8小时,同时要求每4个小时就要对设备进行一次巡查。根据上班时间分为早班、中班、晚班,每个班由1到多个人员组成。要求在他们上班后的一个小时内和快下班的一个小时内实现对目标设备的巡视,系统需要记录每次的检查记录,比如早班第一次和早班第二次等等。同时呢,在生产高峰期,由于订单的增加,有的机器运行更加频繁,因此要求加大巡视力度,巡视次数增加至四次,即两个小时巡视一次。同样要求系统记录不同次数的状态,一天巡查结束后,系统自动提供巡视结果,能反应出应巡的次数和漏巡的次数,工厂的管理班组将根据情况对相应的车间和安全管理人员进行考核和评价,纳入到月的的绩效考核当中,对于提早发现的故障信息,处置得当的给予奖励和奖金。
以上就是大致的需求,其实刚开始拿到这个需求的时候,对于状态的记录到底用什么字段来存储,如何能达到快速保存状态和检索。比如可以快速的设置第一次和第二次的巡视状态为已完成。同时在查询时能快速查询第N次是否已完成等等操作。在实际业务中可有哪些选择来支持以上的需求,既能满足业务需求,也能较少技术的复杂度。
这就是本文的理由,本文以一个实际的工厂日常检查工作的状态标记场景为例,首先讲解可以有哪些技术方案来实现上述需求,然后讲解表结构的设计,其次着重介绍位运算的表设计方式,以及位运算的处理方式,最后以MySQL和PostgreSQL为例介绍如何在这两个数据库中实现位运算,通过实际例子的讲解,让朋友理解位运算在数据库状态位的场景中的具体使用。通过本文,您可以掌握在面对状态标记时的数据库设计方法,如何在位运算中体现多次,如何操作位运算来设置值,以及如何快速查询定位等知识。
一、两种不同的数据库设计 本节将根据拿到的用户初步需求,对需求进行分析,根据分析结果完成数据库的设计,同时具体阐述如何去进行表状态字段的更新和查询操作。设计没有好坏,根据不同的场景,有不同的应用。这里欢迎各位朋友进行讨论。由于在实际情况下,在上面的巡视工作中,根据不同的工作需求,每个组的巡视次数可能不固定的,所以这里要考虑实现次数的动态标记的需求。
1、状态字段存储JSON 之所以考虑使用JSON的方式来进行存储,第一个考虑就是实现灵活的状态,如果是固定的次数,比如每个班就巡视两次,那么我们不妨设计出多个字段,比如早班第一次状态,早班第二次状态,一直到早班第N次,如果N有限,我们的字段尚且还可以设计出来,如果N是一个不固定的值,那么这种设计也是一种灾难。这里我想可能有朋友会说,多设计一些冗余字段是否可行,比如一次性设计8个字段出来。诚然,这种方案是没有大毛病,但是你想想这些问题,万一超了怎么办,还有就是一个班组8个字段,3个班组就是24个字段,光用来标记状态的字典就有24个,再加上其它的业务字段,这就是25+了,如此设计不仅浪费,同时查询性能也低,扩展性也不好。
这个方式的改良办法就是将多字段改成JSON,通过JSON的存储来实现动态的次数,比如{“1”:0,“0”:1}用这样的字符串表示第一次已完成,第二次未完成。然后在查询的时候每次只需要进行json的关联查询即可,性能暂时还在可以接受的范围之内。你可以想想使用JSON存储值究竟有什么问题。
2、使用位运算 其实在上面一节中已经大体讲了一下,在我们的业务中,我们只要顺序的记录每一次任务的执行状态,比如用0表示未完成,1表示已完成。0和1是二进制中最简单的表示,应用到应用程序中也是,使用他们来进行数据查询和检索,速度也是非常快的。而且也能实现动态的效果。比如,我们设计一个8位的二进制数,如下所示:
第8位第7位第6位第5位第4位第3位第2位第1位00000000 在上面的二进制数表示中,我们采用8位(可以根据实际情况增加长度)来表示对应次数的状态位,第一位表示第一次的状态,0表示未完成。在设计字段时,我们会将状态只设计成一个字段,它的值则有这8位二进制数转成对应的十进制数来表示,这样子不仅大大的减少了字段数,同时还能实现不同次数的状态分别记录。下面举个例子:
第一次巡视已完成的二进制表示如下:
第8位第7位第6位第5位第4位第3位第2位第1位00000001 这里的第一位表示第一次为1,其它的仍为0,这是计算出来的二进制值是1。下面再来举一个例子,我们将第二次和第四次的状态设置为1,则8位的二进制表示如下:
第8位第7位第6位第5位第4位第3位第2位第1位00001010 此时,00001010这个数字换算成十进制的值为10,也就是十进制10表示二进制的00001010,表示该班组的第4次和第2次的巡视工作已完成,其它次数尚未完成。通过以上例子的讲解,您是否发现,使用位运算是否极大的简化了相关的数据库设计,也降低了数据的数据更新和检索的难度。因此我们在此情况下决定采用位运算的方式进行对应工作状态的标记。
二、数据库中的位运算实践 前一节详细的介绍了我们选择的两种方案,也重点比较了两种方案的不同,优缺点也都进行了说明。当然,以上两种方案都可以实现业务需求,也能实现动态灵活的方案,但是相比于复杂度,我们选择位运算来实现。
本节将结合MySQL和PostgreSQL数据库来分别详细讲解如何在这两个数据库中实现位运算,如何在这两个数据库中设置位运算结果和查询位状态。通过本节大家可以了解在MySQL和PostgreSQL数据库中熟练的进行位运算的操作。
1、MySQL中的位运算实践 这里使用的MySQL的版本是5.7.14-x的版本,位运算是基础的计算,在更高级的版本中应该都是兼容的。本博客使用MySQL 5.7来做实验环境。
查询MySQL版本,使用以下sql:
select VERSION(); 5.7.14-log 我们首先来创建一张表,表仅用作演示,不代表实际的业务,实际的业务表还请各位朋友自己去设计。主要体现的位运算的处理过程,表的物理结构如下所示:
CREATE TABLE `example_table` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `status` INT NOT NULL DEFAULT 0 ); 表结构非常简单,只有两个字段,第一个字段是主键ID,设置位自增,而第二个字段为状态位,存储的值是十进制的表示数,请注意,这里的数据类型请结合具体的二进制状态位的计算过来定,int是一个非常大的数字了,用来存储是足够了,它的默认值用0表示,因为二进制8个0对应的十进制数也是0。
首先我们查询一下表的数据,默认情况下,表里是没有数据的,需要我们手动插入数据,插入数据后的表数据如下:
select * from example_table; idstatus10203040506070 下面我们来修改表记录的值,比如我们设置id为3的数据,第一次为1即标记已完成。sql语句如下:
-- 设置第N次为已完成 正确的做法 UPDATE example_table SET status = status | (1 << (N - 1)) WHERE id = 3; -- N表示具体的次数,即N=1 UPDATE example_table SET status = status | (1 << (1 - 1)) WHERE id = 3; 在数据库客户端执行以下sql之后,客户端返回如下:
目录 一、题目二、解法完整代码 一、题目 给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律。
这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。
示例1:
输入: pattern = “abba”, s = “dog cat cat dog”
输出: true
示例 2:
输入:pattern = “abba”, s = “dog cat cat fish”
输出: false
示例 3:
输入: pattern = “aaaa”, s = “dog cat cat dog”
输出: false
提示:
1 <= pattern.length <= 300
pattern 只包含小写英文字母
1 <= s.length <= 3000