CMU15445(2024 fall) Project #0 - C++ Primer
初雪落薄衫,
赤胆压天寒。
破虏八百万,
洒酒祭长安。
完整代码见:
SnowLegend-star/CMU15445-2024fall at 8edeb1373ee8d55454432b91f84c6a05f0584fb9
目录
Task #1
Task #2
遇到的Bug
笔者对2024fall这个版本的 HyperLogLog (HLL)十分感兴趣,就顺手把HLL这个lab也完成了。由于之前版本的Trie Tree已经有太多博主分析了,故不再赘述。
Task #1
Task1的主要问题就是读懂这张图。参数b是给定的;参数p是排除了高b位的剩余子串中,最高位1所在的位置(从左往右数)。m则是2^b,表示一共有m个寄存器。
注意我这里说的是高b位,那说明二进制串bitset的遍历方式应该是从右往左,即低位遍历到高位。
对于每个不同的参数x,转换位对应的hash_value后,先去高b位找到这个参数x对应的寄存器y,然后设置寄存器的值为max(register[y], p)。
Task #2
Task2则是让我们实现密集型存储的HLL。
这里提取高p位作为寄存器编号的存储位置,逻辑和task1差不多。不同是这次计算的事二进制串中LSB=1的位置,而且这次不能把1自身的位置算进去。假设这个LSB=1的右侧有k个0,dense_bucket就只存小于等于15的值,溢出的值则是存在overflow_bucket中。
值得一提的是,task2在给寄存器赋值时,依然是max(register[y], k)的方式,而不是直接就将register[y]的值覆盖为k。
遇到的Bug
①其实Lab 0有个重点贯穿始终——无符号整形的处理。就像下面这种写法
sum +=std::pow(2, -r);
这种写法看似没问题,但是我事先将register声明为vector<uint64_t>。
Register的元素是0 1,为什么pow(2,-1)变成了inf呢?因为register的类型是uint64_t,所以“-r”是不可以表示负数的,只会出现“整数下溢”的bug。
②在task1和task2中,注意边界问题。我这就是在计算0的个数时多算了一个。
③无符号整形的问题,我将nbits_声明为
uint16_t nbits_;
然后我还纳闷自己明明做了边界判断,但是这个判断形同虚设到底是为什么呢?找了半天bug才发现自己的nbits_是无符号整形,怎么可能小于0呢?可害苦了我啊,论随手设置uint_t的弊端。
至于别的问题就没有了。本来想着让GPT直接把代码给写了我抄一遍熟悉下语法,结果这小丑给的两份代码全是错的。本来自己写一个小时不到就能写完的东西,硬是让我找bug找了五六个小时。