C++ 为什么std::bit_width为值0返回0,不应';它不是返回1吗?
C++ 为什么std::bit_width为值0返回0,不应';它不是返回1吗?,c++,c++20,C++,C++20,std::bit_width查找表示整数xas1+floor(log(x)) 为什么std::bit_width为值0返回0?它不应该返回1吗,因为表示0所需的位数是1 此外,我认为公式中的1是一个偏移量。位宽度有一段奇怪的历史 最终被称为bit_width的函数作为提案的一部分,从log2开始使用日志2被指定在传递0时生成UB 因为对数就是这样工作的 但后来,情况发生了变化。该函数后来成为 Log2P1,并且(C++语句中的“宽合同”意味着更多的东西被认为是有效的输入)。具体来说,0是有效输入
std::bit_width
查找表示整数x
as1+floor(log(x))
为什么std::bit_width
为值0返回0?它不应该返回1吗,因为表示0所需的位数是1
此外,我认为公式中的
1
是一个偏移量。位宽度有一段奇怪的历史
最终被称为bit_width
的函数作为提案的一部分,从log2
开始使用<代码>日志2
被指定在传递0时生成UB
因为对数就是这样工作的
但后来,情况发生了变化。该函数后来成为位长度的名称。就这样
因为它不再假装做对数了,所以0的行为可以是我们想要的任何东西
的确。前导零不被视为位长度的一部分,并且由于0
的值包含所有前导零…,因为它在数学上有意义:
bit_width(x) = log2(round_up_to_nearest_integer_power_of_2(x + 1))
bit_width(0) = log2(round_up_to_nearest_integer_power_of_2(0 + 1))
= log2(1)
= 0
要详细说明评论中所说的话:
假设“位宽度”表示“存储(非负整数)数字所需的最少位数”。直观地说,我们至少需要log2(n)
位取整,所以这是一个接近ceil(log2(n))
的公式,所以255将需要ceil(log2(255))=ceil(7.99..=8位
位,但这对2的幂不起作用,所以我们可以在n
中添加一个模糊因子来获得ceil(log2(n+1))
。这恰好在数学上等同于正数n的1+floor(log2(n))
,但是log2(0)
在floor版本中没有定义或定义为像负数无穷大这样无用的东西
如果我们使用0的上限公式,我们会得到结果。你也可以看到我没有写出前导零,正如Nicol Bolas指出的,0都是前导零
N
垃圾箱(n)
位宽(n)
8.
1000
4.
7.
111
3.
6.
110
3.
5.
101
3.
4.
100
3.
3.
11
2.
2.
10
2.
1.
1.
1.
0
0
标准明确指定了这种行为,但没有给出任何动机。为什么它应该返回1?如果你想拿零个苹果,你需要零个篮子,不是吗?因此,例如,如果将数据存储为长度和指向可变长度缓冲区的指针,甚至不必使用任何缓冲区来表示零,因为开始时的长度为零。从另一个角度来看,这也是合乎逻辑的:它返回从右侧开始的最高值1位的位置,从1开始,所以0表示根本没有1位。或者,从另一个角度来看:2^0=1,因此一个0位长的数字可以正好代表一个状态:零。因此,零位足以表示数字零。@rohitt:是的,您需要长度零,但这与必须存储长度或提前知道最大可能长度没有区别。如果你想表示数字5,你需要3位,但是你还需要记住你需要3位,否则你无法区分数字5和一个更大的数字,当它们出现在比特流中时,包括更多的位。对于零也没什么不同,你需要0位来存储它,但是你仍然需要存储或者记住你需要读/写多少,在这种情况下什么都不需要。我们不需要一个数字来表示零。只有在人类可读的句子中,我们需要检测数字的存在,才需要使用一位数字表示零。否则,当我们已经知道那里有一个数字时,空的数字序列是零的完美表示,这也是更规则的。尝试编写一个算法,将自然值转换为可变长度的位字符串,反之亦然:如果我们将零表示为空字符串,则更容易。事实上,当我们需要一位数字零时,我们需要实现一个特殊的情况。非常小的诡辩,但我认为说“当超过0时UB…因为对数就是这样工作的”并不准确。UB的意思是“可以做任何事情,包括在函数返回值之外产生影响”。特别是,较新规范的行为与较旧规范100%兼容,因为“返回0”是UB的一个完全有效的实现。@psmears:“包括超出此函数返回值的效果”,这也是取0的对数时发生的情况。这是一件你不能做的事情,如果你做了,那么你的数学就被打破了,不再是真正的数学。在数学中,包含加减无穷大,并将log0定义为负无穷大是完全有效的(也是有用的)。或者将日志视为reals上的。这个答案现在说“这不是对数的工作方式”,关于一个行为,它100%符合你所描述的“这就是对数的工作方式”,这似乎有点不一致:)@psmears那么,以前称为log2p1
的函数的工作原理与对数完全相同;问题是它计算的公式不是floor(log(n)+1)
,而是ceil(log(n+1))
。为什么委员会没有用第二个公式来描述它,它适用于所有的<代码> N>代码>,而是使用了第一个在代码< n=0 < /COD>中有尴尬的不连续性,因此需要更详细地描述,这是任何人的猜测(毕竟是我们所讨论的C++标准委员会)。