Jquery combobox实现二级级联效果。
最近在通过js中的拼接实现input和select的下拉框级联效果,功夫不负有心人终于可以分享一下自己的劳动成果了。
很简单的应用,如果使用服务器下拉框控件,添加几个事件,相信能够轻松的解决,但是现在所有的操作都是在js中进行的。
如代码所示,仅仅通过input和select拼接来实现级联功能,确实增加了很大的难度。
<select οnchange='return getValue(this.value," + i + ")' id='SOilCorpName" + i + "'>" + SetOilName(ListContent[i].SOilCorpName) + "</select><input id='SRefineFactoryName" + i + "' readonly value='" + ListContent[i].SRefineFactoryName + "' /> 曾经这么想过,在select中添加onchange事件,然后触发事件,将参数传到后台,根据参数查询出结果,绑定到input域中,但是从js中怎么来触发后台事件,曾经想过用ajax来实现,但是相对来说太复杂了。
最后采用的是,将被级联的数据全部加载出来,然后传到前台,在js中接受,在onchange事件中与下拉点击的参数进行对比。
function getValue(result, i) { var opt1 = '<%= FactoryNamelist%>' var ListOpt = new Array(); var optionList = opt1.split(';'); if (optionList != "") { for (var j = 0; j < optionList.length; j++) { var optionListItem = optionList[j].
将两个递增的有序链表合并为一个递增的有序链表。要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中不允许有重复的数据。
#include<stdio.h> #include<malloc.h> typedef struct list { int data; struct list * next; //下一个节点地址 }list; //第一条链表 struct list * L=NULL;//头 struct list * head=NULL;//首 struct list * p=NULL; //第二条链表 struct list * L1=NULL;//头 struct list * head1=NULL;//首 struct list * p1=NULL; //代理链表 struct list * L2=NULL;//头 struct list * q=NULL;//L2备用地址 struct list * q1=NULL;//备用地址 int main(){ int i=0,length; printf("请输入链表的长度\n"); scanf("%d",&length); head=(struct list *)malloc(sizeof(struct list)); L=head; printf("请依次输入链表的内容\n"); for(i;i<length;i++){ p = (struct list *)malloc(sizeof(struct list)); scanf("
1、 使用Java输出json格式的实体数组(UserAction)
public class User { private String id; private String account;// 账号 private String psw;// 密码 private String name;// 姓名 private String sex;// 姓名 private String phone;// 电话 private Integer type;// 类型 1.管理员 2.饭店管理员 3.普通用户 } public class UserAction extends BaseAction<User> { public void f_ajax_list() { List<User> user_list = userService.findAll(); jsonWrite(user_list, new String[] { "account", "id", "type" }); } } - 其中String数组中的字段是不需要转化成json的字段 2、Html Ajax 访问数据接口-显示数据(http://服务器ip:8080/项目名称/user_f_ajax_list.htm)
<table id='content'></table> <script type="
有时一张导图看上去漂漂亮亮的思维导图让人赞叹不已,可谁知往往这张图的背后却是照着目录拼凑,逻辑性弱的让作者过了很久都回忆不起。
----题记
对于思维导图的绘制,通过这次软考小组内部的交流和讲解,对于如何划分分支、节点之间寻找关系,如何去撒魔术粉有了新的认识,期间对于数据结构、操作系统、软件工程部分的知识进行了画图,结合昨天晚上对计算机硬件的讲解,分享初步导图如下:
这张图是针对“软考一本通”教材来绘制的,重点针对于考试,这样对于我来说思维导图分为两类:No1、知识点编网;No2、应用类思维导图,而上面这张就属于后者,但是依赖于前者存在,下面就对这段时间来对知识网的编织学习进行如下总结:
知识网导图和应用类导图的关系 应用类导图依托于知识网导图存在,二者之间是个普通和特殊,No2是No1的多态的体现,就像上图所示,它应该是我从完整的“计算机系统”导图中提取的一部分,而且站在No1的角度来讲,要知道自己下面有多少张应用类导图,有点像米老师讲过的记忆英文单词,找到根源,这样能做到牵一发而动全身,整个知识点的知识体系以及所有应用全部揪出来。
就像上面那张图所示,针对软考的硬件部分考点有一张“计算机系统”导图,可能针对软件部分、针对公司面试也有对应的一张……这就强调我对最根本那张知识点编网导图要求的重要性。这一点从“数据结构”软考和自考部分画出的导图不一致现象得出,最终反思出这样一个结论,而且用在“计算机硬件”上效果很好。
如何将课本中众多节合理融合到一起,拒绝拼凑 仍然拿“计算机系统硬件”这部分知识举例子,书中的分类如下:
(1)数据的表示
数制转换、四类码、浮点数
(2)计算机系统的组成与体系结构
体系结构分裂、硬件组成、指令基础、CISC与RISC、流水线
(3)存储系统
Cache、主存
(4)可靠性与系统性能评测
可靠性计算、系统性能评价、校验码
从此可以看到(1)(2)(3)(4)这四部分在层次上不属于同一个等级,这样划分仅仅是凸显考点,如果直接这样去学习的话,做题时细节上的问题能够解决,但是在解决问题需要宏观的时候就歇菜了。
仍然举这个例子:(如下图所示)硬件部分找一个分类标准作为突破口,范围最大的可以用硬件组成或者体系结构,但是体系结构往下划分时候找思维的连续性就显得牵强,于是以硬件组成为依据划分,这时候通过(2)这个标准便把(1)和(3)仅仅关联起来,why?
如图所示:硬件组成中的运算器和控制器组成CPU,通过CPU引申出部分(1)中具体的细节知识点(因为数制、指令、流水线都是在CPU中进行的),然而通过存储器又能够引申出存储系统这样又将(3)部分联系在一起,然而可靠性性能分析可以放到计算机系统根目录下和硬件系统齐平,这样整体大框架(两层)导图就建好了,而且关系最强。
这个过程很重要,在画第二层的时候,一定要思量哪种组合关系能够将知识体系以最强的关系体现出来,这样相当于打下了最坚固的地基。
如何在各个分支之间构建关联 地基打好了就该架钢筋浇筑水泥了,如何让钢筋和水泥紧紧地结合在一起是保证房屋稳固的关键,在思维导图中,相同层次之间各个节点之间的关系如何揪出一个就能把所有节点提炼出来,就是这个道理。
仍然看这个例子:
知道了CPU分支下面的“流水线”,怎么能够关联出“数制”和“指令”呢? 如上图所示,在CPU中进行的操作,结合考点,通过一条“数据执行过程”的线串起来,同时又通过一个“操作”的关系和上层节点“CPU”结合在一起,这样子整体和细节就都把握起来了。
这个例子其实还是比较片面,自己总结的一些要点如下:
(1)细节部分要和上一层之间建立好联系。
(2)细节部分之间的节点间的关系要建牢。
(3)重要地方用图标做以标记。
方法:一、套用之前的知识网,比如宏观的计算机硬件中有一项“组成部分”,这里可以直接拿来。二、编织新故事,原则:自己用来编网的故事不要太偏,不要太多,第一年时候那篇(“三分钟”倒背26个英文字母),现在仍然能够脱口而出,只可惜之前没有将此用到计算机编网中。
软考这个过程看来是一个很好的巩固先前知识点的过程,把握好了,以后的学习模式会发生很大的变化。
That is all.
转自:http://www.cnblogs.com/ffhajbq/archive/2012/06/01/2529354.html C++及C中的 string char指针及char数组 C++中string是标准库中一种容器,相当于保存元素类型为char的vector容器(自己理解),这个类提供了相当丰富的函数来完成对字符串操作,以及与C风格字符串之间转换,下面是对string一些总结<引用>
一,C语言的字符串
在C语言里,对字符串的处理一项都是一件比较痛苦的事情,因为通常在实现字符串的操作的时候都会用到最不容易驾驭的类型——指针。
比如下面这个例子:
//example 1:
char str[12] = "Hello";
char *p = str;
*p = 'h'; //改变第一个字母
//example 2:
char *ptr = "Hello";
*ptr = 'h'; //错误
第一个字符串时用数组开辟的,它是可以改变的变量。而第二个字符串则是一个常量,也就是字面值。ptr只是指向它的指针而已,而不能改变指向的内容。
看两者的汇编即可明了:
char p[] = "Hello";
004114B8 mov eax,dword ptr [string "Hello" (4166FCh)] 004114BD mov dword ptr [ebp-10h],eax 004114C0 mov cx,word ptr ds:[416700h] 004114C7 mov word ptr [ebp-0Ch],cx
char *ptr = "Hello";
004114CB mov dword ptr [ebp-1Ch],offset string "
这个章节没得什么讲得,用的时候记得调用模块,自己配置一些寄存器。
ADC对自身芯片温度的采集:
void InitClock(void)//还是原来的味道 { CLKCONCMD &= ~0x40; //设置系统时钟源为 32MHZ晶振 while(CLKCONSTA & 0x40); //等待晶振稳定 CLKCONCMD &= ~0x47; //设置系统主时钟频率为 32MHZ } void InitSensor(void)//温度传感器初始化函数 { IEN0 = IEN1 = IEN2 = 0x00 //关闭所有中断 InitClock(); //设置系统主时钟为 32M TR0=0x01; //设置为1来连接温度传感器到SOC_ADC ATEST=0x01; //使能温度传感 } float GetTemperature(void)//获取温度传感器 AD 值 通过计算返回实际的温度值 { uint value; ADCCON3 = (0x3E); //选择1.25V为参考电压;14位分辨率;对片内温度传感器采样 ADCCON1 |= 0x30; //选择ADC的启动模式为手动 ADCCON1 |= 0x40; //启动AD转化 while(!(ADCCON1 & 0x80)); //等待 AD 转换完成 value = ADCL >> 4; //ADCL 寄存器低 2 位无效,由于他只有12位有效,ADCL寄存器低4位无效。网络上很多代码这里都是右移两位,那是不对的 value |= (((uint)ADCH) << 4); return (value-1367.
1.关闭键盘的方式有几种,比较好用的一种就是给当前view添加一个手势监听:
/** * @author Jerry.Yao, 15-09-30 18:09:58 * * 给当前view添加手势识别 */ - (void)setKeyBoardListener { UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(screenClick)]; [self.view addGestureRecognizer:recognizer]; } /** * @author Jerry.Yao, 15-09-30 18:09:32 * * 点击屏幕关闭键盘 */ - (void)screenClick { [self.view endEditing:YES]; } 2. 还有一种就是touch事件关闭:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { [self.view endEditing:YES]; } 个人总结下这两个方法的不同点:貌似第二个方法只能用在UITextField的直接父控件是self.view的这种情况,否则可以用第一种方法。
一、异常
异常指不期而至的各种状况,如:文件找不到、网络连接失败、非法参数等。异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程。
Java通 过API中Throwable类的众多子类描述各种不同的异常。因而,Java异常都是对象,是Throwable子类的实例,描述了出现在一段编码中的 错误条件。当条件生成时,错误将引发异常。
二、 Java异常类层次结构图
在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可用异常传播机制通过 Java 应用程序传输的任何问题的共性。
Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。
Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java虚拟机(JVM)一般会选择线程终止。
这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时,如Java虚拟机运行错误(Virtual MachineError)、类定义错误(NoClassDefFoundError)等。这些错误是不可查的,因为它们在应用程序的控制和处理能力之 外,而且绝大多数是程序运行时不允许出现的状况。对于设计合理的应用程序来说,即使确实发生了错误,本质上也不应该试图去处理它所引起的异常状况。在 Java中,错误通过Error的子类描述。
Exception(异常):是程序本身可以处理的异常。
Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。
注意:异常和错误的区别:异常能被程序本身可以处理,错误是无法处理。
通常,Java的异常(包括Exception和Error)分为可查的异常(checked exceptions)和不可查的异常(unchecked exceptions)。
可查异常(编译器要求必须处置的异常):正确的程序在运行中,很容易出现的、情理可容的异常状况。可查异常虽然是异常状况,但在一定程度上它的发生是可以预计的,而且一旦发生这种异常状况,就必须采取某种方式进行处理。
除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。这种异常的特点是Java编译器会检查它,也就是说,当程序中可能出现这类异常,要么用try-catch语句捕获它,要么用throws子句声明抛出它,否则编译不会通过。
不可查异常(编译器不要求强制处置的异常):包括运行时异常(RuntimeException与其子类)和错误(Error)。
Exception 这种异常分两大类运行时异常和非运行时异常(编译异常)。程序中应当尽可能去处理这些异常。
运行时异常:都是RuntimeException类及其子类异常,如NullPointerException(空指针异常)、IndexOutOfBoundsException(下标越界异常)等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
运行时异常的特点是Java编译器不会检查它,也就是说,当程序中可能出现这类异常,即使没有用try-catch语句捕获它,也没有用throws子句声明抛出它,也会编译通过。
非运行时异常 (编译异常):是RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如IOException、SQLException等以及用户自定义的Exception异常,一般情况下不自定义检查异常。
三、异常处理机制
在 Java 应用程序中,异常处理机制为:抛出异常,捕捉异常。
抛出异常:当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。
捕获异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exceptionhandler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适 的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适 的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。
1.1捕获异常:try、catch 和 finally 1.try-catch语句 在Java中,异常通过try-catch语句捕获。其一般语法形式为:
1. try { 2. // 可能会发生异常的程序代码 3.
转载自:http://blog.csdn.net/jackfrued/article/details/42617675
头插法思想就是建立一个头结点,自己指向自己,然后新来一个结点,
就让这个新结点指向头结点所指向的结点,然后让头结点指向新来的结点。
这样把新结点永远插到头结点之后就是头插法了。
C语言编程实现
#include<stdio.h> #include<malloc.h> struct list { int a; struct list * next; } ; struct list * head; struct list * p=NULL; int main(){ printf("%s\n","请输入链表的长度"); int length=0,i,data; scanf("%d",&length); printf("%s\n","请依次输入链表中的数据"); head = (struct list *)malloc(sizeof(struct list)); head->next=NULL; for(i=0;i<length;i++){ p = (struct list *)malloc(sizeof(struct list)); scanf("%d",&p->a); p->next=head->next; head->next=p; } while(p!=NULL){ printf("%d ",p->a); p=p->next; } }
SQLite数据库简介 1. 介绍 SQLite 是 D.Richard Hipp 用 C 语言编写的开源嵌入式数据库引擎。SQLite 是一种轻量级的小型数据库,虽然比较小,但是功能相对比较完善,一些常见的数据库基本功能也具有,它支持大多数的 SQL92 标准,并且可以在所有主要的操作系统上运行。因为它占用系统资源很少,Android 系统中也主要采用 SQLite 数据库引擎。
SQLite 实现自包容、零配置、支持事务的SQL数据库引擎。 其特点是高度便携、使用方便、结构紧凑、高效、可靠。 与其他数据库管理系统不同,SQLite 的安装和运行非常简单,在大多数情况下,只要确保 SQLite 的二进制文件存在即可开始创建、连接和使用数据库。
2. 准备 在操作之前,我们要先下载SQLite数据库,官方的下载页面是 http://www.sqlite.org/download.html,由于是在Windows下测试,所以我选择了 Precompiled Binaries For Windows 下面的 sqlite-shell-win32-x86-3081101.zip 和 sqlite-analyzer-win32-x86-3081101.zip 的zip包,前者是SQLite数据库引擎,后者是SQLite数据库分析器,主要用于分析数据库的状态等信息,大家也可以根据自己的情况去下载。解压后的文件:
3. 创建数据库 语法:
sqlite3.exe [数据库名字.后缀名] 示例:
D:\Program Files\SQLite>sqlite3.exe mydb.db SQLite version 3.8.11.1 2015-07-29 20:00:57 Enter ".help" for usage hints. sqlite> 创建的数据库后缀名可以是任意的,不过注意一点就是:在命令框下执行创建数据库的时候,如果没有为数据库创建表格,则看不见数据库文件,所以必须创建表格后才能看见数据库文件。
我们可以使用 .databases 命令查看数据库文件信息:
sqlite> .databases seq name file --- --------------- ------------------------------------------- 0 main D:\Program Files\SQLite\mydb.
错误 将XCode升级到6后,报Too many arguments to function call, expected 0, have *,在XCode5.1里能编译通过的,到xcode6就报错
查了下工程,原来是 objc_msgSend() 方法报的错误,在 MJRefresh 和 SDWebimage使用的项目中曾经都出现过此错误。
解决方案 Build Setting–> Apple LLVM - Preprocessing–> Enable Strict Checking of objc_msgSend Calls 将YES 改为 NO 参考资料: Managing Toll-Free Bridging
ARC下OC对象和CF对象之间的桥接
内存管理 包括内存管理和虚拟内存管理。
内存管理包括内存管理概念、交换与覆盖、连续分配管理方式和非连续分配管理方式(分页管理方式、分段管理方式、段页式管理方式)。
虚拟内存管理包括虚拟内存概念、请求分页管理方式、页面置换算法、页面分配策略、工作集和抖动。 3.1 内存管理的概念 内存管理(Memory Management)是操作系统设计中最重要和最复杂的内容之一。虽然计算机硬件一直在飞速发展,内存容量也在不断增长,但是仍然不可能将所有用户进程和系统所需要的全部程序和数据放入主存中,所以操作系统必须将内存空间进行合理地划分和有效地动态分配。操作系统对内存的划分和动态分配,就是内存管理的概念。
有效的内存管理在多道程序设计中非常重要,不仅方便用户使用存储器、提高内存利用率,还可以通过虚拟技术从逻辑上扩充存储器。
内存管理的功能有: 内存空间的分配与回收:由操作系统完成主存储器空间的分配和管理,使程序员摆脱存储分配的麻烦,提高编程效率。地址转换:在多道程序环境下,程序中的逻辑地址与内存中的物理地址不可能一致,因此存储管理必须提供地址变换功能,把逻辑地址转换成相应的物理地址。内存空间的扩充:利用虚拟存储技术或自动覆盖技术,从逻辑上扩充内存。存储保护:保证各道作业在各自的存储空间内运行,.互不干扰。 在进行具体的内存管理之前,需要了解进程运行的基本原理和要求。 程序装入和链接 创建进程首先要将程序和数据装入内存。将用户源程序变为可在内存中执行的程序,通常需要以下几个步骤: 编译:由编译程序将用户源代码编译成若干个目标模块。链接:由链接程序将编译后形成的一组目标模块,以及所需库函数链接在一起,形成一个完整的装入模块。装入:由装入程序将装入模块装入内存运行。 这三步过程如图3-1所示。
图3-1 对用户程序的处理步骤 程序的链接有以下三种方式: 静态链接:在程序运行之前,先将各目标模块及它们所需的库函数链接成一个完整的可执行程序,以后不再拆开。装入时动态链接:将用户源程序编译后所得到的一组目标模块,在装入内存时,釆用边装入边链接的链接方式。运行时动态链接:对某些目标模块的链接,是在程序执行中需要该目标模块时,才对它进行的链接。其优点是便于修改和更新,便于实现对目标模块的共享。 内存的装入模块在装入内存时,同样有以下三种方式:
1) 绝对装入。在编译时,如果知道程序将驻留在内存的某个位置,编译程序将产生绝对地址的目标代码。绝对装入程序按照装入模块中的地址,将程序和数据装入内存。由于程序中的逻辑地址与实际内存地址完全相同,故不需对程序和数据的地址进行修改。
绝对装入方式只适用于单道程序环境。另外,程序中所使用的绝对地址,可在编译或汇编时给出,也可由程序员直接赋予。而通常情况下在程序中釆用的是符号地址,编译或汇编时再转换为绝对地址。
2) 可重定位装入。在多道程序环境下,多个目标模块的起始地址通常都是从0开始,程序中的其他地址都是相对于起始地址的,此时应釆用可重定位装入方式。根据内存的当前情况,将装入模块装入到内存的适当位置。装入时对目标程序中指令和数据的修改过程称为重定位,地址变换通常是在装入时一次完成的,所以又称为静态重定位,如图3-2(a) 所示。
图3-2 重定向类型 静态重定位的特点是在一个作业装入内存时,必须分配其要求的全部内存空间,如果没有足够的内存,就不能装入该作业。此外,作业一旦进入内存后,在整个运行期间不能在内存中移动,也不能再申请内存空间。
3) 动态运行时装入,也称为动态重定位,程序在内存中如果发生移动,就需要釆用动态的装入方式。装入程序在把装入模块装入内存后,并不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正要执行时才进行。因此,装入内存后的所有地址均为相对地址。这种方式需要一个重定位寄存器的支持,如图3-2(b)所示。
动态重定位的特点是可以将程序分配到不连续的存储区中;在程序运行之前可以只装入它的部分代码即可投入运行,然后在程序运行期间,根据需要动态申请分配内存;便于程序段的共享,可以向用户提供一个比存储空间大得多的地址空间。 逻辑地址空间与物理地址空间 编译后,每个目标模块都是从0号单元开始编址,称为该目标模块的相对地址(或逻辑地址)。 当链接程序将各个模块链接成一个完整的可执行目标程序时,链接程序顺序依次按各个模块的相对地址构成统一的从0号单元开始编址的逻辑地址空间。用户程序和程序员只需知道逻辑地址,而内存管理的具体机制则是完全透明的,它们只有系统编程人员才会涉及。不同进程可以有相同的逻辑地址,因为这些相同的逻辑地址可以映射到主存的不同位置。
物理地址空间是指内存中物理单元的集合,它是地址转换的最终地址,进程在运行时执行指令和访问数据最后都要通过物理地址从主存中存取。当装入程序将可执行代码装入内存时,必须通过地址转换将逻辑地址转换成物理地址,这个过程称为地址重定位。 内存保护 内存分配前,需要保护操作系统不受用户进程的影响,同时保护用户进程不受其他用户进程的影响。通过釆用重定位寄存器和界地址寄存器来实现这种保护。重定位寄存器含最小的物理地址值,界地址寄存器含逻辑地址值。每个逻辑地址值必须小于界地址寄存器;内存管理机构动态地将逻辑地址与界地址寄存器进行比较,如果未发生地址越界,则加上重定位寄存器的值后映射成物理地址,再送交内存单元,如图3-3所示。
当CPU调度程序选择进程执行时,派遣程序会初始化重定位寄存器和界地址寄存器。每一个逻辑地址都需要与这两个寄存器进行核对,以保证操作系统和其他用户程序及数据不被该进程的运行所影响。
图3-3 重定位和界地址寄存器的硬件支持 3.2 内存覆盖与内存交换 覆盖与交换技术是在多道程序环境下用来扩充内存的两种方法。 内存覆盖 早期的计算机系统中,主存容量很小,虽然主存中仅存放一道用户程序,但是存储空间放不下用户进程的现象也经常发生,这一矛盾可以用覆盖技术来解决。
覆盖的基本思想是:由于程序运行时并非任何时候都要访问程序及数据的各个部分(尤其是大程序),因此可以把用户空间分成一个固定区和若干个覆盖区。将经常活跃的部分放在固定区,其余部分按调用关系分段。首先将那些即将要访问的段放入覆盖区,其他段放在外存中,在需要调用前,系统再将其调入覆盖区,替换覆盖区中原有的段。
覆盖技术的特点是打破了必须将一个进程的全部信息装入主存后才能运行的限制,但当同时运行程序的代码量大于主存时仍不能运行。 内存交换 交换(对换)的基本思想是,把处于等待状态(或在CPU调度原则下被剥夺运行权利)的程序从内存移到辅存,把内存空间腾出来,这一过程又叫换出;把准备好竞争CPU运行的程序从辅存移到内存,这一过程又称为换入。中级调度就是釆用交换技术。
例如,有一个CPU釆用时间片轮转调度算法的多道程序环境。时间片到,内存管理器将刚刚执行过的进程换出,将另一进程换入到刚刚释放的内存空间中。同时,CPU调度器可以将时间片分配给其他已在内存中的进程。每个进程用完时间片都与另一进程交换。理想情况下,内存管理器的交换过程速度足够快,总有进程在内存中可以执行。
有关交换需要注意以下几个问题: 交换需要备份存储,通常是快速磁盘。它必须足够大,并且提供对这些内存映像的直接访问。为了有效使用CPU,需要每个进程的执行时间比交换时间长,而影响交换时间的主要是转移时间。转移时间与所交换的内存空间成正比。如果换出进程,必须确保该进程是完全处于空闲状态。交换空间通常作为磁盘的一整块,且独立于文件系统,因此使用就可能很快。交换通常在有许多进程运行且内存空间吃紧时开始启动,而系统负荷降低就暂停。普通的交换使用不多,但交换策略的某些变种在许多系统中(如UNIX系统)仍发挥作用。 交换技术主要是在不同进程(或作业)之间进行,而覆盖则用于同一个程序或进程中。由于覆盖技术要求给出程序段之间的覆盖结构,使得其对用户和程序员不透明,所以对于主存无法存放用户程序的矛盾,现代操作系统是通过虚拟内存技术来解决的,覆盖技术则已成为历史;而交换技术在现代操作系统中仍具有较强的生命力。
3.3 内存连续分配管理方式 连续分配方式,是指为一个用户程序分配一个连续的内存空间。它主要包括单一连续分配、固定分区分配和动态分区分配。 单一连续分配 内存在此方式下分为系统区和用户区,系统区仅提供给操作系统使用,通常在低地址部分;用户区是为用户提供的、除系统区之外的内存空间。这种方式无需进行内存保护。
这种方式的优点是简单、无外部碎片,可以釆用覆盖技术,不需要额外的技术支持。缺点是只能用于单用户、单任务的操作系统中,有内部碎片,存储器的利用率极低。 固定分区分配 固定分区分配是最简单的一种多道程序存储管理方式,它将用户内存空间划分为若干个固定大小的区域,每个分区只装入一道作业。当有空闲分区时,便可以再从外存的后备作业队列中,选择适当大小的作业装入该分区,如此循环。
图3-4 固定分区分配的两种方法 固定分区分配在划分分区时,有两种不同的方法,如图3-4所示。 分区大小相等:用于利用一台计算机去控制多个相同对象的场合,缺乏灵活性。分区大小不等:划分为含有多个较小的分区、适量的中等分区及少量的大分区。 为便于内存分配,通常将分区按大小排队,并为之建立一张分区说明表,其中各表项包括每个分区的起始地址、大小及状态(是否已分配),如图3-5(a)所示。当有用户程序要装入时,便检索该表,以找到合适的分区给予分配并将其状态置为”已分配”;未找到合适分区则拒绝为该用户程序分配内存。存储空间的分配情况如图3-5(b)所示。
这种分区方式存在两个问题:一是程序可能太大而放不进任何一个分区中,这时用户不得不使用覆盖技术来使用内存空间;二是主存利用率低,当程序小于固定分区大小时,也占用了一个完整的内存分区空间,这样分区内部有空间浪费,这种现象称为内部碎片。
linux 重命名文件和文件夹 linux下重命名文件或文件夹的命令mv既可以重命名,又可以移动文件或文件夹.
例子:将目录A重命名为B
mv A B
例子:将/a目录移动到/b下,并重命名为c
mv /a /b/c
其实在文本模式中要重命名文件或目录的话也是很简单的,我们只需要使用mv命令就可以了,
比如说我们要将一个名为abc的文件重命名为1234就可以这样来写:mv abc 1234,
但是要注意的是,如果当前目录下也有个1234的文件的话,我们的这个文件是会将它覆盖的。
短流行:为什么爆款App越来越多,流行时间越来越短(转)
记者朱晓培 编辑施雨华 刊登于《财经天下》周刊
原文标题:短流行/短命的流行
关于“短流行”这的想象,是年初就注意到的,6月10日做的第一个采访,然后拖拖拉拉就做到了9月。
唱吧、魔漫相机、疯狂猜图、脸萌、围住神经猫、无秘、足记……爆款App越来越多,流行的时间却似乎越来越短。它们真的就此销声匿迹了,还是会卷土重来?
移动应用领域越来越像是一片红海。不过,总有些人试图奋力游到对岸去。眼下,秒拍旗下的一款App——模仿德国短视频应用Dubsmash的小咖秀,正在微博上掀起一阵对口型的模仿秀,其中女演员蒋欣的多个模仿视频被转发了20多万次。
虽然有秒拍的经验和Dubsmash的成功在先,小咖秀还是让秒拍团队感到兴奋。“原计划半年达到的效果,一个月就做到了。”联合创始人、高级副总裁雷涛对《财经天下》周刊说。5月13日,小咖秀在苹果商店上线,7月26日登上免费排行榜第一,单日下载量超过100万次。
对于小咖秀能火多久,雷涛并不太担心。“这就像流行性感冒,有传染性,爆发得快,但人们也会很快产生抗体。看热闹的用户早晚离开,我们满足的是真正有需求的用户。”
实际上,从2012年开始,类似的应用不断涌现。移动互联网的普及造就了一个新名词——“现象级应用”。这类应用通过微博、微信等社交网络,全面爆红。据《财经天下》周刊不完全统计,其中至少包括了唱吧、魔漫相机、百度魔图、你画我猜、疯狂猜图、脸萌、围住神经猫、无秘、足记、小偶等应用。
一夜之间,仿佛所有人都在用它们加工自己的生活——把微信头像换成魔漫相机或脸萌的图片,用唱吧在线K歌,或者用足记为朋友圈的照片添加感性的文字。然而,一段时间之后,许多“现象”消失了。
不错,它们流行过,但只是“短暂”的流行。
“现在传播网络如此发达,能让病毒性传播像DNA复制一样,一瞬间让用户产生兴趣,但这种兴趣又可能一下子消失。”晨兴资本合伙人程宇告诉《财经天下》周刊,“有可能一夜疯狂,也有可能一夜掉下来,公司要做好长远的准备。”
指数级爆发
“等我发现非互联网圈的人也在用时,事情已经超出我的预想,刹不住车了。”足记CEO杨柳对《财经天下》周刊记者复盘足记爆红的那段日子。一开始,杨柳看到朋友圈里与互联网相关的人用足记时,以为他们在测试产品。
足记的主要功能是加工图片,可以将图片处理成宽屏,还可以添加字幕,使图片看起来具有电影大片的效果。2014年6月12日,足记1.0在苹果应用商店上线。之后,像绝大多数App一样用户增长缓慢,到2015年3月9日才达到10万用户。
但用户数突破10万后,足记突然开始呈现出指数级的爆炸式增长:3月14日,100万;3月19日,700万;3月24日,1200万……一个多月后,用户的热情才逐渐冷却下来。
招聘工程师、A轮融资、媒体采访随着用户数的增长一起到来,杨柳甚至连洗头的时间都挤不出来。当时足记只有8名员工。“为了让基本功能运行下去,只能让服务降级,原计划的改版、优化全都来不及做,全部精力都放在了补漏洞上。”杨柳坦言她完全没有预料到足记会突然爆发,更没有为此做好准备。但她又表示,“创业这件事,永远都不会有完全准备好的那一天。虽然很痛苦,但也很美好。”
疯狂猜图的研发团队规模更小,只有4个人。这是豪腾科技的一个小项目。2013年5月13日,这款手机App在苹果应用商店上线。从5月29日开始,用户开始快速增长,6月7日一天新增用户数达到了30万,成为苹果中国区App免费榜排行第一。3个月内,这款App总下载量超过了1亿次。
豪腾科技CEO曹晓刚向《财经天下》周刊表示,做疯狂猜图的目的就是通过朋友圈的互动带来好的传播效应。最终,这4人小团队产生的传播效果,是此前豪腾近百名员工都没有达到过的。
2013年5月,90后郭列成立了MT团队。11月,脸萌1.0在苹果应用商店上线。2014年6月,脸萌开始出现爆炸式增长,日下载最高达500万,在中国、英国、西班牙等17个国家的苹果应用商店总排行榜上排第一。
把“指数级爆发”现象发挥到极致的是围住神经猫。2014年7月,这款基于H5的游戏从开发上线到全民刷屏,只用了3天,获得超过1亿次的访问。
但这些应用在出现爆炸性增长后,都遇到了与足记相同的问题。由于团队规模小,前期准备不充分,后端的服务开始面临严重挑战。“能把后台维护好就不错了,那时候我连招人、面试的时间都挤不出来。”魔漫相机联合创始人黄光明说。
用户使用热情下降后,开发团队都选择回归产品。郭列开始拒绝采访,他在自己的微信朋友圈中写道:“不想把公司办成旅游景点,如果真的为我们好,请不要打扰我们工作。”
而小偶,一款可以直接用手机摄像头拍出3D卡通形象的App,在苹果商店上线后意外在海外市场走红。应用追踪分析工具 App Annie统计显示,小偶在包括美国在内的37个国家的苹果应用商店免费榜排名第一,并在124个国家进入了前100名。但小偶创始人陈军宏却表达了自己的忧虑,“全球流行只是个意外,是我们不希望发生的事情,太早曝光反而被动。我们不希望被视为那种莫名流行而后销声匿迹的应用。”
“爆款”的“引爆点”
留意观察这些应用,你会发现它们有一些共同特点:新颖有趣、操作简单、能够凸显用户个性,可以在社交网络中分享,从而带动更多的用户参与。
比如,百度魔图的PK大咖功能,可以满足普通用户与明星们对比的心理,分享到朋友圈引发吐槽或赞美,也可以获得满足感。通过脸萌创作自己的卡通形象,或者用魔漫相机对照片进行处理,满足了用户定制个性化形象和创意拼脸的需求。
就像宾夕法尼亚大学沃顿商学院教授凯文·韦巴赫在《游戏化思维:改变商业的力量》中指出过的,游戏中的一些常见元素,如输赢、得分、奖励,让游戏更有乐趣、更容易吸引玩家。
在韦巴赫看来,Nike + 就是利用了游戏化思维——用户可以对个人数据与其他用户的数据做比较,同时直观地看到自己在跑步上的进展——得以迅速传播。2013年,Nike + 在苹果应用商店上线后,各地掀起跑步热潮,人们争相在朋友圈中分享含有自己跑步里程和路线的Nike + 图片。
除了这些共同特点,还有两个因素起了关键作用:时间点和意见领袖。
“关键是时间点。”2012年5月31日,唱吧在苹果应用商店上线,5天之后便排在了免费排行榜的首位。CEO陈华事后总结道:唱吧能火起来是很多因素聚集而成的结果,最重要的是,当时正是中国移动互联网普及的时间点。“大家都在快速更换手机,从之前的功能机换到智能机。这时,用户对一个新的应用、好玩的应用,需求是极其强烈的。”
中国工信部电信研究院的数据显示,2011年中国智能手机出货量达到1.18亿台,同比增长175%,超过此前历年总和。从2011年到2013年,智能手机用户都在寻求各种有趣的App。唱吧、魔漫相机、疯狂猜图等App就在这段时间陆续爆发。
市场的空白,为App开发者提供了红利。猎豹移动CEO傅盛提到过,2012年他开始研究美国的应用市场,发现谷歌应用商店中,一个排名前5的App竟然是由黑龙江的一名个人开发者做的。
秒拍联合创始人雷涛认为,秒拍的爆发得益于4G网络普及的时间点。2014年,4G网络和4G智能手机迅速普及,微信也开始在朋友圈中加入短视频功能,美拍、秒拍等短视频App迅速进入大众视野。2014年3月,美拍在苹果应用商店上线一天后即成为香港、澳门等地区下载排行第一。到2014年5月,美拍用户数就突破了1亿。
“这一般出现在一个平台诞生的初期,而且一定是娱乐、功能性应用早于实际的生活应用。所有人都在找好玩的东西——小游戏、基础工具,但生活类的、电商类的,是没那么容易火起来的。”陈华这么认为。
小偶在海外市场与在中国市场的表现反差,或许更能集中反映出这些因素的影响。
2014年8月小偶发布时,名为“3D大头秀”,不久改为“小偶”。2015年2月,小偶首次进入美国苹果商店排行榜。4月5日,小偶进行了一次更新,并将应用所属类别从社交调整到了娱乐。不到20天后,小偶就从娱乐类1000名外,冲到了美国苹果商店免费榜第一位。
但在中国,小偶的表现,要比它在很多国家的表现差一些。农历新年,小偶因为动画拜年功能曾登上中国苹果商店免费榜第一的位置,但很快又滑到1000名外。通过4月5日的更新,小偶的排名又开始爬升,但也只是在20位左右。
对比小偶、脸萌这两款以卡通形象为主要功能的应用在中国应用市场上的表现,可以发现,以图片为主的脸萌,得益于中国用户微信头像的传播;而小偶以视频为主,非常适合美国社交网络,比如Instagram、Vine、Snapchat等有视频社交功能,中国的视频社交则要弱很多。
“它的这个形式确实契合到了某些点,是比较容易的一种表达方式。”杨柳说的点是图片表达方式。在足记之前,Instagram、nice等图片社交网站一直在帮助用户培养分享图片的习惯。2013年的D11大会上,互联网女皇玛丽米克尔指出,网民每天共享的照片总数超过了5亿张。不难看出图片应用已经成为互联网一个重要组成部分。
杨柳事后总结,足记的传播遵循一定轨迹:最早是身边试用的朋友,而其中一些人是与摄影和电影相关的从业者,因此足记就在这群人的圈子中辐射开来。由于他们原本就具有摄影优势,拍摄的图片质量高,因此容易得到传播。摄影、电影人群本身就有一定影响力,会影响到一些明星、达人,这群人作为日常生活中的“意见领袖”,最终导致了越来越多普通人群的追随。
“表演型”用户的作用
魔漫相机联合创始人黄光明记得,2013年6月魔漫相机被放到腾讯应用宝上后,第一天有25个用户下载,第二天170多,第三天400多,第四天突破了1000。此后,有一小段时间,每日下载量维持在六七千。
当时黄光明对员工说,用户下载量突破1万、5万、10万、50万、100万的时候,他会分别请大家吃饭。黄光明预计,3个月后,魔漫相机能成为百万量级的应用,2013年底做到3000万。
“我们一点都没有推,完全就是自发的口碑。但后来,一名摄影师使用了软件并分享后,那天一下子就破万了,然后就爆了。”2013年8月,黄光明请同事们吃了一顿饭。“当时想3个月做到100万,结果一个月就达到了。”到了9月份,魔漫相机已经不再统计下载量而只看激活用户数了。“下载量已经不具备任何的参考价值了,激活用户已经过10万了。”
显然,那位摄影家起了“意见领袖”的作用。传播学家拉扎菲尔德认为,“意见领袖”是在人际传播网络中经常为他人提供信息,同时对他人施加影响的“活跃分子”,他们在大众传播效果的形成过程中起重要的中介或过滤作用,形成信息传递的两级传播。
唱吧的设计充分考虑到了“意见领袖”的作用。“唱吧实际上是一个考虑周全的产品。我们在做之前就考虑到了怎么吸引用户,怎么让用户兴奋,怎么进一步去推广。”唱吧CEO陈华说。他把唱吧吸引用户进而传播的路径分三个阶段。
“吸引用户的本质上是一个工具属性的东西,我们提供了一个最好的K歌工具。我们的曲库非常大、对声音的修饰做得非常棒,所有的歌曲是免费的。这种工具属性就把大量喜欢唱歌的用户给拽进来了。这是第一波用户。”
第一批用户唱完后,唱吧会显示其“击败了全国X%的用户”,并显示出分享到微博、微信等社交网络的按钮。“这很容易让用户兴奋,他可以分享到朋友圈,分享到微博,把他的朋友给拉进来。”唱吧还提供了打榜功能,收到的鲜花越多,排名越靠前。“本来你唱歌,你的朋友听着不错,大家送花把你送到某个小城市的最后一名。既然你已经上了最后一名,你就想上到第一名。这时候你会把你的作品强制性地分享给所有朋友,要求每人都上来送一下花。这就是第二波传播。”当一个人已经成为唱吧里小小的明星时,就有了自己的知名度和粉丝。喜欢他的陌生人就会去号召自己的朋友为他拉票,从而形成第三波的传播。
“唱吧通过一套产品体系把用户源源不断地吸引进来,形成我们自己的一个比较有意思的唱歌加打榜的生态。”陈华说。显然,演唱并分享、打榜的用户是唱吧的核心用户。
“我们把这种用户叫做‘表演型用户’。”秒拍联合创始人雷涛认为,在分享和传播过程中,“表演型用户”起到了关键作用。
“表演型用户”可能是像蒋欣一样愿意展示才艺并且愿意自黑的用户,也可能是好胜心较强的用户——看到朋友分享自己的创意或者玩游戏的成绩时,会忍不住要超过对方。这类用户既是这些应用的超级粉丝,又在传播中起到了“意见领袖”作用。小咖秀在前期推广中,也刻意选择了一些“表演型用户”进行合作。
感觉没有那么火了
“你有没有感觉,当年唱吧那么火,火得不得了,但现在的关注度不像当年那么强烈了?”新鲜传媒CEO纪中展在《创业分子》的视频录制中向陈华提出了这样的问题。纪中展认为,唱吧错过了某些可能性,比如唱吧可以成为一个造星平台,因为当时连王菲也在唱吧上发布自己的唱歌音频。
“不像以前那么火了”是每一个爆红过的应用都遇到的问题。百度指数(以百度网民行为数据为基础的统计分析平台,反映某个关键词在百度的搜索规模、一段时间内的涨跌态势以及相关的新闻舆论变化)显示,这些应用相关指数在一个月左右,就会从几万点跌回几千甚至不到一千。
蓝港互动副总裁王世颖认为,在微信朋友圈中爆红的游戏App,以休闲娱乐的轻游戏为主。这类游戏的一个共同特点就是功能简单,然而简单本身就意味着容易审美疲劳,而且容易被复制。
此外,在这些应用中,游戏和社交软件占了大部分,包括脸萌、围住神经猫、2048、无秘等等。它们快速引爆并衰退的现象,和游戏产品属性息息相关。
王世颖指出,大部分游戏在上线后,从用户明显增长到达到峰值,一般为一到两个月,此后便开始下降。按蓝港互动的数据来看,一般次日留存率为50%,一款好游戏最终用户留存率在30%。
当用户的规模达到一定程度后,增长速度就必然会变慢。“在体量变大后,继续增长是一件很困难的事。”唱吧CEO陈华说。“如果只是发明了一个新奇的玩法,人们开头觉得挺新奇的,但玩一阵子后可能就觉得没什么意思,疲劳了。”陈华认为,唱吧解决的是人们本来就存在的K歌需求,解决现实生活中本来就存在的需求的应用,生命力会相对长一些。
首先在开始菜单——》所有程序——》Microsoft SQL Server 2008 R2——》配置工具——》SQL Server 配置管理器,如下图: 然后再sqlserver网络配置中开启TCP/IP协议,如下图所示: TCP/IP——》右击——》属性——》IP地址,如下图所示: 最后设置某一个访问IP地址的端口号,我选的是192.0.0.1 端口号是:1433,记住“活动”选择“是”,“已启用”也是“是”;
服务端控件
ClientID 我们以后在客户端操作服务端控件的时候,不要用ID,而是最好是使用ClinetID。因为服务端控件的ID不一定等于“服务端控件渲染到客户端后生成的HTML中的ID”
比如说在ListView等控件的模板中。因此如果在客户端通过JavaScript,Dom,Jquery的documnet.getElementById("id") ,或者$("#id")来操作控件的话最好不要直接
写服务端控件的ID,而是通过 $("#<%=Button1.ClientID%>")这种形式来操作。
用jquery时间设置鼠标移动到控件上和控件移开的不同样式,在用户控件中就可以看到ClientID和Id的不同。 UserControl,母版,ListView,推荐永远用ClientID
例如:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm3.aspx.cs" Inherits="WebApp.WebForm3" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title></title> </head> <body> <form id="form1" runat="server"> <div> <%--获取由ASP.NET生成的HTML标记的控件ID 这里虽然也是输出Button1--%> <%=this.Button1.ClientID %> </div> <asp:Button ID="Button1" runat="server" Text="Button" /> </form> </body> </html> Visible属性 表示控件是否可见,如果Visible=False那么在在渲染的时候就会忽略掉这个控件,也就是说这个控件不会生成HTML代码。也就表明根本不存在这个控件,既然控件都不存在,也就不会占用区域。
怎么给服务器端控件设置Class样式? using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace WebApp { public partial class WebForm3 : System.
以前所做的工作,大多是把FFmpeg用在windows平台,采用D3D或者OpenGL的方式进行渲染呈现;
前面两篇文章中,已经做好了ubuntu平台下的ffmpeg编译与简单调试(ubuntu编译ffmpeg并且demo测试),以及windows平台下的ffmpeg解码SDL显示(FFmpeg与SDL双剑合璧之Windows );
梳理一下手上已经具备的材料:
①ffmpeg解码,SDL播放的Demo(windows平台);
②ubuntu平台下编译好的ffmpeg库;
③ubuntu平台下编译好的SDL库;
第③份材料,没有写出来,因为太简单了,大致操作步骤是:
1.下载SDL源码(SDL),解压;
2.打开终端,切换到SDL源码解压后的目录,执行./configure
3.make
4.sudo make install
OVER;
接下来,就是把windows平台下的代码直接搬过来,没有多少需要修改的地方,主要是库的引用上下了点功夫
一个需要注意的,对于ffmpeg库的调用,需要在包含头文件之前,定义一下
#define __STDC_CONSTANT_MACROS 下面上干货: //FFDecoder.h #pragma once #define __STDC_CONSTANT_MACROS extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavutil/avutil.h" #include "libavutil/opt.h" #include "libswscale/swscale.h" } class CFFDecoder { public: CFFDecoder(); virtual ~CFFDecoder(); int OpenFile(const char *pFilePath); int GetMediaInfo(int &nFrameW,int &nFrameH); int GetOneFrame(AVFrame *pFrame); private: AVFormatContext *m_pFormatCxt; AVCodecContext *m_pCodecCtx; AVCodec *m_pCodec; AVPacket m_Packet; int m_nVideoIndex; int m_nAudioIndex; }; //FFDecoder.
笔者家里2台台式机,一台使用网线直连无线路由,另一台使用无线网卡接收信号来上网,在打开网上邻居中的计算机后,出现假死现象,很长时间才能反应过来,打开下级目录、返回到上级目录也是很慢才能反应过来,并且两台电脑传输文件也是慢的要死,把笔记本拿到路由器跟前,上述情况依旧如此!查阅了相关资料后,问题得到大部分解决。
一:让打开网上邻居中的电脑如同本地一样快
开始菜单-运行,输入regedit,找到
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\RemoteComputer\NameSpace
这个键值,并且将红色区域里的数值删除:
二:让局域网传输文件速度加快
1、这一步需要更改网卡的设置,在运行窗口输入ncpa.cpl,回车后打开网络连接窗口,右击本地连接-属性
修改了上述设置,测试一个33MB大小的文件原本需要40秒,现在缩短了一半时间。
public class TestLock { private final HashMap map = new HashMap(); public TestLock() { final Thread t1 = new Thread() { @Override public void run() { for(int i=0; i<500000; i++) { map.put(new Integer(i), i); } System.out.println("t1 over"); } }; final Thread t2 = new Thread() { @Override public void run() { for(int i=0; i<500000; i++) { map.put(new Integer(i), i); } System.out.println("t2 over"); } }; t1.start(); t2.start(); } public static void main(final String[] args) { new TestLock(); } } 就是启了两个线程,不断的往一个非线程安全的HashMap中put内容,put的内容很简单,key和value都是从0自增的整数(这个put的内容做的并不好,以致于后来干扰了我分析问题的思路)。对HashMap做并发写操作,我原以为只不过会产生脏数据的情况,但反复运行这个程序,会出现线程t1、t2被hang住的情况,多数情况下是一个线程被hang住另一个成功结束,偶尔会两个线程都被hang住。说到这里,你如果觉得不好好学习ConcurrentHashMap而在这瞎折腾就手下留情跳过吧。 好吧,分析下HashMap的put函数 源码 看看问题出在哪,这里就罗列出相关代码(jdk1.
第一种情况
双冒号 :: 操作符被称为域操作符(scope operator),含义和用法如下:
1.在类外部声明成员函数。void Point::Area(){};
1.类中 静态方法和静态属性的引用方法
例如
class Test{
public static $test = 1;
public static function test(){
}
}
可以不用实例化对象直接使用 Test::$test 来取得$test属性的值
静态方法调用也同理Test::test(); 直接调用静态方法test
2.两个冒号(::)是对类中的方法的静态引用
也就是不需要实例化对象,直接通过类名对类中的方法进行引用
第二种情况
调用父类的构造函数:
class A {
public $name; //名字
function __construct($name){ //构造函数
$this->name = $name;
}
function test(){
echo $this->name;
}
}
//派生类
class B extends A{
function __construct(){
parent::__construct("测试"); //调用或者说继承父类的构造函数:
self::test();
}
}
$b = new B();
进行更多交流
微信扫描关注“公众号”
环境:Ubuntu 14.04 + ROS Indigo
LSD-SLAM 安装网址:https://github.com/tum-vision/lsd_slam
数据集:http://vision.in.tum.de/research/vslam/lsdslam?redirect=1
ROS Indigo 安装请参照:http://wiki.ros.org/cn/indigo/Installation/Ubuntu
前言:如果是初次安装Ubuntu并准备作为长期编程平台
建议安装顺序为 OpenCV依赖包-》Nvidia驱动(可选)-》OpenCV-》ROS
否则容易出现libqt4相关软件包的依赖问题
一. 安装并配置好 ROS Indigo(建议使用ROS官网推荐安装教程)
二. 安装uvc_camera (可选,适用于需要USB摄像头且没有安装过ROS摄像驱动的情况)
此节来自http://blog.csdn.net/sonictl/article/details/48053597,感谢sonictl
$ sudo apt-get install ros-indigo-uvc-camera 或者使用catkin,工作空间构建请参考ROS官网相关教程
$ cd ~/catkin_ws/src $ git clone https://github.com/ktossell/camera_umd $ cd ~/catkin_ws $ catkin_make $ source ~/catkin_ws/devel/setup.bash 测试是否安装成功: 开启三个终端:
第一个启动ROS服务:
$ roscore第二个启动驱动: $ rosrun uvc_camera uvc_camera_node device:=/dev/video0第三个启动视频窗口: $ rosrun image_view image_view image:=/image_raw如果正常显示摄像头视频即成功 三. 安装并运行LSD-SLAM
1. 如果没有rosbuild并且打算使用rosbuild空间的话,执行下列代码
sudo apt-get install python-rosinstall mkdir ~/rosbuild_ws cd ~/rosbuild_ws rosws init .
不废话 第一次写博客,不知道怎么写, 直接进入主题
我来这最熟悉的代码
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initUI(); } private void initUI() { save = (Button) findViewById(R.id.save); read = (Button) findViewById(R.id.read); textView = (TextView) findViewById(R.id.textview); save.setOnClickListener(this); read.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.save: initData(); break; case R.id.read: break; } } private void initData() { // TODO Auto-generated method stub LinkedList<MyTrafficDetailsBin> detailsBins=new LinkedList<MyTrafficDetailsBin>(); for (int i = 0; i < 20; i++) { MyTrafficDetailsBin bin=new MyTrafficDetailsBin(i, "
<a href="javascript:;" class="a-upload"> <input type="file" name="" id="">点击这里上传文件 </a> <a href="javascript:;" class="file">选择文件 <input type="file" name="" id=""> </a> /*a upload */ .a-upload { padding: 4px 10px; height: 20px; line-height: 20px; position: relative; cursor: pointer; color: #888; background: #fafafa; border: 1px solid #ddd; border-radius: 4px; overflow: hidden; display: inline-block; *display: inline; *zoom: 1 } .a-upload input { position: absolute; font-size: 100px; right: 0; top: 0; opacity: 0; filter: alpha(opacity=0); cursor: pointer } .
Java 与 C/C++ 字节序是不同的: 1、Java采用高字节在前的方式读写数据,例如要把一个4字节的int数值写入文件时,它是按照从高字节到低字节的顺序写入的,读取的时候也是这样读出来。 而C/C++则采用平台相关的方式,在Windows平台采用低字节在前的方式,在Linux/Unix平台则采用高字节在前的方式。 如果Java要读取C/C++创建的二进制文件,就要注意这个问题,最好先搞清楚原来的文件是采用哪种方式创建的。 2、Java没有无符号数,无论byte,short,int,long都是有符号整数,而C/C++有个unsigned关键字可以设置一个数值为无符号数。 3、Java的整数基本数据类型就是byte,short,int,long这几个,长度分别为1,2,4,8字节,C/C++可以用typedef定义各种数据类型。
这是上篇博文(http://blog.csdn.net/u010412719/article/details/48324799)中遇到的问题,详细原因明天再总结,总之,因为自己这样写了,花了很长时间才把这个bug调通。
在scanf里 \n 很特别的,不是要求输入一个回车换行
引用一下别人的说法: 过滤空格、制表符、回车等输入,也就是说 scanf(“%d\n”, &i); printf(“%d\n”, i); 你输入一个数后,它是不会立即显示的,要等再接收到一个非(空格、制表符、回车)的输入scanf语句才结束。
但请注意的是,最后输入的那个非(空格、制表符、回车)的东西是不会被这个scanf读进来的,而是留在输入流里。
python中字符串自带的split方法一次只能使用一个字符对字符串进行分割,但是python的正则模块则可以实现多个字符分割
import re re.split('[_#|]','this_is#a|test') 返回的是一个列表(list),输出结果如下:
['this', 'is', 'a', 'test']
在工程圖中, 線段被[倒圓角]後,如何找出[虛擬相交]點進行標註。請參考以下說明:
1. 打開工程圖任一線段圓角。
2. 將智慧草圖的 [交點] 與 [延伸] 關係勾選。
3. 使用 [間距]標註,類型用 [2點] 標註,這時候將滑鼠移動到1的位置,使端點跑出來。
※ 備註:移動的時候並不需要指定鎖端點,只要讓電腦判斷第一個位置與第二個位置,將是我們需要的線段
4. 滑鼠移動到第2的端點。
5. 接下來把滑鼠移動到兩條線段延伸附近的位置,延伸交點將會自動出現,這時候將交點當作標註第一點。
6. 點選我們要的第二點,直線標註就完成。
7. 將原本直線線段用虛線延伸後差別顯示。
来源:凯德科技:【SolidEdge 工程圖圓角交點標註 - 2015/07/24】
原文链接地址:http://mp.weixin.qq.com/s?__biz=MjM5OTk4NDc2NQ==&mid=211213135&idx=1&sn=9adc717e1f094cdbbcba931332c9ae3a#rd
转自西门子工业软件官方微信公众号【solidedge联盟】,如果有任何需要向我们咨询或者帮助的地方,欢迎在公众号下面留言。
转载于:https://my.oschina.net/u/2357930/blog/502040
1979年4月,贝尔实验室的Bjarne Stroustrup(本贾尼·斯特劳斯特卢普)博士等人负责分析UNIX内核,但当时没有合适的工具能够有效地分析由于内核分布而造成的网络流量,将内核模块化,因此他们的工作进展缓慢。1979年10月,Bjarne Stroustrup为C语言增加了类似于Simula语言的类机制并设计开发了一个预处理器Cpre,来处理这些添加的元素和C语言的对应。在这个过程中,Bjarne Stroustrup产生了创建一门新语言的想法,这就是C++语言的萌芽。
1980年,C++的早期版本诞生,称作带类的C(C with Classes)。1983年Rick Mascitti建议将带类的C命名为C++(C Plus Plus),从此,C++作为一个优秀的程序设计语言被广为人知。C++是在C语言的基础上开发出来的,是C语言的超集,同时参考了很多其他语言的特性,例如Simula中的类概念,Algol68的运算符重载、引用及在任何地方声明变量的特性,BCPL的//注释和Ada语言中的模板、命名空间以及Ada、Clu和ML中的异常概念,它既具有C语言的高效性和灵活性,也提供了程序组织的高层特性。
1983年之后,C++使用的爆炸式增长。传统的面向用户遇到的问题及基于同事间讨论的演化方式已无法满足需求,迫切需要对C++语言进行标准化。1989年,《The Annotated C++ Reference Manual》发布,成为C++标准的基础。同年12月,ANSI的X3J16委员会成立并在华盛顿召开第一次技术会议,ANSI C++标准的制定开始提上日程。1991年7月ANSI C++标准化成为ISO标准化工作的一部分。1995年4月,C++标准草案提交公众审阅,1998年ISO C++标准通过ISO评审成为国际标准,称作C++98.
2003年,C++标准委员会对C++98中的问题进行了修订,发布了C++03版本,该版本并没有对核心语言进行修改。2011年,新的C++标准C++11面世,增加了多线程支持、通用编程支持等,标准库也有很多变化,集成了C++技术报告1库(TR1)中的大部分内容。2014年12月15号,C++ ISO/IEC标准的最新版本C++14。C++14是对C++11的小范围的扩展,主要内容是修复bug和略微提高性能。
参考文献 Bjarne Stroustrup著,裘宗燕译. C++程序设计语言(特别版).机械工业出版社 2009.http://zhidao.baidu.com/link?url=eLW5nMUN3ljGPGVb9q63VeQJ1Xkxsk3Iuy4m3iiF3GHBfQhIE6mwpZYWz0wZIovjnV0iFZGEepT1-jMJNcMw5qhttp://www.howzhi.com/course/3687/lesson/43412http://blog.jobbole.com/64349/https://en.wikipedia.org/wiki/C%2B%2B03https://en.wikipedia.org/wiki/C%2B%2B14https://en.wikipedia.org/wiki/C%2B%2B#Standardization
师兄发了一篇CCF-C类的文章,但是那个会议在澳洲排名属于B类,他说他在CVPR的某一篇文章的基础之上用了MST算法,避免了局部最优解,找到了全局最优解,实验结果比原文好很多,整个文章加实验前后仅仅做了2周。真是羡煞旁人也。。其实在机器学习当中,经常会遇到局部最优解的问题,所以,就花了点时间看看MST,兴许我也能找点灵感呢,呵呵..
看完最小生成树之后得到的一个想法就是:其实MST就是一种贪心算法,每一步选择都是选取当前候选中最优的一个选择。下面详细谈谈我认识的最小生成树吧
1. 最小生成树解决什么样的问题
城市之间建设道路的问题,首先,因为道路照价较高所以我们希望总的道路是最短的;其次,我们希望造的路在每个城市之间不会形成环路。那么MST的数学表达式就是这样,期望在图 G(V,E) 中找到一个子集 T 使得,使得造价函数w(T) 最小
2. MST 伪代码
在算法导论中对最小生成树的伪代码是这样描述的:
GENERIC(G,w){ A = empty while A does not form a spanning tree find an edge (u,v) that is safe for A A = A & (u,v) return A }算法的核心是在找到一条对于集合A安全的边。那么如何定义“安全”呢? 安全边 先要定义一个名词: 切割:无向图 G=(V,E) (V代表图中的结点,E代表图中两个节点之间的边) 的一个切割就是 (S , V-S) 就是集合V 的一个切割。 如上图就是图 G 的一个切割实例,如果图中的某一条边 (u,v) 的一个端点位于集合 S 中,另一个端点位于 V-S 中,那么这条边 横跨切割 (S , V-S)。如果集合 A 中不存在这样的横跨边,那么该切割 尊重集合 A 。在横跨一个切割的所有边中,权重最小的边称为 轻量级边。上图中红色结点属于集合 S ,白色结点属于集合 V-S ,横跨改切割的边是那些连接红色与白色结点的边,边 (c,d) 是横跨改切割的唯一一条轻量级边。其中红色边属于子集 A :注意切割 (S , V-S) 尊重集合A,因为集合 A 中没有横跨改切割的边。那么安全边的定于有如下定义 设G=(V , E) 是一个在边E上定义了实数权值函数 w 的的连通无向图。设集合 A 为 E 的一个子集,且 A 包括在图G的某棵最小生成树中,设 (S , V-S) 是图G中尊重集合A的任意一个切割,又设 (u,v) 是横跨切割 (S,V-S) 的一条轻量级边。那么边 (u,v) 对于集合 A 是安全的。 3.
一、CoordinatorLayout有什么作用 CoordinatorLayout作为“super-powered FrameLayout”基本实现两个功能: 1、作为顶层布局 2、调度协调子布局
CoordinatorLayout使用新的思路通过协调调度子布局的形式实现触摸影响布局的形式产生动画效果。CoordinatorLayout通过设置子View的 Behaviors来调度子View。系统(Support V7)提供了AppBarLayout.Behavior, AppBarLayout.ScrollingViewBehavior, FloatingActionButton.Behavior, SwipeDismissBehavior<V extends View> 等。 使用CoordinatorLayout需要在Gradle加入Support Design Library:
compile 'com.android.support:design:22.2.1' 二、CoordinatorLayout与FloatingActionButton 定义布局文件:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|bottom" android:layout_margin="16dp" android:src="@drawable/ic_done" /> </android.support.design.widget.CoordinatorLayout> CoordinatorLayout作为“super-powered FrameLayout”,设置子视图的android:layout_gravity属性控制位置。
Activity:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view,"FAB",Snackbar.LENGTH_LONG) .setAction("cancel", new View.OnClickListener() { @Override public void onClick(View v) { //这里的单击事件代表点击消除Action后的响应事件 } }) .
boost基本库包含很多实用的类库,比如队列,以下是高性能queue的简单例子
1.创建工程,然后设置头文件和lib库的路径,值得注意的是,Debug时必须选择“多线程调试(/MTD)”,Release时选择"多线程(/MT)";
2.包含头文件
#include <boost/lockfree/queue.hpp> #include <boost/bind.hpp> #include <boost/threadpool.hpp> #include <boost/thread/mutex.hpp> using namespace boost; using namespace boost::threadpool; using namespace boost::lockfree; 3.定义一个结构体tagMyStruct,和结构体队列que
typedef struct _MYSTRUCT_ { int nID; char GUID[64]; _MYSTRUCT_() { memset(this,0x0,sizeof(_MYSTRUCT_)); } }tagMyStruct; //指定使用固定大小的队列 //boost::lockfree::fixed_sized<true> //使用动态大小的队列 //boost::lockfree::fixed_sized<false> boost::lockfree::queue<tagMyStruct, fixed_sized<false> > que(0); 4.定义一个全局的递增变量g_nID;为了测试队列的性能,定义三个线程,其中两个线程写数据到队列que,另外一个线程从队列读数据,看读出来的数据是否会混乱;
注:i++,i--,++i,--i均不是原子操作,实际使用中,需要对g_nID改写的业务加锁。
int g_nID=0; void Thread_SetQueue() { bool bRet = false; //插入数据 tagMyStruct tagIn; strcpy(tagIn.GUID,"1234556"); while (1) { tagIn.nID = g_nID++; bRet = que.push(tagIn); boost::thread::sleep(boost::get_system_time()+boost::posix_time::millisec(1000)); } } void Thread_SetQueue2() { bool bRet = false; //插入数据 tagMyStruct tagIn; strcpy(tagIn.
Description 输入一个整数n和n个整数,输出这n个整数的最大值。
Input 输入有两行:第一行是一个正整数n,第二行是n个整数。
Output 输出包含一个整数,即n个数中的最大值,单独占一行。
Sample Input 43 7 5 6 Sample Output 7 HINT Source #include<stdio.h> #include<limits.h> int main() { int i, n; int number, max; scanf("%d", &n); max = INT_MIN; //将max赋值为int类型的最小极限值 for(i = 1; i <= n; i++) { scanf("%d", &number); //读入一个值 if(number > max) //若比max,则更新max max = number; } printf("%d\n", max); return 0; }
package shopping; import java.util.Scanner; public class Shopping { //实现购物结算功能 public static void main(String []args){ Scanner sc=new Scanner(System.in); int buyOrNot = 0;//选择买还是取消 do{ System.out.println("====请选择要购买的商品===="); System.out.println("====1.T恤 ===="); System.out.println("====2.手机 ===="); System.out.println("====3.电脑 ===="); System.out.println("请选择输入的编号 :"); int choose1=sc.nextInt(); switch(choose1){ case 1: System.out.println("====请选择品牌 ===="); System.out.println("====1.阿迪 ===="); System.out.println("====2.耐克 ===="); System.out.println("====3.李宁 ===="); //选择购买的是什么品牌 int choose2=sc.nextInt(); switch(choose2){ case 1: System.out.println("====请确认价格 ===="); System.out.println("====您购买的阿迪牌T恤价格为"+Math.round(300*0.95)+" ===="); System.out.println("====1.购买 ===="); System.out.println("====0.取消 ===="); buyOrNot=sc.nextInt(); if(buyOrNot==1){ System.out.println("恭喜你购买成功"); System.out.println("拜拜");break; }else{ System.out.println("请重新选择:"); } break; case 2: System.out.println("====请确认价格 ===="
1. 点开“开始”-运行regedit.exe,进入注册表编辑器,到左边的项目栏里找到
HKEY_LOCAL_MACHINE\SYSTEM \CurrentControlSet\Control\Class\{4D36E965-E325-11C E-BFC1-08002BE10318}选定,在右面窗口找到upperfilter”项和“loweverfilter”项。点右键删除 “upperfilter”项和“loweverfilter”项。
2.在设备管理器中卸载有疑问的光驱,卸载之后在点击扫描硬件改动,会找到光驱。这时候光驱就恢复正常了,如果还不可以就重新启动计算机。
查看原文:http://blog.indexroot.net/2015/08/27/cd-or-dvd-driver-fault/
OS开发中经常要用到输入框,默认情况下点击输入框就会弹出键盘,但是必须要实现输入框return的委托方法才能取消键盘的显示,对于用户体验来说很不友好,我们可以实现点击键盘以外的空白区域来将键盘隐藏,以下我总结出了几种隐藏键盘的方法:
首先说明两种可以让键盘隐藏的Method:
1、[view endEditing:YES] 这个方法可以让整个view取消第一响应者,从而让所有控件的键盘隐藏。
2、[textFiled resignFirstResponder] 这个则是比较常用的让某个textFiled的键盘隐藏。
接下来就是几种实现方式:
第一种: 使用view的touchesBegan:触摸事件来实现对键盘的隐藏,当点击view的区域就会触发这个事件
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ [textFiled resignFirstResponder]; } 第二种:创建自定义的触摸手势来实现对键盘的隐藏: - (void)viewDidLoad { [super viewDidLoad]; UITap *tap = [[UITap alloc] initWithTarget:self action:@selector(keyboardHide:)]; //设置成NO表示当前控件响应后会传播到其他控件上,默认为YES。 tap.cancelsTouchesInView = NO; //将触摸事件添加到当前view [self.view addGestureRecognizer:tapGestureRecognizer]; } -(void)keyboardHide:(UITap*)tap{ [textFiled resignFirstResponder]; } 第三种:修改xib中UIView的Custom class为UIControl,UIControl是一些常用控件如UIButton的父类,是UIView的派生类,实现了对触摸和下按的封装。 1、首先设置xib中得UIView的Custom class为UIControl 2、设置关系事件,将xib中得UIView拖到.h区中 设置好事件为Touch Up Inside 3、编写隐藏代码:
- (IBAction)touchView:(id)sender { [self.view endEditing:YES]; }
1 Overview 图1
如上图为整个PCIE的框架,在C1中PIPE-CompliantPHY部分的SERDES模块,DWC PCIe Core为synopsys提供的IP,而黄色部分为用户需要完成的部分,主要包括参数的配置和数据的发送和接收。
2 Architecture 图2
该IP包含4个重要的模块,CXPL、RADM、XADM、CDM。
Ø Common ExpressPort Logic (CXPL) Module:
整个协议的核心部分,包含了物理层、数据链路层的全部功能、同时包含了传输层大部分的功能。其中包含了一个重要的缩写,LTSSM(link training and statues state machine),在后面的文档中将重复出现,link training的目的在于完成链路的链接。
Ø TransmitApplication-Dependent Module (XADM):
面向数据包发送的应用模块,主要包括以下3个功能:
l TLP(Transaction Layer Packet)arbitration
l TLP formation
l Flow control creditchecking
该模块内部为直接转发的结构,除了重发的缓存区外,内部没有发送的缓存区。
Ø ReceiveApplication-Dependent Module (RADM):
面向数据包接收的应用模块,主要包括以下3个功能:
l Sorting/filtering of received TLPs. The filtering rules and routing areconfigurable.
l Buffering and queuing ofthe received TLPs.
l Routing of received TLPto the core’s receive interfaces.
【-1】写在前面: 以下部分内容总结于 http://blog.csdn.net/ruyanhai/article/details/7181842 complementary: 兼容性是指运行在前期CPU,如8086/8088上的的程序,也可以运行在其以后的处理器,如80286上; 【0】看看intel处理器的发展历程 【1】8086/8088的寻址和问题 1.1)寻址:在8086/8088中,只有20根地址总线,所以可以访问的地址是2^20=1M,但由于8086/8088是16位地址模式,能够表示的地址范围是0-64K,所以为了在8086/8088下能够访问1M内存,Intel采取了分段的模式:16位段基地址:16位偏移。其绝对地址计算方法为:16位基地址左移4位+16位偏移=20位地址;(这个比较简单) 1.2)问题: 但这种方式引起了新的问题,通过上述分段模式,能够表示的最大内存为:FFFFh:FFFFh=FFFF0h+FFFFh=10FFEFh=1M+64K-16Bytes(1M多余出来的部分被称做高端内存区HMA)。但8086/8088只有20位地址线,如果访问100000h~10FFEFh之间的内存,则必须有第21根地址线。所以当程序员给出超过1M(100000H-10FFEFH)的地址时,系统并不认为其访问越界而产生异常,而是自动从重新0开始计算,也就是说系统计算实际地址的时候是按照对1M求模的方式进行的,这种技术被称为wrap-around。 【2】80286的寻址和问题 2.0)寻址: 到了80286,系统的地址总线发展为24根,这样能够访问的内存可以达到2^24=16M。Intel在设计80286时提出的目标是,在实模式下,系统所表现的行为应该和8086/8088所表现的完全一样,也就是说,在实模式下,80286以及后续系列,应该和8086/8088完全兼容; 2.1)问题:如果程序员访问100000H-10FFEFH之间的内存,80286将实际访问这块内存,而不是像过去一样重新从0开始,因为80286有这个寻址能力,但是这就不能满足和8086/8088的系统兼容性,因为8086/8088不能访问到100000H-10FFEFH之间的内存的真实地址而是按照对1M求模的内存寻址方式; 【3】再浅谈80286 和 8086/8088 间的兼容性问题:(实模式下,80286的系统表现要同8086/8088的一致) 3.1)当A20被禁止时:程序员给出100000H~10FFEFH间的地址,80286和8086/8088 的系统表现是一致的,即按照对1M求模的方式进行寻址,满足系统升级的兼容性问题; 3.2)当A20被开启时:程序员给出的100000H~10FFEFH间的地址,80286是访问的真实地址,而8086/8088是始终是按照对1M求模的方式进行的(这里注意,是始终); 【4】解决方法: 为了解决上述问题,IBM使用键盘控制器上剩余的一些输出线来管理第21根地址线(从0开始数是第20根),被称为A20Gate:如果A20 Gate被打开,则当程序员给出100000H-10FFEFH之间的地址的时候,系统将真正访问这块内存区域;如果A20Gate被禁止,则当程序员给出100000H-10FFEFH之间的地址的时候,系统仍然使用8086/8088的方式。 【5】有请实模式+保护模式闪亮登场(干货) 5.1)实模式:实模式就是, 为了实现系统升级的兼容性,如80286的系统表现(包括80286以后的CPU)要与8086/8088 的系统表现一致,就需要80286 CPU访问100000H-10FFEFH之间的地址的时候, 按照对1M求模的方式进行, 无论A20地址线开启关闭与否, 这种内存访问情况 称为实模式; 5.2)保护模式:保护模式就是, 以A20地址线开启为前提,80286 CPU访问100000H-10FFEFH之间的地址的时候, 是访问真实的内存地址,不是求模访问,如访问100001H,就是真真切切地 访问 0x 100001H,而不是求模的 0x000001H 地址, 这种内存访问情况称为保护模式; 5.3)诞生日: 实模式是从8088/8086 就开始存在了, 而保护模式从 80286 才开始存在; 【6】为什么需要保护模式?(因为实模式与生俱来,是伴随着8088/8086 从天而降的,它仅仅是访问内存的一种方式而已; 还有对于8086/8088而言,它只有实模式这一种内存寻址方式,而对于80286包括其以后的CPU,有实模式和保护模式两种寻址方式,因为要兼顾系统兼容性) 显然随着CPU的升级,8088/8086的内存寻址方式已经无法满足需要,也可以说,为了能够访问10FFEFH以上的内存,则必须进入保护模式; 【7】A20被禁止+被开启的不同结果 7.1)如果A20Gate被禁止:对于80286来说,其地址为24bit,其地址表示为EFFFFF;对于80386极其随后的32-bit芯片来说,其地址表示为FFEFFFFF。这种表示的意思是如果A20Gate被禁止,则其第20-bit在CPU做地址访问的时候是无效的,永远只能被作为0; 7.2)如果A20 Gate被打开:则其第20-bit是有效的,其值既可以是0,又可以是1; 7.3)所以:在保护模式下,如果A20 Gate被打开,则可以访问的内存则是连续的;如果A20Gate被禁止,则可以访问的内存只能是偶数段, 因为是20位(从0始)总为零,所23~20位只能是0000、0010、0100、0110、1000、1010、1100、1110对应十六进制为0、2、4、6、8、A、C、E。对应的十六进制地址段是000000-0FFFFF,200000-2FFFFF,400000-4FFFFF… 版权声明:本文为博主原创文章,未经博主允许不得转载。
转载于:https://www.cnblogs.com/pacoson/p/4893169.html
题目 The count-and-say sequence is the sequence of integers beginning as follows: 1, 11, 21, 1211, 111221, …
1 is read off as “one 1” or 11. 11 is read off as “two 1s” or 21. 21 is read off as “one 2, then one 1” or 1211. Given an integer n, generate the nth sequence.
Note: The sequence of integers will be represented as a string.
分析 这是一道根据规则推导题目,要求给定序列数n,求出该序列对应的字符串。 规则如上图所示。
操作系统win2003sp2,已经是administrator了,但是创建新用户时提示:
在计算机 SERVER-05 上创建用户 abc 时,出现了以下错误:
拒绝访问。
百思不得其解,搜遍google和百度都没对症解药。
然后打开事件查看器,发现创建用户时系统抛错如下:
SAM 无法更改数据库。很可能是因为内存 或磁盘空间不足。SAM 数据库会被还原为先前状态。 最近的更改都会丢失。请检查可用磁盘空间 和页面文件大小设置的最大值。
搜了下SAM的相关知识,估摸着要么是文件被破坏,要么是权限不足
检查了windows/system32/config下面的SAM文件,都还健在,大小正常,查看权限administrator有完全控制权限。估计这块应该没问题。
打开注册表HKEY_LOCAL_MACHINE\SAM,发现是空的,应该是没有权限,右键,给administrators赋权完全控制后刷新。
继续打开到HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\这层,发现下面三个子项aliases、groups、users,竟然都没有权限,估计就是这儿了,继续给administrators赋权。
然后试着重新创建用户,这次成功了。
估计是什么安全软件把这个注册表项的权限给去掉了,才引起的这个问题。
----------------------------------------------------------------------- 方法一 ------------------------------------------------------------
一、迁移src
直接拷贝eclipse中src/com到AS中的src/main/java中。 二、迁移AndroidManifest.xml 直接复制eclipse的AndroidManifest.xml到AS的src/main目录中。 三、迁移图片等文件。
直接将eclipse的图片、风格文件复制到AS的src/main/res目录中。 四、复制*.jar
将eclipse的libs目录中的文件复制到AS的libs目录下。 五、复制*.so
将eclipse的libs/armeabi目录复制到AS的src/main/jniLibs目录下,若没有,则创建。
六、混淆文件添加
在build.gradle中进行配置
android { buildTypes {
release { minifyEnabled true proguardFiles getDefaultProguardFile('proguard-android.txt'),'some-other-rules.txt'
//proguardFile 'some-other-rules.txt' 配置单个文件这样
}
} } 如上面代码所示,我们可以使用minifyEnabled true开启,并且对其配置混淆配置,可以配置多个文件或单个文件。
android的sdk中已经为我们提供了两个默认的配置文件,我们可以拿过来进行使用,proguard-android.txt和proguard-android-optimize.txt。
七、添加assets
/src/main/assets
错误:
1、Error:Execution failed for task ':equipmenttesting:transformClassesWithDexForDebug'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/opt/jdk1.8.0_65/bin/java'' finished with non-zero exit value 1
解决:检查引用的包是否重复了。
----------------------------------------------------------------------- 方法二 ------------------------------------------------------------
将如下build.gradle拷贝到eclipse目录下,用android studio打开build.gradle ,加载完毕即可,过程中可能出现gradle不匹配,只要按需求更新下就好。
repositories { jcenter() flatDir { dirs 'libs' } } //添加以下代码,使classes-full-debug.
原文来自http://vegibit.com/laravel-repository-pattern/
Repository 模式 为了保持代码的整洁性和可读性,使用Repository Pattern 是非常有用的。事实上,我们也不必仅仅为了使用这个特别的设计模式去使用Laravel,然而在下面的场景下,我们将使用OOP的框架Laravel 去展示如何使用repositories 使我们的Controller层不再那么啰嗦、更加解耦和易读。下面让我们更深入的研究一下。
不使用 repositories 其实使用Repositories并不是必要的,在你的应用中你完全可以不使用这个设计模式的前提下完成绝大多数的事情,然而随着时间的推移你可能把自己陷入一个死角,比如不选择使用Repositories会使你的应用测试很不容易,具体的实现将会变的很复杂,下面我们看一个例子。
HousesController.php
<?php class HousesController extends BaseController { public function index() { $houses = House::all(); return View::make('houses.index',compact('houses')); } public function create() { return View::make('houses.create'); } public function show($id) { $house = House::find($id); return View::make('houses.show',compact('house')); } } 这是一个很典型的一段代码使用Eloquent和数据库交互,这段代码工作的很正常,但是controller层对于Eloquent而言将是紧耦合的。在此我们可以注入一个repository创建一个解耦类型的代码版本,这个解耦的版本代码可以使后续程序的具体实现更加简单。
使用 repositories 其实完成整个repository模式需要相当多的步骤,但是一旦你完成几次就会自然而然变成了一种习惯了,下面我们将详细介绍每一步。
1.创建 Repository 文件夹 首先我们需要在app文件夹创建自己Repository 文件夹repositories,然后文件夹的每一个文件都要设置相应的命名空间。
2: 创建相应的 Interface类 第二步创建对应的接口,其决定着我们的repository类必须要实现的相关方法,如下例所示,在此再次强调的是命名空间一定要记得加上。
HouseRepositoryInterface.php
<?php namespace App\Repositories; interface HouseRepositoryInterface { public function selectAll(); public function find($id); } 3:创建对应的 Repository类 现在我们可以创建我们repository类 来给我们干活了,在这个类文件中我们可以把我们的绝大多数的数据库查询都放进去,不论多么复杂。如下面的例子
1、OIO中,每个线程只能处理一个channel(同步的,该线程和该channel绑定)。 线程发起IO请求,不管内核是否准备好IO操作,从发起请求起,线程一直阻塞,直到操作完成,如图: NIO中,每个线程可以处理多个channel(异步)。
线程发起IO请求,立即返回;内核在做好IO操作的准备之后,通过调用注册的回调函数通知线程做IO操作,线程开始阻塞,直到操作完成 AIO中,线程发起IO请求,立即返回;内存做好IO操作的准备之后,做IO操作,直到操作完成或者失败,通过调用注册的回调函数通知线程做IO操作完成或者失败 那么OIO如何处理海量连接请求呢? 是对每个请求封装成一个request,然后从线程池中挑一个worker线程专门为此请求服务,如果线程池中的线程用完了,就对请求进行排队。请求中如果有读写数据,是会阻塞线程的
2、NIO中channel肯定是非阻塞模式的,否则抛出异常。为什么呢?因为前面selector异步通知程序的时候,通道中的数据肯定是有的。
3、同步与阻塞是不同的概念,异步与非阻塞也是不同的概念。
4、阻塞式iO会浪费大量的cup进行无意义的上下文切换,因为还是可能读/写不到任何数据。
5、同步阻塞:通常给人的印象。把通知应用程序和读/写消息结合在了一起,因为有了数据才能通知, 同步非阻塞:
异步阻塞:
异步非阻塞:通常给人的印象。因为如果是异步通知的话,肯定是能拿到数据的。有效减少线程切换。目前java的nio的异步看起来是阻塞的,因为阻塞在select.select()操作上了。但是其实可以通过select.wakeUp()方法,不用一直阻塞。但要想获得通道状态,还是必须等待select.select返回才行的。
综上所述,同步和阻塞给人的概念是一样的。而异步和非阻塞跟给人的概念是一样的
6、同步异步指的是通信模式,而阻塞和非阻塞指的是在接收和发送时是否等待动作完成才返回所以不能混淆这四个词。
首先是通信的同步,主要是指客户端在发送请求后,必须得在服务端有回应后才发送下一个请求。所以这个时候的所有请求将会在服务端得到同步 其次是通信的异步,指客户端在发送请求后,不必等待服务端的回应就可以发送下一个请求,这样对于所有的请求动作来说将会在服务端得到异步,这条请求的链路就象是一个请求队列,所有的动作在这里不会得到同步的。 阻塞和非阻塞只是应用在请求的读取和发送。 在实现过程中,如果服务端是异步的话,客户端也是异步的话,通信效率会很高,但如果服务端在请求的返回时也是返回给请求的链路时,客户端是可以同步的,这种情况下,服务端是兼容同步和异步的。相反,如果客户端是异步而服务端是同步的也不会有问题,只是处理效率低了些。
同步=阻塞式,异步=非阻塞式 同步和异步都只针对于本机SOCKET而言的 同步模式下,比如RECIEV和SEND,都要确保收到或发送完才返回,继续执行下面的代码不然就阻塞在哪里,所以,同步模式下,一般要用到线程来处理。
异步模式就不同了,不管有没有收到或发送出去,他都马上返回,继续执行下面的代码,结果由消息通知。
另外可参考:http://my.oschina.net/u/2001537/blog/353035
Android中Java与web通信不是新的技术了,在android发布之初就支持这种方式,2011年开始流行,而这种模式开发也称作Hybird模式。这里对android中的Java与web通信方式做一下总结。Android中有3种方式可以实现Java与web通信。
1、重写WebViewClient private class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (Uri.parse(url).getHost().equals("www.example.com")) { // This is my web site, so do not override; let my WebView load the page Toast.makeText(WebViewClientActivity.this, url, Toast.LENGTH_SHORT).show(); return false; } return true; } } 通过 shouldOverrideUrlLoading(WebView view, String url)返回的url获取数据 例如:url=“www.example.com?body=loadurl” 可以截取后面的body数据。
在web中调用方式:
<button οnclick="window.open('www.example.com?body=loadurl')">showAndroidToast</button> 2、重写WebChromeClient final class MyWebChromeClient extends WebChromeClient { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { Log.
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5412 题意:带修改的区间第k小,允许离线 分析:这道经典的问题有多种做法,其中知名度比较高的有树状数组套主席树( nlog2n 空间+ nlog2n 时间),线段树套平衡树( nlogn 空间+ nlog2n 时间)。然而树套树不仅代码量大,而且难写难调,令人望而生畏。这里介绍一种神奇的方法替代树套树。 整体二分,顾名思义,对所有询问二分答案,然后判定每个询问的答案是否大于当前标准,据此决定将询问划分到左区间还是右区间。 把一开始的所有数都看成操作,因此现在原数列是空的,操作有三种: 1.给位置l增加一个数x. 2.给位置l减少一个数x 3.询问[l,r]中不大于mid的数是否 < <script type="math/tex" id="MathJax-Element-409"><</script>k个,其中mid为当前的判定标准 思路很简单,写起来有些细节要考虑。空间复杂度可以做到 O(n) ,但是方便起见,我用 O(nlogn)的空间 去实现。时间复杂度也很好算,假如把所有数值离散化,考虑线段树的模型,总共节点数只有 O(n) ,总共 logn 层,每层的操作数之和是 O(n) ,每个节点需要做一次 O(qlogn)(q为节点的操作数) 的判定,所以总复杂度是 O(qlog2n) 代码很短,而且不容易写错
#include<bits/stdc++.h> using namespace std; const int Maxn=100020; int nq; int ty[Maxn*3],ql[Maxn*3],qr[Maxn*3],qk[Maxn*3],rep[Maxn*3]; vector<int>dp[Maxn<<2]; int L[Maxn<<2],R[Maxn<<2]; int val[Maxn]; int n,m; int front,rear,via[Maxn],a[Maxn]; vector<int>V; int getid(int x){return lower_bound(V.begin(),V.end(),x)-V.begin();} inline int low(int x){return x&(-x);} int ask(int loc) { int ret=0; for(int i=loc;i>=1;i-=low(i))if(via[i]==front)ret+=a[i]; return ret; } void upd(int loc,int w) { for(int i=loc;i<=n;i+=low(i)) { if(via[i]<front){via[i]=front;a[i]=w;} else a[i]+=w; } } int main() { while(scanf("
1.报错信息:
django.core.exceptions.ImproperlyConfigured: Requested setting LOGGING_CONFIG,but settings are not configured. You must either define the environmentvariable DJANGO_SETTINGS_MODULE or call settings.configure() before accessingsettings.
需要添加两行语句:
import os
os.environ['DJANGO_SETTINGS_MODULE']= 'mysite.settings'
注释:在什么情况下出现上述错误呢?在我编写程序的过程遇到这个错误时,是当我引入models时,比如在文件开始我引包时from database.models import list_url_save,就会出现这个提示的错误。是因为程序没有识别出database这个应用,我已经把database应用添加到settings文件INSTALLED_APPS中了,但还是需要在文件开头添加那两行环境变量的配置语句,让程序知道去哪里寻找models中的文件。
2.报错信息:
"The translation infrastructure cannotbe initialized before the "
django.core.exceptions.AppRegistryNotReady: The translation infrastructurecannot be initialized before the apps registry is ready. Check that you don'tmake non-lazy gettext calls at import time.
需要添加两行语句:
import django
django.setup()
两者的引用顺序也是有要求的,先引用import os 再引用import django。。。。。。
修改 /etc/opkg.config 配置文件 将此文件内容换为下面内容,即可解决opkg update download时报错的问题
dest root / dest ram /tmp lists_dir ext /var/opkg-lists option overlay_root /overlay arch all 10 arch ar71xx 100 src/gz barrier_breaker_base http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/base src/gz barrier_breaker_luci http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/luci src/gz barrier_breaker_management http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/management src/gz barrier_breaker_oldpackages http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/oldpackages src/gz barrier_breaker_packages http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/packages src/gz barrier_breaker_routing http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/routing src/gz barrier_breaker_telephony http://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/packages/telephony 问题解决参考网址:http://www.right.com.cn/forum/thread-149434-1-1.html
本文描述:渗透测试中,windows/linux环境下,使用代理访问内网服务器。
环境:
本地Windows的IP: 172.18.5.26
本地Linux的IP:172.18.5.116
远程公网IP: 221.6.25.208
远程公网221.6.25.208映射的内网服务器ip:172.20.1.3
其中,可通过221.6.25.208:80端口提供的服务上传文件至172.20.1.3
一、 windows环境:reGeorg与proxifier 1.1 搭建reGeorg运行环境python 1.1.1 按照自己系统的环境,在 https://www.python.org/downloads/windows/下载对应的python
1.1.2 安装完后验证python是否安装成功:命令提示符下敲Python --verseion
至此,Python基本的安装完成了。
1.2 安装reGeorg 1.2.1 下载reGeorg-master (https://github.com/sensepost/reGeorg),Copy到 C:\Python27\ 。
1.2.2 安装setuptools (a)下载ez_setup.py(https://pypi.python.org/pypi/setuptools#windows-simplified),Copy到 C:\Python27\ 。
(b)在命令提示符下切换到C:\Python27\,依次运行如下命令
python ez_setup.py build
python ez_setup.py install
看到 Finished就可以了,表示setuptools安装成功。
1.2.3 安装Pip
(a)下载地址http://pypi.python.org/packages/source/p/pip/pip-1.0.tar.gz ,解压,目录现在可以随便放了,因为刚刚安装了setuptools了.
(b) 依次运行如下命令
python setup.py build
python setup.py install
看到 Finished就可以了,表示Pip安装成功。
1.2.4 安装urllib3。(urllib3是reGeorg开启代理必需的模块)
在命令提示符下切换到C:\Python27\Scripts,直接运行pip install urllib3 。
至此,reGeorg安装完成。
1.3 使用reGeorg开启socks5反向代理服务 1.3.1 上传反向代理服务端至远程主机
通过221.6.25.208:80端口提供的服务,上传C:\Python27\reGeorg-master目录下tunnel.jsp文件至远程目标机。
1.3.2 开启socks5反向代理服务
对无锁队列的最初兴趣来自梁斌同志的一个英雄帖:http://coderpk.com/。 第一次看到这个题目的时候还不知道CAS,FAA等所谓的“原子操作”,但直觉上感觉,通过对读写操作的性能优化来达到大幅提高队列性能的方法是行不通的,就算读写操作全用汇编来写,也不会和正常的read及 write有数量级上的区别。后来搜索了一下lock free data structure,才知道了关于原子操作的一些东西,同时也纠正了自己由来已久的一个错误观点:C++中的++操作和--操作都不是原子操作。这篇笔记将记录在我在探索这个问题的过程中产生的一些想法,同时对多线程编程——或者说是并发编程的一些问题进行备忘。
多线程及并发
线程是操作系统进行作业调度的最小单位,也是进程内部的一条执行路径。与进程不同,线程并没有对操作系统的资源所有权,也就是说多个线程对资源的访问权是共享的。一个进程中的所有线程共享一个地址空间或者诸如打开的文件之类的其他资源,一个进程对这些资源的任何修改,都会影响到本进程中其他线程的运行。因此,需要对多个线程的执行进行细致地设计,使它们能够互不干涉,并且不破坏共享的数据及资源。
在单处理器中的并发系统里,不同进程和线程之间的指令流是交替执行的,但由于调度系统及CPU时钟的配合,使得程序对外表现出一种同时执行的外部特征;而在并行多处理器系统中,指令流之间的执行则是重叠的。无论是交替执行还是重叠执行,实际上并发程序都面临这同样的问题,即指令流的执行速度不可预测,这取决于其他指令流的活动状态、操作系统处理中断的方式及操作系统的调度策略。这给并发程序设计带来了如下的一些问题:
1)多个进程(或线程)对同一全局资源的访问可能造成未定义的后果。例如,如果两个并发线程都使用同一个全局变量,并且都对该变量执行读写操作,那么程序执行的结果就取决于不同的读写执行顺序——而这些读写执行顺序是不可预知的。
2)操作系统难以对资源进行最优化分配。这涉及到死锁及饥饿的问题。
3)很难定位程序的错误。在多数情况下,并发程序设计的失误都是很难复现的,在一次执行中出现一种结果,而在下一次执行中,往往会出现迥然不同的其他结果。
因此,在进行多线程程序或者并发程序的设计时,尤其需要小心。可以看到的是,绝大多数并发程序的错误都出现在对共享资源的访问上,因此,如何保证对共享资源的访问以一种确定的、我们可以预知的方式运行,成为并发程序设计的首要问题。在操作系统领域,对共享资源的访问有个专用的数据,称为临界区。
临界区是一段代码,在这段代码中,进程将访问共享资源。当另外一个进程已经在这段代码中执行时,这个进程就不能在这段代码中执行。
也就是说,临界区是一个代码段,这个代码段不允许两条并行的指令流同时进入。提供这种保证的机制称为互斥:当一个进程在临界区访问共享资源时,其他进程不能进入该临界区。
锁及互斥
实现互斥的机制,最重要的是互斥锁(Mutex)。互斥锁实际上是一种二元信号量(只有0和1),专用于多任务之间临界区的互斥操作。(关于信号量及互斥锁的区别,可以参看操作系统相关知识)
Mutex本质上是一个信号量对象,只有0和1两个值。同时,mutex还对信号量加1和减1的操作进行了限制,即某个线程对其进行了+1操作,则-1操作也必须由这个线程来完成。mutex的两个值也分别代表了Mutex的两种状态。值为0, 表示锁定状态,当前对象被锁定,用户进程/线程如果试图Lock临界资源,则进入排队等待;值为1,表示空闲状态,当前对象为空闲,用户进程/线程可以Lock临界资源,之后Mutex值减1变为0。
Mutex可以抽象为创建(Create),加锁(Lock),解锁(Unlock),及销毁(Destroy)等四个操作。在创建Mutex时,可以指定锁的状态是空闲或者是锁定,在linux中,这个属性的设置主要通过pthread_mutex_init来实现。
在使用mutex的时候,务必需要了解其本质:Mutex实际上是一个在多个线程之间共享的信号量,当其进入锁定状态时,再试图对其加锁,则会阻塞线程。例如,对于两个线程A和B,其指令序列如下:
线程A
线程B
1.lock(&mutex);
2.do something;
3.unlock(&mutex);
1.lock(&mutex);
2.do something;
3.unlock(&mutex);
在线程A的语句1处,线程A对mutex进行了加锁操作,mutex变为锁定状态。在线程A的语句2及线程B的语句1处,A尚未对mutex进行解锁,而B则试图是mutex进行加锁操作,因此线程B被阻塞,直到A的语句3处,线程A对mutex进行了解锁,B的语句1才得以继续执行,将mutex进行加锁并继续执行语句2和语句3。因此,如果在do something中有对共享资源的访问操作,那么do something就是一个临界区,每次都只有一个线程能够进入这段代码。
原子操作
无论是信号量,还是互斥,其中最重要的一个概念就是原子操作。所谓原子操作,就是不会被线程调度机制所打断的操作——从该操作的第一条指令开始到最后一条指令结束,中间不会有任何的上下文切换(context switch)。
在单处理器系统上,原子操作的实现较为简单:第一种方式是一些单指令即可完成的操作,如compare and swap、test and set等;由于上下文切换只可能出现在指令之间,因此单处理器系统上的单指令操作都是原子操作;另一种方式则是禁用中断,通过汇编语言支持,在指令执行期间,禁用处理器的所有中断操作,由于上下文切换都是通过中断来触发的,因此禁用中断后,可以保证指令流的执行不会被外部指令所打断。
而在多处理器系统上,情况要复杂一些。由于系统中有多个处理器在独立地运行,即使能在单条指令中完成的操作也有可能受到干扰。如,在不同的CPU运行的两个进行都在执行一条递减指令,即对内存中某个内存单元的值-1,则指令流水线可能是这样:(省略了取指)
A处理器: |--读内存--|--计数减1--|--写内存--|
B处理器: |--读内存--|--计数减1--|--写内存--|
假设原来内存单元中存储的值为5,那么,A、B处理器所读到的内存值都为5,其往内存单元中写入的值都为4。因此,虽然进行了两次-1操作,但实际上运行的结果和执行了1次是一样的。
注:这是一个数据相关问题(关于数据相关问题,可以参考计算机体系结构中指令流水线的设计及数据相关的避免等资料),在单处理机中,这个问题可以通过检查处理机中的指令寄存器,来检查在流水线中的指令之间的相关性,如果出现数据相关的情况,可以通过延迟相关指令执行的方法来规避;而在对称多处理机中,由于CPU之间相互不知道对方的指令寄存器状态,那么这种流水线作业引起的数据竞跑就无法避免。
为了对原子操作提供支持,在x86 平台上,CPU提供了在指令执行期间对总线加锁的手段。CPU芯片上有一条引线#HLOCK pin,如果汇编语言的程序中在一条指令前面加上前缀"LOCK",经过汇编以后的机器代码就使CPU在执行这条指令的时候把#HLOCK pin的电位拉低,持续到这条指令结束时放开,从而把总线锁住,这样同一总线上别的CPU就暂时不能通过总线访问内存了,保证了这条指令在多处理器环境中的原子性。
可以看出,其实pthread_mutex_lock及pthread_mutex_unlock就是一个原子操作。它保证了两个线程不会同时对某个mutex变量加锁或者解锁,否则的话,互斥也就无从实现了。
i++和++i是原子操作吗?
有一个很多人也许都不是很清楚的问题:i++或++i是一个原子操作吗?在上一节,其实已经提到了,在SMP(对称多处理器)上,即使是单条递减汇编指令,其原子性也是不能保证的。那么在单处理机系统中呢?
在编译器对C/C++源代码进行编译时,往往会进行一些代码优化。例如,对i++这条指令,实际上编译器编译出的汇编代码是类似下面的汇编语句:
1.mov eax,[i]
2.add eax,1
3.mov [i],eax
语句1是将i所在的内存读取到寄存器中,而语句2是将寄存器的值加1,语句3是将寄存器值写回到内存中。之所以进行这样的操作,是为了CPU访问数据效率的高效。可以看出,i++是由一条语句被编译成了3条指令,因此,即使在单处理机系统上,i++这种操作也不是原子的。这是由于指令之间的乱序执行而造成的,注意和上节中,指令流水线之间的数据竞跑造成的数据不一致的区别。
GCC的内建原子操作(锁定总线的方法来保证原子操作)
在GCC中,从版本4.1.2起,提供了__sync_*系列的built-in函数,用于提供加减和逻辑运算的原子操作。这些操作通过锁定总线,无论在单处理机和多处理机上都保证了其原子性。GCC提供的原子操作主要包括:
type__sync_fetch_and_add (type *ptr, type value, .
题目链接:
poj1043
题意:
一个犯罪团伙有N个人,他们分别有一个名字和一个网名
现已知他们会先后进出一个房间发送电报
警方可以知道所有时间下:
进出房间的人的真实名字
同时通过截获该房间发出的电报,获得网名
问最后能否将所有真实名字和虚拟网名对上
解题思路:
首先根据题目条件名字和网名是一一对应的,可以大概确定是二分匹配中的完美匹配
然而根据样例很容易看出来,要想根据正确关系来建边是很复杂的
容易的做法是:每次将不可能匹配的名字和网名建边,最后根据补图进行最大匹配即可初步得出所有匹配关系.
但现在得到的最大匹配不一定是完美匹配
要确定某个名字和网名是匹配的 我们可以删除当前已匹配的边,再进行最大匹配
如果结果减小了,则一定是对应的
这样,依次枚举每一条最大匹配中的边.即可得出答案
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #define maxn 25 using namespace std; struct node { string a,b; } s[maxn]; map<string,int>m1,m2; string s1[maxn]; int edge[maxn][maxn]; int link[maxn],vis[maxn]; int mark[maxn]; int id,n; void init() { memset(edge,0,sizeof(edge)); memset(mark,0,sizeof(mark)); id=1; m1.clear(),m2.clear(); } int cmp(node x,node y) { return x.a<y.a; } int dfs(int u) { for(int i=1;i<=n;i++) { if(!
Java和C数据类型的对应表如下:
Java 类型
C 类型
原生表现
boolean
int
32位整数 (可定制)
byte
char 8位整数
char
wchar_t
平台依赖
short
short
16位整数
int
int
32位整数
long
long long, __int64
64位整数
float
float
32位浮点数
double
double
64位浮点数
Buffer/Pointer
pointer
平台依赖(32或 64位指针)
<T>[] (基本类型的数组)
pointer/array
32或 64位指针(参数/返回值)
邻接内存(结构体成员)
String
char*
/0结束的数组 (native encoding or jna.encoding)
WString
wchar_t*
/0结束的数组(unicode)
String[]
char**
/0结束的数组的数组
WString[]
wchar_t**
/0结束的宽字符数组的数组
Structure
struct*/struct
指向结构体的指针 (参数或返回值) (或者明确指定是结构体指针) 结构体(结构体的成员) (或者明确指定是结构体)
Union
union 等同于结构体
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5393 题意:给出 k,b,x0,p , xn=(xn−1∗k+b)modp ,求最小的n,使得 xn=x0 ,如果不存在输出-1。 分析:通过简单的数学推导,题目即求最小的n使得 ((k−1)∗x0+b)∗(1+k+k2+k3+...kn−1)≡0modp 根据同余的性质, (a∗g)mod(b∗g) 等价于 amodb ,于是可以消去 gcd(p,(k−1)∗x0+b) ,剩下的就是求最小的n使得 1+k+k2+k3+...kn−1≡0modq 两边同乘 k−1 ,由于 k−1 不一定与q互质,因此由此推出来的式子只是原式的必要条件,我们得到 kn≡1modq 假如k,q不互质,上式恒不成立,原式无解,否则根据欧拉定理,有 kΦ(q)≡1modq 我们只需要检查 Phi(q)的约数,得到最小的n满足条件。 假设真实的答案为ans,根据前面的推导,ans必然为n的倍数,设 ans=g∗n 则 1+k+k2+k3+...kans−1≡g∗(1+k+k2+k3+...kn−1)modq 因此只需要把n带回去,然后求lcm即可,注意带回去算答案可以只用一个log的复杂度,总复杂度就是分解约数的复杂度*powmod的复杂度,大概是 log2p #include<bits/stdc++.h> using namespace std; typedef long long Int; int getphi(int x) { int ret=1; for(int i=2;i*(Int)i<=x;i++) if(x%i==0) { ret=ret*(i-1); x/=i; while(x%i==0)x/=i,ret*=i; } if(x>1)ret=ret*(x-1); return ret; } int powmod(int x,int y,int mod) { int ret=1; while(y){if(y&1)ret=ret*(Int)x%mod;y>>=1;x=x*(Int)x%mod;} return ret; } int check(int x,int y,int mod) { vector<int>V; while(y){V.
UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,并且是基于BSD协议的开源产品,允许自由使用和修改,使用起来十分方便。如果你是用来输出编排好格式的文章或者其他文本,使用UEditor绝对是一个很不错的选择。 UEditor使用起来十分简单,然而java版本在struts2跟原生的两种情况下又有点不一样。首先说一下创建原生java项目(不包含任何框架)的配置吧。 不包含任何框架:
步骤一:
先到UEditor官网([UEditor](http://ueditor.baidu.com/website/download.html))下载UEditor1.4.3_jsp版本。 下载完成之后解压,复制到你新创建的 java web项目的 WebContent 的目录下。刚复制到项目中的时候可能会出现错误,你只需要把该项目的编码设置成 utf8 错误就会没有了。
步骤二:
创建一个index.jsp
正确引入js文件之后,再在后面加上
<script type="text/javascript"> UE.getEditor('myEditor2'); </script> 注意:jsp中的
<script id="myEditor2" name="content" type="text/plain"> 这里写你的初始化内容 </script> id=”myEditor2” 一定要跟
<script type="text/javascript"> UE.getEditor('myEditor2'); </script> 中的myEditor2相同,否则不能显示编辑器。
步骤三: 把 imageUrlPrefix 对应的参数修改成你项目的根目录,默认是空的。
步骤四:
修改ueditor.config.js中的 window.UEDITOR_HOME_URL,
window.UEDITOR_HOME_URL = “/xxxx/xxxx/”;
也就是以斜杠开头的形如”/myProject/ueditor/”这样的路径。
现在,你运行index.jsp文件百度编辑器应该就会出现了。而且图片上传也没问题。
还有一点要注意的,就是当你上传图片的时候在文件夹中是看不到的,但是他已经上传到指定的文件夹的了,不知道是为什么,我现在还搞不明白。
**
使用了struts2的UEditor
**
首先第一步,配置跟上面是完全一样的。
有一点非常重要,就是当你要上传图片的时候你会发现,上传不了,说找不到资源。原因是struts2中的拦截器把所有文件都拦截了,需要把controller.jsp文件过滤掉,不给拦截器拦截,这样才能实现上传功能。
这是默认的:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:web="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd http://java.sun.com/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee" id="WebApp_9" version="2.4"> <display-name>Struts Blank</display-name> <filter> <filter-name>struts2</filter-name> <filter-class>org.
前阵子从支付宝转账1万块钱到余额宝,这是日常生活的一件普通小事,但作为互联网研发人员的职业病,我就思考支付宝扣除1万之后,如果系统挂掉怎么办,这时余额宝账户并没有增加1万,数据就会出现不一致状况了。
上述场景在各个类型的系统中都能找到相似影子,比如在电商系统中,当有用户下单后,除了在订单表插入一条记录外,对应商品表的这个商品数量必须减1吧,怎么保证?!在搜索广告系统中,当用户点击某广告后,除了在点击事件表中增加一条记录外,还得去商家账户表中找到这个商家并扣除广告费吧,怎么保证?!等等,相信大家或多或多少都能碰到相似情景。
本质上问题可以抽象为:当一个表数据更新后,怎么保证另一个表的数据也必须要更新成功。
1 本地事务
还是以支付宝转账余额宝为例,假设有
支付宝账户表:A(id,userId,amount)
余额宝账户表:B(id,userId,amount)
用户的userId=1;
从支付宝转账1万块钱到余额宝的动作分为两步:
1)支付宝表扣除1万:update A set amount=amount-10000 where userId=1;
2)余额宝表增加1万:update B set amount=amount+10000 where userId=1;
如何确保支付宝余额宝收支平衡呢?
有人说这个很简单嘛,可以用事务解决。
Begin transaction
update A set amount=amount-10000 where userId=1;
update B set amount=amount+10000 where userId=1;
End transaction
commit;
非常正确,如果你使用spring的话一个注解就能搞定上述事务功能。
@Transactional(rollbackFor=Exception.class)
public void update() {
updateATable(); //更新A表
updateBTable(); //更新B表
}
如果系统规模较小,数据表都在一个数据库实例上,上述本地事务方式可以很好地运行,但是如果系统规模较大,比如支付宝账户表和余额宝账户表显然不会在同一个数据库实例上,他们往往分布在不同的物理节点上,这时本地事务已经失去用武之地。
既然本地事务失效,分布式事务自然就登上舞台。
2 分布式事务—两阶段提交协议
两阶段提交协议(Two-phase Commit,2PC)经常被用来实现分布式事务。一般分为协调器C和若干事务执行者Si两种角色,这里的事务执行者就是具体的数据库,协调器可以和事务执行器在一台机器上。
1) 我们的应用程序(client)发起一个开始请求到TC;
2) TC先将<prepare>消息写到本地日志,之后向所有的Si发起<prepare>消息。以支付宝转账到余额宝为例,TC给A的prepare消息是通知支付宝数据库相应账目扣款1万,TC给B的prepare消息是通知余额宝数据库相应账目增加1w。为什么在执行任务前需要先写本地日志,主要是为了故障后恢复用,本地日志起到现实生活中凭证 的效果,如果没有本地日志(凭证),出问题容易死无对证;
3) Si收到<prepare>消息后,执行具体本机事务,但不会进行commit,如果成功返回<yes>,不成功返回<no>。同理,返回前都应把要返回的消息写到日志里,当作凭证。
4) TC收集所有执行器返回的消息,如果所有执行器都返回yes,那么给所有执行器发生送commit消息,执行器收到commit后执行本地事务的commit操作;如果有任一个执行器返回no,那么给所有执行器发送abort消息,执行器收到abort消息后执行事务abort操作。
注:TC或Si把发送或接收到的消息先写到日志里,主要是为了故障后恢复用。如某一Si从故障中恢复后,先检查本机的日志,如果已收到<commit >,则提交,如果<abort >则回滚。如果是<yes>,则再向TC询问一下,确定下一步。如果什么都没有,则很可能在<prepare>阶段Si就崩溃了,因此需要回滚。
好用的SimpleJdbcDaoSupport 及 SimpleJdbcTemplate,已经在3.1中被废弃
原因是JdbcDaoSupport 或NamedParameterJdbcDaoSupport已经提供了其所有功能
请看源代码:
[java] view plain copy /** * Extension of {@link org.springframework.jdbc.core.support.JdbcDaoSupport} * that exposes a {@link #getSimpleJdbcTemplate() SimpleJdbcTemplate} as well. * Only usable on Java 5 and above. * * @author Rod Johnson * @author Juergen Hoeller * @since 2.0 * @see SimpleJdbcTemplate * @deprecated since Spring 3.1 in favor of {@link org.springframework.jdbc.core.support.JdbcDaoSupport} and * {@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport}. The JdbcTemplate and * NamedParameterJdbcTemplate now provide all the functionality of the SimpleJdbcTemplate.
NotificationManager 和Notification的使用总结(转) 文章分类:移动开发 这几天一直在修改twigee的源代码,其中一个要加入的功能是常驻Notification栏,以前写的时候只能出现 在“通知”这一组中,想把它放在“正在运行”组中却不知道怎么放,查了下官方文档,找到了方法,在notification的flags字段中加一下 “FLAG_ONGOING_EVENT”就可以了。同时我也把Notification的使用方法给总结了一下。详见下文: (1)、使用系统定义的Notification 以下是使用示例代码: //创建一个NotificationManager的引用 String ns = Context.NOTIFICATION_SERVICE; NotificationManager mNotificationManager = (NotificationManager)getSystemService(ns); // 定义Notification的各种属性 int icon = R.drawable.icon; //通知图标 CharSequence tickerText = "Hello"; //状态栏显示的通知文本提示 long when = System.currentTimeMillis(); //通知产生的时间,会在通知信息里显示 //用上面的属性初始化 Nofification Notification notification = new Notification(icon,tickerText,when); /* * 添加声音 * notification.defaults |=Notification.DEFAULT_SOUND; * 或者使用以下几种方式 * notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3"); * notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6"); * 如果想要让声音持续重复直到用户对通知做出反应,则可以在notification的flags字段增加"FLAG_INSISTENT" * 如果notification的defaults字段包括了"DEFAULT_SOUND"属性,则这个属性将覆盖sound字段中定义的声音 */ /* * 添加振动 * notification.defaults |= Notification.
ActivityManager在操作系统中有重要的作用,本文利用操作系统源码,逐步理清ActivityManager的框架,并从静态类结构图和动态序列图两个角度分别进行剖析,从而帮助开发人员加强对系统框架及进程通信机制的理解。
ActivityManager的作用 参照SDK的说明,可见ActivityManager的功能是与系统中所有运行着的Activity交互提供了接口,主要的接口围绕着运行中的进程信息,任务信息,服务信息等。比如函数getRunningServices()的源码是:
public List<RunningServiceInfo> getRunningServices(int maxNum)
throws SecurityException {
try {
return (List<RunningServiceInfo>)ActivityManagerNative.getDefault()
.getServices(maxNum, 0);
} catch (RemoteException e) {
// System dead, we will be dead too soon!
return null;
}
}
从中可以看到,ActivityManager的大多数功能都是调用了ActivityManagerNative类接口来完成的,因此,我们寻迹来看ActivityManagerNative的代码,并以此揭示ActivityManager的整体框架。
ActivityManager的静态类图 通过源吗,可以发现ActivityManagerNative类的继承关系如下:
public abstract class ActivityManagerNative extends Binder implements IActivityManager
继承自Binder类,同时实现了IActivityManager接口。
同样的,我们继续沿Binder和IActivityManager上溯,整理出如下图所示的类结构图。
在这张图中,绿色的部分是在SDK中开放给应用程序开发人员的接口,蓝色的部分是一个典型的Proxy模式,红色的部分是底层的服务实现,是真正的动作执行者。这里的一个核心思想是Proxy模式,我们接下来对此模式加以介绍。
Proxy模式 Proxy模式,也称代理模式,是经典设计模式中的一种结构型模式,其定义是为其他对象提供一种代理以控制对这个对象的访问,简单的说就是在访问和被访问对象中间加上的一个间接层,以隔离访问者和被访问者的实现细节。
结合上面的类结构图,其中ActivityManager是一个客户端,为了隔离它与ActivityManagerService,有效降低甚至消除二者的耦合度,在这中间使用了ActivityManagerProxy代理类,所有对ActivityManagerService的访问都转换成对代理类的访问,这样ActivityManager就与ActivityManagerService解耦了。这就是代理模式的典型应用场景。
为了让代理类与被代理类保持一致的接口,从而实现更加灵活的类结构,或者说完美的屏蔽实现细节,通常的作法是让代理类与被代理类实现一个公共的接口,这样对调用者来说,无法知道被调用的是代理类还是直接是被代理类,因为二者的接口是相同的。
这个思路在上面的类结构图里也有落实,IActivityManager接口类就是起的这个作用。
以上就是代理模式的思路,有时我们也称代理类为本地代理(Local Proxy),被代理类为远端代理(Remote Proxy)。
本地代理与远端代理的Binder 我们再来看一下Binder类的作用,Binder的含义可能译为粘合剂更为贴切,即将两侧的东西粘贴起来。在操作系统中,Binder的一大作用就是连接本地代理和远端代理。Binder中最重要的一个函数是:
public final boolean transact(int code, Parcel data, Parcel reply,
int flags) throws RemoteException {
一、概述 HTTP协议是一种无状态协议,服务器端本身不具有识别客户端的能力,必须借助外部机制,比如session和cookie,才能与特定客户端保持对话。
WebSocket的主要作用是,允许服务器端与客户端进行全双工(full-duplex)的通信。举例来说,HTTP协议有点像发电子邮件,发出后必须等待对方回信;WebSocket则是像打电话,服务器端和客户端可以同时向对方发送数据,它们之间存着一条持续打开的数据通道。
WebSocket协议完全可以取代Ajax方法,用来向服务器端发送文本和二进制数据,而且还没有“同域限制”。
WebSocket不使用HTTP协议,而是使用自己的协议。WebSocket与http协议一样都是基于TCP的,属于应用层的协议,所以他们都是可靠的协议。WebSocket在建立握手连接时,数据是通过http协议传输的,但是在建立连接之后,真正的数据传输阶段是不需要http协议参与的。
请求:
GET / HTTP/1.1 Connection: Upgrade //表示浏览器通知服务器,如果可以,就升级到webSocket协议 Upgrade: websocket //表示将通信协议从HTTP/1.1转向该项所指定的协议 Host: example.com Origin: null //验证浏览器域名是否在服务器许可的范围内 Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ== //握手协议的密钥,是base64编码的16字节随机字符串 Sec-WebSocket-Version: 13 响应: HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: websocket Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s= Sec-WebSocket-Origin: null Sec-WebSocket-Location: ws://example.com/ //表示进行通信的WebSocket网址 注意:WebSocket协议用ws表示。此外,还有wss协议,表示加密的WebSocket协议,对应HTTPS协议。
二、客户端 1. 建立连接和断开连接、发送数据和接收数据、处理错误。
2. WebSocket实例对象有一个readyState属性,表示目前的状态,可取4个值:
【0:正在连接;1:连接成功;2:正在关闭;3:连接关闭】
3. 客户端建立WebSocket流程:
(0)检测浏览器是否支持WebSocket
(1)握手协议成功以后,readyState就从0变为1,并触发open事件
(2)关闭WebSocket连接,会触发close事件
(3)客户端收到服务器发送的数据,会触发message事件
(4)连接建立后,客户端通过send方法向服务器端发送数据
if(window.WebSocket != undefined) { var ws = new WebSocket("ws://localhost:10010"); ws.onopen = function(){ console.log("Opened!"); ws.send("I'm client,call server!
The command: "cxstm8 +warn +mods0 +debug -pxp -no -pp -l -iinc -iproject -i"C:\Program Files (x86)\COSMIC\CXSTM8_32K\Hstm8" -cl..\esir-th(v1.0)\ -co..\esir-th(v1.0)\ project\devinit.c" has failed, the returned value is: 1exit code=1.
C Language 的改变会发生如上的错误
对于真机,日志没法保存,不好分析问题。所以有必要将日志保存到应用的Docunment目录下,并设置成共享文件,这样才能取出分析。
首先是日志输出,分为c的printf和标准的NSLog输出,printf会向标准输出(sedout)打印,而NSLog则是向标准出错(stderr),我们需要同时让他们都将日志打印到一个文件中。
例子:
freopen("xx.log","a+",stdout);
freopen("xx.log","a+",stderr);
具体做法:
// 将NSlog打印信息保存到Document目录下的文件中
- (void)redirectNSlogToDocumentFolder
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
NSString *fileName = [NSString stringWithFormat:@"dr.log"];// 注意不是NSData!
NSString *logFilePath = [documentDirectory stringByAppendingPathComponent:fileName];
// 先删除已经存在的文件
NSFileManager *defaultManager = [NSFileManager defaultManager];
[defaultManager removeItemAtPath:logFilePath error:nil];
// 将log输入到文件
freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stdout);
freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding], "a+", stderr);
} 此函数要在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
中调用,这个函数在AppDelegate.m中实现的。
/*******************************************************************************/
// 当真机连接Mac调试的时候把这些注释掉,否则log只会输入到文件中,而不能从xcode的监视器中看到。
// 如果是真机就保存到Document目录下的drm.log文件中
UIDevice *device = [UIDevice currentDevice];
要更深入了解C++, 必须要知道一个程序从开始到结束都干了些什么, 怎么干的。 所以我从C++编译到运行过程,解析下程序是怎么跑的。
首先,初略的说一下之前C++的编译过程,C++编译过程包括预编译-》汇编-》编译-》链接。称为一个可执行文件。(Windows平台下为.exe文件)。
预编译主要展开包含的头文件,宏定义等操作。例如一个简单的main程序,编译预编译后,的文件对比。
可以看到里面的宏已经被去掉了。如果定了那个宏,那么宏里面的内容也会显示出来。头文件也是,如果你包含了你一个.h 文件,那么整个.h文件会包含进来。
汇编过程,就是把已经预编译的文件编译成汇编代码的过程,整个过程会包含语法,词法的分析,和一些优化操作。
编译过程其实是跟汇编可以合成一个阶段,变成目标代码。也就是二进制文件。
链接过程是将单个编译后的文件链接成一个可执行程序。前面的预编译、汇编、编译都是正对单个文件,以一个文件为一个编译单元,而链接则是将所有关联到的编译后单元文件和应用的到库文件,进行一次链接处理,之前编译过的文件 如果有用到其他文件里面定义到的函数,全局变量,在这个过程中都会进行解析。
首先看看编译后的文件样子(已VS2012编译后的OBJ文件为例子,不同编译器 样式可能会不同。)
编译前的文件
#include "Car.h"
int main(int argc, char* argv[])
{
Car* p = new Car();
delete p;
return 1;
}
编译后的样子(由于编译后的文件 信息太多 只贴出里面未解析符号部分。)
UNDEF:00002DC4 ; int __thiscall Car::Car(Car *__hidden this)
UNDEF:00002DC4 extrn ??0Car@@QAE@XZ:near ; CODE XREF: _main+63p
UNDEF:00002DC8 ; int __thiscall Car::~Car(Car *__hidden this)
UNDEF:00002DC8 extrn ??1Car@@QAE@XZ:near
UNDEF:00002DC8 ; CODE XREF: Car::`scalar deleting destructor'(uint)+26p
UNDEF:00002DCC ; __fastcall _RTC_CheckStackVars(x, x)
最近又开始写项目服务器部分了, 再次接触了C++ 有了一些更深入的体会。记录一下,以免忘记~ 之前学习C++ 差不错都是靠死记, 记住C++的用法,C++的特性,然后去使用。没有从根本上理解,导致 几年不用C++,就已经完全忘记,然后又要花好长时间去记忆,使用。所以要真正做到学会C++,必须要从根本上了解,这样才不至于有会忘记, 而且使用起来会更的心应手。
1、明确了一些定义
关于指针, 刚开始学习指针的时候,总是一些模糊的印象,想不清楚具体是什么, 就知道死记用法。仅仅知道指针能指向一个对象,好似一个标识而。
最近深入了思考了下,并且通过研究编译后的文件,有了些具体的东西。我们知道所有程序最终会解释编译成机器码的形式运行的,而我们的计算机都是会变成二进制文件,就是形如010101001这样。关于CPU如何执行 这些二进制文件,这关系到一些硬件知识,我目前也没有去了解过,有机会找块单片机研究下,不过我们只用知道最终程序都是会变成一条条指令去执行。那些指令抽象简单的概括就是把某个内存里面的值与另一个内存里面的值做一些操作(如加、减等)然后写到一个内存。程序执行过程简单来说就是,把一堆二进制指令和一些数据装载到内存中(全部是一堆二进制值),然后CPU执行那些指令,修改内存(包括申请新内存、释放旧内存、内存中数据运算或者赋值)。关于编译运行过程可以参考另一篇文章 C++编译、运行过程详解。
函数调用, 在汇编中一个Call指令,专门针对调用一个函数,Call 接收一个地址,让CPU去执行那个地址的指令集。这就是一个最简单的函数调用过程。当然函数调用必定会涉及到参数的传递。每一个执行程序,操作系统都会分配一个默认的程序栈空间,这个栈本质上就是计算机的内存空间而已,只不过提供了一些栈特性的支持。当初我们学习C++的时候,都是背了一些定义,函数调用过程会先将当期地址入栈,然后参数按照函数的调用约到一次入栈然后在去执行操作,执行完后依次出栈,最后回到函数执行前入职的地址, 这就完成了一个函数调用过程。但是函数入栈和出栈具体是怎样一个过程,其实当时在我脑海里面是比较模糊的概念的,这些知识都是被动接受,所以 也没有 仔细的去想明白。其实栈的特性我们都知道是先入后出,我们的函数栈其实就是内存中的一块地址,然后是低地址增加的,所以栈的大小是有限制的(为什么是像低地址增加,这个得去看看操作系统相关的东西了),函数操作栈是通过2个寄存器来操作的,一个是栈底部地址(ebp寄存器),一个是栈顶地址(esp寄存器)。函数调用时候回将ebp寄存器指向当期函数栈的地址,然后,初始化此函数需要的栈空间大小,每个函数需要的栈空间大小是能明确确定的,在编译期间就能知道,例如 void Test() {int i = 0; A* pA = new A(); A a; delete pA; }的栈空间大小是临时变量 i 占4个字节,临时指针pA占 4个字节(win32平台),临时对象a 占 sizeof(A)的大小,A a 会直接在栈里面构造出来,所以要占sizeof(A)的大小,所以函数需要的栈的大小在编译器就能确定的。然后执行中所谓变量其实都是地址而已,i=0其实就是讲栈里面的epb+0位置的大小为4字节的内存赋值为0,A* pA = new A(); 这个构造一个对象过程稍微复杂一些,会调用到new方法申请一块sizeoof(A)大小的堆内存,堆内存不同于栈内存,堆内存理论上是无限大的(具体区别可以去度年或者谷姐上查询,都有很多文章有详细的解答),然后调用A的构造方法,将对内存进行初始化操作(其中包括初始化虚函数表地址),pA实际上就是一个地址,在栈内存中,这个地址是A这个对象在对内存的地址,所以从这里可以看出其实所谓指针, 变量名 都是高级语言里面的概念,为了更好的编写程序而设计的,其本质 最终都是一个地址值而已。最终操作这个变量就是对这个地址操作。 例如对pA.m_nMenber = 0; 操作其实编译器最后会变成pA的地址加上这个变量所在的一个偏移地址offset的一个操作,即将pA地址+offset处一个4字节的内存赋值为0(0这个值是放在哪里的呢?我猜应该常量区吧,没有验证过,我猜应该是跟常量数据一样,最终执行过程就是把0所在的地址的4字节内容赋值到pA地址+offset处)。函数执行完成后, 会做出栈处理,其实就是将esp寄存器值指向ebp寄存器所以执行完后这段函数栈内存都会被释放掉,然后回到调用函数之前我们入栈的地址处。具体描述下函数调用过程就是,代码编译后运行,会加载到内存中,操作系统会分配一个栈给函数执行,每调用一个函数我们会先将当期函数执行后的下一条指令执行地址入栈(入栈操作其实就是将这个值保持到栈中,栈地址在增加,例如将一个int i入栈会将这个i所在地址复制到当期栈指针esp处(此地址在win32上占4字节)然后栈指针会加上4,即表示这个将变量i入栈了, 出栈就是将esp执行地址-4),在这个栈上初始化这段函数要用到的栈大小,然后依次执行此函数的指令,做一些变量复制、构造、函数调用等操作,然后依次将入栈的值出栈,回到调用之前入栈的那个执行地址继续执行。
当然 函数执行过程中还会有很多细节,如涉及到虚函数类的构造,虚函数的调用等,这些在使用上看上去是不同,当本质还是一样,只是这其中编译器会帮我们做一些操作来实现虚函数的特性。如在虚函数析构的时候编译出来的指令会调用父类的析构,等等操作。
我去发现要写清楚 真的好难, 每一个点都有太多东西要讲,想用一篇文章来描述 真的要写蛮长,写了这么长,我都还没开始讲到构造函数、虚函数、继承那些东西, 累了 休息先~
wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz //直接下载 sudo tar xzvf tcl8.6.1-src.tar.gz -C /usr/local/ cd /usr/local/tcl8.6.1/unix/ sudo ./configure sudo make sudo make install 感谢: http://blog.csdn.net/luyee2010/article/details/18766911
public class DataConversion {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
int num = 24241;
while (num > 0) {
stack.push(num % 10);
num = num / 10;
}
while (stack.size() > 0) {
System.out.print(stack.pop());
}
System.out.println("--------------------------------");
Deque<Integer> stack1 = new ArrayDeque<>();
int number = 12;
while (number > 0) {
stack1.push(number % 8);
number = number / 8;
}
while (stack1.size() > 0) {
A. Gerald's Hexagon time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Gerald got a very curious hexagon for his birthday. The boy found out that all the angles of the hexagon are equal to . Then he measured the length of its sides, and found that each of them is equal to an integer number of centimeters. There the properties of the hexagon ended and Gerald decided to draw on it.
LordPE
简介 一款强大的可执行文件分析辅助脱壳工具,附带16进制编辑器.不包括反汇编模块.它叫LordPE而不是LoadPE. 版本系统支持情况 32位兼容64位
官网 y0da.cjb.net(已失效)
什么时候需要? 你想熟悉PE结构吗?LordPE拥有基于最小功能的PE修改方式. 你当然也可以用它查看PE的其它信息.它提供了有限的自动脱壳功能.此外它的作者y0da曾经开放过数款有趣的壳.
示例 问题:随机基址的标志在哪里? 如果你是一个不太不底层的程序员,我们就会经常听到”随机基址”一词.这项技术将映像基地址变得随机使程序难以被找出有效的攻击漏洞. 据信VS2010以上编译出的程序默认开启了这项功能. 如图: 因为从程序的OEP(入口点)开始就进入了基址重定位的区域.所以我们推断基址重定位的标记应当在PE文件头中. 为了确切得到哪个标志位决定了是否使用基址重定位.需要一个对比实验.首先需要写一个”你好师姐”或者其它任意的程序. 如图: 通过配置开启和关闭随机基址功能分别生成程序后复制出来.等待我们的分析.
如何找到两个PE文件文件头的区别? 使用我们LordPe打开其中一个文件,点击”对比”,找到另外一个文件. 如图: 红×表示不同之处. 如果你竟然看不懂这里的东东.快去学习PE头结构,以下是我当年学习PE的时候找到的比较好的资料: 从计算机病毒讲解PE PE结构详解 教科书般-深入剖析PE文件
拓展学习 该程序的原版非汉化版,被加了壳yoda’s Protector.这很有趣不是吗?以下是一些相关资料: 超级变态壳yoda’s Protector v1.02请高手指教! yoda’s cryptor 壳流程分析
注意 LordPE的PE编辑器模块对文件的改变是不可逆的.很多操作是实时的.别想着通过”取消”来反悔.因为根本没有”取消”按钮.汗.
要说计算机网络的重点肯定是TCP/IP协议族了,这两个协议几乎涵盖了整个网络通信的流程。弄清楚客户端和服务器端之间的通信过程,基本上就对TCP/IP掌握的差不多了。所以接下来要开始介绍这篇文章的主角TCP协议了。
先简单介绍一下TCP协议:它是一个面向连接的,可靠的传输协议。该连接可抽象为一个四元组(local_ip,local_port,remote_ip,remote_port),该四元组唯一标识一个TCP连接。面向连接意味着两个通信双方(两个进程)在彼此交换数据之前必须先建立一个TCP连接。可靠性意味着双方建立的连接是可靠的,基本不会发生丢失数据的现象。总结来说,TCP要点有四,一有连接,二可靠传输,三数据按照到达,四端到端流量控制。
TCP首部:
TCP报文段的首部的前20个字节是固定的,后面有4N字节是根据需要而增加的选项。因此TCP首部的最小长度时20字节。
源端口号和目的端口号:用于寻找发端和收端应用进程,不同的应用进程端口号不同。这两个值加上IP首部中的源端IP地址和目的IP地址唯一确定一个TCP连接。
有时,一个IP地址和一个端口称为一个插口(scoket)。
序号:指的是本报文段所发送的数据的第一个字节的序号。
确认号:指的是希望收到对方下一个报文段的第一个数据字节的序号。接收方只对按序到达的数据中的最高序号给出确认。例如序号31,32,33同时发送,但是31中间丢失,32,33到达,此时接收方给出的确认号仍然是31,而不能是3 2或33.
数据偏移:指的是TCP报文段的数据起始处距离TCP报文段的起始处有多远。
保留:
6个控制位的含义分别如下:
紧急URG:紧急指针字段,当URG=1时,表示系统中有紧急数据,应尽快传送,而不要按原来的排队顺序来传送。
确认ACK:仅当ACK=1时确认号字段才有效。TCP规定,在连接建立后所有传送的报文段都应把ACK置为1.
推送PSH:当两个应用进程进行交互式的通信时,有时一端的应用进程希望在键入一个命令后立即就能收到对方的响应。在这种情况下,TCP就可以使用推送操作。
复位RST:当RST=1时,表明TCP连接中出现严重错误(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。
同步SYN:在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN=1和ACK=1。因此,SYN=1表示这是一个连接请求报文段或者连接接收报文段。
终止FIN:用来释放一个连接。当FIN=1时,表明此报文段的发送发的数据已经发送完毕,并要求释放运输连接。
窗口:指的是发送本报文段的一方的接收窗口。窗口值告诉对方:从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量。
检验和:检验范围是首部和数据部分。
紧急指针:URG=1时才有用。
TCP的建立与终止 1、TCP的建立
几乎众所周知了,TCP的建立需要三次握手,请求-应答-再次确认,才能构建一条可靠的TCP连接。具体流程详见下面的阐述:
假如客户端A想和服务器B通信,建立连接的过程分为以下三步:
第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机,A进入SYN_SENT状态;
第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包,B进入SYN_RCVD状态;
第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功,A进入ESTABLISHED状态。
完成三次握手,主机A与主机B开始传送数据。
Q1:为什么建立连接时三次握手而不是两次握手?
是为了防止失效的连接请求报文段突然又传到了服务端,因而产生错误。
Q2:SYN攻击是典型的DDOS攻击,简述其原理。
在三次握手的过程中,服务器发送SYN和ACK之后,收到客户端的ACK之前的连接成为半连接。此时服务器处于SYN_RCVD状态,收到客户端的ACK之后进入ESTABLISHED状态。SYN攻击就是利用这个时间间隔伪造大量不存在的IP地址向服务器不断发送SYN包,服务器回复确认包,并等待客户的确认。由于源地址不存在,服务器需要不断地重发直至超时,这些伪造的SYN包将长时间占用未连接队列,而正常的SYN请求被丢弃,目标系统运行缓慢,引起网络的严重瘫痪。因此大多数操作系统都闲着半连接的数量。
2、TCP的终止
由于TCP是全双工的通信模式,即通信双方都可以既是发送数据方又可以是接收数据方,因此每个方向都必须进行单独关闭,这个特点导致TCP的终止需要四次挥手。四次挥手的具体过程如下:
具体为以下四步:
1、 连接的某一方首先调用close()发起主动关闭(active close),该api会促使TCP传输层向remote peer发FIN包,这个FIN包表明发起active close一方的application不再发送数据;
2、 收到FIN包的remote peer后,在传输层针对对方的FIN包,回复一个ACK包确认(ACK的包序是在FIN包的基础上加1);
3、 应用层的application收到对方的EOF(end of file,对方的FIN包作为EOF传到应用层的application)后,得知这条连接不会有数据传输,于是也调用close()关闭连接,该close会促使传输层发送FIN包;
4、 发起主动关闭的peer的一方收到remote peer的FIN包后,回复ACK包,至此,TCP连接关闭。
这里出现的几种状态要搞清楚它们的含义:
FIN_WAIT 1:主动关闭的一方在发送FIN包后,此时该socket进入FIN_WAIT 1状态;
FIN_WAIT 2:主动关闭的一方收到对方的ACK后,进入FIN_WAIT 2. FIN_WAIT 1和FIN_WAIT 2这两种状态实际上都是在等待对方的FIN报文;
TIME_WAIT:表示收到了对方的FIN包,并发送了ACK包后的状态,也称为2MSL状态;
CLOSE_WAIT:表示正在等待关闭;
LAST_ACK:被动关闭的一方在发送FIN包后,等待对方的ACK包的时候,当收到对方的ACK包后,立马进入CLOSED状态。
在 且 与 或 优先级比较中 且 的优先级是大于 或 的。
addWhere("and o.age = ?", age);
addWhere("and o.name like ? ", "%" + str + "%");
addWhere("or o.stuNum like ?", "%" + str + "%");
addWhere("or o.calssName like ?", "%" + str + "%");
上面语句中会将age和name查完之后,才会查询or语句。所以要改成:
addWhere("and o.age = ?", age);
addWhere("and (o.name like ? ", "%" + str + "%");
addWhere("or o.stuNum like ?", "%" + str + "%");
addWhere("or o.calssName like ?
1. 简介 du查看目录大小,df查看磁盘使用情况。
2. du disk usage (1)基本功能 递归查看文件夹下所有文件的大小 (2)常用参数: -h, –human-readable 以可读性较好的方式显示尺寸(例如:1K 234M 2G) -s, –summarize 只分别计算命令列中每个参数所占的总用量 (3)其它参数说明: -a, –all 输出所有文件的磁盘用量,不仅仅是目录 –apparent-size 显示表面用量,而并非是磁盘用量;虽然表面用量通常会小一些,但有时它会因为稀疏文件间的”洞”、内部碎片、非直接引用的块等原因而变大。 -B, –block-size=大小 使用指定字节数的块 -b, –bytes 等于–apparent-size –block-size=1 -c, –total 显示总计信息 -D, –dereference-args 解除命令行中列出的符号连接 –files0-from=F 计算文件F 中以NUL 结尾的文件名对应占用的磁盘空间如果F 的值是”-“,则从标准输入读入文件名 -H 等于–dereference-args (-D) -h, –human-readable 以可读性较好的方式显示尺寸(例如:1K 234M 2G) –si 类似-h,但在计算时使用1000 为基底而非1024 -k 等于–block-size=1K -l, –count-links 如果是硬连接,就多次计算其尺寸 -m 等于–block-size=1M -L, –dereference 找出任何符号链接指示的真正目的地 -P, –no-dereference 不跟随任何符号链接(默认) -0, –null 将每个空行视作0 字节而非换行符 -S, –separate-dirs 不包括子目录的占用量 -s, –summarize 只分别计算命令列中每个参数所占的总用量 -x, –one-file-system 跳过处于不同文件系统之上的目录 -X, –exclude-from=文件 排除与指定文件中描述的模式相符的文件 –exclude=PATTERN 排除与PATTERN 中描述的模式相符的文件 –max-depth=N 显示目录总计(与–all 一起使用计算文件) 当N 为指定数值时计算深度为N; –max-depth=0 等于–summarize –time 显示目录或该目录子目录下所有文件的最后修改时间 –time=WORD 显示WORD 时间,而非修改时间:atime,access,use,ctime 或status –time-style=样式 按照指定样式显示时间(样式解释规则同”date”命令): full-iso,long-iso,iso,+FORMAT –help 显示此帮助信息并退出 –version 显示版本信息并退出
1. 安装 phpstorm 2. 配置phpstorm,集成mac php5服务器
a.终端执行:curl -s http://php-osx.liip.ch/install.sh | bash -s 5.5
b.新安装的php目录是/usr/local/php5/bin
c.随便运行一个php文件,提示没有配置服务器,配置目录选:/usr/local/php5/bin
1.创建Windows窗体应用程序
2.从网上下载Quartz.net 的dll文件,并且添加引用到项目中
3.修改项目的目标框架,改为.Net Framework4(点击项目然后右键属性)
4.删除app.config文件(也可以不用删除,里面配置quartz.net日志的信息),添加quartz.config和quartz_jobs.xml这两个文件。quartz.config里的内容都不用修改,有个关于quartz_jobs.xml路径的可以修改,我是不修改的,都放在项目的根目录下,挺好的
5.修改quartz.config和quartz_jobs.xml这2个文件的“复制到输出目录”由不复制改为始终复制
6.添加job任务,新建一个类,末尾加个Job,不是必须这样,但是这样一看就清楚,好一些。然后添加public,在继承接口,实现接口方法就行了
7.将job类配置到quartz_jobs.xml文件中
具体关于触发器trigger和job的配置要求,详细说明有很多。我就不赘述了,我写这个的目的是一个简单的入门实用,因为我不知道里面的很多小细节处理,导致一直没运行。
8.开始使用执行任务调度
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Quartz;
using Quartz.Impl;
namespace SAX_WindowsFormsApplication
{
public partial class Form1 : Form
{
private IScheduler _myScheduler = null;
public IScheduler MyScheduler
{
get
{
if (_myScheduler == null)
{
var schFactory = new StdSchedulerFactory();
_myScheduler = schFactory.GetScheduler();
}
return _myScheduler;
}
在面试时有被问到,最基本的问题,我却不是很清晰,所以事后特意去搜索了一下,将结果整理如下:
不同数据类型所表示的取值范围取决于他所占的内存空间的大小,8位为一个字节
C语言中并没有明确规定数据类型的取值范围,在不同位数的操作系统中,同一数据类型可能会占不同长度的内存空间,自然也就会有不同的取值范围。C语言数据类型表示整理如下
16 位系统 unsigned 取值范围(忽略正负) signed取值范围(不忽略正负)
char 1字节(8位) 0~ 2^8-1 (无符号位2进制数的最大值) -2^7~2^7-1(-128~127)
short 2字节(16位) 0~ 2^16-1 -2^15~2^15-1
int 2字节(16位) 0~ 2^16-1 -2^15~2^15-1
long 4字节(32位) 0~ 2^32-1 -2^31~2^31-1
32 位系统 char 1字节(8位) short 2字节(16位) int 4字节(32位)
long 4字节(32位)
long long 8字节(64位)
64 位系统
char 1字节(8位)
short 2字节(16位)
int 4字节(32位)
long 8字节(64位)
long long 8字节(64位)
通过上面16位系统不同数据类型的取值范围,很轻松的就能够求出其他不同位数操作系统的不同数据类型取值范围,只要知道了该数据类型在当前位数操作系统所占的内存字节长度,就可以很容易的推出取值范围,usigned为 0~2^位数-1,signed为
-2^(位数-1)~2^(位数-1)-1,这里简述一下取值范围的求法
signed需要占用一个符号位来表示正负,而我们所用的机器大多采用补码表示法,以8位的数据类型为例
对于正数,符号位为0 ,和原码一样,对于负数,符号位为1,能取到的最小值为10000000,
将非符号位按位取反为11111111,然后+1 ,为1100000000,表示的数为-128
对于java语言,数据类型所占内存是固定的,如下
boolean 1bit(位) byte 8bit 取值范围的算法和c语言中signed数据类型一样(java 语言数据类型一般都是有正负的)
帖子原地址:http://blog.csdn.net/wejoncy/article/details/44095527
LM在最优化中占据着极其重要的地位,将非线性问题转为为线性问题来求解,求出最优解。
最近在搞相机标定,而不得不面对LM,首先的想法百度,(个人不喜欢去看e文,总觉得效率不高,事实上错了)找到了一些相关的文章,好难啊,这是第一想法。不过还是找到了几篇大牛的文章,以及相关的MATLAB实现代码,本文的c实现便是基于MATLAB代码。感谢原作者
http://www.codelast.com/?p=29,这是大牛对之及其通俗的解释,相信看了能明白个大概。
http://www2.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf
讲解的非常透彻的一篇文档,以及实现。E文的,应该看懂都没问题。
[plain] view plain copy % 计算函数f的雅克比矩阵,是解析式 syms a b y x real; f=a*exp(-b*x); Jsym=jacobian(f,[a b]) % 拟合用数据。参见《数学试验》,p190,例2 data_1=[0.25 0.5 1 1.5 2 3 4 6 8]; obs_1=[19.21 18.15 15.36 14.10 12.89 9.32 7.45 5.24 3.01]; % 2. LM算法 % 初始猜测s a0=10; b0=0.5; y_init = a0*exp(-b0*data_1); % 数据个数 Ndata=length(obs_1); % 参数维数 Nparams=2; % 迭代最大次数 n_iters=50; % LM算法的阻尼系数初值 lamda=0.01; % step1: 变量赋值 updateJ=1; a_est=a0; b_est=b0; % step2: 迭代 for it=1:n_iters if updateJ==1 % 根据当前估计值,计算雅克比矩阵 J=zeros(Ndata,Nparams); for i=1:length(data_1) J(i,:)=[exp(-b_est*data_1(i)) -a_est*data_1(i)*exp(-b_est*data_1(i))]; end % 根据当前参数,得到函数值 y_est = a_est*exp(-b_est*data_1); % 计算误差 d=obs_1-y_est; % 计算(拟)海塞矩阵 H=J'*J; % 若是第一次迭代,计算误差 if it==1 e=dot(d,d); end end % 根据阻尼系数lamda混合得到H矩阵 H_lm=H+(lamda*eye(Nparams,Nparams)); % 计算步长dp,并根据步长计算新的可能的\参数估计值 dp=inv(H_lm)*(J'*d(:)); g = J'*d(:); a_lm=a_est+dp(1); b_lm=b_est+dp(2); % 计算新的可能估计值对应的y和计算残差e y_est_lm = a_lm*exp(-b_lm*data_1); d_lm=obs_1-y_est_lm; e_lm=dot(d_lm,d_lm); % 根据误差,决定如何更新参数和阻尼系数 if e_lm<e lamda=lamda/10; a_est=a_lm; b_est=b_lm; e=e_lm; disp(e); updateJ=1; else updateJ=0; lamda=lamda*10; end end %显示优化的结果 a_est b_est 以上是MATLAB实现,据说原作者是http://www.
从手Q与微信之争,看腾讯内在的真实矛盾与战略(转,2013年老文)
文/阳淼
腾讯手机QQ(以下简称手Q)的最新版在一周前上线后,引发了空前激烈的媒体反应与用户反弹,大概可以称为近期最为引人注目的改版事件;虎嗅改版事件则屈居第二。
不过,大多关于满意度的调查都是浮云,因为表达不满的人更有动力去参与调查,除非有别的目的。比如我们可以看到,央视的历次节目改版和春晚满意度都高得出奇……
撇开表面上的这些数字,思考背后的产品逻辑,可能会有些更有意思的东西。作为唯一拿到移动互联网船票的腾讯,在对自己的支柱级产品进行移动化进化时,采用了哪些原则、设定了哪些场景?由此倒推,我们可以看到腾讯对微信这一产品成功的战略级思考,以及由此得出的移动化战略。
一、腾讯移动用户的巨大空档
很多人说这一版手Q的重大改变是腾讯忽视用户需求、闭门造车的结果,所以导致遭遇强烈吐槽。这其实与实情不符。在这一版更新推出前,腾讯最晚已经在半年前花费重金聘请第三方调查公司,对全国各地的手机用户使用习惯进行调查。
第三方调查结合QQ、微信庞大的用户数据统计,一个明显的结论就是,微信在一线大城市中占据注意力中心,但在二线以下的城市中,手机QQ仍然是移动沟通的王者;有位山寨发布会的记者在五一期间回家时进行调查,发现在安徽某市的同学,手机中只装QQ没装微信的大有人在。
马化腾曾透露,在QQ的8亿活跃用户中,有5.5亿通过手机登录,手Q的活跃用户是微信的2倍。但在大城市用户中,微信侵蚀QQ的过程已经十分明显,而这种侵蚀靠的是更符合手机的界面设计与操作习惯,以及对移动需求的更精准把握。在大城市中发生的事迟早会在中小城市中发生,也就是说,如果手机QQ不更快地移动化,不但微信取代手Q的事可能重演,还可能有微信以外的产品抓住这个空档,在大城市避让微信、在中小城市侵蚀手Q,完成移动互联网的割据。那些依赖手Q胜于依赖微信的亿级用户,都存在这个巨大的空档之中。
所以,马化腾断言移动互联网 “ 压倒性”地到来,并非危言耸听,而是从微信的发展中真切感受到了危机;手机QQ的大幅度革新,也并非出于产品经理们浅薄的争风吃醋,而是在飞速发展与颠覆的互联网速度下,自身已经真切面临生死存亡的境地。
二、腾讯对桌面向移动迁移的反思
手Q在二三线城市的巨大占有量是出于惯性,而它在一线城市中被微信侵蚀,一方面是后者的产品逻辑领先,另一方面也是因为QQ背负的巨大历史包袱。所以手Q这次战略调整的策略就是“放下包袱,彻底移动化”。
手Q有哪些包袱?QQ发展了14年,手Q也有10年历史,数亿用户反过来固化了产品设置和习惯。 第一个包袱,是PC QQ产品原则向手机版的延伸:例如此前手Q好友列表形式与PC版的统一,这种设计不能突出智能手机即时送达的优势,也不能满足用户随时收发的使用需求。当好友不在PC QQ上,用户就会大幅降低发起沟通的频次。再不主动改变,QQ在移动场景下必然沦为非首选沟通工具(这一过程在很多微信用户身上已经发生),因此,QQ全新手机版弱化了在线状态,选择最大程度地适应移动互联网。
从数据上看,移动场景的使用需求迥异于PC。腾讯曾经统计,每天QQ消息中,已经有65%的消息通过手机发出。使用QQ手机版沟通的用户,74%的用户在登录后立即选择收发消息,仅26%的用户去查看好友列表。这表明,快速沟通是最高优先级的需求,移动化需优先考虑沟通效率问题。
另一个包袱,源于不忍割舍的非智能手机(功能机)的产品体验,例如有损压缩传输、点按式交互设计(而iPhone引领的操作习惯则早已进化为划动、多点触摸)。旧的设计太多,语音等移动化功能则被淹没在众多功能中,导致用户的移动化需求无法满足。
为了摆脱这两个包袱,手Q必然会在功能上进行大幅度精简、优化,因为手机的小屏幕明摆着不可能容纳桌面版本的功能平移。而功能优化的第一原则,必然是促进沟通,腾讯腾讯,没有讯怎么能腾?PC时代,人会分为在电脑前和不在电脑前两个状态,后者会大幅度切断好友间的沟通欲望。在没有别的沟通工具时,这不算啥问题,QQ只要能占据整个电脑时间即可;但当手机也成为IM载体时,再这么区分,用户时间就可能被别的APP占领。
知乎用户Kenny ff的签名为QQ产品经理,对这个调整的准备工作做出了详细的描述。他的描述与我从腾讯内部得到的消息逻辑一致,所以我们可以放在这里作为参考:
对于联系人视图的变化,很久之前就在准备,也分析过用户行为数据,包括沟通对象数量、消息量、使用时间等等,也做过许多的访谈,日常沟通频率高的好友非常集中,沟通时候是不会在意是否在线的,会放心的留言,对于沟通较少的对象,即使是对方在线,典型的开场白就是:“Hi、在吗?”
所以,尽管引起的巨大反对声浪让手Q产品团队颇为意外,但目前的弱化在线状态这一大原则不会被推翻,腾讯官方目前的态度也是“大前提不会改变,细节可能调整”。这并非不尊重用户,而是很多反对这一变化的用户更多地是出于使用习惯的被改变,微信的大获成功已经证明了“随时在线、有事留言”状态的被认可;急事打电话、日常沟通用IM将成为将来的两种沟通方式,开着智能手机又IM不在线这种中间状态将尽最大可能消除。
手Q团队顶着巨大反对声浪让这样一个道理深入人心:移动互联网的一个产品基石就是用户随时在线。这个道理看似浅显,但却足以对大量PC互联网时代的王者造成潜在的颠覆。举个例子,淘宝当年击败ebay时发现,中国用户更习惯一口价而非拍卖,所以最后以固定价格取代了ebay的竞价式出售。但这个习惯从哪儿来?当时中国个人PC不普及、用户很难长时间在线盯着价格变动应该也是原因之一。移动互联网时代的24小时在线,会重塑用户的习惯,不定时闪购、随时加价竞拍等模式可能出现新的商机。
每一个互联网的产品经理都应该反思:现有产品中那些看似约定俗成的设定习惯中,哪些来自于对PC互联网“在线”“离线”状态的适应和迁就?这种区别找出的越多,以移动产品取代PC王者的机遇就越大。
三、移动化之后是什么?
在完成了“分时”向“24小时实时”的转变之后,腾讯更下一步的战略方向是什么?其实,在马化腾的最近一次对话中,已经无意间泄露了他的野心:
关注可穿戴的设备,包括以后的手表、手镯、眼镜,未必是直接去做,但是我们会关注里面的体验怎么跟我们的服务结合。
腾讯的服务无外乎是通讯、社交,以及基于这之上衍生的娱乐与商务业务。也就是说,马化腾对可穿带设备的关注,并非仅仅是出于新鲜,而是已经有了近乎于成形的产品规划,就是“无处不在的QQ”:一个可能运行在手表、手镯、眼镜乃至电视上的QQ。这并不令人意外,既然腾讯解决的核心需求是沟通,那当然要利用一切可能的设备界面,来完成这个沟通。
去年马化腾与互联网哲学家KK对话时,后者就介绍了自己身上佩戴的健康跟踪仪,马化腾当时眼睛就亮了。也就是说,这个规划至少已经成形了一年;还没在可穿戴设备上打主意的各家公司们要注意了,腾讯迟到一年都可能翻盘,让它早行动一年对大家都不是啥好事儿。
要把QQ嵌入到这么多设备中,就必须有一个够轻便的内核。这一版的手机QQ,其规划实际上在两年前就已经开始,但中间受制于腾讯的组织架构(马化腾所谓的一个QQ分属于三个事业部),没有顺利推进。在今年1月手机QQ合并回社交网络事业群、与PC QQ、QQ空间团聚后,这一调整得以实质性的推进。春节后,马化腾挂帅,腾讯即时通讯团队进入创业状态,一周工作六天、深圳上海一个电话会议就开十个小时,最后拿出了眼前这个产品。
如此密集的智力成果之下,不可能仅仅做出一个永远在线的界面、一个收缩群助手就了事,大量的工作其实在于底层架构优化、语音送达率、视频连通率提升、运营框架重建等,基于移动设备的能力和用户的场景需求进行产品设计。微信的底层来自于邮箱,桌面QQ的底层原型更是原来的网络寻呼机,腾讯严格来说并没有一个完整的移动产品引擎——但他们很显然已经在做了。
这个“移动核心”的未来,马化腾也曾经有过表述:iPhone做出来,mac回头去模仿体验。苹果和谷歌都在做这样的事,即在移动平台上研发出更轻、更有效率的内核后,以之逐步“反向收编”桌面的产品,Mac OS 的iOS化,Chrome 与安卓的逐渐合流,都是基于这一逻辑。
这个目标能不能完成还不好说,毕竟世界上大软件公司这么多,真正做成了统治性移动内核的就两家,苹果和谷歌;微软都挣扎得半死不活的。但腾讯的产品逻辑至少已经能说得通:微信抢滩,手Q登录,提炼移动核心引擎,再逐步将庞大的业务线和生态系统迁移到这个核心上,最终实现PC帝国在移动互联网领域的重建。
不谈战略成败,仅仅从新版手Q发布后的实际数据来看,实际上也并非像舆论表现的那么不堪。根据我拿到的数据,5月13日一天,新版手Q在安卓上的日登陆近2900万,iOS版日登陆近1300万;新版发布后累计登录用户数达到5600万。新版本在4天内的转化率,就达到以往版本一周的升级转化率。而在遭遇了大量针对“永远在线”功能吐槽的同时,同样有很多用户认为新版的界面清爽、沟通方便,简化后的QQ空间与微信朋友圈靠拢,互动率提升很明显。
从新版手Q的两大探索来看,时间上强调24小时在线、广度上强调潜入各类移动设备并因此打造“微内核”,这将是腾讯官方对微信成功经验的提炼与贯彻,也非常值得广大移动互联网从业者借鉴。
并非题外话的PS:分析腾讯的逻辑
中国丰富的历史文化资源,以及悠久的泛政治传统,都使得一种分析逻辑广受欢迎,那就是“宫斗”。任何公司内部的跌宕起伏,都可以演绎出步步惊心的甄嬛传。
在微信崛起于腾讯体系内之后,这种分析逻辑也一度大行其道。张小龙的媒体曝光率一高,就有“马化腾饭局敲打”的段子流传;手机QQ一改版,也有“腾讯用生命山寨腾讯”的说法出台(没错,说的就是我大虎嗅的那篇著名头条)。仿佛微信与QQ等新老产品已经形成九王夺嫡之势,我保留独门秘笈、你不惜一切代价明争暗抢云云。
但实际上,自前年腾讯推行“媒体开放”活动以来,马化腾以下和几乎所有的大事业群一把手都公开露面过,从跟他们接触的情况来看,无论是负责社交网络事业群的汤道生、负责电商的吴宵光,还是直接负责QQ的即通部负责人殷宇,都是IT产品经理的宅男气息横溢,全无权谋老手对外沟通时的面面俱到、滴水不漏。
微信所在的广研被称为腾讯特区,一方面是它可以脱离现有架构去探索新产品,另一方面则是特区可以得到大后方的资源支持。马化腾说微信的初始用户几乎都是通过QQ关系链导入,即使现在,QQ导入也是微信新用户的绝对多数来源。在享受政策优惠之后,将自己探索出的经验回馈给整体大后方,当年的深圳也同样是这么干的,不过那会儿没人说“中国用生命山寨深圳”而已。
而对于一些竞争对手来说,渲染、夸大微信与其他部门、其他公司的矛盾也是惠而不费的公关策略。这一方面符合国人的想象,另一方面,密集轰炸之下,说不定哪天矛盾就真产生了呢。这次手Q在App Store上三天遭遇了四万多个评论,我去查了一下,最火的微信新版一个月也不过四千多评论,新浪微博也才六百多。这四万多里面有多少真用户、多少刷宫斗气氛的,也真难说。
所以,腾讯这个公司的主要矛盾,不应该用政治宫斗这种逻辑去分析(当然不是说所有互联网公司都不该这么分析),它的主要矛盾在于发展14年、覆盖了七八亿用户;在时间上和广度上要继续保持住这种覆盖,本身就有撕裂产品需求的危险,微软就是在这种“无限兼容”中丧失了创新的动力。微信是一个突破的尝试,手Q正在沿着这种突破往前走,但一旦特区经验推广到整体,历史包袱与发展动力之间能产生多尖锐的对立,将是它面临的最大考验。
离职员工揭露腾讯微博之死:因为No zuo所以Die
原标题:关于腾讯微博之死,离职员工所了解的真相
本文作者:腾讯微博离职员工李阳,微信公众号:veyronli
2011 年加入腾讯前,我直接没有考虑去聊聊新浪微博。因为我觉得腾讯微博其实更有机会笑到最后,即使当时新浪已占先机、如日中天。怀着投机心理和济世情怀,我成了腾讯微博的一员。但2013 年初,我感觉腾讯微博脉象衰微,已经知道“这孩子迟早是要死的”。虽然我做过一点事情,尽管我认为腾讯微博仍有机会,然而并没有什么卵用。从离开的当季开始,微博就再也没在腾讯季报中出现过。
我不晓得当时的战略、决策,也不关心有什么宫斗、内幕,更无意于对任何一位共事过的同事指手画脚。我只从自身体验和观察出发,说说我所知道的真相。毕竟作为一个久病成医的互联网老中医,在腾讯微博活着的时候,我曾牵过它手、摸过它脉。
勉强完成使命,终算死得其所
腾讯当时要做好微博是认真的,它并不注定是个会成为炮灰的产品。我对腾讯微博有三个基本判断:它还算完成了使命,死得其所;它其实可以活得很好;它的死因,真相只有一个——慢性自杀。
关于他的使命,我同意魏老师所说的结果:“从这个意义上讲,腾讯微博又是一个成功的产品:它的确拖缓了新浪微博的商业化速度,并通过微信,将“现象级产品”五个字从新浪微博手中重新抢了回来。”但防守只是他的最低目标,目的都谈不上。如果要说目的,探索社交广告收入才是真实的目的之一。
通过微博一战,腾讯微博和新浪微博硬生生并列为两大主流微博,流量早就第一、收入当时刚刚爬到四大门户第一的腾讯门户,由此正式成为最主流门户。同时,腾讯和新浪一起把微博这个行当做得半死不活,保卫了QQ 空间及其开放平台,也为微信另辟蹊径崛起争取了时间。但这是个客观结果,而不会是初心,它并不是为当肉盾而生的。只能说,腾讯微博成功完成了它的最低使命,结局是腾讯最初设想中能接受的最不济结局。也算死得其所,没有白死吧!
它其实可以活且活得更好。但瞧病可以免费,开药就得收钱了,腾讯又不给我钱。更何况,有药腾讯微博也已没法再吃了。
因为No Zuo,所以Die
腾讯微博之死,真相只有一个,是慢性自杀。它死于跟新浪亦步亦趋、与兄弟若即若离、对资源不依不舍。
常见的死法是No Zuo No Die,腾讯微博却相反,它没犯过啥作死的致命错误,没做什么、坐以待毙才是死因。
魏武挥老师复盘腾讯微博的小败局,认为原因在于丧失先机、激励和动力不足、运营水平落后和定位为防守型产品。还有人认为是这种产品形态水土不服有缺陷。这些都是客观原因或一些原因的结果。我认为还可以往灵魂深处挖一挖。
无数案例,包括微信,证明未得先机其实并不是个事,对巨头来说更是如此。腾讯微博人的运营水平、努力程度够不够,也还不必成败论英雄、轻易下结论。激励机制和求生动力,不是根本原因。劲头不那么足是个未经验证的表象结果,原因不一定就只是激励不够。更深层是求生求胜的欲望不强烈。若一开始就存在失败主义,地球人科技进步、装备提升,也无法战胜三体人。
说到这又要提一下微信。腾讯广研的资源和激励不见得比微博多,当时也并不面临像新浪微博一样需全员上阵、背水一战的境地,起步同样不是最早的。如果说广研团队比别人多点什么,恐怕就是他们从用户真实需求出发设计产品,抱有做成一个产品的欲望和信念。
想赢和相信能赢,真的很重要。这能决定是不是有“你打你的我打我的”的自信,决定是否能从腾讯社交系统和用户的特点出发,用微博形态做出受喜爱的产品。
跟新浪亦步亦趋
腾讯对微博的“战略级产品”定位我认为是真诚的。腾讯微博最初获得的资金、流量、技术、人力支持等资源让竞品都眼红得很。腾讯总办一票大佬天天发微博、体验社交游戏和小应用,甚至不惜沦为广告狗。
腾讯微博动用了很多的资金拼抢名人资源,虽然很粗放,但还是有效的,在局部建立起颇为不错的影响力。只是这打法跟新浪亦步亦趋,得出的结果终究只是跟老大的屁股贴更近点,而不可能从某处超越。运营方法上,跟领先者用一样的方法贴身肉搏,除非体量有真的压倒性优势,不然外界看来,你终究不过是个大老二。
商业模式探索上,腾讯其实也本有优势,无论是社交游戏还是社交广告,腾讯微博都有大过新浪的基本盘。
游戏收入、产品供应和游戏玩家,腾讯都不太缺,但不会阻拦微博把游戏渠道做起来。广告模式是腾讯希望有大突破的,这也本是OMG(腾讯的在线媒体事业群)的基本价值所在。这两个部分最终都是QQ 空间为主的开放平台做起来了,SNG(腾讯的社交网络事业群)的广点通成了全腾讯社交产品和开放平台的广告运营主体。
也许还可以靠电商和卖“大数据”维生,也许吧。这俩其实一直只是理论上可能。
结果腾讯微博只是跟着新浪,对方开发啥广告形态啥广告位,这边就弄个类似的拿去抢着卖,在广告主那里分食到老二级的广告份额。最终结果就是让新浪不要活得太好,自动对号入座做了肉盾。
有一种情绪,内部一直任其存在和滋长,一定程度上影响了军心——“我们就是炮灰”。当时有的同事在群里讨论问题,会带出这种情绪,甚至直接表达这样的意思。一边跟新浪亦步亦趋,一边觉得这样不是出路,一边还觉得自己就注定是在参与一个炮灰事业。好悲壮。
可能有些人真是受了一些媒体和评论家影响,他们天天鼓吹腾讯微博就是防守型产品。比如之前网易副总编张锐宣称,微博对四大门户来说,新浪是战略级产品,网易是变革型产品,腾讯是阻击型产品,搜狐是跟随型产品。更有业者这样评论:新浪拿它当饭吃,网易拿它当菜吃,腾讯条件反射抢着吃,搜狐说你们都吃我也吃。其实都是说说而已。张锐那样讲,有一些对各公司习性的判断在里面,但更像是鼓舞网易士气和打击腾讯气焰。就像以前业界长期诋毁QQ.com 用户低端广告价值低,流量只靠QQ 弹窗不靠门户内容之类,那是对广告圈糊弄糊弄的,大企鹅自己内部竟也有人当真?
其实哪家公司会投入大量资源和人力在一块业务,还公开对这块业务的将士说:“你们就是送死的,对付对付别失守就行。”你见过谁家派敢死队,是配备战役级装备和兵力,还持续那么多年的?肯定还是希望进取打出漂亮仗,最坏能接受“不失守”而已。
与兄弟若即若离
与兄弟若即若离,我指的是腾讯微博跟QQ、QQ 空间等相处起来显得比较独。早期即通、空间和搜搜等部门都对微博有过支持,奉命行事也好,投资于“战略级产品”也罢,GM 们相互支持也成,兄弟们的支持是不少的。但后来微博追求独立性,几乎断绝了与大社交体系和大开放平台的协同,没有背靠腾讯生态体系压制新浪,而是单打独斗去“撞沉吉野”。
微博自己一度说要做个广告系统,后来为啥没做我不确切知道。但广点通运营不错的时候,腾讯微博却没有开心地引进这样一个现成武器。社交游戏也一样。不甘于做一个受兄弟指挥的渠道很有志气,但前提得是你做成了一个好渠道。
既希望大哥小弟们给量给底层支持,又不希望分享运营果实。自己既不是美国,又不肯加入北约给美国当日本小弟,资源有限还想学中国自建“完整工业体系”,呵呵。哥哥弟弟们再宠你让你,也不会一直傻下去。慢慢地,后起的微信都不愿意关联微博了。
要说安心当肉盾,日本这样的肉盾当得其实很不赖,防守中国的时候把自己也搞成了强国。最好的防守是进攻,最好的肉盾本身也肌肉强健。
对资源不依不舍
大企鹅是有系统性的支持,让内部很多产品生下来就含着金钥匙,只靠拼爹轻松就有机会成为千万级、亿级产品。这种系统性的成功保证,让腾讯人不必是特种兵,2 万个普通人加少量的英雄,就能为腾讯帝国持续开疆拓土。
生为富二代是好事,但奶是迟早要断的。什么OMG 没有社交基因,这跟“防守型产品”一样不成立。微信团队不是搞社交起家,陌陌唐岩是搞门户内容出身。根本原因是这个产品一开始就是催熟的,没有尽快形成内在的生长能力,没有了解和满足用户让用户真的爱上,除了撒娇闹独立也没试过真的具备独立生存能力,一直是个靠输血喂奶的怪胎巨婴。直到被抛弃,还在说“妈你生我就是为了让我死吧”。
一开始业界说,腾讯微博就是靠QQ 和空间说说同步,这也本不是真相,而是一种误解,或是别有用心的诋毁,慢慢竟真的一语成谶。
2012 年中已有迹象,腾讯希望微博,作为一个拥有数亿用户的产品,得自己找到好好活的办法了。然后,你懂的。
资源是毒药。当你不知道为何而战,当你并不为胜利而战,有毒药也不给你吃。腾讯微博,卒。
今天在做前端输出的时候,需要和app的做些对接工作。就是在手机浏览器中下载某app时,能判断该用户是否安装了该应用。如果安装了该应用,就直接打开该应用;如果没有安装该应用,就下载该应用。那么下面就对在浏览器中,用js判断某用户是否安装了该应用,并判断是否打开该应用做个简单的介绍。
那么,怎么判断某用户是否安装了某应用呢?
在这里,先写段html代码,如下:
<!doctype html> <html> <head> <meta charset="utf-8"> </head> <body> <a href="某app下载链接" class="down_app" onclick="isInstalled()"></a> </body> </html> 判断手机端是否安装某应用,并打开该应用的js代码如下:
function isInstalled(){ var the_href=$(".down_app").attr("href");//获得下载链接 window.location.href="apps custom url schemes";//打开某手机上的某个app应用 setTimeout(function(){ window.location.href=the_href;//如果超时就跳转到app下载页 },500); } 下面对这段js代码做一个简单的解析:首先试着打开手机端某个app的本地协议;如果超时就转到app下载页,下载该app。
说到这里,有人就要问了,这个本地协议又是怎么建立的呢?好了,下面也就这个做个简单的介绍:
其实就是在app中将http协议转换为本地协议,具体怎么转换,不在本讨论范围。但需要在app里面对配置文件做一下设置(一般是在manifest.xml文件的activity的intent filter里面):
<span> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="**" android:host="**.**" android:pathPrefix="/**"> </data> </intent-filter> </span> apps custom url schemes是什么呢?
其实就是你与app约定的一个协议URL,在IOS客户端或者Android客户端中可以设置一个URL Scheme。例如,设置URL Scheme:app,然后其他的程序就可以通过“URLString=app://”调用该应用。还可以传参数,如:app://reaction/?uid=1
以上介绍了怎么创建该本地协议及调用该本地协议的方法。但这里还有个关键就是怎么判断用户是否安装了该app呢?原理如下:
在手机浏览器中用js代码请求该协议,如果在500ms内,如果有应用程序能解析这个协议,那么就能打开该应用;如果超过500ms就跳转到app下载页。
但最近也发现了一些问题,在iPhone、华为、小米及酷派等手机下,都能正确打开app。但当用户手机没有安装app时,iPhone、华为等手机可以打开app应用,小米就打不开。页面会显示所请求的地址有错等,没能跳转到app下载页面。在网上找了些资料,有以下两种解决方法:
1.将setTimeOut的时间缩短,我这里设置的是500ms,觉得时间有点长了,那么我就设置30ms;
2.另外,iOS下将连接协议改成itms://itunes.apple.com/cn/app可以避免。(至于Android能不能这么搞,还待测试后才知)。
Combination Sum Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T. The same repeated number may be chosen from C unlimited number of times. Note: All numbers (including target) will be positive integers. Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
Count and Say The count-and-say sequence is the sequence of integers beginning as follows: 1, 11, 21, 1211, 111221, ... 1 is read off as "one 1" or 11. 11 is read off as "two 1s" or 21. 21 is read off as "one 2, then one 1" or 1211. Given an integer n, generate the nth sequence. Note: The sequence of integers will be represented as a string.
一、设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。 行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。 其实还有两类:并发型模式和线程池模式。用一个图片来整体描述一下:
二、设计模式的六大原则 总原则:开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,而是要扩展原有代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类等,后面的具体设计中我们会提到这点。 1、单一职责原则 不要存在多于一个导致类变更的原因,也就是说每个类应该实现单一的职责,如若不然,就应该把类拆分。
2、里氏替换原则(Liskov Substitution Principle) 里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。—— From Baidu 百科 历史替换原则中,子类对父类的方法尽量不要重写和重载。因为父类代表了定义好的结构,通过这个规范的接口与外界交互,子类不应该随便破坏它。
3、依赖倒转原则(Dependence Inversion Principle) 这个是开闭原则的基础,具体内容:面向接口编程,依赖于抽象而不依赖于具体。写代码时用到具体类时,不与具体类交互,而与具体类的上层接口交互。
4、接口隔离原则(Interface Segregation Principle) 这个原则的意思是:每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。
5、迪米特法则(最少知道原则)(Demeter Principle) 就是说:一个类对自己依赖的类知道的越少越好。也就是说无论被依赖的类多么复杂,都应该将逻辑封装在方法的内部,通过public方法提供给外部。这样当被依赖的类变化时,才能最小的影响该类。 最少知道原则的另一个表达方式是:只与直接的朋友通信。类之间只要有耦合关系,就叫朋友关系。耦合分为依赖、关联、聚合、组合等。我们称出现为成员变量、方法参数、方法返回值中的类为直接朋友。局部变量、临时变量则不是直接的朋友。我们要求陌生的类不要作为局部变量出现在类中。
6、合成复用原则(Composite Reuse Principle) 原则是尽量首先使用合成/聚合的方式,而不是使用继承。
三、Java的23中设计模式 A、创建模式 从这一块开始,我们详细介绍Java中23种设计模式的概念,应用场景等情况,并结合他们的特点及设计模式的原则进行分析。
首先,简单工厂模式不属于23中涉及模式,简单工厂一般分为:普通简单工厂、多方法简单工厂、静态方法简单工厂。 0、简单工厂模式 简单工厂模式模式分为三种: 01、普通 就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。首先看下关系图:
举例如下:(我们举一个发送邮件和短信的例子) 首先,创建二者的共同接口: [java] view plaincopy public interface Sender { public void Send(); } 其次,创建实现类: [java] view plaincopy public class MailSender implements Sender { @Override public void Send() { System.
matlab中元胞数组(cell)转换为矩阵、 cell转换为矩阵函数为:cell2mat(c),其中c为待转换的元胞数组;
转化之后的矩阵可能不满足我们对矩阵维数的要求,那么也许还需要下面两个函数:
——reshape(A,m,n,p,...),将矩阵A变换为m*n*p*...的矩阵;
——permute(A,[1,3,2]),将矩阵A的第3维和第2维交换,从而满足顺序要求;
下面举一个我自己用过的例子:
H——<K*1>cell,其中每个元素为U*S*N*T的四维矩阵(H为WINNERII的信道矩阵)
U:接收天线数目 S:发送天线数目 N:多径数目 T:每条链路采样点数 K:链路数
为了将H变换为U*S*N*T*K的五维矩阵,进行下述变换:
(1)H1=cell2mat(H);%转换为矩阵,如下图所示,则H1为(U*K)*S*N*T的四维矩阵
(2)H2=reshape(H2,U,K,S,N,T);%改变矩阵H1的形状
(3)H3=permute*(H2,[1,3,4,5,2];%将矩阵变化为U*S*N*T*K的矩阵
现在一部分人中存在一个误区,他们认为同步建模不是参数化的。你可以拥有一个或者另一个,但是不可能两者同时拥有。我想那事因为有许多人将基于历史的建模等同于参数化,而其他的建模方式一定是不同的。
事实上同步建模的零部件都是完全参数化的。我们这样说并不是要混淆概念,玩文字游戏或者是利用某些术语。对于 “参数化”的任何传统意义而言,同步建模的零部件都是符合的。零部件是由尺寸和集合关系来控制的,并且尺寸能通过其他的赋值或者方程式来控制。
这儿有一个简单的例子。这个零件是同步的,所以它有特征,但是特征都完全是面上采集的,并且是通过草图来创造的,但是草图什么都控制不了,他们在那什么都做不了。尺寸是直接和三维几何模型相联系的,红色的是控制的,紫色的是由方程来控制的。
参数组合的一部分几何关系有两个来源:由用户定义的面之间的关系(称为面关系),或者是由实时的规则设定来自动控制的实时的规则关系。当你工作的时候你可以改变这些设定,但是他们是为了帮你保持垂直度,同心度,相切,平行和其他一些常见的关系。
模型的尺寸也可以从几个地方得到。如果你在草图上定义尺寸,那么那些尺寸就由草图直接反映到三维模型上。或者,用户也可以通过手动选择边缘来来应用尺寸。在同步建模环境下产生的尺寸,都是可驱动PMI尺寸。
然后SOLIDEDGE 通过颜色来指示不同状态的尺寸:
红色:锁定或者开启,你必须明确地编辑值来使它改变。
蓝色:解锁,值可以通过其他的尺寸或者关系的改变而被改变
紫色:被其他方式来控制的尺寸和没有驱动的尺寸同样用紫色来表示。没有驱动的尺寸同样是被控制的。
Solidedge同样使你能够使用方程来控制尺寸。方程可以通过使用在工具条变量组里的变量表来输入。变量表如下图所示:
这个表非常的方便,并且在使用过其他CAD程序之后,我能够说输入公式并且命名变量和暴露变量来自定义属性是非常方便的。另外,在你做其他事情时,这个对话框也能保持开启的状态。如果你过去只用过Solidedge,你可能像其他的CAD使用者一样对这个并不欣赏。这并不性感,或者闪耀,或者做旋转或者运行机器人,但是这个对话框是众多的功能之一,是这些家伙多么致力于生产效率的证据。
而且,对于这片文章更为主要的观点而言,变量表显示了你能够用参数化功能到同步建模中的程度。当然我这边所用的零件是非常简单的,但是这些理念你可以用在任何东西上来改变他们的尺寸。
所以如果那些不知道他的CAD系统已经是历史的使用者之一尝试着去告诉你同步技术不是参数化的时候,你可以把他送过来接受教育,或者让他坐下来,你自己展示给他看。
如果你想在一个公式都已经编辑好的零件上试验其中的一些理念,你可以从下方下载我的简单的样例。
链接:http://community.plm.automation.siemens.com/t5/Solid-Edge-Blog/Synchronous-AND-Parametric/ba-p/297109
文中的一些图片无法显示,可以关注soiidedge联盟微信公众号~~~
http://mp.weixin.qq.com/s?__biz=MjM5OTk4NDc2NQ==&mid=210062445&idx=1&sn=f7bc11a48e093212d585ec3fd97dea11#rd
转载于:https://my.oschina.net/u/2357930/blog/475428
openssl TLS的关系
TLS(Transport Layer Security,安全传输层),TLS是建立在传输层TCP协议之上的协议,服务于应用层,它的前身是SSL(Secure Socket Layer,安全套接字层),它实现了将应用层的报文进行加密后再交由TCP进行传输的功能。
在SSL更新到3.0时,IETF对SSL3.0进行了标准化,并添加了少数机制(但是几乎和SSL3.0无差异),标准化后的IETF更名为TLS1.0(Transport Layer Security 安全传输层协议),可以说TLS就是SSL的新版本3.1,并同时发布“RFC2246-TLS加密协议详解”
1.0.0h的Openssl版本支持SSLv2,SSLv3和 TLSv1.0
从Openssl 1.0.1开始,添加了对TLSv1.1和TLSv1.2的支持
从Openssl 1.1.1开始支持TLS1.3
mac下的opessl默认是0.9,更新方式如下:
http://www.liuchungui.com/blog/2016/05/10/mac10-dot-11sheng-ji-an-zhuang-openssl/
生成公私钥(证书)
https://openhome.alipay.com/doc/docIndex.htm?url=https://openhome.alipay.com/doc/viewKbDoc.htm?key=236615_428849&type=info
注意 PKCS8格式私钥 是给java服务端用的,C++客户端使用RSA格式
PEM格式证书
PEM – Openssl使用 PEM(Privacy Enhanced Mail)格式来存放各种信息,它是 openssl 默认采用的信息存放方式。Openssl 中的 PEM 文件一般包含如下信息:
内容类型:表明本文件存放的是什么信息内容,它的形式为“——-BEGIN XXXX ——”,与结尾的“——END XXXX——”对应。
使用PEM格式存储的证书:
—–BEGIN CERTIFICATE—–
MIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx
………
1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU=
—–END CERTIFICATE—–
使用PEM格式存储的私钥:
—–BEGIN RSA PRIVATE KEY—–
MIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx
………
1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU=
—–END RSA PRIVATE KEY—–
使用PEM格式存储的证书请求文件:
—–BEGIN CERTIFICATE REQUEST—–
MIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx
………
1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU=
—–END CERTIFICATE REQUEST—–
1, Lua 是一个小巧的 脚本语言。是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组,由Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo所组成并于1993年开发。 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行。Lua并没有提供强大的库,这是由它的定位决定的。所以Lua不适合作为开发独立应用程序的语言。Lua 有一个同时进行的JIT项目,提供在特定平台上的即时编译功能。 Lua脚本可以很容易的被 C/C++ 代码调用,也可以反过来调用C/C++的函数,这使得Lua在应用程序中可以被广泛应用。不仅仅作为扩展脚本,也可以作为普通的配置文件,代替 XML,ini等文件格式,并且更容易理解和维护。 [1] Lua由标准C编写而成,代码简洁优美,几乎在所有操作系统和平台上都可以 编译,运行。 [1] 一个完整的Lua解释器不过200k,在目前所有 脚本引擎中,Lua的速度是最快的。这一切都决定了Lua是作为嵌入式脚本的最佳选择 2,运行和保存 运行可以通过 Lua 的交互模式,也可以用记事本编辑代码保存为 .lua 的格式,通过 lua 编译器运行。也可以通过第三方工具,将 lua 打包独立运行。
3,目标 Lua的目标是成为一个很容易嵌入其它语言中使用的语言。大多数程序员也认为它的确做到了这一点。
Android背景音乐示例,Android背景音乐需要用到server,服务(Service)是Android中实现程序后台运行的解决方案,它非常适合用于去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使当程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。
程序中我用了 Switch控件,Switch控件只能在Android4.0版本以上使用,因此程序的版本不能低于Android4.0
<Switch
android:id="@+id/st_music"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:textOn="@string/play"
android:textOff="@string/stop"
android:layout_marginTop="184dp"
android:text="@string/music_bg" />
背景音乐的server我是新建了一个AudioService类并继承了MediaPlayer.OnCompletionListener,AudioService类的源码如下:
package com.example.service;
/**
* 多线程实现后台播放背景音乐的service
*/
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;
public class AudioService extends Service implements
MediaPlayer.OnCompletionListener {
// 实例化MediaPlayer对象
MediaPlayer player;
private final IBinder binder = new AudioBinder();
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public void onCreate() {
super.onCreate();
// 从raw文件夹中获取一个应用自带的mp3文件
player = MediaPlayer.
据前面所述,谷歌地图采用的Web Mercator对于中国境内是做了坐标加密处理的,而在境外又没有加密,所以,一直以来都有一个问号:接边是怎么处理的?也就是说在国境边界上会发生什么情况,下面的两个实验将说明这个问题。
实验二:谷歌地图(街道图)边界问题
辽宁丹东(中朝边界)
广西东兴(中越边界)
毫无疑问,基本没有接边处理,完全乱套,无奈。
实验三:谷歌地图(影像图)会怎么处理,街道可以错接,影像又会怎样?
还是在广西东兴(中越边界)
影像图正常,而叠加的街道是乱的。
影像图正常,就意味着影像图并没有偏移,这一点我们再来看 清华东门处的影像叠加街道。
仔细看会发现,影像中清华东门校训位置与上一篇中谷歌地图的标记位置是基本重叠。这就很好的说明了影像图没有任何偏移,而街道图做了加密偏移。
汇总来说,谷歌自身的街道图与影像图在中国境内是无法叠加的,同时谷歌地图的中国边境的街道图是完全混乱的,但是为了国测局加密要求,谷歌很无奈。
题外话:那么高德地图会如何表现呢?
Java post 提交数据工具类
package com.wd.util; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.http.HttpResponse; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.apache.http.util.EntityUtils; public class HttpUtil { /** * 提交Post请求 * @param params url参数Map * @param url * @return */ public String post(Map<String,String> params,String url){ List<BasicNameValuePair> paramsList = new ArrayList<BasicNameValuePair>(); for(String key : params.keySet()){ paramsList.add(new BasicNameValuePair(key, params.get(key))); } // 第一步,创建HttpPost对象 HttpPost httpPost = new HttpPost(url); HttpResponse httpResponse = null; try { // 设置httpPost请求参数 httpPost.
如喜欢本书,请购买正版。 外界评价 《快乐之道》阐述了一些最基础的原理,它们不仅适用于游戏,也适用于所有的娱乐。更好的是,这本书用一种清晰、富有洞察力并且饶有情趣的风格做到了这一点!对于任何做过游戏或者玩过游戏的人来说,我预期这本书将很快成为经典的迷人之作。
一法尔斯坦,自由游戏设计师/作家/制片人
读这本关于快乐的书真的很快乐。它令我想起了麦克劳德的《理解漫画》——这本书引起了巨大争议——因为它将游戏引向基础理论,并以富有魅力的方式呈现出来。
——詹金斯,麻省理工学院比较媒体研究项目主管
这些年来,拉夫对于无数游戏开发者都是灵感的源泉。现在,他正在揭示最最重要的原理,所有的游戏设计师都会在某一天需要这些原理,以便成为“制造快乐”的大师!
——佩雷,Atari旗下Shiny娱乐公司总裁
非游戏玩家:为了你生活中的游戏玩家买这本书。游戏玩家:为了你生活中的非游戏玩家买这本书。你将再也不可能用同样的方式来看待快乐了。
——多克特罗,著名科幻作家,BoingBoing网站主编
游戏远远不止是玩得开心——它是做人的核心。理解游戏和获得快乐能帮助我们理解自己。拉夫•科斯特是一个好人,总是致力于在我们的世界中创造更有趣的事物。他也用这本书帮助我们这些读者和他的学生们做到这一点。
——麦克•沙弗雷,布雷克威游戏电台台长
太令人惊讶了!全新的感觉!只有在电视上才可能见到!科斯特的《快乐之道》是一本写得极好的、及时的、充满热情的书,一定会得到极大关注。
——卡斯特诺瓦,印第安纳州立大学电信学副教授
致中国读者 看到我的这本书在中国翻译出版是一个莫大的荣幸。中国正在经历一场游戏的“文艺复兴”,一个庞大的游戏行业正在不断成长。很长时间以来,中国就有一种挑战思维游戏的文化传统,今天我们看到,中国的游戏业正在前所未有地兴旺发达。
我写这本书的目的,是因为许多人多多少少会把游戏看成无足轻重的业余活动。某些游戏(比如围棋和国际象棋)被看作文化象征,那些精通它们的人也获得了相应的尊重。但大多数游戏还是被看成是儿童的玩物。只用来让小孩子们开心。
随着电子娱乐的兴起,我们看到游戏正在日常生活中占据相当显著的位置。现代文化日益被电子行业所主宰,而那些由于电子行业才得以诞生的新游戏则是十分引人注目的创造,它们消耗了人们大量的时间。
在这么一个调整时期,回到游戏的根源,思考一下游戏为什么会存在于每一种文明之中,思考一下为什么各个年龄的孩子都玩游戏,以及它们在我们的大脑发育中扮演了什么角色,是一个很好的主意。
现代科学已经证明,游戏根本不是无足轻重的,它可以是一种重要的教育工具,是故事和娱乐的展示场,是强有力的大众传媒。不过,这里有一条代沟——由于其威力,新的电子游戏吓坏了许多人。
我衷心希望本书能成为你送给父母、老师和朋友的礼物,这样他们就会懂得为什么游戏能感动你的心灵。如果你是一名游戏设计师,那么我希望它会让你用一种新的角度看待游戏,充分认识到它们的潜力。如果你是一个玩游戏的人。那么我希望它会给你一个理由,让你在告诉別人你是一个游戏玩家时能高高地昂起你的头。
希望你喜欢这本书!
序言 这本书的标题几乎让我产生了错觉。作为一名游戏设计师,看到“理论”(或者说“道”)和“快乐”这两个词如此紧密地放在一起,会近乎本能地令我感觉有点不舒服。理论是枯燥的、学院派的东西,存在于图书馆收藏的那些厚厚的书里,而快乐是轻松的、活泼的、好玩的……嗯……就是快乐的。
在交互式游戏设计出现的头几十年中,当我们慢慢地、痛苦地蹒珊学步时,我们可以高高兴兴地忽略周围很多棘手的潜在问题。现在,我们第一次从学术的角度,开始寻求我们所做工作的严肃意义。这本书迫使我们这些游戏业内人士停下来思考,“我们正在其中工作的新媒体到底是什么?”
对这个问题的学术兴趣看起来有两方面:首先是承认视频游戏可能代表了一种正在出现的新媒体,一个新的设计领域,也可能是一个全新的艺术形态。所有这些都是值得研究的。其次,越来越多积极主动的学生们在玩游戏的过程中成长起来,他们发现自己受到了激励,希望自己有一天会在这个领域中工作。他们想要找到学校,帮助他们理解什么是游戏,怎么制作游戏。
这里就有了一个小问题:无论学生们多么主动,非常懂得游戏并有能力讲授相关知识的教师却很少。事实上更糟的是,在当今的游戏业中,只有非常少的人真正懂得游戏,并且能够向他人讲述他们所知道的以及他们是如何知道的(拉夫•科斯特自然是其中一员)。
在游戏业和希望研究及讲授游戏的学术界之间,桥梁正在开始慢慢地建立起来。一种通用的语言正在发展,它可以使得大家在一种共同的语境下谈论游戏,并帮助开发者更容易地彼此共享他们的经验。将来的学生们将在这种语言环境下学习。
游戏(包括视频游戏和传统游戏)是很难研究的。因为它们是如此的多维。有许多不同的方法可以让我们接近游戏。游戏的设计和制作包含了认知心理学、计算机科学、环境设计和故事叙述等等(这里只举了几个例子)。要真正理解什么是游戏,你需要从所有这些角度来审视它们。
我总是喜欢听拉夫•科斯特谈话。在我所认识的游戏业人士当中。他是少数对这个可能涉及自己工作领域的课题进行研究的人之一,即使他不能立刻清晰地知道为什么。他在非常广泛的知识领域搜寻,然后回来和我们共享他所发现的东西。他不仅是一名勇敢的探险家,而且是一名用功的地图制作者。
在本书中,科斯特做了非常优秀的工作,通过各种观点来看待游戏。带着在此领域工作的设计师的本能,他通过自己在一系列相关课题上的研究,挖掘出了一个行业的财富宝藏,其中的金块可谓价值连城。然后,他想方设法将他的发现用一种友好的、有趣的方式表达出来,使得一切看上去都如此恰到好处。这本书简直完美无瑕。
对于这样一本荟萃智慧精华之书……我想我可以认可这样的标题。
威尔•怀特(Will Wright)
威尔•怀特,Maxis公司首席设计师,该公司是他在1987年和布劳恩共同创办的,曾开发过《模拟城市》等经典游戏。1999年,怀特被《娱乐周刊》列入“娱乐界100名最具创意者”榜单,并在《数字时代》关于塑造今日科技的最重要人物评选“Digital 50”中榜上有名。
开场白 我的爷爷 我的爷爷曾经想知道,我是否为自己所从事的工作感到骄傲,这对他来说是一个很合理的问题。他做了一辈子的消防队长,抚养了六个孩子长大。问我的时候,他正在逐渐衰老并即将离开人世,虽然当时我并不知道这一点。他的六个孩子中,有一个追随他的脚步也成了一名消防队员,但是现在在销售浴缸。其他几个孩子有一个做了特殊教育老师,一个做了建筑工程师,还有一个做了木匠。这些工作都为社会作出了有益的贡献,他们都是有益于社会的人。而那时的我——正在开发游戏,却没有在为社会作贡献。
我告诉爷爷,我觉得自己确实为社会作了贡献。游戏不仅仅是消遣,游戏是有价值的、重要的东西。而我的证据就摆在我面前——我的孩子们,他们正在地上玩井字棋游戏。
看着我的孩子们在游戏中得到快乐和教育,我受到了后发。虽然我的职业是开发游戏,但我经常迷失于制作大型现代娱乐产品的复杂性之中,却忽略了游戏为什么是快乐的,到底什么是快乐。
不知不觉中,我的孩子们正引导我领悟何为快乐之道。所以,我就这么回答我的爷爷:“是的,这是有意义的事情。我把人们联系起来,并且教育他们。”但是在我这么说的时候,事实上我并不能提供任何证据。
第一章 为卄么写这本书? 我们的孩子们在很小的时候就开始玩游戏。游戏在他们的生活中无处不在,因为工作关系,我带回来不计其数的游戏。我觉得孩子模仿他们的父母是不足为奇的事情。但我和我的妻子痴迷于阅读,孩子们却抵触阅读。他们更加本能地被游戏所吸引。还是婴儿的时候,他们就发现捉迷藏游戏具有无穷的魅力,即使现在他们长大了,这个游戏偶尔还会引起他们的欢笑。作为婴儿,他们对外界的关注有着非常明显的意图。当他们想知道橡皮鸭子去了哪里时,这表明这个游戏时他们而言非常有吸引力。
孩子们随时随地在玩耍,他们常常玩一些我们并不是很理解的游戏。他们玩耍着,并且以惊人的速度学习。我们都看到过一些统计,关于孩子们一天内吸收了多少单词,他们对运动控制的开发有多快,他们掌握了多少生活的基本方面——老实说,其中有些方面是如此细微,我们甚至都忘了学习它们。可是我们经常未能认识到,这是多么令人惊异的能力啊。
想想看,学习一门语言是多么困难,但是全世界的孩子们都例行公事般地办到了。这是他们的第一门语言。他们学习语言时,不需要通过他们天生的说话方式来分配同源词(正文中的楷体或斜体字表示在书末的注释中对此有进一步的说明,下同。——译者),也不需要在他们的头脑中进行转换。最近,一些尼加拉瓜的失聪儿童受到了很多关注,他们只经过几代就发明了一种全功能性的符号语言。很多人相信,这显示了语言是植根于大脑中的,在我们的大脑线路中有某些东西不可抗拒地将我们导向语言。
语言并不是惟一不可更改的习性。当婴儿们爬上成长的阶梯时,他们会参与一些本能的行为。任何经历过“麻烦的两岁”的父母都会告诉你,在其孩子的大脑中似乎有一个开关,能在根本上改变他们的行为(顺便说一句,这种情况可能会延续至两岁以后的很长时间——仅仅是一个善意的提醒)。
随着孩子的长大,他们会跟随某些游戏一同前进。我曾经饶有兴致地观察我的孩子从井字棋游戏中获得的成长。我曾经一连好几年都能在这个游戏中击败他们,直到有一天,所有比赛变成了平局。
在这个游戏不再吸引他们的那一刻,它却引起了我极大的兴趣。为什么?我问自己,难道他们突然间就变得精通和理解了?孩子们不可能告诉我,井字棋是一种有限的最优策略游戏。他们看到了模式,但却没有像我们思考事物时一样,设法去理解。
对大多数人来说,这种现象并不陌生。我做很多事情时经常并没有完全明白它们,即使是那些我自己感觉已经很精通的事情。我并不需要有汽车工程师的学位才能去开车。在日常交流中,我不需要记得各种语法规则就能非常遵循语法地与人交流。我也不需要通过了解井字棋是属于NP难度还是NP完全,才能知道这是一个愚蠢的游戏。
他们已经领悟到井字棋是一种愚蠢的游戏。
我也有过很多次这样的经历:我凝视着某些事物,却就是不能够了解它们。我讨厌承认这一点,但我典型的反应是简单地避开。最近这些天,我感到我的心情有点糟糕(好吧,是很糟糕)。我发现自己没法去碰那些每个人都推荐我去玩的游戏。我就是没办法像以前那样快速地移动鼠标。我不想去感受这种笨拙,我宁愿不去玩游戏,即使其他玩家是我的朋友。
“我在网络游戏中根本干不过他们!那些14岁的混账孩子们。”说这句话的可不仅仅是我一个人。面对这种情况,我的反应不仅仅是挫折;它也让我感觉有点厌倦。我看到了这个问题,并且说:“好吧,我可以接受一个永远做不完的西西弗式的任务,试囝去赶上那些家伙。但是坦白地说,可以预见的是我会不断失败,这相当令人厌烦。我有更好的事情需要用自己的时间去做。”
从我听到的每件事情来看,这种感觉可能会随着我的年龄增长而加强。越来越多的新奇经历将会出现,直到2038年的某一刻,那时我将会需要自作聪明的孙子帮我摆弄一些弄不清楚是做什么用的机器,因为我应付不了那些新奇的装置。
这是不是不可避免呢?
我知道他们的感觉。我已经不再是一个孩子了,有一天,当我在电脑上玩游戏(第一人称视角射击渰戏)的时候,看起来我像正在于潮流对抗。
我退出了,因为我感觉自己已经不够格了。
当我在玩一些很合乎我胃口的游戏时,我依然能打败他们(木哈哈哈)。我们经常读到一些消息说,玩拼字游戏或其他智力挑战游戏的人延缓了阿尔茨海默氏病的发作。保持思维活跃真的能使人更加灵活并永葆青春活力吗?
当然,游戏不能永远持续下去。总有这么一个时候,你会说:“看,我想我玩过这个游戏所能提供的一切了。”这种情况在我身上最近发生的时候,是我在互联网上发现了一款打字游戏——这是一款可爱的游戏,我扮演一名潜水者,鲨鱼们想要吃了我。在每条鲨鱼边上都有一个单词,当我输入了这个单词,鲨鱼就会爆炸。
哎呀,我可是一个很厉害的正规打字员,每分钟差不多能打100个单词。这个游戏是很有趣,但它不过是小菜一碟。在第12或14关之后,游戏就认输了。它屈服了。它对我说,“你知道,我已经尝试了我能想到的每一种窍门,包括中间带有随机产生的标点符号的单词、反过来拼写的单词,而且直到最后一分钟才把单词显示给你。所以,随它去吧!从现在开始,我将只向你提出相同的挑战。但事实上,你现在就可以退出了,因为你已经看到了我所有的一切。”
我接受了它的建议,退出了。
其他时候,如果我玩自己擅长的游戏(解谜游戏),我会玩很久并玩得很好,直到我觉得厌烦。
太难的游戏令我厌烦,太简单的游戏也令我厌烦。随着我的成长,身边的游戏从一个换到另一个,就像井字棋对我的孩子们一样。有时候我和别人一起玩游戏,他们打败了我,随后和善地解释说:“噢,你看,这是一个关于顶点的游戏。”而我说:“顶点?我正在棋盘上移动棋子呢。”他们耸耸肩,好像在说我永远也弄不明白这一点。
正因为如此,我决定探究下面这些问题:什么是游戏,什么是快乐,为什么游戏是有意义的。我知道我得去探索一些已经广为人知的领域——例如很多叙述孩子发育行为的心理学文献。但事实上,我们不想总是那么严肃地看待游戏。
在我写这些话的时候,很多人已经开始探寻这些问题。以数字形态存在的游戏,已经成为一个巨大的产业。我们在电视上看到它们的宣传广告,我们争论游戏业是否比电影业更加赚钱(顺便说一下,到目前为止,回答是否定的),而且我们为游戏是否会给孩子们带来暴力倾向感到头疼。游戏现在是一股重要的文化力量。现在是时候来深入思考一下游戏衍生出来的种种问题了。
作为家长,我们强调应该给孩子们玩耍的时间,因为这对童年非常重要;但我们同时还会强调,工作在以后的生活中注定显得更为重要。我觉得这很古怪。说实话,我认为工作和游戏并没有那么大的区别。接下来的内容会让你明白,力什么我会得出这个结论。
为什么有些游戏很有趣,而有些游戏却令人厌倦呢?
为什么有些游戏玩了一会就会令人厌烦,而有些游戏经过很长时间还会让人觉得很好玩呢?
如需转载请标明作者,原文地址:http://xiaoquqi.github.io/blog/2015/06/28/ceph-performance-optimization-summary/
最近一直在忙着搞Ceph存储的优化和测试,看了各种资料,但是好像没有一篇文章把其中的方法论交代清楚,所以呢想在这里进行一下总结,很多内容并不是我原创,只是做一个总结。如果其中有任何的问题,欢迎各位喷我,以便我提高。
优化方法论 做任何事情还是要有个方法论的,“授人以鱼不如授人以渔”的道理吧,方法通了,所有的问题就有了解决的途径。通过对公开资料的分析进行总结,对分布式存储系统的优化离不开以下几点:
1. 硬件层面 硬件规划SSD选择BIOS设置 2. 软件层面 Linux OSCeph ConfigurationsPG Number调整CRUSH Map其他因素 硬件优化 1. 硬件规划 Processor ceph-osd进程在运行过程中会消耗CPU资源,所以一般会为每一个ceph-osd进程绑定一个CPU核上。当然如果你使用EC方式,可能需要更多的CPU资源。
ceph-mon进程并不十分消耗CPU资源,所以不必为ceph-mon进程预留过多的CPU资源。
ceph-msd也是非常消耗CPU资源的,所以需要提供更多的CPU资源。
内存 ceph-mon和ceph-mds需要2G内存,每个ceph-osd进程需要1G内存,当然2G更好。
网络规划 万兆网络现在基本上是跑Ceph必备的,网络规划上,也尽量考虑分离cilent和cluster网络。
2. SSD选择 硬件的选择也直接决定了Ceph集群的性能,从成本考虑,一般选择SATA SSD作为Journal,Intel® SSD DC S3500 Series基本是目前看到的方案中的首选。400G的规格4K随机写可以达到11000 IOPS。如果在预算足够的情况下,推荐使用PCIE SSD,性能会得到进一步提升,但是由于Journal在向数据盘写入数据时Block后续请求,所以Journal的加入并未呈现出想象中的性能提升,但是的确会对Latency有很大的改善。
如何确定你的SSD是否适合作为SSD Journal,可以参考SÉBASTIEN HAN的Ceph: How to Test if Your SSD Is Suitable as a Journal Device?,这里面他也列出了常见的SSD的测试结果,从结果来看SATA SSD中,Intel S3500性能表现最好。
3. BIOS设置 Hyper-Threading(HT) 基本做云平台的,VT和HT打开都是必须的,超线程技术(HT)就是利用特殊的硬件指令,把两个逻辑内核模拟成两个物理芯片,让单个处理器都能使用线程级并行计算,进而兼容多线程操作系统和软件,减少了CPU的闲置时间,提高的CPU的运行效率。
关闭节能 关闭节能后,对性能还是有所提升的,所以坚决调整成性能型(Performance)。当然也可以在操作系统级别进行调整,详细的调整过程请参考链接,但是不知道是不是由于BIOS已经调整的缘故,所以在CentOS 6.6上并没有发现相关的设置。
for CPUFREQ in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do [ -f $CPUFREQ ] || continue; echo -n performance > $CPUFREQ; done NUMA 简单来说,NUMA思路就是将内存和CPU分割为多个区域,每个区域叫做NODE,然后将NODE高速互联。 node内cpu与内存访问速度快于访问其他node的内存,NUMA可能会在某些情况下影响ceph-osd。解决的方案,一种是通过BIOS关闭NUMA,另外一种就是通过cgroup将ceph-osd进程与某一个CPU Core以及同一NODE下的内存进行绑定。但是第二种看起来更麻烦,所以一般部署的时候可以在系统层面关闭NUMA。CentOS系统下,通过修改/etc/grub.
链接:http://codeforces.com/gym/100405 这场yyn给我们找的用来练手的比赛,虽然很水,但我还是想写一下简要题解
A:N个点N条边提示我们去求最小生成树,然后枚举两个距离与距离表不符的点,选一对距离最小的,然后添加这条非树边。证明还有点混乱。。。(坑)
B:因为要求平面图,画一下就知道最大团不会超过4,暴力枚举就可以通过这道题
C:因为数据范围比较小,可以暴力dp在每个位置出现的概率
D:这题有很多组,卡时间比较厉害,如果按行转移的话每一行最多有1000左右的状态,复杂度就是1000*1000*7*7有可能会tle,但如果按列转移每一列的状态最多只有C(7,3)=35,暴力把这些状态搜出来,然后做一个35*35*7*7的dp就可以通过了
E:首先我们考虑先把第一层拆成 xy 的形式,因为 (ab)c=abc ,也就是说第二层的可以随便放回到第一层,因此我们先把第一层提出一个最大的b乘到第二层里面去。而对于第二层,由于 9587<214 ,因此第二层分解质因数结束后指数不会超过13,乘上第三层之后也不会超过13*9587,因此我们只需要暴力枚举第二层的公共次数,累加起来就可以了,这题可能不太好说,可以参考一下代码
#include<bits/stdc++.h> using namespace std; typedef long long Int; const Int Maxn=130000; typedef pair<int,int>pi; Int dp[Maxn]; vector<Int>has[Maxn]; void prepare() { for(Int i=2;i<Maxn;i++) { for(Int j=i*i,t=2;j<Maxn;j*=i,t++) has[j].push_back(t); } for(Int i=2;i<Maxn;i++) { dp[i]=1; for(Int x:has[i])dp[i]+=dp[x]; } } void f(vector<pi>&v,int x)//对x分解质因数 { v.clear(); for(int i=2;i*i<=x;i++) if(x%i==0) { int t=1; x/=i; while(x%i==0)x/=i,t++; v.push_back(pi(i,t)); } if(x!=1)v.push_back(pi(x,1)); } int main() { prepare(); Int a,b,c; while(scanf("
自己封装一个View
//在.h声明 @interface SelectView : UIView @property(nonatomic,assign)NSInteger selectIndex; - (instancetype)initWithTitle:(NSString *)title andItemArrar:(NSArray *)items; @end //在.m里面实现 #import "SelectView.h" #import "Masonry.h" @interface SelectView() @property(nonatomic,strong)UILabel * titleLabel; @property(nonatomic,strong)UIButton * selectBtn; @property(nonatomic,strong)NSString * title; @property(nonatomic,strong)NSArray * items; @end @implementation SelectView - (instancetype)initWithTitle:(NSString *)title andItemArrar:(NSArray *)items{ if (! (self = [super init])) return nil; self.backgroundColor = [UIColor yellowColor]; _title = title; _items = items; [self addSubview:self.titleLabel]; [self layoutPageFrame]; [self addSubview:self.selectBtn]; return self; } //点击事件 - (void)selectBtnClick:(UIButton *)sender{ //多选模式 // if (!
Promise用于解决异步中的流程控制问题。(比如只有完成1和2的调用后,才能做3,1和2都是异步调用,不知道1和2谁先谁后返回,那么Promise就能很好的解决这个问题)
解决邪恶金字塔问题。
详细参见:https://github.com/alsotang/node-lessons/tree/master/lesson17
php实现页面纯静态化的最终目的就是生成纯html文件,而这个纯html文件就存放在服务器的磁盘当中;
php实现页面纯静态化需要的东西:
1、文件写入函数
file_put_contents()、或者fopen()、fwrite()、fclose()等函数;
2、缓冲区(缓存)操作函数
ob函数(ob_start()、ob_get_contents()、ob_clear()、ob_get_clearn()等);
ob_start() — 打开“输出控制缓冲”;
ob_get_contents() — 返回“输出缓冲区的内容”;
ob_clearn() — 清空(擦掉)“输出缓冲区”;
ob_get_clearn() — 得到当前缓冲区的内容并删除当前“输出缓冲区”;
在之前的文章中曾经说过,当我们在执行一个php程序,如果这个php程序有数据输出,那么这个数据会首先输出
到php缓冲区,然后缓冲区才会将数据通过tcp传输到客户端并进行显示;
那么有了上面的ob函数(输出控制缓冲函数),那么我们就可以通过控制缓冲区的输出来达到我们的目的,即实现
页面的静态化;
流程如下:
首先,当我们执行一个有输出数据的php程序时,我们应该在输出数据之前开启“控制缓冲区”,让数据输出到缓冲区;
其次,我们就可以通过ob函数获取缓冲区的数据;
然后,将获取到的数据使用“文件写入函数”写入到一个html文件中,这个html文件就是纯静态化的html文件;
所以,我们就可以通过直接访问生成的纯静态化的html文件来达到和访问动态的php文件同样的目的,使程序更加高效的运行;
阿里巴巴的2014实习生面试刚刚结束。饱食终日无所用心,抱着试试看的态度,去游荡了一圈,把经历分享在这里,难免言不及义看官见谅。我面试C++后台开发、前端开发。在这里总结一下经验教训。
我报名了研发工程师实习,报名要填的内容好多,填了很久,阿里给了我在线笔试的机会。
笔试题目大多是数学逻辑基础和数据结构的题目,不太偏重计算机基础概念。成功通过。因为误报了北京面试,通知我去中科院blablabla(报名网站右bug,在选择面试城市之后就不能改了,什么都能改,就是面试城市不能改)。后来经过沟通,让我去广州大学城面试。
然后就赶到广州的大学城。这里邻近黄埔军校旧址,大学城被河水围绕,也是个好去处。很快就叫我进去了,里面有十几个小桌子,面试官和应聘者成对交谈。
首先,当然是自我介绍,然后稍微问了一下简历上的项目。面试官很nice,循序渐进。然后问了一些操作系统的问题,诸如线程和进程有什么区别(面试必问!),这部分没有很深入。 然后主要进入C++部分。
写一个自动锁,当时我不知道什么是自动锁,他便给我写了一个示例,大致就是利用对象的构造析构行为自动管理资源锁。 然后我在构造函数里写了lock(sth),析构函数里写unlock(sth)。后来才知道他希望我回答与操作系统交互的那部分,我说操作系统提供的锁的系统调用无非两种情况,一是直接返回true或false,我们进行忙等待;二是在该调用处阻塞该进程,直到获得了锁。至此面试官说OK。
构造函数里调用虚函数会出什么问题。我说编译错,回答错了。不会有任何问题,只是此时的虚函数表指针指向的永远是当前类型。Effective C++中指出 Don't 这样做。
单链表反向,给定head指针,写出C++函数。我一直以为这件事极其容易没有认真看过,没完全写出来。面试官很nice地让我描述给他怎么做,居然瞬间想出来了。维护两个链表head,一个指向已反向的链表头,一个指向仍未反向的链表头。遍历一次就好了。
找出链表的中间节点。使用两个指针,一次循环中A走两步,B走一步,A到头时,B即是中间节点。其实让一个指针遍历两次其时间复杂度是一样的,只不过代码冗余。面试官不关心这个~
快速删除链表中某节点,有指针。用其next节点覆盖该节点内容,然后把后面链表接上。
5TL相关的知识。Stl容器的参数allocate是用来做什么的?这是一个函数对象,用来指定小于运算过程。Map的Key有什么要求?开始我答不能重复,他继续问,答必须重载<运算符,OK。
智能指针是怎么实现的,你来实现一个智能指针。在构造函数里进行指针赋值,析构里delete。其实还有很多的,比如实现get方法,拷贝构造函数、赋值运算符行为。
static_cast,const_cast,dynamic_cast区别,没有问reinterpret_cast。第一个是强制隐式转换,是比较安全的;第二个是去常量性的;第三个是安全向下转型(safe downcasting);最后一个是低级转换。当时没这么清楚。。
你用过哪些C++库?gsl。面试官表示没听过。Boost,貌似他们整天在用。
然后让我出去等,接着二面。面试官有点忙,经常打电话进来。看了我的项目经历,问了很多。然后告诉我去面前端怎么样,我说好啊(注意,这是一个错误)!于是继续面前端一面。 我做过很多web开发,js开发,但对于前端我没有系统的学习。结果很糟糕。我就把这几个问题罗列一下:
你认为一个好的前端开发者应具备哪些素质?
你对HTML5和CSS3了解多少?他会继续问的。
实现一个三栏布局,两端固定宽度,中间自适应。
javascript优化可以怎么做?
怎么处理跨域请求限制。
最后,你有要问我的问题吗?
我问了我应如何学习前端。面试官很严肃,是个值得尊敬的技术男。告诉我要多读最新的前端博客和文章,多了解新技术。然后,基础的书籍要学习,面试中问的基本都可以回答。
最后总结一下感受,首先要知道自己想干什么;简历一定要对口;自我介绍是需要准备的;不到最后一刻不要懈怠。
OK~ 结束了。预祝后来的同行们成功。祝君好运!
转载于:https://www.cnblogs.com/buxizhizhou/p/4602137.html
Android 应用有道词典主要是应用了有道词典网站的搜索,通过链接http://dict.youdao.com/m获取词典。
程序主要是应用一个EditText控件,一个Button按钮,查询出来的词典由WebView控件展示。程序的界面如图:
程序的查询方法主要是将EditText控件中的词加到查询的链接的后面,查询后再显示到WebView中,查询方法代码如下:
/**
*查询事件
*/
public void query(View view){
String strURI=etText.getText().toString();
if (strURI.length() == 0)
{
Toast.makeText(MainActivity.this, "查询内容不能为空!", Toast.LENGTH_LONG)
.show();
}else{
String strURL = "http://dict.youdao.com/m/search?keyfrom=dict.mindex&q="
+ strURI;
wv_content.loadUrl(strURL);
}
}
但是程序这样直接查询是调用的手机中的浏览器进行的查询,为了使程序使用WebView控件,于是添加了下列代码
wv_content=(WebView) findViewById(R.id.wv_content);
wv_content.getSettings().setJavaScriptEnabled(true);
wv_content.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view,String url){
view.loadUrl(url);
return true; }
});
通过添加上述代码,程序即可在WebView控件查询显示。
程序需要联网,因此不要忘记在AndroidManifest.xml中添加网络权限<uses-permission android:name="android.permission.INTERNET"/>。
转自:http://blog.sina.com.cn/s/blog_62b83291010127bf.html
在数据分析和数据挖掘的过程中,我们经常需要知道个体间差异的大小,进而评价个体的相似性和类别。最常见的是数据分析中的相关分析,数据挖掘中的分 类和聚类算法,如K最近邻(KNN)和K均值(K-Means)。当然衡量个体差异的方法有很多,最近查阅了相关的资料,这里整理罗列下。
为了方便下面的解释和举例,先设定我们要比较X个体和Y个体间的差异,它们都包含了N个维的特征,即X=(x1, x2, x3, … xn),Y=(y1, y2, y3, … yn)。下面来看看主要可以用哪些方法来衡量两者的差异,主要分为距离度量和相似度度量。
距离度量 距离度量(Distance)用于衡量个体在空间上存在的距离,距离越远说明个体间的差异越大。
欧几里得距离(Euclidean Distance) 欧氏距离是最常见的距离度量,衡量的是多维空间中各个点之间的绝对距离。公式如下:
因为计算是基于各维度特征的绝对数值,所以欧氏度量需要保证各维度指标在相同的刻度级别,比如对身高(cm)和体重(kg)两个单位不同的指标使用欧式距离可能使结果失效。
明可夫斯基距离(Minkowski Distance) 明氏距离是欧氏距离的推广,是对多个距离度量公式的概括性的表述。公式如下:
这里的p值是一个变量,当p=2的时候就得到了上面的欧氏距离。
曼哈顿距离(Manhattan Distance) 曼哈顿距离来源于城市区块距离,是将多个维度上的距离进行求和后的结果,即当上面的明氏距离中p=1时得到的距离度量公式,如下:
切比雪夫距离(Chebyshev Distance) 切比雪夫距离起源于国际象棋中国王的走法,我们知道国际象棋国王每次只能往周围的8格中走一步,那么如果要从棋盘中A格(x1, y1)走到B格(x2, y2)最少需要走几步?扩展到多维空间,其实切比雪夫距离就是当p趋向于无穷大时的明氏距离:
其实上面的曼哈顿距离、欧氏距离和切比雪夫距离都是明可夫斯基距离在特殊条件下的应用。
马哈拉诺比斯距离(Mahalanobis Distance) 既然欧几里得距离无法忽略指标度量的差异,所以在使用欧氏距离之前需要对底层指标进行数据的标准化,而基于各指标维度进行标准化后再使用欧氏距离就衍生出来另外一个距离度量——马哈拉诺比斯距离(Mahalanobis Distance),简称马氏距离。
相似度度量 相似度度量(Similarity),即计算个体间的相似程度,与距离度量相反,相似度度量的值越小,说明个体间相似度越小,差异越大。
向量空间余弦相似度(Cosine Similarity) 余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。相比距离度量,余弦相似度更加注重两个向量在方向上的差异,而非距离或长度上。公式如下:
皮尔森相关系数(Pearson Correlation Coefficient) 即相关分析中的相关系数r,分别对X和Y基于自身总体标准化后计算空间向量的余弦夹角。公式如下:
Jaccard相似系数(Jaccard Coefficient) Jaccard系数主要用于计算符号度量或布尔值度量的个体间的相似度,因为个体的特征属性都是由符号度量或者布尔值标识,因此无法衡量差异具 体值的大小,只能获得“是否相同”这个结果,所以Jaccard系数只关心个体间共同具有的特征是否一致这个问题。如果比较X与Y的Jaccard相似系 数,只比较xn和yn中相同的个数,公式如下:
调整余弦相似度(Adjusted Cosine Similarity) 虽然余弦相似度对个体间存在的偏见可以进行一定的修正,但是因为只能分辨个体在维之间的差异,没法衡量每个维数值的差异,会导致这样一个情况: 比如用户对内容评分,5分制,X和Y两个用户对两个内容的评分分别为(1,2)和(4,5),使用余弦相似度得出的结果是0.98,两者极为相似,但从评 分上看X似乎不喜欢这2个内容,而Y比较喜欢,余弦相似度对数值的不敏感导致了结果的误差,需要修正这种不合理性,就出现了调整余弦相似度,即所有维度上 的数值都减去一个均值,比如X和Y的评分均值都是3,那么调整后为(-2,-1)和(1,2),再用余弦相似度计算,得到-0.8,相似度为负值并且差异 不小,但显然更加符合现实。
欧氏距离与余弦相似度 欧氏距离是最常见的距离度量,而余弦相似度则是最常见的相似度度量,很多的距离度量和相似度度量都是基于这两者的变形和衍生,所以下面重点比较下两者在衡量个体差异时实现方式和应用环境上的区别。
借助三维坐标系来看下欧氏距离和余弦相似度的区别:
从图上可以看出距离度量衡量的是空间各点间的绝对距离,跟各个点所在的位置坐标(即个体特征维度的数值)直接相关;而余弦相似度衡量的是空间向 量的夹角,更加的是体现在方向上的差异,而不是位置。如果保持A点的位置不变,B点朝原方向远离坐标轴原点,那么这个时候余弦相似度cosθ是保持不变 的,因为夹角不变,而A、B两点的距离显然在发生改变,这就是欧氏距离和余弦相似度的不同之处。
根据欧氏距离和余弦相似度各自的计算方式和衡量特征,分别适用于不同的数据分析模型:欧氏距离能够体现个体数值特征的绝对差异,所以更多的用于 需要从维度的数值大小中体现差异的分析,如使用用户行为指标分析用户价值的相似度或差异;而余弦相似度更多的是从方向上区分差异,而对绝对的数值不敏感, 更多的用于使用用户对内容评分来区分用户兴趣的相似度和差异,同时修正了用户间可能存在的度量标准不统一的问题(因为余弦相似度对绝对数值不敏感)。
上面都是对距离度量和相似度度量的一些整理和汇总,在现实的使用中选择合适的距离度量或相似度度量可以完成很多的数据分析和数据挖掘的建模,后续会有相关的介绍。 附件为python部分相似度算法: #!/usr/bin/python #coding=utf-8 critics = { 'Lisa':{ 'Lady in the water':2.
文章来源:http://www.360doc.com/myfollow.aspx
先来看一下X-Forwarded-For的定义:
X-Forwarded-For:简称XFF头,它代表客户端,也就是HTTP的请求端真实的IP,只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项。它不是RFC中定义的标准请求头信息,在squid缓存代理服务器开发文档中可以找到该项的详细介绍。
标准格式如下:
X-Forwarded-For: client1, proxy1, proxy2
从标准格式可以看出,X-Forwarded-For头信息可以有多个,中间用逗号分隔,第一项为真实的客户端ip,剩下的就是曾经经过的代理或负载均衡的ip地址,经过几个就会出现几个。
按照上图的Web架构图,可以很容易的看出,当用户请求经过CDN后到达Nginx负载均衡服务器时,其X-Forwarded-For头信息应该为 客户端IP,CDN的IP 但实际情况并非如此,一般情况下CDN服务商为了自身安全考虑会将这个信息做些改动,只保留客户端IP。我们可以通过php程序获得X-Forwarded-For信息或者通过Nginx的add header方法来设置返回头来查看。
下面来分析请求头到达Nginx负载均衡服务器的情况;在默认情况下,Nginx并不会对X-Forwarded-For头做任何的处理,除非用户使用proxy_set_header 参数设置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
$proxy_add_x_forwarded_for变量包含客户端请求头中的"X-Forwarded-For",与$remote_addr用逗号分开,如果没有"X-Forwarded-For" 请求头,则$proxy_add_x_forwarded_for等于$remote_addr。
$remote_addr变量的值是客户端的IP
当Nginx设置X-Forwarded-For等于$proxy_add_x_forwarded_for后会有两种情况发生
1、如果从CDN过来的请求没有设置X-Forwarded-For头(通常这种事情不会发生),而到了我们这里Nginx设置将其设置为$proxy_add_x_forwarded_for的话,X-Forwarded-For的信息应该为CDN的IP,因为相对于Nginx负载均衡来说客户端即为CDN,这样的话,后端的web程序时死活也获得不了真实用户的IP的。
2、CDN设置了X-Forwarded-For,我们这里又设置了一次,且值为$proxy_add_x_forwarded_for的话,那么X-Forwarded-For的内容变成 ”客户端IP,Nginx负载均衡服务器IP“如果是这种情况的话,那后端的程序通过X-Forwarded-For获得客户端IP,则取逗号分隔的第一项即可。
如上两点所说,如果我们知道了CDN设置了X-Forwarded-For信息,且只有客户端真实的IP的话,那么我们的Nginx负载均衡服务器可以不必理会该头,让它默认即可。
其实Nginx中还有一个$http_x_forwarded_for变量,这个变量中保存的内容就是请求中的X-Forwarded-For信息。如果后端获得X-Forwarded-For信息的程序兼容性不好的话(没有考虑到X-Forwarded-For含有多个IP的情况),最好就不要将X-Forwarded-For设置为 $proxy_add_x_forwarded_for。应该设置为$http_x_forwarded_for或者干脆不设置!
另在不同的代理情况下,其中x-forward-for的情况 对于这三个值:REMOTE_ADDR、HTTP_VIA、HTTP_X_FORWARDED_FOR 来说,可以分以下五种情况:
一、没有使用代理服务器的情况:
REMOTE_ADDR = 您的 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示
二、使用透明代理服务器的情况:Transparent Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 您的真实 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。
三、使用普通匿名代理服务器的情况:Anonymous Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
关于LOG4J 按照级别输出日志,并按照级别输出到不同文件中的说法有很多, 网上贴的最多的log4j.properties的设置是这样的
[java] view plain copy log4j.rootLogger=info,stdout,info,debug,error log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n log4j.logger.info=info log4j.appender.info=org.apache.log4j.DailyRollingFileAppender log4j.appender.info.layout=org.apache.log4j.PatternLayout log4j.appender.info.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n log4j.appender.info.datePattern='.'yyyy-MM-dd log4j.appender.info.Threshold = INFO log4j.appender.info.append=true log4j.appender.info.File=${webApp.root}/WEB-INF/logs/info.log log4j.logger.debug=debug log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender log4j.appender.debug.layout=org.apache.log4j.PatternLayout log4j.appender.debug.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n log4j.appender.debug.datePattern='.'yyyy-MM-dd log4j.appender.debug.Threshold = DEBUG log4j.appender.debug.append=true log4j.appender.debug.File=${webApp.root}/WEB-INF/logs/debug.log log4j.logger.error=error log4j.appender.error=org.apache.log4j.DailyRollingFileAppender log4j.appender.error.layout=org.apache.log4j.PatternLayout log4j.appender.error.layout.ConversionPattern=[%-5p] [%d{HH:mm:ss}] %c - %m%n log4j.appender.error.datePattern='.'yyyy-MM-dd log4j.appender.error.Threshold = ERROR log4j.appender.error.append=true log4j.appender.error.File=${webApp.root}/WEB-INF/logs/error.log 而实际上这部分代码解决不了按照LOG4J的级别文件进行文件输出。
配置中关键的配置说明是这一句:
[java] view plain copy log4j.appender.debug.Threshold = INFO 而它的作用是输出INFO级别以上的内容到${webApp.root}/WEB-INF/logs/info.log中,所以info.log文件中包含了ERROR级别的文件。
正确的解法是:
定义自己的Appender类,继承DailyRollingFileAppender,改写针对Threshold 的设置说明。
在處理音訊相關的問題時,我通常會找個方法來讀寫codec中register的值。幸好linux上也有這樣的工具 – i2c tools。先到lm-sensors下載soure code,然後cross compile成arm的執行檔,就可以放到板子來試試看了。 i2c-tools中含有四個執行檔 i2cdetect – 用來列舉I2C bus和上面所有的裝置 i2cdump – 顯示裝置上所有register的值 i2cget – 讀取裝置上某個register的值 i2cset – 寫入裝置上某個register 以下是我用beagleboard得到的結果 root@android:/temp # ./i2cdetect -l i2c-1 i2c OMAP I2C adapter I2C adapter i2c-2 i2c OMAP I2C adapter I2C adapter i2c-3 i2c OMAP I2C adapter I2C adapter 原來beagleboad上有三組I2C bus。 i2cdetect也可以用來看bus上有那些裝置 root@android:/temp # ./i2cdetect -y -r 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- UU UU UU UU -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- 這表示bus上有四備裝置,位址分別是0×48, 0×49, 0x4a, 0x4b。 我們要找的是codec,beagleboard上的codec是TI的TPS65950,從technical reference manual可以得知codec在I2C上的位址是0×49。 然後用i2cdump來看codec中所有register的值 [ root@android:/temp # .
Wireshark 包过滤规则 Wireshark CaptureFilters 英文原文地址:http://wiki.wireshark.org/CaptureFilte 翻译整理:dalerkd
其实它与任何libpcap/WinPcap库的使用格式相同
//你应当从Caption->Options 输入表达式.
0x1仅捕获指定IP地址的流量
host 172.18.5.4 0x2从一个IP地址范围捕获流量
net 192.168.0.0/24 或者
net 192.168.0.0 mask 255.255.255.0 0x3捕获来自某地址范围的流量
src net 192.168.0.0/24 或者
src net 192.168.0.0 mask 255.255.255.0 0x4捕获前往某地址范围的流量
dst net 192.168.0.0/24 或者
src net 192.168.0.0 mask 255.255.255.0 0x5仅捕获某端口的流量
port 53 //DNS协议 port 80 //TCP UDP协议 0x6捕获目标host流量包中除去某些端口的内容
host www.example.com and not (port 80 or port 25) //不要HTTP和SMTP包 host www.example.com and not port 80 and not port 25 0x7捕获除了ARP和DNS外的流量
我尝试了以下三种方式:
一、
like '%#{mkName}%' 这种方式,myBatis直接报错,说参数的数量不匹配。
二、
like '%'||#{mkName}||'%' 这种方式不报错,但是查询出来的结果是不是对的。比如,对于 mkName这个字段,数据库中只有 “小学” 这个值,但是当mkName的值为“中”时,它也会将“小学”相关的记录全部查询出来。
所以,这种方式也NG了。
三、
like CONCAT('%', #{mkName}, '%') 这种方式是能够正常工作的,而且取得的是正常的结果集。