没想到不同银行在存款证明方面的逻辑有这么大差异,我目前试出来的信息:
- 招商银行:可开非冻结或冻结的,会显示开户日期,可以任意输入更小的金额数字
- 中国银行:只能开冻结的,可以冻 1 天但不能不冻
- 中国建设银行:可开非冻结或冻结的(他们称为时点和时段),不显示开户日期,不能自定义金额,只能是当前实际余额
- 招商银行:可开非冻结或冻结的,会显示开户日期,可以任意输入更小的金额数字
- 中国银行:只能开冻结的,可以冻 1 天但不能不冻
- 中国建设银行:可开非冻结或冻结的(他们称为时点和时段),不显示开户日期,不能自定义金额,只能是当前实际余额
👍1
不同云服务商的几台机器之间有安全通信的需求的话(例如需要调用 HTTP API 或连接数据库),可以选择 VPN 或者 TLS。如果自己维护一个 CA,为所有机器正确配置 server certificate 和 client certificate 的话,是可以达到与 VPN 相似的保护效果的。
但是由于种种原因,TLS 有一些设计并不令我满意,效果上总是比 VPN 差那么一点。例如:端口号是公开的,别人一扫就知道你在运行什么服务,改用随机端口的话不太方便,并且仍然可以扫出一些信息。验证 client certificate 之前就会发送 server certificate,这里面可以泄露不少信息,包括 hostname、证书签发时间、CA 的名字等,可以用于猜测这台机器的拥有者和功能。SNI 目前仍然是没加密的。用 VPN 的话是没有这些信息泄露的。
但 VPN 也有自己的问题,配置起来更麻烦一些,不适合增量式地为每个应用配置,需要提前决定好怎么把所有机器组网,想临时给别人一个权限时,给对方签一张 client certificate 也更轻量级。
如果想要一种可以为各个应用按需启用的、可以灵活配置权限规则的方案,似乎还是更像 TLS 一点。它要是把更多步骤挪到检查客户端证书之后再做,并且都加密传输,就好了。
但是由于种种原因,TLS 有一些设计并不令我满意,效果上总是比 VPN 差那么一点。例如:端口号是公开的,别人一扫就知道你在运行什么服务,改用随机端口的话不太方便,并且仍然可以扫出一些信息。验证 client certificate 之前就会发送 server certificate,这里面可以泄露不少信息,包括 hostname、证书签发时间、CA 的名字等,可以用于猜测这台机器的拥有者和功能。SNI 目前仍然是没加密的。用 VPN 的话是没有这些信息泄露的。
但 VPN 也有自己的问题,配置起来更麻烦一些,不适合增量式地为每个应用配置,需要提前决定好怎么把所有机器组网,想临时给别人一个权限时,给对方签一张 client certificate 也更轻量级。
如果想要一种可以为各个应用按需启用的、可以灵活配置权限规则的方案,似乎还是更像 TLS 一点。它要是把更多步骤挪到检查客户端证书之后再做,并且都加密传输,就好了。
遇到了一个神奇妙妙 bug,我使用某系统时总是有概率登录失败,需要重试才能成功。而且最近几个月以来失败概率越来越高,到了难以忍受的程度,常常需要重试两三次才能成功。但别人都没遇到同样的问题。
今天在 @taoky42 认真调查之后终于搞明白了,问题在于登录时在数据库中查询我的本月用量花费的时间超过一秒。数据库表结构为 使用记录(时间, 用户, 用量),时间列和用户列分别有单列索引,查询语句为 select sum(用量) from 使用记录 where 用户 = ... and UNIX_TIMESTAMP(时间) > ...。
我看到这个查询的第一反应是,这肯定用时间索引,然后行数很少,应该不会慢,就算慢也不可能只有我一个人慢,应该是大家一样慢。但是,注意以下两种写法的区别:
1. UNIX_TIMESTAMP(时间) > ...
2. 时间 > FROM_UNIXTIME(...)
1 运行花费 1.37 秒,2 运行花费 0.05 秒。1 用不上时间索引,只能用用户索引,导致行数多了不少,并且每行还有函数调用开销。
今天在 @taoky42 认真调查之后终于搞明白了,问题在于登录时在数据库中查询我的本月用量花费的时间超过一秒。数据库表结构为 使用记录(时间, 用户, 用量),时间列和用户列分别有单列索引,查询语句为 select sum(用量) from 使用记录 where 用户 = ... and UNIX_TIMESTAMP(时间) > ...。
我看到这个查询的第一反应是,这肯定用时间索引,然后行数很少,应该不会慢,就算慢也不可能只有我一个人慢,应该是大家一样慢。但是,注意以下两种写法的区别:
1. UNIX_TIMESTAMP(时间) > ...
2. 时间 > FROM_UNIXTIME(...)
1 运行花费 1.37 秒,2 运行花费 0.05 秒。1 用不上时间索引,只能用用户索引,导致行数多了不少,并且每行还有函数调用开销。
👍1
SQLite 支持一些处理 JSON 的函数,可以直接对 JSON 格式的列进行查询和建立索引,看似很方便,但要当心:
1. json('{"a/b": 1}') != json('{"a\/b": 1}')
虽然在 JSON 的意义上两个 object 是一样的,但 SQLite 认为是不等的。
2. json_extract('{"a\/b": 1}', '$.a/b') is null
类似地,json_extract('{"\u0031":1}', '$.1') is null
类似地,json_extract('{"\u6211":1}', '$.我') is null
这个问题只在老版本的 SQLite 上存在,最新版本已经修复了。
感觉很坑,因为很多时候我是没法控制我用的 JSON 库怎么 escape 各种字符的,例如 / 这个字符其实不必 escape,但有的库会把它 escape 成 \/,进了 SQLite 后就会出现匹配不到 key 的问题。
1. json('{"a/b": 1}') != json('{"a\/b": 1}')
虽然在 JSON 的意义上两个 object 是一样的,但 SQLite 认为是不等的。
2. json_extract('{"a\/b": 1}', '$.a/b') is null
类似地,json_extract('{"\u0031":1}', '$.1') is null
类似地,json_extract('{"\u6211":1}', '$.我') is null
这个问题只在老版本的 SQLite 上存在,最新版本已经修复了。
感觉很坑,因为很多时候我是没法控制我用的 JSON 库怎么 escape 各种字符的,例如 / 这个字符其实不必 escape,但有的库会把它 escape 成 \/,进了 SQLite 后就会出现匹配不到 key 的问题。
微信备份/迁移聊天记录时会丢失和公众号的对话记录,包括公众号推送的文章和消息记录,以及自己打字和公众号对话的记录。望周知。
(上一条消息搞错了,删了重发)
(上一条消息搞错了,删了重发)
怎么避免“毕业论文10.pdf”排序时排在“毕业论文1.pdf”和“毕业论文2.pdf”之间?一个非常简单并且足够好的做法就是把连起来的数字看作一个整体,["毕业论文", 10, ".pdf"] > ["毕业论文", 2, ".pdf"]。这样遇到“毕业论文13送审版.pdf”、“毕业论文13送审版2.pdf”等更复杂的情况时也会正好产生好的结果。
我之前一直觉得这个问题就算是已经解决得很好了,今天给 @zzh1996 讲这个算法时,他说“听起来十六进制的文件名会完全乱掉”,我才意识到有这个坑😂我好像从来没有在 Windows 文件管理器等程序中打开过包含很多十六进制文件名的目录。
那 Windows 是怎么解决的呢?刚刚调查了一下,Windows 还真就没解决这个问题,我想了想也没想到好的方法。
我之前一直觉得这个问题就算是已经解决得很好了,今天给 @zzh1996 讲这个算法时,他说“听起来十六进制的文件名会完全乱掉”,我才意识到有这个坑😂我好像从来没有在 Windows 文件管理器等程序中打开过包含很多十六进制文件名的目录。
那 Windows 是怎么解决的呢?刚刚调查了一下,Windows 还真就没解决这个问题,我想了想也没想到好的方法。
👍1
IEEE 754 认为二进制规约浮点数应该视为 (-1)^s * m * 2^e,其中 s 是符号位,m 是一个二进制数,其整数部分总是为 1,小数部分每一位都是 0 或 1,e 是指数。
也就是说,一般来说系数 m 应满足 1 <= m < 2,在这个形式下才按照 m * 2^e 这个公式定义指数 e。提到指数的最小值和最大值时也都是按这个标准理解的,例如规定双精度浮点数的指数最大值是 1023,所以 1.999 * 2^1023 能表示,2 * 2^1023 就超出范围了。
但 C 和 Python 提供的提取浮点数指数部分的函数 frexp 居然用的不是这个定义。它总是把系数放到 0.5 <= m < 1 这个范围内,并相应返回指数,导致一般来说它返回的指数比 IEEE 754 中常说的那个指数概念大 1。它有可能返回的最大指数是 1024,不是 1023。
当然这里怎么规定都是可以的,但采用和 IEEE 754 不同的规定会导致 emin emax 对不上,感觉平添不少混乱啊。
也就是说,一般来说系数 m 应满足 1 <= m < 2,在这个形式下才按照 m * 2^e 这个公式定义指数 e。提到指数的最小值和最大值时也都是按这个标准理解的,例如规定双精度浮点数的指数最大值是 1023,所以 1.999 * 2^1023 能表示,2 * 2^1023 就超出范围了。
但 C 和 Python 提供的提取浮点数指数部分的函数 frexp 居然用的不是这个定义。它总是把系数放到 0.5 <= m < 1 这个范围内,并相应返回指数,导致一般来说它返回的指数比 IEEE 754 中常说的那个指数概念大 1。它有可能返回的最大指数是 1024,不是 1023。
当然这里怎么规定都是可以的,但采用和 IEEE 754 不同的规定会导致 emin emax 对不上,感觉平添不少混乱啊。
我做实验时常遇到这个需求:在对数意义下均匀地测试一个变量的一系列取值,例如每秒 10 个请求、100 个请求、1000 个请求时系统性能,或是 4KiB、8KiB、16KiB 等不同数据量的处理性能。
每次乘以 10 或乘以 2 都比较简单,但是如果希望乘以更小的数,还希望序列中的数字有效位数较少,对人来说看起来方便,就有点难了。例如每次简单地乘以 1.1 会得到 1.21、1.331、1.4641、1.61051。
于是我常在实验脚本中手写:[10, 13, 17, 20, 25, 30, 40, 50, 60, 80, 100, 130, 170, …],相对来说比较好读,对数意义下切分也比较均匀。(不需要完美均匀,只是越不均匀的话实验效率越低,会有一些区间实验太多,另一些区间实验不足。)
今天才知道这个问题叫 https://en.wikipedia.org/wiki/Preferred_number ,一些例子:
1-2-5:1, 2, 5, 10
R5:10, 16, 25, 40, 63, 100
R10:100, 125, 160, 200, 250, 315, 400, 500, 630, 800, 1000
E3:10, 22, 47, 100
E6:10, 15, 22, 33, 47, 68, 100
E12:10, 12, 15, 18, 22, 27, 33, 39, 47, 56, 68, 82, 100
E24:10, 11, 12, 13, 15, 16, 18, 20, 22, 24, 27, 30, 33, 36, 39, 43, 47, 51, 56, 62, 68, 75, 82, 91, 100
E 系列的数还有一个好处,E6、E12、E24 分别近似每步加 50%、20%、10%,步长比较“整”。
每次乘以 10 或乘以 2 都比较简单,但是如果希望乘以更小的数,还希望序列中的数字有效位数较少,对人来说看起来方便,就有点难了。例如每次简单地乘以 1.1 会得到 1.21、1.331、1.4641、1.61051。
于是我常在实验脚本中手写:[10, 13, 17, 20, 25, 30, 40, 50, 60, 80, 100, 130, 170, …],相对来说比较好读,对数意义下切分也比较均匀。(不需要完美均匀,只是越不均匀的话实验效率越低,会有一些区间实验太多,另一些区间实验不足。)
今天才知道这个问题叫 https://en.wikipedia.org/wiki/Preferred_number ,一些例子:
1-2-5:1, 2, 5, 10
R5:10, 16, 25, 40, 63, 100
R10:100, 125, 160, 200, 250, 315, 400, 500, 630, 800, 1000
E3:10, 22, 47, 100
E6:10, 15, 22, 33, 47, 68, 100
E12:10, 12, 15, 18, 22, 27, 33, 39, 47, 56, 68, 82, 100
E24:10, 11, 12, 13, 15, 16, 18, 20, 22, 24, 27, 30, 33, 36, 39, 43, 47, 51, 56, 62, 68, 75, 82, 91, 100
E 系列的数还有一个好处,E6、E12、E24 分别近似每步加 50%、20%、10%,步长比较“整”。
👍3
把我一直在用的 bashrc prompt 作为单独的项目开源了😃并给代码加了详细的注释以便修改,欢迎取用。
https://github.com/SmartHypercube/fancy-prompt
https://github.com/SmartHypercube/fancy-prompt
👍3
这么多网站用 https://github.com/bilibili/flv.js 播放视频,yt-dlp 和 youtube-dl 怎么都没人做过下载 flv.js 中的视频的功能呢?网上一个相关内容都搜不到。
前段时间有个俄罗斯的学生突然加我,向我请教用 PyQt6 开发翻转棋游戏相关问题,说是课程大作业。帮他的过程中感觉好像曾经给 C 语言课带助教啊😂昨天他说成功赶上 ddl 交了,代码在 https://github.com/kkasuann2000/gameR 。
我问他到底在哪找到我的,为什么会这样跑来求助一个陌生网友,而且我也没发布过翻转棋或者 PyQt6 相关代码。他说是搜索 reversi game python 找到了 https://ibug.io/blog/2018/05/python-reversi/ ,侧栏有 Telegram Channel 链接 @iBugThought ,那天最新一条消息正好是我和 iBug 约饭时聊到的话题 https://t.iss.one/iBugThought/4098 ,其中有我的 username。
原来是把我当成 iBug 了😂
我问他到底在哪找到我的,为什么会这样跑来求助一个陌生网友,而且我也没发布过翻转棋或者 PyQt6 相关代码。他说是搜索 reversi game python 找到了 https://ibug.io/blog/2018/05/python-reversi/ ,侧栏有 Telegram Channel 链接 @iBugThought ,那天最新一条消息正好是我和 iBug 约饭时聊到的话题 https://t.iss.one/iBugThought/4098 ,其中有我的 username。
原来是把我当成 iBug 了😂
👍11
https://youtu.be/58hoktsqk_Q
这张专辑(Chromatica,2020)我倒是很早就听过,然而是工作的时候作为背景音乐听的,没看 MV,太可惜了!昨晚偶然看到这个视频,导致睡觉推迟一个多小时👀而且一晚上也很多次在想这个视频。
说不清楚具体是什么吸引我,可能是整个过程的艺术化表现非常精彩,可能是最后结尾处的短短几句话让我对事故原因和她的精神状态有很多思考,也可能是其中的人物形象太像我最近在玩的游戏《巴别塔圣歌》了😂
这张专辑(Chromatica,2020)我倒是很早就听过,然而是工作的时候作为背景音乐听的,没看 MV,太可惜了!昨晚偶然看到这个视频,导致睡觉推迟一个多小时👀而且一晚上也很多次在想这个视频。
说不清楚具体是什么吸引我,可能是
YouTube
Lady Gaga - 911 (Short Film)
MAYHEM OUT NOW
https://ladygaga.com
Follow Lady Gaga:
Facebook: https://www.facebook.com/ladygaga
Instagram: https://www.instagram.com/ladygaga
TikTok: https://www.tiktok.com/@ladygaga
Twitter: https://twitter.com/ladygaga
YouTube: https://www.…
https://ladygaga.com
Follow Lady Gaga:
Facebook: https://www.facebook.com/ladygaga
Instagram: https://www.instagram.com/ladygaga
TikTok: https://www.tiktok.com/@ladygaga
Twitter: https://twitter.com/ladygaga
YouTube: https://www.…
我才知道 Python 捕获异常得到的 traceback 是只从 try 这里开始的?!例如 f1 调 f2,f2 在 try 里面调 f3,f3 抛异常,在 f2 的 except 中捕获的异常带的 traceback 只会有两条,第一条是 f2 里面调 f3 的那一行,第二条是 f3 里面抛异常的那一行。当然了,未捕获的异常相当于在程序最外层被捕获,会带完整的 traceback。
明白了这一点后,读 traceback 就突然感觉清晰多了。
明白了这一点后,读 traceback 就突然感觉清晰多了。
研究了一下 compositing and blending 的原理,之前一直不太明白 alpha 如何影响各种 blend mode,以及结果的 alpha 是如何确定的。以下信息整理自 https://www.w3.org/TR/2024/CRD-compositing-1-20240321/ ,符号与之保持一致,Cs、Cb、Co 分别表示前景、背景、输出颜色,αs、αb、αo 分别表示其 alpha。
1. Cm = B(Cb, Cs)
混合前景色和背景色,这一步完全不考虑 alpha,其中 B 取决于 blend mode,并且大多数 blend mode 独立处理 rgb 三个通道。
2. Cr = αb * Cm + (1 - αb) * Cs
用背景 alpha 控制混合结果与前景色的比例。
3. αo = Fa * αs + Fb * αb
计算输出 alpha,其中 Fa 和 Fb 取决于 compositing operator。
4. Co = (Fa * αs * Cr + Fb * αb * Cb) / αo
计算输出颜色。
默认的 blend mode 是 normal,其定义 B(Cb, Cs) = Cs。默认的 compositing operator 是 source over,其定义 Fa = 1,Fb = 1 - αs。代入可知默认情况下:
Cm = Cr = Cs
αo = αs + (1 - αs) * αb
Co = (αs * Cs + (1 - αs) * Cb) / (αs + (1 - αs) * αb)
这种默认情况被称为 simple alpha compositing,它具有结合律,多个层次用不同方式组合得到的结果相同。但使用不同的 blend mode 或 compositing operator 可能会破坏结合律,规定从下向上组合,也就是位于最底部的两层先组合,再与上层组合。
P.S. 原文第 6 节公式错了,Co 应改为 co,我发现有别人也注意到这个错误了: https://github.com/w3c/fxtf-drafts/issues/478
1. Cm = B(Cb, Cs)
混合前景色和背景色,这一步完全不考虑 alpha,其中 B 取决于 blend mode,并且大多数 blend mode 独立处理 rgb 三个通道。
2. Cr = αb * Cm + (1 - αb) * Cs
用背景 alpha 控制混合结果与前景色的比例。
3. αo = Fa * αs + Fb * αb
计算输出 alpha,其中 Fa 和 Fb 取决于 compositing operator。
4. Co = (Fa * αs * Cr + Fb * αb * Cb) / αo
计算输出颜色。
默认的 blend mode 是 normal,其定义 B(Cb, Cs) = Cs。默认的 compositing operator 是 source over,其定义 Fa = 1,Fb = 1 - αs。代入可知默认情况下:
Cm = Cr = Cs
αo = αs + (1 - αs) * αb
Co = (αs * Cs + (1 - αs) * Cb) / (αs + (1 - αs) * αb)
这种默认情况被称为 simple alpha compositing,它具有结合律,多个层次用不同方式组合得到的结果相同。但使用不同的 blend mode 或 compositing operator 可能会破坏结合律,规定从下向上组合,也就是位于最底部的两层先组合,再与上层组合。
P.S. 原文第 6 节公式错了,Co 应改为 co,我发现有别人也注意到这个错误了: https://github.com/w3c/fxtf-drafts/issues/478
以前一直没好好学过 Python logging,最近学了一下觉得设计得挺灵活的,完全够满足我的各种需求:
1. 日志可以不是字符串而是对象,自己序列化保存。
2. 可以用 JSON / YAML 在运行期间随时修改日志管线。
3. 默认会采集线程名、task 名等信息,想记录的话自定义 Formatter 就行。
4. 想附加其他上下文信息只需要自定义 Filter。
5. 自带 rotating file、syslog、SMTP、HTTP 等各种 Handler,还可以配置攒多条后按特定条件触发一起发送的逻辑。
6. 可以接管 Python warnings。
7. 日志级别选项可以自定义。
8. 开销较大的计算基本都会只在必要时才做,并有缓存。
1. 日志可以不是字符串而是对象,自己序列化保存。
2. 可以用 JSON / YAML 在运行期间随时修改日志管线。
3. 默认会采集线程名、task 名等信息,想记录的话自定义 Formatter 就行。
4. 想附加其他上下文信息只需要自定义 Filter。
5. 自带 rotating file、syslog、SMTP、HTTP 等各种 Handler,还可以配置攒多条后按特定条件触发一起发送的逻辑。
6. 可以接管 Python warnings。
7. 日志级别选项可以自定义。
8. 开销较大的计算基本都会只在必要时才做,并有缓存。
👍3
@zzh1996 问我为什么在不同云服务商的 Debian 11 的机器上安装 unattended-upgrades,有的会自动创建 /etc/apt/apt.conf.d/20auto-upgrades,有的却不会,导致并没有启用自动更新。
这个行为受 debconf 数据库中的一个选项控制,相关信息存储在 /var/cache/debconf/{config,templates}.dat,两个文件都是纯文本。
执行 apt source unattended-upgrades 会下载这个包的源代码:
- debian/templates 有一个选项 enable_auto_updates,默认值为 true。
- debian/config 会设置这个选项的值,但因为优先级是 low 所以默认不会询问用户。
- debian/postinst 会从数据库查询这个选项的值,决定是否创建配置文件。
在腾讯云和 Hetzner 提供的 Debian 11 系统中,虽然没有预装 unattended-upgrades 包,但 debconf 数据库中奇怪地有这个选项,其值为 false。这是通过 debconf-set-selections 工具做到的,它专门用来在安装包之前设置各种选项(称为 preseed)。按我的理解,在 config.dat 中搜索 seen 可以看到所有被 preseed 过的值,在 templates.dat 中搜索 fake 可以看到所有被 preseed 过但没被真的安装用到的值。
我猜或许曾经某个系统会自动安装 unattended-upgrades,但云厂商没想默认启用,所以 preseed 成了 false,后来这个包不会被自动安装了,忘了移除相应配置?
这个行为受 debconf 数据库中的一个选项控制,相关信息存储在 /var/cache/debconf/{config,templates}.dat,两个文件都是纯文本。
执行 apt source unattended-upgrades 会下载这个包的源代码:
- debian/templates 有一个选项 enable_auto_updates,默认值为 true。
- debian/config 会设置这个选项的值,但因为优先级是 low 所以默认不会询问用户。
- debian/postinst 会从数据库查询这个选项的值,决定是否创建配置文件。
在腾讯云和 Hetzner 提供的 Debian 11 系统中,虽然没有预装 unattended-upgrades 包,但 debconf 数据库中奇怪地有这个选项,其值为 false。这是通过 debconf-set-selections 工具做到的,它专门用来在安装包之前设置各种选项(称为 preseed)。按我的理解,在 config.dat 中搜索 seen 可以看到所有被 preseed 过的值,在 templates.dat 中搜索 fake 可以看到所有被 preseed 过但没被真的安装用到的值。
我猜或许曾经某个系统会自动安装 unattended-upgrades,但云厂商没想默认启用,所以 preseed 成了 false,后来这个包不会被自动安装了,忘了移除相应配置?
👍2