首页 文章 精选 留言 我的

精选列表

搜索[程序开发],共10000篇文章
优秀的个人博客,低调大师

程序员必须知道的数字电子技术——(二,八,十,十六进制,原码,补码,反码及常见编码方式)

1.进制介绍: 十进制: 在十进制数中,每一位有0-9十个数码,所以计数的基数是10。超过9的数必须用多位数表示,其中低位和相邻高位之间的关系是:逢十进一,故称为十进制。例如: 所以一个任意多位的十进制D均可展开为:若以N取代式中的10,即可得到多位任意进制(N进制)数展开式的普遍形式:式中i的取值与十进制展开式的规定相同。N称为计数的基数,k为第i位的系数,N称为第i位的权。 二进制: 目前在数字电路中应用最广泛的是二进制。在二进制数中,每一位仅有0和1两个可能的数码,所以计数基数为2。低位和相邻高位间的进位关系是“逢二进一”, 故称为二进制。根据N进制数展开的普遍形式可得任何一个二进制数均可展开为:并可利用上式计算出它所表达的十进制数的大小:上式中分别使用下脚注2和10表示括号里的数是二进制数和十进制数。有时也用B( Bima-ry)和D( Decimal)代替2和10这两个脚注。 八进制 在某些场合有时也使用八进制。八进制数的每一位有0~7 八个不同的数码,计数的基数为8。低位和相邻的高位之间的进位关系是“逢八进一”。任意一个八进制数可以展开为并可利用上式计算出相应的十进制数:有时也用O(Oetal)代替下脚注8,表示八进制数。 十六进制 十六进制 数的每一位有十六个不同的数码,分别用0~9.A(10)、B(11) .C(12)、D(13)、E(14)、P(15)表示。因此,任意一个十六进制数均可展开为 并可以利用上式计算出相应的十进制数 式中的下脚注16表示括号里的数是十六进制数,有时也用H( Hexadecimal)代替这个脚注,0X表示前缀。 小节:不同进制数的对照表:小拓展:(1)一位八进制可以表示三位二进制数:因为三位二进制最小是000b,最大是111b,其范围恰好在0-7,构成了八进制一位。(2)一位十六进制可以表示为四位二进制十六进制数的进率是16,二进制数的进率是2,且16=2^4,说明二进制数连续进位4次,等效于16进制数进1位。这么说可能不好理解,那么举个例子吧,比如15+1=16,用二进制表示就是1111+1=10000,用十六进制表示就是F+1=10。这也就说明了一位十六进制数对应四位二进制数了 2.不同进制间的转换 (1)八进制,二进制,十六进制转换为十进制 都可根据上述十进制介绍中的 多位任意进制数展开式的普遍形式 进行转换,即按位权展开式。 (2)十进制转换为二进制,八进制,十六进制 十进制整数转换R进制(R可以是任何整数,比如2,8,16)整数,方法就是除R取余。 1.十进制转换为二进制: 十进制整数转换为二进制:(除二取余,从下往上倒序排序)十进制小数转换为二进制:(乘二取整,从上向下顺序排序) 2.十进制转换为十六进制 十进制数为整数时,除16取余十进制数为小数时,乘16取整 3.十进制转换为八进制 十进制为整数时,除八取余十进制为小数时,乘八取整 (3)二进制转换为十六进制 只要从低位到高位将整数部分每4位二进制数分为一组并代之以等值的十六进制数,同时从高位到低位将小数部分的每4位数分为一组并代之以等值的十六进制数,即可得到对应的十六进制数。若二进制数整数部分最高- -组不足4位时,用0补足4位;小数部分最低一组不足 4位时,也需用0补足4位。 (2)二进制转换为八进制 在将二进制数转换为八进制数时,只要将二进制数的整数部分从低位到高位每3位分为一组并代之以等值的八进制数,同时将小数部分从高位到低位每3位分为一组并代之以等值的八进制数就可以了。二进制数最高一组不足3位或小数部分最低一组不足3位时,仍需以0补足三位。 (3)十六进制转换为二进制 转换时只需将十六进制数的每一位用等值的4位二进制数代替就行了。 (2)八进制转换为二进制 若将八进制数转换为二进制数,则只要将八进制数的每一位代之以等值的3位二进制。 (3)八进制与十六进制之间的转换 第一种:他们之间的转换可以先转成二进制然后再相互转换。第二种:他们之间的转换可以先转成十进制然后再相互转换 建议:先将八进制转换为对应的二进制,再将二进制转换为十六进制。 3.二进制算数运算 如果我们再能设法将减法操作转化为某种形式的加法操作,那么加,减,乘.除运算就全部可以用“移位”和“相加”两种操作实现了。利用上述特点能使运算电路的结构大为简化。这也是 (1)反码,补码和补码运算 我们已经知道,在数字电路中是用逻辑电路输出的高、低电平表示二进制数的1和0的。那么数的正,负又如何表示呢?通常采用的方法是在二进制数的前面增加一位符号位。符号位为0表示这个数是正数,符号位为1表示这个数是负数。这种形式的数称为原码。 因为计算机只会执行加法,不会进行减法运算,所以我们考虑怎样把二进制的减法运算变为加法运算,这里就出现了补码。 可以发现:在舍弃进位的条件下,减去某个数可以用加上它的补码来代替!!! 然后我们考虑,如果直接得到原码的补码的话非常麻烦,所以这里就出现了反码这个中介。 反码:正数(即符号位为0)的反码与原码相同,负数(即符号位为1)的反码为(注意:符号位不变)原码的数值位逐位取反(即1变为0,0变为1)。 补码:正数的补码与原码相同,负数的补码为原码的数值位(注意:符号位不变)逐位取反再加1。 即直接原码的反码加1即可!!! 注意:求原码对应的补码是逐位取反再加1;那么求补码对应的原码也是一样,逐位取反再加1. 下面再来讨论两个用补码表示的二进制数相加时,和的符号位如何得到。为此,我们在例下面再来讨论两个用补码表示的二进制数相加时,和的符号位如何得到。 为此,我们在例1.4.2中列举出了两数相加时的四种情况。 (2)几种常用的编码 1.十进制码 为了用二进制代码表示十进制数的0~9这十个状态,二进制代码至少应当有4位。4位二进制代码一共有十六个(000-1111),取其中哪十个以及如何与0-9相对应,有许多种方案。表1.5.1中列出了常见的几种十进制代码,它们的编码规则各不相同。 (1)8421码又称BCD( Binary Coded Decimal)码,是十进制代码中最常用的一种。在这种编码方式中,每一位二值代码的1都代表一个固定数值,将每一位的 1代表的十进制数加起来,得到的结果就是它所代表的十进制数码。由于代码中从左到右每一位的1分别表示8,4,2,1,所以将这种代码称为8421码。每一位的1代表的十进制数称为这一位的权。8421码中每一位的权是固定不变的,它属于恒权代码。 余3码的编码规则与8421码不同,如果把每–个余3码看作4位二进制数.则它的数值要# 1.进制介绍: 十进制: 在十进制数中,每一位有0-9十个数码,所以计数的基数是10。超过9的数必须用多位数表示,其中低位和相邻高位之间的关系是:逢十进一,故称为十进制。例如: 所以一个任意多位的十进制D均可展开为:若以N取代式中的10,即可得到多位任意进制(N进制)数展开式的普遍形式:式中i的取值与十进制展开式的规定相同。N称为计数的基数,k为第i位的系数,N称为第i位的权。 二进制: 目前在数字电路中应用最广泛的是二进制。在二进制数中,每一位仅有0和1两个可能的数码,所以计数基数为2。低位和相邻高位间的进位关系是“逢二进一”, 故称为二进制。根据N进制数展开的普遍形式可得任何一个二进制数均可展开为:并可利用上式计算出它所表达的十进制数的大小:上式中分别使用下脚注2和10表示括号里的数是二进制数和十进制数。有时也用B( Bima-ry)和D( Decimal)代替2和10这两个脚注。 八进制 在某些场合有时也使用八进制。八进制数的每一位有0~7 八个不同的数码,计数的基数为8。低位和相邻的高位之间的进位关系是“逢八进一”。任意一个八进制数可以展开为并可利用上式计算出相应的十进制数:有时也用O(Oetal)代替下脚注8,表示八进制数。 十六进制 十六进制 数的每一位有十六个不同的数码,分别用0~9.A(10)、B(11) .C(12)、D(13)、E(14)、P(15)表示。因此,任意一个十六进制数均可展开为 并可以利用上式计算出相应的十进制数 式中的下脚注16表示括号里的数是十六进制数,有时也用H( Hexadecimal)代替这个脚注,0X表示前缀。 小节:不同进制数的对照表:小拓展:(1)一位八进制可以表示三位二进制数:因为三位二进制最小是000b,最大是111b,其范围恰好在0-7,构成了八进制一位。(2)一位十六进制可以表示为四位二进制十六进制数的进率是16,二进制数的进率是2,且16=2^4,说明二进制数连续进位4次,等效于16进制数进1位。这么说可能不好理解,那么举个例子吧,比如15+1=16,用二进制表示就是1111+1=10000,用十六进制表示就是F+1=10。这也就说明了一位十六进制数对应四位二进制数了 2.不同进制间的转换 (1)八进制,二进制,十六进制转换为十进制 都可根据上述十进制介绍中的 多位任意进制数展开式的普遍形式 进行转换,即按位权展开式。 (2)十进制转换为二进制,八进制,十六进制 十进制整数转换R进制(R可以是任何整数,比如2,8,16)整数,方法就是除R取余。 1.十进制转换为二进制: 十进制整数转换为二进制:(除二取余,从下往上倒序排序)十进制小数转换为二进制:(乘二取整,从上向下顺序排序) 2.十进制转换为十六进制 十进制数为整数时,除16取余十进制数为小数时,乘16取整 3.十进制转换为八进制 十进制为整数时,除八取余十进制为小数时,乘八取整 (3)二进制转换为十六进制 只要从低位到高位将整数部分每4位二进制数分为一组并代之以等值的十六进制数,同时从高位到低位将小数部分的每4位数分为一组并代之以等值的十六进制数,即可得到对应的十六进制数。若二进制数整数部分最高- -组不足4位时,用0补足4位;小数部分最低一组不足 4位时,也需用0补足4位。 (2)二进制转换为八进制 在将二进制数转换为八进制数时,只要将二进制数的整数部分从低位到高位每3位分为一组并代之以等值的八进制数,同时将小数部分从高位到低位每3位分为一组并代之以等值的八进制数就可以了。二进制数最高一组不足3位或小数部分最低一组不足3位时,仍需以0补足三位。 (3)十六进制转换为二进制 转换时只需将十六进制数的每一位用等值的4位二进制数代替就行了。 (2)八进制转换为二进制 若将八进制数转换为二进制数,则只要将八进制数的每一位代之以等值的3位二进制。 (3)八进制与十六进制之间的转换 第一种:他们之间的转换可以先转成二进制然后再相互转换。第二种:他们之间的转换可以先转成十进制然后再相互转换 建议:先将八进制转换为对应的二进制,再将二进制转换为十六进制。 3.二进制算数运算 如果我们再能设法将减法操作转化为某种形式的加法操作,那么加,减,乘.除运算就全部可以用“移位”和“相加”两种操作实现了。利用上述特点能使运算电路的结构大为简化。这也是 (1)反码,补码和补码运算 我们已经知道,在数字电路中是用逻辑电路输出的高、低电平表示二进制数的1和0的。那么数的正,负又如何表示呢?通常采用的方法是在二进制数的前面增加一位符号位。符号位为0表示这个数是正数,符号位为1表示这个数是负数。这种形式的数称为原码。 因为计算机只会执行加法,不会进行减法运算,所以我们考虑怎样把二进制的减法运算变为加法运算,这里就出现了补码。 可以发现:在舍弃进位的条件下,减去某个数可以用加上它的补码来代替!!! 然后我们考虑,如果直接得到原码的补码的话非常麻烦,所以这里就出现了反码这个中介。 反码:正数(即符号位为0)的反码与原码相同,负数(即符号位为1)的反码为(注意:符号位不变)原码的数值位逐位取反(即1变为0,0变为1)。 补码:正数的补码与原码相同,负数的补码为原码的数值位(注意:符号位不变)逐位取反再加1。 即直接原码的反码加1即可!!! 注意:求原码对应的补码是逐位取反再加1;那么求补码对应的原码也是一样,逐位取反再加1. 下面再来讨论两个用补码表示的二进制数相加时,和的符号位如何得到。为此,我们在例下面再来讨论两个用补码表示的二进制数相加时,和的符号位如何得到。 为此,我们在例1.4.2中列举出了两数相加时的四种情况。 (2)几种常用的编码 1.十进制码 为了用二进制代码表示十进制数的0~9这十个状态,二进制代码至少应当有4位。4位二进制代码一共有十六个(000-1111),取其中哪十个以及如何与0-9相对应,有许多种方案。表1.5.1中列出了常见的几种十进制代码,它们的编码规则各不相同。 (1)8421码又称BCD( Binary Coded Decimal)码,是十进制代码中最常用的一种。在这种编码方式中,每一位二值代码的1都代表一个固定数值,将每一位的 1代表的十进制数加起来,得到的结果就是它所代表的十进制数码。由于代码中从左到右每一位的1分别表示8,4,2,1,所以将这种代码称为8421码。每一位的1代表的十进制数称为这一位的权。8421码中每一位的权是固定不变的,它属于恒权代码。 余3码的编码规则与8421码不同,如果把每–个余3码看作4位二进制数.则它的数值要# 1.进制介绍: 十进制: 在十进制数中,每一位有0-9十个数码,所以计数的基数是10。超过9的数必须用多位数表示,其中低位和相邻高位之间的关系是:逢十进一,故称为十进制。例如: 所以一个任意多位的十进制D均可展开为:若以N取代式中的10,即可得到多位任意进制(N进制)数展开式的普遍形式:式中i的取值与十进制展开式的规定相同。N称为计数的基数,k为第i位的系数,N称为第i位的权。 二进制: 目前在数字电路中应用最广泛的是二进制。在二进制数中,每一位仅有0和1两个可能的数码,所以计数基数为2。低位和相邻高位间的进位关系是“逢二进一”, 故称为二进制。根据N进制数展开的普遍形式可得任何一个二进制数均可展开为:并可利用上式计算出它所表达的十进制数的大小:上式中分别使用下脚注2和10表示括号里的数是二进制数和十进制数。有时也用B( Bima-ry)和D( Decimal)代替2和10这两个脚注。 八进制 在某些场合有时也使用八进制。八进制数的每一位有0~7 八个不同的数码,计数的基数为8。低位和相邻的高位之间的进位关系是“逢八进一”。任意一个八进制数可以展开为并可利用上式计算出相应的十进制数:有时也用O(Oetal)代替下脚注8,表示八进制数。 十六进制 十六进制 数的每一位有十六个不同的数码,分别用0~9.A(10)、B(11) .C(12)、D(13)、E(14)、P(15)表示。因此,任意一个十六进制数均可展开为 并可以利用上式计算出相应的十进制数 式中的下脚注16表示括号里的数是十六进制数,有时也用H( Hexadecimal)代替这个脚注,0X表示前缀。 小节:不同进制数的对照表:小拓展:(1)一位八进制可以表示三位二进制数:因为三位二进制最小是000b,最大是111b,其范围恰好在0-7,构成了八进制一位。(2)一位十六进制可以表示为四位二进制十六进制数的进率是16,二进制数的进率是2,且16=2^4,说明二进制数连续进位4次,等效于16进制数进1位。这么说可能不好理解,那么举个例子吧,比如15+1=16,用二进制表示就是1111+1=10000,用十六进制表示就是F+1=10。这也就说明了一位十六进制数对应四位二进制数了 2.不同进制间的转换 (1)八进制,二进制,十六进制转换为十进制 都可根据上述十进制介绍中的 多位任意进制数展开式的普遍形式 进行转换,即按位权展开式。 (2)十进制转换为二进制,八进制,十六进制 十进制整数转换R进制(R可以是任何整数,比如2,8,16)整数,方法就是除R取余。 1.十进制转换为二进制: 十进制整数转换为二进制:(除二取余,从下往上倒序排序)十进制小数转换为二进制:(乘二取整,从上向下顺序排序) 2.十进制转换为十六进制 十进制数为整数时,除16取余十进制数为小数时,乘16取整 3.十进制转换为八进制 十进制为整数时,除八取余十进制为小数时,乘八取整 (3)二进制转换为十六进制 只要从低位到高位将整数部分每4位二进制数分为一组并代之以等值的十六进制数,同时从高位到低位将小数部分的每4位数分为一组并代之以等值的十六进制数,即可得到对应的十六进制数。若二进制数整数部分最高- -组不足4位时,用0补足4位;小数部分最低一组不足 4位时,也需用0补足4位。 (2)二进制转换为八进制 在将二进制数转换为八进制数时,只要将二进制数的整数部分从低位到高位每3位分为一组并代之以等值的八进制数,同时将小数部分从高位到低位每3位分为一组并代之以等值的八进制数就可以了。二进制数最高一组不足3位或小数部分最低一组不足3位时,仍需以0补足三位。 (3)十六进制转换为二进制 转换时只需将十六进制数的每一位用等值的4位二进制数代替就行了。 (2)八进制转换为二进制 若将八进制数转换为二进制数,则只要将八进制数的每一位代之以等值的3位二进制。 (3)八进制与十六进制之间的转换 第一种:他们之间的转换可以先转成二进制然后再相互转换。第二种:他们之间的转换可以先转成十进制然后再相互转换 建议:先将八进制转换为对应的二进制,再将二进制转换为十六进制。 3.二进制算数运算 如果我们再能设法将减法操作转化为某种形式的加法操作,那么加,减,乘.除运算就全部可以用“移位”和“相加”两种操作实现了。利用上述特点能使运算电路的结构大为简化。这也是 (1)反码,补码和补码运算 我们已经知道,在数字电路中是用逻辑电路输出的高、低电平表示二进制数的1和0的。那么数的正,负又如何表示呢?通常采用的方法是在二进制数的前面增加一位符号位。符号位为0表示这个数是正数,符号位为1表示这个数是负数。这种形式的数称为原码。 因为计算机只会执行加法,不会进行减法运算,所以我们考虑怎样把二进制的减法运算变为加法运算,这里就出现了补码。 可以发现:在舍弃进位的条件下,减去某个数可以用加上它的补码来代替!!! 然后我们考虑,如果直接得到原码的补码的话非常麻烦,所以这里就出现了反码这个中介。 反码:正数(即符号位为0)的反码与原码相同,负数(即符号位为1)的反码为(注意:符号位不变)原码的数值位逐位取反(即1变为0,0变为1)。 补码:正数的补码与原码相同,负数的补码为原码的数值位(注意:符号位不变)逐位取反再加1。 即直接原码的反码加1即可!!! 注意:求原码对应的补码是逐位取反再加1;那么求补码对应的原码也是一样,逐位取反再加1. 下面再来讨论两个用补码表示的二进制数相加时,和的符号位如何得到。为此,我们在例下面再来讨论两个用补码表示的二进制数相加时,和的符号位如何得到。 为此,我们在例1.4.2中列举出了两数相加时的四种情况。 (2)几种常用的编码 1.十进制码 为了用二进制代码表示十进制数的0~9这十个状态,二进制代码至少应当有4位。4位二进制代码一共有十六个(000-1111),取其中哪十个以及如何与0-9相对应,有许多种方案。表1.5.1中列出了常见的几种十进制代码,它们的编码规则各不相同。 (1)8421码又称BCD( Binary Coded Decimal)码,是十进制代码中最常用的一种。在这种编码方式中,每一位二值代码的1都代表一个固定数值,将每一位的 1代表的十进制数加起来,得到的结果就是它所代表的十进制数码。由于代码中从左到右每一位的1分别表示8,4,2,1,所以将这种代码称为8421码。每一位的1代表的十进制数称为这一位的权。8421码中每一位的权是固定不变的,它属于恒权代码。 (2)余3码的编码规则与8421码不同,如果把每–个余3码看作4位二进制数.则它的数值要比它所表示的十进制数码多3,故而将这种代码称为余3码。 如果将两个余3码相加,所得的和将比十进制数和所对应的二进制数多6。因此,在用余3码做十进制加法运算时.若两数之和为10.正好等于二进制数的16.于是便从高位自动产生进位信号。此外,从表1.5.1中还可以看出,0和9、1和8.2和7,3和6.4和5的余3码互为反码,这对于求取对10的补码是很方便的。余3码不是恒权代码。如果试图将每个代码视为二进制数,并使它等效的十进制数与所表示的代码相等,那么代码中每一位的1所代表的十进制数在各个代码中不能是固定的。 (3)2421码是一种恒权代码,它的0和9.1和8.2和7,3和6.4和5也互为反码,这个特点和余3码相仿。 (4)5211码是另一种恒权代码。待学了第六章中计数器的分频作用后可以发现,如果按8421码接成十进制计数器,则连续输入计数脉冲时,4个触发器输出脉冲对于计数脉冲的分频比从低位到高位依次为5:2:1:1。可见,5211 码每一位的权正好与8421码十进制计数器4个触发器输出脉冲的分频比相对应。这种对应关系在构成某些数字系统时很有用。 (5)余3循环码是- -种变权码,每一位的1在不同代码中并不化表固定的数值。它的主要特点是相邻的两个代码之间仅有一位的状态不同, 2.格雷码 格雷码(GrayCode)又称循环码。从表1.5.2的4位格雷码编码表中可以看出格雷码的构成方法,这就是每一位的状态变化都按一定的 顺序循环。如果从0000开始,最右边一位的状态按0110顺序循环变化,右边第二位的状态按01011100 顺序循环变化,右边第三位按00011111100000顺序循环变化。可见,自右向左,每一位状态循环中连续的0,1数目增加一倍。由于4位格雷码只有16 个,所以最左边一位的状态只有半个循环,即0000001111111。按照上述原则,我们就很容易得到更多位数的格雷码。 与普通的二进制代码相比,格雷码的最大优点就在于当它按照表1.5.2的编码顺序依次变化时,相邻两个代码之间只有一位发生变化。这样在代码转换的过程中就不会产生过渡“噪声”。而在普通二进制代码的转换过程中,则有时会产生过渡噪声。例如,第四行的二进制代码0011转换为第五行的0100过程中,如果最右边一位的变化比其他两位的变化慢,就会在一个极短的瞬间出现0101状态,这个状态将成为转换过程中出现的噪声。而在第四行的格雷码0010向第五行的0110转换过程中则不会出现过渡噪声。这种过渡噪声在有些情况下甚至会影响电路的正常工作,这时就必须采取揩施加以避免。在第4.9节中我们还将进一步讨论这个问题:十进制代码中的余3循环码就是取4位格雷码中的十个代码组成的,它仍然具有格雷码的优点,即两个相邻代码之间仅有一位不同。

优秀的个人博客,低调大师

每日一面 - Redis程序设计中,上百万的新闻,如何实时展示最热点的top10条呢

假设可以使用 MySQL,redis,本地缓存以及MQ。 用户量级千万,新闻数据百万,用户数比新闻数还多。用户的操作包括: 关注某个新闻 获取某个新闻的关注数量 获取 top10 热点新闻 查询自己关注的新闻。 可以推测,获取 top10 热点新闻请求会远大于关注某个新闻的请求。这些请求都不能直接压入数据库,数据库受不了。 首先想到的是 Redis 中的 Zset,所有的新闻id作为key放入同一个zset中,用户关注某个新闻,使用 zincrby 给这个新闻分数 +1。读取 top 10的时候,用zrevrange. 并且,在实际业务上(例如微博热点话题,知乎热点话题,都是每过一段时间才更新的),top10 热点新闻并不是实时更新的,可以接受一点延迟,可以通过客户端实例的本地缓存,将读取到的 top 10 存在本地缓存一段时间,过了这段时间自动失效。 但是这样也会很快遇到性能瓶颈: 1.zset 在很大时可能不满足我们对于性能的要求: Redis 的 Zset 在数量够大的时候底层基于 skiplist: skiplist 实现简单,插入、删除、查找的复杂度均为O(logN)。zincrby 实际上是一个查找+删除+插入(当然由于score只加了1,所以删除插入只修改相邻节点,这个有优化) 我们的场景是首先插入的新闻分数都是0,之后增长这个分数,在新闻很多,并且并不能确定某些新闻是热点的时候,zincrby 导致的节点变动很频繁。这个通过业务设计可以优化,例如新闻分级,不同级别的新闻初始分数不同 2.放入同一个 zset,对于单实例 redis 性能瓶颈时,扩展不友好。 用户千万量级,更新很频繁,如果都更新同一个 zset,很快会遇到性能瓶颈。读取还好说,可以通过本地缓存,因为展示最热点的top10的实时性要求并没有那么高。这时考虑 redis 集群,redis分片,但是如果放在同一个 zset,无法分摊压力。 那么我们可以换一种思路:redis 中,每个新闻id作为key,关注数作为value,存储简单的键值对。用户关注了某个新闻: 同步事务更新数据库中的用户关注新闻表,这个每个用户会均摊行锁压力 缓存新闻id key + 1(注意catch住缓存不可用的异常) 写入 MQ,之后返回 MQ 消费更新数据库这个新闻的关注数量,这样不会有性能瓶颈,同时针对新闻id做queue以及线程分区(就是同一个新闻总是对应特定的queue以及线程,尽量每一个行锁一个线程更新,避免数据库 lock wait timeout) 怎样获取 top 10:定时任务扫描数据库,按照新闻关注数量排序获取top10,直接放入缓存。用户请求都是读取这个缓存。虽然实时性差,但是能满足需求。 读取某个新闻的关注数量:这个就读缓存,缓存不可用,读取数据库。 获取某个用户关注的新闻列表:这个读取数据库,如果感觉也有性能瓶颈,对于每个用户id添加缓存保存关注的新闻列表即可。这个很简单

优秀的个人博客,低调大师

C语言奇淫技巧,字符串的三种表示方法,不会用不是合格的程序员

1.在C语言中,是将字符串作为字符数组来处理的,字符串是逐个存放到数组元素中的 例如用一个一维的字符数组存放字符串"I am a boy.",如下代码: char c[12] = {'I','a','m','a','b','o','y','.'}; 这个字符串的实际长度是11,数组长度是12,实际工作中,人们关心的往往是字符串的有效长度而不是字符串的数组长度,例如要打印字符串,这是就要知道字符串的实际长度。平时常使用下面三种方式来测定字符串的实际长度: (1)在串值后面加一个不计入长度的结束标记字符,比如''来表示串值的终结 初始化一个字符串的方法如下,在最后添加'' char str[] = {'I','a','m','h','a','p','p','y',''}; 也可以直接使用字符串常量初始化字符数组(系统自动加上''),这种方法符合人们的习惯。 char str[] = "I am happy"; 或者 char str[] = {"I am happy"}; 注意:不能使用下面的赋值方式: char str[20]; str = "I am happy"; 但可以用字符指针指向这个字符串: char *str; str = "I love China"; (2)将实际串长度值保存在数组0的下标下 #define MAXSIZE 20 //数组的长度 typdef char String[MAXSIZE+1]; 初始化字符串的方法: String t; StrAssign(t,"I am happy"); int StrAssign(String T,char *chars) { T[0] = strlen(chars); //下标为0存放数组长度 for(i=1;i<=strlen(chars);i++) //下标位置从1开始存放数据 { T[i] = *(chars+i-1); } return 1; } (3)使用结构体类型(自定义类型) #define MAXSIZE 20 typedef struct{ char ch[MAXSIZE]; int len; }String; 其中:MAXSIZE表示串的最大长度,ch是存储字符串的一维数组,len是字符串的长度 初始化函数示例: String t; StrAssign(&t,"I am happy"); int StrAssign(String *t,char *chars) { int i; if(strlen(chars)>MAXSIZE+1) //字符串的长度大于数组的长度,操作失败,返回0 return 0; for(i=0;i<strlen(chars);i++) { t->ch[i] = *(chars+i); } t->len = strlen(chars); //数组的长度 return 1; //返回1,操作成功 } 说明:这里的StrAssign函数的参数t使用的是指针,是因为结构体变量做做形参,用法和普通变量一样属于值传递方式,在子函数中要给t赋值,所以输入的是t的指针。与之对比的是(2)子函数中T是数组,传入的是数组的首地址(改变形参也就改变了实参)。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册