左耳听风

作者: Jack_Cui | 来源:发表于2018-10-31 15:09 被阅读0次

    00开篇词

    • 自我介绍
    • 本收费专栏会讲哪些东西
      • 会以体系话的方式讲解2-3 个分布式的文章
      • 热点事件
      • 经验之谈
    • 如何自我成长
    • 管理
      • 团队管理
      • 自我管理
      • 项目管理

    01程序员如何用技术变现上

    • 自己的学生时代如何赚钱

      • 帮打印店打字
      • 帮老师开发软件
    • 初入职场

      • 写稿子赚钱
      • 通过提升写代码的效率来看书提升自己
      • 写博客 客户通过博客联系到耗子去做培训赚钱
        一个人的25 -35 是最黄金的时期 应该花在刀刃上
    • 职场上升期

      • 帮其他公司解决技术问题赚钱

    02程序员如何用技术变现下

    • 千里之行 始于足下
      让自己身边的人有求于己 或者向别人推荐自己
    • 关注有价值的东西
      那些供大于求的东西是不需要关注的
    • 关注市场需求
      同上
    • 关注技术趋势
      看清技术趋势 了解技术发展轨迹
    • 找到能体现价值的东西。在一家告诉发展的公司技术人员可以达到最大的提升和发展
    • 动手能力很重要
      魔鬼隐藏在细节里面
    • 关注技术付费点
      要么是帮别人赚钱 要么是帮别人省钱
    • 提升自己的能力和经历
    • 找到有价值的信息源
      有时需要为了获取1%的知识而去看99%无用的内容 这样的效率是非常低的
    • 输出观点和价值观
      前提是自己的积累和经历 可以很好的提升自己的影响力
    • 朋友圈很重要
      在什么样的朋友圈就会被什么样的朋友圈所影响 如果在优质的朋友圈中受到的影响和信息也都是优质的 首先自己也要是优秀的人
      有自己的看法观点 经验比较丰富
      涉猎面比较广
      有或多或少的成功
      喜欢折腾搞事
      对现状不满并想做一些改变
      都有一定的影响力

    03从Equifax数据泄露看数据安全

    • 介绍了Equifax数据泄露的始末

    04第四讲 从Equifax数据泄露看数据安全下

    • 数据泄漏介绍和历史回顾
    • 攻击是如何实现的
      • 利用已知程序框架或库的漏洞
        -暴力破解密码
      • 利用程序日志泄漏的密码
      • 社会工程学
    • 为什么会被攻击
      • 只有一层防护
      • 弱密码
      • 向公网暴露内部系统
      • 未对系统及时更新补丁
      • 安全日志暴露
      • 保存了不必要的用户数据
      • 密码没有被合理的散列
    • 对于使用了库的程序的安全建议
      • 详细了解程序具体使用哪些框架和库 版本号是多少 时刻跟踪这些产品和版本的最新安全性声明
      • 建立流程 可以快速的部署带有安全补丁的产品发布版本
      • 不要基于程序没有漏洞的假设来建立安全策略
      • 建立多个安全层 就算表层被攻破也不会泄露重要数据
      • 建立对异常访问的监控机制
    • 技术上的安全做法
      • 将关键数据定义并且隔离出来 隔离到一个安全级别很高的地方 (需要安全审计 安全监控 安全访问的地方)
      • 在上述区域中敏感数据只进不出 拿手机号来说 如果要发短息 发送短信的功能要在安全区域实现 外部通过uuid 或是抽象的字段来调用这个API
      • 使用加密算法 定时更新秘钥 将秘钥和数据分开保存
        当黑客的投入成本和收益大大不相符时 黑客也就失去了入侵的意义
    • 做好风控管理

    05何为技术影响力

    技术领导力不仅仅是呈现出来的技术,而是一种可以获得绝对优势的技术能力。

    • 尊重技术 追求核心基础技术
    • 追逐自动化的高效率的工具和技术,同时避免无效了的同时避免无效率的组织架构和管理。
    • 解放生产力,追逐人效的提高。
    • 开发抽象和高质量的可以重用的技术组件。
    • 坚持高于社会主流的技术标准和要求

    说人话就是

    • 能够发现问题。能够发现现有方案的问题。
    • 能够提供解决问题的思路和方案,并能比较这些方案的优缺点。
    • 能够做正确的技术决定。用什么样的技术、什么解决方案、怎样实现来完成一个项目
    • 能够用更优雅,更简单,更容易的方式来解决问题。
    • 能够提高代码或软件的扩展性、重用性和可维护性。
    • 能够用正确的方式管理团队。所谓正确的方式是,一方面是,让正确人做正确的事,并发挥每个人的潜力;另一方面是,可以提高团队的的生产力和人效,找到最有价值的需求,用最少的成本实现之。并且,可以不断地提高自身和团队的标准。
    • 创新能力。能够使用新的方法新的方式解决问题,追逐新的工具和技术

    要实现这些需要一些前提

    • 扎实的基础技术。
    • 非同一般的学习能力。
    • 坚持做正确的事。
    • 不断提高对自己的要求标准

    06怎么才能拥有领导力

    吃透基础知识

    编程部分

    • c语言 《c程序设计语言》
    • 编程范式
    • 算法和数据结构

    系统部分

    • 计算机系统原理
      《升入理解计算机系统》
    • 操作系统原理和基础
      《UNIX环境高级编程》
      《UNIX网络编程》
      《windows核心编程》
      -网络基础
      《TCP/IP详解》
    • 数据库原理
    • 分布式技术架构

    提高学习能力

    • 学习的信息源
    • 与高手交流
    • 举一反三的思考
    • 不怕困难的态度
    • 开放的心态

    坚持做正确的事

    • 提高效率的事
    • 自动化的事
    • 掌握前沿技术的事
    • 知识密集型的事
    • 技术驱动的事

    高标准要求自己

    • 自我评分
    • 敏锐的技术嗅觉
    • 强调实现 学以致用
    • 永远在编程

    07 推荐一些有价值的东西

    • 每个程序员都应该读的书
      • 《代码大全》
      • 《程序员修炼之道》
      • 《计算机的构造和解释》
      • 《算法导论》
      • 《设计模式》
      • 《重构》
      • 《人月神话》
      • 《代码整洁之道》
      • 《 Effective C++》/《More Effective C==》
      • 《Unix 编程艺术》《Unix》高级环境编程
    • 每个搞计算机专业的学生都应该有的知识(有点标题党啊)
      • 要获得一份好的工作学生应该知道什么
      • 为了一辈子都有工作干学生需要知道什么
      • 学生需要知道什么才能进入研究生
      • 学生需要知道什么才能对社会有益
      • 本书总结
        • 对于每个人来说,作品会比简历更有参考意义,所以在自己的简历中应该放上自己的一些项目经历或者对开源项目的贡献。最好有一个自己的网站,上面有一些自己的技能、经历。
        • 计算机专业的工作者也要学会与人沟通的技巧,包括如何掩饰文稿,如何面对质疑是与人辩论的能力
        • 最后说明计算机专业人士需要的硬技能

    08 GO语言 Docker和新技术

    • 为什么Go语言和Docker会是因一带云计算技术
      • Go语言语法简单上手快
      • 并行和异步编程几乎无痛点
      • lib库虽小但五脏俱全
      • C 语言的理念和 Python 的姿态 Go 语言想要把 C 和 Python 集合起来
      • 一个技术能不能发展起来要看三点
        • 有没有一个比较好的社区
        • 有没有一个工业化的标准
        • 有没有一个或者多个杀手级应用
    • 作为技术人员如何辨别什么样的新技术会是未来的趋势
      • 有没有一个比较好的社区
      • 有没有一个工业化的标准
      • 有没有一个或者多个杀手级应用
      • 学习曲线是否低、上手是否快
      • 有没有一个不错的提高效率的开发框架
      • 有没有一个或者多个巨型公司作为后盾

    09 渴望、热情和选择

    • 加班太严重 没有时间学习
      没有时间学习,但是自己却又熬夜刷视频、玩游戏。不在于加班,而在于对于学习的渴望有多大
    • 怎么写出数量多 质量高的文章
      和上面一样 需要自己的热爱和坚持
    • 怎样选择自己的人生和职业发展
      • 20 - 30 岁打基础的阶段
      • 30 - 40 岁人生发展的阶段
      • 客观的审视自己 知道自己几斤几两,清楚自己适合干什么
      • 清楚自己想要什么
        自己不会收到其他东西或者其他人的干扰,不会因为这条路上有人退出就会怀疑自己,也不会因为这条路上有人成功就羡慕别人。
      • 注重长期的可能性而不是短期的功利
      • 尽量关注自己会得到的东西而不是自己会失去的东西
      • 不要和大众的思维一样

    10 如何成为一个大家愿意追随的Leader

    Boss和Leader的不同
    • 帮别人解决问题
    • 被人依赖
    • 可以有下面的人成为朋友
    • 赢得他人的信任
    • 开放的心态 + 倾向性的价值观
    • Lead by Example
    • 保持热情和冲劲
    • 能够抓住重点 看透事物的本质
    • 描绘令人激动的方向 提供令人向往的环境
    • 甘当铺路石 为他人创造机会

    11 程序中的错误处理:返回码和异常捕捉

    • 错误处理基本可以分为:

      • 通过返回码处理
      • 通过异常处理返回
        各自优缺点
    • 错误码

      • 容易不小心忘掉错误码的检查
      • 接口不纯洁 正常值和错误值混在一起导致语义有歧义
      • 在对于某些特殊的函数比如字符转数字的时候可以使用多返回值来处理无法判断错误码的情况
      • 在资源释放可以采用goto fail的方式 在面向对象编程的实现可以通过析构实现资源的释放
      • 在分布式的情况下远程服务只能看返回码
    • 异常捕捉

      • 语义比较清楚
      • 正常逻辑代码和错误处理分开,提高了代码的可读性
      • 异常不能被忽略
      • 可以实现多台的catch
      • 异常捕捉对性能有影响
      • 异常捕捉只能用在同步的情况下使用,异步情况下无法使用
    • 错误可以分为3类

      • 系统资源的错误 这种时候只能停止运行,甚至退出整个程序
      • 程序的错误。这个是自己程序的错误,需要写入日志,最好触发系统报警
      • 用户的错误 比如参数传的不合法
    • 对于我们不希望发生的事情可以采用异常捕捉

    • 对于有可能会发生的事情用返回码
      顺便复习下try catch

    #include<iostream.h>                        //包含头文件
    
    #include<stdlib.h>
    
    double fuc(double x, double y)                        //定义函数
    
    {
    
    if(y==0)
    
    {
    
    throw y;                                    //[除数为0,抛出异常
    
    }
    
    return x/y;                                    //否则返回两个数的商
    
    }
    
    void main()
    
    {
    
    double res;
    
    try                                         //定义异常
    
    {
    
    res=fuc(2,3);
    
    cout<<"The result of x/y is : "<<res<<endl;
    
    res=fuc(4,0);                                //出现异常
    
    }
    
    catch(double)                                    //捕获并处理异常
    
    {
    
    cerr<<"error of dividing zero.\n";
    
    exit(1);                                    //异常退出程序
    
    }
    
    }
    
    

    12 程序中的错误处理:异步编程

    异步编程中的错误处理

    在异步编程的世界里,因为被调用的函数是被放到了另外一个线程里运行这将导致:

    • 无法使用返回值

    • 无法使用抛异常的方式
      除了上述的函数里吗返回的原因之外,抛出的异常也在另外一个线程中,不同线程中的栈是完全不同的,所以主线程的catch完成看不到另外一个线程中的异常。

    • 在异步编程的世界里,也有常用的几种处理错误的方法,最常用的就是callback方式。

    • 中间看不懂啊
      不懂JS和Go啊

    • 错误处理的最佳实践

      • 统一分类的错误字典
      • 同类错误的定义最好是可以扩展的
      • 定义错误的严重程度
      • 错误入职的输出最好使用错误码,而不是错误信息。
      • 忽略错误要有日志
      • 对于一个地方不停的报错,最好不要都打印到日志里,可能会导致其他日志被淹没
      • 不要用错误处理逻辑来处理业务逻辑
        不要使用异常捕捉这样的方式来处理业务逻辑,应该用条件判断。
      • 对于同类的错误处理,用一样的模式
      • 尽可能在错误发生的地方处理错误
      • 向上尽可能地返回原是的错误
      • 处理错误时,清理已经分配的资源
      • 不要在循环体里面处理错误
      • 不要把大量的代码都放在一个try语句快里面
      • 提供清楚的文档以及每种错误的代码事例
      • 对于异步的方式,推荐使用Promise模式处理错误
      • 对于分布式系统,推荐使用APM相关的软件

    13 魔数 0x5f3759df 看不懂啊 放弃了 todo

    先看下面这段代码

    float Q_rsqrt( float number )
    {
        long I;
        float x2, y;
        const float threehalfs = 1.5F;
    
        x2 = number * 0.5F;
        y  = number;
        i  = * ( long * ) &y; // evil floating point bit level hacking
        i  = 0x5f3759df - ( i >> 1 );  // what the fuck? 
        y  = * ( float * ) &I;
        y  = y * ( threehalfs - ( x2 * y * y ) );  // 1st iteration 
        // 2nd iteration, this can be removed
        // y  = y * ( threehalfs - ( x2 * y * y ) ); 
    
        return y;
    }
    

    这个函数的作用是秋平方根倒数,即 x^{-1/2}
    \frac{1}{\sqrt{x}}
    当然,它算的是近似值,只不过这个近似值的京都很高,而且计算成本比传统的浮点数运算平方根的算法低很多。
    在以前那个计算资源还不充沛的年代,在一些3D游戏场景的计算机图形学中,要求取照明和投影的光照与反射的计算。其中x,y,z是3D坐标上的一个点的三个坐标值。
    \frac{1}{\sqrt{x^2}+y^{2}+z^{2}}
    基本来说,在一个3D游戏中,我们每秒钟都需要做上百万次平方根倒数运算,而在计算机还不成熟的时代,这些计算都需要软件来完成,计算速度非常慢。

    • 在C语言中,计算机的浮点数表示用的是IEEE 754标准,这个标准其实就是把一个32 bit 分成三段
      • 第一段栈 1 bit 表示符号位,代码为S(sign)
      • 第二段占 8 bit 表示指数,代称E(Exponent)
      • 第三段占 23 bit ,表示尾数,代称为M(Mantissa)
        如下图:

        然后呢,一个小数的计算方式就是下面这个算式:
        (-1)^(S)\ast(1+\frac{M}{2^{23}})\ast 2^{(E-127)}
        但是,这个算式基本上来说就是让人一头雾水,摸不着头脑,就想下面这个样子:
        image.png
        下面我们来解释下浮点数的三段表示什么意思
    • 第一段符号位 这个大家都了解
    • 第二段指数位 什么叫指数?也就是说对于任何数X,都可以找到一个n,使得2的n次方小于等于x,x小于等于2的n+1次方。比如对于3来说,2<3<4,所以n=1.而浮点数的这个指数为了要 表示0.00x的小数,所以要有负数,这8个bits本来可以表示0-255,为了表示负的,取值要放在[-127,128]这个区间中,这就是为什么我们在上面的公式中看到的2的(E-127)次方这一项来。
      也就是说,n= E -127,如果n=1,那么E就是128了。
    • 第三段尾数位。也就是小数位,但是这里叫偏移量可能好一些,这里的取值是从[0 - 2的23次方]中。可以认为我们把一条线分成2的23次方个线段,也就是8388608个线段。也就是说,把2的n次方到2的n+1次方分成了8388608个线段,而存储的M值,及时从2的n次方到x要经过多少个段。这要计算一下,2的n次方到x的长度占2的n次方到2的n+1次方长度的比例是多少。
      现在看的还是云里雾里的,我们来举个例子。比如说对3.14这个小数。
    • 是正数。所以,S = 0
    • 2的1次方小于3.14,3.14小于2的2次方。所以n = 1,n= E-127,所以E= 128.
    • (3.14-2)/(4-2)= 0.57,而0.57*2的23次方= 4781506.56,四舍五入,得到M= 4781507。因为有四舍五入,所以产生了浮点点数的精度问题。
      把S、E、M转换成二进制,得到3.14的二进制问题。
      image.png
      在用IEEE 754那个算式来算下:
      {(-1)}^0*({1+\frac{4781507}{}{2^{23}}})*2^{(128-127)}
      1*(1+0.5700000524520874)*2
      =3.1400001049041748046875
      浮点的精度就出现问题了。
      我们再来看一个例子,小数0.015
    • 是正数 所以S = 0
    • 2 的-7次方小于0.015,0.015小于2的-6次方。所以n = -7 ,所以E = 120.
    • (0.015 - 2 的-7次方)/(2的-6次方 - 2的-7次方) = 0.0071875/0.0078125 = 0.92.而0.92*2的23次方 = 7717519.36,四舍五入,得到M = 7717519
      于是,我们得到0.015的二进制编码:


      image.png

      其中:

    • 120 的二进制是0111100
    • 7717519的二进制是1110101110000101000111
      返回过来算一下:
      (-1)^{0}\ast (1+\frac{7717519}{2^{23}})\ast 2^{(120-127)}
      (1+0.919999957084656)*0.0078125
      =0.014999999664724
      浮点数的精度问题又出现了。
      我们用代码来实现下:
    int main() {
        float x = 3.14;
        float y = 0.015;
        return 0;
    }
    

    在Mac上用lldb工具debug一下。

    (lldb) frame variable
    (float) x = 3.1400001
    (float) y = 0.0149999997
    
    (lldb) frame variable -f b
    (float) x = 0b01000000010010001111010111000011
    (float) y = 0b00111100011101011100001010001111
    

    从结果上完成验证了我们的方法。

    简化浮点数公式

    因为浮点数表示的公式有些复杂,我们简化一下
    (-1)^{S}\ast (1+\frac{M}{2^{23}})\ast 2^{(E-127)}
    我们令,m = (\frac{M}{2^{23}} )e = (E-127)。因为符号位在y= x^{-\frac{1}{2}}的两端都是0(正数),也就可以去掉,所以浮点数的算式简化为:
    (1+m)\ast2^{e}
    上面这个算式是从一个32bits二进制计算出一个浮点数。这个32bits的整型算式是:
    M+E\ast2^{23}
    比如,0.015的32bits的二进制是:00111100011101011100001010001111,也就是整形的:
    7717519+120\ast 2^{23}
    = 1014350479
    = 0X3C75C28F

    平方根倒数公式推导

    相关文章

      网友评论

        本文标题:左耳听风

        本文链接:https://www.haomeiwen.com/subject/ljsatqtx.html