Deviation Scaling

背景是给一些点构成的曲线做延长,只要插入一个点,那么很自然的就拿点集的最后两个点,沿这个向量 v\vec{v}追加一个固定长度(假设为 L)的向量就可以了。

问题出现在,当 v||{\vec{v}}|| 相比 L 很小的时候,L 的存在就会放大 v\vec{v}的方向属性,如果 v\vec{v}本身是异常的,或者出现了一些需要特殊处理的 corner case,那么就不能套用常规场景下的插值方法了。

同类问题还有浮点数的比较,比较严谨的比较方法,都会考虑 absolute tolerance 和 relative tolerance。

Reference:

https://www.learncpp.com/cpp-tutorial/relational-operators-and-floating-point-comparisons/

https://beta.boost.org/doc/libs/1_68_0/libs/math/doc/html/math_toolkit/float_comparison.html

https://www.boost.org/doc/libs/1_88_0/libs/test/doc/html/boost_test/testing_tools/extended_comparison/floating_point/floating_points_comparison_theory.html

Code Review

Review 代码是很容易“得罪”人的,尤其是别人认为他在“挪”代码的时候。

我说吧,代码有啥好抄的呢,在目测可以优化、几乎不存在副作用的场景下,有什么理由不顺手把代码改好、或者直接小重构一把呢?

代码量就在一两百行的一些小机制,能不能简单地写好,效率和可读性最优,很能体现思维的清晰度和代码水平的。

那说说有什么可以改的,或者我平时 review 代码会看的一些东西:

  • 代码规范

    老生常谈,主要是一个精神面貌的问题,反映你有没有用心,脑袋清不清晰。

  • API 设计

    具有表达力和约束力的接口设计,该有的 const 不能少,一些关于屏蔽实现细节的抽象,一些所有权和性能的考量,unique_ptrstring_view 我是真喜欢。

  • 一致性

    举例一个实现的一致性,同一个 mutex,有用 std::scope_lock 锁的,也有用 mutex.lock() 锁的,啊这?

  • 标准库使用

    如果基础的数据结构和算法都不会好好地设计和使用,那真是没啥看的意思。

    不好看的也没心情细看,一般看到 3 个 if 整在一坨的,瞄一眼就过去了,反正你跟他说用 find_if 他也说现在功能是好的。

    说几个可能有用的:

    • map::insert 的返回值,虽然这个 pair 我每次都要吐槽;
    • map::insert_or_assign,比 [] 优雅多了吧;
    • vectorarray 是真的快啊;

Couple Structs

Review 的时候见到一个:

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
struct Something {};

struct Thing {
std::vector<Something> data;
std::vector<double> extra_values;
};

int main() {
Thing thing{};

// init
for (size_t i = 0; i < 10; ++i) {
thing.data.push_back({});
thing.extra_values.push_back(i);
}

// use
size_t index{};
for (size_t i = 0; i < thing.data.size(); ++i) {
if (true) { // Assuming some_condition is defined in Something
index = i;
break;
}
}

thing.extra_values[index] = 0.0;
}

看到这个下标有点不适,虽然说理论上、流程上来说,Thing 里面的两个 vector 是等长的,但是,谁知道呢?

也很好改:

1
2
3
4
5
6
7
8
9
// Better alternatives: 1
using BetterThing_1 = std::vector<std::pair<Something, double>>;

// Better alternatives: 2
struct BetterThing_2_impl {
Something data;
double extra_value;
};
using BetterThing_2 = std::vector<BetterThing_2_impl>;

既然逻辑上两个数据是成对使用的,那么就应该通过类型把它们约束到一起,同生共死。而且还少了一次 vector 的内存申请,访问起来 cache 友好度也是更好的。

当然我肯定是不喜欢 pair 的。