线性代数矩阵转置乘法_单位矩阵转置属性| 使用Python的线性代数

线性代数矩阵转置乘法 Prerequisites: 先决条件: Defining a matrix 定义矩阵 Identity matrix 身份矩阵 Transpose matrix 转置矩阵 In linear algebra, the identity matrix, of size n is the n × n square matrix with ones on the main diagonal and zeros elsewhere. It is denoted by I. Also known as the unit matrix because its determinant value is 1 irrespective of size. This is the key feature of an Identity matrix and it plays an important role in Linear Algebra.

解决方法:Invalid mime type “properties;charset=UTF-8“: does not contain ‘/‘

报错如下: 16:09:36.221 [http-nio-8080-exec-1] ERROR c.k.f.w.e.GlobalExceptionHandler - [handleException,83] - Invalid mime type "properties;charset=UTF-8": does not contain '/' org.springframework.http.InvalidMediaTypeException: Invalid mime type "properties;charset=UTF-8": does not contain '/' at org.springframework.http.MediaType.parseMediaType(MediaType.java:534) at org.springframework.http.HttpHeaders.getContentType(HttpHeaders.java:924) at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:219) at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:180) at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:82) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:119) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908) at javax.servlet.http.HttpServlet.service(HttpServlet.java:660) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101) at org.

关联规则常用算法

关联规则(Association Rules)是海量数据挖掘(Mining Massive Datasets,MMDs)非常经典的任务,其主要目标是试图从一系列事务集中挖掘出频繁项以及对应的关联规则。关联规则来自于一个家喻户晓的“啤酒与尿布”的故事,本文通过故事来引出关联规则的方法。 啤酒与尿布的故事 在一家超市里,有一个有趣的现象:尿布和啤酒赫然摆在一起出售。但是这个奇怪的举措却使尿布和啤酒的销量双双增加了。这不是一个笑话,而是发生在美国沃尔玛连锁店超市的真实案例,并一直为商家所津津乐道。沃尔玛拥有世界上最大的数据仓库系统,为了能够准确了解顾客在其门店的购买习惯,沃尔玛对其顾客的购物行为进行购物篮分析,想知道顾客经常一起购买的商品有哪些。沃尔玛数据仓库里集中了其各门店的详细原始交易数据。在这些原始交易数据的基础上,沃尔玛利用数据挖掘方法对这些数据进行分析和挖掘。一个意外的发现是:"跟尿布一起购买最多的商品竟是啤酒!经过大量实际调查和分析,揭示了一个隐藏在"尿布与啤酒"背后的美国人的一种行为模式:在美国,一些年轻的父亲下班后经常要到超市去买婴儿尿布,而他们中有30%~40%的人同时也为自己买一些啤酒。产生这一现象的原因是:美国的太太们常叮嘱她们的丈夫下班后为小孩买尿布,而丈夫们在买尿布后又随手带回了他们喜欢的啤酒。 关联规则是一种大数据挖掘的任务,最初的动机是针对购物篮分析(Market Basket Analysis)问题提出的,例如上述的“啤酒与尿布”的故事,如果超市能够发现一些具有相关联的商品购物行为,通过对商品的适当调整可以提高顾客的购物体验,提升超市的销售额,因此如何发现这些潜在的规律呢? 本文首先介绍关联规则的任务,以及相关概念,其次介绍相关算法,目录索引如下: 本文目录 1、关联规则形式化描述2、Apriori算法3、PCY算法4、多阶段算法5、多哈希算法6、FP-Tree算法7、XFP-Tree算法8、GPApriori算法 1、关联规则形式化描述 设 I = { I 1 , I 2 , . . . , I m } I=\{I_1,I_2,...,I_m\} I={I1​,I2​,...,Im​}是一个项集(Item Set), m m m为项的个数,其中 I i I_i Ii​表示第 i i i个项,对应于一个个商品。事务(Transaction) t i t_i ti​表示 I I I的一个子集,对应于一个个订单。事务组成的集合记做 D = { t 1 , t 2 , . . . , t n } D=\{t_1,t_2,...,t_n\} D={t1​,t2​,...,tn​},通常也称作事务数据库。通常描述中,每一个事务都有唯一的编号,记做TID,每个事务中都包含若干个项Items。 关联规则是形如 X → Y X→Y X→Y的蕴涵式,其中, X X X和 Y Y Y分别称为关联规则的先导(antecedent或left-hand-side, LHS)和后继(consequent或right-hand-side, RHS) 。其中,关联规则 X Y XY XY,存在支持度和置信度,定义如下:

Android 编译错误undefined symbol分析与解决

​ 最近在Android Q上写一个bin文件时遇到编译报错的问题,具体报错如下: ld.lld: error: undefined symbol: android::RefBase::decStrong(void const*) const >>> referenced by StrongPointer.h:182 (system/core/libutils/include/utilsPointer.h:182) >>> out/target/product/hello/obj/EXECUTABLES/hello_intermediates/hello.o:(say_hello(char const*, char*, int)) clang-9: error: linker command failed with exit code 1 (use -v to see invocation) 开始没认真分析报错的原因,直接在网上找答案了。看了网上的答案,基本上都是下面的答案: 在Android.mk中添加 LOCAL_LDFLAGS := -Wl,--unresolved-symbols=ignore-all 然而,加上这句之后,依然还是报同样的错误,似乎他们的解决方法对这个问题不起作用。 这个方法意思是告诉编译器 绕过这些检查,因此如果您尝试使用库中确实不存在的函数,ld就没有机会警告您,一般是不能随便用的。 然后来分析这个报错,它提示 undefined symbol。因此尝试去解决这个报错,通过引用system/core/libutils/include来解决,具体修改如下: LOCAL_C_INCLUDES += \ system/core/libnetutils/include \ system/core/libutils/include \ 然后编译之后,依然报一样的错。 后来,将 include $(BUILD_EXECUTABLE) 改成 include $(BUILD_STATIC_LIBRARY) 之后,竟然编译过了。因此,怀疑是 build系统不让通过LOCAL_C_INCLUDES的形式引用。 虽然已经包含了头文件,但由于编译器找不到要链接的库。不过,由于他们是共享库,因此在构建的时候,并不是严格要求需要拥有这些库。 从Android高版本开始,Android ndk规定了第三方可以使用的稳定的api(可以查看google官方的介绍https://developer.android.google.cn/ndk/guides/stable_apis.html)。一般可以通过在Android.mk中添加以下行来包括: LOCAL_LDLIBS := \ --lfoo \ ​ 由于使用的库不是稳定api的一部分。这本质上意味着,即使你的代码在某个特定版本的android上工作,它也可能在任何更高版本上中断,因为api可能已经更改了。

笔记:jdk 1.8 使用switch报错:Incompatible types. Found: ‘java.lang.String‘, required: ‘byte, char, short o

今天我在使用idea开发Java的时候发现,jdk1.8使用switch报错,Incompatible types. Found: 'java.lang.String', required: 'byte, char, short o: 新版本一般也会向下兼容旧版本的特性,根据idea提示可能会变成1.7,关于这个的解决方法并不是没有,解决方法如:https://blog.csdn.net/sinat_31726559/article/details/51659601?locationNum=4 总结:在idea左上角依次打开File-->Project structure-->Project 或 Modules -->language level,选择对应等级 有图如下: 1.打开导航栏的File 2.点击Project structure选项 3.进去,检查Project或Modules对应选项框中language level下是否选择的是jdk1.8的等级,

专业课错题记录(数据结构)

文章目录 五、二叉树七、二叉搜索树八、高级搜索树九、字典十一、优先级队列十二、排序 五、二叉树 1.高度为h的满二叉树有多少个节点?(A) A.2h+1−1 B.2h+1 C.2h−1 D.2h 解析:这里的h是高度,不是层次,两者的对应关系应该是高度h=总的层级数-1 2.设二叉树有n个节点,高度为h.在其中插入一个新的节点,高度发生改变的节点个数为:C A.O(1) B.O(n) C.O(h) D.O(hlog2(n)) 解析:这个题也是做的我一脸懵逼,这不是和插入的位置有关吗?看了答案才知道,原来问题想说的可能是插入一个叶子节点。答案的解析是,插入的节点的这条路径上所有的节点的高度都会发生变化 3.中序遍历中第一个被访问的节点是:(A) A.Leftmost node最左的节点 B.Rightmost node最右的节点 C.Root node根节点 D.Leaf node on the left branch左侧分枝的叶节点 解析:这个对我而言也是懵逼题。我不太清楚这个左侧分支的叶结点和最左的节点有什么区别,如果硬要说区别,大概就是左侧分支的叶节点分为左叶子和右叶子吧? 4.从n个节点的二叉树的叶节点u逐个节点地上溯到根节点的过程中,以下说法中错误的是:(D) A.The passing nodes are all ancestors of u.经过的节点都是u的祖先。 B.The worst time complexity is O(n)最坏时间复杂度为O(n) C.The path that is passed is uniquely determined经过的路径是唯一确定的 D.Each time it goes up one level, the depth of the current node decreases by one and the height increases by one.

HashMap面试题总结

文章目录 HashMap简介问题集合问点一:你了解HashMap的底层数据结构吗?问点二:为什么JDK 7使用数组+链表?JDK8中为什么要使用红黑树?哈希冲突是怎么回事?HashMap又是怎么解决的?问点三:HashMap的扩容机制是怎么样的?JDK7与JDK8有什么不同吗?问点四:HashMap中的键值可以为Null吗?能简单说一下原理吗?问点五:HashMap中能put两个相同的Key吗?为什么能或为什么不能?问点六:聊一聊JDK 7的HashMap中的“死锁”是怎么回事?问点七:HashMap是线程安全的吗?为什么安全或者不安全?问点八:什么 HashMap 的加载因子是0.75?为什么是超过“8”才用红黑树?问点九:HashMap、HashTable、ConcurrentHashMap的区别问点十:谈谈你理解的 HashMap,讲讲其中的 get和put 过程 由于HashMap在面试中是一个重点,内容十分多,需要单独写一篇文章总结 HashMap在Jdk1.7与1.8之中有很大区别!! HashMap简介 HashMap 是用来存储数据的,它底层在JDK 1.7是数组+链表实现的,而JDK 1.8是使用数组+链表+红黑树实现,通过对 key 进行哈希计算等操作后得到数组下标,把 value 等信息存放在链表或红黑树存在此位置。 如果两个不同的 key 运算后获取的数组下标一致,就出现了哈希冲突。数组默认长度是16,如果实际数组长度超过一定的值,就会进行扩容。 问题集合 问点一:你了解HashMap的底层数据结构吗? 在JDK1.7使用的是数组+链表的实现,在JDK1.8中使用的是数组+链表+红黑树 问点二:为什么JDK 7使用数组+链表?JDK8中为什么要使用红黑树?哈希冲突是怎么回事?HashMap又是怎么解决的? JDK 7使用数组+链表,是因为HashMap是根据Key计算Hash值,从而得到哈希表的索引下标,而哈希表本质是数组实现。当出现Hash冲突时,则一个桶可能需要存放多个数据。HashMap将会根据equals()方法,判断Hash冲突的Key是否是同一个值,此时如果仍然不相同,就会利用头插法,将出现Hash冲突的Key+Value存放在链表上。但是如果一个链表比较长,那么查询的效率将会降低,所以JDK8中又使用了红黑树来解决链表过长导致查询效率变差的问题,会在一个桶上链表长度为8时,进行树化。但是树化的时候,会判断当前的长度是否小于64,如果小于,则不进行树化,而是选择进行一次扩容,因为扩容的时候会使哈希表长度增加,hash值会重新计算,将重新打乱当前的元素排列,分配到新的空间上,这样也避免了链表过长。 对于HashMap中的每个key,根据一个Hash函数,计算出一个Hash值,对应就是桶的编号,桶实际上是用数组实现的。 //key 进行哈希计算 int hash = hash(key); //获取数组下标 int i = indexFor(hash, table.length); 通过计算后的下标,从而得到数组的对应下标的位置,最后把k,v值存进去,同样的当再次第二次存值的时候,同样把k,v传进来,当k再次进行计算出数组下标index,有可能和第一次计算的index的值相同。 但是,两次的需要存进去的value值是不同的,这就出现了同一个数组后面有一条链表,会比较链表上的每一个value值与当前的value是否相同,若是不相同,通过头插法,将数值插入链表中。如下图所示: 接下来通通过源码进行分析,在jdk 7插入的put 方法源码如下: public V put(K key, V value) { //数组为空就进行初始化 if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) return putForNullKey(value); //key 进行哈希计算 int hash = hash(key); //获取数组下标 int i = indexFor(hash, table.

springboot整合mybatis配置异常:Property ‘configuration‘and‘configLocation‘cannotspecifiedwithtogether源码角度分析

Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]: Factory method 'sqlSessionFactory' threw exception; Caused by: java.lang.IllegalStateException: Property 'configuration' and 'configLocation' can not specified with together 出现这个异常的原因是:我们在配置文件中指定了:config-location,然后我们又配置了关于configuration的信息,导致的报错。 大体意思就是,二者只能选择一种,要么指定config-location我们自己的xml配置文件,要么我们就使用Mybatis的start提供的配置。 如果两者都存在,那么他就会包冲突。 比如如下配置: mybatis: config-location: classpath:mybatis-config.xml mapper-locations: classpath:mapper/*Mapper.xml configuration: cache-enabled: true 这样他就会启动报错: Property 'configuration' and 'configLocation' can not specified with together 解决办法:要么我们去除掉config-location的xml配置,要么我们就去除configuration下面的配置 为了验证这一个异常,那么我们就深入源码看一波: 1、这里是springboot的自动装配,那么我们就应该重启动器入手 找到mybatis-spring-boot-starter的包,然后打开找到META-INF/spring.factories文件 # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration 这里能够查看mybatis使用了springboot的那些扩展点,同时也包括自动装配的扩展点: 然后我们进入org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration @org.springframework.context.annotation.Configuration @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class }) @ConditionalOnBean(DataSource.class) @EnableConfigurationProperties(MybatisProperties.class) @AutoConfigureAfter(DataSourceAutoConfiguration.class) public class MybatisAutoConfiguration {} 这里我们看到@EnableConfigurationProperties(MybatisProperties.class)注解指定的类(他就是读取配置文件的类) /** * 用于自定义默认设置的配置对象。如果指定了configLocation,则不使用此属性。 */ @NestedConfigurationProperty // 嵌套装配注解 private Configuration configuration; 这个属性上面的注解上讲到:如果configLocation,则不使用此属性。

打家劫舍

打家劫舍 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 示例 1: 输入:[1,2,3,1] 输出:4 解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。 偷窃到的最高金额 = 1 + 3 = 4 。 示例 2: 输入:[2,7,9,3,1] 输出:12 解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。 偷窃到的最高金额 = 2 + 9 + 1 = 12 。 public static int text(int[] nums){ if(nums.length == 0) return 0; int [] dp = new int[nums.

python3报错处理:UnicodeEncodeError: ‘ascii‘ codec can‘t encode characters in position 0-1

一、背景说明 最开始不愿意使用Python,一大原因是因为Python2默认使用ASCII编码处理中文可以说是一件痛苦的事情。仅从更换默认编码一项变换,就可以说Python3和Python2不算同一门语言。 Python3更换为默认使用Unicode(utf-8)编码,一直使用下来再没有遇到编码问题带来的困挠,似乎编码问题在Python3时代就该完全消失的。但这两天遇到了一个问题。 在调用一个库时,出现了一个异常报错类似如UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128),几经排查之下发现只要该库返回结果包含中文,我这边使用print()打印该结果时就会出现该异常。 二、原因分析 2.1 数据要经过编码才能传输 我们知道数据在网络上传输时,需要先编码;平时我们可能并不注意,但现在要明确,编码的原因不在于网络而在于传输。 print()相当于把字符串从内存传输到了tty上,所以print()是需要encode()动作的;平时我们print()时一般都不需要encode(),只是因为当print()检测到传来的参数是不是byte类型时自动进行了编码。 2.2 print()使用何种编码 Python3默认使用的是utf-8,这可以通过sys.getdefaultencoding()进行确认。但这只是默认,当系统配置了LC_ALL、LC_CTYPE、LANG等环境变量时(三者优先级从高到低),Python3采用这些变量配置的编码;如果这些变量配置的是utf-8那Python3用的就还是utf-8,但如果不是utf-8那Python3所用的也就不是utf-8了。 当前使用的编码可通过sys.getfilesystemencoding()获取。 三、场景复现 为简单起见,我们这里直接以打印一个中文字符串作为演示,示例代码如下(我这里保存成test_encode.py): import sys class TestEncode(): def __int__(self): pass def main_logic(self): # 打印语言默认编码 print(f"defaultencoding--{sys.getdefaultencoding()}") # 打印系统配置的编码 print(f"filesystemencoding--{sys.getfilesystemencoding()}") # 最后尝试打印中文 print("中文") if __name__ == "__main__": obj = TestEncode() obj.main_logic() shell依次执行如下命令: # 查看当前编码情况 locale # 确认在utf-8情况下打印中文无误 python3 test_encode.py # 设置LC_TYPE,C代表ASCII export LC_CTYPE="C" # 查看当前编码情况 locale # 再次运行,确认系统编码已改变,并出现编码错误 python3 test_encode.

使用nginx部署vue项目时,请求接口报404,但是postman能够拿到数据:解决办法

问题重现 在使用nginx部署vue项目时,使用的是前后端分离的方式部署vue,采用nginx反向代理部署的,但是当我把打包后的文件放入 /nginx/html/文件下时,然后再将nginx的配置文件修改如下: 这里我是在宝塔面版里面直接修改的配置文件 server { listen 80; server_name localhost; location / { root html; index index.html index.htm; } #error_page 404 /404.html; include enable-php.conf; location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ .*\.(js|css)?$ { expires 12h; } location ~ /\. { deny all; } access_log /www/wwwlogs/access.log; } 然后就出现如下问题: 我刷新之后,就变成如下页面: 这里有两个问题,一个是,发送的请求报404,并且路由跳转的时候,出现404的情况。 问题分析 首先我们需要分析,vue-cli的配置文件vue.config.js,这里说的就是为了解决跨域写的配置文件。vue-cli官网的说法:如果你的前端应用和后端 API 服务器没有运行在同一个主机上,你需要在开发环境下将 API 请求代理到 API 服务器。这个问题可以通过 vue.config.js 中的 devServer.proxy 选项来配置。 module.exports = { devServer: { proxy: { '/api': { target: '<url>', ws: true, changeOrigin: true }, '/foo': { target: '<other_url>' } } } } 可以发现为了解决跨域问题,vue在启动项目的时候也启动了一个node写的内置服务器,域名和端口是:localhost:8080,细心的小伙伴可以发现,vue ui 界面就是这个地址,当使用axios发送请求时,vue会帮你把请求的端口拼接到 localhost:8080 后面,如:http://localhost:8080/category 这种形式,并且再把这个地址的域名和端口号替换成 target属性中的端口号入下:

博客园增加Live2D看板娘教程,超级简单,一看就懂

目录 一、前言 二、效果图 三、资源准备 1、相关的资源,可以点击下面的网盘链接直接下载 2、也可以通过下面的地址到Gitbuh中下载 四、实现教程 1、个人小站实现教程 2、博客园实现教程 一、前言 最近逛博客园发现个很有意思的东西,查了一下原来叫看板娘,看板娘是一种职业和习惯称呼,也是ACGN次文化中的萌属性之一。简而言之就是小店的女服务生,也有“吸引顾客,招揽生意,提高人气”等作用类似品牌形象代言人的含义。 如果想在自己的博客上放一个呆萌的看板娘非常的简单只需要简单的几行代码就能实现。不过CSDN貌似不支持这个玩意,只能在博客园玩一玩,或者个人网站的玩一下。 二、效果图 可以到博主的小站查看效果图 博客园:https://www.cnblogs.com/wjhsmart/ 个人小站:http://wjhsmart.vip 三、资源准备 1、相关的资源,可以点击下面的网盘链接直接下载 链接:https://pan.baidu.com/s/1mKMKMGuQkH_XouRHXYGLcQ 提取码:m8x6 2、也可以通过下面的地址到Gitbuh中下载 Github地址:https://github.com/stevenjoezhang/live2d-widget.git 四、实现教程 1、个人小站实现教程 自己的网站要实现特别简单,本插件需要 Font Awesome (v4 或 v5) 图标支持,请确保相关样式表已在页面中加载。以 Font Awesome v4 为例,请在 <head> 中加入: Font Awesome (v4 or v5) is required for this plugin. Take Font Awesome v4 as an example, please add the following in <head>: <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome/css/font-awesome.min.css"> 否则图标将无法正常显示。(如果网页中已经加载了任何版本的 Font Awesome,就不要重复加载了) 导入了图标之后,将这一行代码加入 <head> 或 <body>,即可展现出效果:

项目中的常用注解(二)

之前对项目中常用注解有过一次整理项目中的常用注解,这里继续补充一下。供自己和有需要的小伙伴查漏补缺。

pycharm 社区版链接mysql数据库

文章目录 说明:步骤:1、安装database navigator2、链接数据库: 说明: 这个之前台式机用过一次,但是现在办公电脑换成笔记本,突然忘了之前怎么弄的了,所以干脆直接在搜索一次,记录下来,方便一会再使用其他电脑,可以快速配置。 步骤: 1、安装database navigator 1、打开pycharm,进入setting: 点击plugins地方,然后搜索database就出来了,安装database navigator 安装完毕: 然后重启一pycharm。 2、链接数据库: 重启之后左上角有个DB navigator 点击setting, 点击信息进入链接: 然后就可以在左边有数据库链接成功的,可以写一些MySQL命令语句执行了。 也可以在connection地方有机,选择测试,看看是否刚刚输入的链接mysql是否配置成功。

springcloud修改项目名称导致的pom文件出错

1、这个是完整可运行的已经编译过的父子项目(idea)中 修改project为springcloud,module为eureka-server,需要做的几步步骤,如下。 直接在外面文件夹改project:parentMavenProject——>springcloud module:childeMavenProject——>eureka-server, 然后在父目录下删除这些,如图: 然后修改父目录pom.xml文件: 同理,进入子目录,与父目录同样的操作: 然后同样修改pom.xml,重新导入该项目到idea中,reimport pom即可。

BIMFACE之3D

var config = new Glodon.Bimface.Viewer.Viewer3DConfig(); // 配置项 config.domElement = domId; // 设置文档元素为domId config.apiHost; // api网址 config.resourceHost; // 资源网址 config.initialViewOption; // 初始化视角 config.homeViewOption; // 主视角 config.enableViewHouse; // 是否开启viewHouse config.enableOrbit; // 是否可以旋转 config.orbitButton; // 设置鼠标右转 默认为左转 config.enableToggleContextMenuDisplay; //是否开启右键菜单 config.enableHover; // 是否开启构件鼠标悬停效果 config.enableBorderLine; // 是否显示轮廓线 config.exposure; // 设置曝光度 config,enableIBLBackground; // 是否启用环境光照 config.loadIBLScene; // 选择环境贴图 var viewer3D = new Goldon.Bimface.Viewer.Viewer3D(config); // 创建3D模型 并传入配置项 viewer3D.render(); // 渲染整个场景。如果调用了viewer3D的其它函数,建议在最后调用一次render(); viewer3D.addView(viewToken); // 添加一个模型场景 viewer3D.hideComponents(); // 隐藏构件 (已弃用)

系统学习NLP(三十二)--BERT、XLNet、RoBERTa、ALBERT及知识蒸馏

参考:https://zhuanlan.zhihu.com/p/84559048 一.BERT BERT是一种基于Transformer Encoder来构建的一种模型,它整个的架构其实是基于DAE(Denoising Autoencoder)的,这部分在BERT文章里叫作Masked Lanauge Model(MLM)。MLM并不是严格意义上的语言模型,因为整个训练过程并不是利用语言模型方式来训练的。BERT随机把一些单词通过MASK标签来代替,并接着去预测被MASK的这个单词,过程其实就是DAE的过程。BERT有两种主要训练好的模型,分别是BERT-Small和BERT-Large, 其中BERT-Large使用了12层的Encoder结构。 整个的模型具有非常多的参数。 BERT在2018年提出,当时引起了爆炸式的反应,因为从效果上来讲刷新了非常多的记录,之后基本上开启了这个领域的飞速的发展。 二.XLNet BERT之后的一个爆发节点发生在XLNet发布的时候,因为它刷新了BERT保留的很多记录。除了效果之外,那为什么要提出XLNet呢?这就需要从BERT的缺点说起。 虽然BERT有很好的表现,但本身也有一些问题。总结起来有以下几点: 1.训练数据和测试数据之间的不一致性,这也叫作Discrephancy。当我们训练BERT的时候,会随机的Mask掉一些单词的,但实际上在使用的过程当中,我们却没有MASK这类的标签,所以这个问题就导致训练的过程和使用(测试)的过程其实不太一样,这是一个主要的问题。 2. 并不能用来生成数据。由于BERT本身是依赖于DAE的结构来训练的,所以不像那些基于语言模型训练出来的模型具备很好地生成能力。之前的方法比如NNLM[12],ELMo是基于语言模型生成的,所以用训练好的模型可以生成出一些句子、文本等。但基于这类生成模型的方法论本身也存在一些问题,因为理解一个单词在上下文里的意思的时候,语言模型只考虑了它的上文,而没有考虑下文! 基于这些BERT的缺点,学者们提出了XLNet, 而且也借鉴了语言模型,还有BERT的优缺点。最后设计出来的模型既可以很好地用来执行生成工作,也可以学习出上下文的向量表示。那如何做的呢? 首先,生成模型是单向的,即便我们使用Bidirectional LSTM类模型,其实本质是使用了两套单向的模型。那又如何去解决呢?答案是他们使用了permutation language model, 也就是把所有可能的permutation全部考虑进来。这个想法源自于hugo之前的工作叫作NADE,感兴趣的读者可以去看一下。 另外,为了迎合这种改变,他们在原来的Transformer Encoder架构上做了改进,这部分叫作Two-stream attention, 而且为了更好地处理较长的文本,进而使用的是Transformer-XL。 这就是XLNet的几大核心!关于Transformer-XL 看这里 https://zhuanlan.zhihu.com/p/70745925 核心: Transformer编码固定长度的上下文,即将一个长的文本序列截断为几百个字符的固定长度片段(segment),然后分别编码每个片段[1],片段之间没有任何的信息交互。比如BERT,序列长度的极限一般在512。动机总结如下: Transformer无法建模超过固定长度的依赖关系,对长文本编码效果差。Transformer把要处理的文本分割成等长的片段,通常不考虑句子(语义)边界,导致上下文碎片化(context fragmentation)。通俗来讲,一个完整的句子在分割后,一半在前面的片段,一半在后面的片段。 文章围绕如何建模长距离依赖,提出Transformer-XL【XL是extra long的意思】: 提出片段级递归机制(segment-level recurrence mechanism),引入一个记忆(memory)模块(类似于cache或cell),循环用来建模片段之间的联系。 使得长距离依赖的建模成为可能;使得片段之间产生交互,解决上下文碎片化问题。提出相对位置编码机制(relative position embedding scheme),代替绝对位置编码。 在memory的循环计算过程中,避免时序混淆【见model部分】,位置编码可重用。 小结一下,片段级递归机制为了解决编码长距离依赖和上下文碎片化,相对位置编码机制为了实现片段级递归机制而提出,解决可能出现的时序混淆问题。 三.RoBERTa RoBERTa 模型更多的是基于 BERT 的一种改进版本。是 BERT 在多个层面上的重大改进。 RoBERTa 在模型规模、算力和数据上,主要比 BERT 提升了以下几点: 更大的模型参数量(从 RoBERTa 论文提供的训练时间来看,模型使用 1024 块 V 100 GPU 训练了 1 天的时间) 更多的训练数据(包括:CC-NEWS 等在内的 160GB 纯文本)

用nginx实现分布式限流(防DDOS攻击)

1.前言 一般对外暴露的系统,在促销或者黑客攻击时会涌来大量的请求,为了保护系统不被瞬间到来的高并发流量给打垮, 就需要限流 . 本文主要阐述如何用nginx 来实现限流. 听说 Hystrix 也可以, 各位有兴趣可以去研究哈 . 2. 首先部署一个对外暴露接口的程序 我这里部署的是一个spring boot 项目 里面暴露了如下接口, 很简单 package com.anuo.app.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/test") public class TestController { Logger logger = LoggerFactory.getLogger(TestController.class); @RequestMapping(value = "/show/message", method = RequestMethod.GET) public String test() { return "hello world "; } } 暴露了一个 get 请求返回 hello world 的restful 接口. 将此程序部署到 linux 服务器上. 部署步奏不再赘述, 自行百度 spring boot 部署 即可.

【Java学习-进阶】-swagger配置与优化

1、Swagger简介 Swagger是一个实现了OpenAPI(OpenAPI Specification)规范的工具集。OpenAPI是Linux基金会的一个项目,试图通过定义一种用来描述API格式或API定义的语言,来规范RESTful服务开发过程。 官网地址:https://swagger.io/ 2、工具集介绍 现在SWAGGER官网主要提供了几种开源工具,提供相应的功能。可以通过配置甚至是修改源码以达到你想要的效果。 Swagger UI: Swagger UI是HTML,Javascript和CSS资产的集合,可以从符合OAS标准的API动态生成漂亮的文档。 SwaggerEditor: Swagger文件编辑器,可以在线或者本地编辑描述文件,类似于markdown。 Swagger Codegen: 基于OpeanAPI的规范,通过Codegen可以将描述文件生成html格式和cwiki形式的接口文档,支持通过jar包,docker,node等方式在本地化执行生成。也可以在Swagger Editor中在线生成。 Swagger Inspector(免费): API测试工具,可让您验证您的API并从现有API生成OpenAPI定义 SwaggerHub(免费和商业): 集成了上面所有项目的各个功能,你可以以项目和版本为单位,将你的描述文件上传到Swagger Hub中。在Swagger Hub中可以完成上面项目的所有工作,需要注册账号,分免费版和收费版。 3、Maveny依赖引入 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> 4、配置编写 /** * swagger API测试配置 * * @author xxx */ @Configuration @EnableSwagger2 //表示swagger表示Swagger的开关,已经启用swagger public class Swagger2 { @Value("${spring.application.name}") private String appName; @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).enable(true).select() .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))//监控所有RestController注解的 .paths(PathSelectors.any()).build();//对跟下所有路径进行监控 } private ApiInfo apiInfo() { return new ApiInfoBuilder().

SSD固态硬盘颗粒SLC MLC TLC QLC有什么区别

NOR Flash 和 NAND Flash是现在市场上两种主要的非易失闪存技术。Intel于1988年首先开发出NOR Flash 技术,彻底改变了原先由EPROM(Electrically Programmable Read-Only-Memory电可编程序只读存储器)和EEPROM(电可擦只读存储器Electrically Erasable Programmable Read – Only Memory)一统天下的局面。紧接着,1989年,东芝公司发表了NAND Flash 结构,强调降低每比特的成本,有更高的性能,并且像磁盘一样可以通过接口轻松升级。NOR Flash 的特点是芯片内执行(XIP ,eXecute In Place),这样应用程序可以直接在Flash闪存内运行,不必再把代码读到系统RAM中。NOR 的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除速度大大影响到它的性能。NAND的结构能提供极高的单元密度,可以达到高存储密度,并且写入和擦除的速度也很快。应用NAND的困难在于Flash的管理和需要特殊的系统接口。通常读取NOR的速度比NAND稍快一些,而NAND的写入速度比NOR快很多,在设计中应该考虑这些情况。 NAND Flash根据存储原理分为三种,SLC、MLC、TLC。 什么是SLC?SLC英文全称(Single Level Cell——SLC)即单层式储存 。主要由三星、海力士、美光、东芝等使用。 SLC技术特点是在浮置闸极与源极之中的氧化薄膜更薄,在写入数据时通过对浮置闸极的电荷加电压,然后透过源极,即可将所储存的电荷消除,通过这样的方式,便可储存1个信息单元,这种技术能提供快速的程序编程与读取,不过此技术受限于Silicon efficiency的问题,必须要由较先进的流程强化技术(Process enhancements),才能向上提升SLC制程技术。 什么是MLC?MLC英文全称(Multi Level Cell——MLC)即多层式储存。主要由东芝、Renesas、三星使用。 MLC是英特尔(Intel)在1997年9月最先研发成功的,其原理是将两个位的信息存入一个浮动栅(Floating Gate,闪存存储单元中存放电荷的部分),然后利用不同电位(Level)的电荷,透过内存储存格的电压控制精准读写。MLC通过使用大量的电压等级,每个单元储存两位数据,数据密度比较大。SLC架构是0和1两个值,而MLC架构可以一次储存4个以上的值,因此,MLC架构可以有比较好的储存密度。讲白话点就是一个Cell存放多个bit,现在常见的MLC架构闪存每Cell可存放2bit,容量是同等SLC架构芯片的2倍,目前三星、东芝、海力士(Hynix)、IMFT(英特尔与美光合资公司)、瑞萨(Renesas)都是此技术的使用者,而且这个队伍还在不断壮大,其发展速度远快于曾经的SLC架构。 与SLC比较MLC的优势:鉴于目前市场主要以SLC和MLC储存为主,我们多了解下SLC和MLC储存。SLC架构是0和1两个值,而MLC架构可以一次储存4个以上的值,因此MLC架构的储存密度较高,并且可以利用老旧的生产程备来提高产品的容量,无须额外投资生产设备,拥有成本与良率的优势。与SLC相比较,MLC生产成本较低,容量大。如果经过改进,MLC的读写性能应该还可以进一步提升。与SLC比较MLC的缺点:MLC架构有许多缺点,首先是使用寿命较短,SLC架构可以写入10万次,而MLC架构只能承受约1万次的写入。其次就是存取速度慢,在目前技术条件下,MLC芯片理论速度只能达到6MB左右。SLC架构比MLC架构要快速三倍以上。再者,MLC能耗比SLC高,在相同使用条件下比SLC要多15%左右的电流消耗。虽然与SLC相比,MLC缺点很多,但在单颗芯片容量方面,目前MLC还是占了绝对的优势。由于MLC架构和成本都具有绝对优势,能满足2GB、4GB、8GB甚至更大容量的市场需求。 什么是TLC? TLC = Triple-Level Cell,即3 bit per cell架构。TLC芯片技术是SLC和MLC技术的延伸,最早期NAND Flash技术架构是SLC(Single-Level Cell),原理是在1个存储器储存单元(cell)中存放1位元(bit)的资料,直到MLC(Multi-Level Cell)技术接棒后,架构演进为1个存储器储存单元存放2位元。 2009年TLC架构正式问世,代表1个存储器储存单元可存放3位元,成本进一步大幅降低。如同上一波SLC技术转MLC技术趋势般,这次也是由NAND Flash大厂东芝(Toshiba)引发战火,之后三星电子(Samsung Electronics)也赶紧加入战局,使得整个TLC技术大量被量产且应用在终端产品上。TLC芯片虽然储存容量变大,成本低廉许多,但因为效能也大打折扣,因此仅能用在低阶的NAND Flash相关产品上,象是低速快闪记忆卡、小型记忆卡microSD或随身碟等。智能型手机(Smartphone)、固态硬碟(SSD)等技术门槛高,对于NAND Flash效能讲求高速且不出错等应用产品,则一定要使用SLC或MLC芯片。 根据NAND的物理结构,NAND是通过绝缘层存储数据的。当你要写入数据,需要施加电压并形成一个电场,这样电子就可以通过绝缘体进入到存储单元,此时完成写入数据。如果要删除存储单元(数据),则要再次施加电压让电子穿过绝缘层,从而离开存储单元。所以,NAND闪存在重新写入新数据之前必须要删除原来数据。 由于数据写入到TLC中需要八种不同电压状态, 而施加不同的电压状态、尤其是相对较高的电压,需要更长的时间才能得以实现(电压不断增高的过程,直到合适的电压值被发现才算完成)。 所以,在TLC中数据所需访问时间更长,因此传输速度更慢。经过实测,同等技术条件下,TLC的SSD性能是比不上MLC SSD的。 什么是QLC? QLC = Quad-Level Cell架构,即4bit/cell,支持16充电值,速度最慢寿命最短,目前中技术上在研发阶段,但是intel、三星电子等厂商都已经取得了不错的进展。但在SSD应用中目前仍不现实 。 需要说明的闪存的寿命指的是写入(擦写)的次数,不是读出的次数,因为读取对芯片的寿命影响不大。下面是SLC、MLC、TLC、QLC闪存芯片的区别: SLC = Single-Level Cell,即1bit/cell,利用正、负两种电荷,一个浮动栅存储1个bit的信息,约10万次擦写寿命。速度快,寿命长,价格贵(约MLC 3倍以上的价格)。

毕业三两句

终于在2020年上半年的尾巴里,顺利毕业了,本来以为自己会有很多的感悟,但是却是出乎意料的平静。 仅有三天返校时间,收拾东西,办理毕业的相关材料,拍毕业照,领双证,冒着大雨寄东西。还因为要请老师吃饭不得不提前一天离校。 时间紧张到没空去逛逛阔别已久的校园,没有时间产生伤感的情绪,本科毕业的时候大家都很难过,所有人都流眼泪,研究生看来还是变的成熟了,长大了,没有人哭,很少见大家有啥伤感的情绪。 直到我背着包要离开了,途径那个来来回回走了三年的东风广场,看了眼在上面拍照的毕业生,突然地恍惚了一下,噫,我以后再也回不来了奥。 走出校门回头看了看牌子,好嘛,这下子要成为社会精英(社畜)了。 不知道是不是正常,问过一些同学,很多都会对本科有着更高的认同感(本硕不同校),本科的校歌校训背的熟的一匹,研究生就记得不是很牢,甚至记不住,想到这里感觉自己十分没有良心了,赶紧去百度了一下加深印象。 很多都是在校千般吐槽,出校万般维护。颇有一种失去了才知道珍惜的感觉。 感觉自己也算是比较特殊的一届毕业生了,因为疫情的原因在家呆了半年,原本计划的毕业旅行和同学间的毕业酒局都木有了。 有好有坏,好的是多了很多时间陪家人,陪女朋友,毕竟以后上班了就没有这么多的时间了,不好的就是假期这么久呆的自己没了状态,虽然一直在忙着写论文,但是按部就班的,压力不大,在家就少了很多学习的氛围。大半年没咋敲过代码(带回家的电脑也就打打文档,撑不起来啥),很多的知识都忘的差不多了,最近也在赶紧的恶补一下知识。然后就是一个人待着的时候,思维就比较活跃,想的也杂,就开始有点恐惧上班,想来想去也不知道自己怕啥(也可能是怕的太多,不知道哪个是主要原因了)。 但是,再怕还是要去做啊,还是要接着干才行,做着做着习惯了适应了大概就会好多了吧,一开始慌张迷茫也是正常的,我也没去实习过,头一次脱离学生的身份正式进入社会,进入公司,年轻人嘛,莽就完了。 7月10号入职,新的篇章就要掀开了,要继续努力啊!这辈子,要为自己拼个命啊。

Ubuntu18.04重装系统+常用软件安装

1.Ubuntu18.04重装系统 1.1 安装盘制作 1) 首先从官网上下载Ubuntu18.04镜像,下载最好从官网上下载(Download Ubuntu Desktop | Download | Ubuntu)。 Index of /releases/18.04.4 如下图: 2) 下载好Ubuntu18.04镜像后,我们需要进行U盘的制作或者光盘的刻录,我们先看一下U盘启动项的制作, 刻录U盘或者光盘,我们需要一款刻录软件、本人所用的是UltraISO软通牒刻录软件,这款软件网上都可以找到,下载安装就可以,这里只示范U盘刻录。示例如下: 安装好的UltraISO 这里选择下载好的ISO,点击文件项下的打开将ISO添加进来 选择启动项下的写入硬盘镜像,写入硬盘镜像下的参数、默认的就可以,所用不需要修改。如果为了验证的话,把刻录校验选择上就可以。最后点击写入、等待完成。最后,一款随身携带的U盘安装Ubuntu16.04就完成了 3) 光盘的刻录、还是在我们的UltraISO中,将我们ISO加载进来。如下图: 选择工具项下的刻录光盘镜像,切记,这里最好刻录的是干净的光盘,之后点击刻录就OK了 最后,我们的U盘安装启动项和光盘刻录完成了,可以直接安装系统了! 1.2 安装过程 进行U盘安装系统之前,还需要设置BIOS boot启动选项,默认的是硬盘启动,需要设置为U盘启动 不同的主板设置U盘启动的方式也不同,因此小编就不详述怎么更改BIOS设置,大家查找自己的主板型号然后在网上找相关的设置教程即可完成BIOS设置后就可以插入U盘重启电脑就可以使用U盘进行Ubuntu操作系统的安装了 参考https://jingyan.baidu.com/article/3c48dd348bc005e10be358eb.html 1.3 分区 法一: Swap(相当于电脑内存):逻辑分区、大小设置为电脑内存大小,2G,4G; /boot(引导分区):主分区:大小设置为200M; /home(用户存储数据用):逻辑分区,要尽可能大,100G空间可以设置为85G,留10G给主分区即可。 /.(主分区):主分区,用于存放系统,相当于win7的C盘,10G即可。 法二: /.(主分区):主分区,只分这一个区,将所有空闲空间(free space)都分给主分区。 法三: Swap(相当于电脑内存):逻辑分区、大小设置为电脑内存大小的两倍; /.(主分区):主分区,用于存放系统和其他(包括/home等),其他剩余空间都分给主分区,避免分区过多导致主分区空间太小. 小结: 1) 三种方法都同样适用,推荐第三种方法(swap 32G ; /. 主分区 200G); 2) 当分给linux的硬盘比较小时,可以选择法二。 创建主分区: 5G 主分区 空间起始位置 Ext4日志文件系统 / 创建swap分区: 2048MB 逻辑分区 空间起始位置 交换空间 创建boot分区: 200MB 逻辑分区 空间起始位置 Ext4日志文件系统 /boot

一篇来自前端同学对后端接口的吐槽

小Hub领读: 企业接口规范有没统一定义,直接会影响到工作中的对接效率。今天来听听来自前端同学的吐槽,你有没也这种做过?哈哈~ 对了,还有一件事情要提醒下,今天6月30日,2020年已过一半!你的目标实现多少了? 本文作者:李熠 https://juejin.im/post/5cfbe8c7e51d4556da53d07f 前言 去年的某个时候就想写一篇关于接口的吐槽,当时后端提出了接口方案对于我来说调用起来非常难受,但又说不上为什么,没有论点论据所以也就作罢。最近因为写全栈的缘故,团队内部也遇到了一些关于接口设计的问题,于是开始思考实现接口的最佳实践是什么。在参考了许多资料之后,逐渐对这个问题有了自己的理解。同时回想起过去的经验,终于恍然大悟自己当时的痛点在哪里。 既然是吐槽,那么请原谅我接下来态度的不友善。本文中列举的所有例子都是我个人的亲身经历。 谁应该主导接口的设计 或者更直白一些,应该是接口的消费方还是提供方来决定接口的设计? 当然是接口的消费方 「接口」最吊诡的地方在于提供方大费周章把它实现了,但它自己却(几乎)重来都不使用。于是这极易陷入一种自嗨的境地,因为他更本不知道接口的好坏。就好比一个从来不尝自己做的菜的厨子,你指望他的菜能好到哪里去,他的厨艺能好到哪里去。上面隐含的前提是(我认为)接口是有绝对好坏之分的,坏的接口消费者调用难受,提供者维护难受,还导致产品行为别扭体验变差。 然而接口的好坏与谁来主导设计有什么关系?因为坏接口产生的原因之一是提供方只站在开发者的角度解决问题: 例子一 (Chatty API) 某次需要实现允许用户创建仪表盘页面的功能(如果你对仪表盘页面感到陌生的话,可以想象它是一张集中了不同图表的页面,比如柱状图、折线图、饼图等等。用户可以添加自己想要的图表到页面中,并且手动调整它们的尺寸和位置。仪表盘通常用于总览某个产品或者服务的运行状态)。后端同学的接口初步设计是,当用户填写完基本信息、添加完图表、点击创建按钮之后,我需要连续调用两次接口才能完成一次仪表盘的创建: 利用用户填写的基本信息以及图表的尺寸和位置创建一个空的仪表盘 再向仪表盘中填充图表的具体信息,比如图表类型,使用的维度和指标等 很明显看出他完全是按照自己后端的存储结构在设计接口,不仅是存储结构,甚至存储过程都一览无余。想象一种极端的情况,那不只提供一些更新数据库表的接口得了,前端自己把通过接口把数据插入库中 面对这类底层性质的接口,消费者在集成时需要考虑接口的调用步骤以及理解背后的原理。如果后端的底层结构一旦发生更改,接口很有可能也需要发生更改,前端的调用代码也需要随之更改。 后端研发可能会辩解说:后端用了微服务啊,不同类型的数据存储在不同的服务上,所以你需要和不同的服务通信才能实现完整的存储。他们始终没有明白的事情是,后端的实现导致了接口的碎片化,那是你的问题,而不应该把这部分负担转移到前端的开发者上,其实也是间接转移到了用户身上。不要欺负我不懂后端,至少我了解加一层类似于 BFF 的 Orchestration Layer 就能解决这个问题 Netflix 的工程师 Daniel Jacobson 在他的文章 The future of API design: The orchestration layer 中指出, API 无非是要面对两类受众: LSUD: Large set of unknown developers SSKD: Small set of known developers 随着产品服务化的趋势,很有可能需要像 AWS 或者 Github 那样对公共开发者即 LSUD 暴露接口。且不说上面例子中的接口方案会不会被唾沫星子淹死,如此明显的暴露内部服务的细节是非常危险的事情。 所以在设计接口时,应该让消费者来主导。如果消费者没能给出很好的建议,那么至少提供者在设计时也应该站在消费者的立场上来思考问题。又或者,至少想一想如果你自己会乐意使用用你自己设计出来的接口吗? 使用后端思维设计接口不仅体现在 URI 的设计上,还有可能体现在请求参数和返回体结构上: 例子二 假设现在需要一个请求批量文章的接口,接口同时返回多篇文章的内容,包括这些文章的内容,作者信息,评论信息等等。 理想情况下,我们期望返回的数据是以文章为单位的,比如

EINTR

当程序在执行处于阻塞状态的系统调用时接收到信号,并且我们为该信号设置了信号处理函数,在信号处理函数返回后,程序将面临继续执行或不执行慢速系统调用两种选择,默认情况下是系统调用将被中断,并且errno被设置为EINTR。我们可以选择继续执行,有以下两种方法: 1.在设置信号处理函数的时候,为信号设置SA_RESTART标志以自动重启被该信号中断的系统调用,但是该方法对某些慢速系统调用无效,比如epoll_wait,poll,seletc等慢速系统调用,即使给信号设置了该选项,也会被中断。具体对那些慢速系统调用无效可查看manpages。 2.手动重启,对慢速系统调用的返回值进行判断,若errno==EINTR,则重新调用慢速系统调用 综上所述,若想要重启系统调用,最好使用方法2。

Dell服务器 iDRAC(IPMI) 如何连接管理服务器

给IPMI口配置IP地址 1 什么是IPMI2 准备硬件3 开机配置4 验证 1 什么是IPMI IPMI是智能平台管理接口(Intelligent Platform Management Interface)原本是一种Intel架构的企业系统的周边设备所采用的一种工业标准。 简单的说就是将配置好IP的IPMI口接入交换机,你就可以通过电脑远程来管理服务器的一个接口 2 准备硬件 显示器一个(由于不知道IPMI口IP地址,需要用显示器连接服务器进行可视化操作)键盘一个(不用说就是来控制服务器的)网线一根(用来测试配置是否成功,以及接入局域网用)注:如果是没做任何配置的IPMI可以直接用网线将服务器与笔记本电脑连接, 默认的IP是192.168.0.120 用户名root,默认的初始密码是calvin 用笔记本连接后配置本地连接的IPV4属性 3 开机配置 1.用合适的线连接显示器与服务器,因为连接线有多种,大胆尝试连上即可。 2.插上鼠标,服务器开机 3.当服务器出现Press <Ctrl-E> for Remote Access Setup within 5 sec... 时同时按下Ctrl键和E键 **注:** 因服务不同按键略有差异,主要看到Remote Access Setup within 5 sec. 按下这些关键字所对应的按键按下就可进入iDRAC配置界面 (1)我进入的是iDRAC6的配置界面,如下图: (2)配置界面:将iDRAC6 LAN 和IPMI Over LAN这两项状态都设为On (3)按下LAN Parameters进行IP的配置 (4)根据交换机可分配的IP网段进行配置,正常情况下IP、网关、DNS缺一不可 (5)按下LAN UserConfiguration进行web登录时用户名和密码的设置 最后按Esc退出保存! 4 验证 1.此时将服务器的IPMI口和笔记本网线口连接即可验证(部分服务器会标出,未标出的可以看与其他网线口略有不同的就是IPMI口了) 用笔记本连接后可以直接打开浏览器输入你设置的IP地址进行访问,如不能访问,请检查你的以太网连接的IPV4是不是自动获取IP 2.将服务器的IPMI接入到交换机,交换机做一些简单的配置即可实现远程连接了

Java ListResourceBundle getContents()方法与示例

ListResourceBundle类的getContents()方法 (ListResourceBundle Class getContents() method) getContents() method is available in java.util package. getContents()方法在java.util包中可用。 getContents() method is used to get the contents into the form of an Object array (Object [][]) and every item is pairs of objects in an Object[][] where first indices represent the key element and the second indices represent the value element linked with the key in an object array. getContents()方法用于将内容转换为Object数组(Object [] [])的形式,每个项目都是Object [] []中的成对对象,其中第一个索引代表键元素,第二个索引代表与对象数组中的键链接的value元素。 getContents() method is a non-static method, it is accessible with the class object only and if we try to access the method with the class name then we will get an error.

Unity3D Http接口常用加密算法

HMAC-SHA1 算法 //HMAC-SHA1 算法1 public static object HMAC_SHA1(string content, string secretKey, bool raw_outut = false) { Encoding enc = Encoding.UTF8; HMACSHA1 hmacsha1 = new HMACSHA1(enc.GetBytes(secretKey)); byte[] bytes = enc.GetBytes(content); if (raw_outut) { return hmacsha1.ComputeHash(bytes); } else { return BitConverter.ToString(hmacsha1.ComputeHash(bytes)).Replace("-", string.Empty).ToLower(); } } //HMAC-SHA1 算法2 public static string ComputeHMAC_SHA1Base64(string data, string key) { System.Security.Cryptography.HMACSHA1 hmacsha1 = new System.Security.Cryptography.HMACSHA1(Encoding.UTF8.GetBytes(key), true); byte[] dataBuffer = Encoding.UTF8.GetBytes(data); byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer); return Convert.ToBase64String(hashBytes); } MD5 算法 //md5 public static string Md5Sum(string strToEncrypt) { byte[] bs = Encoding.

moduleName is declared but its value is never read.ts(6133)报错解析

问题重现 当使用ts语法导入第三方库时,比如koa模块,这时会发现出现这个错误。这个错误因为没有默认导出。 问题原因 一般我们使用ts导入其他模块时都会有一个声明文件。不明白可以看我另外一篇 博客,我们进入声明文件中可以发现模块是通过export =的方式导出的。 于是我们去TS官网中的模块可以发现:当使用export = 和 import = require()时 CommonJS和AMD的环境里都有一个exports变量,这个变量包含了一个模块的所有导出内容。CommonJS和AMD的exports都可以被赋值为一个对象, 这种情况下其作用就类似于 es6 语法里的默认导出,即 export default语法了。虽然作用相似,但是 export default 语法并不能兼容CommonJS和AMD的exports。为了支持CommonJS和AMD的exports, TypeScript提供了export =语法。export =语法定义一个模块的导出对象。 这里的对象一词指的是类,接口,命名空间,函数或枚举。若使用export =导出一个模块,则必须使用TypeScript的特定语法import module = require(“module”)来导入此模块。 可以发现,ts为了兼容CommonJS和AMD的exports。所以这里定义了一种方法来解决这种问题使用export= 的方式导出的模块必须使用import module = require(“module”)这种方式导入。 这里也可以使用另外一种方式解决这个问题: import * as koa from ‘koa’ 但是这种方式导入和上面是有一些区别的。

Spring Boot(二):外部配置文件(超级详细)

Spring Boot 配置文件及自动配置原理 前言一、配置文件的两种类型二、YAML 语言入门1、基本语法2、数据类型2.1、YAML 纯量2.2、数组2.3、对象2.4、开发实例 三、Spring Boot 配置文件取值1、通过获取环境变量获取配置1.1、创建新工程1.2、编写配置文件1.3、获取配置内容1.3.1、启动类获取环境变量获取配置1.3.2、注入环境变量获取配置 2、通过注解获取配置2.1、@Value 注解2.2、@ConfigurationProperties注解2.2.1、思考案例2.2.2、作用和注意点2.2.3、和@Value注解的异同点2.2.4、松散绑定(Relaxed Binding)2.2.5、JSR303数据校验 3、小结 四、Spring Boot 多环境配置1、单yml文件2、多yml文件 五、Spring Boot 加载配置文件 前言 前面我们说到,springboot使用了特定的方式来进行配置,即约定优于配置(Spring Boot在底层已经把配置都约定(配置)好了)的设计范式,从而使开发人员不再需要定义样板化的配置,就可以正常运行一个spring程序。但是在一些特殊的情况下,我们需要偏离springboot中的约定(默认配置),这时我们就需要自定义一些配置用来修改springboot的默认配置。 一、配置文件的两种类型 Spring Boot 为我们提供一个名称为 application 的全局配置文件,支持两种类型,一种properties类型,一种YAML类型,用于修改 Spring Boot 的默认配置。 两种配置文件 ​ application.properties ​ application.yaml 或者 application.yml 在上一篇文章中我们可以看到,当我们创建一个springboot项目的时候,系统默认会为我们在 src/main/java/resources 目录下创建一个 application.properties 配置文件。 因为我个人更喜欢 yaml 格式的配置文件,所以一般在创建好项目后我会将 application.properties 修改为 application.yml。可能我们会在不同的项目中看见两种不同的配置文件格式,实际上两种格式都是OK的。我会在后面详细介绍一下 YAML语言,关于properties就展开来说了。 二、YAML 语言入门 YAML是 YAML Ain't Markup Language(YAML 不是一种标记语言)的递归缩写 ,YAML还可以理解为 Yet Another Markup Language(仍是一种标记语言)。 YAML 是专门用来写配置文件的语言,以数据为中心,非常简洁和强大,比json、xml等更适合做配置文件。 1、基本语法 采用 key: value方式表示数据(冒号后面需要空格隔开)大小写敏感使用缩进表示层级关系缩进不允许使用tab,只允许空格缩进的空格数不重要,只要相同层级的元素左对齐即可'#'表示注释 需要注意的是,YMAL语言只支持单行注释,从 # 开始一直到行尾,都会被解析器忽略。

二连杆动力学建模

仿真环境:matlab 内容涉及:拉格朗日方程,动力学建模。 实现效果:将关节视为轴承连接,无动能损耗,连杆摆动过程中,动能与势能相互转换,但是连杆的总能量恒定,如下图红线所示,黑线和蓝线分别代表动能和势能。 (一)欧拉-拉格朗日方程推导 根据牛顿第二定律: 定义: 那么牛顿第二定律可以表示为: L称为拉格朗日算子,上式称为欧拉-拉格朗日方程。 将上述用广义坐标q=(q1,q2,q3,…qn)的形式表示,n为系统的自由度数目。 是与广义坐标qk相关的广义力。 (二)二连杆动能势能计算 2.1 速度传递(以转动关节为例) 其中vk表示k杆中任意位置pk处的速度,wk表示k杆的角速度。(从中我们可以发现,线速度表示的某点的属性,而角速度在同一杆件上处处相同,是杆件坐标系的属性。) 使用以上公式可以计算杆件上任意一点的角速度和线速度,首先应表达出杆件重心和杆件末端的坐标,坐标的表示可参照上期内容。 两个关节的绝对角速度表示如下: aw1=[w1_x,w1_y,w1_z]’; aw2=[w2_x,w2_y,w2_z]’; 以矢量的形式表示: w0_1=aw1.x1; w1_2=aw2.x2; 速度传递: w1=w0_1; w2=w1+(R0_1w1_2); v_a=v0; v_e=v_a+w1xr_ae; v_b=v_a+w1xr_ab; v_c=v_b+w2xr_bc; v_f=v_b+w2xr_bf; 2.2动能计算 K=平动动能+转动动能 平动动能=0.5m1v_ev_e+0.5m2v_fv_f; 转动动能=0.5w1’I1_ww1+0.5w2’I2_ww2; 其中,I1_w,I2_w表示的是杆件的惯性张量。 I1_w=R0_1I1R0_1’; I2_w=R0_2I2R0_2’; I1,I2表示初始姿态(基态)的惯性张量,常将容易计算的位置当做初始状态。 2.3势能计算 P=m1gdot(p_e,z0)+m2g*dot(p_f,z0)); dot表示在世界坐标系z0方向(重力方向)上的投影。 (三)状态更新 问题描述:输入关节力矩为零,求解关节变量角度和角速度。 问题转换:即求解以下微分方程: (四)仿真 关注公众号获取更多内容

tkinter-label

本文介绍tkinter中label控件的使用。结合实际的示例来理解label控件的使用,看完本文基本上就能理解label各个属性的含义并能灵活使用,做到心中有谱。 文章目录 标签(label)标签属性background\bg,textwidthheightanchorforeground\fgfontcursorimagebitmapborderwidth\bdpadxpadyreliefjustifystateactivebackgroundactiveforegrounddisabledforegroundtextvariableunderlinewraplength 标签(label) 标签(label)控件中可以显示文字和图像。label显示的文本内容是可以动态更新。 标签属性 background\bg, 表示显示区的背景色 # bg 设置显示区的背景颜色 # 如果没有指定显示区的宽高,label会自适应text文字的宽高 label1 = Label(main_win, bg='white', text='hello', anchor='center') label1.pack() # 如果label显示区是自适应文字的宽高,那么设置anchor其实没有实际作用 label2 = Label(main_win, bg='white', text='hello', anchor='se') label2.pack() text 指定显示的文本,文本中的’\n’将会换行。 width 指定显示区的宽度,如果没有指定,将自适应文本实际的宽度。如果显示区的内容是文本,那么以字符为单位; 如果显示区的内容是图片,那么以像素为单位。 height 指定显示区的高度 anchor 锚点,用来指定文本或图像在label显示区的显示位置。默认值是"center",可设置的值为’n’, ‘ne’, ‘e’, ‘se’, ‘s’, ‘sw’, ‘w’, ‘nw’; ‘e’、‘w’、‘s’、'n’分别表示东西南北。 # width height 设置显示区的宽高 # 这里我们将显示区的宽和高设置为40和10,anchor为'se' # 最终的显示效果是 hello在显示区的东南方,也就是右下角; # 另外宽和高的单位不是像素,而是字符.例如,显示区的宽度为40个字符的宽度 label1 = Label(main_win, width=40, height=10, bg='white', text='hello', anchor='se') label1.pack() foreground\fg 指定文本显示颜色 # fg 将前景色设置成红色, 即设置文本的颜色为红色 # 同时将anchor设置成'ne', 将文本显示在东北方,也就是右上角 label1 = Label(main_win, width=40, height=10, fg='red', bg='white', text='hello', anchor='ne') label1.

intouch与PLC之间通讯状态监测和设置

intouch与PLC进行通讯状态监测中,一般做法需要PLC来实施主动脉冲计数,或者bool变化来实现。本文通过上位机自带参数设置,实现对intouch通讯状态监视,将画面恢复初始状态,并及时弹窗报警,以达到监视通讯状态的目的。 1.新建I/O离散点 新建I/O离散量,设置访问名为所需监视PLC的访问名。在项目中填写$sys$status,此为系统自带通讯监视点。 2.设置报警处理方法 1.建立触发条件脚本 设置条件触发脚本,当新建的离散点status为0时触发 2.画面恢复初始化 利用系统自带函数:IOReinitAccessName("AccessName",1)将当前intouch画面恢复初始化 3.赋值弹窗 编写调用窗体赋值脚本,弹出公共弹窗报警即可。

LereDiary-Lere日记

LereDiary 一款开源的Android日记软件-An open source Android diary software 简介 这是一款简单的安卓日记软件,目前它已经实现了一个日记软件应该具有的大部分基础功能,包括基本的富文本编辑,封面图片的选择,展示界面等等。当然,由于是刚刚着手制作的缘故,许多功能还有待实现,并且有诸多可以优化的内容。 简言之,这个作品只是个人练习之作,所以难免在很多方面仍有欠缺和不足,如果您有任何好的意见或建议,都可以通过以下方式联系到我: 个人网站:ywrby.cn腾讯QQ:2491757717GitHub:https://github.com/Ywrby/LereDiaryGitee:https://gitee.com/ywrby/LereDiary 软件预览 主页面(卡片模式) 由于项目刚刚开始着手,主页面的诸多功能还没有具体实现,目前仅实现了基本的编辑/重编辑功能以及长按删除功能,预览功能 日记展示页面 日记编辑页面 日记编辑页面的功能基本实现,不足之处在于使用的百度语音识别仅支持短句识别。其余功能日期,时间,天气的选择,富文本框,清空文本等功能基本实现。出于美观,界面统一的考量,没有设置插入图片功能,取而代之的是设置日记封面功能 主页面(简单模式) 侧边栏(功能尚未实现) 更新情况 日期版本更新情况2020/6/29Fourth commit添加主页每日提醒功能,优化代码结构 尾记 作者本人是CS专业大一在读学生,Lere日记的初衷完全是作为个人练习所用,所以难免有不足之处,如果您有其他宝贵的建议,期待您的留言

备忘 vscod连接远程服务器

默认已有环境 安装有vscode安装有 git vscode远程连接服务器需要用到ssh, 如果是win7请把git安装目录下的 bin 目录加入环境变量PATH中,win10自带ssh服务, 如果win10 连接失败,请在 设置->应用和功能->管理可选功能 选项里是否安装有ssh服务,如果没有 点击添加功能 安装 openSSH服务 vscode安装插件 在扩展中搜索 Remote-SSH插件并安装ctrl+shift+p 搜索 Remote-SSH ctrl+shift+p 打开搜索功能,搜索 Remote-SSH 然后按如下选择: 打开ssh config 文件然后 输入远程服务器的ip 用户名 端口 此时打开远程连接选项 选择你起的别名服务器, 右键选择连接服务器,在控制台输入密码 ,初次连接服务器 选择连接服务器的类型, 我选择的是bash 如果连接不成功, 请仔细查看 TERMINAL栏 中 OUTPUT 错误提示, 此时你只能见招拆招了

iOS:RunLoop的简单应用

RunLoop的简单应用 - (void)runLoopAddDependance{ self.runLoopThreadDidFinishFlag = NO; NSLog(@"Start a New Run Loop Thread"); NSThread *runLoopThread = [[NSThread alloc] initWithTarget:self selector:@selector(handleRunLoopThreadTask) object:nil]; [runLoopThread start]; NSLog(@"Exit handleRunLoopThreadButtonTouchUpInside"); dispatch_async(dispatch_get_global_queue(0, 0), ^{ while (!self.runLoopThreadDidFinishFlag) { self.myThread = [NSThread currentThread]; NSLog(@"Begin RunLoop"); NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; NSPort *myPort = [NSPort port]; [runLoop addPort:myPort forMode:NSDefaultRunLoopMode]; [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; NSLog(@"End RunLoop"); [self.myThread cancel]; self.myThread = nil; } }); } - (void)handleRunLoopThreadTask { NSLog(@"Enter Run Loop Thread"

每日一题Day04 顺序表逆序

基于顺序存储结构的图书信息表的逆序存储 题目描述 定义一个包含图书信息(书号、书名、价格)的顺序表,读入相应的图书数据来完成图书信息表的创建,然后将读入的图书信息逆序存储,逐行输出逆序存储后每本图书的信息。 输入描述 输入n+1 行,第一行是图书数目n,后n 行是n 本图书的信息(书号、书名、价格),每本图书信息占一行,书号、书名、价格用空格分隔,价格之后没有空格。其中书号和书名为字符串类型,价格为浮点数类型。 输出描述 总计n 行,第i 行是原有图书表中第n-i+1 行的图书的信息(书号、书名、价格),每本图书信息占一行,书号、书名、价格用空格分隔。其中价格输出保留两位小数。 样例输入 6 9787302257646 程序设计基础 25.00 9787302164340 程序设计基础(第2版) 20.00 9787302219972 单片机技术及应用 32.00 9787302203513 单片机原理与应用技术 26.00 9787810827430 工业计算机控制技术——原理与应用 29.00 9787811234923 汇编语言程序设计教程 21.00 样例输出 9787811234923 汇编语言程序设计教程 21.00 9787810827430 工业计算机控制技术——原理与应用 29.00 9787302203513 单片机原理与应用技术 26.00 9787302219972 单片机技术及应用 32.00 9787302164340 程序设计基础(第2版) 20.00 9787302257646 程序设计基础 25.00 /** * main函数返回值不能为void,否则会汇编出错,请使用int main(),并在最后return 0。 * 虽然VC等windows下的编译器支持,但C/C++标准中不允许使用void main()! */ #include<stdio.h> #include<stdlib.h> typedef struct Book { long long int num; char name[50]; double price; } Book; int main() { int i,j,n; scanf("

空间金字塔思想在图像处理中的应用:SPP,PPM、ASPP和FPN结构理解和总结

图像空间金字塔思想在图像处理中被广泛应用,本文主要针对具体的 SPP ,PPM,ASPP和 FPN 结构,以及传统图像处理的SIFT等进行简单的介绍和总结。 欢迎各位进行交流学习。【人肉整理,转载请注明出处】 文章目录 1 综述1.1 SPP结构(Spatial Pyramid Pooling)1.2 PPM结构(Pyramid Pooling Module)1.3 ASPP结构(Atrous Spatial Pyramid Pooling)1.4 FPN结构(Feature Pyramid Networks for Object Detection) 2 总结 1 综述 SPP论文链接: Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition pspNet论文链接: Pyramid Scene Parsing Network ASPP论文链接(此处已deeplab v3为例): deeplab v3(2017年):Rethinking Atrous Convolution for Semantic Image Segmentation deeplab v3+(2018年):Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation FPN论文连接: Feature Pyramid Networks for Object Detection

nodemon一款给热爱技术的开发者定制的热更新软件

nodemon是开发环境中启动node服务的一款工具 当我们每次修改node文件需要测试的时候都需要node app.js重新启动,非常耗时,编辑器又需要配置,也是不太方便 这款工具可以检测你的报错操作然后执行对应的命令 安装方式: npm install -g nodemon mac 或者Linux使用 sudo npm install -g nodemon -g为把工具安装到全局变量中,这样可以在任意位置直接调用 在项目目录中创建 nodemon.js 文件 ,文件内容如下 { "ignore": [ "**/*.test.ts", "**/*.spec.ts", ".git", "node_modules" ], "watch": [ "src", ], "exec": "npm start", "ext": "ts" } ignore 忽略监听的文件 watch:[ ] 需要监听的文件目录,多个用逗号隔开 exec :为当你监听的目录中文件发送变更执行的命令 ext: 扩展名 启动方式,进入项目目录 nodemon

我用Python展示Excel中常用的20个操作

前言 Excel与Python都是数据分析中常用的工具,本文将使用动态图(Excel)+代码(Python)的方式来演示这两种工具是如何实现数据的读取、生成、计算、修改、统计、抽样、查找、可视化、存储等数据处理中的常用操作! 数据读取 说明:读取本地Excel数据 Excel Excel读取本地数据需要打开目标文件夹选中该文件并打开 Pandas Pandas支持读取本地Excel、txt文件,也支持从网页直接读取表格数据,只用一行代码即可,例如读取上述本地Excel数据可以使用pd.read_excel("示例数据.xlsx") 数据生成 说明:生成指定格式/数量的数据 Excel 以生成10*2的0—1均匀分布随机数矩阵为例,在Excel中需要使用rand()函数生成随机数,并手动拉取指定范围 Pandas 在Pandas中可以结合NumPy生成由指定随机数(均匀分布、正态分布等)生成的矩阵,例如同样生成10*2的0—1均匀分布随机数矩阵为,使用一行代码即可:pd.DataFrame(np.random.rand(10,2)) 数据存储 说明:将表格中的数据存储至本地 Excel 在Excel中需要点击保存并设置格式/文件名 Pandas 在Pandas中可以使用pd.to_excel("filename.xlsx")来将当前工作表格保存至当前目录下,当然也可以使用to_csv保存为csv等其他格式,也可以使用绝对路径来指定保存位置 数据筛选 说明:按照指定要求筛选数据 Excel 使用我们之前的示例数据,在Excel中筛选出薪资大于5000的数据步骤如下 Pandas 在Pandas中,可直接对数据框进行条件筛选,例如同样进行单个条件(薪资大于5000)的筛选可以使用df[df['薪资水平']>5000],如果使用多个条件的筛选只需要使用&(并)与|(或)操作符实现 数据插入 说明:在指定位置插入指定数据 Excel 在Excel中我们可以将光标放在指定位置并右键增加一行/列,当然也可以在添加时对数据进行一些计算,比如我们就可以使用IF函数(=IF(G2>10000,"高","低")),将薪资大于10000的设为高,低于10000的设为低,添加一列在最后 Pandas 在pandas中,如果不借助自定义函数的话,我们可以使用cut方法来实现同样操作 bins = [0,10000,max(df['薪资水平'])] group_names = ['低','高'] df['new_col'] = pd.cut(df['薪资水平'], bins, labels=group_names) 数据删除 说明:删除指定行/列/单元格 Excel 在Excel删除数据十分简单,找到需要删除的数据右键删除即可,比如删除刚刚生成的最后一列 Pandas 在pandas中删除数据也很简单,比如删除最后一列使用del df['new_col']即可 数据排序 说明:按照指定要求对数据排序 Excel 在Excel中可以点击排序按钮进行排序,例如将示例数据按照薪资从高到低进行排序可以按照下面的步骤进行 Pandas 在pandas中可以使用sort_values进行排序,使用ascending来控制升降序,例如将示例数据按照薪资从高到低进行排序可以使用df.sort_values("薪资水平",ascending=False,inplace=True) 缺失值处理 说明:对缺失值(空值)按照指定要求处理 Excel 在Excel中可以按照查找—>定位条件—>空值来快速定位数据中的空值,接着可以自己定义缺失值的填充方式,比如将缺失值用上一个数据进行填充 Pandas 在pandas中可以使用data.isnull().sum()来检查缺失值,之后可以使用多种方法来填充或者删除缺失值,比如我们可以使用df = df.fillna(axis=0,method='ffill')来横向/纵向用缺失值前面的值替换缺失值 数据去重 说明:对重复值按照指定要求处理 Excel 在Excel中可以通过点击数据—>删除重复值按钮并选择需要去重的列即可,例如对示例数据按照创建时间列进行去重,可以发现去掉了196 个重复值,保留了 629 个唯一值。

CSS图片img标签根据宽度或高度相互自适应

实现效果:img标签,限制图片的高度或宽度,当高度或宽度达到限制时,未达到限制的边不改变图片的比例自适应缩放; 代码实例:这里贴出基于vue的完整的html文件,直接看样式在底部style标签内 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"> <!-- 引入样式 --> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> </head> <body> <div id="app"> <el-container class="container"> <el-header> <h4>{{ message }}</h4> </el-header> <el-main> <el-row :gutter="20"> <el-col :sm="24" :md="20"> <div class="grid-content"> <div><h4>欢迎使用 Element</h4></div> <div> <div>文本</div> <div class="centent-img"> <img src="http://a1.att.hudong.com/05/00/01300000194285122188000535877.jpg"> </div> <div class="centent-img"> <img src="http://img50.photophoto.cn/20190123/0008118076305063_s.jpg"> </div> <div class="centent-img"> <img src="http://t9.baidu.com/it/u=3363001160,1163944807&fm=79&app=86&f=JPEG?w=1280&h=830"> </div> </div> </div> </el-col> <el-col :sm="24" :md="4"> <div class="grid-content bg-purple"> <el-button @click="visible = true"

获取省市区geoJson数据(精确到县、镇)用于echarts实现地图数据可视化

写在前面 本文着重介绍关于获取数据的部分,如果数据处理好了,不会使用echarts将地图绘制出来,可以参考echarts的官方文档,或去搜寻大佬们的教程,或者另外问我,我再写一份我自己理解的关于echarts绘制地图的使用。 本文前半部分实现的效果很多软件都可以实现,但精确不到县级市的子区域也就是镇级。因此如果有镇级需求的可以直接拉到后半部分。 先看效果: 熟悉echarts的看到这个图之后,都想到了什么?没错,就是官方示例里的香港18区人口密度图: 从官方示例代码我们可以看到,生成图中各区域地图的,就是引入的这个json文件: 那么,如果我们想要生成自己想要的地区地图,只要拿到相应地区的json文件就可以了。这个文件里面主要是什么内容呢?把这个文件地址打出来打开它,我们可以看到,它是geoJson格式的: (这里补一下GeoJson的百科链接,第一次接触的小伙伴可以了解一下:百度百科 - geoJson) 因此,我们如果能拿到自己需要的区域的geoJson数据,引入之后就可以生成对应的地图区域了。那么,这样的数据从哪里来呢? 这里推荐一个比较好用的网站:地图选择器 打开之后是这样子的: 其中,左上角的输入框可以输入选择自己想要的地区: 也可以将鼠标悬停在右边的地图上,会浮现出当前停在的城市名称及区域编码(adcode)和级别(province): 双击后可以打开它的子级地图,如本文上张图选择的是江苏省,双击后打开的就是江苏省的地图: 这样利用搜索后,或者用地图逐级选取,即可选到自己想要的地区。地区选好之后,可以利用下图标注的方法获取数据: 标号①处是该json文件的地址,直接用就可以,注意,它是不带子区域的,而标号②是包含子区域的。可以使用标号③处的勾选来切换。区别在于如果不选用包含子区域,生成的地图是没有子区域分割的,如下图: 标号④是整个文件的内容,可以直接拷贝使用。注意上面的切换是否包含子区域按钮会影响到这里面的数据,在使用的时候要注意自己的需求。 最后标号⑤的两个按钮可以下载geoJson格式数据,或svg格式图片,如果只是想用这个地区形状也是没问题的。 到这一步为止,除了上述介绍的这个网站,运用其他比如百度地图、高德地图,谷歌地图等各种地图软件,都是可以拿到上述数据的,但如果我们想要一些县级市的数据,比如常熟,你会发现它是这样子的: 注意到了吗?没错,它是没有子区域的。这里并不是我没有勾选包含子区域那个选项,而是它只到这一级为止。不只是这个网站只到这一级,很多地图软件能拿到的数据也都只到这一级。那么,如何才能拿到它子区域的数据,从而生成本文开篇的那张图的效果呢? 这里先推荐一个网站:geojson.io,打开可能有点慢。 这个网站打开之后是这样子的: 左边是地图,右边是对应你选中区域的geojson数据。图中因为还没有选择区域,所以右边是空的。 点开左上角的open,可以导入你需要的文件。格式很多,本文接下来的例子使用的是kml格式的文件,其他格式请自行研究,本文不再进行扩展。 这个网站还可以自己去绘制路径,相关功能也不在本文展开了。 这里先补上kml的百度百科:百度百科 - kml 百科里也介绍了,可以使用google earth来创建kml文件,但我还不太会用,所以我这里使用的是bigMap。这个软件如果要下载地图要正版授权(似乎可以免费授权),但如果只是用导出选择区域kml文件功能是不需要授权的,可以直接免费使用。当然这里还是建议大家使用正版授权(本文关于该软件的内容如果涉及到权益问题请联系我进行删除)。 下载安装之后打开,可以在右上角进行区域的选择,可以发现,它是精确到镇级的: 这里不要点击左边的下载按钮,请选择图中红框选中的按钮,即可保存kml文件。这个里面的数据就是你选择的区域,可以在地图上看到效果: 把导出的kml文件导入到刚才的geojson.io网站,就变成了下图这样(和上图不一样是因为我上面选择的是虞山镇,这里选的是我导出的碧溪街道的kml文件,不影响理解): 可以看到,左边就是你导入文件选择的数据区域,右边则是自动生成的geojson数据。 这样就完成了常熟市其中一部分区域的绘制。接下来只要把所有区域选择,生成kml文件导出,再导入到这个网站,像拼拼图一样拼起来就可以了。这边open也是可以打开多个文件的,虽然不支持一次性选择多个,但一个一个选择打开也不影响。 这里只拼一部分,不全部拼了,大家按自己需要使用就可以了。 全部导入拼好之后,全选右边的数据,新建一个.json文件,拷贝进去保存,这样引用的时候就可以正常使用了。 总结一下 本文在实现这个需求的时候没有发现可以直接获取镇级子区域geojson数据的网站或软件,因此使用了这种折中的办法,利用拼接还原整个区域,如果大家有更好的方法拿到镇级子区域geojson数据,请在评论指正,不胜感激! 那么归根结底,想要实现地图数据可视化,一定要有相关区域的geojson格式数据的支持,难点就在于过于精确的区域数据并不是很好获取,需要寻找借用各种软件。本人在研究这个需求实现的过程中也尝试了各种网站和软件,效果都不是很理想,大部分都只能精确到县级市,因此在这里将我最终的实现方法记录分享,欢迎各位大佬一起讨论研究。 注意 后续测试发现用这种方法合成张家港市子区域的地图时,地图无法显示出来,我把张家港市各子级geojson数据一个一个单独格式化之后发现,张家港市经济开发区的结构和张家港市其他区域或者比如常熟市的有区别: 常熟: 张家港(经济技术开发区): 可以看到,是多了一层的。暂时不知道这多出来的一层是什么原因,但如果将这一层去掉,变成像常熟市那样的结构或者张家港市其他子区域的结构,那张家港市的也可以全部正常显示了。所以推测echarts的源码在进行处理的时候并没有考虑到这个情况,只是直接去读指定字段里的内容,如果报错就整个挂了。并且这个现象只出现在张家港市经济开发区,如果在拼张家港市地图的时候不拼这个区域,只拼其他的比如杨舍镇,整体结构和常熟之类的是完全一样的,也能正常显示,所以就是在拼这个经济开发区的时候给整个多加了一层,导致出了问题,我又尝试了其他如镇江等地区,都没有发现这个现象。目前暂时未发现其他地区的数据结构和这个一样,大家在使用时要注意一下,如果发现了也可以在评论记录一下。 那么上述问题的解决办法就是把经济开发区这多出来的一层去掉,再去拼他就不会给整体加这一层了。目前还未发现去掉这一层有什么影响,等待后续再进行研究。 题外话 有的小伙伴这样处理好数据,在使用echarts时,会发现地图显示不出来,报错如下: 可以根据报错得知,这是引入本地资源时跨域了。CORS 策略只支持http、data、 chrome、chrome-extension 以及 https。那么如果直接双击打开使用 file 协议的html 文件,就不受浏览器 CORS 支持了。 这里可以使用前端应用启动服务anywhere来解决这个问题。它可以将当前目录变成一个静态文件服务器,能像资源管理器一样可视化预览目录下的一切文件,并且支持http 和 https协议。 首先使用命令npm i anywhere -g全局安装,然后直接在控制台输入anywhere即可正常使用了。 如果报错npm 不是内部或外部命令,说明你还没有安装node.js。先去安装吧,这里就不展开了。

每日一题Day01 顺序表创建

基于顺序存储结构的图书信息表的创建和输出 描述 定义一个包含图书信息(书号、书名、价格)的顺序表,读入相应的图书数据来完成图书信息表的创建,然后统计图书表中的图书个数,同时逐行输出每本图书的信息。 输入 输入n+1行,其中前n行是n本图书的信息(书号、书名、价格),每本图书信息占一行,书号、书名、价格用空格分隔,价格之后没有空格。 最后第n+1行是输入结束标志:0 0 0(空格分隔的三个0)。 其中书号和书名为字符串类型,价格为浮点数类型。 输出 总计n+1行,第1行是所创建的图书表中的图书个数,后n行是n本图书的信息(书号、书名、价格),每本图书信息占一行,书号、书名、价格用空格分隔。其中价格输出保留两位小数。 样例输入1 9787302257646 程序设计基础 25.00 9787302164340 程序设计基础(第2版) 20.00 9787302219972 单片机技术及应用 32.00 9787302203513 单片机原理与应用技术 26.00 9787810827430 工业计算机控制技术——原理与应用 29.00 9787811234923 汇编语言程序设计教程 21.00 0 0 0 样例输出1 6 9787302257646 程序设计基础 25.00 9787302164340 程序设计基础(第2版) 20.00 9787302219972 单片机技术及应用 32.00 9787302203513 单片机原理与应用技术 26.00 9787810827430 工业计算机控制技术——原理与应用 29.00 9787811234923 汇编语言程序设计教程 21.00 解答:开辟一段结构体数组空间,将图书信息长度保存于第一个结点。输入图书信息,同时统计结点个数。 /** * main函数返回值不能为void,否则会汇编出错,请使用int main(),并在最后return 0。 * 虽然VC等windows下的编译器支持,但C/C++标准中不允许使用void main()! */ #include<stdio.h> #include<stdlib.h> #define maxn 1000 typedef struct node { long long int num; char name[50]; double price; } Book; int main() { Book *book; book=(Book *)malloc(maxn*sizeof(Book)); book[0].

用JAVA编程实现斗地主小游戏(建牌,发牌,选地主,排序)

JAVA编程实现斗地主小游戏 主程序排序算法 主程序 public static void main(String[] args) { //牌 List<String> pokes = new ArrayList<>(); //颜色花色 List<String> colors = new ArrayList<>(); //数量 List<String> nums = new ArrayList<>(); colors.add("♥"); colors.add("♠"); colors.add("♦"); colors.add("♣"); nums.add("A"); for (int i=2; i<=10; i++){ nums.add(i+""); } nums.add("J"); nums.add("Q"); nums.add("K"); for (String c:colors){ for (String n:nums){ String pai = c+n; pokes.add(pai); } } pokes.add("大王"); pokes.add("小王"); // System.out.println(pokes); // System.out.println(pokes.size()); Collections.shuffle(pokes); System.out.println(pokes); //玩家 //发牌,留三张 ArrayList<String> smj = new ArrayList<>(); ArrayList<String> whb = new ArrayList<>(); ArrayList<String> zk = new ArrayList<>(); ArrayList<String> bottom = new ArrayList<>(); for (int i = 0; i < pokes.

读源码学MYSQL系列(二)decimal存储转化函数decimal2bin

问题来源 高精度计算是计算机工程实践中非常重要的内容,在涉及到精确计算的项目中,思考过数据库的设计。因而比较好奇MYSQL中是如何实现对decimal的支持的。本文通过源码阅读,分析理解decimal的存储及各种运算转化。参考源代码: https://github.com/google/mysql/blob/master/include/decimal.h https://github.com/twitter-forks/mysql/blob/master/strings/decimal.c 基础准备 首先,在头文件decimal.h中定义了基本结构体和类型: typedef int32 decimal_digit_t; MYSQL采取4字节为一组来存储高精度小数,可以存储9位十进制数字。不足9位部分仍然使用4字节存储。 typedef struct st_decimal_t { int intg, frac, len; my_bool sign; decimal_digit_t *buf; } decimal_t; 其中,各个字段含义如下: intg: 整数,十进制整数部分位数 frac: 整数,十进制小数部分位数 sign: 布尔,false表示正数,true表示负数 buf: int32类型数组,每个int32存储9位十进制数字 len: 数组buf的长度 还有一些其他的宏定义如下: typedef decimal_digit_t dec1; typedef longlong dec2; #define DIG_PER_DEC1 9 #define DIG_MASK 100000000 #define DIG_BASE 1000000000 #define DIG_MAX (DIG_BASE-1) #define DIG_BASE2 ((dec2)DIG_BASE * (dec2)DIG_BASE) #define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1) static const dec1 powers10[DIG_PER_DEC1+1]={ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; static const int dig2bytes[DIG_PER_DEC1+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4}; static const dec1 frac_max[DIG_PER_DEC1-1]={ 900000000, 990000000, 999000000, 999900000, 999990000, 999999000, 999999900, 999999990 }; 存储转化函数decimal2bin 该函数将decimal_t类型的结构体转化为二进制形式。下面结合源代码说明,为了便于理解,将整个函数按照功能顺序拆分成几个模块分析。

【数据处理】数据集划分、打乱(shuffle)、以及keras里K-折交叉验证

前言 在进行机器学习的时候,本质上都是在训练模型,而训练模型都离不开对数据集的处理。往往在模型表现不佳或难以再提升的情况下,进行一定的处理,科学的训练会使模型再更进一步。 目录 前言1 数据集划分1.1 常规理解1.2 自己理解 2 打乱(shuffle)2.1 numpy里的shuffle2.2 keras里的shuffle2.3 sklearn里的shuffle ★2.4 代码(2.1和2.3两种) 3 keras里进行K-折交叉验证3.1 K-折交叉验证3.2 keras模型实现K折交叉验证3.3 完整代码 1 数据集划分 1.1 常规理解 这是老生常谈的问题,但理论和实践还是会有偏差。理论上,数据集可划分为三类,训练集、验证集和测试集。引用cnn网络为什么有时验证集会和训练集一起参与训练?的一个理解,这三者的关系就如同刷题、模拟考和高考。刷题不能刷到模拟考题目,那模拟考直接起飞,高考题目不准看,看了考的分数就是假分数。 下面开始盗图,参考训练集、验证集、测试集划分,从图中可以看出各部分之间的关系,其中训练集和测试集是大家经常听到的,而验证集在图中归属于训练集,这也是导致验证集和测试集经常混淆的点。 参考中还给了不同数据集大小的情况下划分比例。 1.2 自己理解 自己其实在之前的博客中也经常搞混,现在来说下自己的理解,不一定正确。其实我认为,在写论文、打比赛的时候,我们主要划分的还是训练集与验证集,测试集不属于考虑范围,或者认为测试集和验证集是一个东西。以打比赛为例,我们拿到了比赛的数据集,然后自己进行了数据集划分,对于模型训练来说,数据量一般越多越好,所以我们是划分训练集与验证集,在验证集效果较好时,再把验证集也拿去训练。那测试集呢?测试集其实是比赛官方拿出一部分数据集出来,用它来评估你的模型。因此对于比赛选手来说,专门拿出测试集来仅进行测试是不利的,而一旦测试完又拿去训练,那就变成验证集了。所以,我认为只有真正在工业环境下,才需要进行严格的划分。 2 打乱(shuffle) 既然有数据集的划分,那么就少不了随机打乱。因为原本的数据集有可能是有序的,如果正例集中在前面,负例集中在后面,那么便会导致验证集或测试集会出现大部分是负例的情况。很有可能导致负例训练效果不佳,模型整体性能变差。此外,就算不是有序的,打乱也会显得更为“公平”,也给模型提升多一份机会。(即随机划分出的某个数据集可能更能代表整体数据(包括未收集到的数据))。 那么接下来介绍shuffle的几种方式:numpy shuffle、keras fit里的shuffle以及sklearn shuffle。 当你的数据集比较简单的时候,如特征与标签在一个numpy矩阵中,那么可以直接选用numpy里的shuffle。以鸢尾花数据集为例,该数据集本身是有序的,部分数据如下所示。 2.1 numpy里的shuffle 该方法适合简单的矩阵,且特征和标签未分开。如果是分开的,还要先合并再拆开。 # In[*] shuffle in numpy def shuffle_np(X,Y): Y = Y.reshape(len(Y),1) data = np.concatenate([X,Y],axis=-1) np.random.seed(1337) np.random.shuffle(data) print(data) X = data[:,:-1] Y = data[:,-1] return X,Y 部分效果。 2.2 keras里的shuffle 可参考Keras model.fit()参数详解,要注意这里的shuffle的解释是:

R的randomForestSRC包做生存分析(用随机生存森林做生存分析)

用R的randomForestSRC包做生存分析 用randomForestSRC做生存分析导入randomForestSRC包准备生存分析的数据构建模型,进行生存分析绘图 用randomForestSRC做生存分析 导入randomForestSRC包 在R中的实现如如下图所示 准备生存分析的数据 在R中的实现如下图所示 在上图中,data_express即是我们要进行生存分析的数据,数据共有411个样本。 构建模型,进行生存分析 在R中的实现如下图所示 绘图 在R中的实现如下图所示 绘图结果如下

用cookie保存并读取用户登录信息(简易)

准备工作 首先建立两个jsp页面 一个命名为index.jsp 另一个命名为deal.jsp 要实现的目标 在index.jsp中输入用户账户和密码,然后进入到deal.jsp中 如果没有来过或者超过cookie保存时间,就需要输入账户和密码,反之则提示欢迎xxx,并只需要输入密码 如果密码错误能提示输入错误 代码实现 这是index.jsp <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@page import="java.net.URLDecoder" %> <!DOCTYPE html> <html> <meta http-equiv="Content-Type" content="text/html;charset=ISO-8850-1"> <head> <meta charset="ISO-8859-1"> <title>First Java Web Application</title> </head> <body> <% Cookie[] cookies=request.getCookies(); String account=""; if(cookies!=null){ int i; for(i=0;i<cookies.length;i++){ if(cookies[i].getName().equals("acCookie")){//deal界面设置的cookie名为acCookie String cookieValue=cookies[i].getValue(); String accountinfo[]=cookieValue.split("#");//拆分字符串 account=URLDecoder.decode(accountinfo[0]); } } } if("".equals(account)){ %> <p>Please input your account</p> <form action="deal.jsp" method="post"> account&ensp;&thinsp;:<input name="account" type="text" value=""> <br>password:<input name="password" type="text" value=""> <input type="

毕业设计--2020.02.18 奇耘4.2寸墨水屏的程序设计思路分享

毕设中我使用了奇耘的4.2寸墨水屏,官方的范例代码给出了一些局部刷新的例子,但是我认为官方给的代码太过于简单实现的功能也不是我想要的,所以对先有的官方的代码进行了一些改进,让这一套代码更适合于我自己的毕业设计。 以下的只有程序思路, 程序还没有完全的完善,就不放出来 误导别人了(代码太烂了)。而且作为毕业设计的一部分 至少要等我毕业了再开源 首先先分享一下这块屏幕的特性 这款屏幕的分辨率是400*300 的 DPI是120 看起来颗粒感还行不是那么的强烈。 屏幕的刷新方式定义成这样, 我用的是侧方向用的屏幕 屏幕的方向设置貌似比较麻烦,我也没太过深入的了解,参数都是一个个实验找到的、、、、、 这是我的屏幕的方位定义,我的程序的逻辑是这样的 第一 整个显示得数据都是在内存中保存的,我在内存中开辟了一个15000(300*400/8)byte的数组,这个数组用于保存各个点的bit信息,在进行 字符显示的时候我就向指定的内存地址写入新的数据,然后执行全屏刷新操作(这里是针对全屏刷新) 当进行局部刷新的时候,我们的墨水屏驱动器需要我们输入以前的数据然后再输入最新的数据以此来达到局部刷新的目的。 (我猜测是需要前后的数据去进行对比,决定翻转哪一些墨水颗粒) 在这种背景下,我设计了两个函数 这两个函数的作用很简单,就是设置一个点的 bit值到指定的位置或者是获取一个点的bit值(这里提一嘴,这个算法肯定有更优化的办法,比如一次操作8个bit 但是我为了减少逻辑复杂度就直接采用了这个笨的办法,一次只读或者写一个bit ),这两个函数就是整个系统的一个对外的接口,我们可以很轻易的把以前的 OLED显示函数迁移过来(其实我就是这么干的),一次只设置一个点的值 通过这样的操作 我可以很简单的写出我自己的墨水屏相关的显示函数,毕竟各种字符 图片本质都是一个个点阵。 相比较于OLED的程序而言,墨水屏的程序上面添加了一个全局刷新和局部刷新的概念, 而又因为局部刷新我需要向墨水屏的驱动芯片提供先前的显示内容所以操作有有了一点点的不同 这一部分我的操作是这样的 : 第一步: 声明一个数组 然后将你要修改的区域 的数据读到一个数组(p_Before[xxx])里面去(数据其实是保存在内部的内存 数组中, 就是数据从数组搬到另一个数组) 这里用到get point 函数 而且为了程序尽可能简单 我还对 Y坐标进行了 对8取整 , 然后修改显示内容,这一步还是set point函数, 使用Set_point() 函数 我们直接对内部的显存进行修改, 然后再次调用 EPD_COPY_AREA() 这个函数,将最新的数据数组提取出来 ;然后 设置好参数 主要是刷新的区域的起始点坐标 然后就是 两次提取出来的数组的信息 void EPD_partial_display(u16 x_start,u16 x_end,u16 y_start,u16 y_end ,const unsigned char *old_data,const unsigned char *new_data,unsigned char mode)

以高通camera 申请ion内存看dma-buf

1 fd 与ion buffer, file绑定 简单总结就是申请一个buffer,再创建一个dmabuf 结构体然后将,然后将dmabuf中得指针指向buffer,dmabuf 再传递给一个匿名的inode,获取到一个file,这样file和dmabuf绑定起来,也就和buffer关联上。然后再从进程中分配一个空闲的fd,将fd 和file囊绑定。这样就能通过fd 快速查找到buffer。file 是个全系统的,他和进程无关,但是fd 是每个进程都是自己独立的,所以再跨进程传输时只需要保证fd 和同一个file绑定就可以实现buffer的共享。 高通camera 申请ion buffer 并且smmu 映射是在cam_mem_mgr_alloc_and_map 函数种。 cam_mem_mgr_alloc_and_map->cam_mem_util_ion_alloc cam_mem_util_ion_alloc 函数会返回dma-buf 和fd。确定分配得buffer 大小, 从哪个heap种分配,ion有很多heap。会调用 cam_mem_util_get_dma_buf_fd。 cam_mem_mgr_alloc_and_map->cam_mem_util_ion_alloc->cam_mem_util_get_dma_buf_fd static int cam_mem_util_get_dma_buf_fd(size_t len, size_t align, unsigned int heap_id_mask, unsigned int flags, struct dma_buf **buf, int *fd) { struct dma_buf *dmabuf = NULL; int rc = 0; if (!buf || !fd) { CAM_ERR(CAM_MEM, "Invalid params, buf=%pK, fd=%pK", buf, fd); return -EINVAL; } // 分配一个buffer 并且将buffer 与dma-buf 结构体绑定 *buf = ion_alloc(len, heap_id_mask, flags); if (IS_ERR_OR_NULL(*buf)) return -ENOMEM; /* 从当前进程种分配一个空闲得fd,注意这里是从进程得到fd,fd 关联得file file却不是 *属于进程的,所以不能close 就万事大吉。close 是将fd重新放入进程得空闲数组种,file *得索引值只是减1.