今日阅读-工作相关内容

记录日常读到的和工作相关的文章/链接
长期更新

缘起

虽然看过很多好文章, 但一直没找到整理的地方, 后续再找时也不方便. 最近翻 github 时看到了陶文整理的今日阅读文件, 记录每天看到的优秀文章, 贴下链接, 附一两句简单的评论, 感觉是一个不错的方案

一方面, 阅读经历本身不涉及关键隐私, 分享好文可以创造信息. 另一方面, 也可以作为外人了解我们的途径. 没有明显坏处但成本低有收益的事, 是可以做一做的.

故有此页面

历史汇总

2024-01-29

2024-01-17

  • JS的浮点数精度问题
    • 关于浮点数精度问题最有名的案例是0.1+0.2 !== 0.3
    • 不过这里有个现实版, Number.parseInt(`${+16.124 * 1000}`) / 1000 === 16.123, 代码目标是对16.124进行取整精确到厘(三位小数), 结果算出来少了1厘钱
      • 如果愿意尝试的话会发现有很多这样的例子
        • 16.127*1000 => 16.126
        • 16.130*1000 => 16.129
        • 16.141*1000 => 16.140
      • 进一步探索发现, 上边的 bad case 会在一个范围内密集分布
        •   /**
             * 返回整数为baseNumber, 小数为precision位的所有转换后不相等的数字列表
             */
            function getAllErrorNumber(baseNumber = 10,precision=2){
                const transErrorList = []
                if( precision < 1){
                    return transErrorList
                }
                const maxNumber = Math.pow(10, precision) 
                for(let i = 0; i < maxNumber; i++) {
                    const iStr = `${i}`.padStart(2, '0')
                    const legalNumber = parseFloat(`${baseNumber}.${iStr}`)
                    if(legalNumber !== Math.floor(legalNumber * 1000) / 1000){
                        transErrorList.push(legalNumber)
                    }
                }
                if(transErrorList.length > 0){
                console.log(`[base][${baseNumber}]total error number => ${transErrorList.length}`)
                }
                return transErrorList
            }
            const allErrorList = []
            for(let i = 0; i<1000;i++){
                allErrorList.push(...getAllErrorNumber(i, 2)) 
            }
          
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
          24
          25
          26
          27
          28
          29
          30
          31
          32
          33
          34
          35
          36
          37
          38
          39
          40
          41
          42
          43
          44
          45
          46
          47
          48
          49
          50
          51
          52
          53
          54
          55
          56
          57
          58
          59
          60
          61
          62
          63
          64
          65
          66
          67
          68
          69
          70
          71
          72
          73
          74
          75
          76
          77
          78
          79
          80
          81
          82
          83
          84
          85
          86
          87
          88
          89
          90
          91
          92
          93
          94
          95
          96
          97
          98
          99
          100
          101
          102
          103
          104
          105
          106
          107
          108
          109
          110
          111
          112
          113
          114
              - 用脚本跑了一下, 当小数位数为2/3位时, 前1000位异常数字数分布如下(出现问题时的整数位都一样)
          | 整数位 | x.00~x.99之间的异常数字数 | x.000~x.999之间的异常数字数 |
          | :----- | :------------------------ | :-------------------------- |
          | 2 | 2 | 2 |
          | 4 | 2 | 2 |
          | 8 | 5 | 27 |
          | 16 | 9 | 76 |
          | 32 | 19 | 182 |
          | 64 | 24 | 243 |
          | 65 | 13 | 121 |
          | 128 | 24 | 238 |
          | 129 | 24 | 238 |
          | 130 | 24 | 238 |
          | 131 | 2 | 2 |
          | 256 | 24 | 239 |
          | 257 | 24 | 239 |
          | 258 | 24 | 239 |
          | 259 | 24 | 239 |
          | 260 | 24 | 239 |
          | 261 | 24 | 239 |
          | 262 | 4 | 14 |
          | 512 | 24 | 239 |
          | 513 | 24 | 239 |
          | 514 | 24 | 239 |
          | 515 | 24 | 239 |
          | 516 | 24 | 239 |
          | 517 | 24 | 239 |
          | 518 | 24 | 239 |
          | 519 | 24 | 239 |
          | 520 | 24 | 239 |
          | 521 | 24 | 239 |
          | 522 | 24 | 239 |
          | 523 | 24 | 239 |
          | 524 | 6 | 51 |
          - 核心原因是大部分十进制下的小数不能转成有限长度的二进制值, 例如0.1在二进制下是`.0001100110011...`(无限循环0011)
          - [微软总结了四点注意事项](https://learn.microsoft.com/zh-cn/office/troubleshoot/access/floating-calculations-info)
          - 在涉及单精度和双精度的计算中,结果通常不会比单精度更准确。 如果需要双精度,请确定计算中的所有术语(包括常量)均以双精度指定。
          - 备注: js中没有单双精度转换问题, 所有数字(不止小数)都是双精度数
          - 切勿假定在计算机中准确表示简单的数值。 大多数浮点值不能精确地表示为有限的二进制值。 例如, .1 是在 .0001100110011... 二进制 (它永远重复) ,所以它不能在计算机上使用二进制算术(包括所有电脑)以完全准确的方式表示。
          - 切勿假设结果准确到最后一个小数位。 “true”答案与任何浮点处理单元的有限精度可以计算的内容之间始终存在很小的差异。
          - 切勿比较两个浮点值,以查看它们是否相等。 这是规则 3 的必然结果。 数字之间几乎总是有小的差异,“应该”是相等的。 相反,请始终检查数字是否几乎相等。 换句话说,检查它们之间的差异是小的还是微不足道的。
          - 按照[这篇文章](https://www.zoucz.com/blog/2021/07/08/52c9e5d0-dfb5-11eb-9fe7-534bbf9f369d/)分析, 但凡没有自己实现基于十进制的数字运算的语言,都这种问题. 解决方案是使用对关键问题使用十进制计数. 例如[decimal.js](https://www.npmjs.com/package/decimal.js?activeTab=readme)库.
          - 缺点是性能比较差, 简单的对比结果显示计算100万次两数加法, decimal.js比原生慢500倍(decimal cost: 1234, native cost: 2)

          # 2024-01-11

          - 解决vue2.6升级2.7时的异常case
          - el-table 在 vue2.7 渲染失败问题
          - 业务代码用的是 "module": "dist/vue.runtime.esm.js",而 element-ui 用的是 "main": "dist/vue.runtime.common.js",因此页面加载了两个不同的vue, 但因为只有一个vue的实例可以正常使用, 因此会导致渲染失败, 形成白屏. 指定vue指向同一个运行文件即可修复.
          via https://github.com/ElemeFE/element/issues/21984
          - 进阶: 特定场景下, vite将`vue`指定为`vue/dist/vue.esm.js`后, 读取到其他目录下的`vue/dist/vue.esm.js`问题
          - 改为`path.resolve(__dirname, 'node_modules', 'vue/dist/vue.esm.js')`, 通过绝对路径指定文件
          - 进阶v2: 项目中包都依赖vue2, 但某一个依赖的依赖需要vue3
          - 若项目中依赖vue3的项目需要实际执行 => 略过, 暂未想到解决方案
          - 若项目中依赖vue3的项目不需要实际执行, 只进行编译即可 => 通过自定义依赖加载函数, 根据当前执行导入的文件动态替换vue2/3
          - 代码示例
          ```js
          resolve: {
          alias: [
          // {
          // // 升级vue3时使用用
          // find: "vue",
          // replacement: '@vue/compat',
          // },
          {
          find: 'vue',
          customResolver: (source, importer, options) => {
          // 通过指定vue解析算法, 解决vue2/3依赖共存时, 代码白屏问题

          // 首先解决el-table 在 vue2.7 渲染失败问题
          // 业务代码用的是 "module": "dist/vue.runtime.esm.js",而 element-ui 用的是 "main": "dist/vue.runtime.common.js",因此页面加载了两个不同的vue, 但因为只有一个vue的实例可以正常使用, 因此会导致渲染失败, 形成白屏. 指定vue指向同一个运行文件即可修复.
          // via https://github.com/ElemeFE/element/issues/21984
          // 注: 文件本身需要使用绝对路径, 以避免相对路径时文件指向错误
          // replacement: path.resolve(__dirname, 'node_modules', 'vue/dist/vue.runtime.common.js'),
          const vue2Uri = path.resolve(__dirname, 'node_modules', 'vue/dist/vue.esm.js');

          // platforms/TreeSelect.vue 中的服务树组件需要执行特殊hack逻辑

          // @sre/service-tree中使用了@sre/common@0.1.1, 而该包引用了@element-plus/element-plus@0.1.0(该包又依赖了@element-plus/icons-vue). @element-plus/element-plus 中的代码虽然并未实际使用, 但也会阻塞编译过程, 导致白屏. 且其既要求使用vue3, 又对vue是peerDependencies依赖, 不会直接安装. 所以要通过工具包@infra/only-dependency-vue3来强制保证项目中存在vue3包. 并通过以下代码找到其位置, 在运行时进行主动替换, 确保项目可以正常运行

          // 根据工具包在node_modules中的路径, 确认其在.pnpm目录中的真实路径, 进而找到实际vue3文件的路径
          // 工具包原始地址
          // /Users/yao/www/project/platforms/node_modules/@infra/only-dependency-vue3
          const utilPackageUri = path.resolve(__dirname, 'node_modules', '@infra/only-dependency-vue3');
          // 转换成实际地址
          // /Users/yao/www/project/platforms/node_modules/@infra/only-dependency-vue3
          // ../../../../node_modules/.pnpm/@infra+only-dependency-vue3@1.0.0_typescript@5.2.2/node_modules/@infra/only-dependency-vue3
          const utilPackageRealLinkRelative = fs.readlinkSync(utilPackageUri);
          // 将相对路径转换成真实路径
          // /Users/yao/www/project/node_modules/.pnpm/@infra+only-dependency-vue3@1.0.0_typescript@5.2.2/node_modules/@infra/only-dependency-vue3
          const utilPackageRealLinkAbsolute = path.resolve(
          utilPackageUri,
          '..',
          utilPackageRealLinkRelative
          );
          // 最终拼接成@infra/only-dependency-vue3 在pnpm中实际依赖的vue@3.4.5路径
          const vue3Uri = path.resolve(
          utilPackageRealLinkAbsolute,
          '../..',
          'vue/dist/vue.esm-browser.js'
          );

          for (let keyword of ['@element-plus/element-plus', '@element-plus/icons-vue']) {
          if (importer?.includes(keyword) === true) {
          // 命中关键字才按vue3进行返回
          return vue3Uri;
          }
          }
          // 默认直接返回vue2的文件路径
          return vue2Uri;
          },
          },
          ],
          },

2024-01-10

  • PAKE
    • 基于Tauri 直接封装h5页面作为桌面客户端. 缺点是只支持h5, 不支持node
    • EXPO也可以考虑
  • 知乎回答对柯氏复杂度的介绍
    • 随机生成5位数,得到11111和得到54176的概率相同,为什么遇到前者时我们会觉得随机算法有问题
    • Kolmogorov复杂度给出了这样一种洞见: 一个序列是否 “足够随机/有规律” , 可以用 “我最短能用多短的语句描述这个序列” 来衡量, 描述能压缩得越短, 就说明规律性越强.
    • 1111111111可以用10个1描述, 复杂度为3, 而5417627465只能原样讲述, 所以5417627465的复杂度更高, 更"没有规律"
    • 这篇介绍写的也不错
      • 算法信息论是计算机科学的一个分支,研究 Kolmogorov 复杂性和字符串(或其他数据结构)的其他复杂性度量。
  • 零知识证明の百万富翁问题
    • 如何在AB互相不透露有多少钱的情况下, 得到AB谁的钱更多

2024-01-04

  • pnpm支持在package.json中通过pnpm.neverBuiltDependencies字段, 跳过指定包的preinstallinstallpostinstall阶段.
    • 用法一: 如果用不到某个包的特定依赖. 例如typeorm中的libpq, 而这个包的script脚本构建时间又极长甚至构建不成功会阻塞lock文件的生成, 可以通过该选项跳过该包的安装脚本执行
    • 用法二: 流水线排障中, 若某个包安装时间过长且和最终排障目标无关, 可以在排障阶段临时略过该包的执行过程, 例如fsevent/grpc

今日阅读-工作相关内容
https://www.yaozeyuan.online/2024/01/01/what-read-today/工作相关/
作者
姚泽源
发布于
2024年1月1日
许可协议