使用 calc 计算保险实际收益率

今天某银行的客户经理来推销一个“增额终身寿险”,号称是能锁定3.5%的收益率。 具体来说,就是前5年每年投入一笔钱但是不计息,第6年开始按3.5%的收益率进行计息,听起来似乎很不错,毕竟长期来看利率是下行趋势。 而且现在理财的收益也不高了,能锁定3.5的利率似乎还不错,虽然前5年没算利息,但直觉上似乎利率下降不会太多。 然而在仔细计算一下,我发现情况完全不是那么一回事。 假设利率是x那么根据等比数列求和公式可以知道第5年的金额应该变成 =(1-x^5)/1-x=, 因此可以得到等式 ~(1-x^5)*x/(1-x) = 5*1.035~. 对于我这种数学渣来说,这种公式完全不会计算,不过好在我有 Emacs [[help:calc][calc]] 啊 那么,让我们运行 =M-x calc=,输入 ='fsolve((1-x^5)*x/(1-x) = 5*1.035,x)= 就可以得到结果如下: #+begin_src calc :export both :results org fsolve((1-x^5)*x/(1-x) = 5*1.035,x) #+end_src #+RESULTS: #+begin_src org x = [0.999999999998, 1.01148914259, (-1.29523147819, 0.862841415432), (0.289486906893, -1.42424965717), (-1.29523147819, -0.862841415432), (0.289486906893, 1.42424965717)]_n4 #+end_src 可以看出,x的求值为 =1.01148914259=,也就是说实际收益率只有不到 =1.15%= 而已,跟直观感觉真的差别巨大啊。

2022/8/10
articleCard.readMore

使用 org-mode columnview 生成任务列表

org-mode的columnview[[https://orgmode.org/manual/Dynamic-Blocks.html#Dynamic-Blocks][动态块]]能够帮你把树形的代办事项归整为表格,方便查看 在org-mode中可以通过两个命令来插入colmnviewa动态块: + 一个是通过 =M-x org-dynamic-block-insert-dblock= 插入一个动态块,默认情况下 org-mode 自带了两类动态块 =columnview= 和 =clocktable= ,然后我们选择 =columnview= 即可 + 另一个是通过 =M-x org-columns-insert-dblock= 直接插入columnviewa动态块 一个 columnview 动态块大概长这个样子的: #+begin_src org ,#+BEGIN: columnview :参数1 参数值 :参数N h参数值 ,#+END: #+end_src 其中 =columnview= 标识动态块的类型,该名字决定了org-mode会调用哪个函数来生成动态块的内容,比如这里调用的函数就是 =org-dblock-write:columnview=. 后面的 =:参数1 参数值 :参数N h参数值= 参数则会组装成一个plist传递给函数作为唯一的参数,并将函数的返回值作为动态块的内容 我们可以通过查看 =org-dblock-write:columnview= 的docstring来找出 =columnwive= 动态块支持的参数: #+begin_example (org-dblock-write:columnview PARAMS) Write the column view table. PARAMS is a property list of parameters: ‘:id’ (mandatory) The ID property of the entry where the columns view should be built. When the symbol ‘local’, call locally. When ‘global’ call column view with the cursor at the beginning of the buffer (usually this means that the whole buffer switches to column view). When "file:path/to/file.org", invoke column view at the start of that file. Otherwise, the ID is located using ‘org-id-find’. ‘:exclude-tags’ List of tags to exclude from column view table. ‘:format’ When non-nil, specify the column view format to use. ‘:hlines’ When non-nil, insert a hline before each item. When a number, insert a hline before each level inferior or equal to that number. ‘:indent’ When non-nil, indent each ITEM field according to its level. ‘:match’ When set to a string, use this as a tags/property match filter. ‘:maxlevel’ When set to a number, don’t capture headlines below this level. ‘:skip-empty-rows’ When non-nil, skip rows where all specifiers other than ITEM are empty. ‘:vlines’ When non-nil, make each column a column group to enforce vertical lines. #+end_example 这里比较重要的参数有 + :id :: 这是最重要的参数. 它指定了column视图的数据来源。 + :maxlevel :: 若设置为数字N,表示不捕捉层级在N级以下的条目 + :skip-empty-rows :: 若设置为`t`,则会跳过那些除了`ITEM`属性列外,其他属性列都是空值的行 + :format :: 设置column视图的格式。 其中 =:format= 是一个以多个列定义式组成的字符串,各定义式之间使用空格进行分隔。 column的定义式中可以包含有列的属性. 一般来说列的定义式看起来是这样做的 #+BEGIN_SRC org ,%[width]property[(title)][{summary-type}] #+END_SRC 除了百分号和属性名之外,所有的都是可选的. 各部分的意思如下所示 #+BEGIN_EXAMPLE width 整型,代表了列的宽度,如果忽略则由org自动决定 property 该列所表示的属性,可以是上文提到的哪些特殊属性 title 列的标题,如果忽略,则会使用属性名代替 {summary-type} 总和的类型,如果指定了,那么父节点的列值由其下子节点的值计算得到 支持的总和类型包括: {+} 该列的累加值 {+;%.1f} 指定了格式的列累加值 {$} 货币格式,其实就是 ‘+;%.2f’. {:} 把列中的值作为时间进行累加,格式为HH[:MM] {X} Checkbox 的状态, 若所有子checkboxd都标记为‘[X]’ 则显示‘[X]’. {X/} Checkbox 的状态, 显示格式为‘[n/m]’. {X%} Checkbox 的状态, 显示格式为‘[n%]’. {min} 列中的最小值 {max} 列中的最大值 {mean} 列的算术平均值 {:min} 列中的最小值(以时间为单位) {:max} 列中的最大值(以时间为单位) {:mean} 列中的算术平均值(以时间为单位) {@min} 列中的最小值(以时间区间为单位) {@max} 列中的最大值(以时间区间为单位) {@mean} 列中的算术平均值(以时间区间为单位) {est+} 耗时的范围 #+END_EXAMPLE 我一般使用 columnview 来生成任务列表方便我对任务进度进行追踪。下面是一个例子 #+begin_src org ,* 任务分派 ,#+BEGIN: columnview :hlines 1 :id local :format "%ITEM(任务) %CHARGER(负责人) %DEADLINE(死线) %TODO(状态)" :skip-empty-rows t | 任务 | 负责人 | 死线 | 状态 | |--------+-----------+-----------------+-------| | 任务一 | 甲xx | | NEXT | | 任务二 | 乙xx | | TODAY | | 任务三 | 甲xx 乙xx | | TODO | ,#+END: ,** NEXT 任务一 :PROPERTIES: :CHARGER: 甲xx :END: + [ ] xxxx + [ ] yyyy + [ ] zzzz + [X] abcd ,** TODAY [#A] 任务二 DEADLINE: :PROPERTIES: :CHARGER: 乙xx :END: + [ ] 111111 + [ ] 222222 ,** TODO [#C] 任务三 :PROPERTIES: :CHARGER: 甲xx 乙xx :END: #+end_src

2022/7/5
articleCard.readMore

Emacs 作为 MPD 客户端

今天才知道,Emacs居然内置了一个 mpc.el 可以将 Emacs 转换为 [[https://wiki.archlinux.org/title/Music_Player_Daemon][MPD]]([[https://musicpd.org/][Music Player Daemon]])客户端。 1. 设置 [[help:mpc-host][mpc-host]] #+begin_src emacs-lisp (setq mpc-host "192.168.31.9:6600") #+end_src #+RESULTS: : 192.168.31.9:6600 2. 执行 [[help:mpc][mpc]] 命令,进入 mpc 控制界面 [[file:images/mpc01.png]] 3. 快捷键 + (mpc-previous) :: 下一首歌 + g (mpc-seek-current) :: 设置当前歌曲的播放进度 + s (mpc-toggle-play) :: 播放/暂停 + g (mpc-seek-current) :: 设置当前歌曲的播放进度 + mpc-toggle-{consume,repeat,single,shuffle} :: 设置播放模式 + q (mpc-quit) :: 退出

2022/6/29
articleCard.readMore

移动文件路径却不破坏org file link的方法

我习惯在Org file中记录电子书的文件路径、阅读耗时、笔记等信息。 电子书放在统一的目录中,按照分类分子目录进行存放。 但这会带来一个问题,就是我在整理电子书时经常会在不同分类之间移动电子书,这就会破坏Org file中电子书的文件路径。 如果每次都需要手工修改文件中的链接地址的话,那就太麻烦了。好在通过自定义link,我们可以自定义搜索函数来动态搜索电子书路径,而不是写死电子书的存放路径。 方法如下: #+begin_src emacs-lisp (defvar MY-EBOOK "~/ebooks") (defun my-search-ebook (pattern &optional _) (let* ((files (directory-files-recursively MY-EBOOK pattern)) (count (length files))) (cond ((= count 0) (message "Can't found file mathcing %s" pattern)) ((= count 1) (find-file (car files))) ((> count 1) (find-file (completing-read "Please pick a file: " files nil t)))))) (org-link-set-parameters "ebook" :follow #'my-search-ebook :help-echo (format "Open the file in %s" MY-EBOOK) :face '(underline t)) #+end_src 这就自定义了一个 =ebook= 的link,访问这个 link 会自动从 =MY-EBOOK= 定义的目录(~/ebooks)中搜索匹配的文件并打开。

2022/6/26
articleCard.readMore

如何合理的导出help link 成HTML

Org 文件在导出为 html 是会将 =help= link 导出为一个HTTP链接,例如一个 #+begin_example 这是一个 [[help:lazy-helm/describe-char][Help]] link #+end_example 导出成HTML时会变成 #+begin_src html 这是一个 Help link #+end_src 这个操作很迷,因为实际上并没有这个链接对应的页面。 一个比较合理的方法是导出时保留原文字,但当光标移动到这段文字上去时弹出相关说明。 通过 [[help:org-link-set-parameters][org-link-set-parameters]] 可以注册自己定义的链接导出函数,相关配置如下: #+begin_src emacs-lisp (defun org-link--export-help (path desc backend &optional _) "Export a \"help\" type link. PATH is a symbol name, as a string." (let ((info (pcase (intern path) ((and (pred fboundp) function) (describe-function function)) ((and (pred boundp) variable) (describe-variable variable)) (name (user-error "Unknown function or variable: %s" name))))) (quit-window) ;关闭新开的 help window (pcase backend ('html (format "%s" info desc)) (_ desc)))) ;; 注册 help 的导出函数 (org-link-set-parameters "help" :export #'org-link--export-help) #+end_src 就可以导出为 #+begin_src html 这是一个 Help link #+end_src 效果如下所示: [[file:./images/export-help-link.png]]

2022/6/26
articleCard.readMore

笑话理解之Biology

1. Buy-ologist #+begin_example How do you call a member of the finacial staff of the faculty of Biology? A Buy-ologist. #+end_example

2022/6/20
articleCard.readMore

笑话理解之Round

* Your round #+begin_example Two fat blokes sitting in a pub, one say to the other, "Your round!" The other replies, "So are you, you fat bastard!" #+end_example =Your round= 听起来很像 =You're round=.意思就从 =轮到你了=,变成了 =你圆圆的=

2022/6/20
articleCard.readMore

笑话理解之Potential

#+begin_example What did the physicist say to the young man who was about to jump off the Empire State building? Don’t do it. You have so much potential. #+end_example =potential= 既有 =潜能= 也有 =势能= 的意思。帝国大厦那么高,势能确实很多...

2022/6/11
articleCard.readMore

使用 org-depend 自动化任务流程

当项目涉及多项任务时,任务之间往往有先后的依赖关系,例如一个信息系统建设可能需要经过 =可行性分析= 后才能进入 =立项申请= 阶段,再然后才是 =项目启动=, =需求=, =设计=, =开发=, =测试=, =上线=. 下一个步骤的开始依赖于上一个步骤的结束。 这就产生了两个需求: 1. 如何在上一个步骤未完成的时候,禁止下一个步骤开始 2. 上一个步骤完成后,自动开始下一个步骤 [[https://karl-voit.at][Karl Voit]] 给出的解决方法是 =org-depend=,原理其实非常简单,通过 [[help:org-blocker-hook][org-blocker-hook]] 可以检查是否允许进行状态变化,而 [[help:org-trigger-hook][org-trigger-hook]] 可以指定状态变化时要触发的函数。 * org-depend 使用方法简介 org-depend 通过 =BLOCKER= 属性来指定当前任务开始所依赖的任务,使用 =TRIGGER= 属性来设置当前任务结束后自动开始的任务 ** BLOCKER 检查任务是否允许开始 =BLOCKER= 属性是一些 =空格= 分隔的任务ID列表,这些ID所代表的任务存在未完成的,则该任务不能开始(*不过由于org-mode 的状态不能区分待开始和进行中,因此实际上只能约束其不允许结束*) 考虑到很多时候上下游任务本身会按照兄弟关系从上倒下进行排列的,因此 =org-depend= 提供了一个关键字 =previous-sibling= 来表示上一个同级的任务。例如 #+begin_src org ,* 项目 ,** TODO 可行性分析 ,** 立项申请 :PROPERTIES: :BLOCKER: previous-sibling :END: ,** 项目启动 ,** 需求 ,** 设计 ,** 开发 ,** 测试 ,** 上线 #+end_src ** TRIGGER 自动开始任务 =TRIGGER= 属性稍微复杂一些,是一些 =空格= 分隔的 =任务ID(状态)= 列表。当本任务完成后,则会将这些ID所代表的任务设置为括号能的状态。 类似的, =org-depend= 也提供了一个关键字 =chain-siblings= 来表示下一个同级的任务。例如 #+begin_src org ,* 项目 ,** TODO 可行性分析 :PROPERTIES: :TRIGGER: chain-siblings(TODAY) :END: ,** 立项申请 ,** 项目启动 ,** 需求 ,** 设计 ,** 开发 ,** 测试 ,** 上线 #+end_src 事实上关于 =TRIGGER= 的语法支持多种形式,比如 =chain-siblings-scheduled= 可以传递计划时间, =chain-find-next(状态[,选项])= 可以灵活定义下一个任务的搜索方式。 详情可以参见 =org-depend.el= 中的注释部分。 * 定义自己的规则 前面说的由于 org-mode 的状态关键字不能区分 =待开始= 和 =进行中= 这两种状态,因此 =org-depend= 只能限制依赖任务在被依赖任务未完成之前无法切换到完成状态。不过只要指导了原理,我们也可以实现自己的检查条件: 例如,假设我们以 =PROG= 状态来表示 =进行中=, 那么以下设置可以实现当 task 属性中包含 =:DEPEND_ID= 时,表示该属性值对应的 task 必须先完成,否则不能进入PROG状态。 #+begin_src emacs-lisp (defun my-check-depend-task-state (args) "检查依赖任务是否完成" (message "%s" args) (let* ((to (plist-get args :to)) (depend-id (org-element-property :DEPEND_ID (org-element-at-point))) (depend-task-state (when (and depend-id (not (string= depend-id ""))) (save-excursion (goto-char (org-find-entry-with-id depend-id)) (nth 2 (org-heading-components)))))) (or (not (member to '("PROG"))) (not depend-task-state) (member depend-task-state org-done-keywords)))) (add-hook 'org-blocker-hook #'my-check-depend-task-state) #+end_src * 参考文档 + https://karl-voit.at/2016/12/18/org-depend/

2022/5/31
articleCard.readMore

让 Org-mode 为你规划任务安排

PROPERTIES: :ID: s6e04h11ygj0 :ROAM_REFS: https://www.reddit.com/r/emacs/comments/6suy3m/realized_that_org_mode_is_a_rabbit_hole/dlint83/ :END: #+TITLE: 让 Org-mode 为你规划任务安排 #+filetags: :GTD:读书:Org-mode:Emacs: #+AUTHOR: lujun9972 #+TAGS: Reading #+DATE: [2022-05-29 日 08:26] #+LANGUAGE: zh-CN #+STARTUP: inlineimages #+OPTIONS: H:6 num:nil toc:t \n:nil ::t |:t ^:nil -:nil f:t *:t <:nil 今天才知道 [[info:org#Agenda Commands][org-agenda]] 中有一个 bulk edit 的功能,可以同时对多个任务进行操作,其中有一个特别好玩的功能叫 scatter tasks 可以帮你将多个任务随机分散到一个时间段内. 1. 在 agenda 中通过 =m= (org-agenda-bulk-mark)标记要操作的任务 2. 按 =B= 执行 =org-agenda-bulk-action= 3. 选择 =S= (scatter),然后输入一个天数N 然后这些标记的任务就被随机分配到随后的N天内了。 老实说,这个功能的使用场景似乎并不多,因为随机分配的时间无法预测,有时任务间的间隔特别短,完不成任务,有时任务间的间隔又太长了。 目前我一般用这个功能来为我随机分配安排读书任务,比如我想在接下来的三个月内读完三本书(三本书不存在阅读顺序),那么我可能就会用这个功能来让Org-mode随机分配这几本书的阅读顺序。

2022/5/29
articleCard.readMore