分类 系统 下的文章

有趣的浮点数

  • 浮点数编码

    从高到低分别是:符号位、指数位、有效数位
    float:4字节,符号1位、指数8位、有效数23位
    double:8字节,符号1位、指数11位、有效数52位
  • 二进制表示

    以4字节的float为例,整数部分采用除2取余法,小数部分采用乘2取整法,然后严格按照以下步骤编码:

    1. 正数或0符号位0,负数符号位1
    2. 移动小数点到第一个有效数字的右边,假定移动N位,左移N为正,右移N为负
    3. 若N为正,则指数位的最高位为1,剩余7位则用N-1的二进制来填充
    4. 若N为负或0,则指数位的最高位为0,剩余7位则用N的二进制取反来填充
    5. N的取之范围[-127, 127],当N为128时,则为无穷数
    6. 小数点右边的其余数字,依次填充有效数位即可,多余数字截断
    7. 为了表示更小的小数,当右移位数大于等于127位时,只移127位,此时需要借用有效数位的最高位来区分小数点前是0还是1,因此此时的有效数位少一位
  • 取值范围

    从以上分析可得出float的取值范围:最大数为1.999...pow(2, 127),最小数为pow(2, -127-22)
    double的取值范围:最大数为1.999...
    pow(2, 1023),最小数为pow(2, -1023-51)

  • 精度

    以整数为例,对于float来说,能精确表示的最大整数为pow(2, 24)
    对于不在精度范围内的数,编译器和cpu采用“五舍六入”法

  • 游戏采用浮点数的误区

    游戏内经常会判断两个float是否相等,采用差值的绝对值小于一个很小的数delta,这种是不严谨的,由于float的最小粒度为pow(2, -23),精确到小数点后7位,是在整数部分只占最多1bit的情况下,假设整数部分为10000,此时若delta为0.0001,会超出精度,应改成delta为0.001,可采用以下函数来判断:

    bool is_float_eq(float x, float y) {
        return x == y || abs(*(unsigned int*)&x-*(unsigned int*)&y) == 1;
    }
    

redis集群

  • redis集群原理

    由于redis是内存型数据库,因此想承载大量的缓存需要加集群,redis集群实现原理是一致性哈希,即把key先做hash运算,得到一个32位的整数,然后对redis的slot总数取模,再把key放到slot对应的redis节点上。若当前连接的redis节点上不存在要查询的key,此时会自动重定向key所在的redis节点,因此redis集群不支持涉及多个key的命令,例如集合取交集。

  • redis集群搭建

    由于redis集群采用投票容错机制,即有一半以上投票某个master节点挂了,才认为此节点不可用,需要用相应的slave节点替换,因此 redis集群至少需要3个master和3个slave节点,为了方便演示采用一个虚拟机同时启动6个实例的方式。

    1. 启动6个实例

     mkdir redis-cluster
     cd redis-cluster
     mkdir redis1
     cp redis-server redis1
     cp redis.conf redis1
     依次6份复制redis1
     把redis.conf配置项cluster-enabled设置为yes,port改为7701、7702...7706
     最后依次启动redis-server
    

    2. 创建集群

     redis-cli --cluster create 127.0.0.1:7701 127.0.0.1:7702 127.0.0.1:7703 127.0.0.1:7704 127.0.0.1:7705 127.0.0.1:7706 --cluster-replicas 1
    
  • 添加节点

    1. 添加主节点到集群

    redis-cli --cluster add-node 127.0.0.1:7707 127.0.0.1:7701

    2. 分配哈希槽

    redis-cli --cluster reshard 127.0.0.1:7701
    可选择分配多少哈希槽,以及分配方式

    3. 添加从节点到集群

    redis-cli --cluster add-node 127.0.0.1:7708 127.0.0.1:7701

    4. 构建主从关系

    登录到7708:redis-cli -c -p 7708
    执行集群复制命令:cluster replicate fccadebeb5b769bd084369e5cbe391979fb53b40
    fccadebeb5b769bd084369e5cbe391979fb53b40为7707的节点id

  • 删除节点

    1. 重分配哈希槽

    redis-cli --cluster reshard 127.0.0.1:7701
    源节点选择7707,哈希槽个数选择全部,接受节点随机选一个即可

    2. 删除主节点、从节点

    redis-cli --cluster del-node 127.0.0.1:7701 masterID
    redis-cli --cluster del-node 127.0.0.1:7701 slaveID
    masterID为主节点id,slaveID为从节点的id

自动生成GNU项目的configure和Makefile

通常开源的GNU项目编译和安装只需以下两步:

./configure
make && make install

而我们发布自己的个人项目通常手工写Makefile文件,总感觉跟GNU的Makefile文件相比很low,而且很多时候依赖系统的配置,因此就有以下工具帮助我们自动生成标准的configure文件和Makefile文件,下图就是工具的流程图:
2009052517385173.png

1. 自动扫描工具autoscan

在工程的根目录下运行autoscan命令,autoscan会自动扫描工程中的源码,生成configure.scan文件,然后把configure.scan文件重命名为configure.ac或configure.in,并做相应的修改,详细可参考文末的demo

2. m4文件生成工具aclocal

aclocal是一个perl脚本,可根据configure.ac生成aclocal.m4

3. configure文件生成工具autoconf

autoconf可根据configure.ac和aclocal.m4文件生成configure文件,configure是一个shell脚本,能根据不同的操作系统生成相应的Makefile

4. Makefile.in文件生成工具automake

首先编写Makefile.am文件,详细可参考文末的demo,automake会根据configure.ac和Makefile.am文件生成Makefile.in文件,运行automake通常带--add-missing选项,此选项会让automake加入一个标准的软件包所必须的一些文件

5. 生成最终Makefile文件

运行./confiugre,configure会根据Makfile.in文件生成最终的Makefile文件

由此可见,为了生成标准的Makefile文件,需要以上复杂的步骤,因此很多项目通常会有configure.ac、Makefile.am、autogen.sh三个文件,由autogen.sh根据configure.ac和Makefile.am文件自动完成以上步骤来生成Makefile文件,详情参考github地址:https://github.com/song2010040402102/autoconf_demo.git

对于autoconf系列的工具集,目前我也是仅知其然而不知其所以然,按以往的性格会把这整块吃透,只是最近才突然感觉到,时间和精力有限,应把主要的时间和精力放在内功修炼上,而不是类似工具这种外功上,工具会用即可,想搞明白只是时间问题,体现不出一个人的能力高低,所以此篇只介绍使用而不了解其细节实现

vmware-kvm.exe 管理虚拟机

1. windows开机自启动linux虚拟机

vmware-kvm.exe ubuntu-serv.vmx
把此脚本放在B:\Windows\System32\GroupPolicy\User\Scripts\Logon

2. windows关机自挂起linux虚拟机

vmware-kvm.exe --suspend ubuntu-serv.vmx
把此脚本放在B:\Windows\System32\GroupPolicy\User\Scripts\Logoff

ubuntu samba 服务器配置

1. 检查windows所在的工作站域

windows若想通过samba服务器访问linux,必须和samba上配置的工作站域一致,默认都用WORKGROUP

2. 添加本地域名以便于访问

追加hosts文件:192.168.1.111    ubuntu.com    ubuntu

3. 建立匿名访问

  • 修改/etc/samba/smb.conf配置

    [global]
    workgroup = WORKGROUP
    server string = Samba Server %v
    netbios name = ubuntu
    security = user
    map to guest = bad user
    dns proxy = no

    [Anonymous]
    path = /samba/anonymous
    browsable =yes
    writable = yes
    guest ok = yes
    read only = no

  • 建立匿名访问根目录

    mkdir -p /samba/anonymous
    chmod -R 0777 /samba/anonymous
    chown -R nobody:nogroup /samba/anonymous

4. 建立安全访问

  • 追加/etc/samba/smb.conf配置

    [secured]
    path = /samba/secured
    valid users = @smbgrp
    guest ok = no
    writable = yes
    browsable = yes

  • 建立安全访问根目录

    addgroup smbgrp
    adduser smbusr -G smbgrp //若命令失败,可用 -g group_id
    smbpasswd -a smbusr
    mkdir -p /samba/secured
    chmod -R 0750 /samba/secured
    chown -R smbusr:smbgrp /samba/secured

5. 重启samba服务器

service smbd restart

6. 验证

在windows地址栏输入:\\ubuntu,可在anonymous和secured文件夹进行读写操作